Update V8 to r7427: Initial merge by git

As required by WebKit r82507

Change-Id: I7ae83ef3f689356043b4929255b7c1dd31d8c5df
diff --git a/AUTHORS b/AUTHORS
index 92b69cb..843d1d2 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -24,12 +24,14 @@
 Joel Stanley <joel.stan@gmail.com>
 John Jozwiak <jjozwiak@codeaurora.org>
 Kun Zhang <zhangk@codeaurora.org>
-Matt Hanselman <mjhanselman@gmail.com>
 Martyn Capewell <martyn.capewell@arm.com>
+Matt Hanselman <mjhanselman@gmail.com>
+Maxim Mossienko <maxim.mossienko@gmail.com>
 Michael Smith <mike@w3.org>
 Mike Gilbert <floppymaster@gmail.com>
 Paolo Giarrusso <p.giarrusso@gmail.com>
 Patrick Gansterer <paroga@paroga.com>
+Peter Varga <pvarga@inf.u-szeged.hu>
 Rafal Krypa <rafal@krypa.net>
 Rene Rebe <rene@exactcode.de>
 Rodolph Perfetta <rodolph.perfetta@arm.com>
diff --git a/ChangeLog b/ChangeLog
index 44935ca..b5b4423 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,72 @@
+2011-03-30: Version 3.2.6
+
+        Fixed xcode build warning in shell.cc (out of order initialization).
+
+        Fixed null-pointer dereference in the compiler when running without
+        SSE3 support (Chromium issue 77654).
+
+        Fixed x64 compilation error due to some dead code. (Issue 1286)
+
+        Introduced scons target to build the preparser stand-alone example.
+
+        Made FreeBSD build and pass all tests.
+
+
+2011-03-28: Version 3.2.5
+
+        Fixed build with Irregexp interpreter (issue 1266).
+
+        Added Crankshaft support for external arrays.
+
+        Fixed two potential crash bugs.
+
+
+2011-03-23: Version 3.2.4
+
+        Added isolates which allows several V8 instances in the same process.
+        This is controlled through the new Isolate class in the API.
+
+        Implemented more of EcmaScript 5 strict mode.
+
+        Reduced the time it takes to make detailed heap snapshot.
+
+        Added a number of commands to the ARM simulator and enhanced the ARM
+        disassembler.
+
+
+2011-03-17: Version 3.2.3
+
+        Fixed a number of crash bugs.
+
+        Fixed Array::New(length) to return an array with a length (issue 1256).
+
+        Fixed FreeBSD build.
+
+        Changed __defineGetter__ to not throw (matching the behavior of Safari).
+
+        Implemented more of EcmaScript 5 strict mode.
+
+        Improved Crankshaft performance on all platforms.
+
+
+2011-03-14: Version 3.2.2
+
+        Fixed a number of crash and correctness bugs.
+
+        Improved Crankshaft performance on all platforms.
+
+        Fixed Crankshaft on Solaris/Illumos.
+
+
+2011-03-10: Version 3.2.1
+
+        Fixed a number of crash bugs.
+
+        Improved Crankshaft for x64 and ARM.
+
+        Implemented more of EcmaScript 5 strict mode.
+
+
 2011-03-07: Version 3.2.0
 
         Fixed a number of crash bugs.
diff --git a/SConstruct b/SConstruct
index 84707e9..2287c80 100644
--- a/SConstruct
+++ b/SConstruct
@@ -128,6 +128,9 @@
     'inspector:on': {
       'CPPDEFINES':   ['INSPECTOR'],
     },
+    'fasttls:on': {
+      'CPPDEFINES':   ['V8_FAST_TLS'],
+    },
     'liveobjectlist:on': {
       'CPPDEFINES':   ['ENABLE_DEBUGGER_SUPPORT', 'INSPECTOR',
                        'LIVE_OBJECT_LIST', 'OBJECT_PRINT'],
@@ -174,6 +177,7 @@
       'CPPPATH' : ['/usr/local/include'],
       'LIBPATH' : ['/usr/local/lib'],
       'CCFLAGS':      ['-ansi'],
+      'LIBS': ['execinfo']
     },
     'os:openbsd': {
       'CPPPATH' : ['/usr/local/include'],
@@ -220,14 +224,37 @@
     },
     'arch:mips': {
       'CPPDEFINES':   ['V8_TARGET_ARCH_MIPS'],
+      'mips_arch_variant:mips32r2': {
+        'CPPDEFINES':    ['_MIPS_ARCH_MIPS32R2']
+      },
       'simulator:none': {
-        'CCFLAGS':      ['-EL', '-mips32r2', '-Wa,-mips32r2', '-fno-inline'],
-        'LDFLAGS':      ['-EL']
+        'CCFLAGS':      ['-EL'],
+        'LINKFLAGS':    ['-EL'],
+        'mips_arch_variant:mips32r2': {
+          'CCFLAGS':      ['-mips32r2', '-Wa,-mips32r2']
+        },
+        'mips_arch_variant:mips32r1': {
+          'CCFLAGS':      ['-mips32', '-Wa,-mips32']
+        },
+        'library:static': {
+          'LINKFLAGS':    ['-static', '-static-libgcc']
+        },
+        'mipsabi:softfloat': {
+          'CCFLAGS':      ['-msoft-float'],
+          'LINKFLAGS':    ['-msoft-float']
+        },
+        'mipsabi:hardfloat': {
+          'CCFLAGS':      ['-mhard-float'],
+          'LINKFLAGS':    ['-mhard-float']
+        }
       }
     },
     'simulator:mips': {
       'CCFLAGS':      ['-m32'],
       'LINKFLAGS':    ['-m32'],
+      'mipsabi:softfloat': {
+        'CPPDEFINES':    ['__mips_soft_float=1'],
+      }
     },
     'arch:x64': {
       'CPPDEFINES':   ['V8_TARGET_ARCH_X64'],
@@ -341,6 +368,9 @@
     },
     'arch:mips': {
       'CPPDEFINES':   ['V8_TARGET_ARCH_MIPS'],
+      'mips_arch_variant:mips32r2': {
+        'CPPDEFINES':    ['_MIPS_ARCH_MIPS32R2']
+      },
     },
     'disassembler:on': {
       'CPPDEFINES':   ['ENABLE_DISASSEMBLER']
@@ -474,17 +504,17 @@
       'LIBS':         ['pthread'],
     },
     'os:freebsd': {
-      'LIBPATH' : ['/usr/local/lib'],
-      'LIBS':     ['execinfo', 'pthread']
+      'LIBPATH' :     ['/usr/local/lib'],
+      'LIBS':         ['execinfo', 'pthread']
     },
     'os:solaris': {
-      'LIBPATH' : ['/usr/local/lib'],
-      'LIBS':     ['m', 'pthread', 'socket', 'nsl', 'rt'],
-      'LINKFLAGS': ['-mt']
+      'LIBPATH' :     ['/usr/local/lib'],
+      'LIBS':         ['m', 'pthread', 'socket', 'nsl', 'rt'],
+      'LINKFLAGS':    ['-mt']
     },
     'os:openbsd': {
-      'LIBPATH' : ['/usr/local/lib'],
-      'LIBS':     ['execinfo', 'pthread']
+      'LIBPATH' :     ['/usr/local/lib'],
+      'LIBS':         ['execinfo', 'pthread']
     },
     'os:win32': {
       'LIBS':         ['winmm', 'ws2_32']
@@ -577,11 +607,155 @@
       }
     },
     'arch:ia32': {
-      'CPPDEFINES': ['V8_TARGET_ARCH_IA32'],
+      'CPPDEFINES': ['V8_TARGET_ARCH_IA32', 'WIN32'],
       'LINKFLAGS': ['/MACHINE:X86']
     },
     'arch:x64': {
-      'CPPDEFINES': ['V8_TARGET_ARCH_X64'],
+      'CPPDEFINES': ['V8_TARGET_ARCH_X64', 'WIN32'],
+      'LINKFLAGS': ['/MACHINE:X64', '/STACK:2091752']
+    },
+    'mode:debug': {
+      'CCFLAGS':    ['/Od'],
+      'LINKFLAGS':  ['/DEBUG'],
+      'CPPDEFINES': ['DEBUG'],
+      'msvcrt:static': {
+        'CCFLAGS':  ['/MTd']
+      },
+      'msvcrt:shared': {
+        'CCFLAGS':  ['/MDd']
+      }
+    }
+  }
+}
+
+
+PREPARSER_FLAGS = {
+  'all': {
+    'CPPPATH': [join(abspath('.'), 'include'), join(abspath('.'), 'src')]
+  },
+  'gcc': {
+    'all': {
+      'LIBPATH': ['.'],
+      'CCFLAGS': ['-fno-rtti', '-fno-exceptions']
+    },
+    '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',
+                      ANDROID_TOP + '/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/lib/gcc/arm-eabi/4.4.0/interwork'],
+      'LINKFLAGS':    ANDROID_LINKFLAGS,
+      'LIBS':         ['log', 'c', 'stdc++', 'm', 'gcc'],
+      'mode:release': {
+        'CPPDEFINES': ['SK_RELEASE', 'NDEBUG']
+      }
+    },
+    'arch:arm': {
+      'LINKFLAGS':   ARM_LINK_FLAGS
+    },
+    'arch:ia32': {
+      'CCFLAGS':      ['-m32'],
+      'LINKFLAGS':    ['-m32']
+    },
+    'arch:x64': {
+      'CCFLAGS':      ['-m64'],
+      'LINKFLAGS':    ['-m64']
+    },
+    'arch:mips': {
+      'CPPDEFINES':   ['V8_TARGET_ARCH_MIPS'],
+      'mips_arch_variant:mips32r2': {
+        'CPPDEFINES':    ['_MIPS_ARCH_MIPS32R2']
+      },
+      'simulator:none': {
+        'CCFLAGS':      ['-EL'],
+        'LINKFLAGS':    ['-EL'],
+        'mips_arch_variant:mips32r2': {
+          'CCFLAGS':      ['-mips32r2', '-Wa,-mips32r2']
+        },
+        'mips_arch_variant:mips32r1': {
+          'CCFLAGS':      ['-mips32', '-Wa,-mips32']
+        },
+        'library:static': {
+          'LINKFLAGS':    ['-static', '-static-libgcc']
+        },
+        'mipsabi:softfloat': {
+          'CCFLAGS':      ['-msoft-float'],
+          'LINKFLAGS':    ['-msoft-float']
+        },
+        'mipsabi:hardfloat': {
+          'CCFLAGS':      ['-mhard-float'],
+          'LINKFLAGS':    ['-mhard-float']
+        }
+      }
+    },
+    'simulator:arm': {
+      'CCFLAGS':      ['-m32'],
+      'LINKFLAGS':    ['-m32']
+    },
+    'simulator:mips': {
+      'CCFLAGS':      ['-m32'],
+      'LINKFLAGS':    ['-m32'],
+      'mipsabi:softfloat': {
+        'CPPDEFINES':    ['__mips_soft_float=1'],
+      }
+    },
+    'mode:release': {
+      'CCFLAGS':      ['-O2']
+    },
+    'mode:debug': {
+      'CCFLAGS':      ['-g', '-O0'],
+      'CPPDEFINES':   ['DEBUG']
+    },
+  },
+  'msvc': {
+    'all': {
+      'LIBS': ['winmm', 'ws2_32']
+    },
+    'verbose:off': {
+      'CCFLAGS': ['/nologo'],
+      'LINKFLAGS': ['/NOLOGO']
+    },
+    'verbose:on': {
+      'LINKFLAGS': ['/VERBOSE']
+    },
+    'library:shared': {
+      'CPPDEFINES': ['USING_V8_SHARED']
+    },
+    'prof:on': {
+      'LINKFLAGS': ['/MAP']
+    },
+    'mode:release': {
+      'CCFLAGS':   ['/O2'],
+      'LINKFLAGS': ['/OPT:REF', '/OPT:ICF'],
+      'msvcrt:static': {
+        'CCFLAGS': ['/MT']
+      },
+      'msvcrt:shared': {
+        'CCFLAGS': ['/MD']
+      },
+      'msvcltcg:on': {
+        'CCFLAGS':      ['/GL'],
+        'pgo:off': {
+          'LINKFLAGS':    ['/LTCG'],
+        },
+      },
+      'pgo:instrument': {
+        'LINKFLAGS':    ['/LTCG:PGI']
+      },
+      'pgo:optimize': {
+        'LINKFLAGS':    ['/LTCG:PGO']
+      }
+    },
+    'arch:ia32': {
+      'CPPDEFINES': ['V8_TARGET_ARCH_IA32', 'WIN32'],
+      'LINKFLAGS': ['/MACHINE:X86']
+    },
+    'arch:x64': {
+      'CPPDEFINES': ['V8_TARGET_ARCH_X64', 'WIN32'],
       'LINKFLAGS': ['/MACHINE:X64', '/STACK:2091752']
     },
     'mode:debug': {
@@ -784,6 +958,12 @@
     'default': 'off',
     'help': 'enable the disassembler to inspect generated code'
   },
+  'fasttls': {
+    'values': ['on', 'off'],
+    'default': 'on',
+    'help': 'enable fast thread local storage support '
+            '(if available on the current architecture/platform)'
+  },
   'sourcesignatures': {
     'values': ['MD5', 'timestamp'],
     'default': 'MD5',
@@ -808,6 +988,16 @@
     'values': ['off', 'instrument', 'optimize'],
     'default': 'off',
     'help': 'select profile guided optimization variant',
+  },
+  'mipsabi': {
+    'values': ['hardfloat', 'softfloat', 'none'],
+    'default': 'hardfloat',
+    'help': 'generate calling conventiont according to selected mips ABI'
+  },
+  'mips_arch_variant': {
+    'values': ['mips32r2', 'mips32r1'],
+    'default': 'mips32r2',
+    'help': 'mips variant'
   }
 }
 
@@ -926,6 +1116,7 @@
     self.options = options
     self.env_overrides = env_overrides
     self.samples = samples
+    self.preparser_targets = []
     self.use_snapshot = (options['snapshot'] != 'off')
     self.build_snapshot = (options['snapshot'] == 'on')
     self.flags = None
@@ -1004,11 +1195,12 @@
     if 'msvcltcg' in ARGUMENTS:
       print "Warning: forcing msvcltcg on as it is required for pgo (%s)" % options['pgo']
     options['msvcltcg'] = 'on'
-  if options['arch'] == 'mips':
-    if ('regexp' in ARGUMENTS) and options['regexp'] == 'native':
-      # Print a warning if native regexp is specified for mips
-      print "Warning: forcing regexp to interpreted for mips"
-    options['regexp'] = 'interpreted'
+    if (options['simulator'] == 'mips' and options['mipsabi'] != 'softfloat'):
+      # Print a warning if soft-float ABI is not selected for mips simulator
+      print "Warning: forcing soft-float mips ABI when running on simulator"
+      options['mipsabi'] = 'softfloat'
+    if (options['mipsabi'] != 'none') and (options['arch'] != 'mips') and (options['simulator'] != 'mips'):
+      options['mipsabi'] = 'none'
   if options['liveobjectlist'] == 'on':
     if (options['debuggersupport'] != 'on') or (options['mode'] == 'release'):
       # Print a warning that liveobjectlist will implicitly enable the debugger
@@ -1055,6 +1247,7 @@
   dtoa_flags = context.AddRelevantFlags(library_flags, DTOA_EXTRA_FLAGS)
   cctest_flags = context.AddRelevantFlags(v8_flags, CCTEST_EXTRA_FLAGS)
   sample_flags = context.AddRelevantFlags(user_environ, SAMPLE_FLAGS)
+  preparser_flags = context.AddRelevantFlags(user_environ, PREPARSER_FLAGS)
   d8_flags = context.AddRelevantFlags(library_flags, D8_FLAGS)
 
   context.flags = {
@@ -1063,13 +1256,15 @@
     'dtoa': dtoa_flags,
     'cctest': cctest_flags,
     'sample': sample_flags,
-    'd8': d8_flags
+    'd8': d8_flags,
+    'preparser': preparser_flags
   }
 
   # Generate library base name.
   target_id = mode
   suffix = SUFFIXES[target_id]
   library_name = 'v8' + suffix
+  preparser_library_name = 'v8preparser' + suffix
   version = GetVersion()
   if context.options['soname'] == 'on':
     # When building shared object with SONAME version the library name.
@@ -1083,7 +1278,7 @@
     env['SONAME'] = soname
 
   # Build the object files by invoking SCons recursively.
-  (object_files, shell_files, mksnapshot) = env.SConscript(
+  (object_files, shell_files, mksnapshot, preparser_files) = env.SConscript(
     join('src', 'SConscript'),
     build_dir=join('obj', target_id),
     exports='context',
@@ -1098,13 +1293,20 @@
   context.ApplyEnvOverrides(env)
   if context.options['library'] == 'static':
     library = env.StaticLibrary(library_name, object_files)
+    preparser_library = env.StaticLibrary(preparser_library_name,
+                                          preparser_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)
+    preparser_pdb_name = preparser_library_name + '.dll.pdb';
+    preparser_library = env.SharedLibrary(preparser_library_name,
+                                          preparser_files,
+                                          PDB=preparser_pdb_name)
   context.library_targets.append(library)
+  context.library_targets.append(preparser_library)
 
   d8_env = Environment()
   d8_env.Replace(**context.flags['d8'])
@@ -1138,6 +1340,21 @@
   )
   context.cctest_targets.append(cctest_program)
 
+  preparser_env = env.Copy()
+  preparser_env.Replace(**context.flags['preparser'])
+  preparser_env.Prepend(LIBS=[preparser_library_name])
+  context.ApplyEnvOverrides(preparser_env)
+  preparser_object = preparser_env.SConscript(
+    join('preparser', 'SConscript'),
+    build_dir=join('obj', 'preparser', target_id),
+    exports='context',
+    duplicate=False
+  )
+  preparser_name = join('obj', 'preparser', target_id, 'preparser' + suffix)
+  preparser_program = preparser_env.Program(preparser_name, preparser_object);
+  preparser_env.Depends(preparser_program, preparser_library)
+  context.preparser_targets.append(preparser_program)
+
   return context
 
 
@@ -1154,6 +1371,7 @@
   mksnapshots = []
   cctests = []
   samples = []
+  preparsers = []
   d8s = []
   modes = SplitList(env['mode'])
   for mode in modes:
@@ -1162,6 +1380,7 @@
     mksnapshots += context.mksnapshot_targets
     cctests += context.cctest_targets
     samples += context.sample_targets
+    preparsers += context.preparser_targets
     d8s += context.d8_targets
 
   env.Alias('library', libraries)
@@ -1169,6 +1388,7 @@
   env.Alias('cctests', cctests)
   env.Alias('sample', samples)
   env.Alias('d8', d8s)
+  env.Alias('preparser', preparsers)
 
   if env['sample']:
     env.Default('sample')
diff --git a/include/v8-debug.h b/include/v8-debug.h
index f17b848..0bdff84 100755
--- a/include/v8-debug.h
+++ b/include/v8-debug.h
@@ -227,7 +227,7 @@
    * Debug message callback function.
    *
    * \param message the debug message handler message object
-
+   *
    * A MessageHandler does not take possession of the message data,
    * and must not rely on the data persisting after the handler returns.
    */
@@ -253,25 +253,35 @@
   static bool SetDebugEventListener(v8::Handle<v8::Object> that,
                                     Handle<Value> data = Handle<Value>());
 
-  // Schedule a debugger break to happen when JavaScript code is run.
-  static void DebugBreak();
+  // Schedule a debugger break to happen when JavaScript code is run
+  // in the given isolate. If no isolate is provided the default
+  // isolate is used.
+  static void DebugBreak(Isolate* isolate = NULL);
 
-  // Remove scheduled debugger break if it has not happened yet.
-  static void CancelDebugBreak();
+  // Remove scheduled debugger break in given isolate if it has not
+  // happened yet. If no isolate is provided the default isolate is
+  // used.
+  static void CancelDebugBreak(Isolate* isolate = NULL);
 
-  // Break execution of JavaScript (this method can be invoked from a
-  // non-VM thread) for further client command execution on a VM
-  // thread. Client data is then passed in EventDetails to
-  // EventCallback at the moment when the VM actually stops.
-  static void DebugBreakForCommand(ClientData* data = NULL);
+  // Break execution of JavaScript in the given isolate (this method
+  // can be invoked from a non-VM thread) for further client command
+  // execution on a VM thread. Client data is then passed in
+  // EventDetails to EventCallback at the moment when the VM actually
+  // stops. If no isolate is provided the default isolate is used.
+  static void DebugBreakForCommand(ClientData* data = NULL,
+                                   Isolate* isolate = NULL);
 
   // Message based interface. The message protocol is JSON. NOTE the message
   // handler thread is not supported any more parameter must be false.
   static void SetMessageHandler(MessageHandler handler,
                                 bool message_handler_thread = false);
   static void SetMessageHandler2(MessageHandler2 handler);
+
+  // If no isolate is provided the default isolate is
+  // used.
   static void SendCommand(const uint16_t* command, int length,
-                          ClientData* client_data = NULL);
+                          ClientData* client_data = NULL,
+                          Isolate* isolate = NULL);
 
   // Dispatch interface.
   static void SetHostDispatchHandler(HostDispatchHandler handler,
diff --git a/include/v8-profiler.h b/include/v8-profiler.h
index 675a229..db56e26 100644
--- a/include/v8-profiler.h
+++ b/include/v8-profiler.h
@@ -131,6 +131,16 @@
 
   /** Returns the root node of the top down call tree. */
   const CpuProfileNode* GetTopDownRoot() const;
+
+  /**
+   * Deletes the profile and removes it from CpuProfiler's list.
+   * All pointers to nodes previously returned become invalid.
+   * Profiles with the same uid but obtained using different
+   * security token are not deleted, but become inaccessible
+   * using FindProfile method. It is embedder's responsibility
+   * to call Delete on these profiles.
+   */
+  void Delete();
 };
 
 
@@ -181,6 +191,13 @@
   static const CpuProfile* StopProfiling(
       Handle<String> title,
       Handle<Value> security_token = Handle<Value>());
+
+  /**
+   * Deletes all existing profiles, also cancelling all profiling
+   * activity.  All previously returned pointers to profiles and their
+   * contents become invalid after this call.
+   */
+  static void DeleteAllProfiles();
 };
 
 
@@ -223,36 +240,21 @@
 };
 
 
-class V8EXPORT HeapGraphPath {
- public:
-  /** Returns the number of edges in the path. */
-  int GetEdgesCount() const;
-
-  /** Returns an edge from the path. */
-  const HeapGraphEdge* GetEdge(int index) const;
-
-  /** Returns origin node. */
-  const HeapGraphNode* GetFromNode() const;
-
-  /** Returns destination node. */
-  const HeapGraphNode* GetToNode() const;
-};
-
-
 /**
  * HeapGraphNode represents a node in a heap graph.
  */
 class V8EXPORT HeapGraphNode {
  public:
   enum Type {
-    kHidden = 0,     // Hidden node, may be filtered when shown to user.
-    kArray = 1,      // An array of elements.
-    kString = 2,     // A string.
-    kObject = 3,     // A JS object (except for arrays and strings).
-    kCode = 4,       // Compiled code.
-    kClosure = 5,    // Function closure.
-    kRegExp = 6,     // RegExp.
-    kHeapNumber = 7  // Number stored in the heap.
+    kHidden = 0,      // Hidden node, may be filtered when shown to user.
+    kArray = 1,       // An array of elements.
+    kString = 2,      // A string.
+    kObject = 3,      // A JS object (except for arrays and strings).
+    kCode = 4,        // Compiled code.
+    kClosure = 5,     // Function closure.
+    kRegExp = 6,      // RegExp.
+    kHeapNumber = 7,  // Number stored in the heap.
+    kNative = 8       // Native object (not from V8 heap).
   };
 
   /** Returns node type (see HeapGraphNode::Type). */
@@ -307,12 +309,6 @@
   /** Returns a retainer by index. */
   const HeapGraphEdge* GetRetainer(int index) const;
 
-  /** Returns the number of simple retaining paths from the root to the node. */
-  int GetRetainingPathsCount() const;
-
-  /** Returns a retaining path by index. */
-  const HeapGraphPath* GetRetainingPath(int index) const;
-
   /**
    * Returns a dominator node. This is the node that participates in every
    * path from the snapshot root to the current node.
@@ -321,16 +317,6 @@
 };
 
 
-class V8EXPORT HeapSnapshotsDiff {
- public:
-  /** Returns the root node for added nodes. */
-  const HeapGraphNode* GetAdditionsRoot() const;
-
-  /** Returns the root node for deleted nodes. */
-  const HeapGraphNode* GetDeletionsRoot() const;
-};
-
-
 /**
  * HeapSnapshots record the state of the JS heap at some moment.
  */
@@ -361,10 +347,11 @@
   const HeapGraphNode* GetNodeById(uint64_t id) const;
 
   /**
-   * Returns a diff between this snapshot and another one. Only snapshots
-   * of the same type can be compared.
+   * Deletes the snapshot and removes it from HeapProfiler's list.
+   * All pointers to nodes, edges and paths previously returned become
+   * invalid.
    */
-  const HeapSnapshotsDiff* CompareWith(const HeapSnapshot* snapshot) const;
+  void Delete();
 
   /**
    * Prepare a serialized representation of the snapshot. The result
@@ -392,11 +379,22 @@
 };
 
 
+class RetainedObjectInfo;
+
 /**
  * Interface for controlling heap profiling.
  */
 class V8EXPORT HeapProfiler {
  public:
+  /**
+   * Callback function invoked for obtaining RetainedObjectInfo for
+   * the given JavaScript wrapper object. It is prohibited to enter V8
+   * while the callback is running: only getters on the handle and
+   * GetPointerFromInternalField on the objects are allowed.
+   */
+  typedef RetainedObjectInfo* (*WrapperInfoCallback)
+      (uint16_t class_id, Handle<Value> wrapper);
+
   /** Returns the number of snapshots taken. */
   static int GetSnapshotsCount();
 
@@ -414,6 +412,87 @@
       Handle<String> title,
       HeapSnapshot::Type type = HeapSnapshot::kFull,
       ActivityControl* control = NULL);
+
+  /**
+   * Deletes all snapshots taken. All previously returned pointers to
+   * snapshots and their contents become invalid after this call.
+   */
+  static void DeleteAllSnapshots();
+
+  /** Binds a callback to embedder's class ID. */
+  static void DefineWrapperClass(
+      uint16_t class_id,
+      WrapperInfoCallback callback);
+
+  /**
+   * Default value of persistent handle class ID. Must not be used to
+   * define a class. Can be used to reset a class of a persistent
+   * handle.
+   */
+  static const uint16_t kPersistentHandleNoClassId = 0;
+};
+
+
+/**
+ * Interface for providing information about embedder's objects
+ * held by global handles. This information is reported in two ways:
+ *
+ *  1. When calling AddObjectGroup, an embedder may pass
+ *     RetainedObjectInfo instance describing the group.  To collect
+ *     this information while taking a heap snapshot, V8 calls GC
+ *     prologue and epilogue callbacks.
+ *
+ *  2. When a heap snapshot is collected, V8 additionally
+ *     requests RetainedObjectInfos for persistent handles that
+ *     were not previously reported via AddObjectGroup.
+ *
+ * Thus, if an embedder wants to provide information about native
+ * objects for heap snapshots, he can do it in a GC prologue
+ * handler, and / or by assigning wrapper class ids in the following way:
+ *
+ *  1. Bind a callback to class id by calling DefineWrapperClass.
+ *  2. Call SetWrapperClassId on certain persistent handles.
+ *
+ * V8 takes ownership of RetainedObjectInfo instances passed to it and
+ * keeps them alive only during snapshot collection. Afterwards, they
+ * are freed by calling the Dispose class function.
+ */
+class V8EXPORT RetainedObjectInfo {  // NOLINT
+ public:
+  /** Called by V8 when it no longer needs an instance. */
+  virtual void Dispose() = 0;
+
+  /** Returns whether two instances are equivalent. */
+  virtual bool IsEquivalent(RetainedObjectInfo* other) = 0;
+
+  /**
+   * Returns hash value for the instance. Equivalent instances
+   * must have the same hash value.
+   */
+  virtual intptr_t GetHash() = 0;
+
+  /**
+   * Returns human-readable label. It must be a NUL-terminated UTF-8
+   * encoded string. V8 copies its contents during a call to GetLabel.
+   */
+  virtual const char* GetLabel() = 0;
+
+  /**
+   * Returns element count in case if a global handle retains
+   * a subgraph by holding one of its nodes.
+   */
+  virtual intptr_t GetElementCount() { return -1; }
+
+  /** Returns embedder's object size in bytes. */
+  virtual intptr_t GetSizeInBytes() { return -1; }
+
+ protected:
+  RetainedObjectInfo() {}
+  virtual ~RetainedObjectInfo() {}
+
+ private:
+  RetainedObjectInfo(const RetainedObjectInfo&);
+  RetainedObjectInfo& operator=(const RetainedObjectInfo&);
 };
 
 
diff --git a/include/v8-testing.h b/include/v8-testing.h
index 4db30a4..245f74d 100644
--- a/include/v8-testing.h
+++ b/include/v8-testing.h
@@ -87,6 +87,11 @@
    * should be between 0 and one less than the result from GetStressRuns()
    */
   static void PrepareStressRun(int run);
+
+  /**
+   * Force deoptimization of all functions.
+   */
+  static void DeoptimizeAll();
 };
 
 
diff --git a/include/v8.h b/include/v8.h
index 83a5744..62d1085 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -110,7 +110,8 @@
 class Arguments;
 class Object;
 class Heap;
-class Top;
+class HeapObject;
+class Isolate;
 }
 
 
@@ -396,6 +397,12 @@
    */
   inline bool IsWeak() const;
 
+  /**
+   * Assigns a wrapper class ID to the handle. See RetainedObjectInfo
+   * interface description in v8-profiler.h for details.
+   */
+  inline void SetWrapperClassId(uint16_t class_id);
+
  private:
   friend class ImplementationUtilities;
   friend class ObjectTemplate;
@@ -437,6 +444,8 @@
    * Creates a new handle with the given value.
    */
   static internal::Object** CreateHandle(internal::Object* value);
+  // Faster version, uses HeapObject to obtain the current Isolate.
+  static internal::Object** CreateHandle(internal::HeapObject* value);
 
  private:
   // Make it impossible to create heap-allocated or illegal handle
@@ -453,7 +462,6 @@
     internal::Object** next;
     internal::Object** limit;
     int level;
-
     inline void Initialize() {
       next = limit = NULL;
       level = 0;
@@ -462,6 +470,7 @@
 
   void Leave();
 
+  internal::Isolate* isolate_;
   internal::Object** prev_next_;
   internal::Object** prev_limit_;
 
@@ -1435,7 +1444,8 @@
   kExternalUnsignedShortArray,
   kExternalIntArray,
   kExternalUnsignedIntArray,
-  kExternalFloatArray
+  kExternalFloatArray,
+  kExternalPixelArray
 };
 
 /**
@@ -1699,7 +1709,12 @@
    */
   V8EXPORT Local<Object> CloneElementAt(uint32_t index);
 
+  /**
+   * Creates a JavaScript array with the given length. If the length
+   * is negative the returned array will have length 0.
+   */
   V8EXPORT static Local<Array> New(int length = 0);
+
   static inline Array* Cast(Value* obj);
  private:
   V8EXPORT Array();
@@ -2533,6 +2548,92 @@
 };
 
 
+class RetainedObjectInfo;
+
+/**
+ * Isolate represents an isolated instance of the V8 engine.  V8
+ * isolates have completely separate states.  Objects from one isolate
+ * must not be used in other isolates.  When V8 is initialized a
+ * default isolate is implicitly created and entered.  The embedder
+ * can create additional isolates and use them in parallel in multiple
+ * threads.  An isolate can be entered by at most one thread at any
+ * given time.  The Locker/Unlocker API can be used to synchronize.
+ */
+class V8EXPORT Isolate {
+ public:
+  /**
+   * Stack-allocated class which sets the isolate for all operations
+   * executed within a local scope.
+   */
+  class V8EXPORT Scope {
+   public:
+    explicit Scope(Isolate* isolate) : isolate_(isolate) {
+      isolate->Enter();
+    }
+
+    ~Scope() { isolate_->Exit(); }
+
+   private:
+    Isolate* const isolate_;
+
+    // Prevent copying of Scope objects.
+    Scope(const Scope&);
+    Scope& operator=(const Scope&);
+  };
+
+  /**
+   * Creates a new isolate.  Does not change the currently entered
+   * isolate.
+   *
+   * When an isolate is no longer used its resources should be freed
+   * by calling Dispose().  Using the delete operator is not allowed.
+   */
+  static Isolate* New();
+
+  /**
+   * Returns the entered isolate for the current thread or NULL in
+   * case there is no current isolate.
+   */
+  static Isolate* GetCurrent();
+
+  /**
+   * Methods below this point require holding a lock (using Locker) in
+   * a multi-threaded environment.
+   */
+
+  /**
+   * Sets this isolate as the entered one for the current thread.
+   * Saves the previously entered one (if any), so that it can be
+   * restored when exiting.  Re-entering an isolate is allowed.
+   */
+  void Enter();
+
+  /**
+   * Exits this isolate by restoring the previously entered one in the
+   * current thread.  The isolate may still stay the same, if it was
+   * entered more than once.
+   *
+   * Requires: this == Isolate::GetCurrent().
+   */
+  void Exit();
+
+  /**
+   * Disposes the isolate.  The isolate must not be entered by any
+   * thread to be disposable.
+   */
+  void Dispose();
+
+ private:
+
+  Isolate();
+  Isolate(const Isolate&);
+  ~Isolate();
+  Isolate& operator=(const Isolate&);
+  void* operator new(size_t size);
+  void operator delete(void*, size_t);
+};
+
+
 /**
  * Container class for static utility functions.
  */
@@ -2702,8 +2803,22 @@
    * intended to be used in the before-garbage-collection callback
    * function, for instance to simulate DOM tree connections among JS
    * wrapper objects.
+   * See v8-profiler.h for RetainedObjectInfo interface description.
    */
-  static void AddObjectGroup(Persistent<Value>* objects, size_t length);
+  static void AddObjectGroup(Persistent<Value>* objects,
+                             size_t length,
+                             RetainedObjectInfo* info = NULL);
+
+  /**
+   * Allows the host application to declare implicit references between
+   * the objects: if |parent| is alive, all |children| are alive too.
+   * After each garbage collection, all implicit references
+   * are removed.  It is intended to be used in the before-garbage-collection
+   * callback function.
+   */
+  static void AddImplicitReferences(Persistent<Object> parent,
+                                    Persistent<Value>* children,
+                                    size_t length);
 
   /**
    * Initializes from snapshot if possible. Otherwise, attempts to
@@ -2844,12 +2959,16 @@
   static void TerminateExecution(int thread_id);
 
   /**
-   * Forcefully terminate the current thread of JavaScript execution.
+   * Forcefully terminate the current thread of JavaScript execution
+   * in the given isolate. If no isolate is provided, the default
+   * isolate is used.
    *
    * This method can be used by any thread even if that thread has not
    * acquired the V8 lock with a Locker object.
+   *
+   * \param isolate The isolate in which to terminate the current JS execution.
    */
-  static void TerminateExecution();
+  static void TerminateExecution(Isolate* isolate = NULL);
 
   /**
    * Is V8 terminating JavaScript execution.
@@ -2912,6 +3031,8 @@
   static void ClearWeak(internal::Object** global_handle);
   static bool IsGlobalNearDeath(internal::Object** global_handle);
   static bool IsGlobalWeak(internal::Object** global_handle);
+  static void SetWrapperClassId(internal::Object** global_handle,
+                                uint16_t class_id);
 
   template <class T> friend class Handle;
   template <class T> friend class Local;
@@ -3025,7 +3146,7 @@
   bool capture_message_ : 1;
   bool rethrow_ : 1;
 
-  friend class v8::internal::Top;
+  friend class v8::internal::Isolate;
 };
 
 
@@ -3188,15 +3309,26 @@
 
 /**
  * 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.
+ * is allowed to use any given V8 isolate. See Isolate class
+ * comments. The definition of 'using V8 isolate' includes
+ * accessing handles or holding onto object pointers obtained
+ * from V8 handles while in the particular V8 isolate.  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:
+ * More then one thread and multiple V8 isolates can be used
+ * without any locking if each isolate is created and accessed
+ * by a single thread only. For example, one thread can use
+ * multiple isolates or multiple threads can each create and run
+ * their own isolate.
+ *
+ * If you wish to start using V8 isolate in more then one thread
+ * you can do this by constructing a v8::Locker object to guard
+ * access to the isolate. 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
+ * (assumes the default isolate that is used if not specified as
+ * a parameter for the Locker):
  *
  * \code
  * ...
@@ -3438,7 +3570,7 @@
   // These values match non-compiler-dependent values defined within
   // the implementation of v8.
   static const int kHeapObjectMapOffset = 0;
-  static const int kMapInstanceTypeOffset = kApiPointerSize + kApiIntSize;
+  static const int kMapInstanceTypeOffset = 1 * kApiPointerSize + kApiIntSize;
   static const int kStringResourceOffset =
       InternalConstants<kApiPointerSize>::kStringResourceOffset;
 
@@ -3495,6 +3627,14 @@
     uint8_t* addr = reinterpret_cast<uint8_t*>(ptr) + offset - kHeapObjectTag;
     return *reinterpret_cast<T*>(addr);
   }
+
+  static inline bool CanCastToHeapObject(void* o) { return false; }
+  static inline bool CanCastToHeapObject(Context* o) { return true; }
+  static inline bool CanCastToHeapObject(String* o) { return true; }
+  static inline bool CanCastToHeapObject(Object* o) { return true; }
+  static inline bool CanCastToHeapObject(Message* o) { return true; }
+  static inline bool CanCastToHeapObject(StackTrace* o) { return true; }
+  static inline bool CanCastToHeapObject(StackFrame* o) { return true; }
 };
 
 }  // namespace internal
@@ -3511,7 +3651,12 @@
 template <class T>
 Local<T> Local<T>::New(Handle<T> that) {
   if (that.IsEmpty()) return Local<T>();
-  internal::Object** p = reinterpret_cast<internal::Object**>(*that);
+  T* that_ptr = *that;
+  internal::Object** p = reinterpret_cast<internal::Object**>(that_ptr);
+  if (internal::Internals::CanCastToHeapObject(that_ptr)) {
+    return Local<T>(reinterpret_cast<T*>(HandleScope::CreateHandle(
+        reinterpret_cast<internal::HeapObject*>(*p))));
+  }
   return Local<T>(reinterpret_cast<T*>(HandleScope::CreateHandle(*p)));
 }
 
@@ -3560,6 +3705,10 @@
   V8::ClearWeak(reinterpret_cast<internal::Object**>(**this));
 }
 
+template <class T>
+void Persistent<T>::SetWrapperClassId(uint16_t class_id) {
+  V8::SetWrapperClassId(reinterpret_cast<internal::Object**>(**this), class_id);
+}
 
 Arguments::Arguments(internal::Object** implicit_args,
                      internal::Object** values, int length,
diff --git a/samples/shell.cc b/samples/shell.cc
index 64f78f0..0710d46 100644
--- a/samples/shell.cc
+++ b/samples/shell.cc
@@ -33,7 +33,28 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+// When building with V8 in a shared library we cannot use functions which
+// is not explicitly a part of the public V8 API. This extensive use of
+// #ifndef USING_V8_SHARED/#endif is a hack until we can resolve whether to
+// still use the shell sample for testing or change to use the developer
+// shell d8 TODO(1272).
+#ifndef USING_V8_SHARED
+#include "../src/v8.h"
+#endif  // USING_V8_SHARED
 
+#if !defined(_WIN32) && !defined(_WIN64)
+#include <unistd.h>  // NOLINT
+#endif
+
+static void ExitShell(int exit_code) {
+  // Use _exit instead of exit to avoid races between isolate
+  // threads and static destructors.
+  fflush(stdout);
+  fflush(stderr);
+  _exit(exit_code);
+}
+
+v8::Persistent<v8::Context> CreateShellContext();
 void RunShell(v8::Handle<v8::Context> context);
 bool ExecuteString(v8::Handle<v8::String> source,
                    v8::Handle<v8::Value> name,
@@ -48,58 +69,200 @@
 void ReportException(v8::TryCatch* handler);
 
 
-int RunMain(int argc, char* argv[]) {
-  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 'read' function to the C++ Read callback.
-  global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read));
-  // Bind the global 'load' function to the C++ Load callback.
-  global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load));
-  // 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::Persistent<v8::Context> context = v8::Context::New(NULL, global);
-  bool run_shell = (argc == 1);
-  for (int i = 1; i < argc; i++) {
-    // Enter the execution environment before evaluating any code.
-    v8::Context::Scope context_scope(context);
-    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;
+static bool last_run = true;
+
+class SourceGroup {
+ public:
+  SourceGroup() :
+#ifndef USING_V8_SHARED
+                  next_semaphore_(v8::internal::OS::CreateSemaphore(0)),
+                  done_semaphore_(v8::internal::OS::CreateSemaphore(0)),
+                  thread_(NULL),
+#endif  // USING_V8_SHARED
+                  argv_(NULL),
+                  begin_offset_(0),
+                  end_offset_(0) { }
+
+  void Begin(char** argv, int offset) {
+    argv_ = const_cast<const char**>(argv);
+    begin_offset_ = offset;
+  }
+
+  void End(int offset) { end_offset_ = offset; }
+
+  void Execute() {
+    for (int i = begin_offset_; i < end_offset_; ++i) {
+      const char* arg = argv_[i];
+      if (strcmp(arg, "-e") == 0 && i + 1 < end_offset_) {
+        // 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)) {
+          ExitShell(1);
+          return;
+        }
+        ++i;
+      } else if (arg[0] == '-') {
+        // Ignore other options. They have been parsed already.
+      } 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(arg);
+        v8::Handle<v8::String> source = ReadFile(arg);
+        if (source.IsEmpty()) {
+          printf("Error reading '%s'\n", arg);
+        }
+        if (!ExecuteString(source, file_name, false, true)) {
+          ExitShell(1);
+          return;
+        }
       }
-      if (!ExecuteString(source, file_name, false, true))
-        return 1;
     }
   }
+
+#ifndef USING_V8_SHARED
+  void StartExecuteInThread() {
+    if (thread_ == NULL) {
+      thread_ = new IsolateThread(this);
+      thread_->Start();
+    }
+    next_semaphore_->Signal();
+  }
+
+  void WaitForThread() {
+    if (thread_ == NULL) return;
+    if (last_run) {
+      thread_->Join();
+      thread_ = NULL;
+    } else {
+      done_semaphore_->Wait();
+    }
+  }
+#endif  // USING_V8_SHARED
+
+ private:
+#ifndef USING_V8_SHARED
+  static v8::internal::Thread::Options GetThreadOptions() {
+    v8::internal::Thread::Options options;
+    options.name = "IsolateThread";
+    // On some systems (OSX 10.6) the stack size default is 0.5Mb or less
+    // which is not enough to parse the big literal expressions used in tests.
+    // The stack size should be at least StackGuard::kLimitSize + some
+    // OS-specific padding for thread startup code.
+    options.stack_size = 2 << 20;  // 2 Mb seems to be enough
+    return options;
+  }
+
+  class IsolateThread : public v8::internal::Thread {
+   public:
+    explicit IsolateThread(SourceGroup* group)
+        : v8::internal::Thread(NULL, GetThreadOptions()), group_(group) {}
+
+    virtual void Run() {
+      group_->ExecuteInThread();
+    }
+
+   private:
+    SourceGroup* group_;
+  };
+
+  void ExecuteInThread() {
+    v8::Isolate* isolate = v8::Isolate::New();
+    do {
+      if (next_semaphore_ != NULL) next_semaphore_->Wait();
+      {
+        v8::Isolate::Scope iscope(isolate);
+        v8::HandleScope scope;
+        v8::Persistent<v8::Context> context = CreateShellContext();
+        {
+          v8::Context::Scope cscope(context);
+          Execute();
+        }
+        context.Dispose();
+      }
+      if (done_semaphore_ != NULL) done_semaphore_->Signal();
+    } while (!last_run);
+    isolate->Dispose();
+  }
+
+  v8::internal::Semaphore* next_semaphore_;
+  v8::internal::Semaphore* done_semaphore_;
+  v8::internal::Thread* thread_;
+#endif  // USING_V8_SHARED
+
+  const char** argv_;
+  int begin_offset_;
+  int end_offset_;
+};
+
+
+static SourceGroup* isolate_sources = NULL;
+
+
+int RunMain(int argc, char* argv[]) {
+  v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
+  v8::HandleScope handle_scope;
+  v8::Persistent<v8::Context> context = CreateShellContext();
+  // Enter the newly created execution environment.
+  context->Enter();
+  if (context.IsEmpty()) {
+    printf("Error creating context\n");
+    return 1;
+  }
+
+  bool run_shell = (argc == 1);
+  int num_isolates = 1;
+  for (int i = 1; i < argc; i++) {
+    if (strcmp(argv[i], "--isolate") == 0) {
+#ifndef USING_V8_SHARED
+      ++num_isolates;
+#else  // USING_V8_SHARED
+      printf("Error: --isolate not supported when linked with shared "
+             "library\n");
+      ExitShell(1);
+#endif  // USING_V8_SHARED
+    }
+  }
+  if (isolate_sources == NULL) {
+    isolate_sources = new SourceGroup[num_isolates];
+    SourceGroup* current = isolate_sources;
+    current->Begin(argv, 1);
+    for (int i = 1; i < argc; i++) {
+      const char* str = argv[i];
+      if (strcmp(str, "--isolate") == 0) {
+        current->End(i);
+        current++;
+        current->Begin(argv, i + 1);
+      } else 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);
+      }
+    }
+    current->End(argc);
+  }
+#ifndef USING_V8_SHARED
+  for (int i = 1; i < num_isolates; ++i) {
+    isolate_sources[i].StartExecuteInThread();
+  }
+#endif  // USING_V8_SHARED
+  isolate_sources[0].Execute();
   if (run_shell) RunShell(context);
+#ifndef USING_V8_SHARED
+  for (int i = 1; i < num_isolates; ++i) {
+    isolate_sources[i].WaitForThread();
+  }
+#endif  // USING_V8_SHARED
+  if (last_run) {
+    delete[] isolate_sources;
+    isolate_sources = NULL;
+  }
+  context->Exit();
   context.Dispose();
   return 0;
 }
@@ -137,8 +300,11 @@
       printf("============ Stress %d/%d ============\n",
              i + 1, stress_runs);
       v8::Testing::PrepareStressRun(i);
+      last_run = (i == stress_runs - 1);
       result = RunMain(argc, argv);
     }
+    printf("======== Full Deoptimization =======\n");
+    v8::Testing::DeoptimizeAll();
   } else {
     result = RunMain(argc, argv);
   }
@@ -153,6 +319,25 @@
 }
 
 
+// Creates a new execution environment containing the built-in
+// functions.
+v8::Persistent<v8::Context> CreateShellContext() {
+  // 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 'read' function to the C++ Read callback.
+  global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read));
+  // Bind the global 'load' function to the C++ Load callback.
+  global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load));
+  // 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));
+  return v8::Context::New(NULL, global);
+}
+
+
 // 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.
@@ -222,7 +407,7 @@
   // 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);
+  ExitShell(exit_code);
   return v8::Undefined();
 }
 
diff --git a/src/SConscript b/src/SConscript
index 34ca91c..3b9968e 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -84,6 +84,7 @@
     ic.cc
     inspector.cc
     interpreter-irregexp.cc
+    isolate.cc
     jsregexp.cc
     jump-target.cc
     lithium-allocator.cc
@@ -162,18 +163,23 @@
     arm/assembler-arm.cc
     """),
   'arch:mips': Split("""
+    jump-target-light.cc
+    virtual-frame-light.cc
     mips/assembler-mips.cc
     mips/builtins-mips.cc
+    mips/code-stubs-mips.cc
     mips/codegen-mips.cc
     mips/constants-mips.cc
     mips/cpu-mips.cc
     mips/debug-mips.cc
+    mips/deoptimizer-mips.cc
     mips/disasm-mips.cc
-    mips/full-codegen-mips.cc
     mips/frames-mips.cc
+    mips/full-codegen-mips.cc
     mips/ic-mips.cc
     mips/jump-target-mips.cc
     mips/macro-assembler-mips.cc
+    mips/regexp-macro-assembler-mips.cc
     mips/register-allocator-mips.cc
     mips/stub-cache-mips.cc
     mips/virtual-frame-mips.cc
@@ -244,6 +250,20 @@
 }
 
 
+PREPARSER_SOURCES = {
+  'all': Split("""
+    allocation.cc
+    hashmap.cc
+    preparse-data.cc
+    preparser.cc
+    preparser-api.cc
+    scanner-base.cc
+    token.cc
+    unicode.cc
+    """)
+}
+
+
 D8_FILES = {
   'all': [
     'd8.cc', 'd8-debug.cc'
@@ -329,6 +349,9 @@
   source_objs = context.ConfigureObject(env, source_files)
   non_snapshot_files = [source_objs]
 
+  preparser_source_files = context.GetRelevantSources(PREPARSER_SOURCES)
+  preparser_objs = context.ConfigureObject(env, preparser_source_files)
+
   # Create snapshot if necessary.  For cross compilation you should either
   # do without snapshots and take the performance hit or you should build a
   # host VM with the simulator=arm and snapshot=on options and then take the
@@ -349,8 +372,8 @@
   else:
     snapshot_obj = empty_snapshot_obj
   library_objs = [non_snapshot_files, libraries_obj, snapshot_obj]
-  return (library_objs, d8_objs, [mksnapshot])
+  return (library_objs, d8_objs, [mksnapshot], preparser_objs)
 
 
-(library_objs, d8_objs, mksnapshot) = ConfigureObjectFiles()
-Return('library_objs d8_objs mksnapshot')
+(library_objs, d8_objs, mksnapshot, preparser_objs) = ConfigureObjectFiles()
+Return('library_objs d8_objs mksnapshot preparser_objs')
diff --git a/src/accessors.cc b/src/accessors.cc
index 1826425..e33b4d7 100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -34,7 +34,6 @@
 #include "factory.h"
 #include "safepoint-table.h"
 #include "scopeinfo.h"
-#include "top.h"
 
 namespace v8 {
 namespace internal {
@@ -43,8 +42,9 @@
 template <class C>
 static C* FindInPrototypeChain(Object* obj, bool* found_it) {
   ASSERT(!*found_it);
+  Heap* heap = HEAP;
   while (!Is<C>(obj)) {
-    if (obj == Heap::null_value()) return NULL;
+    if (obj == heap->null_value()) return NULL;
     obj = obj->GetPrototype();
   }
   *found_it = true;
@@ -90,24 +90,25 @@
 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();
+  ASSERT(Isolate::Current()->context()->global_context()->number_function()->
+      has_initial_map());
+  Map* number_map = Isolate::Current()->context()->global_context()->
+      number_function()->initial_map();
   if (wrapper->map() == number_map) return wrapper->value();
   return value;
 }
 
 
 MaybeObject* Accessors::ArraySetLength(JSObject* object, Object* value, void*) {
+  Isolate* isolate = object->GetIsolate();
   value = FlattenNumber(value);
 
   // Need to call methods that may trigger GC.
-  HandleScope scope;
+  HandleScope scope(isolate);
 
   // Protect raw pointers.
-  Handle<JSObject> object_handle(object);
-  Handle<Object> value_handle(value);
+  Handle<JSObject> object_handle(object, isolate);
+  Handle<Object> value_handle(value, isolate);
 
   bool has_exception;
   Handle<Object> uint32_v = Execution::ToUint32(value_handle, &has_exception);
@@ -126,12 +127,13 @@
       // 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->SetLocalPropertyIgnoreAttributes(Heap::length_symbol(),
-                                                      value, NONE);
+      return object->SetLocalPropertyIgnoreAttributes(
+          isolate->heap()->length_symbol(), value, NONE);
     }
   }
-  return Top::Throw(*Factory::NewRangeError("invalid_array_length",
-                                            HandleVector<Object>(NULL, 0)));
+  return isolate->Throw(
+      *isolate->factory()->NewRangeError("invalid_array_length",
+                                         HandleVector<Object>(NULL, 0)));
 }
 
 
@@ -314,15 +316,18 @@
 
 
 MaybeObject* Accessors::ScriptGetLineEnds(Object* object, void*) {
-  HandleScope scope;
-  Handle<Script> script(Script::cast(JSValue::cast(object)->value()));
+  JSValue* wrapper = JSValue::cast(object);
+  Isolate* isolate = wrapper->GetIsolate();
+  HandleScope scope(isolate);
+  Handle<Script> script(Script::cast(wrapper->value()), isolate);
   InitScriptLineEnds(script);
   ASSERT(script->line_ends()->IsFixedArray());
   Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
   // We do not want anyone to modify this array from JS.
-  ASSERT(*line_ends == Heap::empty_fixed_array() ||
-         line_ends->map() == Heap::fixed_cow_array_map());
-  Handle<JSArray> js_array = Factory::NewJSArrayWithElements(line_ends);
+  ASSERT(*line_ends == isolate->heap()->empty_fixed_array() ||
+         line_ends->map() == isolate->heap()->fixed_cow_array_map());
+  Handle<JSArray> js_array =
+      isolate->factory()->NewJSArrayWithElements(line_ends);
   return *js_array;
 }
 
@@ -368,7 +373,7 @@
       return *GetScriptWrapper(eval_from_script);
     }
   }
-  return Heap::undefined_value();
+  return HEAP->undefined_value();
 }
 
 
@@ -391,7 +396,7 @@
   // If this is not a script compiled through eval there is no eval position.
   int compilation_type = Smi::cast(script->compilation_type())->value();
   if (compilation_type != Script::COMPILATION_TYPE_EVAL) {
-    return Heap::undefined_value();
+    return HEAP->undefined_value();
   }
 
   // Get the function from where eval was called and find the source position
@@ -443,9 +448,10 @@
 
 
 MaybeObject* Accessors::FunctionGetPrototype(Object* object, void*) {
+  Heap* heap = Isolate::Current()->heap();
   bool found_it = false;
   JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
-  if (!found_it) return Heap::undefined_value();
+  if (!found_it) return heap->undefined_value();
   while (!function->should_have_prototype()) {
     found_it = false;
     function = FindInPrototypeChain<JSFunction>(object->GetPrototype(),
@@ -456,7 +462,7 @@
 
   if (!function->has_prototype()) {
     Object* prototype;
-    { MaybeObject* maybe_prototype = Heap::AllocateFunctionPrototype(function);
+    { MaybeObject* maybe_prototype = heap->AllocateFunctionPrototype(function);
       if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype;
     }
     Object* result;
@@ -471,12 +477,13 @@
 MaybeObject* Accessors::FunctionSetPrototype(JSObject* object,
                                              Object* value,
                                              void*) {
+  Heap* heap = object->GetHeap();
   bool found_it = false;
   JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
-  if (!found_it) return Heap::undefined_value();
+  if (!found_it) return heap->undefined_value();
   if (!function->should_have_prototype()) {
     // Since we hit this accessor, object will have no prototype property.
-    return object->SetLocalPropertyIgnoreAttributes(Heap::prototype_symbol(),
+    return object->SetLocalPropertyIgnoreAttributes(heap->prototype_symbol(),
                                                     value,
                                                     NONE);
   }
@@ -545,7 +552,7 @@
 MaybeObject* Accessors::FunctionGetName(Object* object, void*) {
   bool found_it = false;
   JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
-  if (!found_it) return Heap::undefined_value();
+  if (!found_it) return HEAP->undefined_value();
   return holder->shared()->name();
 }
 
@@ -604,13 +611,13 @@
         if (Smi::IsValid(value)) {
           return Handle<Object>(Smi::FromInt(value));
         } else {
-          return Factory::NewNumberFromInt(value);
+          return Isolate::Current()->factory()->NewNumberFromInt(value);
         }
       }
 
       case DOUBLE: {
         double value = Memory::double_at(addr_);
-        return Factory::NewNumber(value);
+        return Isolate::Current()->factory()->NewNumber(value);
       }
 
       case LITERAL:
@@ -732,12 +739,13 @@
     JavaScriptFrame* frame,
     Handle<JSFunction> inlined_function,
     int inlined_frame_index) {
+  Factory* factory = Isolate::Current()->factory();
   int args_count = inlined_function->shared()->formal_parameter_count();
   ScopedVector<SlotRef> args_slots(args_count);
   ComputeSlotMappingForArguments(frame, inlined_frame_index, &args_slots);
   Handle<JSObject> arguments =
-      Factory::NewArgumentsObject(inlined_function, args_count);
-  Handle<FixedArray> array = Factory::NewFixedArray(args_count);
+      factory->NewArgumentsObject(inlined_function, args_count);
+  Handle<FixedArray> array = factory->NewFixedArray(args_count);
   for (int i = 0; i < args_count; ++i) {
     Handle<Object> value = args_slots[i].GetValue();
     array->set(i, *value);
@@ -750,11 +758,12 @@
 
 
 MaybeObject* Accessors::FunctionGetArguments(Object* object, void*) {
-  HandleScope scope;
+  Isolate* isolate = Isolate::Current();
+  HandleScope scope(isolate);
   bool found_it = false;
   JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
-  if (!found_it) return Heap::undefined_value();
-  Handle<JSFunction> function(holder);
+  if (!found_it) return isolate->heap()->undefined_value();
+  Handle<JSFunction> function(holder, isolate);
 
   // Find the top invocation of the function by traversing frames.
   List<JSFunction*> functions(2);
@@ -776,9 +785,9 @@
       if (!frame->is_optimized()) {
         // If there is an arguments variable in the stack, we return that.
         Handle<SerializedScopeInfo> info(function->shared()->scope_info());
-        int index = info->StackSlotIndex(Heap::arguments_symbol());
+        int index = info->StackSlotIndex(isolate->heap()->arguments_symbol());
         if (index >= 0) {
-          Handle<Object> arguments(frame->GetExpression(index));
+          Handle<Object> arguments(frame->GetExpression(index), isolate);
           if (!arguments->IsArgumentsMarker()) return *arguments;
         }
       }
@@ -791,10 +800,10 @@
 
       // 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);
+      const int length = frame->ComputeParametersCount();
+      Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject(
+          function, length);
+      Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
 
       // Copy the parameters to the arguments object.
       ASSERT(array->length() == length);
@@ -808,7 +817,7 @@
   }
 
   // No frame corresponding to the given function found. Return null.
-  return Heap::null_value();
+  return isolate->heap()->null_value();
 }
 
 
@@ -824,13 +833,27 @@
 //
 
 
+static MaybeObject* CheckNonStrictCallerOrThrow(
+    Isolate* isolate,
+    JSFunction* caller) {
+  DisableAssertNoAllocation enable_allocation;
+  if (caller->shared()->strict_mode()) {
+    return isolate->Throw(
+        *isolate->factory()->NewTypeError("strict_caller",
+                                          HandleVector<Object>(NULL, 0)));
+  }
+  return caller;
+}
+
+
 MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) {
-  HandleScope scope;
+  Isolate* isolate = Isolate::Current();
+  HandleScope scope(isolate);
   AssertNoAllocation no_alloc;
   bool found_it = false;
   JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
-  if (!found_it) return Heap::undefined_value();
-  Handle<JSFunction> function(holder);
+  if (!found_it) return isolate->heap()->undefined_value();
+  Handle<JSFunction> function(holder, isolate);
 
   List<JSFunction*> functions(2);
   for (JavaScriptFrameIterator it; !it.done(); it.Advance()) {
@@ -843,18 +866,18 @@
         // frames, e.g. frames for scripts not functions.
         if (i > 0) {
           ASSERT(!functions[i - 1]->shared()->is_toplevel());
-          return functions[i - 1];
+          return CheckNonStrictCallerOrThrow(isolate, functions[i - 1]);
         } else {
           for (it.Advance(); !it.done(); it.Advance()) {
             frame = it.frame();
             functions.Rewind(0);
             frame->GetFunctions(&functions);
             if (!functions.last()->shared()->is_toplevel()) {
-              return functions.last();
+              return CheckNonStrictCallerOrThrow(isolate, functions.last());
             }
             ASSERT(functions.length() == 1);
           }
-          if (it.done()) return Heap::null_value();
+          if (it.done()) return isolate->heap()->null_value();
           break;
         }
       }
@@ -863,7 +886,7 @@
   }
 
   // No frame corresponding to the given function found. Return null.
-  return Heap::null_value();
+  return isolate->heap()->null_value();
 }
 
 
diff --git a/test/cctest/test-mips.cc b/src/allocation-inl.h
similarity index 72%
rename from test/cctest/test-mips.cc
rename to src/allocation-inl.h
index efd4cc9..04a3fe6 100644
--- a/test/cctest/test-mips.cc
+++ b/src/allocation-inl.h
@@ -25,28 +25,25 @@
 // (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_INL_H_
+#define V8_ALLOCATION_INL_H_
 
-#include "v8.h"
-#include "execution.h"
+#include "allocation.h"
 
-#include "cctest.h"
+namespace v8 {
+namespace internal {
 
-using ::v8::Local;
-using ::v8::String;
-using ::v8::Script;
 
-namespace i = ::v8::internal;
-
-TEST(MIPSFunctionCalls) {
-  // Disable compilation of natives.
-  i::FLAG_disable_native_files = true;
-  i::FLAG_full_compiler = false;
-
-  v8::HandleScope scope;
-  LocalContext env;  // from cctest.h
-
-  const char* c_source = "function foo() { return 0x1234; }; foo();";
-  Local<String> source = ::v8::String::New(c_source);
-  Local<Script> script = ::v8::Script::Compile(source);
-  CHECK_EQ(0x1234,  script->Run()->Int32Value());
+void* PreallocatedStorage::New(size_t size) {
+  return Isolate::Current()->PreallocatedStorageNew(size);
 }
+
+
+void PreallocatedStorage::Delete(void* p) {
+  return Isolate::Current()->PreallocatedStorageDelete(p);
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_ALLOCATION_INL_H_
diff --git a/src/allocation.cc b/src/allocation.cc
index d74c37c..119b087 100644
--- a/src/allocation.cc
+++ b/src/allocation.cc
@@ -25,8 +25,6 @@
 // (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 "../include/v8stdint.h"
 #include "globals.h"
 #include "checks.h"
@@ -37,7 +35,6 @@
 namespace internal {
 
 void* Malloced::New(size_t size) {
-  ASSERT(NativeAllocationChecker::allocation_allowed());
   void* result = malloc(size);
   if (result == NULL) {
     v8::internal::FatalProcessOutOfMemory("Malloced operator new");
@@ -103,85 +100,6 @@
 }
 
 
-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;
diff --git a/src/allocation.h b/src/allocation.h
index 394366e..75aba35 100644
--- a/src/allocation.h
+++ b/src/allocation.h
@@ -39,38 +39,6 @@
 // processing.
 void FatalProcessOutOfMemory(const char* message);
 
-// 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:
@@ -114,7 +82,6 @@
 
 template <typename T>
 static T* NewArray(int size) {
-  ASSERT(NativeAllocationChecker::allocation_allowed());
   T* result = new T[size];
   if (result == NULL) Malloced::FatalProcessOutOfMemory();
   return result;
@@ -146,27 +113,27 @@
 // Allocation policy for allocating in preallocated space.
 // Used as an allocation policy for ScopeInfo when generating
 // stack traces.
-class PreallocatedStorage : public AllStatic {
+class PreallocatedStorage {
  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);
+  // TODO(isolates): Get rid of these-- we'll have to change the allocator
+  //                 interface to include a pointer to an isolate to do this
+  //                 efficiently.
+  static inline void* New(size_t size);
+  static inline void Delete(void* p);
 
  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();
+
+  friend class Isolate;
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(PreallocatedStorage);
 };
 
diff --git a/src/api.cc b/src/api.cc
index 555af84..0d5e4f0 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -44,7 +44,6 @@
 #include "runtime-profiler.h"
 #include "serialize.h"
 #include "snapshot.h"
-#include "top.h"
 #include "v8threads.h"
 #include "version.h"
 #include "vm-state-inl.h"
@@ -52,81 +51,84 @@
 #include "../include/v8-profiler.h"
 #include "../include/v8-testing.h"
 
-#define LOG_API(expr) LOG(ApiEntryCall(expr))
+#define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr))
 
+// TODO(isolates): avoid repeated TLS reads in function prologues.
 #ifdef ENABLE_VMSTATE_TRACKING
-#define ENTER_V8 ASSERT(i::V8::IsRunning()); i::VMState __state__(i::OTHER)
-#define LEAVE_V8 i::VMState __state__(i::EXTERNAL)
+#define ENTER_V8(isolate)                                        \
+  ASSERT((isolate)->IsInitialized());                           \
+  i::VMState __state__((isolate), i::OTHER)
+#define LEAVE_V8(isolate) \
+  i::VMState __state__((isolate), i::EXTERNAL)
 #else
-#define ENTER_V8 ((void) 0)
-#define LEAVE_V8 ((void) 0)
+#define ENTER_V8(isolate) ((void) 0)
+#define LEAVE_V8(isolate) ((void) 0)
 #endif
 
 namespace v8 {
 
-#define ON_BAILOUT(location, code)                                 \
-  if (IsDeadCheck(location) || v8::V8::IsExecutionTerminating()) { \
+#define ON_BAILOUT(isolate, location, code)                        \
+  if (IsDeadCheck(isolate, location) ||                            \
+      IsExecutionTerminatingCheck(isolate)) {                      \
     code;                                                          \
     UNREACHABLE();                                                 \
   }
 
 
-#define EXCEPTION_PREAMBLE()                                      \
-  thread_local.IncrementCallDepth();                              \
-  ASSERT(!i::Top::external_caught_exception());                   \
+#define EXCEPTION_PREAMBLE(isolate)                                         \
+  (isolate)->handle_scope_implementer()->IncrementCallDepth();              \
+  ASSERT(!(isolate)->external_caught_exception());                          \
   bool has_pending_exception = false
 
 
-#define EXCEPTION_BAILOUT_CHECK(value)                                         \
+#define EXCEPTION_BAILOUT_CHECK(isolate, value)                                \
   do {                                                                         \
-    thread_local.DecrementCallDepth();                                         \
+    i::HandleScopeImplementer* handle_scope_implementer =                      \
+        (isolate)->handle_scope_implementer();                                 \
+    handle_scope_implementer->DecrementCallDepth();                            \
     if (has_pending_exception) {                                               \
-      if (thread_local.CallDepthIsZero() && i::Top::is_out_of_memory()) {      \
-        if (!thread_local.ignore_out_of_memory())                              \
+      if (handle_scope_implementer->CallDepthIsZero() &&                       \
+          (isolate)->is_out_of_memory()) {                                     \
+        if (!handle_scope_implementer->ignore_out_of_memory())                 \
           i::V8::FatalProcessOutOfMemory(NULL);                                \
       }                                                                        \
-      bool call_depth_is_zero = thread_local.CallDepthIsZero();                \
-      i::Top::OptionalRescheduleException(call_depth_is_zero);                 \
+      bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero();   \
+      (isolate)->OptionalRescheduleException(call_depth_is_zero);              \
       return value;                                                            \
     }                                                                          \
   } while (false)
 
+// TODO(isolates): Add a parameter to this macro for an isolate.
 
 #define API_ENTRY_CHECK(msg)                                                   \
   do {                                                                         \
     if (v8::Locker::IsActive()) {                                              \
-      ApiCheck(i::ThreadManager::IsLockedByCurrentThread(),                    \
+      ApiCheck(i::Isolate::Current()->thread_manager()->                       \
+                  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 FatalErrorCallback exception_behavior = NULL;
-
 static void DefaultFatalErrorHandler(const char* location,
                                      const char* message) {
 #ifdef ENABLE_VMSTATE_TRACKING
-  i::VMState __state__(i::OTHER);
+  i::VMState __state__(i::Isolate::Current(), i::OTHER);
 #endif
   API_Fatal(location, message);
 }
 
 
-static FatalErrorCallback& GetFatalErrorHandler() {
-  if (exception_behavior == NULL) {
-    exception_behavior = DefaultFatalErrorHandler;
+static FatalErrorCallback GetFatalErrorHandler() {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (isolate->exception_behavior() == NULL) {
+    isolate->set_exception_behavior(DefaultFatalErrorHandler);
   }
-  return exception_behavior;
+  return isolate->exception_behavior();
 }
 
 
@@ -189,11 +191,12 @@
   heap_stats.os_error = &os_error;
   int end_marker;
   heap_stats.end_marker = &end_marker;
-  i::Heap::RecordStats(&heap_stats, take_snapshot);
+  i::Isolate* isolate = i::Isolate::Current();
+  isolate->heap()->RecordStats(&heap_stats, take_snapshot);
   i::V8::SetFatalError();
   FatalErrorCallback callback = GetFatalErrorHandler();
   {
-    LEAVE_V8;
+    LEAVE_V8(isolate);
     callback(location, "Allocation failed - process out of memory");
   }
   // If the callback returns, we stop execution.
@@ -201,11 +204,6 @@
 }
 
 
-void V8::SetFatalErrorHandler(FatalErrorCallback that) {
-  exception_behavior = that;
-}
-
-
 bool Utils::ReportApiFailure(const char* location, const char* message) {
   FatalErrorCallback callback = GetFatalErrorHandler();
   callback(location, message);
@@ -252,12 +250,22 @@
  * 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 !i::V8::IsRunning()
+static inline bool IsDeadCheck(i::Isolate* isolate, const char* location) {
+  return !isolate->IsInitialized()
       && i::V8::IsDead() ? ReportV8Dead(location) : false;
 }
 
 
+static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) {
+  if (!isolate->IsInitialized()) return false;
+  if (isolate->has_scheduled_exception()) {
+    return isolate->scheduled_exception() ==
+        isolate->heap()->termination_exception();
+  }
+  return false;
+}
+
+
 static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
   return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
 }
@@ -270,23 +278,42 @@
 // --- S t a t i c s ---
 
 
-static i::StringInputBuffer write_input_buffer;
-
-
-static inline bool EnsureInitialized(const char* location) {
-  if (i::V8::IsRunning()) {
-    return true;
-  }
-  if (IsDeadCheck(location)) {
-    return false;
-  }
-  return ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
+static bool InitializeHelper() {
+  if (i::Snapshot::Initialize()) return true;
+  return i::V8::Initialize(NULL);
 }
 
 
-ImplementationUtilities::HandleScopeData*
-    ImplementationUtilities::CurrentHandleScope() {
-  return &i::HandleScope::current_;
+static inline bool EnsureInitializedForIsolate(i::Isolate* isolate,
+                                               const char* location) {
+  if (IsDeadCheck(isolate, location)) return false;
+  if (isolate != NULL) {
+    if (isolate->IsInitialized()) return true;
+  }
+  return ApiCheck(InitializeHelper(), location, "Error initializing V8");
+}
+
+// Some initializing API functions are called early and may be
+// called on a thread different from static initializer thread.
+// If Isolate API is used, Isolate::Enter() will initialize TLS so
+// Isolate::Current() works. If it's a legacy case, then the thread
+// may not have TLS initialized yet. However, in initializing APIs it
+// may be too early to call EnsureInitialized() - some pre-init
+// parameters still have to be configured.
+static inline i::Isolate* EnterIsolateIfNeeded() {
+  i::Isolate* isolate = i::Isolate::UncheckedCurrent();
+  if (isolate != NULL)
+    return isolate;
+
+  i::Isolate::EnterDefaultIsolate();
+  isolate = i::Isolate::Current();
+  return isolate;
+}
+
+
+void V8::SetFatalErrorHandler(FatalErrorCallback that) {
+  i::Isolate* isolate = EnterIsolateIfNeeded();
+  isolate->set_exception_behavior(that);
 }
 
 
@@ -298,30 +325,6 @@
 #endif
 
 
-v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
-  if (!EnsureInitialized("v8::Undefined()")) return v8::Handle<v8::Primitive>();
-  return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
-}
-
-
-v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
-  if (!EnsureInitialized("v8::Null()")) return v8::Handle<v8::Primitive>();
-  return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
-}
-
-
-v8::Handle<v8::Boolean> ImplementationUtilities::True() {
-  if (!EnsureInitialized("v8::True()")) return v8::Handle<v8::Boolean>();
-  return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
-}
-
-
-v8::Handle<v8::Boolean> ImplementationUtilities::False() {
-  if (!EnsureInitialized("v8::False()")) return v8::Handle<v8::Boolean>();
-  return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
-}
-
-
 void V8::SetFlagsFromString(const char* str, int length) {
   i::FlagList::SetFlagsFromString(str, length);
 }
@@ -333,14 +336,17 @@
 
 
 v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
-  if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::ThrowException()")) {
+    return v8::Handle<Value>();
+  }
+  ENTER_V8(isolate);
   // 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());
+    isolate->ScheduleThrow(isolate->heap()->undefined_value());
   } else {
-    i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
+    isolate->ScheduleThrow(*Utils::OpenHandle(*value));
   }
   return v8::Undefined();
 }
@@ -354,8 +360,8 @@
 
 
 void RegisteredExtension::Register(RegisteredExtension* that) {
-  that->next_ = RegisteredExtension::first_extension_;
-  RegisteredExtension::first_extension_ = that;
+  that->next_ = first_extension_;
+  first_extension_ = that;
 }
 
 
@@ -377,26 +383,42 @@
 
 
 v8::Handle<Primitive> Undefined() {
-  LOG_API("Undefined");
-  return ImplementationUtilities::Undefined();
+  i::Isolate* isolate = i::Isolate::Current();
+  if (!EnsureInitializedForIsolate(isolate, "v8::Undefined()")) {
+    return v8::Handle<v8::Primitive>();
+  }
+  return v8::Handle<Primitive>(ToApi<Primitive>(
+      isolate->factory()->undefined_value()));
 }
 
 
 v8::Handle<Primitive> Null() {
-  LOG_API("Null");
-  return ImplementationUtilities::Null();
+  i::Isolate* isolate = i::Isolate::Current();
+  if (!EnsureInitializedForIsolate(isolate, "v8::Null()")) {
+    return v8::Handle<v8::Primitive>();
+  }
+  return v8::Handle<Primitive>(
+      ToApi<Primitive>(isolate->factory()->null_value()));
 }
 
 
 v8::Handle<Boolean> True() {
-  LOG_API("True");
-  return ImplementationUtilities::True();
+  i::Isolate* isolate = i::Isolate::Current();
+  if (!EnsureInitializedForIsolate(isolate, "v8::True()")) {
+    return v8::Handle<Boolean>();
+  }
+  return v8::Handle<Boolean>(
+      ToApi<Boolean>(isolate->factory()->true_value()));
 }
 
 
 v8::Handle<Boolean> False() {
-  LOG_API("False");
-  return ImplementationUtilities::False();
+  i::Isolate* isolate = i::Isolate::Current();
+  if (!EnsureInitializedForIsolate(isolate, "v8::False()")) {
+    return v8::Handle<Boolean>();
+  }
+  return v8::Handle<Boolean>(
+      ToApi<Boolean>(isolate->factory()->false_value()));
 }
 
 
@@ -408,74 +430,89 @@
 
 
 bool SetResourceConstraints(ResourceConstraints* constraints) {
+  i::Isolate* isolate = EnterIsolateIfNeeded();
+
   int young_space_size = constraints->max_young_space_size();
   int old_gen_size = constraints->max_old_space_size();
   int max_executable_size = constraints->max_executable_size();
   if (young_space_size != 0 || old_gen_size != 0 || max_executable_size != 0) {
-    bool result = i::Heap::ConfigureHeap(young_space_size / 2,
-                                         old_gen_size,
-                                         max_executable_size);
+    // After initialization it's too late to change Heap constraints.
+    ASSERT(!isolate->IsInitialized());
+    bool result = isolate->heap()->ConfigureHeap(young_space_size / 2,
+                                                 old_gen_size,
+                                                 max_executable_size);
     if (!result) return false;
   }
   if (constraints->stack_limit() != NULL) {
     uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
-    i::StackGuard::SetStackLimit(limit);
+    isolate->stack_guard()->SetStackLimit(limit);
   }
   return true;
 }
 
 
 i::Object** V8::GlobalizeReference(i::Object** obj) {
-  if (IsDeadCheck("V8::Persistent::New")) return NULL;
-  LOG_API("Persistent::New");
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "V8::Persistent::New")) return NULL;
+  LOG_API(isolate, "Persistent::New");
   i::Handle<i::Object> result =
-      i::GlobalHandles::Create(*obj);
+      isolate->global_handles()->Create(*obj);
   return result.location();
 }
 
 
 void V8::MakeWeak(i::Object** object, void* parameters,
                   WeakReferenceCallback callback) {
-  LOG_API("MakeWeak");
-  i::GlobalHandles::MakeWeak(object, parameters, callback);
+  i::Isolate* isolate = i::Isolate::Current();
+  LOG_API(isolate, "MakeWeak");
+  isolate->global_handles()->MakeWeak(object, parameters,
+                                                    callback);
 }
 
 
 void V8::ClearWeak(i::Object** obj) {
-  LOG_API("ClearWeak");
-  i::GlobalHandles::ClearWeakness(obj);
+  i::Isolate* isolate = i::Isolate::Current();
+  LOG_API(isolate, "ClearWeak");
+  isolate->global_handles()->ClearWeakness(obj);
 }
 
 
 bool V8::IsGlobalNearDeath(i::Object** obj) {
-  LOG_API("IsGlobalNearDeath");
-  if (!i::V8::IsRunning()) return false;
+  i::Isolate* isolate = i::Isolate::Current();
+  LOG_API(isolate, "IsGlobalNearDeath");
+  if (!isolate->IsInitialized()) return false;
   return i::GlobalHandles::IsNearDeath(obj);
 }
 
 
 bool V8::IsGlobalWeak(i::Object** obj) {
-  LOG_API("IsGlobalWeak");
-  if (!i::V8::IsRunning()) return false;
+  i::Isolate* isolate = i::Isolate::Current();
+  LOG_API(isolate, "IsGlobalWeak");
+  if (!isolate->IsInitialized()) return false;
   return i::GlobalHandles::IsWeak(obj);
 }
 
 
 void V8::DisposeGlobal(i::Object** obj) {
-  LOG_API("DisposeGlobal");
-  if (!i::V8::IsRunning()) return;
-  i::GlobalHandles::Destroy(obj);
+  i::Isolate* isolate = i::Isolate::Current();
+  LOG_API(isolate, "DisposeGlobal");
+  if (!isolate->IsInitialized()) return;
+  isolate->global_handles()->Destroy(obj);
 }
 
 // --- H a n d l e s ---
 
 
-HandleScope::HandleScope()
-    : prev_next_(i::HandleScope::current_.next),
-      prev_limit_(i::HandleScope::current_.limit),
-      is_closed_(false) {
+HandleScope::HandleScope() {
   API_ENTRY_CHECK("HandleScope::HandleScope");
-  i::HandleScope::current_.level++;
+  i::Isolate* isolate = i::Isolate::Current();
+  v8::ImplementationUtilities::HandleScopeData* current =
+      isolate->handle_scope_data();
+  isolate_ = isolate;
+  prev_next_ = current->next;
+  prev_limit_ = current->limit;
+  is_closed_ = false;
+  current->level++;
 }
 
 
@@ -487,12 +524,15 @@
 
 
 void HandleScope::Leave() {
-  i::HandleScope::current_.level--;
-  ASSERT(i::HandleScope::current_.level >= 0);
-  i::HandleScope::current_.next = prev_next_;
-  if (i::HandleScope::current_.limit != prev_limit_) {
-    i::HandleScope::current_.limit = prev_limit_;
-    i::HandleScope::DeleteExtensions();
+  ASSERT(isolate_ == i::Isolate::Current());
+  v8::ImplementationUtilities::HandleScopeData* current =
+      isolate_->handle_scope_data();
+  current->level--;
+  ASSERT(current->level >= 0);
+  current->next = prev_next_;
+  if (current->limit != prev_limit_) {
+    current->limit = prev_limit_;
+    i::HandleScope::DeleteExtensions(isolate_);
   }
 
 #ifdef DEBUG
@@ -502,45 +542,63 @@
 
 
 int HandleScope::NumberOfHandles() {
+  EnsureInitializedForIsolate(
+      i::Isolate::Current(), "HandleScope::NumberOfHandles");
   return i::HandleScope::NumberOfHandles();
 }
 
 
-i::Object** v8::HandleScope::CreateHandle(i::Object* value) {
-  return i::HandleScope::CreateHandle(value);
+i::Object** HandleScope::CreateHandle(i::Object* value) {
+  return i::HandleScope::CreateHandle(value, i::Isolate::Current());
+}
+
+
+i::Object** HandleScope::CreateHandle(i::HeapObject* value) {
+  ASSERT(value->IsHeapObject());
+  return reinterpret_cast<i::Object**>(
+      i::HandleScope::CreateHandle(value, value->GetIsolate()));
 }
 
 
 void Context::Enter() {
-  if (IsDeadCheck("v8::Context::Enter()")) return;
-  ENTER_V8;
-  i::Handle<i::Context> env = Utils::OpenHandle(this);
-  thread_local.EnterContext(env);
+  // TODO(isolates): Context should have a pointer to isolate.
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Context::Enter()")) return;
+  ENTER_V8(isolate);
 
-  thread_local.SaveContext(i::Top::context());
-  i::Top::set_context(*env);
+  i::Handle<i::Context> env = Utils::OpenHandle(this);
+  isolate->handle_scope_implementer()->EnterContext(env);
+
+  isolate->handle_scope_implementer()->SaveContext(isolate->context());
+  isolate->set_context(*env);
 }
 
 
 void Context::Exit() {
-  if (!i::V8::IsRunning()) return;
-  if (!ApiCheck(thread_local.LeaveLastContext(),
+  // TODO(isolates): Context should have a pointer to isolate.
+  i::Isolate* isolate = i::Isolate::Current();
+  if (!isolate->IsInitialized()) return;
+
+  if (!ApiCheck(isolate->handle_scope_implementer()->LeaveLastContext(),
                 "v8::Context::Exit()",
                 "Cannot exit non-entered context")) {
     return;
   }
 
   // Content of 'last_context' could be NULL.
-  i::Context* last_context = thread_local.RestoreContext();
-  i::Top::set_context(last_context);
+  i::Context* last_context =
+      isolate->handle_scope_implementer()->RestoreContext();
+  isolate->set_context(last_context);
 }
 
 
 void Context::SetData(v8::Handle<String> data) {
-  if (IsDeadCheck("v8::Context::SetData()")) return;
-  ENTER_V8;
+  // TODO(isolates): Context should have a pointer to isolate.
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Context::SetData()")) return;
+  ENTER_V8(isolate);
   {
-    HandleScope scope;
+    i::HandleScope scope(isolate);
     i::Handle<i::Context> env = Utils::OpenHandle(this);
     i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
     ASSERT(env->IsGlobalContext());
@@ -552,11 +610,15 @@
 
 
 v8::Local<v8::Value> Context::GetData() {
-  if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
-  ENTER_V8;
+  // TODO(isolates): Context should have a pointer to isolate.
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Context::GetData()")) {
+    return v8::Local<Value>();
+  }
+  ENTER_V8(isolate);
   i::Object* raw_result = NULL;
   {
-    HandleScope scope;
+    i::HandleScope scope(isolate);
     i::Handle<i::Context> env = Utils::OpenHandle(this);
     ASSERT(env->IsGlobalContext());
     if (env->IsGlobalContext()) {
@@ -576,7 +638,7 @@
                 "Local scope has already been closed")) {
     return 0;
   }
-  LOG_API("CloseHandleScope");
+  LOG_API(isolate_, "CloseHandleScope");
 
   // Read the result before popping the handle block.
   i::Object* result = NULL;
@@ -605,10 +667,11 @@
 // 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);
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::Nowhere");
+  ENTER_V8(isolate);
+  value_ = isolate->factory()->NewNeanderObject();
+  i::Handle<i::FixedArray> elements = isolate->factory()->NewFixedArray(size);
   value_->set_elements(*elements);
 }
 
@@ -644,7 +707,7 @@
   int length = this->length();
   int size = obj_.size();
   if (length == size - 1) {
-    i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
+    i::Handle<i::FixedArray> new_elms = FACTORY->NewFixedArray(2 * size);
     for (int i = 0; i < length; i++)
       new_elms->set(i + 1, get(i));
     obj_.value()->set_elements(*new_elms);
@@ -670,9 +733,10 @@
 
 void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
                    v8::PropertyAttribute attribute) {
-  if (IsDeadCheck("v8::Template::Set()")) return;
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Template::Set()")) return;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
   if (list->IsUndefined()) {
     list = NeanderArray().value();
@@ -694,10 +758,11 @@
 
 
 Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
-  if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::FunctionTemplate::PrototypeTemplate()")) {
     return Local<ObjectTemplate>();
   }
-  ENTER_V8;
+  ENTER_V8(isolate);
   i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
   if (result->IsUndefined()) {
     result = Utils::OpenHandle(*ObjectTemplate::New());
@@ -708,28 +773,27 @@
 
 
 void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
-  if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::FunctionTemplate::Inherit()")) return;
+  ENTER_V8(isolate);
   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::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::FunctionTemplate::New()");
+  LOG_API(isolate, "FunctionTemplate::New");
+  ENTER_V8(isolate);
   i::Handle<i::Struct> struct_obj =
-      i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
+      isolate->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++));
+  int next_serial_number = isolate->next_serial_number();
+  isolate->set_next_serial_number(next_serial_number + 1);
+  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);
@@ -745,16 +809,17 @@
 
 Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
       int argc, Handle<FunctionTemplate> argv[]) {
-  EnsureInitialized("v8::Signature::New()");
-  LOG_API("Signature::New");
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::Signature::New()");
+  LOG_API(isolate, "Signature::New");
+  ENTER_V8(isolate);
   i::Handle<i::Struct> struct_obj =
-      i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
+      isolate->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);
+    i::Handle<i::FixedArray> args = isolate->factory()->NewFixedArray(argc);
     for (int i = 0; i < argc; i++) {
       if (!argv[i].IsEmpty())
         args->set(i, *Utils::OpenHandle(*argv[i]));
@@ -772,14 +837,15 @@
 
 
 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);
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::TypeSwitch::New()");
+  LOG_API(isolate, "TypeSwitch::New");
+  ENTER_V8(isolate);
+  i::Handle<i::FixedArray> vector = isolate->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);
+      isolate->factory()->NewStruct(i::TYPE_SWITCH_INFO_TYPE);
   i::Handle<i::TypeSwitchInfo> obj =
       i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
   obj->set_types(*vector);
@@ -788,7 +854,8 @@
 
 
 int TypeSwitch::match(v8::Handle<Value> value) {
-  LOG_API("TypeSwitch::match");
+  i::Isolate* isolate = i::Isolate::Current();
+  LOG_API(isolate, "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());
@@ -808,11 +875,12 @@
 
 void FunctionTemplate::SetCallHandler(InvocationCallback callback,
                                       v8::Handle<Value> data) {
-  if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::FunctionTemplate::SetCallHandler()")) return;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::Struct> struct_obj =
-      i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
+      isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
   i::Handle<i::CallHandlerInfo> obj =
       i::Handle<i::CallHandlerInfo>::cast(struct_obj);
   SET_FIELD_WRAPPED(obj, set_callback, callback);
@@ -829,7 +897,7 @@
       v8::Handle<Value> data,
       v8::AccessControl settings,
       v8::PropertyAttribute attributes) {
-  i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
+  i::Handle<i::AccessorInfo> obj = FACTORY->NewAccessorInfo();
   ASSERT(getter != NULL);
   SET_FIELD_WRAPPED(obj, set_getter, getter);
   SET_FIELD_WRAPPED(obj, set_setter, setter);
@@ -851,11 +919,13 @@
       v8::Handle<Value> data,
       v8::AccessControl settings,
       v8::PropertyAttribute attributes) {
-  if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate,
+                  "v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
     return;
   }
-  ENTER_V8;
-  HandleScope scope;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
 
   i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(name,
                                                     getter, setter, data,
@@ -871,10 +941,11 @@
 
 
 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
-  if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::FunctionTemplate::InstanceTemplate()")
       || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
     return Local<ObjectTemplate>();
-  ENTER_V8;
+  ENTER_V8(isolate);
   if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
     Local<ObjectTemplate> templ =
         ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
@@ -887,15 +958,19 @@
 
 
 void FunctionTemplate::SetClassName(Handle<String> name) {
-  if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::FunctionTemplate::SetClassName()")) return;
+  ENTER_V8(isolate);
   Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
 }
 
 
 void FunctionTemplate::SetHiddenPrototype(bool value) {
-  if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::FunctionTemplate::SetHiddenPrototype()")) {
+    return;
+  }
+  ENTER_V8(isolate);
   Utils::OpenHandle(this)->set_hidden_prototype(value);
 }
 
@@ -907,13 +982,15 @@
       NamedPropertyDeleter remover,
       NamedPropertyEnumerator enumerator,
       Handle<Value> data) {
-  if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate,
+                  "v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
     return;
   }
-  ENTER_V8;
-  HandleScope scope;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::Struct> struct_obj =
-      i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
+      isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
   i::Handle<i::InterceptorInfo> obj =
       i::Handle<i::InterceptorInfo>::cast(struct_obj);
 
@@ -936,14 +1013,15 @@
       IndexedPropertyDeleter remover,
       IndexedPropertyEnumerator enumerator,
       Handle<Value> data) {
-  if (IsDeadCheck(
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate,
         "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
     return;
   }
-  ENTER_V8;
-  HandleScope scope;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::Struct> struct_obj =
-      i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
+      isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
   i::Handle<i::InterceptorInfo> obj =
       i::Handle<i::InterceptorInfo>::cast(struct_obj);
 
@@ -962,13 +1040,15 @@
 void FunctionTemplate::SetInstanceCallAsFunctionHandler(
       InvocationCallback callback,
       Handle<Value> data) {
-  if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate,
+                  "v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
     return;
   }
-  ENTER_V8;
-  HandleScope scope;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::Struct> struct_obj =
-      i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
+      isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
   i::Handle<i::CallHandlerInfo> obj =
       i::Handle<i::CallHandlerInfo>::cast(struct_obj);
   SET_FIELD_WRAPPED(obj, set_callback, callback);
@@ -988,12 +1068,15 @@
 
 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::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::ObjectTemplate::New()")) {
+    return Local<ObjectTemplate>();
+  }
+  EnsureInitializedForIsolate(isolate, "v8::ObjectTemplate::New()");
+  LOG_API(isolate, "ObjectTemplate::New");
+  ENTER_V8(isolate);
   i::Handle<i::Struct> struct_obj =
-      i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
+      isolate->factory()->NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
   i::Handle<i::ObjectTemplateInfo> obj =
       i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
   InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
@@ -1022,9 +1105,10 @@
                                  v8::Handle<Value> data,
                                  AccessControl settings,
                                  PropertyAttribute attribute) {
-  if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetAccessor()")) return;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   EnsureConstructor(this);
   i::FunctionTemplateInfo* constructor =
       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
@@ -1044,9 +1128,12 @@
                                              NamedPropertyDeleter remover,
                                              NamedPropertyEnumerator enumerator,
                                              Handle<Value> data) {
-  if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetNamedPropertyHandler()")) {
+    return;
+  }
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   EnsureConstructor(this);
   i::FunctionTemplateInfo* constructor =
       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
@@ -1061,9 +1148,10 @@
 
 
 void ObjectTemplate::MarkAsUndetectable() {
-  if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::ObjectTemplate::MarkAsUndetectable()")) return;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   EnsureConstructor(this);
   i::FunctionTemplateInfo* constructor =
       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
@@ -1077,13 +1165,16 @@
       IndexedSecurityCallback indexed_callback,
       Handle<Value> data,
       bool turned_on_by_default) {
-  if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetAccessCheckCallbacks()")) {
+    return;
+  }
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   EnsureConstructor(this);
 
   i::Handle<i::Struct> struct_info =
-      i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
+      isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE);
   i::Handle<i::AccessCheckInfo> info =
       i::Handle<i::AccessCheckInfo>::cast(struct_info);
 
@@ -1108,9 +1199,12 @@
       IndexedPropertyDeleter remover,
       IndexedPropertyEnumerator enumerator,
       Handle<Value> data) {
-  if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetIndexedPropertyHandler()")) {
+    return;
+  }
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   EnsureConstructor(this);
   i::FunctionTemplateInfo* constructor =
       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
@@ -1126,9 +1220,13 @@
 
 void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
                                               Handle<Value> data) {
-  if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate,
+                  "v8::ObjectTemplate::SetCallAsFunctionHandler()")) {
+    return;
+  }
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   EnsureConstructor(this);
   i::FunctionTemplateInfo* constructor =
       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
@@ -1138,7 +1236,8 @@
 
 
 int ObjectTemplate::InternalFieldCount() {
-  if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
+  if (IsDeadCheck(Utils::OpenHandle(this)->GetIsolate(),
+                  "v8::ObjectTemplate::InternalFieldCount()")) {
     return 0;
   }
   return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
@@ -1146,13 +1245,16 @@
 
 
 void ObjectTemplate::SetInternalFieldCount(int value) {
-  if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetInternalFieldCount()")) {
+    return;
+  }
   if (!ApiCheck(i::Smi::IsValid(value),
                 "v8::ObjectTemplate::SetInternalFieldCount()",
                 "Invalid internal field count")) {
     return;
   }
-  ENTER_V8;
+  ENTER_V8(isolate);
   if (value > 0) {
     // The internal field count is set by the constructor function's
     // construct code, so we ensure that there is a constructor
@@ -1214,9 +1316,10 @@
                           v8::ScriptOrigin* origin,
                           v8::ScriptData* pre_data,
                           v8::Handle<String> script_data) {
-  ON_BAILOUT("v8::Script::New()", return Local<Script>());
-  LOG_API("Script::New");
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  ON_BAILOUT(isolate, "v8::Script::New()", return Local<Script>());
+  LOG_API(isolate, "Script::New");
+  ENTER_V8(isolate);
   i::Handle<i::String> str = Utils::OpenHandle(*source);
   i::Handle<i::Object> name_obj;
   int line_offset = 0;
@@ -1232,7 +1335,7 @@
       column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
     }
   }
-  EXCEPTION_PREAMBLE();
+  EXCEPTION_PREAMBLE(isolate);
   i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_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.
@@ -1251,7 +1354,7 @@
                            Utils::OpenHandle(*script_data),
                            i::NOT_NATIVES_CODE);
   has_pending_exception = result.is_null();
-  EXCEPTION_BAILOUT_CHECK(Local<Script>());
+  EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>());
   return Local<Script>(ToApi<Script>(result));
 }
 
@@ -1267,9 +1370,10 @@
                               v8::ScriptOrigin* origin,
                               v8::ScriptData* pre_data,
                               v8::Handle<String> script_data) {
-  ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
-  LOG_API("Script::Compile");
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  ON_BAILOUT(isolate, "v8::Script::Compile()", return Local<Script>());
+  LOG_API(isolate, "Script::Compile");
+  ENTER_V8(isolate);
   Local<Script> generic = New(source, origin, pre_data, script_data);
   if (generic.IsEmpty())
     return generic;
@@ -1277,8 +1381,9 @@
   i::Handle<i::SharedFunctionInfo> function =
       i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
   i::Handle<i::JSFunction> result =
-      i::Factory::NewFunctionFromSharedFunctionInfo(function,
-                                                    i::Top::global_context());
+      isolate->factory()->NewFunctionFromSharedFunctionInfo(
+          function,
+          isolate->global_context());
   return Local<Script>(ToApi<Script>(result));
 }
 
@@ -1292,30 +1397,32 @@
 
 
 Local<Value> Script::Run() {
-  ON_BAILOUT("v8::Script::Run()", return Local<Value>());
-  LOG_API("Script::Run");
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>());
+  LOG_API(isolate, "Script::Run");
+  ENTER_V8(isolate);
   i::Object* raw_result = NULL;
   {
-    HandleScope scope;
+    i::HandleScope scope(isolate);
     i::Handle<i::Object> obj = Utils::OpenHandle(this);
     i::Handle<i::JSFunction> fun;
     if (obj->IsSharedFunctionInfo()) {
       i::Handle<i::SharedFunctionInfo>
-          function_info(i::SharedFunctionInfo::cast(*obj));
-      fun = i::Factory::NewFunctionFromSharedFunctionInfo(
-          function_info, i::Top::global_context());
+          function_info(i::SharedFunctionInfo::cast(*obj), isolate);
+      fun = isolate->factory()->NewFunctionFromSharedFunctionInfo(
+          function_info, isolate->global_context());
     } else {
-      fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj));
+      fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj), isolate);
     }
-    EXCEPTION_PREAMBLE();
-    i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
+    EXCEPTION_PREAMBLE(isolate);
+    i::Handle<i::Object> receiver(
+        isolate->context()->global_proxy(), isolate);
     i::Handle<i::Object> result =
         i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(Local<Value>());
+    EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
     raw_result = *result;
   }
-  i::Handle<i::Object> result(raw_result);
+  i::Handle<i::Object> result(raw_result, isolate);
   return Utils::ToLocal(result);
 }
 
@@ -1335,11 +1442,12 @@
 
 
 Local<Value> Script::Id() {
-  ON_BAILOUT("v8::Script::Id()", return Local<Value>());
-  LOG_API("Script::Id");
+  i::Isolate* isolate = i::Isolate::Current();
+  ON_BAILOUT(isolate, "v8::Script::Id()", return Local<Value>());
+  LOG_API(isolate, "Script::Id");
   i::Object* raw_id = NULL;
   {
-    HandleScope scope;
+    i::HandleScope scope(isolate);
     i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
     i::Handle<i::Script> script(i::Script::cast(function_info->script()));
     i::Handle<i::Object> id(script->id());
@@ -1351,10 +1459,11 @@
 
 
 void Script::SetData(v8::Handle<String> data) {
-  ON_BAILOUT("v8::Script::SetData()", return);
-  LOG_API("Script::SetData");
+  i::Isolate* isolate = i::Isolate::Current();
+  ON_BAILOUT(isolate, "v8::Script::SetData()", return);
+  LOG_API(isolate, "Script::SetData");
   {
-    HandleScope scope;
+    i::HandleScope scope(isolate);
     i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
     i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
     i::Handle<i::Script> script(i::Script::cast(function_info->script()));
@@ -1367,25 +1476,26 @@
 
 
 v8::TryCatch::TryCatch()
-    : next_(i::Top::try_catch_handler_address()),
-      exception_(i::Heap::the_hole_value()),
+    : next_(i::Isolate::Current()->try_catch_handler_address()),
+      exception_(HEAP->the_hole_value()),
       message_(i::Smi::FromInt(0)),
       is_verbose_(false),
       can_continue_(true),
       capture_message_(true),
       rethrow_(false) {
-  i::Top::RegisterTryCatchHandler(this);
+  i::Isolate::Current()->RegisterTryCatchHandler(this);
 }
 
 
 v8::TryCatch::~TryCatch() {
+  i::Isolate* isolate = i::Isolate::Current();
   if (rethrow_) {
     v8::HandleScope scope;
     v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
-    i::Top::UnregisterTryCatchHandler(this);
+    isolate->UnregisterTryCatchHandler(this);
     v8::ThrowException(exc);
   } else {
-    i::Top::UnregisterTryCatchHandler(this);
+    isolate->UnregisterTryCatchHandler(this);
   }
 }
 
@@ -1424,7 +1534,7 @@
     if (!raw_obj->IsJSObject()) return v8::Local<Value>();
     v8::HandleScope scope;
     i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
-    i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
+    i::Handle<i::String> name = FACTORY->LookupAsciiSymbol("stack");
     if (!obj->HasProperty(*name))
       return v8::Local<Value>();
     return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
@@ -1445,7 +1555,7 @@
 
 
 void v8::TryCatch::Reset() {
-  exception_ = i::Heap::the_hole_value();
+  exception_ = HEAP->the_hole_value();
   message_ = i::Smi::FromInt(0);
 }
 
@@ -1464,8 +1574,9 @@
 
 
 Local<String> Message::Get() const {
-  ON_BAILOUT("v8::Message::Get()", return Local<String>());
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Message::Get()", return Local<String>());
+  ENTER_V8(isolate);
   HandleScope scope;
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
@@ -1475,10 +1586,11 @@
 
 
 v8::Handle<Value> Message::GetScriptResourceName() const {
-  if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::Message::GetScriptResourceName()")) {
     return Local<String>();
   }
-  ENTER_V8;
+  ENTER_V8(isolate);
   HandleScope scope;
   i::Handle<i::JSMessageObject> message =
       i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
@@ -1491,10 +1603,11 @@
 
 
 v8::Handle<Value> Message::GetScriptData() const {
-  if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::Message::GetScriptResourceData()")) {
     return Local<Value>();
   }
-  ENTER_V8;
+  ENTER_V8(isolate);
   HandleScope scope;
   i::Handle<i::JSMessageObject> message =
       i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
@@ -1507,10 +1620,11 @@
 
 
 v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
-  if (IsDeadCheck("v8::Message::GetStackTrace()")) {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::Message::GetStackTrace()")) {
     return Local<v8::StackTrace>();
   }
-  ENTER_V8;
+  ENTER_V8(isolate);
   HandleScope scope;
   i::Handle<i::JSMessageObject> message =
       i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
@@ -1527,9 +1641,10 @@
                                                int argc,
                                                i::Object** argv[],
                                                bool* has_pending_exception) {
-  i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
+  i::Isolate* isolate = i::Isolate::Current();
+  i::Handle<i::String> fmt_str = isolate->factory()->LookupAsciiSymbol(name);
   i::Object* object_fun =
-      i::Top::builtins()->GetPropertyNoExceptionThrown(*fmt_str);
+      isolate->js_builtins_object()->GetPropertyNoExceptionThrown(*fmt_str);
   i::Handle<i::JSFunction> fun =
       i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
   i::Handle<i::Object> value =
@@ -1543,7 +1658,7 @@
                                                bool* has_pending_exception) {
   i::Object** argv[1] = { data.location() };
   return CallV8HeapFunction(name,
-                            i::Top::builtins(),
+                            i::Isolate::Current()->js_builtins_object(),
                             1,
                             argv,
                             has_pending_exception);
@@ -1551,23 +1666,25 @@
 
 
 int Message::GetLineNumber() const {
-  ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Message::GetLineNumber()", return kNoLineNumberInfo);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
 
-  EXCEPTION_PREAMBLE();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
                                                    Utils::OpenHandle(this),
                                                    &has_pending_exception);
-  EXCEPTION_BAILOUT_CHECK(0);
+  EXCEPTION_BAILOUT_CHECK(isolate, 0);
   return static_cast<int>(result->Number());
 }
 
 
 int Message::GetStartPosition() const {
-  if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::Message::GetStartPosition()")) return 0;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSMessageObject> message =
       i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
   return message->start_position();
@@ -1575,9 +1692,10 @@
 
 
 int Message::GetEndPosition() const {
-  if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::Message::GetEndPosition()")) return 0;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSMessageObject> message =
       i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
   return message->end_position();
@@ -1585,31 +1703,35 @@
 
 
 int Message::GetStartColumn() const {
-  if (IsDeadCheck("v8::Message::GetStartColumn()")) return kNoColumnInfo;
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::Message::GetStartColumn()")) {
+    return kNoColumnInfo;
+  }
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
-  EXCEPTION_PREAMBLE();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
       "GetPositionInLine",
       data_obj,
       &has_pending_exception);
-  EXCEPTION_BAILOUT_CHECK(0);
+  EXCEPTION_BAILOUT_CHECK(isolate, 0);
   return static_cast<int>(start_col_obj->Number());
 }
 
 
 int Message::GetEndColumn() const {
-  if (IsDeadCheck("v8::Message::GetEndColumn()")) return kNoColumnInfo;
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::Message::GetEndColumn()")) return kNoColumnInfo;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
-  EXCEPTION_PREAMBLE();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
       "GetPositionInLine",
       data_obj,
       &has_pending_exception);
-  EXCEPTION_BAILOUT_CHECK(0);
+  EXCEPTION_BAILOUT_CHECK(isolate, 0);
   i::Handle<i::JSMessageObject> message =
       i::Handle<i::JSMessageObject>::cast(data_obj);
   int start = message->start_position();
@@ -1619,14 +1741,15 @@
 
 
 Local<String> Message::GetSourceLine() const {
-  ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Message::GetSourceLine()", return Local<String>());
+  ENTER_V8(isolate);
   HandleScope scope;
-  EXCEPTION_PREAMBLE();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
                                                    Utils::OpenHandle(this),
                                                    &has_pending_exception);
-  EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
+  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::String>());
   if (result->IsString()) {
     return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
   } else {
@@ -1636,17 +1759,21 @@
 
 
 void Message::PrintCurrentStackTrace(FILE* out) {
-  if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
-  ENTER_V8;
-  i::Top::PrintCurrentStackTrace(out);
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Message::PrintCurrentStackTrace()")) return;
+  ENTER_V8(isolate);
+  isolate->PrintCurrentStackTrace(out);
 }
 
 
 // --- S t a c k T r a c e ---
 
 Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
-  if (IsDeadCheck("v8::StackTrace::GetFrame()")) return Local<StackFrame>();
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::StackTrace::GetFrame()")) {
+    return Local<StackFrame>();
+  }
+  ENTER_V8(isolate);
   HandleScope scope;
   i::Handle<i::JSArray> self = Utils::OpenHandle(this);
   i::Object* raw_object = self->GetElementNoExceptionThrown(index);
@@ -1656,25 +1783,30 @@
 
 
 int StackTrace::GetFrameCount() const {
-  if (IsDeadCheck("v8::StackTrace::GetFrameCount()")) return -1;
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::StackTrace::GetFrameCount()")) return -1;
+  ENTER_V8(isolate);
   return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
 }
 
 
 Local<Array> StackTrace::AsArray() {
-  if (IsDeadCheck("v8::StackTrace::AsArray()")) Local<Array>();
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::StackTrace::AsArray()")) Local<Array>();
+  ENTER_V8(isolate);
   return Utils::ToLocal(Utils::OpenHandle(this));
 }
 
 
 Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
     StackTraceOptions options) {
-  if (IsDeadCheck("v8::StackTrace::CurrentStackTrace()")) Local<StackTrace>();
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::StackTrace::CurrentStackTrace()")) {
+    Local<StackTrace>();
+  }
+  ENTER_V8(isolate);
   i::Handle<i::JSArray> stackTrace =
-      i::Top::CaptureCurrentStackTrace(frame_limit, options);
+      isolate->CaptureCurrentStackTrace(frame_limit, options);
   return Utils::StackTraceToLocal(stackTrace);
 }
 
@@ -1682,11 +1814,12 @@
 // --- S t a c k F r a m e ---
 
 int StackFrame::GetLineNumber() const {
-  if (IsDeadCheck("v8::StackFrame::GetLineNumber()")) {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::StackFrame::GetLineNumber()")) {
     return Message::kNoLineNumberInfo;
   }
-  ENTER_V8;
-  i::HandleScope scope;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::Object> line = GetProperty(self, "lineNumber");
   if (!line->IsSmi()) {
@@ -1697,11 +1830,12 @@
 
 
 int StackFrame::GetColumn() const {
-  if (IsDeadCheck("v8::StackFrame::GetColumn()")) {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::StackFrame::GetColumn()")) {
     return Message::kNoColumnInfo;
   }
-  ENTER_V8;
-  i::HandleScope scope;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::Object> column = GetProperty(self, "column");
   if (!column->IsSmi()) {
@@ -1712,8 +1846,11 @@
 
 
 Local<String> StackFrame::GetScriptName() const {
-  if (IsDeadCheck("v8::StackFrame::GetScriptName()")) return Local<String>();
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::StackFrame::GetScriptName()")) {
+    return Local<String>();
+  }
+  ENTER_V8(isolate);
   HandleScope scope;
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::Object> name = GetProperty(self, "scriptName");
@@ -1725,10 +1862,11 @@
 
 
 Local<String> StackFrame::GetScriptNameOrSourceURL() const {
-  if (IsDeadCheck("v8::StackFrame::GetScriptNameOrSourceURL()")) {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::StackFrame::GetScriptNameOrSourceURL()")) {
     return Local<String>();
   }
-  ENTER_V8;
+  ENTER_V8(isolate);
   HandleScope scope;
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::Object> name = GetProperty(self, "scriptNameOrSourceURL");
@@ -1740,8 +1878,11 @@
 
 
 Local<String> StackFrame::GetFunctionName() const {
-  if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::StackFrame::GetFunctionName()")) {
+    return Local<String>();
+  }
+  ENTER_V8(isolate);
   HandleScope scope;
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::Object> name = GetProperty(self, "functionName");
@@ -1753,9 +1894,10 @@
 
 
 bool StackFrame::IsEval() const {
-  if (IsDeadCheck("v8::StackFrame::IsEval()")) return false;
-  ENTER_V8;
-  i::HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::StackFrame::IsEval()")) return false;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::Object> is_eval = GetProperty(self, "isEval");
   return is_eval->IsTrue();
@@ -1763,9 +1905,10 @@
 
 
 bool StackFrame::IsConstructor() const {
-  if (IsDeadCheck("v8::StackFrame::IsConstructor()")) return false;
-  ENTER_V8;
-  i::HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::StackFrame::IsConstructor()")) return false;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor");
   return is_constructor->IsTrue();
@@ -1775,37 +1918,41 @@
 // --- D a t a ---
 
 bool Value::IsUndefined() const {
-  if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsUndefined()")) {
+    return false;
+  }
   return Utils::OpenHandle(this)->IsUndefined();
 }
 
 
 bool Value::IsNull() const {
-  if (IsDeadCheck("v8::Value::IsNull()")) return false;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsNull()")) return false;
   return Utils::OpenHandle(this)->IsNull();
 }
 
 
 bool Value::IsTrue() const {
-  if (IsDeadCheck("v8::Value::IsTrue()")) return false;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsTrue()")) return false;
   return Utils::OpenHandle(this)->IsTrue();
 }
 
 
 bool Value::IsFalse() const {
-  if (IsDeadCheck("v8::Value::IsFalse()")) return false;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsFalse()")) return false;
   return Utils::OpenHandle(this)->IsFalse();
 }
 
 
 bool Value::IsFunction() const {
-  if (IsDeadCheck("v8::Value::IsFunction()")) return false;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsFunction()")) {
+    return false;
+  }
   return Utils::OpenHandle(this)->IsJSFunction();
 }
 
 
 bool Value::FullIsString() const {
-  if (IsDeadCheck("v8::Value::IsString()")) return false;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsString()")) return false;
   bool result = Utils::OpenHandle(this)->IsString();
   ASSERT_EQ(result, QuickIsString());
   return result;
@@ -1813,37 +1960,41 @@
 
 
 bool Value::IsArray() const {
-  if (IsDeadCheck("v8::Value::IsArray()")) return false;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsArray()")) return false;
   return Utils::OpenHandle(this)->IsJSArray();
 }
 
 
 bool Value::IsObject() const {
-  if (IsDeadCheck("v8::Value::IsObject()")) return false;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsObject()")) return false;
   return Utils::OpenHandle(this)->IsJSObject();
 }
 
 
 bool Value::IsNumber() const {
-  if (IsDeadCheck("v8::Value::IsNumber()")) return false;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsNumber()")) return false;
   return Utils::OpenHandle(this)->IsNumber();
 }
 
 
 bool Value::IsBoolean() const {
-  if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsBoolean()")) {
+    return false;
+  }
   return Utils::OpenHandle(this)->IsBoolean();
 }
 
 
 bool Value::IsExternal() const {
-  if (IsDeadCheck("v8::Value::IsExternal()")) return false;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsExternal()")) {
+    return false;
+  }
   return Utils::OpenHandle(this)->IsProxy();
 }
 
 
 bool Value::IsInt32() const {
-  if (IsDeadCheck("v8::Value::IsInt32()")) return false;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsInt32()")) return false;
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   if (obj->IsSmi()) return true;
   if (obj->IsNumber()) {
@@ -1855,7 +2006,7 @@
 
 
 bool Value::IsUint32() const {
-  if (IsDeadCheck("v8::Value::IsUint32()")) return false;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsUint32()")) return false;
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
   if (obj->IsNumber()) {
@@ -1867,78 +2018,91 @@
 
 
 bool Value::IsDate() const {
-  if (IsDeadCheck("v8::Value::IsDate()")) return false;
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Value::IsDate()")) return false;
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
-  return obj->HasSpecificClassOf(i::Heap::Date_symbol());
+  return obj->HasSpecificClassOf(isolate->heap()->Date_symbol());
 }
 
 
 bool Value::IsRegExp() const {
-  if (IsDeadCheck("v8::Value::IsRegExp()")) return false;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsRegExp()")) return false;
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   return obj->IsJSRegExp();
 }
 
 
 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();
+    i::Isolate* isolate = i::Isolate::Current();
+    if (IsDeadCheck(isolate, "v8::Value::ToString()")) {
+      return Local<String>();
+    }
+    LOG_API(isolate, "ToString");
+    ENTER_V8(isolate);
+    EXCEPTION_PREAMBLE(isolate);
     str = i::Execution::ToString(obj, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(Local<String>());
+    EXCEPTION_BAILOUT_CHECK(isolate, 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();
+    i::Isolate* isolate = i::Isolate::Current();
+    if (IsDeadCheck(isolate, "v8::Value::ToDetailString()")) {
+      return Local<String>();
+    }
+    LOG_API(isolate, "ToDetailString");
+    ENTER_V8(isolate);
+    EXCEPTION_PREAMBLE(isolate);
     str = i::Execution::ToDetailString(obj, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(Local<String>());
+    EXCEPTION_BAILOUT_CHECK(isolate, 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();
+    i::Isolate* isolate = i::Isolate::Current();
+    if (IsDeadCheck(isolate, "v8::Value::ToObject()")) {
+      return Local<v8::Object>();
+    }
+    LOG_API(isolate, "ToObject");
+    ENTER_V8(isolate);
+    EXCEPTION_PREAMBLE(isolate);
     val = i::Execution::ToObject(obj, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
+    EXCEPTION_BAILOUT_CHECK(isolate, 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::Isolate* isolate = i::Isolate::Current();
+    if (IsDeadCheck(isolate, "v8::Value::ToBoolean()")) {
+      return Local<Boolean>();
+    }
+    LOG_API(isolate, "ToBoolean");
+    ENTER_V8(isolate);
     i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
     return Local<Boolean>(ToApi<Boolean>(val));
   }
@@ -1946,41 +2110,45 @@
 
 
 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();
+    i::Isolate* isolate = i::Isolate::Current();
+    if (IsDeadCheck(isolate, "v8::Value::ToNumber()")) {
+      return Local<Number>();
+    }
+    LOG_API(isolate, "ToNumber");
+    ENTER_V8(isolate);
+    EXCEPTION_PREAMBLE(isolate);
     num = i::Execution::ToNumber(obj, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(Local<Number>());
+    EXCEPTION_BAILOUT_CHECK(isolate, 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();
+    i::Isolate* isolate = i::Isolate::Current();
+    if (IsDeadCheck(isolate, "v8::Value::ToInteger()")) return Local<Integer>();
+    LOG_API(isolate, "ToInteger");
+    ENTER_V8(isolate);
+    EXCEPTION_PREAMBLE(isolate);
     num = i::Execution::ToInteger(obj, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(Local<Integer>());
+    EXCEPTION_BAILOUT_CHECK(isolate, Local<Integer>());
   }
   return Local<Integer>(ToApi<Integer>(num));
 }
 
 
 void External::CheckCast(v8::Value* that) {
-  if (IsDeadCheck("v8::External::Cast()")) return;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::External::Cast()")) return;
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   ApiCheck(obj->IsProxy(),
            "v8::External::Cast()",
@@ -1989,7 +2157,7 @@
 
 
 void v8::Object::CheckCast(Value* that) {
-  if (IsDeadCheck("v8::Object::Cast()")) return;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Object::Cast()")) return;
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   ApiCheck(obj->IsJSObject(),
            "v8::Object::Cast()",
@@ -1998,7 +2166,7 @@
 
 
 void v8::Function::CheckCast(Value* that) {
-  if (IsDeadCheck("v8::Function::Cast()")) return;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Function::Cast()")) return;
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   ApiCheck(obj->IsJSFunction(),
            "v8::Function::Cast()",
@@ -2007,7 +2175,7 @@
 
 
 void v8::String::CheckCast(v8::Value* that) {
-  if (IsDeadCheck("v8::String::Cast()")) return;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::String::Cast()")) return;
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   ApiCheck(obj->IsString(),
            "v8::String::Cast()",
@@ -2016,7 +2184,7 @@
 
 
 void v8::Number::CheckCast(v8::Value* that) {
-  if (IsDeadCheck("v8::Number::Cast()")) return;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Number::Cast()")) return;
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   ApiCheck(obj->IsNumber(),
            "v8::Number::Cast()",
@@ -2025,7 +2193,7 @@
 
 
 void v8::Integer::CheckCast(v8::Value* that) {
-  if (IsDeadCheck("v8::Integer::Cast()")) return;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Integer::Cast()")) return;
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   ApiCheck(obj->IsNumber(),
            "v8::Integer::Cast()",
@@ -2034,7 +2202,7 @@
 
 
 void v8::Array::CheckCast(Value* that) {
-  if (IsDeadCheck("v8::Array::Cast()")) return;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Array::Cast()")) return;
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   ApiCheck(obj->IsJSArray(),
            "v8::Array::Cast()",
@@ -2043,16 +2211,17 @@
 
 
 void v8::Date::CheckCast(v8::Value* that) {
-  if (IsDeadCheck("v8::Date::Cast()")) return;
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Date::Cast()")) return;
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
+  ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Date_symbol()),
            "v8::Date::Cast()",
            "Could not convert to date");
 }
 
 
 void v8::RegExp::CheckCast(v8::Value* that) {
-  if (IsDeadCheck("v8::RegExp::Cast()")) return;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::RegExp::Cast()")) return;
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
   ApiCheck(obj->IsJSRegExp(),
            "v8::RegExp::Cast()",
@@ -2061,13 +2230,14 @@
 
 
 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::Isolate* isolate = i::Isolate::Current();
+    if (IsDeadCheck(isolate, "v8::Value::BooleanValue()")) return false;
+    LOG_API(isolate, "BooleanValue");
+    ENTER_V8(isolate);
     i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
     return value->IsTrue();
   }
@@ -2075,34 +2245,38 @@
 
 
 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();
+    i::Isolate* isolate = i::Isolate::Current();
+    if (IsDeadCheck(isolate, "v8::Value::NumberValue()")) {
+      return i::OS::nan_value();
+    }
+    LOG_API(isolate, "NumberValue");
+    ENTER_V8(isolate);
+    EXCEPTION_PREAMBLE(isolate);
     num = i::Execution::ToNumber(obj, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
+    EXCEPTION_BAILOUT_CHECK(isolate, 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();
+    i::Isolate* isolate = i::Isolate::Current();
+    if (IsDeadCheck(isolate, "v8::Value::IntegerValue()")) return 0;
+    LOG_API(isolate, "IntegerValue");
+    ENTER_V8(isolate);
+    EXCEPTION_PREAMBLE(isolate);
     num = i::Execution::ToInteger(obj, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(0);
+    EXCEPTION_BAILOUT_CHECK(isolate, 0);
   }
   if (num->IsSmi()) {
     return i::Smi::cast(*num)->value();
@@ -2113,52 +2287,55 @@
 
 
 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();
+    i::Isolate* isolate = i::Isolate::Current();
+    if (IsDeadCheck(isolate, "v8::Value::ToInt32()")) return Local<Int32>();
+    LOG_API(isolate, "ToInt32");
+    ENTER_V8(isolate);
+    EXCEPTION_PREAMBLE(isolate);
     num = i::Execution::ToInt32(obj, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(Local<Int32>());
+    EXCEPTION_BAILOUT_CHECK(isolate, 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();
+    i::Isolate* isolate = i::Isolate::Current();
+    if (IsDeadCheck(isolate, "v8::Value::ToUint32()")) return Local<Uint32>();
+    LOG_API(isolate, "ToUInt32");
+    ENTER_V8(isolate);
+    EXCEPTION_PREAMBLE(isolate);
     num = i::Execution::ToUint32(obj, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
+    EXCEPTION_BAILOUT_CHECK(isolate, 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::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Value::ToArrayIndex()")) return Local<Uint32>();
+  LOG_API(isolate, "ToArrayIndex");
+  ENTER_V8(isolate);
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> string_obj =
       i::Execution::ToString(obj, &has_pending_exception);
-  EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
+  EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
   i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
   uint32_t index;
   if (str->AsArrayIndex(&index)) {
@@ -2166,7 +2343,7 @@
     if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
       value = i::Handle<i::Object>(i::Smi::FromInt(index));
     } else {
-      value = i::Factory::NewNumber(index);
+      value = isolate->factory()->NewNumber(index);
     }
     return Utils::Uint32ToLocal(value);
   }
@@ -2175,18 +2352,18 @@
 
 
 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::Isolate* isolate = i::Isolate::Current();
+    if (IsDeadCheck(isolate, "v8::Value::Int32Value()")) return 0;
+    LOG_API(isolate, "Int32Value (slow)");
+    ENTER_V8(isolate);
+    EXCEPTION_PREAMBLE(isolate);
     i::Handle<i::Object> num =
         i::Execution::ToInt32(obj, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(0);
+    EXCEPTION_BAILOUT_CHECK(isolate, 0);
     if (num->IsSmi()) {
       return i::Smi::cast(*num)->value();
     } else {
@@ -2197,13 +2374,14 @@
 
 
 bool Value::Equals(Handle<Value> that) const {
-  if (IsDeadCheck("v8::Value::Equals()")
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Value::Equals()")
       || EmptyCheck("v8::Value::Equals()", this)
       || EmptyCheck("v8::Value::Equals()", that)) {
     return false;
   }
-  LOG_API("Equals");
-  ENTER_V8;
+  LOG_API(isolate, "Equals");
+  ENTER_V8(isolate);
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   i::Handle<i::Object> other = Utils::OpenHandle(*that);
   // If both obj and other are JSObjects, we'd better compare by identity
@@ -2213,21 +2391,22 @@
     return *obj == *other;
   }
   i::Object** args[1] = { other.location() };
-  EXCEPTION_PREAMBLE();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> result =
       CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
-  EXCEPTION_BAILOUT_CHECK(false);
+  EXCEPTION_BAILOUT_CHECK(isolate, false);
   return *result == i::Smi::FromInt(i::EQUAL);
 }
 
 
 bool Value::StrictEquals(Handle<Value> that) const {
-  if (IsDeadCheck("v8::Value::StrictEquals()")
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Value::StrictEquals()")
       || EmptyCheck("v8::Value::StrictEquals()", this)
       || EmptyCheck("v8::Value::StrictEquals()", that)) {
     return false;
   }
-  LOG_API("StrictEquals");
+  LOG_API(isolate, "StrictEquals");
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   i::Handle<i::Object> other = Utils::OpenHandle(*that);
   // Must check HeapNumber first, since NaN !== NaN.
@@ -2253,17 +2432,18 @@
 
 
 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::Isolate* isolate = i::Isolate::Current();
+    if (IsDeadCheck(isolate, "v8::Value::Uint32Value()")) return 0;
+    LOG_API(isolate, "Uint32Value");
+    ENTER_V8(isolate);
+    EXCEPTION_PREAMBLE(isolate);
     i::Handle<i::Object> num =
         i::Execution::ToUint32(obj, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(0);
+    EXCEPTION_BAILOUT_CHECK(isolate, 0);
     if (num->IsSmi()) {
       return i::Smi::cast(*num)->value();
     } else {
@@ -2275,13 +2455,14 @@
 
 bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
                      v8::PropertyAttribute attribs) {
-  ON_BAILOUT("v8::Object::Set()", return false);
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::Set()", return false);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   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();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> obj = i::SetProperty(
       self,
       key_obj,
@@ -2289,25 +2470,26 @@
       static_cast<PropertyAttributes>(attribs),
       i::kNonStrictMode);
   has_pending_exception = obj.is_null();
-  EXCEPTION_BAILOUT_CHECK(false);
+  EXCEPTION_BAILOUT_CHECK(isolate, false);
   return true;
 }
 
 
 bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
-  ON_BAILOUT("v8::Object::Set()", return false);
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::Set()", return false);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
-  EXCEPTION_PREAMBLE();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> obj = i::SetElement(
       self,
       index,
       value_obj,
       i::kNonStrictMode);
   has_pending_exception = obj.is_null();
-  EXCEPTION_BAILOUT_CHECK(false);
+  EXCEPTION_BAILOUT_CHECK(isolate, false);
   return true;
 }
 
@@ -2315,28 +2497,30 @@
 bool v8::Object::ForceSet(v8::Handle<Value> key,
                           v8::Handle<Value> value,
                           v8::PropertyAttribute attribs) {
-  ON_BAILOUT("v8::Object::ForceSet()", return false);
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::ForceSet()", return false);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
-  EXCEPTION_PREAMBLE();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> obj = i::ForceSetProperty(
       self,
       key_obj,
       value_obj,
       static_cast<PropertyAttributes>(attribs));
   has_pending_exception = obj.is_null();
-  EXCEPTION_BAILOUT_CHECK(false);
+  EXCEPTION_BAILOUT_CHECK(isolate, false);
   return true;
 }
 
 
 bool v8::Object::ForceDelete(v8::Handle<Value> key) {
-  ON_BAILOUT("v8::Object::ForceDelete()", return false);
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::ForceDelete()", return false);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
 
@@ -2344,42 +2528,46 @@
   // as optimized code does not always handle access checks.
   i::Deoptimizer::DeoptimizeGlobalObject(*self);
 
-  EXCEPTION_PREAMBLE();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
   has_pending_exception = obj.is_null();
-  EXCEPTION_BAILOUT_CHECK(false);
+  EXCEPTION_BAILOUT_CHECK(isolate, false);
   return obj->IsTrue();
 }
 
 
 Local<Value> v8::Object::Get(v8::Handle<Value> key) {
-  ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
+  ENTER_V8(isolate);
   i::Handle<i::Object> self = Utils::OpenHandle(this);
   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
-  EXCEPTION_PREAMBLE();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> result = i::GetProperty(self, key_obj);
   has_pending_exception = result.is_null();
-  EXCEPTION_BAILOUT_CHECK(Local<Value>());
+  EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
   return Utils::ToLocal(result);
 }
 
 
 Local<Value> v8::Object::Get(uint32_t index) {
-  ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
+  ENTER_V8(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  EXCEPTION_PREAMBLE();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> result = i::GetElement(self, index);
   has_pending_exception = result.is_null();
-  EXCEPTION_BAILOUT_CHECK(Local<Value>());
+  EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
   return Utils::ToLocal(result);
 }
 
 
 Local<Value> v8::Object::GetPrototype() {
-  ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::GetPrototype()",
+             return Local<v8::Value>());
+  ENTER_V8(isolate);
   i::Handle<i::Object> self = Utils::OpenHandle(this);
   i::Handle<i::Object> result = i::GetPrototype(self);
   return Utils::ToLocal(result);
@@ -2387,23 +2575,26 @@
 
 
 bool v8::Object::SetPrototype(Handle<Value> value) {
-  ON_BAILOUT("v8::Object::SetPrototype()", return false);
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::SetPrototype()", return false);
+  ENTER_V8(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
-  EXCEPTION_PREAMBLE();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
   has_pending_exception = result.is_null();
-  EXCEPTION_BAILOUT_CHECK(false);
+  EXCEPTION_BAILOUT_CHECK(isolate, false);
   return true;
 }
 
 
 Local<Object> v8::Object::FindInstanceInPrototypeChain(
     v8::Handle<FunctionTemplate> tmpl) {
-  ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate,
+             "v8::Object::FindInstanceInPrototypeChain()",
              return Local<v8::Object>());
-  ENTER_V8;
+  ENTER_V8(isolate);
   i::JSObject* object = *Utils::OpenHandle(this);
   i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
   while (!object->IsInstanceOf(tmpl_info)) {
@@ -2416,24 +2607,29 @@
 
 
 Local<Array> v8::Object::GetPropertyNames() {
-  ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
-  ENTER_V8;
-  v8::HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::GetPropertyNames()",
+             return Local<v8::Array>());
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::FixedArray> value =
       i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
   // 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));
+  i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value);
+  i::Handle<i::JSArray> result =
+      isolate->factory()->NewJSArrayWithElements(elms);
+  return Utils::ToLocal(scope.CloseAndEscape(result));
 }
 
 
 Local<String> v8::Object::ObjectProtoToString() {
-  ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::ObjectProtoToString()",
+             return Local<v8::String>());
+  ENTER_V8(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
 
   i::Handle<i::Object> name(self->class_name());
@@ -2484,8 +2680,10 @@
 
 
 Local<String> v8::Object::GetConstructorName() {
-  ON_BAILOUT("v8::Object::GetConstructorName()", return Local<v8::String>());
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::GetConstructorName()",
+             return Local<v8::String>());
+  ENTER_V8(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::String> name(self->constructor_name());
   return Utils::ToLocal(name);
@@ -2493,9 +2691,10 @@
 
 
 bool v8::Object::Delete(v8::Handle<String> key) {
-  ON_BAILOUT("v8::Object::Delete()", return false);
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::Delete()", return false);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
   return i::DeleteProperty(self, key_obj)->IsTrue();
@@ -2503,8 +2702,9 @@
 
 
 bool v8::Object::Has(v8::Handle<String> key) {
-  ON_BAILOUT("v8::Object::Has()", return false);
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::Has()", return false);
+  ENTER_V8(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
   return self->HasProperty(*key_obj);
@@ -2512,8 +2712,10 @@
 
 
 bool v8::Object::Delete(uint32_t index) {
-  ON_BAILOUT("v8::Object::DeleteProperty()", return false);
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::DeleteProperty()",
+             return false);
+  ENTER_V8(isolate);
   HandleScope scope;
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   return i::DeleteElement(self, index)->IsTrue();
@@ -2521,7 +2723,8 @@
 
 
 bool v8::Object::Has(uint32_t index) {
-  ON_BAILOUT("v8::Object::HasProperty()", return false);
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::HasProperty()", return false);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   return self->HasElement(index);
 }
@@ -2533,9 +2736,10 @@
                          v8::Handle<Value> data,
                          AccessControl settings,
                          PropertyAttribute attributes) {
-  ON_BAILOUT("v8::Object::SetAccessor()", return false);
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::SetAccessor()", return false);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name,
                                                      getter, setter, data,
                                                      settings, attributes);
@@ -2545,43 +2749,56 @@
 
 
 bool v8::Object::HasRealNamedProperty(Handle<String> key) {
-  ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "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);
+  ON_BAILOUT(Utils::OpenHandle(this)->GetIsolate(),
+             "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;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate,
+             "v8::Object::HasRealNamedCallbackProperty()",
+             return false);
+  ENTER_V8(isolate);
   return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
       *Utils::OpenHandle(*key));
 }
 
 
 bool v8::Object::HasNamedLookupInterceptor() {
-  ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::HasNamedLookupInterceptor()",
+             return false);
   return Utils::OpenHandle(this)->HasNamedInterceptor();
 }
 
 
 bool v8::Object::HasIndexedLookupInterceptor() {
-  ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::HasIndexedLookupInterceptor()",
+             return false);
   return Utils::OpenHandle(this)->HasIndexedInterceptor();
 }
 
 
 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
       Handle<String> key) {
-  ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate,
+             "v8::Object::GetRealNamedPropertyInPrototypeChain()",
              return Local<Value>());
-  ENTER_V8;
+  ENTER_V8(isolate);
   i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
   i::LookupResult lookup;
@@ -2601,8 +2818,10 @@
 
 
 Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
-  ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::GetRealNamedProperty()",
+             return Local<Value>());
+  ENTER_V8(isolate);
   i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
   i::LookupResult lookup;
@@ -2625,9 +2844,10 @@
 // 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;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::TurnOnAccessCheck()", return);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
 
   // When turning on access checks for a global object deoptimize all functions
@@ -2635,7 +2855,7 @@
   i::Deoptimizer::DeoptimizeGlobalObject(*obj);
 
   i::Handle<i::Map> new_map =
-    i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
+      isolate->factory()->CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
   new_map->set_is_access_check_needed(true);
   obj->set_map(*new_map);
 }
@@ -2647,21 +2867,23 @@
 
 
 Local<v8::Object> v8::Object::Clone() {
-  ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::Clone()", return Local<Object>());
+  ENTER_V8(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  EXCEPTION_PREAMBLE();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::JSObject> result = i::Copy(self);
   has_pending_exception = result.is_null();
-  EXCEPTION_BAILOUT_CHECK(Local<Object>());
+  EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
   return Utils::ToLocal(result);
 }
 
 
 int v8::Object::GetIdentityHash() {
-  ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::GetIdentityHash()", return 0);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::Object> hidden_props_obj(i::GetHiddenProperties(self, true));
   if (!hidden_props_obj->IsJSObject()) {
@@ -2672,7 +2894,7 @@
   }
   i::Handle<i::JSObject> hidden_props =
       i::Handle<i::JSObject>::cast(hidden_props_obj);
-  i::Handle<i::String> hash_symbol = i::Factory::identity_hash_symbol();
+  i::Handle<i::String> hash_symbol = isolate->factory()->identity_hash_symbol();
   if (hidden_props->HasLocalProperty(*hash_symbol)) {
     i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
     CHECK(!hash.is_null());
@@ -2685,7 +2907,7 @@
   do {
     // Generate a random 32-bit hash value but limit range to fit
     // within a smi.
-    hash_value = i::V8::Random() & i::Smi::kMaxValue;
+    hash_value = i::V8::Random(self->GetIsolate()) & i::Smi::kMaxValue;
     attempts++;
   } while (hash_value == 0 && attempts < 30);
   hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
@@ -2701,14 +2923,15 @@
 
 bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
                                 v8::Handle<v8::Value> value) {
-  ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::SetHiddenValue()", return false);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   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();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> obj = i::SetProperty(
       hidden_props,
       key_obj,
@@ -2716,24 +2939,26 @@
       static_cast<PropertyAttributes>(None),
       i::kNonStrictMode);
   has_pending_exception = obj.is_null();
-  EXCEPTION_BAILOUT_CHECK(false);
+  EXCEPTION_BAILOUT_CHECK(isolate, 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::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::GetHiddenValue()",
+             return Local<v8::Value>());
+  ENTER_V8(isolate);
   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();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
   has_pending_exception = result.is_null();
-  EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
+  EXCEPTION_BAILOUT_CHECK(isolate, v8::Local<v8::Value>());
   if (result->IsUndefined()) {
     return v8::Local<v8::Value>();
   }
@@ -2742,9 +2967,10 @@
 
 
 bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
-  ON_BAILOUT("v8::DeleteHiddenValue()", return false);
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::DeleteHiddenValue()", return false);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
   if (hidden_props->IsUndefined()) {
@@ -2756,11 +2982,44 @@
 }
 
 
+namespace {
+
+void PrepareExternalArrayElements(i::Handle<i::JSObject> object,
+                                  void* data,
+                                  ExternalArrayType array_type,
+                                  int length) {
+  i::Isolate* isolate = object->GetIsolate();
+  i::Handle<i::ExternalArray> array =
+      isolate->factory()->NewExternalArray(length, array_type, data);
+
+  // If the object already has external elements, create a new, unique
+  // map if the element type is now changing, because assumptions about
+  // generated code based on the receiver's map will be invalid.
+  i::Handle<i::HeapObject> elements(object->elements());
+  bool cant_reuse_map =
+      elements->map()->IsUndefined() ||
+      !elements->map()->has_external_array_elements() ||
+      elements->map() != isolate->heap()->MapForExternalArrayType(array_type);
+  if (cant_reuse_map) {
+    i::Handle<i::Map> external_array_map =
+        isolate->factory()->GetExternalArrayElementsMap(
+            i::Handle<i::Map>(object->map()),
+            array_type,
+            object->HasFastProperties());
+    object->set_map(*external_array_map);
+  }
+  object->set_elements(*array);
+}
+
+}  // namespace
+
+
 void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
-  ON_BAILOUT("v8::SetElementsToPixelData()", return);
-  ENTER_V8;
-  HandleScope scope;
-  if (!ApiCheck(length <= i::PixelArray::kMaxLength,
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
+  if (!ApiCheck(length <= i::ExternalPixelArray::kMaxLength,
                 "v8::Object::SetIndexedPropertiesToPixelData()",
                 "length exceeds max acceptable value")) {
     return;
@@ -2771,26 +3030,25 @@
                 "JSArray is not supported")) {
     return;
   }
-  i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
-  i::Handle<i::Map> pixel_array_map =
-      i::Factory::GetPixelArrayElementsMap(i::Handle<i::Map>(self->map()));
-  self->set_map(*pixel_array_map);
-  self->set_elements(*pixels);
+  PrepareExternalArrayElements(self, data, kExternalPixelArray, length);
 }
 
 
 bool v8::Object::HasIndexedPropertiesInPixelData() {
-  ON_BAILOUT("v8::HasIndexedPropertiesInPixelData()", return false);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  return self->HasPixelElements();
+  ON_BAILOUT(self->GetIsolate(), "v8::HasIndexedPropertiesInPixelData()",
+             return false);
+  return self->HasExternalPixelElements();
 }
 
 
 uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
-  ON_BAILOUT("v8::GetIndexedPropertiesPixelData()", return NULL);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  if (self->HasPixelElements()) {
-    return i::PixelArray::cast(self->elements())->external_pointer();
+  ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelData()",
+             return NULL);
+  if (self->HasExternalPixelElements()) {
+    return i::ExternalPixelArray::cast(self->elements())->
+        external_pixel_pointer();
   } else {
     return NULL;
   }
@@ -2798,23 +3056,24 @@
 
 
 int v8::Object::GetIndexedPropertiesPixelDataLength() {
-  ON_BAILOUT("v8::GetIndexedPropertiesPixelDataLength()", return -1);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
-  if (self->HasPixelElements()) {
-    return i::PixelArray::cast(self->elements())->length();
+  ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelDataLength()",
+             return -1);
+  if (self->HasExternalPixelElements()) {
+    return i::ExternalPixelArray::cast(self->elements())->length();
   } else {
     return -1;
   }
 }
 
-
 void v8::Object::SetIndexedPropertiesToExternalArrayData(
     void* data,
     ExternalArrayType array_type,
     int length) {
-  ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
-  ENTER_V8;
-  HandleScope scope;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::SetIndexedPropertiesToExternalArrayData()", return);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
                 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
                 "length exceeds max acceptable value")) {
@@ -2826,25 +3085,24 @@
                 "JSArray is not supported")) {
     return;
   }
-  i::Handle<i::ExternalArray> array =
-      i::Factory::NewExternalArray(length, array_type, data);
-  i::Handle<i::Map> slow_map =
-      i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map()));
-  self->set_map(*slow_map);
-  self->set_elements(*array);
+  PrepareExternalArrayElements(self, data, array_type, length);
 }
 
 
 bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
-  ON_BAILOUT("v8::HasIndexedPropertiesInExternalArrayData()", return false);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  ON_BAILOUT(self->GetIsolate(),
+             "v8::HasIndexedPropertiesInExternalArrayData()",
+             return false);
   return self->HasExternalArrayElements();
 }
 
 
 void* v8::Object::GetIndexedPropertiesExternalArrayData() {
-  ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayData()", return NULL);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  ON_BAILOUT(self->GetIsolate(),
+             "v8::GetIndexedPropertiesExternalArrayData()",
+             return NULL);
   if (self->HasExternalArrayElements()) {
     return i::ExternalArray::cast(self->elements())->external_pointer();
   } else {
@@ -2854,9 +3112,10 @@
 
 
 ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
-  ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataType()",
-             return static_cast<ExternalArrayType>(-1));
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  ON_BAILOUT(self->GetIsolate(),
+             "v8::GetIndexedPropertiesExternalArrayDataType()",
+             return static_cast<ExternalArrayType>(-1));
   switch (self->elements()->map()->instance_type()) {
     case i::EXTERNAL_BYTE_ARRAY_TYPE:
       return kExternalByteArray;
@@ -2872,6 +3131,8 @@
       return kExternalUnsignedIntArray;
     case i::EXTERNAL_FLOAT_ARRAY_TYPE:
       return kExternalFloatArray;
+    case i::EXTERNAL_PIXEL_ARRAY_TYPE:
+      return kExternalPixelArray;
     default:
       return static_cast<ExternalArrayType>(-1);
   }
@@ -2879,8 +3140,10 @@
 
 
 int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
-  ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataLength()", return 0);
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  ON_BAILOUT(self->GetIsolate(),
+             "v8::GetIndexedPropertiesExternalArrayDataLength()",
+             return 0);
   if (self->HasExternalArrayElements()) {
     return i::ExternalArray::cast(self->elements())->length();
   } else {
@@ -2896,37 +3159,40 @@
 
 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;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Function::NewInstance()",
+             return Local<v8::Object>());
+  LOG_API(isolate, "Function::NewInstance");
+  ENTER_V8(isolate);
   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();
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> returned =
       i::Execution::New(function, argc, args, &has_pending_exception);
-  EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
+  EXCEPTION_BAILOUT_CHECK(isolate, 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::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Function::Call()", return Local<v8::Value>());
+  LOG_API(isolate, "Function::Call");
+  ENTER_V8(isolate);
   i::Object* raw_result = NULL;
   {
-    HandleScope scope;
+    i::HandleScope scope(isolate);
     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();
+    EXCEPTION_PREAMBLE(isolate);
     i::Handle<i::Object> returned =
         i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(Local<Object>());
+    EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
     raw_result = *returned;
   }
   i::Handle<i::Object> result(raw_result);
@@ -2935,7 +3201,8 @@
 
 
 void Function::SetName(v8::Handle<v8::String> name) {
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ENTER_V8(isolate);
   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
   func->shared()->set_name(*Utils::OpenHandle(*name));
 }
@@ -2974,81 +3241,17 @@
 }
 
 
-namespace {
-
-// Tracks string usage to help make better decisions when
-// externalizing strings.
-//
-// Implementation note: internally this class only tracks fresh
-// strings and keeps a single use counter for them.
-class StringTracker {
- public:
-  // Records that the given string's characters were copied to some
-  // external buffer. If this happens often we should honor
-  // externalization requests for the string.
-  static void RecordWrite(i::Handle<i::String> string) {
-    i::Address address = reinterpret_cast<i::Address>(*string);
-    i::Address top = i::Heap::NewSpaceTop();
-    if (IsFreshString(address, top)) {
-      IncrementUseCount(top);
-    }
-  }
-
-  // Estimates freshness and use frequency of the given string based
-  // on how close it is to the new space top and the recorded usage
-  // history.
-  static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
-    i::Address address = reinterpret_cast<i::Address>(*string);
-    i::Address top = i::Heap::NewSpaceTop();
-    return IsFreshString(address, top) && IsUseCountLow(top);
-  }
-
- private:
-  static inline bool IsFreshString(i::Address string, i::Address top) {
-    return top - kFreshnessLimit <= string && string <= top;
-  }
-
-  static inline bool IsUseCountLow(i::Address top) {
-    if (last_top_ != top) return true;
-    return use_count_ < kUseLimit;
-  }
-
-  static inline void IncrementUseCount(i::Address top) {
-    if (last_top_ != top) {
-      use_count_ = 0;
-      last_top_ = top;
-    }
-    ++use_count_;
-  }
-
-  // How close to the new space top a fresh string has to be.
-  static const int kFreshnessLimit = 1024;
-
-  // The number of uses required to consider a string useful.
-  static const int kUseLimit = 32;
-
-  // Single use counter shared by all fresh strings.
-  static int use_count_;
-
-  // Last new space top when the use count above was valid.
-  static i::Address last_top_;
-};
-
-int StringTracker::use_count_ = 0;
-i::Address StringTracker::last_top_ = NULL;
-
-}  // namespace
-
-
 int String::Length() const {
-  if (IsDeadCheck("v8::String::Length()")) return 0;
-  return Utils::OpenHandle(this)->length();
+  i::Handle<i::String> str = Utils::OpenHandle(this);
+  if (IsDeadCheck(str->GetIsolate(), "v8::String::Length()")) return 0;
+  return str->length();
 }
 
 
 int String::Utf8Length() const {
-  if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
-  return Utils::OpenHandle(this)->Utf8Length();
+  i::Handle<i::String> str = Utils::OpenHandle(this);
+  if (IsDeadCheck(str->GetIsolate(), "v8::String::Utf8Length()")) return 0;
+  return str->Utf8Length();
 }
 
 
@@ -3056,11 +3259,13 @@
                       int capacity,
                       int* nchars_ref,
                       WriteHints hints) const {
-  if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
-  LOG_API("String::WriteUtf8");
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0;
+  LOG_API(isolate, "String::WriteUtf8");
+  ENTER_V8(isolate);
+  i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer();
   i::Handle<i::String> str = Utils::OpenHandle(this);
-  StringTracker::RecordWrite(str);
+  isolate->string_tracker()->RecordWrite(str);
   if (hints & HINT_MANY_WRITES_EXPECTED) {
     // Flatten the string for efficiency.  This applies whether we are
     // using StringInputBuffer or Get(i) to access the characters.
@@ -3111,12 +3316,14 @@
                        int start,
                        int length,
                        WriteHints hints) const {
-  if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
-  LOG_API("String::WriteAscii");
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0;
+  LOG_API(isolate, "String::WriteAscii");
+  ENTER_V8(isolate);
+  i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer();
   ASSERT(start >= 0 && length >= -1);
   i::Handle<i::String> str = Utils::OpenHandle(this);
-  StringTracker::RecordWrite(str);
+  isolate->string_tracker()->RecordWrite(str);
   if (hints & HINT_MANY_WRITES_EXPECTED) {
     // Flatten the string for efficiency.  This applies whether we are
     // using StringInputBuffer or Get(i) to access the characters.
@@ -3143,12 +3350,13 @@
                   int start,
                   int length,
                   WriteHints hints) const {
-  if (IsDeadCheck("v8::String::Write()")) return 0;
-  LOG_API("String::Write");
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::String::Write()")) return 0;
+  LOG_API(isolate, "String::Write");
+  ENTER_V8(isolate);
   ASSERT(start >= 0 && length >= -1);
   i::Handle<i::String> str = Utils::OpenHandle(this);
-  StringTracker::RecordWrite(str);
+  isolate->string_tracker()->RecordWrite(str);
   if (hints & HINT_MANY_WRITES_EXPECTED) {
     // Flatten the string for efficiency.  This applies whether we are
     // using StringInputBuffer or Get(i) to access the characters.
@@ -3167,15 +3375,20 @@
 
 
 bool v8::String::IsExternal() const {
-  EnsureInitialized("v8::String::IsExternal()");
   i::Handle<i::String> str = Utils::OpenHandle(this);
+  if (IsDeadCheck(str->GetIsolate(), "v8::String::IsExternal()")) {
+    return false;
+  }
+  EnsureInitializedForIsolate(str->GetIsolate(), "v8::String::IsExternal()");
   return i::StringShape(*str).IsExternalTwoByte();
 }
 
 
 bool v8::String::IsExternalAscii() const {
-  EnsureInitialized("v8::String::IsExternalAscii()");
   i::Handle<i::String> str = Utils::OpenHandle(this);
+  if (IsDeadCheck(str->GetIsolate(), "v8::String::IsExternalAscii()")) {
+    return false;
+  }
   return i::StringShape(*str).IsExternalAscii();
 }
 
@@ -3196,8 +3409,11 @@
 
 v8::String::ExternalAsciiStringResource*
       v8::String::GetExternalAsciiStringResource() const {
-  EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
   i::Handle<i::String> str = Utils::OpenHandle(this);
+  if (IsDeadCheck(str->GetIsolate(),
+                  "v8::String::GetExternalAsciiStringResource()")) {
+    return NULL;
+  }
   if (i::StringShape(*str).IsExternalAscii()) {
     void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
     return reinterpret_cast<ExternalAsciiStringResource*>(resource);
@@ -3208,21 +3424,21 @@
 
 
 double Number::Value() const {
-  if (IsDeadCheck("v8::Number::Value()")) return 0;
+  if (IsDeadCheck(i::Isolate::Current(), "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;
+  if (IsDeadCheck(i::Isolate::Current(), "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;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Integer::Value()")) return 0;
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   if (obj->IsSmi()) {
     return i::Smi::cast(*obj)->value();
@@ -3233,7 +3449,7 @@
 
 
 int32_t Int32::Value() const {
-  if (IsDeadCheck("v8::Int32::Value()")) return 0;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Int32::Value()")) return 0;
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   if (obj->IsSmi()) {
     return i::Smi::cast(*obj)->value();
@@ -3244,7 +3460,7 @@
 
 
 uint32_t Uint32::Value() const {
-  if (IsDeadCheck("v8::Uint32::Value()")) return 0;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::Uint32::Value()")) return 0;
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   if (obj->IsSmi()) {
     return i::Smi::cast(*obj)->value();
@@ -3255,15 +3471,19 @@
 
 
 int v8::Object::InternalFieldCount() {
-  if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+  if (IsDeadCheck(obj->GetIsolate(), "v8::Object::InternalFieldCount()")) {
+    return 0;
+  }
   return obj->GetInternalFieldCount();
 }
 
 
 Local<Value> v8::Object::CheckedGetInternalField(int index) {
-  if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+  if (IsDeadCheck(obj->GetIsolate(), "v8::Object::GetInternalField()")) {
+    return Local<Value>();
+  }
   if (!ApiCheck(index < obj->GetInternalFieldCount(),
                 "v8::Object::GetInternalField()",
                 "Reading internal field out of bounds")) {
@@ -3280,14 +3500,17 @@
 
 
 void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
-  if (IsDeadCheck("v8::Object::SetInternalField()")) return;
   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+  i::Isolate* isolate = obj->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::Object::SetInternalField()")) {
+    return;
+  }
   if (!ApiCheck(index < obj->GetInternalFieldCount(),
                 "v8::Object::SetInternalField()",
                 "Writing internal field out of bounds")) {
     return;
   }
-  ENTER_V8;
+  ENTER_V8(isolate);
   i::Handle<i::Object> val = Utils::OpenHandle(*value);
   obj->SetInternalField(index, *val);
 }
@@ -3311,13 +3534,15 @@
 
 
 void v8::Object::SetPointerInInternalField(int index, void* value) {
-  ENTER_V8;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ENTER_V8(isolate);
   if (CanBeEncodedAsSmi(value)) {
     Utils::OpenHandle(this)->SetInternalField(index, EncodeAsSmi(value));
   } else {
     HandleScope scope;
     i::Handle<i::Proxy> proxy =
-        i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
+        isolate->factory()->NewProxy(
+            reinterpret_cast<i::Address>(value), i::TENURED);
     if (!proxy.is_null())
         Utils::OpenHandle(this)->SetInternalField(index, *proxy);
   }
@@ -3327,15 +3552,23 @@
 
 // --- E n v i r o n m e n t ---
 
+
 bool v8::V8::Initialize() {
-  if (i::V8::IsRunning()) return true;
-  HandleScope scope;
-  if (i::Snapshot::Initialize()) return true;
-  return i::V8::Initialize(NULL);
+  i::Isolate* isolate = i::Isolate::UncheckedCurrent();
+  if (isolate != NULL && isolate->IsInitialized()) {
+    return true;
+  }
+  return InitializeHelper();
 }
 
 
 bool v8::V8::Dispose() {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (!ApiCheck(isolate != NULL && isolate->IsDefaultIsolate(),
+                "v8::V8::Dispose()",
+                "Use v8::Isolate::Dispose() for a non-default isolate.")) {
+    return false;
+  }
   i::V8::TearDown();
   return true;
 }
@@ -3348,38 +3581,39 @@
 
 
 void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
-  heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
+  i::Heap* heap = i::Isolate::Current()->heap();
+  heap_statistics->set_total_heap_size(heap->CommittedMemory());
   heap_statistics->set_total_heap_size_executable(
-      i::Heap::CommittedMemoryExecutable());
-  heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
-  heap_statistics->set_heap_size_limit(i::Heap::MaxReserved());
+      heap->CommittedMemoryExecutable());
+  heap_statistics->set_used_heap_size(heap->SizeOfObjects());
+  heap_statistics->set_heap_size_limit(heap->MaxReserved());
 }
 
 
 bool v8::V8::IdleNotification() {
   // Returning true tells the caller that it need not
   // continue to call IdleNotification.
-  if (!i::V8::IsRunning()) return true;
+  if (!i::Isolate::Current()->IsInitialized()) return true;
   return i::V8::IdleNotification();
 }
 
 
 void v8::V8::LowMemoryNotification() {
-  if (!i::V8::IsRunning()) return;
-  i::Heap::CollectAllGarbage(true);
+  i::Isolate* isolate = i::Isolate::Current();
+  if (!isolate->IsInitialized()) return;
+  isolate->heap()->CollectAllGarbage(true);
 }
 
 
 int v8::V8::ContextDisposedNotification() {
-  if (!i::V8::IsRunning()) return 0;
-  return i::Heap::NotifyContextDisposed();
+  i::Isolate* isolate = i::Isolate::Current();
+  if (!isolate->IsInitialized()) return 0;
+  return isolate->heap()->NotifyContextDisposed();
 }
 
 
 const char* v8::V8::GetVersion() {
-  static v8::internal::EmbeddedVector<char, 128> buffer;
-  v8::internal::Version::GetString(buffer);
-  return buffer.start();
+  return i::Version::GetVersion();
 }
 
 
@@ -3399,14 +3633,15 @@
     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>());
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::Context::New()");
+  LOG_API(isolate, "Context::New");
+  ON_BAILOUT(isolate, "v8::Context::New()", return Persistent<Context>());
 
   // Enter V8 via an ENTER_V8 scope.
   i::Handle<i::Context> env;
   {
-    ENTER_V8;
+    ENTER_V8(isolate);
     v8::Handle<ObjectTemplate> proxy_template = global_template;
     i::Handle<i::FunctionTemplateInfo> proxy_constructor;
     i::Handle<i::FunctionTemplateInfo> global_constructor;
@@ -3435,12 +3670,13 @@
         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());
+        global_constructor->set_access_check_info(
+            isolate->heap()->undefined_value());
       }
     }
 
     // Create the environment.
-    env = i::Bootstrapper::CreateEnvironment(
+    env = isolate->bootstrapper()->CreateEnvironment(
         Utils::OpenHandle(*global_object),
         proxy_template,
         extensions);
@@ -3454,7 +3690,7 @@
       global_constructor->set_needs_access_check(
           proxy_constructor->needs_access_check());
     }
-    i::RuntimeProfiler::Reset();
+    isolate->runtime_profiler()->Reset();
   }
   // Leave V8.
 
@@ -3465,8 +3701,11 @@
 
 
 void v8::Context::SetSecurityToken(Handle<Value> token) {
-  if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Context::SetSecurityToken()")) {
+    return;
+  }
+  ENTER_V8(isolate);
   i::Handle<i::Context> env = Utils::OpenHandle(this);
   i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
   env->set_security_token(*token_handle);
@@ -3474,15 +3713,22 @@
 
 
 void v8::Context::UseDefaultSecurityToken() {
-  if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate,
+                  "v8::Context::UseDefaultSecurityToken()")) {
+    return;
+  }
+  ENTER_V8(isolate);
   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::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "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);
@@ -3497,13 +3743,17 @@
 
 
 bool Context::InContext() {
-  return i::Top::context() != NULL;
+  return i::Isolate::Current()->context() != NULL;
 }
 
 
 v8::Local<v8::Context> Context::GetEntered() {
-  if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
-  i::Handle<i::Object> last = thread_local.LastEnteredContext();
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Context::GetEntered()")) {
+    return Local<Context>();
+  }
+  i::Handle<i::Object> last =
+      isolate->handle_scope_implementer()->LastEnteredContext();
   if (last.is_null()) return Local<Context>();
   i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
   return Utils::ToLocal(context);
@@ -3511,8 +3761,11 @@
 
 
 v8::Local<v8::Context> Context::GetCurrent() {
-  if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
-  i::Handle<i::Object> current = i::Top::global_context();
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Context::GetCurrent()")) {
+    return Local<Context>();
+  }
+  i::Handle<i::Object> current = isolate->global_context();
   if (current.is_null()) return Local<Context>();
   i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
   return Utils::ToLocal(context);
@@ -3520,8 +3773,12 @@
 
 
 v8::Local<v8::Context> Context::GetCalling() {
-  if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
-  i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Context::GetCalling()")) {
+    return Local<Context>();
+  }
+  i::Handle<i::Object> calling =
+      isolate->GetCallingGlobalContext();
   if (calling.is_null()) return Local<Context>();
   i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
   return Utils::ToLocal(context);
@@ -3529,7 +3786,9 @@
 
 
 v8::Local<v8::Object> Context::Global() {
-  if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
+  if (IsDeadCheck(i::Isolate::Current(), "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));
@@ -3539,61 +3798,74 @@
 
 
 void Context::DetachGlobal() {
-  if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Context::DetachGlobal()")) return;
+  ENTER_V8(isolate);
   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);
+  isolate->bootstrapper()->DetachGlobal(context);
 }
 
 
 void Context::ReattachGlobal(Handle<Object> global_object) {
-  if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Context::ReattachGlobal()")) return;
+  ENTER_V8(isolate);
   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::ReattachGlobal(context, Utils::OpenHandle(*global_object));
+  isolate->bootstrapper()->ReattachGlobal(
+      context,
+      Utils::OpenHandle(*global_object));
+}
+
+
+void V8::SetWrapperClassId(i::Object** global_handle, uint16_t class_id) {
+  i::GlobalHandles::SetWrapperClassId(global_handle, class_id);
 }
 
 
 Local<v8::Object> ObjectTemplate::NewInstance() {
-  ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
-  LOG_API("ObjectTemplate::NewInstance");
-  ENTER_V8;
-  EXCEPTION_PREAMBLE();
+  i::Isolate* isolate = i::Isolate::Current();
+  ON_BAILOUT(isolate, "v8::ObjectTemplate::NewInstance()",
+             return Local<v8::Object>());
+  LOG_API(isolate, "ObjectTemplate::NewInstance");
+  ENTER_V8(isolate);
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> obj =
       i::Execution::InstantiateObject(Utils::OpenHandle(this),
                                       &has_pending_exception);
-  EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
+  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
   return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
 }
 
 
 Local<v8::Function> FunctionTemplate::GetFunction() {
-  ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
+  i::Isolate* isolate = i::Isolate::Current();
+  ON_BAILOUT(isolate, "v8::FunctionTemplate::GetFunction()",
              return Local<v8::Function>());
-  LOG_API("FunctionTemplate::GetFunction");
-  ENTER_V8;
-  EXCEPTION_PREAMBLE();
+  LOG_API(isolate, "FunctionTemplate::GetFunction");
+  ENTER_V8(isolate);
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> obj =
       i::Execution::InstantiateFunction(Utils::OpenHandle(this),
                                         &has_pending_exception);
-  EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
+  EXCEPTION_BAILOUT_CHECK(isolate, 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);
+  ON_BAILOUT(i::Isolate::Current(), "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)));
+  return Utils::ToLocal(FACTORY->NewProxy(static_cast<i::Address>(data)));
 }
 
 static void* ExternalValueImpl(i::Handle<i::Object> obj) {
@@ -3602,10 +3874,11 @@
 
 
 Local<Value> v8::External::Wrap(void* data) {
+  i::Isolate* isolate = i::Isolate::Current();
   STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
-  LOG_API("External::Wrap");
-  EnsureInitialized("v8::External::Wrap()");
-  ENTER_V8;
+  LOG_API(isolate, "External::Wrap");
+  EnsureInitializedForIsolate(isolate, "v8::External::Wrap()");
+  ENTER_V8(isolate);
 
   v8::Local<v8::Value> result = CanBeEncodedAsSmi(data)
       ? Utils::ToLocal(i::Handle<i::Object>(EncodeAsSmi(data)))
@@ -3630,7 +3903,7 @@
 
 
 void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
-  if (IsDeadCheck("v8::External::Unwrap()")) return 0;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::External::Unwrap()")) return 0;
   i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
   void* result;
   if (obj->IsSmi()) {
@@ -3647,58 +3920,65 @@
 
 Local<External> v8::External::New(void* data) {
   STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
-  LOG_API("External::New");
-  EnsureInitialized("v8::External::New()");
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  LOG_API(isolate, "External::New");
+  EnsureInitializedForIsolate(isolate, "v8::External::New()");
+  ENTER_V8(isolate);
   return ExternalNewImpl(data);
 }
 
 
 void* External::Value() const {
-  if (IsDeadCheck("v8::External::Value()")) return 0;
+  if (IsDeadCheck(i::Isolate::Current(), "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());
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::String::Empty()");
+  LOG_API(isolate, "String::Empty()");
+  return Utils::ToLocal(isolate->factory()->empty_symbol());
 }
 
 
 Local<String> v8::String::New(const char* data, int length) {
-  EnsureInitialized("v8::String::New()");
-  LOG_API("String::New(char)");
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::String::New()");
+  LOG_API(isolate, "String::New(char)");
   if (length == 0) return Empty();
-  ENTER_V8;
+  ENTER_V8(isolate);
   if (length == -1) length = i::StrLength(data);
   i::Handle<i::String> result =
-      i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
+      isolate->factory()->NewStringFromUtf8(
+          i::Vector<const char>(data, length));
   return Utils::ToLocal(result);
 }
 
 
 Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
-  EnsureInitialized("v8::String::New()");
-  LOG_API("String::New(char)");
-  ENTER_V8;
   i::Handle<i::String> left_string = Utils::OpenHandle(*left);
+  i::Isolate* isolate = left_string->GetIsolate();
+  EnsureInitializedForIsolate(isolate, "v8::String::New()");
+  LOG_API(isolate, "String::New(char)");
+  ENTER_V8(isolate);
   i::Handle<i::String> right_string = Utils::OpenHandle(*right);
-  i::Handle<i::String> result = i::Factory::NewConsString(left_string,
-                                                          right_string);
+  i::Handle<i::String> result = isolate->factory()->NewConsString(left_string,
+                                                                  right_string);
   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;
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()");
+  LOG_API(isolate, "String::NewUndetectable(char)");
+  ENTER_V8(isolate);
   if (length == -1) length = i::StrLength(data);
   i::Handle<i::String> result =
-      i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
+      isolate->factory()->NewStringFromUtf8(
+          i::Vector<const char>(data, length));
   result->MarkAsUndetectable();
   return Utils::ToLocal(result);
 }
@@ -3712,65 +3992,75 @@
 
 
 Local<String> v8::String::New(const uint16_t* data, int length) {
-  EnsureInitialized("v8::String::New()");
-  LOG_API("String::New(uint16_)");
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::String::New()");
+  LOG_API(isolate, "String::New(uint16_)");
   if (length == 0) return Empty();
-  ENTER_V8;
+  ENTER_V8(isolate);
   if (length == -1) length = TwoByteStringLength(data);
   i::Handle<i::String> result =
-      i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
+      isolate->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;
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()");
+  LOG_API(isolate, "String::NewUndetectable(uint16_)");
+  ENTER_V8(isolate);
   if (length == -1) length = TwoByteStringLength(data);
   i::Handle<i::String> result =
-      i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
+      isolate->factory()->NewStringFromTwoByte(
+          i::Vector<const uint16_t>(data, length));
   result->MarkAsUndetectable();
   return Utils::ToLocal(result);
 }
 
 
-i::Handle<i::String> NewExternalStringHandle(
+i::Handle<i::String> NewExternalStringHandle(i::Isolate* isolate,
       v8::String::ExternalStringResource* resource) {
   i::Handle<i::String> result =
-      i::Factory::NewExternalStringFromTwoByte(resource);
+      isolate->factory()->NewExternalStringFromTwoByte(resource);
   return result;
 }
 
 
-i::Handle<i::String> NewExternalAsciiStringHandle(
+i::Handle<i::String> NewExternalAsciiStringHandle(i::Isolate* isolate,
       v8::String::ExternalAsciiStringResource* resource) {
   i::Handle<i::String> result =
-      i::Factory::NewExternalStringFromAscii(resource);
+      isolate->factory()->NewExternalStringFromAscii(resource);
   return result;
 }
 
 
 Local<String> v8::String::NewExternal(
       v8::String::ExternalStringResource* resource) {
-  EnsureInitialized("v8::String::NewExternal()");
-  LOG_API("String::NewExternal");
-  ENTER_V8;
-  i::Handle<i::String> result = NewExternalStringHandle(resource);
-  i::ExternalStringTable::AddString(*result);
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()");
+  LOG_API(isolate, "String::NewExternal");
+  ENTER_V8(isolate);
+  i::Handle<i::String> result = NewExternalStringHandle(isolate, resource);
+  isolate->heap()->external_string_table()->AddString(*result);
   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);
-  if (StringTracker::IsFreshUnusedString(obj)) return false;
+  i::Isolate* isolate = obj->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::String::MakeExternal()")) return false;
+  if (i::StringShape(*obj).IsExternalTwoByte()) {
+    return false;  // Already an external string.
+  }
+  ENTER_V8(isolate);
+  if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
+    return false;
+  }
   bool result = obj->MakeExternal(resource);
   if (result && !obj->IsSymbol()) {
-    i::ExternalStringTable::AddString(*obj);
+    isolate->heap()->external_string_table()->AddString(*obj);
   }
   return result;
 }
@@ -3778,34 +4068,43 @@
 
 Local<String> v8::String::NewExternal(
       v8::String::ExternalAsciiStringResource* resource) {
-  EnsureInitialized("v8::String::NewExternal()");
-  LOG_API("String::NewExternal");
-  ENTER_V8;
-  i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
-  i::ExternalStringTable::AddString(*result);
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()");
+  LOG_API(isolate, "String::NewExternal");
+  ENTER_V8(isolate);
+  i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource);
+  isolate->heap()->external_string_table()->AddString(*result);
   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);
-  if (StringTracker::IsFreshUnusedString(obj)) return false;
+  i::Isolate* isolate = obj->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::String::MakeExternal()")) return false;
+  if (i::StringShape(*obj).IsExternalTwoByte()) {
+    return false;  // Already an external string.
+  }
+  ENTER_V8(isolate);
+  if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
+    return false;
+  }
   bool result = obj->MakeExternal(resource);
   if (result && !obj->IsSymbol()) {
-    i::ExternalStringTable::AddString(*obj);
+    isolate->heap()->external_string_table()->AddString(*obj);
   }
   return result;
 }
 
 
 bool v8::String::CanMakeExternal() {
-  if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
   i::Handle<i::String> obj = Utils::OpenHandle(this);
-  if (StringTracker::IsFreshUnusedString(obj)) return false;
+  i::Isolate* isolate = obj->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::String::CanMakeExternal()")) return false;
+  if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
+    return false;
+  }
   int size = obj->Size();  // Byte size of the original string.
   if (size < i::ExternalString::kSize)
     return false;
@@ -3815,34 +4114,37 @@
 
 
 Local<v8::Object> v8::Object::New() {
-  EnsureInitialized("v8::Object::New()");
-  LOG_API("Object::New");
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::Object::New()");
+  LOG_API(isolate, "Object::New");
+  ENTER_V8(isolate);
   i::Handle<i::JSObject> obj =
-      i::Factory::NewJSObject(i::Top::object_function());
+      isolate->factory()->NewJSObject(isolate->object_function());
   return Utils::ToLocal(obj);
 }
 
 
 Local<v8::Value> v8::Date::New(double time) {
-  EnsureInitialized("v8::Date::New()");
-  LOG_API("Date::New");
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::Date::New()");
+  LOG_API(isolate, "Date::New");
   if (isnan(time)) {
     // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
     time = i::OS::nan_value();
   }
-  ENTER_V8;
-  EXCEPTION_PREAMBLE();
+  ENTER_V8(isolate);
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> obj =
       i::Execution::NewDate(time, &has_pending_exception);
-  EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
+  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Value>());
   return Utils::ToLocal(obj);
 }
 
 
 double v8::Date::NumberValue() const {
-  if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
-  LOG_API("Date::NumberValue");
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Date::NumberValue()")) return 0;
+  LOG_API(isolate, "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();
@@ -3850,16 +4152,18 @@
 
 
 void v8::Date::DateTimeConfigurationChangeNotification() {
-  ON_BAILOUT("v8::Date::DateTimeConfigurationChangeNotification()", return);
-  LOG_API("Date::DateTimeConfigurationChangeNotification");
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  ON_BAILOUT(isolate, "v8::Date::DateTimeConfigurationChangeNotification()",
+             return);
+  LOG_API(isolate, "Date::DateTimeConfigurationChangeNotification");
+  ENTER_V8(isolate);
 
-  HandleScope scope;
-
+  i::HandleScope scope(isolate);
   // Get the function ResetDateCache (defined in date-delay.js).
   i::Handle<i::String> func_name_str =
-      i::Factory::LookupAsciiSymbol("ResetDateCache");
-  i::MaybeObject* result = i::Top::builtins()->GetProperty(*func_name_str);
+      isolate->factory()->LookupAsciiSymbol("ResetDateCache");
+  i::MaybeObject* result =
+      isolate->js_builtins_object()->GetProperty(*func_name_str);
   i::Object* object_func;
   if (!result->ToObject(&object_func)) {
     return;
@@ -3872,7 +4176,7 @@
     // Call ResetDateCache(0 but expect no exceptions:
     bool caught_exception = false;
     i::Handle<i::Object> result =
-        i::Execution::TryCall(func, i::Top::builtins(), 0, NULL,
+        i::Execution::TryCall(func, isolate->js_builtins_object(), 0, NULL,
         &caught_exception);
   }
 }
@@ -3885,28 +4189,32 @@
   if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
   if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
   ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
-  return i::Factory::LookupSymbol(
+  return FACTORY->LookupSymbol(
       i::Vector<const char>(flags_buf, num_flags));
 }
 
 
 Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
                                   Flags flags) {
-  EnsureInitialized("v8::RegExp::New()");
-  LOG_API("RegExp::New");
-  ENTER_V8;
-  EXCEPTION_PREAMBLE();
+  i::Isolate* isolate = Utils::OpenHandle(*pattern)->GetIsolate();
+  EnsureInitializedForIsolate(isolate, "v8::RegExp::New()");
+  LOG_API(isolate, "RegExp::New");
+  ENTER_V8(isolate);
+  EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::JSRegExp> obj = i::Execution::NewJSRegExp(
       Utils::OpenHandle(*pattern),
       RegExpFlagsToString(flags),
       &has_pending_exception);
-  EXCEPTION_BAILOUT_CHECK(Local<v8::RegExp>());
+  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::RegExp>());
   return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
 }
 
 
 Local<v8::String> v8::RegExp::GetSource() const {
-  if (IsDeadCheck("v8::RegExp::GetSource()")) return Local<v8::String>();
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::RegExp::GetSource()")) {
+    return Local<v8::String>();
+  }
   i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
   return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
 }
@@ -3923,23 +4231,29 @@
 #undef REGEXP_FLAG_ASSERT_EQ
 
 v8::RegExp::Flags v8::RegExp::GetFlags() const {
-  if (IsDeadCheck("v8::RegExp::GetFlags()")) return v8::RegExp::kNone;
+  if (IsDeadCheck(i::Isolate::Current(), "v8::RegExp::GetFlags()")) {
+    return v8::RegExp::kNone;
+  }
   i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
   return static_cast<RegExp::Flags>(obj->GetFlags().value());
 }
 
 
 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);
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::Array::New()");
+  LOG_API(isolate, "Array::New");
+  ENTER_V8(isolate);
+  int real_length = length > 0 ? length : 0;
+  i::Handle<i::JSArray> obj = isolate->factory()->NewJSArray(real_length);
+  obj->set_length(*isolate->factory()->NewNumberFromInt(real_length));
   return Utils::ToLocal(obj);
 }
 
 
 uint32_t v8::Array::Length() const {
-  if (IsDeadCheck("v8::Array::Length()")) return 0;
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::Array::Length()")) return 0;
   i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
   i::Object* length = obj->length();
   if (length->IsSmi()) {
@@ -3951,7 +4265,8 @@
 
 
 Local<Object> Array::CloneElementAt(uint32_t index) {
-  ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Array::CloneElementAt()", return Local<Object>());
   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
   if (!self->HasFastElements()) {
     return Local<Object>();
@@ -3962,45 +4277,49 @@
     return Local<Object>();
   }
   i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
-  EXCEPTION_PREAMBLE();
-  ENTER_V8;
+  EXCEPTION_PREAMBLE(isolate);
+  ENTER_V8(isolate);
   i::Handle<i::JSObject> result = i::Copy(paragon_handle);
   has_pending_exception = result.is_null();
-  EXCEPTION_BAILOUT_CHECK(Local<Object>());
+  EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
   return Utils::ToLocal(result);
 }
 
 
 Local<String> v8::String::NewSymbol(const char* data, int length) {
-  EnsureInitialized("v8::String::NewSymbol()");
-  LOG_API("String::NewSymbol(char)");
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::String::NewSymbol()");
+  LOG_API(isolate, "String::NewSymbol(char)");
+  ENTER_V8(isolate);
   if (length == -1) length = i::StrLength(data);
   i::Handle<i::String> result =
-      i::Factory::LookupSymbol(i::Vector<const char>(data, length));
+      isolate->factory()->LookupSymbol(i::Vector<const char>(data, length));
   return Utils::ToLocal(result);
 }
 
 
 Local<Number> v8::Number::New(double value) {
-  EnsureInitialized("v8::Number::New()");
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::Number::New()");
   if (isnan(value)) {
     // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
     value = i::OS::nan_value();
   }
-  ENTER_V8;
-  i::Handle<i::Object> result = i::Factory::NewNumber(value);
+  ENTER_V8(isolate);
+  i::Handle<i::Object> result = isolate->factory()->NewNumber(value);
   return Utils::NumberToLocal(result);
 }
 
 
 Local<Integer> v8::Integer::New(int32_t value) {
-  EnsureInitialized("v8::Integer::New()");
+  i::Isolate* isolate = i::Isolate::UncheckedCurrent();
+  EnsureInitializedForIsolate(isolate, "v8::Integer::New()");
   if (i::Smi::IsValid(value)) {
-    return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
+    return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value),
+                                                      isolate));
   }
-  ENTER_V8;
-  i::Handle<i::Object> result = i::Factory::NewNumber(value);
+  ENTER_V8(isolate);
+  i::Handle<i::Object> result = isolate->factory()->NewNumber(value);
   return Utils::IntegerToLocal(result);
 }
 
@@ -4010,27 +4329,30 @@
   if (fits_into_int32_t) {
     return Integer::New(static_cast<int32_t>(value));
   }
-  ENTER_V8;
-  i::Handle<i::Object> result = i::Factory::NewNumber(value);
+  i::Isolate* isolate = i::Isolate::Current();
+  ENTER_V8(isolate);
+  i::Handle<i::Object> result = isolate->factory()->NewNumber(value);
   return Utils::IntegerToLocal(result);
 }
 
 
 void V8::IgnoreOutOfMemoryException() {
-  thread_local.set_ignore_out_of_memory(true);
+  EnterIsolateIfNeeded()->handle_scope_implementer()->set_ignore_out_of_memory(
+      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());
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::V8::AddMessageListener()");
+  ON_BAILOUT(isolate, "v8::V8::AddMessageListener()", return false);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
+  NeanderArray listeners(isolate->factory()->message_listeners());
   NeanderObject obj(2);
-  obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
+  obj.set(0, *isolate->factory()->NewProxy(FUNCTION_ADDR(that)));
   obj.set(1, data.IsEmpty() ?
-             i::Heap::undefined_value() :
+             isolate->heap()->undefined_value() :
              *Utils::OpenHandle(*data));
   listeners.add(obj.value());
   return true;
@@ -4038,18 +4360,19 @@
 
 
 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());
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::V8::RemoveMessageListener()");
+  ON_BAILOUT(isolate, "v8::V8::RemoveMessageListeners()", return);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
+  NeanderArray listeners(isolate->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());
+      listeners.set(i, isolate->heap()->undefined_value());
     }
   }
 }
@@ -4059,7 +4382,7 @@
       bool capture,
       int frame_limit,
       StackTrace::StackTraceOptions options) {
-  i::Top::SetCaptureStackTraceForUncaughtExceptions(
+  i::Isolate::Current()->SetCaptureStackTraceForUncaughtExceptions(
       capture,
       frame_limit,
       options);
@@ -4067,95 +4390,130 @@
 
 
 void V8::SetCounterFunction(CounterLookupCallback callback) {
-  if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
-  i::StatsTable::SetCounterFunction(callback);
+  i::Isolate* isolate = EnterIsolateIfNeeded();
+  if (IsDeadCheck(isolate, "v8::V8::SetCounterFunction()")) return;
+  isolate->stats_table()->SetCounterFunction(callback);
 }
 
 void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
-  if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
-  i::StatsTable::SetCreateHistogramFunction(callback);
+  i::Isolate* isolate = EnterIsolateIfNeeded();
+  if (IsDeadCheck(isolate, "v8::V8::SetCreateHistogramFunction()")) return;
+  isolate->stats_table()->SetCreateHistogramFunction(callback);
 }
 
 void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
-  if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
-  i::StatsTable::SetAddHistogramSampleFunction(callback);
+  i::Isolate* isolate = EnterIsolateIfNeeded();
+  if (IsDeadCheck(isolate, "v8::V8::SetAddHistogramSampleFunction()")) return;
+  isolate->stats_table()->
+      SetAddHistogramSampleFunction(callback);
 }
 
 void V8::EnableSlidingStateWindow() {
-  if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
-  i::Logger::EnableSlidingStateWindow();
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::V8::EnableSlidingStateWindow()")) return;
+  isolate->logger()->EnableSlidingStateWindow();
 }
 
 
 void V8::SetFailedAccessCheckCallbackFunction(
       FailedAccessCheckCallback callback) {
-  if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
-  i::Top::SetFailedAccessCheckCallback(callback);
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::V8::SetFailedAccessCheckCallbackFunction()")) {
+    return;
+  }
+  isolate->SetFailedAccessCheckCallback(callback);
+}
+
+void V8::AddObjectGroup(Persistent<Value>* objects,
+                        size_t length,
+                        RetainedObjectInfo* info) {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::V8::AddObjectGroup()")) return;
+  STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
+  isolate->global_handles()->AddObjectGroup(
+      reinterpret_cast<i::Object***>(objects), length, info);
 }
 
 
-void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
-  if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
+void V8::AddImplicitReferences(Persistent<Object> parent,
+                               Persistent<Value>* children,
+                               size_t length) {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::V8::AddImplicitReferences()")) return;
   STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
-  i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
+  isolate->global_handles()->AddImplicitReferences(
+      *Utils::OpenHandle(*parent),
+      reinterpret_cast<i::Object***>(children), length);
 }
 
 
 int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
-  if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
-  return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::V8::AdjustAmountOfExternalAllocatedMemory()")) {
+    return 0;
+  }
+  return isolate->heap()->AdjustAmountOfExternalAllocatedMemory(
+      change_in_bytes);
 }
 
 
 void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
-  if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
-  i::Heap::SetGlobalGCPrologueCallback(callback);
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::V8::SetGlobalGCPrologueCallback()")) return;
+  isolate->heap()->SetGlobalGCPrologueCallback(callback);
 }
 
 
 void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
-  if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
-  i::Heap::SetGlobalGCEpilogueCallback(callback);
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::V8::SetGlobalGCEpilogueCallback()")) return;
+  isolate->heap()->SetGlobalGCEpilogueCallback(callback);
 }
 
 
 void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
-  if (IsDeadCheck("v8::V8::AddGCPrologueCallback()")) return;
-  i::Heap::AddGCPrologueCallback(callback, gc_type);
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::V8::AddGCPrologueCallback()")) return;
+  isolate->heap()->AddGCPrologueCallback(callback, gc_type);
 }
 
 
 void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
-  if (IsDeadCheck("v8::V8::RemoveGCPrologueCallback()")) return;
-  i::Heap::RemoveGCPrologueCallback(callback);
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::V8::RemoveGCPrologueCallback()")) return;
+  isolate->heap()->RemoveGCPrologueCallback(callback);
 }
 
 
 void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
-  if (IsDeadCheck("v8::V8::AddGCEpilogueCallback()")) return;
-  i::Heap::AddGCEpilogueCallback(callback, gc_type);
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::V8::AddGCEpilogueCallback()")) return;
+  isolate->heap()->AddGCEpilogueCallback(callback, gc_type);
 }
 
 
 void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
-  if (IsDeadCheck("v8::V8::RemoveGCEpilogueCallback()")) return;
-  i::Heap::RemoveGCEpilogueCallback(callback);
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::V8::RemoveGCEpilogueCallback()")) return;
+  isolate->heap()->RemoveGCEpilogueCallback(callback);
 }
 
 
 void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
                                      ObjectSpace space,
                                      AllocationAction action) {
-  if (IsDeadCheck("v8::V8::AddMemoryAllocationCallback()")) return;
-  i::MemoryAllocator::AddMemoryAllocationCallback(callback,
-                                                  space,
-                                                  action);
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::V8::AddMemoryAllocationCallback()")) return;
+  isolate->memory_allocator()->AddMemoryAllocationCallback(
+      callback, space, action);
 }
 
 
 void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
-  if (IsDeadCheck("v8::V8::RemoveMemoryAllocationCallback()")) return;
-  i::MemoryAllocator::RemoveMemoryAllocationCallback(callback);
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::V8::RemoveMemoryAllocationCallback()")) return;
+  isolate->memory_allocator()->RemoveMemoryAllocationCallback(
+      callback);
 }
 
 
@@ -4175,7 +4533,7 @@
 
 bool V8::IsProfilerPaused() {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
+  return LOGGER->GetActiveProfilerModules() & PROFILER_MODULE_CPU;
 #else
   return true;
 #endif
@@ -4184,21 +4542,22 @@
 
 void V8::ResumeProfilerEx(int flags, int tag) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
+  i::Isolate* isolate = i::Isolate::Current();
   if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
     // Snapshot mode: resume modules, perform GC, then pause only
     // those modules which haven't been started prior to making a
     // snapshot.
 
     // Make a GC prior to taking a snapshot.
-    i::Heap::CollectAllGarbage(false);
+    isolate->heap()->CollectAllGarbage(false);
     // Reset snapshot flag and CPU module flags.
     flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
-    const int current_flags = i::Logger::GetActiveProfilerModules();
-    i::Logger::ResumeProfiler(flags, tag);
-    i::Heap::CollectAllGarbage(false);
-    i::Logger::PauseProfiler(~current_flags & flags, tag);
+    const int current_flags = isolate->logger()->GetActiveProfilerModules();
+    isolate->logger()->ResumeProfiler(flags, tag);
+    isolate->heap()->CollectAllGarbage(false);
+    isolate->logger()->PauseProfiler(~current_flags & flags, tag);
   } else {
-    i::Logger::ResumeProfiler(flags, tag);
+    isolate->logger()->ResumeProfiler(flags, tag);
   }
 #endif
 }
@@ -4206,14 +4565,14 @@
 
 void V8::PauseProfilerEx(int flags, int tag) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  i::Logger::PauseProfiler(flags, tag);
+  LOGGER->PauseProfiler(flags, tag);
 #endif
 }
 
 
 int V8::GetActiveProfilerModules() {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  return i::Logger::GetActiveProfilerModules();
+  return LOGGER->GetActiveProfilerModules();
 #else
   return PROFILER_MODULE_NONE;
 #endif
@@ -4223,57 +4582,95 @@
 int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
   ASSERT(max_size >= kMinimumSizeForLogLinesBuffer);
-  return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
+  return LOGGER->GetLogLines(from_pos, dest_buf, max_size);
 #endif
   return 0;
 }
 
 
 int V8::GetCurrentThreadId() {
-  API_ENTRY_CHECK("V8::GetCurrentThreadId()");
-  EnsureInitialized("V8::GetCurrentThreadId()");
-  return i::Top::thread_id();
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "V8::GetCurrentThreadId()");
+  return isolate->thread_id();
 }
 
 
 void V8::TerminateExecution(int thread_id) {
-  if (!i::V8::IsRunning()) return;
-  API_ENTRY_CHECK("V8::GetCurrentThreadId()");
+  i::Isolate* isolate = i::Isolate::Current();
+  if (!isolate->IsInitialized()) return;
+  API_ENTRY_CHECK("V8::TerminateExecution()");
   // If the thread_id identifies the current thread just terminate
   // execution right away.  Otherwise, ask the thread manager to
   // terminate the thread with the given id if any.
-  if (thread_id == i::Top::thread_id()) {
-    i::StackGuard::TerminateExecution();
+  if (thread_id == isolate->thread_id()) {
+    isolate->stack_guard()->TerminateExecution();
   } else {
-    i::ThreadManager::TerminateExecution(thread_id);
+    isolate->thread_manager()->TerminateExecution(thread_id);
   }
 }
 
 
-void V8::TerminateExecution() {
-  if (!i::V8::IsRunning()) return;
-  i::StackGuard::TerminateExecution();
+void V8::TerminateExecution(Isolate* isolate) {
+  // If no isolate is supplied, use the default isolate.
+  if (isolate != NULL) {
+    reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->TerminateExecution();
+  } else {
+    i::Isolate::GetDefaultIsolateStackGuard()->TerminateExecution();
+  }
 }
 
 
 bool V8::IsExecutionTerminating() {
-  if (!i::V8::IsRunning()) return false;
-  if (i::Top::has_scheduled_exception()) {
-    return i::Top::scheduled_exception() == i::Heap::termination_exception();
+  i::Isolate* isolate = i::Isolate::Current();
+  return IsExecutionTerminatingCheck(isolate);
+}
+
+
+Isolate* Isolate::GetCurrent() {
+  i::Isolate* isolate = i::Isolate::UncheckedCurrent();
+  return reinterpret_cast<Isolate*>(isolate);
+}
+
+
+Isolate* Isolate::New() {
+  i::Isolate* isolate = new i::Isolate();
+  return reinterpret_cast<Isolate*>(isolate);
+}
+
+
+void Isolate::Dispose() {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  if (!ApiCheck(!isolate->IsInUse(),
+                "v8::Isolate::Dispose()",
+                "Disposing the isolate that is entered by a thread.")) {
+    return;
   }
-  return false;
+  isolate->TearDown();
+}
+
+
+void Isolate::Enter() {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  isolate->Enter();
+}
+
+
+void Isolate::Exit() {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  isolate->Exit();
 }
 
 
 String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
-  EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::String::Utf8Value::Utf8Value()")) return;
   if (obj.IsEmpty()) {
     str_ = NULL;
     length_ = 0;
     return;
   }
-  ENTER_V8;
-  HandleScope scope;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   TryCatch try_catch;
   Handle<String> str = obj->ToString();
   if (str.IsEmpty()) {
@@ -4293,14 +4690,15 @@
 
 
 String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
-  EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::String::AsciiValue::AsciiValue()")) return;
   if (obj.IsEmpty()) {
     str_ = NULL;
     length_ = 0;
     return;
   }
-  ENTER_V8;
-  HandleScope scope;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   TryCatch try_catch;
   Handle<String> str = obj->ToString();
   if (str.IsEmpty()) {
@@ -4320,14 +4718,15 @@
 
 
 String::Value::Value(v8::Handle<v8::Value> obj) {
-  EnsureInitialized("v8::String::Value::Value()");
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::String::Value::Value()")) return;
   if (obj.IsEmpty()) {
     str_ = NULL;
     length_ = 0;
     return;
   }
-  ENTER_V8;
-  HandleScope scope;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
   TryCatch try_catch;
   Handle<String> str = obj->ToString();
   if (str.IsEmpty()) {
@@ -4346,14 +4745,15 @@
 }
 
 Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
-  LOG_API("RangeError");
-  ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  LOG_API(isolate, "RangeError");
+  ON_BAILOUT(isolate, "v8::Exception::RangeError()", return Local<Value>());
+  ENTER_V8(isolate);
   i::Object* error;
   {
-    HandleScope scope;
+    i::HandleScope scope(isolate);
     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
-    i::Handle<i::Object> result = i::Factory::NewRangeError(message);
+    i::Handle<i::Object> result = isolate->factory()->NewRangeError(message);
     error = *result;
   }
   i::Handle<i::Object> result(error);
@@ -4361,14 +4761,16 @@
 }
 
 Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
-  LOG_API("ReferenceError");
-  ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  LOG_API(isolate, "ReferenceError");
+  ON_BAILOUT(isolate, "v8::Exception::ReferenceError()", return Local<Value>());
+  ENTER_V8(isolate);
   i::Object* error;
   {
-    HandleScope scope;
+    i::HandleScope scope(isolate);
     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
-    i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
+    i::Handle<i::Object> result =
+        isolate->factory()->NewReferenceError(message);
     error = *result;
   }
   i::Handle<i::Object> result(error);
@@ -4376,14 +4778,15 @@
 }
 
 Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
-  LOG_API("SyntaxError");
-  ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  LOG_API(isolate, "SyntaxError");
+  ON_BAILOUT(isolate, "v8::Exception::SyntaxError()", return Local<Value>());
+  ENTER_V8(isolate);
   i::Object* error;
   {
-    HandleScope scope;
+    i::HandleScope scope(isolate);
     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
-    i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
+    i::Handle<i::Object> result = isolate->factory()->NewSyntaxError(message);
     error = *result;
   }
   i::Handle<i::Object> result(error);
@@ -4391,14 +4794,15 @@
 }
 
 Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
-  LOG_API("TypeError");
-  ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  LOG_API(isolate, "TypeError");
+  ON_BAILOUT(isolate, "v8::Exception::TypeError()", return Local<Value>());
+  ENTER_V8(isolate);
   i::Object* error;
   {
-    HandleScope scope;
+    i::HandleScope scope(isolate);
     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
-    i::Handle<i::Object> result = i::Factory::NewTypeError(message);
+    i::Handle<i::Object> result = isolate->factory()->NewTypeError(message);
     error = *result;
   }
   i::Handle<i::Object> result(error);
@@ -4406,14 +4810,15 @@
 }
 
 Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
-  LOG_API("Error");
-  ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  LOG_API(isolate, "Error");
+  ON_BAILOUT(isolate, "v8::Exception::Error()", return Local<Value>());
+  ENTER_V8(isolate);
   i::Object* error;
   {
-    HandleScope scope;
+    i::HandleScope scope(isolate);
     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
-    i::Handle<i::Object> result = i::Factory::NewError(message);
+    i::Handle<i::Object> result = isolate->factory()->NewError(message);
     error = *result;
   }
   i::Handle<i::Object> result(error);
@@ -4425,180 +4830,216 @@
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
 
-static v8::Debug::EventCallback event_callback = NULL;
-
 static void EventCallbackWrapper(const v8::Debug::EventDetails& event_details) {
-  if (event_callback) {
-    event_callback(event_details.GetEvent(),
-                   event_details.GetExecutionState(),
-                   event_details.GetEventData(),
-                   event_details.GetCallbackData());
+  i::Isolate* isolate = i::Isolate::Current();
+  if (isolate->debug_event_callback() != NULL) {
+    isolate->debug_event_callback()(event_details.GetEvent(),
+                                    event_details.GetExecutionState(),
+                                    event_details.GetEventData(),
+                                    event_details.GetCallbackData());
   }
 }
 
 
 bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
-  EnsureInitialized("v8::Debug::SetDebugEventListener()");
-  ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::Debug::SetDebugEventListener()");
+  ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false);
+  ENTER_V8(isolate);
 
-  event_callback = that;
+  isolate->set_debug_event_callback(that);
 
-  HandleScope scope;
-  i::Handle<i::Object> proxy = i::Factory::undefined_value();
+  i::HandleScope scope(isolate);
+  i::Handle<i::Object> proxy = isolate->factory()->undefined_value();
   if (that != NULL) {
-    proxy = i::Factory::NewProxy(FUNCTION_ADDR(EventCallbackWrapper));
+    proxy = isolate->factory()->NewProxy(FUNCTION_ADDR(EventCallbackWrapper));
   }
-  i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
+  isolate->debugger()->SetEventListener(proxy, Utils::OpenHandle(*data));
   return true;
 }
 
 
 bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
-  EnsureInitialized("v8::Debug::SetDebugEventListener2()");
-  ON_BAILOUT("v8::Debug::SetDebugEventListener2()", return false);
-  ENTER_V8;
-  HandleScope scope;
-  i::Handle<i::Object> proxy = i::Factory::undefined_value();
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::Debug::SetDebugEventListener2()");
+  ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener2()", return false);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
+  i::Handle<i::Object> proxy = isolate->factory()->undefined_value();
   if (that != NULL) {
-    proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
+    proxy = isolate->factory()->NewProxy(FUNCTION_ADDR(that));
   }
-  i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
+  isolate->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));
+  i::Isolate* isolate = i::Isolate::Current();
+  ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false);
+  ENTER_V8(isolate);
+  isolate->debugger()->SetEventListener(Utils::OpenHandle(*that),
+                                                      Utils::OpenHandle(*data));
   return true;
 }
 
 
-void Debug::DebugBreak() {
-  if (!i::V8::IsRunning()) return;
-  i::StackGuard::DebugBreak();
+void Debug::DebugBreak(Isolate* isolate) {
+  // If no isolate is supplied, use the default isolate.
+  if (isolate != NULL) {
+    reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->DebugBreak();
+  } else {
+    i::Isolate::GetDefaultIsolateStackGuard()->DebugBreak();
+  }
 }
 
 
-void Debug::CancelDebugBreak() {
-  i::StackGuard::Continue(i::DEBUGBREAK);
+void Debug::CancelDebugBreak(Isolate* isolate) {
+  // If no isolate is supplied, use the default isolate.
+  if (isolate != NULL) {
+    i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+    internal_isolate->stack_guard()->Continue(i::DEBUGBREAK);
+  } else {
+    i::Isolate::GetDefaultIsolateStackGuard()->Continue(i::DEBUGBREAK);
+  }
 }
 
 
-void Debug::DebugBreakForCommand(ClientData* data) {
-  if (!i::V8::IsRunning()) return;
-  i::Debugger::EnqueueDebugCommand(data);
+void Debug::DebugBreakForCommand(ClientData* data, Isolate* isolate) {
+  // If no isolate is supplied, use the default isolate.
+  if (isolate != NULL) {
+    i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+    internal_isolate->debugger()->EnqueueDebugCommand(data);
+  } else {
+    i::Isolate::GetDefaultIsolateDebugger()->EnqueueDebugCommand(data);
+  }
 }
 
 
-static v8::Debug::MessageHandler message_handler = NULL;
-
 static void MessageHandlerWrapper(const v8::Debug::Message& message) {
-  if (message_handler) {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (isolate->message_handler()) {
     v8::String::Value json(message.GetJSON());
-    message_handler(*json, json.length(), message.GetClientData());
+    (isolate->message_handler())(*json, json.length(), message.GetClientData());
   }
 }
 
 
 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
                               bool message_handler_thread) {
-  EnsureInitialized("v8::Debug::SetMessageHandler");
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::Debug::SetMessageHandler");
+  ENTER_V8(isolate);
+
   // Message handler thread not supported any more. Parameter temporally left in
-  // the API for client compatability reasons.
+  // the API for client compatibility reasons.
   CHECK(!message_handler_thread);
 
   // TODO(sgjesse) support the old message handler API through a simple wrapper.
-  message_handler = handler;
-  if (message_handler != NULL) {
-    i::Debugger::SetMessageHandler(MessageHandlerWrapper);
+  isolate->set_message_handler(handler);
+  if (handler != NULL) {
+    isolate->debugger()->SetMessageHandler(MessageHandlerWrapper);
   } else {
-    i::Debugger::SetMessageHandler(NULL);
+    isolate->debugger()->SetMessageHandler(NULL);
   }
 }
 
 
 void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
-  EnsureInitialized("v8::Debug::SetMessageHandler");
-  ENTER_V8;
-  i::Debugger::SetMessageHandler(handler);
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::Debug::SetMessageHandler");
+  ENTER_V8(isolate);
+  isolate->debugger()->SetMessageHandler(handler);
 }
 
 
 void Debug::SendCommand(const uint16_t* command, int length,
-                        ClientData* client_data) {
-  if (!i::V8::IsRunning()) return;
-  i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
-                              client_data);
+                        ClientData* client_data,
+                        Isolate* isolate) {
+  // If no isolate is supplied, use the default isolate.
+  if (isolate != NULL) {
+    i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+    internal_isolate->debugger()->ProcessCommand(
+        i::Vector<const uint16_t>(command, length), client_data);
+  } else {
+    i::Isolate::GetDefaultIsolateDebugger()->ProcessCommand(
+        i::Vector<const uint16_t>(command, length), client_data);
+  }
 }
 
 
 void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
                                    int period) {
-  EnsureInitialized("v8::Debug::SetHostDispatchHandler");
-  ENTER_V8;
-  i::Debugger::SetHostDispatchHandler(handler, period);
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::Debug::SetHostDispatchHandler");
+  ENTER_V8(isolate);
+  isolate->debugger()->SetHostDispatchHandler(handler, period);
 }
 
 
 void Debug::SetDebugMessageDispatchHandler(
     DebugMessageDispatchHandler handler, bool provide_locker) {
-  EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
-  ENTER_V8;
-  i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate,
+                              "v8::Debug::SetDebugMessageDispatchHandler");
+  ENTER_V8(isolate);
+  isolate->debugger()->SetDebugMessageDispatchHandler(
+      handler, provide_locker);
 }
 
 
 Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
                          v8::Handle<v8::Value> data) {
-  if (!i::V8::IsRunning()) return Local<Value>();
-  ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  if (!isolate->IsInitialized()) return Local<Value>();
+  ON_BAILOUT(isolate, "v8::Debug::Call()", return Local<Value>());
+  ENTER_V8(isolate);
   i::Handle<i::Object> result;
-  EXCEPTION_PREAMBLE();
+  EXCEPTION_PREAMBLE(isolate);
   if (data.IsEmpty()) {
-    result = i::Debugger::Call(Utils::OpenHandle(*fun),
-                               i::Factory::undefined_value(),
-                               &has_pending_exception);
+    result = isolate->debugger()->Call(Utils::OpenHandle(*fun),
+                                       isolate->factory()->undefined_value(),
+                                       &has_pending_exception);
   } else {
-    result = i::Debugger::Call(Utils::OpenHandle(*fun),
-                               Utils::OpenHandle(*data),
-                               &has_pending_exception);
+    result = isolate->debugger()->Call(Utils::OpenHandle(*fun),
+                                       Utils::OpenHandle(*data),
+                                       &has_pending_exception);
   }
-  EXCEPTION_BAILOUT_CHECK(Local<Value>());
+  EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
   return Utils::ToLocal(result);
 }
 
 
 Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
-  if (!i::V8::IsRunning()) return Local<Value>();
-  ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
-  ENTER_V8;
+  i::Isolate* isolate = i::Isolate::Current();
+  if (!isolate->IsInitialized()) return Local<Value>();
+  ON_BAILOUT(isolate, "v8::Debug::GetMirror()", return Local<Value>());
+  ENTER_V8(isolate);
   v8::HandleScope scope;
-  i::Debug::Load();
-  i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
-  i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
+  i::Debug* isolate_debug = isolate->debug();
+  isolate_debug->Load();
+  i::Handle<i::JSObject> debug(isolate_debug->debug_context()->global());
+  i::Handle<i::String> name =
+      isolate->factory()->LookupAsciiSymbol("MakeMirror");
   i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
   i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
   v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
   const int kArgc = 1;
   v8::Handle<v8::Value> argv[kArgc] = { obj };
-  EXCEPTION_PREAMBLE();
+  EXCEPTION_PREAMBLE(isolate);
   v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
                                               kArgc,
                                               argv);
-  EXCEPTION_BAILOUT_CHECK(Local<Value>());
+  EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
   return scope.Close(result);
 }
 
 
 bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
-  return i::Debugger::StartAgent(name, port, wait_for_connection);
+  return i::Isolate::Current()->debugger()->StartAgent(name, port,
+                                                       wait_for_connection);
 }
 
 void Debug::ProcessDebugMessages() {
@@ -4606,9 +5047,10 @@
 }
 
 Local<Context> Debug::GetDebugContext() {
-  EnsureInitialized("v8::Debug::GetDebugContext()");
-  ENTER_V8;
-  return Utils::ToLocal(i::Debugger::GetDebugContext());
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::Debug::GetDebugContext()");
+  ENTER_V8(isolate);
+  return Utils::ToLocal(i::Isolate::Current()->debugger()->GetDebugContext());
 }
 
 #endif  // ENABLE_DEBUGGER_SUPPORT
@@ -4617,115 +5059,143 @@
 #ifdef ENABLE_LOGGING_AND_PROFILING
 
 Handle<String> CpuProfileNode::GetFunctionName() const {
-  IsDeadCheck("v8::CpuProfileNode::GetFunctionName");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfileNode::GetFunctionName");
   const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
   const i::CodeEntry* entry = node->entry();
   if (!entry->has_name_prefix()) {
     return Handle<String>(ToApi<String>(
-        i::Factory::LookupAsciiSymbol(entry->name())));
+        isolate->factory()->LookupAsciiSymbol(entry->name())));
   } else {
-    return Handle<String>(ToApi<String>(i::Factory::NewConsString(
-        i::Factory::LookupAsciiSymbol(entry->name_prefix()),
-        i::Factory::LookupAsciiSymbol(entry->name()))));
+    return Handle<String>(ToApi<String>(isolate->factory()->NewConsString(
+        isolate->factory()->LookupAsciiSymbol(entry->name_prefix()),
+        isolate->factory()->LookupAsciiSymbol(entry->name()))));
   }
 }
 
 
 Handle<String> CpuProfileNode::GetScriptResourceName() const {
-  IsDeadCheck("v8::CpuProfileNode::GetScriptResourceName");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfileNode::GetScriptResourceName");
   const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
-  return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
+  return Handle<String>(ToApi<String>(isolate->factory()->LookupAsciiSymbol(
       node->entry()->resource_name())));
 }
 
 
 int CpuProfileNode::GetLineNumber() const {
-  IsDeadCheck("v8::CpuProfileNode::GetLineNumber");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfileNode::GetLineNumber");
   return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
 }
 
 
 double CpuProfileNode::GetTotalTime() const {
-  IsDeadCheck("v8::CpuProfileNode::GetTotalTime");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfileNode::GetTotalTime");
   return reinterpret_cast<const i::ProfileNode*>(this)->GetTotalMillis();
 }
 
 
 double CpuProfileNode::GetSelfTime() const {
-  IsDeadCheck("v8::CpuProfileNode::GetSelfTime");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfileNode::GetSelfTime");
   return reinterpret_cast<const i::ProfileNode*>(this)->GetSelfMillis();
 }
 
 
 double CpuProfileNode::GetTotalSamplesCount() const {
-  IsDeadCheck("v8::CpuProfileNode::GetTotalSamplesCount");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfileNode::GetTotalSamplesCount");
   return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks();
 }
 
 
 double CpuProfileNode::GetSelfSamplesCount() const {
-  IsDeadCheck("v8::CpuProfileNode::GetSelfSamplesCount");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfileNode::GetSelfSamplesCount");
   return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
 }
 
 
 unsigned CpuProfileNode::GetCallUid() const {
-  IsDeadCheck("v8::CpuProfileNode::GetCallUid");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfileNode::GetCallUid");
   return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
 }
 
 
 int CpuProfileNode::GetChildrenCount() const {
-  IsDeadCheck("v8::CpuProfileNode::GetChildrenCount");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfileNode::GetChildrenCount");
   return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
 }
 
 
 const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
-  IsDeadCheck("v8::CpuProfileNode::GetChild");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfileNode::GetChild");
   const i::ProfileNode* child =
       reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
   return reinterpret_cast<const CpuProfileNode*>(child);
 }
 
 
+void CpuProfile::Delete() {
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfile::Delete");
+  i::CpuProfiler::DeleteProfile(reinterpret_cast<i::CpuProfile*>(this));
+  if (i::CpuProfiler::GetProfilesCount() == 0 &&
+      !i::CpuProfiler::HasDetachedProfiles()) {
+    // If this was the last profile, clean up all accessory data as well.
+    i::CpuProfiler::DeleteAllProfiles();
+  }
+}
+
+
 unsigned CpuProfile::GetUid() const {
-  IsDeadCheck("v8::CpuProfile::GetUid");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfile::GetUid");
   return reinterpret_cast<const i::CpuProfile*>(this)->uid();
 }
 
 
 Handle<String> CpuProfile::GetTitle() const {
-  IsDeadCheck("v8::CpuProfile::GetTitle");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfile::GetTitle");
   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
-  return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
+  return Handle<String>(ToApi<String>(isolate->factory()->LookupAsciiSymbol(
       profile->title())));
 }
 
 
 const CpuProfileNode* CpuProfile::GetBottomUpRoot() const {
-  IsDeadCheck("v8::CpuProfile::GetBottomUpRoot");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfile::GetBottomUpRoot");
   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
   return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root());
 }
 
 
 const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
-  IsDeadCheck("v8::CpuProfile::GetTopDownRoot");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfile::GetTopDownRoot");
   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
   return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
 }
 
 
 int CpuProfiler::GetProfilesCount() {
-  IsDeadCheck("v8::CpuProfiler::GetProfilesCount");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfiler::GetProfilesCount");
   return i::CpuProfiler::GetProfilesCount();
 }
 
 
 const CpuProfile* CpuProfiler::GetProfile(int index,
                                           Handle<Value> security_token) {
-  IsDeadCheck("v8::CpuProfiler::GetProfile");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfiler::GetProfile");
   return reinterpret_cast<const CpuProfile*>(
       i::CpuProfiler::GetProfile(
           security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
@@ -4735,7 +5205,8 @@
 
 const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
                                            Handle<Value> security_token) {
-  IsDeadCheck("v8::CpuProfiler::FindProfile");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfiler::FindProfile");
   return reinterpret_cast<const CpuProfile*>(
       i::CpuProfiler::FindProfile(
           security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
@@ -4744,14 +5215,16 @@
 
 
 void CpuProfiler::StartProfiling(Handle<String> title) {
-  IsDeadCheck("v8::CpuProfiler::StartProfiling");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfiler::StartProfiling");
   i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
 }
 
 
 const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title,
                                              Handle<Value> security_token) {
-  IsDeadCheck("v8::CpuProfiler::StopProfiling");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfiler::StopProfiling");
   return reinterpret_cast<const CpuProfile*>(
       i::CpuProfiler::StopProfiling(
           security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
@@ -4759,79 +5232,62 @@
 }
 
 
+void CpuProfiler::DeleteAllProfiles() {
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfiler::DeleteAllProfiles");
+  i::CpuProfiler::DeleteAllProfiles();
+}
+
+
 static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
   return const_cast<i::HeapGraphEdge*>(
       reinterpret_cast<const i::HeapGraphEdge*>(edge));
 }
 
 HeapGraphEdge::Type HeapGraphEdge::GetType() const {
-  IsDeadCheck("v8::HeapGraphEdge::GetType");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapGraphEdge::GetType");
   return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
 }
 
 
 Handle<Value> HeapGraphEdge::GetName() const {
-  IsDeadCheck("v8::HeapGraphEdge::GetName");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapGraphEdge::GetName");
   i::HeapGraphEdge* edge = ToInternal(this);
   switch (edge->type()) {
     case i::HeapGraphEdge::kContextVariable:
     case i::HeapGraphEdge::kInternal:
     case i::HeapGraphEdge::kProperty:
     case i::HeapGraphEdge::kShortcut:
-      return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
+      return Handle<String>(ToApi<String>(isolate->factory()->LookupAsciiSymbol(
           edge->name())));
     case i::HeapGraphEdge::kElement:
     case i::HeapGraphEdge::kHidden:
-      return Handle<Number>(ToApi<Number>(i::Factory::NewNumberFromInt(
+      return Handle<Number>(ToApi<Number>(isolate->factory()->NewNumberFromInt(
           edge->index())));
     default: UNREACHABLE();
   }
-  return ImplementationUtilities::Undefined();
+  return v8::Undefined();
 }
 
 
 const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
-  IsDeadCheck("v8::HeapGraphEdge::GetFromNode");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapGraphEdge::GetFromNode");
   const i::HeapEntry* from = ToInternal(this)->From();
   return reinterpret_cast<const HeapGraphNode*>(from);
 }
 
 
 const HeapGraphNode* HeapGraphEdge::GetToNode() const {
-  IsDeadCheck("v8::HeapGraphEdge::GetToNode");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapGraphEdge::GetToNode");
   const i::HeapEntry* to = ToInternal(this)->to();
   return reinterpret_cast<const HeapGraphNode*>(to);
 }
 
 
-static i::HeapGraphPath* ToInternal(const HeapGraphPath* path) {
-  return const_cast<i::HeapGraphPath*>(
-      reinterpret_cast<const i::HeapGraphPath*>(path));
-}
-
-
-int HeapGraphPath::GetEdgesCount() const {
-  return ToInternal(this)->path()->length();
-}
-
-
-const HeapGraphEdge* HeapGraphPath::GetEdge(int index) const {
-  return reinterpret_cast<const HeapGraphEdge*>(
-      ToInternal(this)->path()->at(index));
-}
-
-
-const HeapGraphNode* HeapGraphPath::GetFromNode() const {
-  return GetEdgesCount() > 0 ? GetEdge(0)->GetFromNode() : NULL;
-}
-
-
-const HeapGraphNode* HeapGraphPath::GetToNode() const {
-  const int count = GetEdgesCount();
-  return count > 0 ? GetEdge(count - 1)->GetToNode() : NULL;
-}
-
-
 static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
   return const_cast<i::HeapEntry*>(
       reinterpret_cast<const i::HeapEntry*>(entry));
@@ -4839,156 +5295,146 @@
 
 
 HeapGraphNode::Type HeapGraphNode::GetType() const {
-  IsDeadCheck("v8::HeapGraphNode::GetType");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapGraphNode::GetType");
   return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
 }
 
 
 Handle<String> HeapGraphNode::GetName() const {
-  IsDeadCheck("v8::HeapGraphNode::GetName");
-  return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapGraphNode::GetName");
+  return Handle<String>(ToApi<String>(isolate->factory()->LookupAsciiSymbol(
       ToInternal(this)->name())));
 }
 
 
 uint64_t HeapGraphNode::GetId() const {
-  IsDeadCheck("v8::HeapGraphNode::GetId");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapGraphNode::GetId");
   ASSERT(ToInternal(this)->snapshot()->type() != i::HeapSnapshot::kAggregated);
   return ToInternal(this)->id();
 }
 
 
 int HeapGraphNode::GetInstancesCount() const {
-  IsDeadCheck("v8::HeapGraphNode::GetInstancesCount");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapGraphNode::GetInstancesCount");
   ASSERT(ToInternal(this)->snapshot()->type() == i::HeapSnapshot::kAggregated);
   return static_cast<int>(ToInternal(this)->id());
 }
 
 
 int HeapGraphNode::GetSelfSize() const {
-  IsDeadCheck("v8::HeapGraphNode::GetSelfSize");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapGraphNode::GetSelfSize");
   return ToInternal(this)->self_size();
 }
 
 
 int HeapGraphNode::GetRetainedSize(bool exact) const {
-  IsDeadCheck("v8::HeapSnapshot::GetRetainedSize");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapSnapshot::GetRetainedSize");
   return ToInternal(this)->RetainedSize(exact);
 }
 
 
 int HeapGraphNode::GetChildrenCount() const {
-  IsDeadCheck("v8::HeapSnapshot::GetChildrenCount");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapSnapshot::GetChildrenCount");
   return ToInternal(this)->children().length();
 }
 
 
 const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
-  IsDeadCheck("v8::HeapSnapshot::GetChild");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapSnapshot::GetChild");
   return reinterpret_cast<const HeapGraphEdge*>(
       &ToInternal(this)->children()[index]);
 }
 
 
 int HeapGraphNode::GetRetainersCount() const {
-  IsDeadCheck("v8::HeapSnapshot::GetRetainersCount");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapSnapshot::GetRetainersCount");
   return ToInternal(this)->retainers().length();
 }
 
 
 const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const {
-  IsDeadCheck("v8::HeapSnapshot::GetRetainer");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapSnapshot::GetRetainer");
   return reinterpret_cast<const HeapGraphEdge*>(
       ToInternal(this)->retainers()[index]);
 }
 
 
-int HeapGraphNode::GetRetainingPathsCount() const {
-  IsDeadCheck("v8::HeapSnapshot::GetRetainingPathsCount");
-  return ToInternal(this)->GetRetainingPaths()->length();
-}
-
-
-const HeapGraphPath* HeapGraphNode::GetRetainingPath(int index) const {
-  IsDeadCheck("v8::HeapSnapshot::GetRetainingPath");
-  return reinterpret_cast<const HeapGraphPath*>(
-      ToInternal(this)->GetRetainingPaths()->at(index));
-}
-
-
 const HeapGraphNode* HeapGraphNode::GetDominatorNode() const {
-  IsDeadCheck("v8::HeapSnapshot::GetDominatorNode");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapSnapshot::GetDominatorNode");
   return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->dominator());
 }
 
 
-const HeapGraphNode* HeapSnapshotsDiff::GetAdditionsRoot() const {
-  IsDeadCheck("v8::HeapSnapshotsDiff::GetAdditionsRoot");
-  i::HeapSnapshotsDiff* diff =
-      const_cast<i::HeapSnapshotsDiff*>(
-          reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
-  return reinterpret_cast<const HeapGraphNode*>(diff->additions_root());
-}
-
-
-const HeapGraphNode* HeapSnapshotsDiff::GetDeletionsRoot() const {
-  IsDeadCheck("v8::HeapSnapshotsDiff::GetDeletionsRoot");
-  i::HeapSnapshotsDiff* diff =
-      const_cast<i::HeapSnapshotsDiff*>(
-          reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
-  return reinterpret_cast<const HeapGraphNode*>(diff->deletions_root());
-}
-
-
 static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
   return const_cast<i::HeapSnapshot*>(
       reinterpret_cast<const i::HeapSnapshot*>(snapshot));
 }
 
 
+void HeapSnapshot::Delete() {
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapSnapshot::Delete");
+  if (i::HeapProfiler::GetSnapshotsCount() > 1) {
+    ToInternal(this)->Delete();
+  } else {
+    // If this is the last snapshot, clean up all accessory data as well.
+    i::HeapProfiler::DeleteAllSnapshots();
+  }
+}
+
+
 HeapSnapshot::Type HeapSnapshot::GetType() const {
-  IsDeadCheck("v8::HeapSnapshot::GetType");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapSnapshot::GetType");
   return static_cast<HeapSnapshot::Type>(ToInternal(this)->type());
 }
 
 
 unsigned HeapSnapshot::GetUid() const {
-  IsDeadCheck("v8::HeapSnapshot::GetUid");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapSnapshot::GetUid");
   return ToInternal(this)->uid();
 }
 
 
 Handle<String> HeapSnapshot::GetTitle() const {
-  IsDeadCheck("v8::HeapSnapshot::GetTitle");
-  return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapSnapshot::GetTitle");
+  return Handle<String>(ToApi<String>(isolate->factory()->LookupAsciiSymbol(
       ToInternal(this)->title())));
 }
 
 
 const HeapGraphNode* HeapSnapshot::GetRoot() const {
-  IsDeadCheck("v8::HeapSnapshot::GetHead");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapSnapshot::GetHead");
   return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
 }
 
 
 const HeapGraphNode* HeapSnapshot::GetNodeById(uint64_t id) const {
-  IsDeadCheck("v8::HeapSnapshot::GetNodeById");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapSnapshot::GetNodeById");
   return reinterpret_cast<const HeapGraphNode*>(
       ToInternal(this)->GetEntryById(id));
 }
 
 
-const HeapSnapshotsDiff* HeapSnapshot::CompareWith(
-    const HeapSnapshot* snapshot) const {
-  IsDeadCheck("v8::HeapSnapshot::CompareWith");
-  return reinterpret_cast<const HeapSnapshotsDiff*>(
-      ToInternal(this)->CompareWith(ToInternal(snapshot)));
-}
-
-
 void HeapSnapshot::Serialize(OutputStream* stream,
                              HeapSnapshot::SerializationFormat format) const {
-  IsDeadCheck("v8::HeapSnapshot::Serialize");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapSnapshot::Serialize");
   ApiCheck(format == kJSON,
            "v8::HeapSnapshot::Serialize",
            "Unknown serialization format");
@@ -5004,20 +5450,23 @@
 
 
 int HeapProfiler::GetSnapshotsCount() {
-  IsDeadCheck("v8::HeapProfiler::GetSnapshotsCount");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapProfiler::GetSnapshotsCount");
   return i::HeapProfiler::GetSnapshotsCount();
 }
 
 
 const HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
-  IsDeadCheck("v8::HeapProfiler::GetSnapshot");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapProfiler::GetSnapshot");
   return reinterpret_cast<const HeapSnapshot*>(
       i::HeapProfiler::GetSnapshot(index));
 }
 
 
 const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
-  IsDeadCheck("v8::HeapProfiler::FindSnapshot");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapProfiler::FindSnapshot");
   return reinterpret_cast<const HeapSnapshot*>(
       i::HeapProfiler::FindSnapshot(uid));
 }
@@ -5026,7 +5475,8 @@
 const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title,
                                                HeapSnapshot::Type type,
                                                ActivityControl* control) {
-  IsDeadCheck("v8::HeapProfiler::TakeSnapshot");
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapProfiler::TakeSnapshot");
   i::HeapSnapshot::Type internal_type = i::HeapSnapshot::kFull;
   switch (type) {
     case HeapSnapshot::kFull:
@@ -5043,6 +5493,20 @@
           *Utils::OpenHandle(*title), internal_type, control));
 }
 
+
+void HeapProfiler::DeleteAllSnapshots() {
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapProfiler::DeleteAllSnapshots");
+  i::HeapProfiler::DeleteAllSnapshots();
+}
+
+
+void HeapProfiler::DefineWrapperClass(uint16_t class_id,
+                                      WrapperInfoCallback callback) {
+  i::Isolate::Current()->heap_profiler()->DefineWrapperClass(class_id,
+                                                             callback);
+}
+
 #endif  // ENABLE_LOGGING_AND_PROFILING
 
 
@@ -5107,27 +5571,23 @@
 }
 
 
-namespace internal {
-
-
-HandleScopeImplementer* HandleScopeImplementer::instance() {
-  return &thread_local;
+void Testing::DeoptimizeAll() {
+  internal::Deoptimizer::DeoptimizeAll();
 }
 
 
+namespace internal {
+
+
 void HandleScopeImplementer::FreeThreadResources() {
-  thread_local.Free();
+  Free();
 }
 
 
 char* HandleScopeImplementer::ArchiveThread(char* storage) {
-  return thread_local.ArchiveThreadHelper(storage);
-}
-
-
-char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
+  Isolate* isolate = Isolate::Current();
   v8::ImplementationUtilities::HandleScopeData* current =
-      v8::ImplementationUtilities::CurrentHandleScope();
+      isolate->handle_scope_data();
   handle_scope_data_ = *current;
   memcpy(storage, this, sizeof(*this));
 
@@ -5139,18 +5599,13 @@
 
 
 int HandleScopeImplementer::ArchiveSpacePerThread() {
-  return sizeof(thread_local);
+  return sizeof(HandleScopeImplementer);
 }
 
 
 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_;
+  *Isolate::Current()->handle_scope_data() = handle_scope_data_;
   return storage + ArchiveSpacePerThread();
 }
 
@@ -5176,16 +5631,16 @@
 
 void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
   v8::ImplementationUtilities::HandleScopeData* current =
-      v8::ImplementationUtilities::CurrentHandleScope();
-  thread_local.handle_scope_data_ = *current;
-  thread_local.IterateThis(v);
+      Isolate::Current()->handle_scope_data();
+  handle_scope_data_ = *current;
+  IterateThis(v);
 }
 
 
 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
-  HandleScopeImplementer* thread_local =
+  HandleScopeImplementer* scope_implementer =
       reinterpret_cast<HandleScopeImplementer*>(storage);
-  thread_local->IterateThis(v);
+  scope_implementer->IterateThis(v);
   return storage + ArchiveSpacePerThread();
 }
 
diff --git a/src/api.h b/src/api.h
index d07d75b..6d46713 100644
--- a/src/api.h
+++ b/src/api.h
@@ -122,7 +122,7 @@
 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(
+  return FACTORY->NewProxy(
       reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(obj)));
 }
 
@@ -157,7 +157,6 @@
   RegisteredExtension* next_auto_;
   ExtensionTraversalState state_;
   static RegisteredExtension* first_extension_;
-  static RegisteredExtension* first_auto_extension_;
 };
 
 
@@ -321,16 +320,83 @@
 
 namespace internal {
 
+// Tracks string usage to help make better decisions when
+// externalizing strings.
+//
+// Implementation note: internally this class only tracks fresh
+// strings and keeps a single use counter for them.
+class StringTracker {
+ public:
+  // Records that the given string's characters were copied to some
+  // external buffer. If this happens often we should honor
+  // externalization requests for the string.
+  void RecordWrite(Handle<String> string) {
+    Address address = reinterpret_cast<Address>(*string);
+    Address top = isolate_->heap()->NewSpaceTop();
+    if (IsFreshString(address, top)) {
+      IncrementUseCount(top);
+    }
+  }
+
+  // Estimates freshness and use frequency of the given string based
+  // on how close it is to the new space top and the recorded usage
+  // history.
+  inline bool IsFreshUnusedString(Handle<String> string) {
+    Address address = reinterpret_cast<Address>(*string);
+    Address top = isolate_->heap()->NewSpaceTop();
+    return IsFreshString(address, top) && IsUseCountLow(top);
+  }
+
+ private:
+  StringTracker() : use_count_(0), last_top_(NULL), isolate_(NULL) { }
+
+  static inline bool IsFreshString(Address string, Address top) {
+    return top - kFreshnessLimit <= string && string <= top;
+  }
+
+  inline bool IsUseCountLow(Address top) {
+    if (last_top_ != top) return true;
+    return use_count_ < kUseLimit;
+  }
+
+  inline void IncrementUseCount(Address top) {
+    if (last_top_ != top) {
+      use_count_ = 0;
+      last_top_ = top;
+    }
+    ++use_count_;
+  }
+
+  // Single use counter shared by all fresh strings.
+  int use_count_;
+
+  // Last new space top when the use count above was valid.
+  Address last_top_;
+
+  Isolate* isolate_;
+
+  // How close to the new space top a fresh string has to be.
+  static const int kFreshnessLimit = 1024;
+
+  // The number of uses required to consider a string useful.
+  static const int kUseLimit = 32;
+
+  friend class Isolate;
+
+  DISALLOW_COPY_AND_ASSIGN(StringTracker);
+};
+
+
 // 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
+// neat in some ways, but it would expose internal 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
+// An isolate has a single instance of this class to hold the current thread's
+// data. In 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 {
+ISOLATED_CLASS HandleScopeImplementer {
  public:
 
   HandleScopeImplementer()
@@ -341,16 +407,14 @@
         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);
-  static void FreeThreadResources();
+  char* RestoreThread(char* from);
+  char* ArchiveThread(char* to);
+  void FreeThreadResources();
 
   // Garbage collection support.
-  static void Iterate(v8::internal::ObjectVisitor* v);
+  void Iterate(v8::internal::ObjectVisitor* v);
   static char* Iterate(v8::internal::ObjectVisitor* v, char* data);
 
 
diff --git a/src/apiutils.h b/src/apiutils.h
index 9683aa4..68579af 100644
--- a/src/apiutils.h
+++ b/src/apiutils.h
@@ -31,11 +31,6 @@
 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_;
   }
@@ -68,8 +63,6 @@
   // to access the HandleScope data.
   typedef v8::HandleScope::Data HandleScopeData;
 
-  static HandleScopeData* CurrentHandleScope();
-
 #ifdef DEBUG
   static void ZapHandleRange(internal::Object** begin, internal::Object** end);
 #endif
diff --git a/src/arguments.h b/src/arguments.h
index 5cf8dea..c80548f 100644
--- a/src/arguments.h
+++ b/src/arguments.h
@@ -65,7 +65,6 @@
   int length() const { return length_; }
 
   Object** arguments() { return arguments_; }
-
  private:
   int length_;
   Object** arguments_;
@@ -77,15 +76,16 @@
 // can.
 class CustomArguments : public Relocatable {
  public:
-  inline CustomArguments(Object* data,
+  inline CustomArguments(Isolate* isolate,
+                         Object* data,
                          Object* self,
-                         JSObject* holder) {
+                         JSObject* holder) : Relocatable(isolate) {
     values_[2] = self;
     values_[1] = holder;
     values_[0] = data;
   }
 
-  inline CustomArguments() {
+  inline explicit CustomArguments(Isolate* isolate) : Relocatable(isolate) {
 #ifdef DEBUG
     for (size_t i = 0; i < ARRAY_SIZE(values_); i++) {
       values_[i] = reinterpret_cast<Object*>(kZapValue);
@@ -99,6 +99,8 @@
   Object* values_[3];
 };
 
+#define RUNTIME_CALLING_CONVENTION Arguments args, Isolate* isolate
+#define RUNTIME_GET_ISOLATE ASSERT(isolate == Isolate::Current())
 
 } }  // namespace v8::internal
 
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index 3b81102..bd76d9a 100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -203,11 +203,12 @@
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     visitor->VisitExternalReference(target_reference_address());
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  } else if (Debug::has_break_points() &&
-             ((RelocInfo::IsJSReturn(mode) &&
+  // TODO(isolates): Get a cached isolate below.
+  } else if (((RelocInfo::IsJSReturn(mode) &&
               IsPatchedReturnSequence()) ||
              (RelocInfo::IsDebugBreakSlot(mode) &&
-              IsPatchedDebugBreakSlotSequence()))) {
+              IsPatchedDebugBreakSlotSequence())) &&
+             Isolate::Current()->debug()->has_break_points()) {
     visitor->VisitDebugTarget(this);
 #endif
   } else if (mode == RelocInfo::RUNTIME_ENTRY) {
@@ -217,10 +218,10 @@
 
 
 template<typename StaticVisitor>
-void RelocInfo::Visit() {
+void RelocInfo::Visit(Heap* heap) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
-    StaticVisitor::VisitPointer(target_object_address());
+    StaticVisitor::VisitPointer(heap, target_object_address());
   } else if (RelocInfo::IsCodeTarget(mode)) {
     StaticVisitor::VisitCodeTarget(this);
   } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
@@ -228,7 +229,7 @@
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     StaticVisitor::VisitExternalReference(target_reference_address());
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  } else if (Debug::has_break_points() &&
+  } else if (heap->isolate()->debug()->has_break_points() &&
              ((RelocInfo::IsJSReturn(mode) &&
               IsPatchedReturnSequence()) ||
              (RelocInfo::IsDebugBreakSlot(mode) &&
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index c91d4ba..be34df9 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -44,11 +44,11 @@
 namespace v8 {
 namespace internal {
 
-// Safe default is no features.
-unsigned CpuFeatures::supported_ = 0;
-unsigned CpuFeatures::enabled_ = 0;
-unsigned CpuFeatures::found_by_runtime_probing_ = 0;
-
+CpuFeatures::CpuFeatures()
+    : supported_(0),
+      enabled_(0),
+      found_by_runtime_probing_(0) {
+}
 
 #ifdef __arm__
 static uint64_t CpuFeaturesImpliedByCompiler() {
@@ -148,7 +148,7 @@
   rm_ = no_reg;
   // Verify all Objects referred by code are NOT in new space.
   Object* obj = *handle;
-  ASSERT(!Heap::InNewSpace(obj));
+  ASSERT(!HEAP->InNewSpace(obj));
   if (obj->IsHeapObject()) {
     imm32_ = reinterpret_cast<intptr_t>(handle.location());
     rmode_ = RelocInfo::EMBEDDED_OBJECT;
@@ -266,21 +266,22 @@
 
 // Spare buffer.
 static const int kMinimalBufferSize = 4*KB;
-static byte* spare_buffer_ = NULL;
 
 
 Assembler::Assembler(void* buffer, int buffer_size)
-    : positions_recorder_(this),
-      allow_peephole_optimization_(false) {
+    : AssemblerBase(Isolate::Current()),
+      positions_recorder_(this),
+      allow_peephole_optimization_(false),
+      emit_debug_code_(FLAG_debug_code) {
   allow_peephole_optimization_ = FLAG_peephole_optimization;
   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 (isolate()->assembler_spare_buffer() != NULL) {
+        buffer = isolate()->assembler_spare_buffer();
+        isolate()->set_assembler_spare_buffer(NULL);
       }
     }
     if (buffer == NULL) {
@@ -315,8 +316,9 @@
 Assembler::~Assembler() {
   ASSERT(const_pool_blocked_nesting_ == 0);
   if (own_buffer_) {
-    if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
-      spare_buffer_ = buffer_;
+    if (isolate()->assembler_spare_buffer() == NULL &&
+        buffer_size_ == kMinimalBufferSize) {
+      isolate()->set_assembler_spare_buffer(buffer_);
     } else {
       DeleteArray(buffer_);
     }
@@ -713,7 +715,7 @@
         *instr ^= kMovMvnFlip;
         return true;
       } else if ((*instr & kMovLeaveCCMask) == kMovLeaveCCPattern) {
-        if (CpuFeatures::IsSupported(ARMv7)) {
+        if (Isolate::Current()->cpu_features()->IsSupported(ARMv7)) {
           if (imm32 < 0x10000) {
             *instr ^= kMovwLeaveCCFlip;
             *instr |= EncodeMovwImmediate(imm32);
@@ -767,11 +769,36 @@
 }
 
 
-bool Operand::is_single_instruction() const {
+bool Operand::is_single_instruction(Instr instr) const {
   if (rm_.is_valid()) return true;
-  if (must_use_constant_pool()) return false;
   uint32_t dummy1, dummy2;
-  return fits_shifter(imm32_, &dummy1, &dummy2, NULL);
+  if (must_use_constant_pool() ||
+      !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) {
+    // The immediate operand cannot be encoded as a shifter operand, or use of
+    // constant pool is required. For a mov instruction not setting the
+    // condition code additional instruction conventions can be used.
+    if ((instr & ~kCondMask) == 13*B21) {  // mov, S not set
+      if (must_use_constant_pool() ||
+          !Isolate::Current()->cpu_features()->IsSupported(ARMv7)) {
+        // mov instruction will be an ldr from constant pool (one instruction).
+        return true;
+      } else {
+        // mov instruction will be a mov or movw followed by movt (two
+        // instructions).
+        return false;
+      }
+    } else {
+      // If this is not a mov or mvn instruction there will always an additional
+      // instructions - either mov or ldr. The mov might actually be two
+      // instructions mov or movw followed by movt so including the actual
+      // instruction two or three instructions will be generated.
+      return false;
+    }
+  } else {
+    // No use of constant pool and the immediate operand can be encoded as a
+    // shifter operand.
+    return true;
+  }
 }
 
 
@@ -794,7 +821,8 @@
       CHECK(!rn.is(ip));  // rn should never be ip, or will be trashed
       Condition cond = Instruction::ConditionField(instr);
       if ((instr & ~kCondMask) == 13*B21) {  // mov, S not set
-        if (x.must_use_constant_pool() || !CpuFeatures::IsSupported(ARMv7)) {
+        if (x.must_use_constant_pool() ||
+            !isolate()->cpu_features()->IsSupported(ARMv7)) {
           RecordRelocInfo(x.rmode_, x.imm32_);
           ldr(rd, MemOperand(pc, 0), cond);
         } else {
@@ -1237,7 +1265,7 @@
                      const Operand& src,
                      Condition cond) {
   // v6 and above.
-  ASSERT(CpuFeatures::IsSupported(ARMv7));
+  ASSERT(isolate()->cpu_features()->IsSupported(ARMv7));
   ASSERT(!dst.is(pc) && !src.rm_.is(pc));
   ASSERT((satpos >= 0) && (satpos <= 31));
   ASSERT((src.shift_op_ == ASR) || (src.shift_op_ == LSL));
@@ -1265,7 +1293,7 @@
                      int width,
                      Condition cond) {
   // v7 and above.
-  ASSERT(CpuFeatures::IsSupported(ARMv7));
+  ASSERT(isolate()->cpu_features()->IsSupported(ARMv7));
   ASSERT(!dst.is(pc) && !src.is(pc));
   ASSERT((lsb >= 0) && (lsb <= 31));
   ASSERT((width >= 1) && (width <= (32 - lsb)));
@@ -1285,7 +1313,7 @@
                      int width,
                      Condition cond) {
   // v7 and above.
-  ASSERT(CpuFeatures::IsSupported(ARMv7));
+  ASSERT(isolate()->cpu_features()->IsSupported(ARMv7));
   ASSERT(!dst.is(pc) && !src.is(pc));
   ASSERT((lsb >= 0) && (lsb <= 31));
   ASSERT((width >= 1) && (width <= (32 - lsb)));
@@ -1300,7 +1328,7 @@
 //   bfc dst, #lsb, #width
 void Assembler::bfc(Register dst, int lsb, int width, Condition cond) {
   // v7 and above.
-  ASSERT(CpuFeatures::IsSupported(ARMv7));
+  ASSERT(isolate()->cpu_features()->IsSupported(ARMv7));
   ASSERT(!dst.is(pc));
   ASSERT((lsb >= 0) && (lsb <= 31));
   ASSERT((width >= 1) && (width <= (32 - lsb)));
@@ -1319,7 +1347,7 @@
                     int width,
                     Condition cond) {
   // v7 and above.
-  ASSERT(CpuFeatures::IsSupported(ARMv7));
+  ASSERT(isolate()->cpu_features()->IsSupported(ARMv7));
   ASSERT(!dst.is(pc) && !src.is(pc));
   ASSERT((lsb >= 0) && (lsb <= 31));
   ASSERT((width >= 1) && (width <= (32 - lsb)));
@@ -1591,7 +1619,7 @@
 
 void Assembler::ldrd(Register dst1, Register dst2,
                      const MemOperand& src, Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(ARMv7));
+  ASSERT(isolate()->cpu_features()->IsEnabled(ARMv7));
   ASSERT(src.rm().is(no_reg));
   ASSERT(!dst1.is(lr));  // r14.
   ASSERT_EQ(0, dst1.code() % 2);
@@ -1606,7 +1634,7 @@
   ASSERT(!src1.is(lr));  // r14.
   ASSERT_EQ(0, src1.code() % 2);
   ASSERT_EQ(src1.code() + 1, src2.code());
-  ASSERT(CpuFeatures::IsEnabled(ARMv7));
+  ASSERT(isolate()->cpu_features()->IsEnabled(ARMv7));
   addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
 }
 
@@ -1842,7 +1870,7 @@
   // Instruction details available in ARM DDI 0406A, A8-628.
   // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
   // Vdst(15-12) | 1011(11-8) | offset
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   int u = 1;
   if (offset < 0) {
     offset = -offset;
@@ -1884,7 +1912,7 @@
   // Instruction details available in ARM DDI 0406A, A8-628.
   // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
   // Vdst(15-12) | 1010(11-8) | offset
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   int u = 1;
   if (offset < 0) {
     offset = -offset;
@@ -1928,7 +1956,7 @@
   // Instruction details available in ARM DDI 0406A, A8-786.
   // cond(31-28) | 1101(27-24)| U000(23-20) | | Rbase(19-16) |
   // Vsrc(15-12) | 1011(11-8) | (offset/4)
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   int u = 1;
   if (offset < 0) {
     offset = -offset;
@@ -1969,7 +1997,7 @@
   // Instruction details available in ARM DDI 0406A, A8-786.
   // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) |
   // Vdst(15-12) | 1010(11-8) | (offset/4)
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   int u = 1;
   if (offset < 0) {
     offset = -offset;
@@ -2015,7 +2043,7 @@
 // Only works for little endian floating point formats.
 // We don't support VFP on the mixed endian floating point platform.
 static bool FitsVMOVDoubleImmediate(double d, uint32_t *encoding) {
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(Isolate::Current()->cpu_features()->IsEnabled(VFP3));
 
   // VMOV can accept an immediate of the form:
   //
@@ -2068,7 +2096,7 @@
                      const Condition cond) {
   // Dd = immediate
   // Instruction details available in ARM DDI 0406B, A8-640.
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
 
   uint32_t enc;
   if (FitsVMOVDoubleImmediate(imm, &enc)) {
@@ -2105,7 +2133,7 @@
                      const Condition cond) {
   // Sd = Sm
   // Instruction details available in ARM DDI 0406B, A8-642.
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   int sd, d, sm, m;
   dst.split_code(&sd, &d);
   src.split_code(&sm, &m);
@@ -2118,7 +2146,7 @@
                      const Condition cond) {
   // Dd = Dm
   // Instruction details available in ARM DDI 0406B, A8-642.
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(cond | 0xE*B24 | 0xB*B20 |
        dst.code()*B12 | 0x5*B9 | B8 | B6 | src.code());
 }
@@ -2132,7 +2160,7 @@
   // Instruction details available in ARM DDI 0406A, A8-646.
   // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
   // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   ASSERT(!src1.is(pc) && !src2.is(pc));
   emit(cond | 0xC*B24 | B22 | src2.code()*B16 |
        src1.code()*B12 | 0xB*B8 | B4 | dst.code());
@@ -2147,7 +2175,7 @@
   // Instruction details available in ARM DDI 0406A, A8-646.
   // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
   // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   ASSERT(!dst1.is(pc) && !dst2.is(pc));
   emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 |
        dst1.code()*B12 | 0xB*B8 | B4 | src.code());
@@ -2161,7 +2189,7 @@
   // Instruction details available in ARM DDI 0406A, A8-642.
   // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) |
   // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   ASSERT(!src.is(pc));
   int sn, n;
   dst.split_code(&sn, &n);
@@ -2176,7 +2204,7 @@
   // Instruction details available in ARM DDI 0406A, A8-642.
   // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) |
   // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   ASSERT(!dst.is(pc));
   int sn, n;
   src.split_code(&sn, &n);
@@ -2301,7 +2329,7 @@
                              const SwVfpRegister src,
                              VFPConversionMode mode,
                              const Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(EncodeVCVT(F64, dst.code(), S32, src.code(), mode, cond));
 }
 
@@ -2310,7 +2338,7 @@
                              const SwVfpRegister src,
                              VFPConversionMode mode,
                              const Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(EncodeVCVT(F32, dst.code(), S32, src.code(), mode, cond));
 }
 
@@ -2319,7 +2347,7 @@
                              const SwVfpRegister src,
                              VFPConversionMode mode,
                              const Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(EncodeVCVT(F64, dst.code(), U32, src.code(), mode, cond));
 }
 
@@ -2328,7 +2356,7 @@
                              const DwVfpRegister src,
                              VFPConversionMode mode,
                              const Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(EncodeVCVT(S32, dst.code(), F64, src.code(), mode, cond));
 }
 
@@ -2337,7 +2365,7 @@
                              const DwVfpRegister src,
                              VFPConversionMode mode,
                              const Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(EncodeVCVT(U32, dst.code(), F64, src.code(), mode, cond));
 }
 
@@ -2346,7 +2374,7 @@
                              const SwVfpRegister src,
                              VFPConversionMode mode,
                              const Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(EncodeVCVT(F64, dst.code(), F32, src.code(), mode, cond));
 }
 
@@ -2355,11 +2383,19 @@
                              const DwVfpRegister src,
                              VFPConversionMode mode,
                              const Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond));
 }
 
 
+void Assembler::vneg(const DwVfpRegister dst,
+                     const DwVfpRegister src,
+                     const Condition cond) {
+  emit(cond | 0xE*B24 | 0xB*B20 | B16 | dst.code()*B12 |
+       0x5*B9 | B8 | B6 | src.code());
+}
+
+
 void Assembler::vabs(const DwVfpRegister dst,
                      const DwVfpRegister src,
                      const Condition cond) {
@@ -2377,7 +2413,7 @@
   // Instruction details available in ARM DDI 0406A, A8-536.
   // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
   // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 |
        dst.code()*B12 | 0x5*B9 | B8 | src2.code());
 }
@@ -2392,7 +2428,7 @@
   // Instruction details available in ARM DDI 0406A, A8-784.
   // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
   // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 1(6) | M=?(5) | 0(4) | Vm(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 |
        dst.code()*B12 | 0x5*B9 | B8 | B6 | src2.code());
 }
@@ -2407,7 +2443,7 @@
   // Instruction details available in ARM DDI 0406A, A8-784.
   // cond(31-28) | 11100(27-23)| D=?(22) | 10(21-20) | Vn(19-16) |
   // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(cond | 0xE*B24 | 0x2*B20 | src1.code()*B16 |
        dst.code()*B12 | 0x5*B9 | B8 | src2.code());
 }
@@ -2422,7 +2458,7 @@
   // Instruction details available in ARM DDI 0406A, A8-584.
   // cond(31-28) | 11101(27-23)| D=?(22) | 00(21-20) | Vn(19-16) |
   // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=? | 0(6) | M=?(5) | 0(4) | Vm(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(cond | 0xE*B24 | B23 | src1.code()*B16 |
        dst.code()*B12 | 0x5*B9 | B8 | src2.code());
 }
@@ -2435,7 +2471,7 @@
   // Instruction details available in ARM DDI 0406A, A8-570.
   // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0100 (19-16) |
   // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | Vm(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 |
        src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code());
 }
@@ -2448,7 +2484,7 @@
   // Instruction details available in ARM DDI 0406A, A8-570.
   // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0101 (19-16) |
   // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | 0000(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   ASSERT(src2 == 0.0);
   emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | B16 |
        src1.code()*B12 | 0x5*B9 | B8 | B6);
@@ -2459,7 +2495,7 @@
   // Instruction details available in ARM DDI 0406A, A8-652.
   // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) |
   // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(cond | 0xE*B24 | 0xE*B20 |  B16 |
        dst.code()*B12 | 0xA*B8 | B4);
 }
@@ -2469,7 +2505,7 @@
   // Instruction details available in ARM DDI 0406A, A8-652.
   // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) |
   // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(cond | 0xE*B24 | 0xF*B20 |  B16 |
        dst.code()*B12 | 0xA*B8 | B4);
 }
@@ -2480,7 +2516,7 @@
                       const Condition cond) {
   // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0001 (19-16) |
   // Vd(15-12) | 101(11-9) | sz(8)=1 | 11 (7-6) | M(5)=? | 0(4) | Vm(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(VFP3));
   emit(cond | 0xE*B24 | B23 | 0x3*B20 | B16 |
        dst.code()*B12 | 0x5*B9 | B8 | 3*B6 | src.code());
 }
@@ -2633,7 +2669,7 @@
         Serializer::TooLateToEnableNow();
       }
 #endif
-      if (!Serializer::enabled() && !FLAG_debug_code) {
+      if (!Serializer::enabled() && !emit_debug_code()) {
         return;
       }
     }
@@ -2711,8 +2747,8 @@
   RecordComment("[ Constant Pool");
 
   // Put down constant pool marker "Undefined instruction" as specified by
-  // A3.1 Instruction set encoding.
-  emit(0x03000000 | num_prinfo_);
+  // A5.6 (ARMv7) Instruction set encoding.
+  emit(kConstantPoolMarker | num_prinfo_);
 
   // Emit constant pool entries.
   for (int i = 0; i < num_prinfo_; i++) {
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index f5eb507..91e6244 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -389,8 +389,11 @@
   INLINE(bool is_reg() const);
 
   // Return true if this operand fits in one instruction so that no
-  // 2-instruction solution with a load into the ip register is necessary.
-  bool is_single_instruction() const;
+  // 2-instruction solution with a load into the ip register is necessary. If
+  // the instruction this operand is used for is a MOV or MVN instruction the
+  // actual instruction to use is required for this calculation. For other
+  // instructions instr is ignored.
+  bool is_single_instruction(Instr instr = 0) const;
   bool must_use_constant_pool() const;
 
   inline int32_t immediate() const {
@@ -465,20 +468,20 @@
 
 // CpuFeatures keeps track of which features are supported by the target CPU.
 // Supported features must be enabled by a Scope before use.
-class CpuFeatures : public AllStatic {
+class CpuFeatures {
  public:
   // Detect features of the target CPU. Set safe defaults if the serializer
   // is enabled (snapshots must be portable).
-  static void Probe(bool portable);
+  void Probe(bool portable);
 
   // Check whether a feature is supported by the target CPU.
-  static bool IsSupported(CpuFeature f) {
+  bool IsSupported(CpuFeature f) const {
     if (f == VFP3 && !FLAG_enable_vfp3) return false;
     return (supported_ & (1u << f)) != 0;
   }
 
   // Check whether a feature is currently enabled.
-  static bool IsEnabled(CpuFeature f) {
+  bool IsEnabled(CpuFeature f) const {
     return (enabled_ & (1u << f)) != 0;
   }
 
@@ -486,16 +489,23 @@
   class Scope BASE_EMBEDDED {
 #ifdef DEBUG
    public:
-    explicit Scope(CpuFeature f) {
-      ASSERT(CpuFeatures::IsSupported(f));
+    explicit Scope(CpuFeature f)
+        : cpu_features_(Isolate::Current()->cpu_features()),
+          isolate_(Isolate::Current()) {
+      ASSERT(cpu_features_->IsSupported(f));
       ASSERT(!Serializer::enabled() ||
-             (found_by_runtime_probing_ & (1u << f)) == 0);
-      old_enabled_ = CpuFeatures::enabled_;
-      CpuFeatures::enabled_ |= 1u << f;
+             (cpu_features_->found_by_runtime_probing_ & (1u << f)) == 0);
+      old_enabled_ = cpu_features_->enabled_;
+      cpu_features_->enabled_ |= 1u << f;
     }
-    ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
+    ~Scope() {
+      ASSERT_EQ(Isolate::Current(), isolate_);
+      cpu_features_->enabled_ = old_enabled_;
+    }
    private:
     unsigned old_enabled_;
+    CpuFeatures* cpu_features_;
+    Isolate* isolate_;
 #else
    public:
     explicit Scope(CpuFeature f) {}
@@ -503,9 +513,15 @@
   };
 
  private:
-  static unsigned supported_;
-  static unsigned enabled_;
-  static unsigned found_by_runtime_probing_;
+  CpuFeatures();
+
+  unsigned supported_;
+  unsigned enabled_;
+  unsigned found_by_runtime_probing_;
+
+  friend class Isolate;
+
+  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
 };
 
 
@@ -533,7 +549,7 @@
 
 
 
-class Assembler : public Malloced {
+class Assembler : public AssemblerBase {
  public:
   // Create an assembler. Instructions and relocation information are emitted
   // into a buffer, with the instructions starting from the beginning and the
@@ -551,6 +567,9 @@
   Assembler(void* buffer, int buffer_size);
   ~Assembler();
 
+  // Overrides the default provided by FLAG_debug_code.
+  void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
+
   // 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.
@@ -989,6 +1008,9 @@
                     VFPConversionMode mode = kDefaultRoundToZero,
                     const Condition cond = al);
 
+  void vneg(const DwVfpRegister dst,
+            const DwVfpRegister src,
+            const Condition cond = al);
   void vabs(const DwVfpRegister dst,
             const DwVfpRegister src,
             const Condition cond = al);
@@ -1148,6 +1170,8 @@
   void CheckConstPool(bool force_emit, bool require_jump);
 
  protected:
+  bool emit_debug_code() const { return emit_debug_code_; }
+
   int buffer_space() const { return reloc_info_writer.pos() - pc_; }
 
   // Read/patch instructions
@@ -1276,6 +1300,7 @@
 
   PositionsRecorder positions_recorder_;
   bool allow_peephole_optimization_;
+  bool emit_debug_code_;
   friend class PositionsRecorder;
   friend class EnsureSpace;
 };
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index 961d3ce..f401cfd 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -68,7 +68,7 @@
   // JumpToExternalReference expects r0 to contain the number of arguments
   // including the receiver and the extra arguments.
   __ add(r0, r0, Operand(num_extra_args + 1));
-  __ JumpToExternalReference(ExternalReference(id));
+  __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
 }
 
 
@@ -310,6 +310,7 @@
 // construct call and normal call.
 static void ArrayNativeCode(MacroAssembler* masm,
                             Label* call_generic_code) {
+  Counters* counters = masm->isolate()->counters();
   Label argc_one_or_more, argc_two_or_more;
 
   // Check for array construction with zero arguments or one.
@@ -325,7 +326,7 @@
                        r5,
                        JSArray::kPreallocatedArrayElements,
                        call_generic_code);
-  __ IncrementCounter(&Counters::array_function_native, 1, r3, r4);
+  __ IncrementCounter(counters->array_function_native(), 1, r3, r4);
   // Setup return value, remove receiver from stack and return.
   __ mov(r0, r2);
   __ add(sp, sp, Operand(kPointerSize));
@@ -361,7 +362,7 @@
                   r7,
                   true,
                   call_generic_code);
-  __ IncrementCounter(&Counters::array_function_native, 1, r2, r4);
+  __ IncrementCounter(counters->array_function_native(), 1, r2, r4);
   // Setup return value, remove receiver and argument from stack and return.
   __ mov(r0, r3);
   __ add(sp, sp, Operand(2 * kPointerSize));
@@ -385,7 +386,7 @@
                   r7,
                   false,
                   call_generic_code);
-  __ IncrementCounter(&Counters::array_function_native, 1, r2, r6);
+  __ IncrementCounter(counters->array_function_native(), 1, r2, r6);
 
   // Fill arguments as array elements. Copy from the top of the stack (last
   // element) to the array backing store filling it backwards. Note:
@@ -442,8 +443,9 @@
   // Jump to the generic array code if the specialized code cannot handle
   // the construction.
   __ bind(&generic_array_code);
-  Code* code = Builtins::builtin(Builtins::ArrayCodeGeneric);
-  Handle<Code> array_code(code);
+
+  Handle<Code> array_code =
+      masm->isolate()->builtins()->ArrayCodeGeneric();
   __ Jump(array_code, RelocInfo::CODE_TARGET);
 }
 
@@ -474,8 +476,8 @@
   // Jump to the generic construct code in case the specialized code cannot
   // handle the construction.
   __ bind(&generic_constructor);
-  Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
-  Handle<Code> generic_construct_stub(code);
+  Handle<Code> generic_construct_stub =
+      masm->isolate()->builtins()->JSConstructStubGeneric();
   __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
 }
 
@@ -488,7 +490,8 @@
   //  -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
   //  -- sp[argc * 4]           : receiver
   // -----------------------------------
-  __ IncrementCounter(&Counters::string_ctor_calls, 1, r2, r3);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->string_ctor_calls(), 1, r2, r3);
 
   Register function = r1;
   if (FLAG_debug_code) {
@@ -518,7 +521,7 @@
       r5,        // Scratch.
       false,     // Is it a Smi?
       &not_cached);
-  __ IncrementCounter(&Counters::string_ctor_cached_number, 1, r3, r4);
+  __ IncrementCounter(counters->string_ctor_cached_number(), 1, r3, r4);
   __ bind(&argument_is_string);
 
   // ----------- S t a t e -------------
@@ -572,13 +575,13 @@
   __ tst(r3, Operand(kIsNotStringMask));
   __ b(ne, &convert_argument);
   __ mov(argument, r0);
-  __ IncrementCounter(&Counters::string_ctor_conversions, 1, r3, r4);
+  __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4);
   __ b(&argument_is_string);
 
   // Invoke the conversion builtin and put the result into r2.
   __ bind(&convert_argument);
   __ push(function);  // Preserve the function.
-  __ IncrementCounter(&Counters::string_ctor_conversions, 1, r3, r4);
+  __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4);
   __ EnterInternalFrame();
   __ push(r0);
   __ InvokeBuiltin(Builtins::TO_STRING, CALL_JS);
@@ -597,7 +600,7 @@
   // At this point the argument is already a string. Call runtime to
   // create a string wrapper.
   __ bind(&gc_required);
-  __ IncrementCounter(&Counters::string_ctor_gc_required, 1, r3, r4);
+  __ IncrementCounter(counters->string_ctor_gc_required(), 1, r3, r4);
   __ EnterInternalFrame();
   __ push(argument);
   __ CallRuntime(Runtime::kNewStringWrapper, 1);
@@ -633,7 +636,7 @@
   // Set expected number of arguments to zero (not changing r0).
   __ mov(r2, Operand(0, RelocInfo::NONE));
   __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
-  __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
+  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
           RelocInfo::CODE_TARGET);
 }
 
@@ -644,6 +647,8 @@
   // Should never count constructions for api objects.
   ASSERT(!is_api_function || !count_constructions);
 
+  Isolate* isolate = masm->isolate();
+
   // Enter a construct frame.
   __ EnterConstructFrame();
 
@@ -659,7 +664,7 @@
     Label undo_allocation;
 #ifdef ENABLE_DEBUGGER_SUPPORT
     ExternalReference debug_step_in_fp =
-        ExternalReference::debug_step_in_fp_address();
+        ExternalReference::debug_step_in_fp_address(isolate);
     __ mov(r2, Operand(debug_step_in_fp));
     __ ldr(r2, MemOperand(r2));
     __ tst(r2, r2);
@@ -905,8 +910,8 @@
   // r1: constructor function
   if (is_api_function) {
     __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
-    Handle<Code> code = Handle<Code>(
-        Builtins::builtin(Builtins::HandleApiCallConstruct));
+    Handle<Code> code =
+        masm->isolate()->builtins()->HandleApiCallConstruct();
     ParameterCount expected(0);
     __ InvokeCode(code, expected, expected,
                   RelocInfo::CODE_TARGET, CALL_FUNCTION);
@@ -963,7 +968,7 @@
   __ LeaveConstructFrame();
   __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
   __ add(sp, sp, Operand(kPointerSize));
-  __ IncrementCounter(&Counters::constructed_objects, 1, r1, r2);
+  __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2);
   __ Jump(lr);
 }
 
@@ -1003,7 +1008,8 @@
   __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
 
   // Set up the roots register.
-  ExternalReference roots_address = ExternalReference::roots_address();
+  ExternalReference roots_address =
+      ExternalReference::roots_address(masm->isolate());
   __ mov(r10, Operand(roots_address));
 
   // Push the function and the receiver onto the stack.
@@ -1039,7 +1045,7 @@
   // Invoke the code and pass argc as r0.
   __ mov(r0, Operand(r3));
   if (is_construct) {
-    __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
+    __ Call(masm->isolate()->builtins()->JSConstructCall(),
             RelocInfo::CODE_TARGET);
   } else {
     ParameterCount actual(r0);
@@ -1169,7 +1175,7 @@
 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
   // Probe the CPU to set the supported features, because this builtin
   // may be called before the initialization performs CPU setup.
-  CpuFeatures::Probe(false);
+  masm->isolate()->cpu_features()->Probe(false);
 
   // Lookup the function in the JavaScript frame and push it as an
   // argument to the on-stack replacement function.
@@ -1332,8 +1338,8 @@
     // Expected number of arguments is 0 for CALL_NON_FUNCTION.
     __ mov(r2, Operand(0, RelocInfo::NONE));
     __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
-    __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
-                         RelocInfo::CODE_TARGET);
+    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
+            RelocInfo::CODE_TARGET);
     __ bind(&function);
   }
 
@@ -1348,8 +1354,9 @@
   __ mov(r2, Operand(r2, ASR, kSmiTagSize));
   __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
   __ cmp(r2, r0);  // Check formal and actual parameter counts.
-  __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
-          RelocInfo::CODE_TARGET, ne);
+  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
+          RelocInfo::CODE_TARGET,
+          ne);
 
   ParameterCount expected(0);
   __ InvokeCode(r3, expected, expected, JUMP_FUNCTION);
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 1c6d709..441adfe 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -91,11 +91,15 @@
                         &gc,
                         TAG_OBJECT);
 
+  int map_index = strict_mode_ == kStrictMode
+      ? Context::STRICT_MODE_FUNCTION_MAP_INDEX
+      : Context::FUNCTION_MAP_INDEX;
+
   // Compute the function map in the current global context and set that
   // as the map of the allocated object.
   __ ldr(r2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset));
-  __ ldr(r2, MemOperand(r2, Context::SlotOffset(Context::FUNCTION_MAP_INDEX)));
+  __ ldr(r2, MemOperand(r2, Context::SlotOffset(map_index)));
   __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
 
   // Initialize the rest of the function. We don't have to update the
@@ -397,20 +401,18 @@
                            Register scratch2,
                            Label* not_number);
 
-  // Loads the number from object into dst as a 32-bit integer if possible. If
-  // the object cannot be converted to a 32-bit integer control continues at
-  // the label not_int32. If VFP is supported double_scratch is used
-  // but not scratch2.
-  // Floating point value in the 32-bit integer range will be rounded
-  // to an integer.
-  static void LoadNumberAsInteger(MacroAssembler* masm,
-                                  Register object,
-                                  Register dst,
-                                  Register heap_number_map,
-                                  Register scratch1,
-                                  Register scratch2,
-                                  DwVfpRegister double_scratch,
-                                  Label* not_int32);
+  // Convert the smi or heap number in object to an int32 using the rules
+  // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
+  // and brought into the range -2^31 .. +2^31 - 1.
+  static void ConvertNumberToInt32(MacroAssembler* masm,
+                                   Register object,
+                                   Register dst,
+                                   Register heap_number_map,
+                                   Register scratch1,
+                                   Register scratch2,
+                                   Register scratch3,
+                                   DwVfpRegister double_scratch,
+                                   Label* not_int32);
 
   // Load the number from object into double_dst in the double format.
   // Control will jump to not_int32 if the value cannot be exactly represented
@@ -500,7 +502,7 @@
                                    FloatingPointHelper::Destination destination,
                                    Register scratch1,
                                    Register scratch2) {
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
     __ mov(scratch1, Operand(r0, ASR, kSmiTagSize));
     __ vmov(d7.high(), scratch1);
@@ -568,7 +570,8 @@
   __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
 
   // Handle loading a double from a heap number.
-  if (CpuFeatures::IsSupported(VFP3) && destination == kVFPRegisters) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3) &&
+      destination == kVFPRegisters) {
     CpuFeatures::Scope scope(VFP3);
     // Load the double from tagged HeapNumber to double register.
     __ sub(scratch1, object, Operand(kHeapObjectTag));
@@ -582,7 +585,7 @@
 
   // Handle loading a double from a smi.
   __ bind(&is_smi);
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
     // Convert smi to double using VFP instructions.
     __ SmiUntag(scratch1, object);
@@ -606,27 +609,46 @@
 }
 
 
-void FloatingPointHelper::LoadNumberAsInteger(MacroAssembler* masm,
-                                              Register object,
-                                              Register dst,
-                                              Register heap_number_map,
-                                              Register scratch1,
-                                              Register scratch2,
-                                              DwVfpRegister double_scratch,
-                                              Label* not_int32) {
+void FloatingPointHelper::ConvertNumberToInt32(MacroAssembler* masm,
+                                               Register object,
+                                               Register dst,
+                                               Register heap_number_map,
+                                               Register scratch1,
+                                               Register scratch2,
+                                               Register scratch3,
+                                               DwVfpRegister double_scratch,
+                                               Label* not_number) {
   if (FLAG_debug_code) {
     __ AbortIfNotRootValue(heap_number_map,
                            Heap::kHeapNumberMapRootIndex,
                            "HeapNumberMap register clobbered.");
   }
-  Label is_smi, done;
+  Label is_smi;
+  Label done;
+  Label not_in_int32_range;
+
   __ JumpIfSmi(object, &is_smi);
   __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kMapOffset));
   __ cmp(scratch1, heap_number_map);
-  __ b(ne, not_int32);
-  __ ConvertToInt32(
-      object, dst, scratch1, scratch2, double_scratch, not_int32);
+  __ b(ne, not_number);
+  __ ConvertToInt32(object,
+                    dst,
+                    scratch1,
+                    scratch2,
+                    double_scratch,
+                    &not_in_int32_range);
   __ jmp(&done);
+
+  __ bind(&not_in_int32_range);
+  __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
+  __ ldr(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
+
+  __ EmitOutOfInt32RangeTruncate(dst,
+                                 scratch1,
+                                 scratch2,
+                                 scratch3);
+  __ jmp(&done);
+
   __ bind(&is_smi);
   __ SmiUntag(dst, object);
   __ bind(&done);
@@ -654,7 +676,7 @@
 
   __ JumpIfNotSmi(object, &obj_is_not_smi);
   __ SmiUntag(scratch1, object);
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
     __ vmov(single_scratch, scratch1);
     __ vcvt_f64_s32(double_dst, single_scratch);
@@ -722,7 +744,7 @@
   __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
 
   // Load the number.
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
     // Load the double value.
     __ sub(scratch1, object, Operand(kHeapObjectTag));
@@ -796,7 +818,7 @@
 
   // Object is a heap number.
   // Convert the floating point value to a 32-bit integer.
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
     SwVfpRegister single_scratch = double_scratch.low();
     // Load the double value.
@@ -927,7 +949,8 @@
   __ push(lr);
   __ PrepareCallCFunction(4, scratch);  // Two doubles are 4 arguments.
   // Call C routine that may not cause GC or other trouble.
-  __ CallCFunction(ExternalReference::double_fp_operation(op), 4);
+  __ CallCFunction(ExternalReference::double_fp_operation(op, masm->isolate()),
+                   4);
   // Store answer in the overwritable heap number.
 #if !defined(USE_ARM_EABI)
   // Double returned in fp coprocessor register 0 and 1, encoded as
@@ -1007,7 +1030,7 @@
   // The two objects are identical.  If we know that one of them isn't NaN then
   // we now know they test equal.
   if (cond != eq || !never_nan_nan) {
-    // Test for NaN. Sadly, we can't just compare to Factory::nan_value(),
+    // Test for NaN. Sadly, we can't just compare to FACTORY->nan_value(),
     // so we do the second best thing - test it ourselves.
     // They are both equal and they are not both Smis so both of them are not
     // Smis.  If it's not a heap number, then return equal.
@@ -1130,7 +1153,7 @@
   }
 
   // Lhs is a smi, rhs is a number.
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     // Convert lhs to a double in d7.
     CpuFeatures::Scope scope(VFP3);
     __ SmiToDoubleVFPRegister(lhs, d7, r7, s15);
@@ -1170,7 +1193,7 @@
   }
 
   // Rhs is a smi, lhs is a heap number.
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
     // Load the double from lhs, tagged HeapNumber r1, to d7.
     __ sub(r7, lhs, Operand(kHeapObjectTag));
@@ -1282,7 +1305,7 @@
     // Call C routine that may not cause GC or other trouble.
     __ push(lr);
     __ PrepareCallCFunction(4, r5);  // Two doubles count as 4 arguments.
-    __ CallCFunction(ExternalReference::compare_doubles(), 4);
+    __ CallCFunction(ExternalReference::compare_doubles(masm->isolate()), 4);
     __ pop(pc);  // Return.
   }
 }
@@ -1350,7 +1373,7 @@
 
   // Both are heap numbers.  Load them up then jump to the code we have
   // for that.
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
     __ sub(r7, rhs, Operand(kHeapObjectTag));
     __ vldr(d6, r7, HeapNumber::kValueOffset);
@@ -1435,11 +1458,12 @@
   // number string cache for smis is just the smi value, and the hash for
   // doubles is the xor of the upper and lower words. See
   // Heap::GetNumberStringCache.
+  Isolate* isolate = masm->isolate();
   Label is_smi;
   Label load_result_from_cache;
   if (!object_is_smi) {
     __ JumpIfSmi(object, &is_smi);
-    if (CpuFeatures::IsSupported(VFP3)) {
+    if (isolate->cpu_features()->IsSupported(VFP3)) {
       CpuFeatures::Scope scope(VFP3);
       __ CheckMap(object,
                   scratch1,
@@ -1496,7 +1520,7 @@
   __ bind(&load_result_from_cache);
   __ ldr(result,
          FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize));
-  __ IncrementCounter(&Counters::number_to_string_native,
+  __ IncrementCounter(isolate->counters()->number_to_string_native(),
                       1,
                       scratch1,
                       scratch2);
@@ -1572,7 +1596,8 @@
   __ bind(&both_loaded_as_doubles);
   // The arguments have been converted to doubles and stored in d6 and d7, if
   // VFP3 is supported, or in r0, r1, r2, and r3.
-  if (CpuFeatures::IsSupported(VFP3)) {
+  Isolate* isolate = masm->isolate();
+  if (isolate->cpu_features()->IsSupported(VFP3)) {
     __ bind(&lhs_not_nan);
     CpuFeatures::Scope scope(VFP3);
     Label no_nan;
@@ -1642,7 +1667,7 @@
 
   __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs_, rhs_, r2, r3, &slow);
 
-  __ IncrementCounter(&Counters::string_compare_native, 1, r2, r3);
+  __ IncrementCounter(isolate->counters()->string_compare_native(), 1, r2, r3);
   StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
                                                      lhs_,
                                                      rhs_,
@@ -1682,7 +1707,7 @@
 // The stub returns zero for false, and a non-zero value for true.
 void ToBooleanStub::Generate(MacroAssembler* masm) {
   // This stub uses VFP3 instructions.
-  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(Isolate::Current()->cpu_features()->IsEnabled(VFP3));
 
   Label false_result;
   Label not_heap_number;
@@ -1768,7 +1793,9 @@
     Register rhs,
     const Builtins::JavaScript& builtin) {
   Label slow, slow_reverse, do_the_call;
-  bool use_fp_registers = CpuFeatures::IsSupported(VFP3) && Token::MOD != op_;
+  bool use_fp_registers =
+      Isolate::Current()->cpu_features()->IsSupported(VFP3) &&
+      Token::MOD != op_;
 
   ASSERT((lhs.is(r0) && rhs.is(r1)) || (lhs.is(r1) && rhs.is(r0)));
   Register heap_number_map = r6;
@@ -1784,7 +1811,7 @@
 
     // If we have floating point hardware, inline ADD, SUB, MUL, and DIV,
     // using registers d7 and d6 for the double values.
-    if (CpuFeatures::IsSupported(VFP3)) {
+    if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
       CpuFeatures::Scope scope(VFP3);
       __ mov(r7, Operand(rhs, ASR, kSmiTagSize));
       __ vmov(s15, r7);
@@ -1880,7 +1907,7 @@
       __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow);
       }
 
-      if (CpuFeatures::IsSupported(VFP3)) {
+      if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
         CpuFeatures::Scope scope(VFP3);
         // Convert smi in r0 to double in d7.
         __ mov(r7, Operand(r0, ASR, kSmiTagSize));
@@ -1937,7 +1964,7 @@
       __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow);
       }
 
-      if (CpuFeatures::IsSupported(VFP3)) {
+      if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
         CpuFeatures::Scope scope(VFP3);
         // Convert smi in r1 to double in d6.
         __ mov(r7, Operand(r1, ASR, kSmiTagSize));
@@ -1994,7 +2021,8 @@
         __ PrepareCallCFunction(4, r4);  // Two doubles count as 4 arguments.
         // Call C routine that may not cause GC or other trouble. r5 is callee
         // save.
-        __ CallCFunction(ExternalReference::double_fp_operation(op_), 4);
+        __ CallCFunction(
+            ExternalReference::double_fp_operation(op_, masm->isolate()), 4);
         // Store answer in the overwritable heap number.
     #if !defined(USE_ARM_EABI)
         // Double returned in fp coprocessor register 0 and 1, encoded as
@@ -2149,7 +2177,7 @@
       // The code below for writing into heap numbers isn't capable of writing
       // the register as an unsigned int so we go to slow case if we hit this
       // case.
-      if (CpuFeatures::IsSupported(VFP3)) {
+      if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
         __ b(mi, &result_not_a_smi);
       } else {
         __ b(mi, &slow);
@@ -2197,7 +2225,7 @@
   // result.
   __ mov(r0, Operand(r5));
 
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     // Convert the int32 in r2 to the heap number in r0. r3 is corrupted.
     CpuFeatures::Scope scope(VFP3);
     __ vmov(s0, r2);
@@ -2798,7 +2826,7 @@
   __ Push(r2, r1, r0);
 
   __ TailCallExternalReference(
-      ExternalReference(IC_Utility(IC::kBinaryOp_Patch)),
+      ExternalReference(IC_Utility(IC::kBinaryOp_Patch), masm->isolate()),
       5,
       1);
 }
@@ -2829,7 +2857,8 @@
   __ Push(r2, r1, r0);
 
   __ TailCallExternalReference(
-      ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch)),
+      ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch),
+                        masm->isolate()),
       5,
       1);
 }
@@ -2855,6 +2884,9 @@
     case TRBinaryOpIC::HEAP_NUMBER:
       GenerateHeapNumberStub(masm);
       break;
+    case TRBinaryOpIC::ODDBALL:
+      GenerateOddballStub(masm);
+      break;
     case TRBinaryOpIC::STRING:
       GenerateStringStub(masm);
       break;
@@ -2870,7 +2902,8 @@
 const char* TypeRecordingBinaryOpStub::GetName() {
   if (name_ != NULL) return name_;
   const int kMaxNameLength = 100;
-  name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
+  name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
+      kMaxNameLength);
   if (name_ == NULL) return "OOM";
   const char* op_name = Token::Name(op_);
   const char* overwrite_name;
@@ -3024,6 +3057,7 @@
   Register right = r0;
   Register scratch1 = r7;
   Register scratch2 = r9;
+  Register scratch3 = r4;
 
   ASSERT(smi_operands || (not_numbers != NULL));
   if (smi_operands && FLAG_debug_code) {
@@ -3043,7 +3077,8 @@
       // Load left and right operands into d6 and d7 or r0/r1 and r2/r3
       // depending on whether VFP3 is available or not.
       FloatingPointHelper::Destination destination =
-          CpuFeatures::IsSupported(VFP3) && op_ != Token::MOD ?
+          Isolate::Current()->cpu_features()->IsSupported(VFP3) &&
+          op_ != Token::MOD ?
           FloatingPointHelper::kVFPRegisters :
           FloatingPointHelper::kCoreRegisters;
 
@@ -3111,22 +3146,24 @@
         __ SmiUntag(r2, right);
       } else {
         // Convert operands to 32-bit integers. Right in r2 and left in r3.
-        FloatingPointHelper::LoadNumberAsInteger(masm,
-                                                 left,
-                                                 r3,
-                                                 heap_number_map,
-                                                 scratch1,
-                                                 scratch2,
-                                                 d0,
-                                                 not_numbers);
-        FloatingPointHelper::LoadNumberAsInteger(masm,
-                                                 right,
-                                                 r2,
-                                                 heap_number_map,
-                                                 scratch1,
-                                                 scratch2,
-                                                 d0,
-                                                 not_numbers);
+        FloatingPointHelper::ConvertNumberToInt32(masm,
+                                                  left,
+                                                  r3,
+                                                  heap_number_map,
+                                                  scratch1,
+                                                  scratch2,
+                                                  scratch3,
+                                                  d0,
+                                                  not_numbers);
+        FloatingPointHelper::ConvertNumberToInt32(masm,
+                                                  right,
+                                                  r2,
+                                                  heap_number_map,
+                                                  scratch1,
+                                                  scratch2,
+                                                  scratch3,
+                                                  d0,
+                                                  not_numbers);
       }
 
       Label result_not_a_smi;
@@ -3153,7 +3190,7 @@
           // The code below for writing into heap numbers isn't capable of
           // writing the register as an unsigned int so we go to slow case if we
           // hit this case.
-          if (CpuFeatures::IsSupported(VFP3)) {
+          if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
             __ b(mi, &result_not_a_smi);
           } else {
             __ b(mi, not_numbers);
@@ -3192,7 +3229,7 @@
       // result.
       __ mov(r0, Operand(r5));
 
-      if (CpuFeatures::IsSupported(VFP3)) {
+      if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
         // Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As
         // mentioned above SHR needs to always produce a positive result.
         CpuFeatures::Scope scope(VFP3);
@@ -3321,7 +3358,8 @@
     // Jump to type transition if they are not. The registers r0 and r1 (right
     // and left) are preserved for the runtime call.
     FloatingPointHelper::Destination destination =
-        CpuFeatures::IsSupported(VFP3) && op_ != Token::MOD ?
+        Isolate::Current()->cpu_features()->IsSupported(VFP3) &&
+        op_ != Token::MOD ?
         FloatingPointHelper::kVFPRegisters :
         FloatingPointHelper::kCoreRegisters;
 
@@ -3391,9 +3429,20 @@
           __ add(scratch2, scratch1, Operand(0x40000000), SetCC);
           // If not try to return a heap number.
           __ b(mi, &return_heap_number);
+          // Check for minus zero. Return heap number for minus zero.
+          Label not_zero;
+          __ cmp(scratch1, Operand(0));
+          __ b(ne, &not_zero);
+          __ vmov(scratch2, d5.high());
+          __ tst(scratch2, Operand(HeapNumber::kSignMask));
+          __ b(ne, &return_heap_number);
+          __ bind(&not_zero);
+
           // Tag the result and return.
           __ SmiTag(r0, scratch1);
           __ Ret();
+        } else {
+          // DIV just falls through to allocating a heap number.
         }
 
         if (result_type_ >= (op_ == Token::DIV) ? TRBinaryOpIC::HEAP_NUMBER
@@ -3496,7 +3545,7 @@
           // to return a heap number if we can.
           // The non vfp3 code does not support this special case, so jump to
           // runtime if we don't support it.
-          if (CpuFeatures::IsSupported(VFP3)) {
+          if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
             __ b(mi,
                  (result_type_ <= TRBinaryOpIC::INT32) ? &transition
                                                        : &return_heap_number);
@@ -3522,7 +3571,7 @@
       __ Ret();
 
       __ bind(&return_heap_number);
-      if (CpuFeatures::IsSupported(VFP3)) {
+      if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
         CpuFeatures::Scope scope(VFP3);
         heap_number_result = r5;
         GenerateHeapResultAllocation(masm,
@@ -3571,14 +3620,42 @@
 }
 
 
+void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
+  Label call_runtime;
+
+  if (op_ == Token::ADD) {
+    // Handle string addition here, because it is the only operation
+    // that does not do a ToNumber conversion on the operands.
+    GenerateAddStrings(masm);
+  }
+
+  // Convert oddball arguments to numbers.
+  Label check, done;
+  __ CompareRoot(r1, Heap::kUndefinedValueRootIndex);
+  __ b(ne, &check);
+  if (Token::IsBitOp(op_)) {
+    __ mov(r1, Operand(Smi::FromInt(0)));
+  } else {
+    __ LoadRoot(r1, Heap::kNanValueRootIndex);
+  }
+  __ jmp(&done);
+  __ bind(&check);
+  __ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
+  __ b(ne, &done);
+  if (Token::IsBitOp(op_)) {
+    __ mov(r0, Operand(Smi::FromInt(0)));
+  } else {
+    __ LoadRoot(r0, Heap::kNanValueRootIndex);
+  }
+  __ bind(&done);
+
+  GenerateHeapNumberStub(masm);
+}
+
+
 void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
-  Label not_numbers, call_runtime;
-  ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER);
-
-  GenerateFPOperation(masm, false, &not_numbers, &call_runtime);
-
-  __ bind(&not_numbers);
-  GenerateTypeTransition(masm);
+  Label call_runtime;
+  GenerateFPOperation(masm, false, &call_runtime, &call_runtime);
 
   __ bind(&call_runtime);
   GenerateCallRuntime(masm);
@@ -3729,7 +3806,7 @@
   const Register cache_entry = r0;
   const bool tagged = (argument_type_ == TAGGED);
 
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
     if (tagged) {
       // Argument is a number and is on stack and in r0.
@@ -3764,17 +3841,20 @@
     __ eor(r1, r2, Operand(r3));
     __ eor(r1, r1, Operand(r1, ASR, 16));
     __ eor(r1, r1, Operand(r1, ASR, 8));
-    ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
-    __ And(r1, r1, Operand(TranscendentalCache::kCacheSize - 1));
+    ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize));
+    __ And(r1, r1, Operand(TranscendentalCache::SubCache::kCacheSize - 1));
 
     // r2 = low 32 bits of double value.
     // r3 = high 32 bits of double value.
     // r1 = TranscendentalCache::hash(double value).
-    __ mov(cache_entry,
-           Operand(ExternalReference::transcendental_cache_array_address()));
-    // r0 points to cache array.
-    __ ldr(cache_entry, MemOperand(cache_entry,
-        type_ * sizeof(TranscendentalCache::caches_[0])));
+    Isolate* isolate = masm->isolate();
+    ExternalReference cache_array =
+        ExternalReference::transcendental_cache_array_address(isolate);
+    __ mov(cache_entry, Operand(cache_array));
+    // cache_entry points to cache array.
+    int cache_array_index
+        = type_ * sizeof(isolate->transcendental_cache()->caches_[0]);
+    __ ldr(cache_entry, MemOperand(cache_entry, cache_array_index));
     // r0 points to the cache for the type type_.
     // If NULL, the cache hasn't been initialized yet, so go through runtime.
     __ cmp(cache_entry, Operand(0, RelocInfo::NONE));
@@ -3782,7 +3862,7 @@
 
 #ifdef DEBUG
     // Check that the layout of cache elements match expectations.
-    { TranscendentalCache::Element test_elem[2];
+    { TranscendentalCache::SubCache::Element test_elem[2];
       char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
       char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
       char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
@@ -3814,14 +3894,16 @@
        __ vldr(d2, FieldMemOperand(r6, HeapNumber::kValueOffset));
     }
     __ Ret();
-  }  // if (CpuFeatures::IsSupported(VFP3))
+  }  // if (Isolate::Current()->cpu_features()->IsSupported(VFP3))
 
   __ bind(&calculate);
   if (tagged) {
     __ bind(&invalid_cache);
-    __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
+    ExternalReference runtime_function =
+        ExternalReference(RuntimeFunction(), masm->isolate());
+    __ TailCallExternalReference(runtime_function, 1, 1);
   } else {
-    if (!CpuFeatures::IsSupported(VFP3)) UNREACHABLE();
+    if (!Isolate::Current()->cpu_features()->IsSupported(VFP3)) UNREACHABLE();
     CpuFeatures::Scope scope(VFP3);
 
     Label no_update;
@@ -3882,18 +3964,20 @@
 
 void TranscendentalCacheStub::GenerateCallCFunction(MacroAssembler* masm,
                                                     Register scratch) {
+  Isolate* isolate = masm->isolate();
+
   __ push(lr);
   __ PrepareCallCFunction(2, scratch);
   __ vmov(r0, r1, d2);
   switch (type_) {
     case TranscendentalCache::SIN:
-      __ CallCFunction(ExternalReference::math_sin_double_function(), 2);
+      __ CallCFunction(ExternalReference::math_sin_double_function(isolate), 2);
       break;
     case TranscendentalCache::COS:
-      __ CallCFunction(ExternalReference::math_cos_double_function(), 2);
+      __ CallCFunction(ExternalReference::math_cos_double_function(isolate), 2);
       break;
     case TranscendentalCache::LOG:
-      __ CallCFunction(ExternalReference::math_log_double_function(), 2);
+      __ CallCFunction(ExternalReference::math_log_double_function(isolate), 2);
       break;
     default:
       UNIMPLEMENTED();
@@ -4018,7 +4102,7 @@
       __ mov(r0, Operand(r2));
     }
 
-    if (CpuFeatures::IsSupported(VFP3)) {
+    if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
       // Convert the int32 in r1 to the heap number in r0. r2 is corrupted.
       CpuFeatures::Scope scope(VFP3);
       __ vmov(s0, r1);
@@ -4056,6 +4140,113 @@
 }
 
 
+void MathPowStub::Generate(MacroAssembler* masm) {
+  Label call_runtime;
+
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
+    CpuFeatures::Scope scope(VFP3);
+
+    Label base_not_smi;
+    Label exponent_not_smi;
+    Label convert_exponent;
+
+    const Register base = r0;
+    const Register exponent = r1;
+    const Register heapnumbermap = r5;
+    const Register heapnumber = r6;
+    const DoubleRegister double_base = d0;
+    const DoubleRegister double_exponent = d1;
+    const DoubleRegister double_result = d2;
+    const SwVfpRegister single_scratch = s0;
+    const Register scratch = r9;
+    const Register scratch2 = r7;
+
+    __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex);
+    __ ldr(base, MemOperand(sp, 1 * kPointerSize));
+    __ ldr(exponent, MemOperand(sp, 0 * kPointerSize));
+
+    // Convert base to double value and store it in d0.
+    __ JumpIfNotSmi(base, &base_not_smi);
+    // Base is a Smi. Untag and convert it.
+    __ SmiUntag(base);
+    __ vmov(single_scratch, base);
+    __ vcvt_f64_s32(double_base, single_scratch);
+    __ b(&convert_exponent);
+
+    __ bind(&base_not_smi);
+    __ ldr(scratch, FieldMemOperand(base, JSObject::kMapOffset));
+    __ cmp(scratch, heapnumbermap);
+    __ b(ne, &call_runtime);
+    // Base is a heapnumber. Load it into double register.
+    __ vldr(double_base, FieldMemOperand(base, HeapNumber::kValueOffset));
+
+    __ bind(&convert_exponent);
+    __ JumpIfNotSmi(exponent, &exponent_not_smi);
+    __ SmiUntag(exponent);
+
+    // The base is in a double register and the exponent is
+    // an untagged smi. Allocate a heap number and call a
+    // C function for integer exponents. The register containing
+    // the heap number is callee-saved.
+    __ AllocateHeapNumber(heapnumber,
+                          scratch,
+                          scratch2,
+                          heapnumbermap,
+                          &call_runtime);
+    __ push(lr);
+    __ PrepareCallCFunction(3, scratch);
+    __ mov(r2, exponent);
+    __ vmov(r0, r1, double_base);
+    __ CallCFunction(
+        ExternalReference::power_double_int_function(masm->isolate()), 3);
+    __ pop(lr);
+    __ GetCFunctionDoubleResult(double_result);
+    __ vstr(double_result,
+            FieldMemOperand(heapnumber, HeapNumber::kValueOffset));
+    __ mov(r0, heapnumber);
+    __ Ret(2 * kPointerSize);
+
+    __ bind(&exponent_not_smi);
+    __ ldr(scratch, FieldMemOperand(exponent, JSObject::kMapOffset));
+    __ cmp(scratch, heapnumbermap);
+    __ b(ne, &call_runtime);
+    // Exponent is a heapnumber. Load it into double register.
+    __ vldr(double_exponent,
+            FieldMemOperand(exponent, HeapNumber::kValueOffset));
+
+    // The base and the exponent are in double registers.
+    // Allocate a heap number and call a C function for
+    // double exponents. The register containing
+    // the heap number is callee-saved.
+    __ AllocateHeapNumber(heapnumber,
+                          scratch,
+                          scratch2,
+                          heapnumbermap,
+                          &call_runtime);
+    __ push(lr);
+    __ PrepareCallCFunction(4, scratch);
+    __ vmov(r0, r1, double_base);
+    __ vmov(r2, r3, double_exponent);
+    __ CallCFunction(
+        ExternalReference::power_double_double_function(masm->isolate()), 4);
+    __ pop(lr);
+    __ GetCFunctionDoubleResult(double_result);
+    __ vstr(double_result,
+            FieldMemOperand(heapnumber, HeapNumber::kValueOffset));
+    __ mov(r0, heapnumber);
+    __ Ret(2 * kPointerSize);
+  }
+
+  __ bind(&call_runtime);
+  __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1);
+}
+
+
+bool CEntryStub::NeedsImmovableCode() {
+  return true;
+}
+
+
 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
   __ Throw(r0);
 }
@@ -4077,15 +4268,16 @@
   // 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)
+  Isolate* isolate = masm->isolate();
 
   if (do_gc) {
     // Passing r0.
     __ PrepareCallCFunction(1, r1);
-    __ CallCFunction(ExternalReference::perform_gc_function(), 1);
+    __ CallCFunction(ExternalReference::perform_gc_function(isolate), 1);
   }
 
   ExternalReference scope_depth =
-      ExternalReference::heap_always_allocate_scope_depth();
+      ExternalReference::heap_always_allocate_scope_depth(isolate);
   if (always_allocate) {
     __ mov(r0, Operand(scope_depth));
     __ ldr(r1, MemOperand(r0));
@@ -4114,6 +4306,9 @@
   }
 #endif
 
+  __ mov(r2, Operand(ExternalReference::isolate_address()));
+
+
   // 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 store it on the stack to be able to find it again, but we never
@@ -4167,15 +4362,16 @@
   __ b(eq, throw_out_of_memory_exception);
 
   // Retrieve the pending exception and clear the variable.
-  __ mov(ip, Operand(ExternalReference::the_hole_value_location()));
+  __ mov(ip, Operand(ExternalReference::the_hole_value_location(isolate)));
   __ ldr(r3, MemOperand(ip));
-  __ mov(ip, Operand(ExternalReference(Top::k_pending_exception_address)));
+  __ mov(ip, Operand(ExternalReference(Isolate::k_pending_exception_address,
+                                       isolate)));
   __ ldr(r0, MemOperand(ip));
   __ str(r3, MemOperand(ip));
 
   // Special handling of termination exceptions which are uncatchable
   // by javascript code.
-  __ cmp(r0, Operand(Factory::termination_exception()));
+  __ cmp(r0, Operand(isolate->factory()->termination_exception()));
   __ b(eq, throw_termination_exception);
 
   // Handle normal exception.
@@ -4283,11 +4479,13 @@
   // r2: receiver
   // r3: argc
   // r4: argv
+  Isolate* isolate = masm->isolate();
   __ mov(r8, Operand(-1));  // Push a bad frame pointer to fail if it is used.
   int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
   __ mov(r7, Operand(Smi::FromInt(marker)));
   __ mov(r6, Operand(Smi::FromInt(marker)));
-  __ mov(r5, Operand(ExternalReference(Top::k_c_entry_fp_address)));
+  __ mov(r5,
+         Operand(ExternalReference(Isolate::k_c_entry_fp_address, isolate)));
   __ ldr(r5, MemOperand(r5));
   __ Push(r8, r7, r6, r5);
 
@@ -4296,7 +4494,7 @@
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
   // If this is the outermost JS call, set js_entry_sp value.
-  ExternalReference js_entry_sp(Top::k_js_entry_sp_address);
+  ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address, isolate);
   __ mov(r5, Operand(ExternalReference(js_entry_sp)));
   __ ldr(r6, MemOperand(r5));
   __ cmp(r6, Operand(0, RelocInfo::NONE));
@@ -4310,7 +4508,8 @@
   // 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)));
+  __ mov(ip, Operand(ExternalReference(Isolate::k_pending_exception_address,
+                                       isolate)));
   __ str(r0, MemOperand(ip));
   __ mov(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception())));
   __ b(&exit);
@@ -4325,9 +4524,10 @@
   // saved values before returning a failure to C.
 
   // Clear any pending exceptions.
-  __ mov(ip, Operand(ExternalReference::the_hole_value_location()));
+  __ mov(ip, Operand(ExternalReference::the_hole_value_location(isolate)));
   __ ldr(r5, MemOperand(ip));
-  __ mov(ip, Operand(ExternalReference(Top::k_pending_exception_address)));
+  __ mov(ip, Operand(ExternalReference(Isolate::k_pending_exception_address,
+                                       isolate)));
   __ str(r5, MemOperand(ip));
 
   // Invoke the function by calling through JS entry trampoline builtin.
@@ -4341,10 +4541,11 @@
   // r3: argc
   // r4: argv
   if (is_construct) {
-    ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline);
+    ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline,
+                                      isolate);
     __ mov(ip, Operand(construct_entry));
   } else {
-    ExternalReference entry(Builtins::JSEntryTrampoline);
+    ExternalReference entry(Builtins::kJSEntryTrampoline, isolate);
     __ mov(ip, Operand(entry));
   }
   __ ldr(ip, MemOperand(ip));  // deref address
@@ -4360,7 +4561,7 @@
   // 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)));
+  __ mov(ip, Operand(ExternalReference(Isolate::k_handler_address, isolate)));
   __ str(r3, MemOperand(ip));
   // No need to restore registers
   __ add(sp, sp, Operand(StackHandlerConstants::kSize));
@@ -4378,7 +4579,8 @@
   __ 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)));
+  __ mov(ip,
+         Operand(ExternalReference(Isolate::k_c_entry_fp_address, isolate)));
   __ str(r3, MemOperand(ip));
 
   // Reset the stack to the callee saved registers.
@@ -4535,7 +4737,7 @@
   __ b(ne, &slow);
 
   // Null is not instance of anything.
-  __ cmp(scratch, Operand(Factory::null_value()));
+  __ cmp(scratch, Operand(FACTORY->null_value()));
   __ b(ne, &object_not_null);
   __ mov(r0, Operand(Smi::FromInt(1)));
   __ Ret(HasArgsInRegisters() ? 0 : 2);
@@ -4662,7 +4864,7 @@
   __ mov(r1, Operand(r1, LSR, kSmiTagSize));
   __ add(r1, r1, Operand(FixedArray::kHeaderSize / kPointerSize));
   __ bind(&add_arguments_object);
-  __ add(r1, r1, Operand(Heap::kArgumentsObjectSize / kPointerSize));
+  __ add(r1, r1, Operand(GetArgumentsObjectSize() / kPointerSize));
 
   // Do the allocation of both objects in one go.
   __ AllocateInNewSpace(
@@ -4674,23 +4876,28 @@
       static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
 
   // Get the arguments boilerplate from the current (global) context.
-  int offset = Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX);
   __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ ldr(r4, FieldMemOperand(r4, GlobalObject::kGlobalContextOffset));
-  __ ldr(r4, MemOperand(r4, offset));
+  __ ldr(r4, MemOperand(r4,
+                        Context::SlotOffset(GetArgumentsBoilerplateIndex())));
 
   // Copy the JS object part.
   __ CopyFields(r0, r4, r3.bit(), JSObject::kHeaderSize / kPointerSize);
 
-  // Setup the callee in-object property.
-  STATIC_ASSERT(Heap::arguments_callee_index == 0);
-  __ ldr(r3, MemOperand(sp, 2 * kPointerSize));
-  __ str(r3, FieldMemOperand(r0, JSObject::kHeaderSize));
+  if (type_ == NEW_NON_STRICT) {
+    // Setup the callee in-object property.
+    STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
+    __ ldr(r3, MemOperand(sp, 2 * kPointerSize));
+    const int kCalleeOffset = JSObject::kHeaderSize +
+                              Heap::kArgumentsCalleeIndex * kPointerSize;
+    __ str(r3, FieldMemOperand(r0, kCalleeOffset));
+  }
 
   // Get the length (smi tagged) and set that as an in-object property too.
-  STATIC_ASSERT(Heap::arguments_length_index == 1);
+  STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
   __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
-  __ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize + kPointerSize));
+  __ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize +
+                                 Heap::kArgumentsLengthIndex * kPointerSize));
 
   // If there are no actual arguments, we're done.
   Label done;
@@ -4702,7 +4909,7 @@
 
   // Setup the elements pointer in the allocated arguments object and
   // initialize the header in the elements fixed array.
-  __ add(r4, r0, Operand(Heap::kArgumentsObjectSize));
+  __ add(r4, r0, Operand(GetArgumentsObjectSize()));
   __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
   __ LoadRoot(r3, Heap::kFixedArrayMapRootIndex);
   __ str(r3, FieldMemOperand(r4, FixedArray::kMapOffset));
@@ -4769,10 +4976,11 @@
   Register last_match_info_elements = r6;
 
   // Ensure that a RegExp stack is allocated.
+  Isolate* isolate = masm->isolate();
   ExternalReference address_of_regexp_stack_memory_address =
-      ExternalReference::address_of_regexp_stack_memory_address();
+      ExternalReference::address_of_regexp_stack_memory_address(isolate);
   ExternalReference address_of_regexp_stack_memory_size =
-      ExternalReference::address_of_regexp_stack_memory_size();
+      ExternalReference::address_of_regexp_stack_memory_size(isolate);
   __ mov(r0, Operand(address_of_regexp_stack_memory_size));
   __ ldr(r0, MemOperand(r0, 0));
   __ tst(r0, Operand(r0));
@@ -4913,7 +5121,7 @@
   __ CompareObjectType(r7, r0, r0, CODE_TYPE);
   __ b(ne, &runtime);
 
-  // r3: encoding of subject string (1 if ascii, 0 if two_byte);
+  // r3: encoding of subject string (1 if ASCII, 0 if two_byte);
   // r7: code
   // subject: Subject string
   // regexp_data: RegExp data (FixedArray)
@@ -4923,20 +5131,25 @@
   __ mov(r1, Operand(r1, ASR, kSmiTagSize));
 
   // r1: previous index
-  // r3: encoding of subject string (1 if ascii, 0 if two_byte);
+  // r3: encoding of subject string (1 if ASCII, 0 if two_byte);
   // r7: code
   // subject: Subject string
   // regexp_data: RegExp data (FixedArray)
   // All checks done. Now push arguments for native regexp code.
-  __ IncrementCounter(&Counters::regexp_entry_native, 1, r0, r2);
+  __ IncrementCounter(isolate->counters()->regexp_entry_native(), 1, r0, r2);
 
-  static const int kRegExpExecuteArguments = 7;
+  // Isolates: note we add an additional parameter here (isolate pointer).
+  static const int kRegExpExecuteArguments = 8;
   static const int kParameterRegisters = 4;
   __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
 
   // Stack pointer now points to cell where return address is to be written.
   // Arguments are before that on the stack or in registers.
 
+  // Argument 8 (sp[16]): Pass current isolate address.
+  __ mov(r0, Operand(ExternalReference::isolate_address()));
+  __ str(r0, MemOperand(sp, 4 * kPointerSize));
+
   // Argument 7 (sp[12]): Indicate that this is a direct call from JavaScript.
   __ mov(r0, Operand(1));
   __ str(r0, MemOperand(sp, 3 * kPointerSize));
@@ -4950,7 +5163,8 @@
   __ str(r0, MemOperand(sp, 2 * kPointerSize));
 
   // Argument 5 (sp[4]): static offsets vector buffer.
-  __ mov(r0, Operand(ExternalReference::address_of_static_offsets_vector()));
+  __ mov(r0,
+         Operand(ExternalReference::address_of_static_offsets_vector(isolate)));
   __ str(r0, MemOperand(sp, 1 * kPointerSize));
 
   // For arguments 4 and 3 get string length, calculate start of string data and
@@ -4998,9 +5212,10 @@
   // stack overflow (on the backtrack stack) was detected in RegExp code but
   // haven't created the exception yet. Handle that in the runtime system.
   // TODO(592): Rerunning the RegExp to get the stack overflow exception.
-  __ mov(r1, Operand(ExternalReference::the_hole_value_location()));
+  __ mov(r1, Operand(ExternalReference::the_hole_value_location(isolate)));
   __ ldr(r1, MemOperand(r1, 0));
-  __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address)));
+  __ mov(r2, Operand(ExternalReference(Isolate::k_pending_exception_address,
+                                       isolate)));
   __ ldr(r0, MemOperand(r2, 0));
   __ cmp(r0, r1);
   __ b(eq, &runtime);
@@ -5020,7 +5235,7 @@
 
   __ bind(&failure);
   // For failure and exception return null.
-  __ mov(r0, Operand(Factory::null_value()));
+  __ mov(r0, Operand(FACTORY->null_value()));
   __ add(sp, sp, Operand(4 * kPointerSize));
   __ Ret();
 
@@ -5053,7 +5268,7 @@
 
   // Get the static offsets vector filled by the native regexp code.
   ExternalReference address_of_static_offsets_vector =
-      ExternalReference::address_of_static_offsets_vector();
+      ExternalReference::address_of_static_offsets_vector(isolate);
   __ mov(r2, Operand(address_of_static_offsets_vector));
 
   // r1: number of capture registers
@@ -5125,7 +5340,7 @@
   // Interleave operations for better latency.
   __ ldr(r2, ContextOperand(cp, Context::GLOBAL_INDEX));
   __ add(r3, r0, Operand(JSRegExpResult::kSize));
-  __ mov(r4, Operand(Factory::empty_fixed_array()));
+  __ mov(r4, Operand(FACTORY->empty_fixed_array()));
   __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset));
   __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
   __ ldr(r2, ContextOperand(r2, Context::REGEXP_RESULT_MAP_INDEX));
@@ -5146,13 +5361,13 @@
   // r5: Number of elements in array, untagged.
 
   // Set map.
-  __ mov(r2, Operand(Factory::fixed_array_map()));
+  __ mov(r2, Operand(FACTORY->fixed_array_map()));
   __ str(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
   // Set FixedArray length.
   __ mov(r6, Operand(r5, LSL, kSmiTagSize));
   __ str(r6, FieldMemOperand(r3, FixedArray::kLengthOffset));
   // Fill contents of fixed-array with the-hole.
-  __ mov(r2, Operand(Factory::the_hole_value()));
+  __ mov(r2, Operand(FACTORY->the_hole_value()));
   __ add(r3, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   // Fill fixed array elements with hole.
   // r0: JSArray, tagged.
@@ -5229,7 +5444,7 @@
   __ mov(r0, Operand(argc_));  // Setup the number of arguments.
   __ mov(r2, Operand(0, RelocInfo::NONE));
   __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
-  __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)),
+  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
           RelocInfo::CODE_TARGET);
 }
 
@@ -5242,7 +5457,8 @@
 
   if (name_ != NULL) return name_;
   const int kMaxNameLength = 100;
-  name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
+  name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
+      kMaxNameLength);
   if (name_ == NULL) return "OOM";
 
   const char* cc_name;
@@ -5455,7 +5671,7 @@
   __ b(ne, &slow_case_);
 
   __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
-  // At this point code register contains smi tagged ascii char code.
+  // At this point code register contains smi tagged ASCII char code.
   STATIC_ASSERT(kSmiTag == 0);
   __ add(result_, result_, Operand(code_, LSL, kPointerSizeLog2 - kSmiTagSize));
   __ ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize));
@@ -5787,7 +6003,6 @@
   Register symbol_table = c2;
   __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex);
 
-  // Load undefined value
   Register undefined = scratch4;
   __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
 
@@ -5808,6 +6023,7 @@
   // mask:  capacity mask
   // first_symbol_table_element: address of the first element of
   //                             the symbol table
+  // undefined: the undefined object
   // scratch: -
 
   // Perform a number of probes in the symbol table.
@@ -5835,20 +6051,32 @@
                       kPointerSizeLog2));
 
     // If entry is undefined no string with this hash can be found.
-    __ cmp(candidate, undefined);
+    Label is_string;
+    __ CompareObjectType(candidate, scratch, scratch, ODDBALL_TYPE);
+    __ b(ne, &is_string);
+
+    __ cmp(undefined, candidate);
     __ b(eq, not_found);
+    // Must be null (deleted entry).
+    if (FLAG_debug_code) {
+      __ LoadRoot(ip, Heap::kNullValueRootIndex);
+      __ cmp(ip, candidate);
+      __ Assert(eq, "oddball in symbol table is not undefined or null");
+    }
+    __ jmp(&next_probe[i]);
+
+    __ bind(&is_string);
+
+    // Check that the candidate is a non-external ASCII string.  The instance
+    // type is still in the scratch register from the CompareObjectType
+    // operation.
+    __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]);
 
     // If length is not 2 the string is not a candidate.
     __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset));
     __ cmp(scratch, Operand(Smi::FromInt(2)));
     __ b(ne, &next_probe[i]);
 
-    // Check that the candidate is a non-external ascii string.
-    __ ldr(scratch, FieldMemOperand(candidate, HeapObject::kMapOffset));
-    __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
-    __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch,
-                                              &next_probe[i]);
-
     // Check if the two characters match.
     // Assumes that word load is little endian.
     __ ldrh(scratch, FieldMemOperand(candidate, SeqAsciiString::kHeaderSize));
@@ -5923,7 +6151,6 @@
   static const int kFromOffset = 1 * kPointerSize;
   static const int kStringOffset = 2 * kPointerSize;
 
-
   // Check bounds and smi-ness.
   Register to = r6;
   Register from = r7;
@@ -6004,7 +6231,7 @@
   // r3: from index (untaged smi)
   // r5: string.
   // r7 (a.k.a. from): from offset (smi)
-  // Check for flat ascii string.
+  // Check for flat ASCII string.
   Label non_ascii_flat;
   __ tst(r1, Operand(kStringEncodingMask));
   STATIC_ASSERT(kTwoByteStringTag == 0);
@@ -6024,7 +6251,8 @@
   Label make_two_character_string;
   StringHelper::GenerateTwoCharacterSymbolTableProbe(
       masm, r3, r4, r1, r5, r6, r7, r9, &make_two_character_string);
-  __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
   __ add(sp, sp, Operand(3 * kPointerSize));
   __ Ret();
 
@@ -6033,7 +6261,7 @@
   __ bind(&make_two_character_string);
   __ AllocateAsciiString(r0, r2, r4, r5, r9, &runtime);
   __ strh(r3, FieldMemOperand(r0, SeqAsciiString::kHeaderSize));
-  __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
+  __ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
   __ add(sp, sp, Operand(3 * kPointerSize));
   __ Ret();
 
@@ -6059,7 +6287,7 @@
   STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
   StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9,
                                            COPY_ASCII | DEST_ALWAYS_ALIGNED);
-  __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
+  __ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
   __ add(sp, sp, Operand(3 * kPointerSize));
   __ Ret();
 
@@ -6091,7 +6319,7 @@
   STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
   StringHelper::GenerateCopyCharactersLong(
       masm, r1, r5, r2, r3, r4, r6, r7, r9, DEST_ALWAYS_ALIGNED);
-  __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
+  __ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
   __ add(sp, sp, Operand(3 * kPointerSize));
   __ Ret();
 
@@ -6163,6 +6391,8 @@
 void StringCompareStub::Generate(MacroAssembler* masm) {
   Label runtime;
 
+  Counters* counters = masm->isolate()->counters();
+
   // Stack frame on entry.
   //  sp[0]: right string
   //  sp[4]: left string
@@ -6174,17 +6404,17 @@
   STATIC_ASSERT(EQUAL == 0);
   STATIC_ASSERT(kSmiTag == 0);
   __ mov(r0, Operand(Smi::FromInt(EQUAL)));
-  __ IncrementCounter(&Counters::string_compare_native, 1, r1, r2);
+  __ IncrementCounter(counters->string_compare_native(), 1, r1, r2);
   __ add(sp, sp, Operand(2 * kPointerSize));
   __ Ret();
 
   __ bind(&not_same);
 
-  // Check that both objects are sequential ascii strings.
+  // Check that both objects are sequential ASCII strings.
   __ JumpIfNotBothSequentialAsciiStrings(r1, r0, r2, r3, &runtime);
 
-  // Compare flat ascii strings natively. Remove arguments from stack first.
-  __ IncrementCounter(&Counters::string_compare_native, 1, r2, r3);
+  // Compare flat ASCII strings natively. Remove arguments from stack first.
+  __ IncrementCounter(counters->string_compare_native(), 1, r2, r3);
   __ add(sp, sp, Operand(2 * kPointerSize));
   GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5);
 
@@ -6199,6 +6429,8 @@
   Label string_add_runtime, call_builtin;
   Builtins::JavaScript builtin_id = Builtins::ADD;
 
+  Counters* counters = masm->isolate()->counters();
+
   // Stack on entry:
   // sp[0]: second argument (right).
   // sp[4]: first argument (left).
@@ -6254,7 +6486,7 @@
     __ cmp(r3, Operand(Smi::FromInt(0)), ne);
     __ b(ne, &strings_not_empty);  // If either string was empty, return r0.
 
-    __ IncrementCounter(&Counters::string_add_native, 1, r2, r3);
+    __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
     __ add(sp, sp, Operand(2 * kPointerSize));
     __ Ret();
 
@@ -6275,12 +6507,12 @@
   // Adding two lengths can't overflow.
   STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2);
   __ add(r6, r2, Operand(r3));
-  // Use the runtime system when adding two one character strings, as it
-  // contains optimizations for this specific case using the symbol table.
+  // Use the symbol table when adding two one character strings, as it
+  // helps later optimizations to return a symbol here.
   __ cmp(r6, Operand(2));
   __ b(ne, &longer_than_two);
 
-  // Check that both strings are non-external ascii strings.
+  // Check that both strings are non-external ASCII strings.
   if (flags_ != NO_STRING_ADD_FLAGS) {
     __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
     __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
@@ -6299,7 +6531,7 @@
   Label make_two_character_string;
   StringHelper::GenerateTwoCharacterSymbolTableProbe(
       masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string);
-  __ IncrementCounter(&Counters::string_add_native, 1, r2, r3);
+  __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
   __ add(sp, sp, Operand(2 * kPointerSize));
   __ Ret();
 
@@ -6312,7 +6544,7 @@
   __ mov(r6, Operand(2));
   __ AllocateAsciiString(r0, r6, r4, r5, r9, &string_add_runtime);
   __ strh(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize));
-  __ IncrementCounter(&Counters::string_add_native, 1, r2, r3);
+  __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
   __ add(sp, sp, Operand(2 * kPointerSize));
   __ Ret();
 
@@ -6328,7 +6560,7 @@
   __ b(hs, &string_add_runtime);
 
   // If result is not supposed to be flat, allocate a cons string object.
-  // If both strings are ascii the result is an ascii cons string.
+  // If both strings are ASCII the result is an ASCII cons string.
   if (flags_ != NO_STRING_ADD_FLAGS) {
     __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
     __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
@@ -6349,13 +6581,13 @@
   __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset));
   __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset));
   __ mov(r0, Operand(r7));
-  __ IncrementCounter(&Counters::string_add_native, 1, r2, r3);
+  __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
   __ add(sp, sp, Operand(2 * kPointerSize));
   __ Ret();
 
   __ bind(&non_ascii);
   // At least one of the strings is two-byte. Check whether it happens
-  // to contain only ascii characters.
+  // to contain only ASCII characters.
   // r4: first instance type.
   // r5: second instance type.
   __ tst(r4, Operand(kAsciiDataHintMask));
@@ -6431,7 +6663,7 @@
   // r7: result string.
   StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, true);
   __ mov(r0, Operand(r7));
-  __ IncrementCounter(&Counters::string_add_native, 1, r2, r3);
+  __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
   __ add(sp, sp, Operand(2 * kPointerSize));
   __ Ret();
 
@@ -6472,7 +6704,7 @@
   StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false);
 
   __ mov(r0, Operand(r7));
-  __ IncrementCounter(&Counters::string_add_native, 1, r2, r3);
+  __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
   __ add(sp, sp, Operand(2 * kPointerSize));
   __ Ret();
 
@@ -6536,56 +6768,6 @@
 }
 
 
-void StringCharAtStub::Generate(MacroAssembler* masm) {
-  // Expects two arguments (object, index) on the stack:
-  //  lr: return address
-  //  sp[0]: index
-  //  sp[4]: object
-  Register object = r1;
-  Register index = r0;
-  Register scratch1 = r2;
-  Register scratch2 = r3;
-  Register result = r0;
-
-  // Get object and index from the stack.
-  __ pop(index);
-  __ pop(object);
-
-  Label need_conversion;
-  Label index_out_of_range;
-  Label done;
-  StringCharAtGenerator generator(object,
-                                  index,
-                                  scratch1,
-                                  scratch2,
-                                  result,
-                                  &need_conversion,
-                                  &need_conversion,
-                                  &index_out_of_range,
-                                  STRING_INDEX_IS_NUMBER);
-  generator.GenerateFast(masm);
-  __ b(&done);
-
-  __ bind(&index_out_of_range);
-  // When the index is out of range, the spec requires us to return
-  // the empty string.
-  __ LoadRoot(result, Heap::kEmptyStringRootIndex);
-  __ jmp(&done);
-
-  __ bind(&need_conversion);
-  // Move smi zero into the result register, which will trigger
-  // conversion.
-  __ mov(result, Operand(Smi::FromInt(0)));
-  __ b(&done);
-
-  StubRuntimeCallHelper call_helper;
-  generator.GenerateSlow(masm, call_helper);
-
-  __ bind(&done);
-  __ Ret();
-}
-
-
 void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
   ASSERT(state_ == CompareIC::SMIS);
   Label miss;
@@ -6625,7 +6807,7 @@
 
   // Inlining the double comparison and falling back to the general compare
   // stub if NaN is involved or VFP3 is unsupported.
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
 
     // Load left and right operand
@@ -6684,7 +6866,8 @@
   __ push(lr);
 
   // Call the runtime system in a fresh internal frame.
-  ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss));
+  ExternalReference miss =
+      ExternalReference(IC_Utility(IC::kCompareIC_Miss), masm->isolate());
   __ EnterInternalFrame();
   __ Push(r1, r0);
   __ mov(ip, Operand(Smi::FromInt(op_)));
@@ -6727,158 +6910,6 @@
 }
 
 
-void GenerateFastPixelArrayLoad(MacroAssembler* masm,
-                                Register receiver,
-                                Register key,
-                                Register elements_map,
-                                Register elements,
-                                Register scratch1,
-                                Register scratch2,
-                                Register result,
-                                Label* not_pixel_array,
-                                Label* key_not_smi,
-                                Label* out_of_range) {
-  // Register use:
-  //
-  // receiver - holds the receiver on entry.
-  //            Unchanged unless 'result' is the same register.
-  //
-  // key      - holds the smi key on entry.
-  //            Unchanged unless 'result' is the same register.
-  //
-  // elements - set to be the receiver's elements on exit.
-  //
-  // elements_map - set to be the map of the receiver's elements
-  //            on exit.
-  //
-  // result   - holds the result of the pixel array load on exit,
-  //            tagged as a smi if successful.
-  //
-  // Scratch registers:
-  //
-  // scratch1 - used a scratch register in map check, if map
-  //            check is successful, contains the length of the
-  //            pixel array, the pointer to external elements and
-  //            the untagged result.
-  //
-  // scratch2 - holds the untaged key.
-
-  // Some callers already have verified that the key is a smi.  key_not_smi is
-  // set to NULL as a sentinel for that case.  Otherwise, add an explicit check
-  // to ensure the key is a smi must be added.
-  if (key_not_smi != NULL) {
-    __ JumpIfNotSmi(key, key_not_smi);
-  } else {
-    if (FLAG_debug_code) {
-      __ AbortIfNotSmi(key);
-    }
-  }
-  __ SmiUntag(scratch2, key);
-
-  // Verify that the receiver has pixel array elements.
-  __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
-  __ CheckMap(elements, scratch1, Heap::kPixelArrayMapRootIndex,
-              not_pixel_array, true);
-
-  // Key must be in range of the pixel array.
-  __ ldr(scratch1, FieldMemOperand(elements, PixelArray::kLengthOffset));
-  __ cmp(scratch2, scratch1);
-  __ b(hs, out_of_range);  // unsigned check handles negative keys.
-
-  // Perform the indexed load and tag the result as a smi.
-  __ ldr(scratch1,
-         FieldMemOperand(elements, PixelArray::kExternalPointerOffset));
-  __ ldrb(scratch1, MemOperand(scratch1, scratch2));
-  __ SmiTag(r0, scratch1);
-  __ Ret();
-}
-
-
-void GenerateFastPixelArrayStore(MacroAssembler* masm,
-                                 Register receiver,
-                                 Register key,
-                                 Register value,
-                                 Register elements,
-                                 Register elements_map,
-                                 Register scratch1,
-                                 Register scratch2,
-                                 bool load_elements_from_receiver,
-                                 bool load_elements_map_from_elements,
-                                 Label* key_not_smi,
-                                 Label* value_not_smi,
-                                 Label* not_pixel_array,
-                                 Label* out_of_range) {
-  // Register use:
-  //   receiver - holds the receiver and is unchanged unless the
-  //              store succeeds.
-  //   key - holds the key (must be a smi) and is unchanged.
-  //   value - holds the value (must be a smi) and is unchanged.
-  //   elements - holds the element object of the receiver on entry if
-  //              load_elements_from_receiver is false, otherwise used
-  //              internally to store the pixel arrays elements and
-  //              external array pointer.
-  //   elements_map - holds the map of the element object if
-  //              load_elements_map_from_elements is false, otherwise
-  //              loaded with the element map.
-  //
-  Register external_pointer = elements;
-  Register untagged_key = scratch1;
-  Register untagged_value = scratch2;
-
-  if (load_elements_from_receiver) {
-    __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
-  }
-
-  // By passing NULL as not_pixel_array, callers signal that they have already
-  // verified that the receiver has pixel array elements.
-  if (not_pixel_array != NULL) {
-    if (load_elements_map_from_elements) {
-      __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
-    }
-    __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
-    __ cmp(elements_map, ip);
-    __ b(ne, not_pixel_array);
-  } else {
-    if (FLAG_debug_code) {
-      // Map check should have already made sure that elements is a pixel array.
-      __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
-      __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
-      __ cmp(elements_map, ip);
-      __ Assert(eq, "Elements isn't a pixel array");
-    }
-  }
-
-  // Some callers already have verified that the key is a smi.  key_not_smi is
-  // set to NULL as a sentinel for that case.  Otherwise, add an explicit check
-  // to ensure the key is a smi must be added.
-  if (key_not_smi != NULL) {
-    __ JumpIfNotSmi(key, key_not_smi);
-  } else {
-    if (FLAG_debug_code) {
-      __ AbortIfNotSmi(key);
-    }
-  }
-
-  __ SmiUntag(untagged_key, key);
-
-  // Perform bounds check.
-  __ ldr(scratch2, FieldMemOperand(elements, PixelArray::kLengthOffset));
-  __ cmp(untagged_key, scratch2);
-  __ b(hs, out_of_range);  // unsigned check handles negative keys.
-
-  __ JumpIfNotSmi(value, value_not_smi);
-  __ SmiUntag(untagged_value, value);
-
-  // Clamp the value to [0..255].
-  __ Usat(untagged_value, 8, Operand(untagged_value));
-  // Get the pointer to the external array. This clobbers elements.
-  __ ldr(external_pointer,
-         FieldMemOperand(elements, PixelArray::kExternalPointerOffset));
-  __ strb(untagged_value, MemOperand(external_pointer, untagged_key));
-  __ Ret();
-}
-
-
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/arm/code-stubs-arm.h b/src/arm/code-stubs-arm.h
index e3ef339..1dde255 100644
--- a/src/arm/code-stubs-arm.h
+++ b/src/arm/code-stubs-arm.h
@@ -235,7 +235,7 @@
         operands_type_(TRBinaryOpIC::UNINITIALIZED),
         result_type_(TRBinaryOpIC::UNINITIALIZED),
         name_(NULL) {
-    use_vfp3_ = CpuFeatures::IsSupported(VFP3);
+    use_vfp3_ = Isolate::Current()->cpu_features()->IsSupported(VFP3);
     ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
   }
 
@@ -311,6 +311,7 @@
   void GenerateSmiStub(MacroAssembler* masm);
   void GenerateInt32Stub(MacroAssembler* masm);
   void GenerateHeapNumberStub(MacroAssembler* masm);
+  void GenerateOddballStub(MacroAssembler* masm);
   void GenerateStringStub(MacroAssembler* masm);
   void GenerateGenericStub(MacroAssembler* masm);
   void GenerateAddStrings(MacroAssembler* masm);
@@ -588,6 +589,9 @@
  private:
   Major MajorKey() { return RegExpCEntry; }
   int MinorKey() { return 0; }
+
+  bool NeedsImmovableCode() { return true; }
+
   const char* GetName() { return "RegExpCEntryStub"; }
 };
 
@@ -607,60 +611,13 @@
  private:
   Major MajorKey() { return DirectCEntry; }
   int MinorKey() { return 0; }
+
+  bool NeedsImmovableCode() { return true; }
+
   const char* GetName() { return "DirectCEntryStub"; }
 };
 
 
-// Generate code to load an element from a pixel array. The receiver is assumed
-// to not be a smi and to have elements, the caller must guarantee this
-// precondition. If key is not a smi, then the generated code branches to
-// key_not_smi. Callers can specify NULL for key_not_smi to signal that a smi
-// check has already been performed on key so that the smi check is not
-// generated. If key is not a valid index within the bounds of the pixel array,
-// the generated code jumps to out_of_range. receiver, key and elements are
-// unchanged throughout the generated code sequence.
-void GenerateFastPixelArrayLoad(MacroAssembler* masm,
-                                Register receiver,
-                                Register key,
-                                Register elements_map,
-                                Register elements,
-                                Register scratch1,
-                                Register scratch2,
-                                Register result,
-                                Label* not_pixel_array,
-                                Label* key_not_smi,
-                                Label* out_of_range);
-
-// Generate code to store an element into a pixel array, clamping values between
-// [0..255]. The receiver is assumed to not be a smi and to have elements, the
-// caller must guarantee this precondition. If key is not a smi, then the
-// generated code branches to key_not_smi. Callers can specify NULL for
-// key_not_smi to signal that a smi check has already been performed on key so
-// that the smi check is not generated. If value is not a smi, the generated
-// code will branch to value_not_smi.  If the receiver doesn't have pixel array
-// elements, the generated code will branch to not_pixel_array, unless
-// not_pixel_array is NULL, in which case the caller must ensure that the
-// receiver has pixel array elements. If key is not a valid index within the
-// bounds of the pixel array, the generated code jumps to out_of_range. If
-// load_elements_from_receiver is true, then the elements of receiver is loaded
-// into elements, otherwise elements is assumed to already be the receiver's
-// elements. If load_elements_map_from_elements is true, elements_map is loaded
-// from elements, otherwise it is assumed to already contain the element map.
-void GenerateFastPixelArrayStore(MacroAssembler* masm,
-                                 Register receiver,
-                                 Register key,
-                                 Register value,
-                                 Register elements,
-                                 Register elements_map,
-                                 Register scratch1,
-                                 Register scratch2,
-                                 bool load_elements_from_receiver,
-                                 bool load_elements_map_from_elements,
-                                 Label* key_not_smi,
-                                 Label* value_not_smi,
-                                 Label* not_pixel_array,
-                                 Label* out_of_range);
-
 } }  // namespace v8::internal
 
 #endif  // V8_ARM_CODE_STUBS_ARM_H_
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index d32b009..91c4747 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -132,8 +132,6 @@
 // -------------------------------------------------------------------------
 // CodeGenerator implementation
 
-int CodeGenerator::inlined_write_barrier_size_ = -1;
-
 CodeGenerator::CodeGenerator(MacroAssembler* masm)
     : deferred_(8),
       masm_(masm),
@@ -307,7 +305,7 @@
     if (!scope()->HasIllegalRedeclaration()) {
       Comment cmnt(masm_, "[ function body");
 #ifdef DEBUG
-      bool is_builtin = Bootstrapper::IsActive();
+      bool is_builtin = Isolate::Current()->bootstrapper()->IsActive();
       bool should_trace =
           is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;
       if (should_trace) {
@@ -577,11 +575,13 @@
 
 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() {
   if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION;
-  ASSERT(scope()->arguments_shadow() != NULL);
+
+  // In strict mode there is no need for shadow arguments.
+  ASSERT(scope()->arguments_shadow() != NULL || scope()->is_strict_mode());
   // We don't want to do lazy arguments allocation for functions that
   // have heap-allocated contexts, because it interfers with the
   // uninitialized const tracking in the context objects.
-  return (scope()->num_heap_slots() > 0)
+  return (scope()->num_heap_slots() > 0 || scope()->is_strict_mode())
       ? EAGER_ARGUMENTS_ALLOCATION
       : LAZY_ARGUMENTS_ALLOCATION;
 }
@@ -599,7 +599,9 @@
     frame_->EmitPushRoot(Heap::kArgumentsMarkerRootIndex);
   } else {
     frame_->SpillAll();
-    ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
+    ArgumentsAccessStub stub(is_strict_mode()
+        ? ArgumentsAccessStub::NEW_STRICT
+        : ArgumentsAccessStub::NEW_NON_STRICT);
     __ ldr(r2, frame_->Function());
     // The receiver is below the arguments, the return address, and the
     // frame pointer on the stack.
@@ -615,7 +617,9 @@
   Variable* arguments = scope()->arguments();
   Variable* shadow = scope()->arguments_shadow();
   ASSERT(arguments != NULL && arguments->AsSlot() != NULL);
-  ASSERT(shadow != NULL && shadow->AsSlot() != NULL);
+  ASSERT((shadow != NULL && shadow->AsSlot() != NULL) ||
+         scope()->is_strict_mode());
+
   JumpTarget done;
   if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) {
     // We have to skip storing into the arguments slot if it has
@@ -629,7 +633,9 @@
   }
   StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT);
   if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind();
-  StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
+  if (shadow != NULL) {
+    StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
+  }
 }
 
 
@@ -764,7 +770,7 @@
     true_target->Branch(eq);
 
     // Slow case.
-    if (CpuFeatures::IsSupported(VFP3)) {
+    if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
       CpuFeatures::Scope scope(VFP3);
       // Implements the slow case by using ToBooleanStub.
       // The ToBooleanStub takes a single argument, and
@@ -961,7 +967,8 @@
 void DeferredInlineSmiOperation::JumpToAnswerOutOfRange(Condition cond) {
   ASSERT(Token::IsBitOp(op_));
 
-  if ((op_ == Token::SHR) && !CpuFeatures::IsSupported(VFP3)) {
+  if ((op_ == Token::SHR) &&
+      !Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     // >>> requires an unsigned to double conversion and the non VFP code
     // does not support this conversion.
     __ b(cond, entry_label());
@@ -1065,7 +1072,7 @@
 void DeferredInlineSmiOperation::WriteNonSmiAnswer(Register answer,
                                                    Register heap_number,
                                                    Register scratch) {
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
     __ vmov(s0, answer);
     if (op_ == Token::SHR) {
@@ -1135,7 +1142,7 @@
         // SHR is special because it is required to produce a positive answer.
         __ cmp(int32, Operand(0, RelocInfo::NONE));
       }
-      if (CpuFeatures::IsSupported(VFP3)) {
+      if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
         __ b(mi, &result_not_a_smi);
       } else {
         // Non VFP code cannot convert from unsigned to double, so fall back
@@ -1153,7 +1160,7 @@
   }
   // Check that the *signed* result fits in a smi. Not necessary for AND, SAR
   // if the shift if more than 0 or SHR if the shit is more than 1.
-  if (!( (op_ == Token::AND) ||
+  if (!( (op_ == Token::AND && value_ >= 0) ||
         ((op_ == Token::SAR) && (shift_value > 0)) ||
         ((op_ == Token::SHR) && (shift_value > 1)))) {
     __ add(r3, int32, Operand(0x40000000), SetCC);
@@ -1414,8 +1421,10 @@
           default: UNREACHABLE();
         }
         deferred->BindExit();
-        TypeInfo result_type =
-            (op == Token::BIT_AND) ? TypeInfo::Smi() : TypeInfo::Integer32();
+        TypeInfo result_type = TypeInfo::Integer32();
+        if (op == Token::BIT_AND && int_value >= 0) {
+          result_type = TypeInfo::Smi();
+        }
         frame_->EmitPush(tos, result_type);
       }
       break;
@@ -1714,7 +1723,7 @@
   // Load applicand.apply onto the stack. This will usually
   // give us a megamorphic load site. Not super, but it works.
   Load(applicand);
-  Handle<String> name = Factory::LookupAsciiSymbol("apply");
+  Handle<String> name = FACTORY->LookupAsciiSymbol("apply");
   frame_->Dup();
   frame_->CallLoadIC(name, RelocInfo::CODE_TARGET);
   frame_->EmitPush(r0);
@@ -1777,7 +1786,8 @@
   __ JumpIfSmi(r0, &build_args);
   __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE);
   __ b(ne, &build_args);
-  Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
+  Handle<Code> apply_code(
+      Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply));
   __ ldr(r1, FieldMemOperand(r0, JSFunction::kCodeEntryOffset));
   __ sub(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ cmp(r1, Operand(apply_code));
@@ -1992,7 +2002,7 @@
   // 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());
+    val = new Literal(FACTORY->the_hole_value());
   } else {
     val = node->fun();  // NULL if we don't have a function
   }
@@ -2849,7 +2859,7 @@
   function_return_is_shadowed_ = function_return_was_shadowed;
 
   // Get an external reference to the handler address.
-  ExternalReference handler_address(Top::k_handler_address);
+  ExternalReference handler_address(Isolate::k_handler_address, isolate());
 
   // If we can fall off the end of the try block, unlink from try chain.
   if (has_valid_frame()) {
@@ -2965,7 +2975,7 @@
   function_return_is_shadowed_ = function_return_was_shadowed;
 
   // Get an external reference to the handler address.
-  ExternalReference handler_address(Top::k_handler_address);
+  ExternalReference handler_address(Isolate::k_handler_address, isolate());
 
   // 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.
@@ -3106,10 +3116,11 @@
     bool pretenure) {
   // Use the fast case closure allocation code that allocates in new
   // space for nested functions that don't need literals cloning.
-  if (scope()->is_function_scope() &&
-      function_info->num_literals() == 0 &&
-      !pretenure) {
-    FastNewClosureStub stub;
+  if (!pretenure &&
+      scope()->is_function_scope() &&
+      function_info->num_literals() == 0) {
+    FastNewClosureStub stub(
+        function_info->strict_mode() ? kStrictMode : kNonStrictMode);
     frame_->EmitPush(Operand(function_info));
     frame_->SpillAll();
     frame_->CallStub(&stub, 1);
@@ -3119,8 +3130,8 @@
     frame_->EmitPush(cp);
     frame_->EmitPush(Operand(function_info));
     frame_->EmitPush(Operand(pretenure
-                             ? Factory::true_value()
-                             : Factory::false_value()));
+                             ? FACTORY->true_value()
+                             : FACTORY->false_value()));
     frame_->CallRuntime(Runtime::kNewClosure, 3);
     frame_->EmitPush(r0);
   }
@@ -3620,7 +3631,8 @@
         // else fall through
       case ObjectLiteral::Property::COMPUTED:
         if (key->handle()->IsSymbol()) {
-          Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+          Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+              Builtins::kStoreIC_Initialize));
           Load(value);
           if (property->emit_store()) {
             frame_->PopToR0();
@@ -3683,11 +3695,12 @@
   frame_->EmitPush(Operand(Smi::FromInt(node->literal_index())));
   frame_->EmitPush(Operand(node->constant_elements()));
   int length = node->values()->length();
-  if (node->constant_elements()->map() == Heap::fixed_cow_array_map()) {
+  if (node->constant_elements()->map() == HEAP->fixed_cow_array_map()) {
     FastCloneShallowArrayStub stub(
         FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
     frame_->CallStub(&stub, 3);
-    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1, r1, r2);
+    __ IncrementCounter(masm_->isolate()->counters()->cow_arrays_created_stub(),
+                        1, r1, r2);
   } else if (node->depth() > 1) {
     frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3);
   } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
@@ -4243,7 +4256,8 @@
     // Setup the name register and call the IC initialization code.
     __ mov(r2, Operand(var->name()));
     InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
-    Handle<Code> stub = StubCache::ComputeCallInitialize(arg_count, in_loop);
+    Handle<Code> stub =
+        ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop);
     CodeForSourcePosition(node->position());
     frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
                            arg_count + 1);
@@ -4338,7 +4352,7 @@
         __ mov(r2, Operand(name));
         InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
         Handle<Code> stub =
-            StubCache::ComputeCallInitialize(arg_count, in_loop);
+            ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop);
         CodeForSourcePosition(node->position());
         frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
         __ ldr(cp, frame_->Context());
@@ -4380,7 +4394,8 @@
         // Load the key into r2 and call the IC initialization code.
         InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
         Handle<Code> stub =
-            StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
+            ISOLATE->stub_cache()->ComputeKeyedCallInitialize(arg_count,
+                                                              in_loop);
         CodeForSourcePosition(node->position());
         frame_->SpillAll();
         __ ldr(r2, frame_->ElementAt(arg_count + 1));
@@ -4445,7 +4460,8 @@
   // Call the construct call builtin that handles allocation and
   // constructor invocation.
   CodeForSourcePosition(node->position());
-  Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      Builtins::kJSConstructCall));
   frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, arg_count + 1);
   frame_->EmitPush(r0);
 
@@ -4494,13 +4510,13 @@
 
   // Functions have class 'Function'.
   function.Bind();
-  __ mov(tos, Operand(Factory::function_class_symbol()));
+  __ mov(tos, Operand(FACTORY->function_class_symbol()));
   frame_->EmitPush(tos);
   leave.Jump();
 
   // Objects with a non-function constructor have class 'Object'.
   non_function_constructor.Bind();
-  __ mov(tos, Operand(Factory::Object_symbol()));
+  __ mov(tos, Operand(FACTORY->Object_symbol()));
   frame_->EmitPush(tos);
   leave.Jump();
 
@@ -4601,7 +4617,7 @@
   Load(args->at(0));
   Load(args->at(1));
 
-  if (!CpuFeatures::IsSupported(VFP3)) {
+  if (!Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     frame_->CallRuntime(Runtime::kMath_pow, 2);
     frame_->EmitPush(r0);
   } else {
@@ -4755,7 +4771,7 @@
   ASSERT(args->length() == 1);
   Load(args->at(0));
 
-  if (!CpuFeatures::IsSupported(VFP3)) {
+  if (!Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     frame_->CallRuntime(Runtime::kMath_sqrt, 1);
     frame_->EmitPush(r0);
   } else {
@@ -5141,7 +5157,7 @@
     Label entry, loop;
     // The use of ip to store the valueOf symbol asumes that it is not otherwise
     // used in the loop below.
-    __ mov(ip, Operand(Factory::value_of_symbol()));
+    __ mov(ip, Operand(FACTORY->value_of_symbol()));
     __ jmp(&entry);
     __ bind(&loop);
     __ ldr(scratch2_, MemOperand(map_result_, 0));
@@ -5344,9 +5360,9 @@
   // Convert 32 random bits in r0 to 0.(32 random bits) in a double
   // by computing:
   // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     __ PrepareCallCFunction(0, r1);
-    __ CallCFunction(ExternalReference::random_uint32_function(), 0);
+    __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 0);
 
     CpuFeatures::Scope scope(VFP3);
     // 0x41300000 is the top half of 1.0 x 2^20 as a double.
@@ -5367,7 +5383,7 @@
     __ mov(r0, Operand(r4));
     __ PrepareCallCFunction(1, r1);
     __ CallCFunction(
-        ExternalReference::fill_heap_number_with_random_function(), 1);
+        ExternalReference::fill_heap_number_with_random_function(isolate()), 1);
     frame_->EmitPush(r0);
   }
 }
@@ -5468,7 +5484,7 @@
   int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
 
   Handle<FixedArray> jsfunction_result_caches(
-      Top::global_context()->jsfunction_result_caches());
+      Isolate::Current()->global_context()->jsfunction_result_caches());
   if (jsfunction_result_caches->length() <= cache_id) {
     __ Abort("Attempt to use undefined cache.");
     frame_->EmitPushRoot(Heap::kUndefinedValueRootIndex);
@@ -5578,8 +5594,8 @@
   // Fetch the map and check if array is in fast case.
   // Check that object doesn't require security checks and
   // has no indexed interceptor.
-  __ CompareObjectType(object, tmp1, tmp2, FIRST_JS_OBJECT_TYPE);
-  deferred->Branch(lt);
+  __ CompareObjectType(object, tmp1, tmp2, JS_ARRAY_TYPE);
+  deferred->Branch(ne);
   __ ldrb(tmp2, FieldMemOperand(tmp1, Map::kBitFieldOffset));
   __ tst(tmp2, Operand(KeyedLoadIC::kSlowCaseBitFieldMask));
   deferred->Branch(ne);
@@ -5658,7 +5674,7 @@
 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
   ASSERT_EQ(args->length(), 1);
   Load(args->at(0));
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     TranscendentalCacheStub stub(TranscendentalCache::SIN,
                                  TranscendentalCacheStub::TAGGED);
     frame_->SpillAllButCopyTOSToR0();
@@ -5673,7 +5689,7 @@
 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
   ASSERT_EQ(args->length(), 1);
   Load(args->at(0));
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     TranscendentalCacheStub stub(TranscendentalCache::COS,
                                  TranscendentalCacheStub::TAGGED);
     frame_->SpillAllButCopyTOSToR0();
@@ -5688,7 +5704,7 @@
 void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) {
   ASSERT_EQ(args->length(), 1);
   Load(args->at(0));
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     TranscendentalCacheStub stub(TranscendentalCache::LOG,
                                  TranscendentalCacheStub::TAGGED);
     frame_->SpillAllButCopyTOSToR0();
@@ -5793,7 +5809,7 @@
 
   ZoneList<Expression*>* args = node->arguments();
   Comment cmnt(masm_, "[ CallRuntime");
-  Runtime::Function* function = node->function();
+  const Runtime::Function* function = node->function();
 
   if (function == NULL) {
     // Prepare stack for calling JS runtime function.
@@ -5817,7 +5833,8 @@
     // Call the JS runtime function.
     __ mov(r2, Operand(node->name()));
     InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
-    Handle<Code> stub = StubCache::ComputeCallInitialize(arg_count, in_loop);
+    Handle<Code> stub =
+        ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop);
     frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
     __ ldr(cp, frame_->Context());
     frame_->EmitPush(r0);
@@ -6352,7 +6369,7 @@
 
     Register scratch = VirtualFrame::scratch0();
 
-    if (check->Equals(Heap::number_symbol())) {
+    if (check->Equals(HEAP->number_symbol())) {
       __ tst(tos, Operand(kSmiTagMask));
       true_target()->Branch(eq);
       __ ldr(tos, FieldMemOperand(tos, HeapObject::kMapOffset));
@@ -6360,7 +6377,7 @@
       __ cmp(tos, ip);
       cc_reg_ = eq;
 
-    } else if (check->Equals(Heap::string_symbol())) {
+    } else if (check->Equals(HEAP->string_symbol())) {
       __ tst(tos, Operand(kSmiTagMask));
       false_target()->Branch(eq);
 
@@ -6376,7 +6393,7 @@
       __ cmp(scratch, Operand(FIRST_NONSTRING_TYPE));
       cc_reg_ = lt;
 
-    } else if (check->Equals(Heap::boolean_symbol())) {
+    } else if (check->Equals(HEAP->boolean_symbol())) {
       __ LoadRoot(ip, Heap::kTrueValueRootIndex);
       __ cmp(tos, ip);
       true_target()->Branch(eq);
@@ -6384,7 +6401,7 @@
       __ cmp(tos, ip);
       cc_reg_ = eq;
 
-    } else if (check->Equals(Heap::undefined_symbol())) {
+    } else if (check->Equals(HEAP->undefined_symbol())) {
       __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
       __ cmp(tos, ip);
       true_target()->Branch(eq);
@@ -6400,7 +6417,7 @@
 
       cc_reg_ = eq;
 
-    } else if (check->Equals(Heap::function_symbol())) {
+    } else if (check->Equals(HEAP->function_symbol())) {
       __ tst(tos, Operand(kSmiTagMask));
       false_target()->Branch(eq);
       Register map_reg = scratch;
@@ -6410,7 +6427,7 @@
       __ CompareInstanceType(map_reg, tos, JS_REGEXP_TYPE);
       cc_reg_ = eq;
 
-    } else if (check->Equals(Heap::object_symbol())) {
+    } else if (check->Equals(HEAP->object_symbol())) {
       __ tst(tos, Operand(kSmiTagMask));
       false_target()->Branch(eq);
 
@@ -6572,8 +6589,10 @@
   Register scratch1 = VirtualFrame::scratch0();
   Register scratch2 = VirtualFrame::scratch1();
   ASSERT(!receiver_.is(scratch1) && !receiver_.is(scratch2));
-  __ DecrementCounter(&Counters::named_load_inline, 1, scratch1, scratch2);
-  __ IncrementCounter(&Counters::named_load_inline_miss, 1, scratch1, scratch2);
+  __ DecrementCounter(masm_->isolate()->counters()->named_load_inline(),
+                      1, scratch1, scratch2);
+  __ IncrementCounter(masm_->isolate()->counters()->named_load_inline_miss(),
+                      1, scratch1, scratch2);
 
   // Ensure receiver in r0 and name in r2 to match load ic calling convention.
   __ Move(r0, receiver_);
@@ -6581,7 +6600,8 @@
 
   // The rest of the instructions in the deferred code must be together.
   { Assembler::BlockConstPoolScope block_const_pool(masm_);
-    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+    Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+        Builtins::kLoadIC_Initialize));
     RelocInfo::Mode mode = is_contextual_
         ? RelocInfo::CODE_TARGET_CONTEXT
         : RelocInfo::CODE_TARGET;
@@ -6643,8 +6663,10 @@
 
   Register scratch1 = VirtualFrame::scratch0();
   Register scratch2 = VirtualFrame::scratch1();
-  __ DecrementCounter(&Counters::keyed_load_inline, 1, scratch1, scratch2);
-  __ IncrementCounter(&Counters::keyed_load_inline_miss, 1, scratch1, scratch2);
+  __ DecrementCounter(masm_->isolate()->counters()->keyed_load_inline(),
+                      1, scratch1, scratch2);
+  __ IncrementCounter(masm_->isolate()->counters()->keyed_load_inline_miss(),
+                      1, scratch1, scratch2);
 
   // Ensure key in r0 and receiver in r1 to match keyed load ic calling
   // convention.
@@ -6655,7 +6677,8 @@
   // The rest of the instructions in the deferred code must be together.
   { Assembler::BlockConstPoolScope block_const_pool(masm_);
     // Call keyed load IC. It has the arguments key and receiver in r0 and r1.
-    Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+    Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+        Builtins::kKeyedLoadIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET);
     // The call must be followed by a nop instruction to indicate that the
     // keyed load has been inlined.
@@ -6702,9 +6725,10 @@
 void DeferredReferenceSetKeyedValue::Generate() {
   Register scratch1 = VirtualFrame::scratch0();
   Register scratch2 = VirtualFrame::scratch1();
-  __ DecrementCounter(&Counters::keyed_store_inline, 1, scratch1, scratch2);
-  __ IncrementCounter(
-      &Counters::keyed_store_inline_miss, 1, scratch1, scratch2);
+  __ DecrementCounter(masm_->isolate()->counters()->keyed_store_inline(),
+                      1, scratch1, scratch2);
+  __ IncrementCounter(masm_->isolate()->counters()->keyed_store_inline_miss(),
+                      1, scratch1, scratch2);
 
   // Ensure value in r0, key in r1 and receiver in r2 to match keyed store ic
   // calling convention.
@@ -6717,9 +6741,10 @@
   { Assembler::BlockConstPoolScope block_const_pool(masm_);
     // Call keyed store IC. It has the arguments value, key and receiver in r0,
     // r1 and r2.
-    Handle<Code> ic(Builtins::builtin(
-        (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
-                                      : Builtins::KeyedStoreIC_Initialize));
+    Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+        (strict_mode_ == kStrictMode)
+        ? Builtins::kKeyedStoreIC_Initialize_Strict
+        : Builtins::kKeyedStoreIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET);
     // The call must be followed by a nop instruction to indicate that the
     // keyed store has been inlined.
@@ -6772,9 +6797,9 @@
   { Assembler::BlockConstPoolScope block_const_pool(masm_);
     // Call keyed store IC. It has the arguments value, key and receiver in r0,
     // r1 and r2.
-    Handle<Code> ic(Builtins::builtin(
-        (strict_mode_ == kStrictMode) ? Builtins::StoreIC_Initialize_Strict
-                                      : Builtins::StoreIC_Initialize));
+    Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+        (strict_mode_ == kStrictMode) ? Builtins::kStoreIC_Initialize_Strict
+                                      : Builtins::kStoreIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET);
     // The call must be followed by a nop instruction to indicate that the
     // named store has been inlined.
@@ -6798,7 +6823,7 @@
 void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
   bool contextual_load_in_builtin =
       is_contextual &&
-      (Bootstrapper::IsActive() ||
+      (ISOLATE->bootstrapper()->IsActive() ||
       (!info_->closure().is_null() && info_->closure()->IsBuiltin()));
 
   if (scope()->is_global_scope() ||
@@ -6820,11 +6845,12 @@
     // Counter will be decremented in the deferred code. Placed here to avoid
     // having it in the instruction stream below where patching will occur.
     if (is_contextual) {
-      __ IncrementCounter(&Counters::named_load_global_inline, 1,
-                          frame_->scratch0(), frame_->scratch1());
+      __ IncrementCounter(
+          masm_->isolate()->counters()->named_load_global_inline(),
+          1, frame_->scratch0(), frame_->scratch1());
     } else {
-      __ IncrementCounter(&Counters::named_load_inline, 1,
-                          frame_->scratch0(), frame_->scratch1());
+      __ IncrementCounter(masm_->isolate()->counters()->named_load_inline(),
+                          1, frame_->scratch0(), frame_->scratch1());
     }
 
     // The following instructions are the inlined load of an in-object property.
@@ -6856,8 +6882,9 @@
         }
       }
       if (is_dont_delete) {
-        __ IncrementCounter(&Counters::dont_delete_hint_hit, 1,
-                            frame_->scratch0(), frame_->scratch1());
+        __ IncrementCounter(
+            masm_->isolate()->counters()->dont_delete_hint_hit(),
+            1, frame_->scratch0(), frame_->scratch1());
       }
     }
 
@@ -6893,7 +6920,7 @@
       // Check the map. The null map used below is patched by the inline cache
       // code.  Therefore we can't use a LoadRoot call.
       __ ldr(scratch, FieldMemOperand(receiver, HeapObject::kMapOffset));
-      __ mov(scratch2, Operand(Factory::null_value()));
+      __ mov(scratch2, Operand(FACTORY->null_value()));
       __ cmp(scratch, scratch2);
       deferred->Branch(ne);
 
@@ -6902,7 +6929,7 @@
         InlinedNamedLoadInstructions += 1;
 #endif
         // Load the (initially invalid) cell and get its value.
-        masm()->mov(receiver, Operand(Factory::null_value()));
+        masm()->mov(receiver, Operand(FACTORY->null_value()));
         __ ldr(receiver,
                FieldMemOperand(receiver, JSGlobalPropertyCell::kValueOffset));
 
@@ -6912,13 +6939,13 @@
 #ifdef DEBUG
           InlinedNamedLoadInstructions += 3;
 #endif
-          __ cmp(receiver, Operand(Factory::the_hole_value()));
+          __ cmp(receiver, Operand(FACTORY->the_hole_value()));
           deferred->Branch(eq);
         } else if (FLAG_debug_code) {
 #ifdef DEBUG
           InlinedNamedLoadInstructions += 3;
 #endif
-          __ cmp(receiver, Operand(Factory::the_hole_value()));
+          __ cmp(receiver, Operand(FACTORY->the_hole_value()));
           __ b(&check_the_hole, eq);
           __ bind(&cont);
         }
@@ -6986,7 +7013,7 @@
       Label check_inlined_codesize;
       masm_->bind(&check_inlined_codesize);
 #endif
-      __ mov(scratch0, Operand(Factory::null_value()));
+      __ mov(scratch0, Operand(FACTORY->null_value()));
       __ cmp(scratch0, scratch1);
       deferred->Branch(ne);
 
@@ -7016,11 +7043,11 @@
       // Check that this is the first inlined write barrier or that
       // this inlined write barrier has the same size as all the other
       // inlined write barriers.
-      ASSERT((inlined_write_barrier_size_ == -1) ||
-             (inlined_write_barrier_size_ ==
+      ASSERT((Isolate::Current()->inlined_write_barrier_size() == -1) ||
+             (Isolate::Current()->inlined_write_barrier_size() ==
               masm()->InstructionsGeneratedSince(&record_write_start)));
-      inlined_write_barrier_size_ =
-          masm()->InstructionsGeneratedSince(&record_write_start);
+      Isolate::Current()->set_inlined_write_barrier_size(
+          masm()->InstructionsGeneratedSince(&record_write_start));
 
       // Make sure that the expected number of instructions are generated.
       ASSERT_EQ(GetInlinedNamedStoreInstructionsAfterPatch(),
@@ -7042,8 +7069,8 @@
 
     // Counter will be decremented in the deferred code. Placed here to avoid
     // having it in the instruction stream below where patching will occur.
-    __ IncrementCounter(&Counters::keyed_load_inline, 1,
-                        frame_->scratch0(), frame_->scratch1());
+    __ IncrementCounter(masm_->isolate()->counters()->keyed_load_inline(),
+                        1, frame_->scratch0(), frame_->scratch1());
 
     // Load the key and receiver from the stack.
     bool key_is_known_smi = frame_->KnownSmiAt(0);
@@ -7079,7 +7106,7 @@
       Label check_inlined_codesize;
       masm_->bind(&check_inlined_codesize);
 #endif
-      __ mov(scratch2, Operand(Factory::null_value()));
+      __ mov(scratch2, Operand(FACTORY->null_value()));
       __ cmp(scratch1, scratch2);
       deferred->Branch(ne);
 
@@ -7129,9 +7156,8 @@
 
     // Counter will be decremented in the deferred code. Placed here to avoid
     // having it in the instruction stream below where patching will occur.
-    __ IncrementCounter(&Counters::keyed_store_inline, 1,
-                        scratch1, scratch2);
-
+    __ IncrementCounter(masm_->isolate()->counters()->keyed_store_inline(),
+                        1, scratch1, scratch2);
 
 
     // Load the value, key and receiver from the stack.
@@ -7181,18 +7207,14 @@
     __ CompareObjectType(receiver, scratch1, scratch1, JS_ARRAY_TYPE);
     deferred->Branch(ne);
 
-    // Check that the key is within bounds. Both the key and the length of
-    // the JSArray are smis. Use unsigned comparison to handle negative keys.
-    __ ldr(scratch1, FieldMemOperand(receiver, JSArray::kLengthOffset));
-    __ cmp(scratch1, key);
-    deferred->Branch(ls);  // Unsigned less equal.
-
     // Get the elements array from the receiver.
     __ ldr(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset));
     if (!value_is_harmless && wb_info != LIKELY_SMI) {
       Label ok;
-      __ and_(scratch2, scratch1, Operand(ExternalReference::new_space_mask()));
-      __ cmp(scratch2, Operand(ExternalReference::new_space_start()));
+      __ and_(scratch2,
+              scratch1,
+              Operand(ExternalReference::new_space_mask(isolate())));
+      __ cmp(scratch2, Operand(ExternalReference::new_space_start(isolate())));
       __ tst(value, Operand(kSmiTagMask), ne);
       deferred->Branch(ne);
 #ifdef DEBUG
@@ -7201,6 +7223,7 @@
     }
     // Check that the elements array is not a dictionary.
     __ ldr(scratch2, FieldMemOperand(scratch1, JSObject::kMapOffset));
+
     // The following instructions are the part of the inlined store keyed
     // property code which can be patched. Therefore the exact number of
     // instructions generated need to be fixed, so the constant pool is blocked
@@ -7216,10 +7239,18 @@
       // comparison to always fail so that we will hit the IC call in the
       // deferred code which will allow the debugger to break for fast case
       // stores.
-      __ mov(scratch3, Operand(Factory::fixed_array_map()));
+      __ mov(scratch3, Operand(FACTORY->fixed_array_map()));
       __ cmp(scratch2, scratch3);
       deferred->Branch(ne);
 
+      // Check that the key is within bounds.  Both the key and the length of
+      // the JSArray are smis (because the fixed array check above ensures the
+      // elements are in fast case). Use unsigned comparison to handle negative
+      // keys.
+      __ ldr(scratch3, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ cmp(scratch3, key);
+      deferred->Branch(ls);  // Unsigned less equal.
+
       // Store the value.
       __ add(scratch1, scratch1,
              Operand(FixedArray::kHeaderSize - kHeapObjectTag));
@@ -7378,7 +7409,7 @@
 const char* GenericBinaryOpStub::GetName() {
   if (name_ != NULL) return name_;
   const int len = 100;
-  name_ = Bootstrapper::AllocateAutoDeletedArray(len);
+  name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(len);
   if (name_ == NULL) return "OOM";
   const char* op_name = Token::Name(op_);
   const char* overwrite_name;
@@ -7398,7 +7429,6 @@
   return name_;
 }
 
-
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index 8f46256..9b1f103 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -268,10 +268,10 @@
   static int GetInlinedKeyedLoadInstructionsAfterPatch() {
     return FLAG_debug_code ? 32 : 13;
   }
-  static const int kInlinedKeyedStoreInstructionsAfterPatch = 5;
+  static const int kInlinedKeyedStoreInstructionsAfterPatch = 8;
   static int GetInlinedNamedStoreInstructionsAfterPatch() {
-    ASSERT(inlined_write_barrier_size_ != -1);
-    return inlined_write_barrier_size_ + 4;
+    ASSERT(Isolate::Current()->inlined_write_barrier_size() != -1);
+    return Isolate::Current()->inlined_write_barrier_size() + 4;
   }
 
  private:
@@ -287,6 +287,7 @@
   // Accessors
   inline bool is_eval();
   inline Scope* scope();
+  inline bool is_strict_mode();
   inline StrictModeFlag strict_mode_flag();
 
   // Generating deferred code.
@@ -575,15 +576,14 @@
   // to some unlinking code).
   bool function_return_is_shadowed_;
 
-  // Size of inlined write barriers generated by EmitNamedStore.
-  static int inlined_write_barrier_size_;
-
   friend class VirtualFrame;
+  friend class Isolate;
   friend class JumpTarget;
   friend class Reference;
   friend class FastCodeGenerator;
   friend class FullCodeGenerator;
   friend class FullCodeGenSyntaxChecker;
+  friend class InlineRuntimeFunctionsTable;
   friend class LCodeGen;
 
   DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
diff --git a/src/arm/constants-arm.h b/src/arm/constants-arm.h
index e6033a8..0ac567c 100644
--- a/src/arm/constants-arm.h
+++ b/src/arm/constants-arm.h
@@ -89,6 +89,11 @@
 namespace v8 {
 namespace internal {
 
+// Constant pool marker.
+static const int kConstantPoolMarkerMask = 0xffe00000;
+static const int kConstantPoolMarker = 0x0c000000;
+static const int kConstantPoolLengthMask = 0x001ffff;
+
 // Number of registers in normal ARM mode.
 static const int kNumRegisters = 16;
 
@@ -388,9 +393,11 @@
 // This mask does not include the "inexact" or "input denormal" cumulative
 // exceptions flags, because we usually don't want to check for it.
 static const uint32_t kVFPExceptionMask = 0xf;
+static const uint32_t kVFPInvalidOpExceptionBit = 1 << 0;
+static const uint32_t kVFPOverflowExceptionBit = 1 << 2;
+static const uint32_t kVFPUnderflowExceptionBit = 1 << 3;
 static const uint32_t kVFPInexactExceptionBit = 1 << 4;
 static const uint32_t kVFPFlushToZeroMask = 1 << 24;
-static const uint32_t kVFPInvalidExceptionBit = 1;
 
 static const uint32_t kVFPNConditionFlagBit = 1 << 31;
 static const uint32_t kVFPZConditionFlagBit = 1 << 30;
diff --git a/src/arm/cpu-arm.cc b/src/arm/cpu-arm.cc
index 51c84b3..0f5bf56 100644
--- a/src/arm/cpu-arm.cc
+++ b/src/arm/cpu-arm.cc
@@ -42,8 +42,9 @@
 namespace internal {
 
 void CPU::Setup() {
-  CpuFeatures::Probe(true);
-  if (!CpuFeatures::IsSupported(VFP3) || Serializer::enabled()) {
+  CpuFeatures* cpu_features = Isolate::Current()->cpu_features();
+  cpu_features->Probe(true);
+  if (!cpu_features->IsSupported(VFP3) || Serializer::enabled()) {
     V8::DisableCrankshaft();
   }
 }
@@ -61,7 +62,7 @@
   // that the Icache was flushed.
   // None of this code ends up in the snapshot so there are no issues
   // around whether or not to generate the code when building snapshots.
-  Simulator::FlushICache(start, size);
+  Simulator::FlushICache(Isolate::Current()->simulator_i_cache(), start, size);
 #else
   // Ideally, we would call
   //   syscall(__ARM_NR_cacheflush, start,
diff --git a/src/arm/debug-arm.cc b/src/arm/debug-arm.cc
index f19e693..e6ad98c 100644
--- a/src/arm/debug-arm.cc
+++ b/src/arm/debug-arm.cc
@@ -65,7 +65,7 @@
   patcher.masm()->mov(v8::internal::lr, v8::internal::pc);
   patcher.masm()->ldr(v8::internal::pc, MemOperand(v8::internal::pc, -4));
 #endif
-  patcher.Emit(Debug::debug_break_return()->entry());
+  patcher.Emit(Isolate::Current()->debug()->debug_break_return()->entry());
   patcher.masm()->bkpt(0);
 }
 
@@ -115,7 +115,7 @@
   patcher.masm()->mov(v8::internal::lr, v8::internal::pc);
   patcher.masm()->ldr(v8::internal::pc, MemOperand(v8::internal::pc, -4));
 #endif
-  patcher.Emit(Debug::debug_break_return()->entry());
+  patcher.Emit(Isolate::Current()->debug()->debug_break_slot()->entry());
 }
 
 
@@ -159,7 +159,7 @@
   __ RecordComment("// Calling from debug break to runtime - come in - over");
 #endif
   __ mov(r0, Operand(0, RelocInfo::NONE));  // no arguments
-  __ mov(r1, Operand(ExternalReference::debug_break()));
+  __ mov(r1, Operand(ExternalReference::debug_break(masm->isolate())));
 
   CEntryStub ceb(1);
   __ CallStub(&ceb);
@@ -185,7 +185,9 @@
   // 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())));
+  ExternalReference after_break_target =
+      ExternalReference(Debug_Address::AfterBreakTarget(), masm->isolate());
+  __ mov(ip, Operand(after_break_target));
   __ ldr(ip, MemOperand(ip));
   __ Jump(ip);
 }
diff --git a/src/arm/deoptimizer-arm.cc b/src/arm/deoptimizer-arm.cc
index 9a5aa90..3a3dcf0 100644
--- a/src/arm/deoptimizer-arm.cc
+++ b/src/arm/deoptimizer-arm.cc
@@ -44,8 +44,14 @@
 }
 
 
+void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
+  // Nothing to do. No new relocation information is written for lazy
+  // deoptimization on ARM.
+}
+
 
 void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
+  HandleScope scope;
   AssertNoAllocation no_allocation;
 
   if (!function->IsOptimized()) return;
@@ -69,8 +75,6 @@
     int deoptimization_index = safepoint_entry.deoptimization_index();
     int gap_code_size = safepoint_entry.gap_code_size();
     // Check that we did not shoot past next safepoint.
-    // TODO(srdjan): How do we guarantee that safepoint code does not
-    // overlap other safepoint patching code?
     CHECK(pc_offset >= last_pc_offset);
 #ifdef DEBUG
     // Destroy the code which is not supposed to be run again.
@@ -107,8 +111,9 @@
 
   // Add the deoptimizing code to the list.
   DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code);
-  node->set_next(deoptimizing_code_list_);
-  deoptimizing_code_list_ = node;
+  DeoptimizerData* data = code->GetIsolate()->deoptimizer_data();
+  node->set_next(data->deoptimizing_code_list_);
+  data->deoptimizing_code_list_ = node;
 
   // Set the code for the function to non-optimized version.
   function->ReplaceCode(function->shared()->code());
@@ -117,6 +122,11 @@
     PrintF("[forced deoptimization: ");
     function->PrintName();
     PrintF(" / %x]\n", reinterpret_cast<uint32_t>(function));
+#ifdef DEBUG
+    if (FLAG_print_code) {
+      code->PrintLn();
+    }
+#endif
   }
 }
 
@@ -278,14 +288,33 @@
 
   // There are no translation commands for the caller's pc and fp, the
   // context, and the function.  Set them up explicitly.
-  for (int i = 0; ok && i < 4; i++) {
+  for (int i =  StandardFrameConstants::kCallerPCOffset;
+       ok && i >=  StandardFrameConstants::kMarkerOffset;
+       i -= kPointerSize) {
     uint32_t input_value = input_->GetFrameSlot(input_offset);
     if (FLAG_trace_osr) {
-      PrintF("    [sp + %d] <- 0x%08x ; [sp + %d] (fixed part)\n",
+      const char* name = "UNKNOWN";
+      switch (i) {
+        case StandardFrameConstants::kCallerPCOffset:
+          name = "caller's pc";
+          break;
+        case StandardFrameConstants::kCallerFPOffset:
+          name = "fp";
+          break;
+        case StandardFrameConstants::kContextOffset:
+          name = "context";
+          break;
+        case StandardFrameConstants::kMarkerOffset:
+          name = "function";
+          break;
+      }
+      PrintF("    [sp + %d] <- 0x%08x ; [sp + %d] (fixed part - %s)\n",
              output_offset,
              input_value,
-             input_offset);
+             input_offset,
+             name);
     }
+
     output_[0]->SetFrameSlot(output_offset, input_->GetFrameSlot(input_offset));
     input_offset -= kPointerSize;
     output_offset -= kPointerSize;
@@ -311,7 +340,7 @@
         optimized_code_->entry() + pc_offset);
     output_[0]->SetPc(pc);
   }
-  Code* continuation = Builtins::builtin(Builtins::NotifyOSR);
+  Code* continuation = isolate_->builtins()->builtin(Builtins::kNotifyOSR);
   output_[0]->SetContinuation(
       reinterpret_cast<uint32_t>(continuation->entry()));
 
@@ -485,11 +514,13 @@
       FullCodeGenerator::StateField::decode(pc_and_state);
   output_frame->SetState(Smi::FromInt(state));
 
+
   // Set the continuation for the topmost frame.
   if (is_topmost) {
+    Builtins* builtins = isolate_->builtins();
     Code* continuation = (bailout_type_ == EAGER)
-        ? Builtins::builtin(Builtins::NotifyDeoptimized)
-        : Builtins::builtin(Builtins::NotifyLazyDeoptimized);
+        ? builtins->builtin(Builtins::kNotifyDeoptimized)
+        : builtins->builtin(Builtins::kNotifyLazyDeoptimized);
     output_frame->SetContinuation(
         reinterpret_cast<uint32_t>(continuation->entry()));
   }
@@ -505,6 +536,9 @@
 // easily ported.
 void Deoptimizer::EntryGenerator::Generate() {
   GeneratePrologue();
+
+  Isolate* isolate = masm()->isolate();
+
   CpuFeatures::Scope scope(VFP3);
   // Save all general purpose registers before messing with them.
   const int kNumberOfRegisters = Register::kNumRegisters;
@@ -559,7 +593,7 @@
   // r3: code address or 0 already loaded.
   __ str(r4, MemOperand(sp, 0 * kPointerSize));  // Fp-to-sp delta.
   // Call Deoptimizer::New().
-  __ CallCFunction(ExternalReference::new_deoptimizer_function(), 5);
+  __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate), 5);
 
   // Preserve "deoptimizer" object in register r0 and get the input
   // frame descriptor pointer to r1 (deoptimizer->input_);
@@ -613,7 +647,8 @@
   // r0: deoptimizer object; r1: scratch.
   __ PrepareCallCFunction(1, r1);
   // Call Deoptimizer::ComputeOutputFrames().
-  __ CallCFunction(ExternalReference::compute_output_frames_function(), 1);
+  __ CallCFunction(
+      ExternalReference::compute_output_frames_function(isolate), 1);
   __ pop(r0);  // Restore deoptimizer object (class Deoptimizer).
 
   // Replace the current (input) frame with the output frames.
@@ -663,7 +698,7 @@
   __ pop(ip);  // remove lr
 
   // Set up the roots register.
-  ExternalReference roots_address = ExternalReference::roots_address();
+  ExternalReference roots_address = ExternalReference::roots_address(isolate);
   __ mov(r10, Operand(roots_address));
 
   __ pop(ip);  // remove pc
diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc
index 08f605b..899b88a 100644
--- a/src/arm/disasm-arm.cc
+++ b/src/arm/disasm-arm.cc
@@ -89,6 +89,9 @@
   // Returns the length of the disassembled machine instruction in bytes.
   int InstructionDecode(byte* instruction);
 
+  static bool IsConstantPoolAt(byte* instr_ptr);
+  static int ConstantPoolSizeAt(byte* instr_ptr);
+
  private:
   // Bottleneck functions to print into the out_buffer.
   void PrintChar(const char ch);
@@ -899,6 +902,7 @@
     case da_x: {
       if (instr->HasW()) {
         Unknown(instr);  // not used in V8
+        return;
       }
       Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
       break;
@@ -906,6 +910,7 @@
     case ia_x: {
       if (instr->HasW()) {
         Unknown(instr);  // not used in V8
+        return;
       }
       Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
       break;
@@ -992,11 +997,15 @@
 
 
 void Decoder::DecodeType4(Instruction* instr) {
-  ASSERT(instr->Bit(22) == 0);  // Privileged mode currently not supported.
-  if (instr->HasL()) {
-    Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
+  if (instr->Bit(22) != 0) {
+    // Privileged mode currently not supported.
+    Unknown(instr);
   } else {
-    Format(instr, "stm'cond'pu 'rn'w, 'rlist");
+    if (instr->HasL()) {
+      Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
+    } else {
+      Format(instr, "stm'cond'pu 'rn'w, 'rlist");
+    }
   }
 }
 
@@ -1042,6 +1051,8 @@
 // vmov: Rt = Sn
 // vcvt: Dd = Sm
 // vcvt: Sd = Dm
+// Dd = vabs(Dm)
+// Dd = vneg(Dm)
 // Dd = vadd(Dn, Dm)
 // Dd = vsub(Dn, Dm)
 // Dd = vmul(Dn, Dm)
@@ -1067,6 +1078,9 @@
       } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
         // vabs
         Format(instr, "vabs'cond 'Dd, 'Dm");
+      } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
+        // vneg
+        Format(instr, "vneg'cond 'Dd, 'Dm");
       } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
         DecodeVCVTBetweenDoubleAndSingle(instr);
       } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
@@ -1294,7 +1308,23 @@
         break;
     }
   } else {
-    UNIMPLEMENTED();  // Not used by V8.
+    Unknown(instr);  // Not used by V8.
+  }
+}
+
+
+bool Decoder::IsConstantPoolAt(byte* instr_ptr) {
+  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
+  return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker;
+}
+
+
+int Decoder::ConstantPoolSizeAt(byte* instr_ptr) {
+  if (IsConstantPoolAt(instr_ptr)) {
+    int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
+    return instruction_bits & kConstantPoolLengthMask;
+  } else {
+    return -1;
   }
 }
 
@@ -1307,7 +1337,15 @@
                                   "%08x       ",
                                   instr->InstructionBits());
   if (instr->ConditionField() == kSpecialCondition) {
-    UNIMPLEMENTED();
+    Unknown(instr);
+    return Instruction::kInstrSize;
+  }
+  int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
+  if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) {
+    out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                    "constant pool begin (length %d)",
+                                    instruction_bits &
+                                    kConstantPoolLengthMask);
     return Instruction::kInstrSize;
   }
   switch (instr->TypeValue()) {
@@ -1359,9 +1397,8 @@
 
 
 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();
+  v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
+  return tmp_buffer_.start();
 }
 
 
@@ -1411,12 +1448,7 @@
 
 
 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
-  int instruction_bits = *(reinterpret_cast<int*>(instruction));
-  if ((instruction_bits & 0xfff00000) == 0x03000000) {
-    return instruction_bits & 0x0000ffff;
-  } else {
-    return -1;
-  }
+  return v8::internal::Decoder::ConstantPoolSizeAt(instruction);
 }
 
 
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 5f5de3a..088ba58 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -210,13 +210,18 @@
     //   function, receiver address, parameter count.
     // The stub will rewrite receiever and parameter count if the previous
     // stack frame was an arguments adapter frame.
-    ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
+    ArgumentsAccessStub stub(
+        is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT
+                         : ArgumentsAccessStub::NEW_NON_STRICT);
     __ CallStub(&stub);
-    // Duplicate the value; move-to-slot operation might clobber registers.
-    __ mov(r3, r0);
+
+    Variable* arguments_shadow = scope()->arguments_shadow();
+    if (arguments_shadow != NULL) {
+      // Duplicate the value; move-to-slot operation might clobber registers.
+      __ mov(r3, r0);
+      Move(arguments_shadow->AsSlot(), r3, r1, r2);
+    }
     Move(arguments->AsSlot(), r0, r1, r2);
-    Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot();
-    Move(dot_arguments_slot, r3, r1, r2);
   }
 
   if (FLAG_trace) {
@@ -557,7 +562,7 @@
 void FullCodeGenerator::DoTest(Label* if_true,
                                Label* if_false,
                                Label* fall_through) {
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
     // Emit the inlined tests assumed by the stub.
     __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
@@ -776,9 +781,9 @@
              prop->key()->AsLiteral()->handle()->IsSmi());
       __ mov(r1, Operand(prop->key()->AsLiteral()->handle()));
 
-      Handle<Code> ic(Builtins::builtin(is_strict()
-          ? Builtins::KeyedStoreIC_Initialize_Strict
-          : Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic = is_strict_mode()
+          ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+          : isolate()->builtins()->KeyedStoreIC_Initialize();
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       // Value in r0 is ignored (declarations are statements).
     }
@@ -875,6 +880,7 @@
     Comment cmnt(masm_, "[ Case body");
     CaseClause* clause = clauses->at(i);
     __ bind(clause->body_target()->entry_label());
+    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
     VisitStatements(clause->statements());
   }
 
@@ -1080,10 +1086,10 @@
   // doesn't just get a copy of the existing unoptimized code.
   if (!FLAG_always_opt &&
       !FLAG_prepare_always_opt &&
+      !pretenure &&
       scope()->is_function_scope() &&
-      info->num_literals() == 0 &&
-      !pretenure) {
-    FastNewClosureStub stub;
+      info->num_literals() == 0) {
+    FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode);
     __ mov(r0, Operand(info));
     __ push(r0);
     __ CallStub(&stub);
@@ -1180,7 +1186,8 @@
                  ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
                                                    slow));
           __ mov(r0, Operand(key_literal->handle()));
-          Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+          Handle<Code> ic =
+              isolate()->builtins()->KeyedLoadIC_Initialize();
           EmitCallIC(ic, RelocInfo::CODE_TARGET);
           __ jmp(done);
         }
@@ -1246,7 +1253,7 @@
   RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
       ? RelocInfo::CODE_TARGET
       : RelocInfo::CODE_TARGET_CONTEXT;
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   EmitCallIC(ic, mode);
 }
 
@@ -1264,7 +1271,7 @@
     // object (receiver) in r0.
     __ ldr(r0, GlobalObjectOperand());
     __ mov(r2, Operand(var->name()));
-    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
     EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
     context()->Plug(r0);
 
@@ -1323,7 +1330,7 @@
     __ mov(r0, Operand(key_literal->handle()));
 
     // Call keyed load IC. It has arguments key and receiver in r0 and r1.
-    Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+    Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
     EmitCallIC(ic, RelocInfo::CODE_TARGET);
     context()->Plug(r0);
   }
@@ -1387,7 +1394,13 @@
   __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
   __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
   __ mov(r1, Operand(expr->constant_properties()));
-  __ mov(r0, Operand(Smi::FromInt(expr->fast_elements() ? 1 : 0)));
+  int flags = expr->fast_elements()
+      ? ObjectLiteral::kFastElements
+      : ObjectLiteral::kNoFlags;
+  flags |= expr->has_function()
+      ? ObjectLiteral::kHasFunction
+      : ObjectLiteral::kNoFlags;
+  __ mov(r0, Operand(Smi::FromInt(flags)));
   __ Push(r3, r2, r1, r0);
   if (expr->depth() > 1) {
     __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
@@ -1426,7 +1439,7 @@
             VisitForAccumulatorValue(value);
             __ mov(r2, Operand(key->handle()));
             __ ldr(r1, MemOperand(sp));
-            Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+            Handle<Code> ic = isolate()->builtins()->StoreIC_Initialize();
             EmitCallIC(ic, RelocInfo::CODE_TARGET);
             PrepareForBailoutForId(key->id(), NO_REGISTERS);
           } else {
@@ -1465,6 +1478,13 @@
     }
   }
 
+  if (expr->has_function()) {
+    ASSERT(result_saved);
+    __ ldr(r0, MemOperand(sp));
+    __ push(r0);
+    __ CallRuntime(Runtime::kToFastProperties, 1);
+  }
+
   if (result_saved) {
     context()->PlugTOS();
   } else {
@@ -1484,11 +1504,13 @@
   __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
   __ mov(r1, Operand(expr->constant_elements()));
   __ Push(r3, r2, r1);
-  if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) {
+  if (expr->constant_elements()->map() ==
+      isolate()->heap()->fixed_cow_array_map()) {
     FastCloneShallowArrayStub stub(
         FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
     __ CallStub(&stub);
-    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1, r1, r2);
+    __ IncrementCounter(
+        isolate()->counters()->cow_arrays_created_stub(), 1, r1, r2);
   } else if (expr->depth() > 1) {
     __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
   } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
@@ -1672,7 +1694,7 @@
   Literal* key = prop->key()->AsLiteral();
   __ mov(r2, Operand(key->handle()));
   // Call load IC. It has arguments receiver and property name r0 and r2.
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 }
 
@@ -1680,7 +1702,7 @@
 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
   SetSourcePosition(prop->position());
   // Call keyed load IC. It has arguments key and receiver in r0 and r1.
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 }
 
@@ -1825,9 +1847,9 @@
       __ mov(r1, r0);
       __ pop(r0);  // Restore value.
       __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
-      Handle<Code> ic(Builtins::builtin(
-          is_strict() ? Builtins::StoreIC_Initialize_Strict
-                      : Builtins::StoreIC_Initialize));
+      Handle<Code> ic = is_strict_mode()
+          ? isolate()->builtins()->StoreIC_Initialize_Strict()
+          : isolate()->builtins()->StoreIC_Initialize();
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
@@ -1848,9 +1870,9 @@
         __ pop(r2);
       }
       __ pop(r0);  // Restore value.
-      Handle<Code> ic(Builtins::builtin(
-          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
-                      : Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic = is_strict_mode()
+          ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+          : isolate()->builtins()->KeyedStoreIC_Initialize();
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
@@ -1874,9 +1896,9 @@
     // r2, and the global object in r1.
     __ mov(r2, Operand(var->name()));
     __ ldr(r1, GlobalObjectOperand());
-    Handle<Code> ic(Builtins::builtin(
-        is_strict() ? Builtins::StoreIC_Initialize_Strict
-                    : Builtins::StoreIC_Initialize));
+    Handle<Code> ic = is_strict_mode()
+        ? isolate()->builtins()->StoreIC_Initialize_Strict()
+        : isolate()->builtins()->StoreIC_Initialize();
     EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
 
   } else if (op == Token::INIT_CONST) {
@@ -1983,9 +2005,9 @@
     __ pop(r1);
   }
 
-  Handle<Code> ic(Builtins::builtin(
-      is_strict() ? Builtins::StoreIC_Initialize_Strict
-                  : Builtins::StoreIC_Initialize));
+  Handle<Code> ic = is_strict_mode()
+      ? isolate()->builtins()->StoreIC_Initialize_Strict()
+      : isolate()->builtins()->StoreIC_Initialize();
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -2029,9 +2051,9 @@
     __ pop(r2);
   }
 
-  Handle<Code> ic(Builtins::builtin(
-      is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
-                  : Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic = is_strict_mode()
+      ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+      : isolate()->builtins()->KeyedStoreIC_Initialize();
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -2082,7 +2104,8 @@
   SetSourcePosition(expr->position());
   // Call the IC initialization code.
   InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
+  Handle<Code> ic =
+      isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop);
   EmitCallIC(ic, mode);
   RecordJSReturnSite(expr);
   // Restore context register.
@@ -2115,7 +2138,8 @@
   SetSourcePosition(expr->position());
   // Call the IC initialization code.
   InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
+  Handle<Code> ic =
+      isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop);
   __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize));  // Key.
   EmitCallIC(ic, mode);
   RecordJSReturnSite(expr);
@@ -2314,7 +2338,7 @@
         // Record source code position for IC call.
         SetSourcePosition(prop->position());
 
-        Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+        Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
         EmitCallIC(ic, RelocInfo::CODE_TARGET);
         __ ldr(r1, GlobalObjectOperand());
         __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
@@ -2333,7 +2357,7 @@
     // also use the fast code generator.
     FunctionLiteral* lit = fun->AsFunctionLiteral();
     if (lit != NULL &&
-        lit->name()->Equals(Heap::empty_string()) &&
+        lit->name()->Equals(isolate()->heap()->empty_string()) &&
         loop_depth() == 0) {
       lit->set_try_full_codegen(true);
     }
@@ -2382,7 +2406,8 @@
   __ mov(r0, Operand(arg_count));
   __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
 
-  Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
+  Handle<Code> construct_builtin =
+      isolate()->builtins()->JSConstructCall();
   __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
   context()->Plug(r0);
 }
@@ -2777,9 +2802,9 @@
   // Convert 32 random bits in r0 to 0.(32 random bits) in a double
   // by computing:
   // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (isolate()->cpu_features()->IsSupported(VFP3)) {
     __ PrepareCallCFunction(0, r1);
-    __ CallCFunction(ExternalReference::random_uint32_function(), 0);
+    __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 0);
 
     CpuFeatures::Scope scope(VFP3);
     // 0x41300000 is the top half of 1.0 x 2^20 as a double.
@@ -2800,7 +2825,7 @@
     __ mov(r0, Operand(r4));
     __ PrepareCallCFunction(1, r1);
     __ CallCFunction(
-        ExternalReference::fill_heap_number_with_random_function(), 1);
+        ExternalReference::fill_heap_number_with_random_function(isolate()), 1);
   }
 
   context()->Plug(r0);
@@ -2855,7 +2880,8 @@
   ASSERT(args->length() == 2);
   VisitForStackValue(args->at(0));
   VisitForStackValue(args->at(1));
-  __ CallRuntime(Runtime::kMath_pow, 2);
+  MathPowStub stub;
+  __ CallStub(&stub);
   context()->Plug(r0);
 }
 
@@ -3126,8 +3152,8 @@
   // Fetch the map and check if array is in fast case.
   // Check that object doesn't require security checks and
   // has no indexed interceptor.
-  __ CompareObjectType(object, scratch1, scratch2, FIRST_JS_OBJECT_TYPE);
-  __ b(lt, &slow_case);
+  __ CompareObjectType(object, scratch1, scratch2, JS_ARRAY_TYPE);
+  __ b(ne, &slow_case);
   // Map is now in scratch1.
 
   __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset));
@@ -3197,7 +3223,7 @@
   int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
 
   Handle<FixedArray> jsfunction_result_caches(
-      Top::global_context()->jsfunction_result_caches());
+      isolate()->global_context()->jsfunction_result_caches());
   if (jsfunction_result_caches->length() <= cache_id) {
     __ Abort("Attempt to use undefined cache.");
     __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
@@ -3576,7 +3602,8 @@
   if (expr->is_jsruntime()) {
     // Call the JS runtime function.
     __ mov(r2, Operand(expr->name()));
-    Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, NOT_IN_LOOP);
+    Handle<Code> ic =
+        isolate()->stub_cache()->ComputeCallInitialize(arg_count, NOT_IN_LOOP);
     EmitCallIC(ic, RelocInfo::CODE_TARGET);
     // Restore context register.
     __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
@@ -3880,9 +3907,9 @@
     case NAMED_PROPERTY: {
       __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
       __ pop(r1);
-      Handle<Code> ic(Builtins::builtin(
-          is_strict() ? Builtins::StoreIC_Initialize_Strict
-                      : Builtins::StoreIC_Initialize));
+      Handle<Code> ic = is_strict_mode()
+          ? isolate()->builtins()->StoreIC_Initialize_Strict()
+          : isolate()->builtins()->StoreIC_Initialize();
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -3897,9 +3924,9 @@
     case KEYED_PROPERTY: {
       __ pop(r1);  // Key.
       __ pop(r2);  // Receiver.
-      Handle<Code> ic(Builtins::builtin(
-          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
-                      : Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic = is_strict_mode()
+          ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+          : isolate()->builtins()->KeyedStoreIC_Initialize();
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -3923,7 +3950,7 @@
     Comment cmnt(masm_, "Global variable");
     __ ldr(r0, GlobalObjectOperand());
     __ mov(r2, Operand(proxy->name()));
-    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
     // Use a regular load, not a contextual load, to avoid a reference
     // error.
     EmitCallIC(ic, RelocInfo::CODE_TARGET);
@@ -3976,13 +4003,13 @@
   }
   PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
 
-  if (check->Equals(Heap::number_symbol())) {
+  if (check->Equals(isolate()->heap()->number_symbol())) {
     __ JumpIfSmi(r0, if_true);
     __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
     __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
     __ cmp(r0, ip);
     Split(eq, if_true, if_false, fall_through);
-  } else if (check->Equals(Heap::string_symbol())) {
+  } else if (check->Equals(isolate()->heap()->string_symbol())) {
     __ JumpIfSmi(r0, if_false);
     // Check for undetectable objects => false.
     __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE);
@@ -3990,12 +4017,12 @@
     __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
     __ tst(r1, Operand(1 << Map::kIsUndetectable));
     Split(eq, if_true, if_false, fall_through);
-  } else if (check->Equals(Heap::boolean_symbol())) {
+  } else if (check->Equals(isolate()->heap()->boolean_symbol())) {
     __ CompareRoot(r0, Heap::kTrueValueRootIndex);
     __ b(eq, if_true);
     __ CompareRoot(r0, Heap::kFalseValueRootIndex);
     Split(eq, if_true, if_false, fall_through);
-  } else if (check->Equals(Heap::undefined_symbol())) {
+  } else if (check->Equals(isolate()->heap()->undefined_symbol())) {
     __ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
     __ b(eq, if_true);
     __ JumpIfSmi(r0, if_false);
@@ -4005,12 +4032,12 @@
     __ tst(r1, Operand(1 << Map::kIsUndetectable));
     Split(ne, if_true, if_false, fall_through);
 
-  } else if (check->Equals(Heap::function_symbol())) {
+  } else if (check->Equals(isolate()->heap()->function_symbol())) {
     __ JumpIfSmi(r0, if_false);
     __ CompareObjectType(r0, r1, r0, FIRST_FUNCTION_CLASS_TYPE);
     Split(ge, if_true, if_false, fall_through);
 
-  } else if (check->Equals(Heap::object_symbol())) {
+  } else if (check->Equals(isolate()->heap()->object_symbol())) {
     __ JumpIfSmi(r0, if_false);
     __ CompareRoot(r0, Heap::kNullValueRootIndex);
     __ b(eq, if_true);
@@ -4194,18 +4221,19 @@
 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) {
   ASSERT(mode == RelocInfo::CODE_TARGET ||
          mode == RelocInfo::CODE_TARGET_CONTEXT);
+  Counters* counters = isolate()->counters();
   switch (ic->kind()) {
     case Code::LOAD_IC:
-      __ IncrementCounter(&Counters::named_load_full, 1, r1, r2);
+      __ IncrementCounter(counters->named_load_full(), 1, r1, r2);
       break;
     case Code::KEYED_LOAD_IC:
-      __ IncrementCounter(&Counters::keyed_load_full, 1, r1, r2);
+      __ IncrementCounter(counters->keyed_load_full(), 1, r1, r2);
       break;
     case Code::STORE_IC:
-      __ IncrementCounter(&Counters::named_store_full, 1, r1, r2);
+      __ IncrementCounter(counters->named_store_full(), 1, r1, r2);
       break;
     case Code::KEYED_STORE_IC:
-      __ IncrementCounter(&Counters::keyed_store_full, 1, r1, r2);
+      __ IncrementCounter(counters->keyed_store_full(), 1, r1, r2);
     default:
       break;
   }
@@ -4215,18 +4243,19 @@
 
 
 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) {
+  Counters* counters = isolate()->counters();
   switch (ic->kind()) {
     case Code::LOAD_IC:
-      __ IncrementCounter(&Counters::named_load_full, 1, r1, r2);
+      __ IncrementCounter(counters->named_load_full(), 1, r1, r2);
       break;
     case Code::KEYED_LOAD_IC:
-      __ IncrementCounter(&Counters::keyed_load_full, 1, r1, r2);
+      __ IncrementCounter(counters->keyed_load_full(), 1, r1, r2);
       break;
     case Code::STORE_IC:
-      __ IncrementCounter(&Counters::named_store_full, 1, r1, r2);
+      __ IncrementCounter(counters->named_store_full(), 1, r1, r2);
       break;
     case Code::KEYED_STORE_IC:
-      __ IncrementCounter(&Counters::keyed_store_full, 1, r1, r2);
+      __ IncrementCounter(counters->keyed_store_full(), 1, r1, r2);
     default:
       break;
   }
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index 0fc6818..dc4f761 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -552,7 +552,8 @@
                                          Code::kNoExtraICState,
                                          NORMAL,
                                          argc);
-  StubCache::GenerateProbe(masm, flags, r1, r2, r3, r4, r5);
+  Isolate::Current()->stub_cache()->GenerateProbe(
+      masm, flags, r1, r2, r3, r4, r5);
 
   // If the stub cache probing failed, the receiver might be a value.
   // For value objects, we use the map of the prototype objects for
@@ -591,7 +592,8 @@
 
   // Probe the stub cache for the value object.
   __ bind(&probe);
-  StubCache::GenerateProbe(masm, flags, r1, r2, r3, r4, r5);
+  Isolate::Current()->stub_cache()->GenerateProbe(
+      masm, flags, r1, r2, r3, r4, r5);
 
   __ bind(&miss);
 }
@@ -644,11 +646,12 @@
   //  -- r2    : name
   //  -- lr    : return address
   // -----------------------------------
+  Isolate* isolate = masm->isolate();
 
   if (id == IC::kCallIC_Miss) {
-    __ IncrementCounter(&Counters::call_miss, 1, r3, r4);
+    __ IncrementCounter(isolate->counters()->call_miss(), 1, r3, r4);
   } else {
-    __ IncrementCounter(&Counters::keyed_call_miss, 1, r3, r4);
+    __ IncrementCounter(isolate->counters()->keyed_call_miss(), 1, r3, r4);
   }
 
   // Get the receiver of the function from the stack.
@@ -661,7 +664,7 @@
 
   // Call the entry.
   __ mov(r0, Operand(2));
-  __ mov(r1, Operand(ExternalReference(IC_Utility(id))));
+  __ mov(r1, Operand(ExternalReference(IC_Utility(id), isolate)));
 
   CEntryStub stub(1);
   __ CallStub(&stub);
@@ -763,7 +766,8 @@
 
   GenerateFastArrayLoad(
       masm, r1, r2, r4, r3, r0, r1, &check_number_dictionary, &slow_load);
-  __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1, r0, r3);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->keyed_call_generic_smi_fast(), 1, r0, r3);
 
   __ bind(&do_call);
   // receiver in r1 is not used after this point.
@@ -782,13 +786,13 @@
   __ mov(r0, Operand(r2, ASR, kSmiTagSize));
   // r0: untagged index
   GenerateNumberDictionaryLoad(masm, &slow_load, r4, r2, r1, r0, r3, r5);
-  __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1, r0, r3);
+  __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1, r0, r3);
   __ jmp(&do_call);
 
   __ bind(&slow_load);
   // This branch is taken when calling KeyedCallIC_Miss is neither required
   // nor beneficial.
-  __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1, r0, r3);
+  __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1, r0, r3);
   __ EnterInternalFrame();
   __ push(r2);  // save the key
   __ Push(r1, r2);  // pass the receiver and the key
@@ -815,11 +819,11 @@
   __ b(ne, &lookup_monomorphic_cache);
 
   GenerateDictionaryLoad(masm, &slow_load, r0, r2, r1, r3, r4);
-  __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1, r0, r3);
+  __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1, r0, r3);
   __ jmp(&do_call);
 
   __ bind(&lookup_monomorphic_cache);
-  __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1, r0, r3);
+  __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1, r0, r3);
   GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC);
   // Fall through on miss.
 
@@ -830,7 +834,7 @@
   // - the value loaded is not a function,
   // - there is hope that the runtime will create a monomorphic call stub
   //   that will get fetched next time.
-  __ IncrementCounter(&Counters::keyed_call_generic_slow, 1, r0, r3);
+  __ IncrementCounter(counters->keyed_call_generic_slow(), 1, r0, r3);
   GenerateMiss(masm, argc);
 
   __ bind(&index_string);
@@ -873,7 +877,8 @@
   Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
                                          NOT_IN_LOOP,
                                          MONOMORPHIC);
-  StubCache::GenerateProbe(masm, flags, r0, r2, r3, r4, r5);
+  Isolate::Current()->stub_cache()->GenerateProbe(
+      masm, flags, r0, r2, r3, r4, r5);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
@@ -908,14 +913,16 @@
   //  -- r0    : receiver
   //  -- sp[0] : receiver
   // -----------------------------------
+  Isolate* isolate = masm->isolate();
 
-  __ IncrementCounter(&Counters::load_miss, 1, r3, r4);
+  __ IncrementCounter(isolate->counters()->load_miss(), 1, r3, r4);
 
   __ mov(r3, r0);
   __ Push(r3, r2);
 
   // Perform tail call to the entry.
-  ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss));
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kLoadIC_Miss), isolate);
   __ TailCallExternalReference(ref, 2, 1);
 }
 
@@ -961,7 +968,7 @@
 
   // Find the end of the inlined code for handling the load if this is an
   // inlined IC call site.
-  Address inline_end_address;
+  Address inline_end_address = 0;
   if (InlinedICSiteMarker(address, &inline_end_address)
       != Assembler::PROPERTY_ACCESS_INLINED) {
     return false;
@@ -1001,7 +1008,7 @@
                                         bool is_dont_delete) {
   // Find the end of the inlined code for handling the contextual load if
   // this is inlined IC call site.
-  Address inline_end_address;
+  Address inline_end_address = 0;
   int marker = InlinedICSiteMarker(address, &inline_end_address);
   if (!((marker == Assembler::PROPERTY_ACCESS_INLINED_CONTEXT) ||
         (marker == Assembler::PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE))) {
@@ -1042,7 +1049,7 @@
 
   // Find the end of the inlined code for the store if there is an
   // inlined version of the store.
-  Address inline_end_address;
+  Address inline_end_address = 0;
   if (InlinedICSiteMarker(address, &inline_end_address)
       != Assembler::PROPERTY_ACCESS_INLINED) {
     return false;
@@ -1057,7 +1064,7 @@
   // Update the offsets if initializing the inlined store. No reason
   // to update the offsets when clearing the inlined version because
   // it will bail out in the map check.
-  if (map != Heap::null_value()) {
+  if (map != HEAP->null_value()) {
     // Patch the offset in the actual store instruction.
     Address str_property_instr_address =
         ldr_map_instr_address + 3 * Assembler::kInstrSize;
@@ -1092,7 +1099,7 @@
 bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) {
   if (V8::UseCrankshaft()) return false;
 
-  Address inline_end_address;
+  Address inline_end_address = 0;
   if (InlinedICSiteMarker(address, &inline_end_address)
       != Assembler::PROPERTY_ACCESS_INLINED) {
     return false;
@@ -1114,7 +1121,7 @@
 
   // Find the end of the inlined code for handling the store if this is an
   // inlined IC call site.
-  Address inline_end_address;
+  Address inline_end_address = 0;
   if (InlinedICSiteMarker(address, &inline_end_address)
       != Assembler::PROPERTY_ACCESS_INLINED) {
     return false;
@@ -1140,12 +1147,14 @@
   //  -- r0     : key
   //  -- r1     : receiver
   // -----------------------------------
+  Isolate* isolate = masm->isolate();
 
-  __ IncrementCounter(&Counters::keyed_load_miss, 1, r3, r4);
+  __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r3, r4);
 
   __ Push(r1, r0);
 
-  ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss));
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate);
   __ TailCallExternalReference(ref, 2, 1);
 }
 
@@ -1170,11 +1179,13 @@
   //  -- r1     : receiver
   // -----------------------------------
   Label slow, check_string, index_smi, index_string, property_array_property;
-  Label check_pixel_array, probe_dictionary, check_number_dictionary;
+  Label probe_dictionary, check_number_dictionary;
 
   Register key = r0;
   Register receiver = r1;
 
+  Isolate* isolate = masm->isolate();
+
   // Check that the key is a smi.
   __ JumpIfNotSmi(key, &check_string);
   __ bind(&index_smi);
@@ -1188,31 +1199,17 @@
   // now in r2.
   __ ldrb(r3, FieldMemOperand(r2, Map::kBitField2Offset));
   __ tst(r3, Operand(1 << Map::kHasFastElements));
-  __ b(eq, &check_pixel_array);
+  __ b(eq, &check_number_dictionary);
 
   GenerateFastArrayLoad(
       masm, receiver, key, r4, r3, r2, r0, NULL, &slow);
-  __ IncrementCounter(&Counters::keyed_load_generic_smi, 1, r2, r3);
+  __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r2, r3);
   __ Ret();
 
-  // Check whether the elements is a pixel array.
-  // r0: key
-  // r1: receiver
-  __ bind(&check_pixel_array);
-
-  GenerateFastPixelArrayLoad(masm,
-                             r1,
-                             r0,
-                             r3,
-                             r4,
-                             r2,
-                             r5,
-                             r0,
-                             &check_number_dictionary,
-                             NULL,
-                             &slow);
-
   __ bind(&check_number_dictionary);
+  __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset));
+  __ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset));
+
   // Check whether the elements is a number dictionary.
   // r0: key
   // r3: elements map
@@ -1226,7 +1223,8 @@
 
   // Slow case, key and receiver still in r0 and r1.
   __ bind(&slow);
-  __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r2, r3);
+  __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(),
+                      1, r2, r3);
   GenerateRuntimeGetProperty(masm);
 
   __ bind(&check_string);
@@ -1253,7 +1251,8 @@
 
   // Load the key (consisting of map and symbol) from the cache and
   // check for match.
-  ExternalReference cache_keys = ExternalReference::keyed_lookup_cache_keys();
+  ExternalReference cache_keys =
+      ExternalReference::keyed_lookup_cache_keys(isolate);
   __ mov(r4, Operand(cache_keys));
   __ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1));
   __ ldr(r5, MemOperand(r4, kPointerSize, PostIndex));  // Move r4 to symbol.
@@ -1268,8 +1267,8 @@
   // r1     : receiver
   // r2     : receiver's map
   // r3     : lookup cache index
-  ExternalReference cache_field_offsets
-      = ExternalReference::keyed_lookup_cache_field_offsets();
+  ExternalReference cache_field_offsets =
+      ExternalReference::keyed_lookup_cache_field_offsets(isolate);
   __ mov(r4, Operand(cache_field_offsets));
   __ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2));
   __ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset));
@@ -1281,7 +1280,8 @@
   __ add(r6, r6, r5);  // Index from start of object.
   __ sub(r1, r1, Operand(kHeapObjectTag));  // Remove the heap tag.
   __ ldr(r0, MemOperand(r1, r6, LSL, kPointerSizeLog2));
-  __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1, r2, r3);
+  __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(),
+                      1, r2, r3);
   __ Ret();
 
   // Load property array property.
@@ -1289,7 +1289,8 @@
   __ ldr(r1, FieldMemOperand(r1, JSObject::kPropertiesOffset));
   __ add(r1, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   __ ldr(r0, MemOperand(r1, r5, LSL, kPointerSizeLog2));
-  __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1, r2, r3);
+  __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(),
+                      1, r2, r3);
   __ Ret();
 
   // Do a quick inline probe of the receiver's dictionary, if it
@@ -1303,7 +1304,8 @@
   GenerateGlobalInstanceTypeCheck(masm, r2, &slow);
   // Load the property to r0.
   GenerateDictionaryLoad(masm, &slow, r3, r0, r0, r2, r4);
-  __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1, r2, r3);
+  __ IncrementCounter(isolate->counters()->keyed_load_generic_symbol(),
+                      1, r2, r3);
   __ Ret();
 
   __ bind(&index_string);
@@ -1376,8 +1378,11 @@
   __ Push(r1, r0);  // Receiver, key.
 
   // Perform tail call to the entry.
-  __ TailCallExternalReference(ExternalReference(
-        IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1);
+  __ TailCallExternalReference(
+      ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor),
+                        masm->isolate()),
+      2,
+      1);
 
   __ bind(&slow);
   GenerateMiss(masm);
@@ -1395,7 +1400,8 @@
   // Push receiver, key and value for runtime call.
   __ Push(r2, r1, r0);
 
-  ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss));
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate());
   __ TailCallExternalReference(ref, 3, 1);
 }
 
@@ -1428,7 +1434,7 @@
   //  -- r2     : receiver
   //  -- lr     : return address
   // -----------------------------------
-  Label slow, fast, array, extra, check_pixel_array;
+  Label slow, fast, array, extra;
 
   // Register usage.
   Register value = r0;
@@ -1464,7 +1470,7 @@
   __ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset));
   __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
   __ cmp(r4, ip);
-  __ b(ne, &check_pixel_array);
+  __ b(ne, &slow);
   // Check array bounds. Both the key and the length of FixedArray are smis.
   __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset));
   __ cmp(key, Operand(ip));
@@ -1478,24 +1484,6 @@
   // r2: receiver.
   GenerateRuntimeSetProperty(masm, strict_mode);
 
-  // Check whether the elements is a pixel array.
-  // r4: elements map.
-  __ bind(&check_pixel_array);
-  GenerateFastPixelArrayStore(masm,
-                              r2,
-                              r1,
-                              r0,
-                              elements,
-                              r4,
-                              r5,
-                              r6,
-                              false,
-                              false,
-                              NULL,
-                              &slow,
-                              &slow,
-                              &slow);
-
   // 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].
@@ -1559,7 +1547,9 @@
                                          NOT_IN_LOOP,
                                          MONOMORPHIC,
                                          strict_mode);
-  StubCache::GenerateProbe(masm, flags, r1, r2, r3, r4, r5);
+
+  Isolate::Current()->stub_cache()->GenerateProbe(
+      masm, flags, r1, r2, r3, r4, r5);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
@@ -1577,7 +1567,8 @@
   __ Push(r1, r2, r0);
 
   // Perform tail call to the entry.
-  ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss));
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate());
   __ TailCallExternalReference(ref, 3, 1);
 }
 
@@ -1622,7 +1613,8 @@
   // Prepare tail call to StoreIC_ArrayLength.
   __ Push(receiver, value);
 
-  ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength));
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate());
   __ TailCallExternalReference(ref, 2, 1);
 
   __ bind(&miss);
@@ -1643,11 +1635,13 @@
   GenerateStringDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss);
 
   GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5);
-  __ IncrementCounter(&Counters::store_normal_hit, 1, r4, r5);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->store_normal_hit(),
+                      1, r4, r5);
   __ Ret();
 
   __ bind(&miss);
-  __ IncrementCounter(&Counters::store_normal_miss, 1, r4, r5);
+  __ IncrementCounter(counters->store_normal_miss(), 1, r4, r5);
   GenerateMiss(masm);
 }
 
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index e79465c..5d31473 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -25,6 +25,8 @@
 // (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 "lithium-allocator-inl.h"
 #include "arm/lithium-arm.h"
 #include "arm/lithium-codegen-arm.h"
@@ -1230,8 +1232,7 @@
       case kMathRound:
         return AssignEnvironment(DefineAsRegister(result));
       case kMathPowHalf:
-        Abort("MathPowHalf LUnaryMathOperation not implemented");
-        return NULL;
+        return DefineSameAsFirst(result);
       default:
         UNREACHABLE();
         return NULL;
@@ -1344,18 +1345,25 @@
 
 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
   if (instr->representation().IsInteger32()) {
-    // TODO(1042) The fixed register allocation
-    // is needed because we call GenericBinaryOpStub from
-    // the generated code, which requires registers r0
-    // and r1 to be used. We should remove that
-    // when we provide a native implementation.
     ASSERT(instr->left()->representation().IsInteger32());
     ASSERT(instr->right()->representation().IsInteger32());
-    LOperand* value = UseFixed(instr->left(), r0);
-    LOperand* divisor = UseFixed(instr->right(), r1);
-    LInstruction* result = DefineFixed(new LModI(value, divisor), r0);
-    result = AssignEnvironment(AssignPointerMap(result));
-    return result;
+
+    LModI* mod;
+    if (instr->HasPowerOf2Divisor()) {
+      ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
+      LOperand* value = UseRegisterAtStart(instr->left());
+      mod = new LModI(value, UseOrConstant(instr->right()));
+    } else {
+      LOperand* dividend = UseRegister(instr->left());
+      LOperand* divisor = UseRegisterAtStart(instr->right());
+      mod = new LModI(dividend,
+                      divisor,
+                      TempRegister(),
+                      FixedTemp(d1),
+                      FixedTemp(d2));
+    }
+
+    return AssignEnvironment(DefineSameAsFirst(mod));
   } else if (instr->representation().IsTagged()) {
     return DoArithmeticT(Token::MOD, instr);
   } else {
@@ -1548,9 +1556,10 @@
 }
 
 
-LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) {
+LInstruction* LChunkBuilder::DoExternalArrayLength(
+    HExternalArrayLength* instr) {
   LOperand* array = UseRegisterAtStart(instr->value());
-  return DefineAsRegister(new LPixelArrayLength(array));
+  return DefineAsRegister(new LExternalArrayLength(array));
 }
 
 
@@ -1599,12 +1608,15 @@
       LOperand* value = UseRegister(instr->value());
       bool needs_check = !instr->value()->type().IsSmi();
       LInstruction* res = NULL;
-      if (needs_check) {
-        res = DefineSameAsFirst(new LTaggedToI(value, FixedTemp(d1)));
-      } else {
+      if (!needs_check) {
         res = DefineSameAsFirst(new LSmiUntag(value, needs_check));
-      }
-      if (needs_check) {
+      } else {
+        LOperand* temp1 = TempRegister();
+        LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
+                                                      : NULL;
+        LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d3)
+                                                      : NULL;
+        res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3));
         res = AssignEnvironment(res);
       }
       return res;
@@ -1624,7 +1636,10 @@
     } else {
       ASSERT(to.IsInteger32());
       LOperand* value = UseRegister(instr->value());
-      LDoubleToI* res = new LDoubleToI(value, TempRegister());
+      LDoubleToI* res =
+        new LDoubleToI(value,
+                       TempRegister(),
+                       instr->CanTruncateToInt32() ? TempRegister() : NULL);
       return AssignEnvironment(DefineAsRegister(res));
     }
   } else if (from.IsInteger32()) {
@@ -1650,7 +1665,7 @@
 
 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
-  return AssignEnvironment(new LCheckSmi(value, eq));
+  return AssignEnvironment(new LCheckNonSmi(value));
 }
 
 
@@ -1671,7 +1686,7 @@
 
 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
-  return AssignEnvironment(new LCheckSmi(value, ne));
+  return AssignEnvironment(new LCheckSmi(value));
 }
 
 
@@ -1754,6 +1769,21 @@
 }
 
 
+LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
+    HLoadNamedFieldPolymorphic* instr) {
+  ASSERT(instr->representation().IsTagged());
+  if (instr->need_generic()) {
+    LOperand* obj = UseFixed(instr->object(), r0);
+    LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
+    return MarkAsCall(DefineFixed(result, r0), instr);
+  } else {
+    LOperand* obj = UseRegisterAtStart(instr->object());
+    LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
+    return AssignEnvironment(DefineAsRegister(result));
+  }
+}
+
+
 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
   LOperand* object = UseFixed(instr->object(), r0);
   LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), r0);
@@ -1774,10 +1804,10 @@
 }
 
 
-LInstruction* LChunkBuilder::DoLoadPixelArrayExternalPointer(
-    HLoadPixelArrayExternalPointer* instr) {
+LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
+    HLoadExternalArrayPointer* instr) {
   LOperand* input = UseRegisterAtStart(instr->value());
-  return DefineAsRegister(new LLoadPixelArrayExternalPointer(input));
+  return DefineAsRegister(new LLoadExternalArrayPointer(input));
 }
 
 
@@ -1792,15 +1822,22 @@
 }
 
 
-LInstruction* LChunkBuilder::DoLoadPixelArrayElement(
-    HLoadPixelArrayElement* instr) {
+LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
+    HLoadKeyedSpecializedArrayElement* instr) {
+  // TODO(danno): Add support for other external array types.
+  if (instr->array_type() != kExternalPixelArray) {
+    Abort("unsupported load for external array type.");
+    return NULL;
+  }
+
   ASSERT(instr->representation().IsInteger32());
   ASSERT(instr->key()->representation().IsInteger32());
   LOperand* external_pointer =
       UseRegisterAtStart(instr->external_pointer());
   LOperand* key = UseRegisterAtStart(instr->key());
-  LLoadPixelArrayElement* result =
-      new LLoadPixelArrayElement(external_pointer, key);
+  LLoadKeyedSpecializedArrayElement* result =
+      new LLoadKeyedSpecializedArrayElement(external_pointer,
+                                            key);
   return DefineAsRegister(result);
 }
 
@@ -1834,10 +1871,25 @@
 }
 
 
-LInstruction* LChunkBuilder::DoStorePixelArrayElement(
-    HStorePixelArrayElement* instr) {
-  Abort("DoStorePixelArrayElement not implemented");
-  return NULL;
+LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
+    HStoreKeyedSpecializedArrayElement* instr) {
+  // TODO(danno): Add support for other external array types.
+  if (instr->array_type() != kExternalPixelArray) {
+    Abort("unsupported store for external array type.");
+    return NULL;
+  }
+
+  ASSERT(instr->value()->representation().IsInteger32());
+  ASSERT(instr->external_pointer()->representation().IsExternal());
+  ASSERT(instr->key()->representation().IsInteger32());
+
+  LOperand* external_pointer = UseRegister(instr->external_pointer());
+  LOperand* value = UseTempRegister(instr->value());  // changed by clamp.
+  LOperand* key = UseRegister(instr->key());
+
+  return new LStoreKeyedSpecializedArrayElement(external_pointer,
+                                                key,
+                                                value);
 }
 
 
@@ -1886,6 +1938,13 @@
 }
 
 
+LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
+  LOperand* char_code = UseRegister(instr->value());
+  LStringCharFromCode* result = new LStringCharFromCode(char_code);
+  return AssignPointerMap(DefineAsRegister(result));
+}
+
+
 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
   LOperand* string = UseRegisterAtStart(instr->value());
   return DefineAsRegister(new LStringLength(string));
@@ -1963,6 +2022,13 @@
 }
 
 
+LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
+  LOperand* object = UseFixed(instr->value(), r0);
+  LToFastProperties* result = new LToFastProperties(object);
+  return MarkAsCall(DefineFixed(result, r0), instr);
+}
+
+
 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
   LTypeof* result = new LTypeof(UseFixed(instr->value(), r0));
   return MarkAsCall(DefineFixed(result, r0), instr);
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 9cbcc3b..77aabaf 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -69,6 +69,7 @@
   V(CallStub)                                   \
   V(CheckFunction)                              \
   V(CheckInstanceType)                          \
+  V(CheckNonSmi)                                \
   V(CheckMap)                                   \
   V(CheckPrototypeMaps)                         \
   V(CheckSmi)                                   \
@@ -89,6 +90,7 @@
   V(Deoptimize)                                 \
   V(DivI)                                       \
   V(DoubleToI)                                  \
+  V(ExternalArrayLength)                        \
   V(FixedArrayLength)                           \
   V(FunctionLiteral)                            \
   V(Gap)                                        \
@@ -115,14 +117,15 @@
   V(LazyBailout)                                \
   V(LoadContextSlot)                            \
   V(LoadElements)                               \
+  V(LoadExternalArrayPointer)                   \
   V(LoadFunctionPrototype)                      \
   V(LoadGlobal)                                 \
   V(LoadKeyedFastElement)                       \
   V(LoadKeyedGeneric)                           \
+  V(LoadKeyedSpecializedArrayElement)           \
   V(LoadNamedField)                             \
+  V(LoadNamedFieldPolymorphic)                  \
   V(LoadNamedGeneric)                           \
-  V(LoadPixelArrayElement)                      \
-  V(LoadPixelArrayExternalPointer)              \
   V(ModI)                                       \
   V(MulI)                                       \
   V(NumberTagD)                                 \
@@ -132,7 +135,6 @@
   V(OsrEntry)                                   \
   V(OuterContext)                               \
   V(Parameter)                                  \
-  V(PixelArrayLength)                           \
   V(Power)                                      \
   V(PushArgument)                               \
   V(RegExpLiteral)                              \
@@ -145,13 +147,16 @@
   V(StoreGlobal)                                \
   V(StoreKeyedFastElement)                      \
   V(StoreKeyedGeneric)                          \
+  V(StoreKeyedSpecializedArrayElement)          \
   V(StoreNamedField)                            \
   V(StoreNamedGeneric)                          \
   V(StringCharCodeAt)                           \
+  V(StringCharFromCode)                         \
   V(StringLength)                               \
   V(SubI)                                       \
   V(TaggedToI)                                  \
   V(Throw)                                      \
+  V(ToFastProperties)                           \
   V(Typeof)                                     \
   V(TypeofIs)                                   \
   V(TypeofIsAndBranch)                          \
@@ -519,11 +524,29 @@
 };
 
 
-class LModI: public LTemplateInstruction<1, 2, 0> {
+class LModI: public LTemplateInstruction<1, 2, 3> {
  public:
-  LModI(LOperand* left, LOperand* right) {
+  // Used when the right hand is a constant power of 2.
+  LModI(LOperand* left,
+        LOperand* right) {
     inputs_[0] = left;
     inputs_[1] = right;
+    temps_[0] = NULL;
+    temps_[1] = NULL;
+    temps_[2] = NULL;
+  }
+
+  // Used for the standard case.
+  LModI(LOperand* left,
+        LOperand* right,
+        LOperand* temp1,
+        LOperand* temp2,
+        LOperand* temp3) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+    temps_[0] = temp1;
+    temps_[1] = temp2;
+    temps_[2] = temp3;
   }
 
   DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i")
@@ -991,14 +1014,14 @@
 };
 
 
-class LPixelArrayLength: public LTemplateInstruction<1, 1, 0> {
+class LExternalArrayLength: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LPixelArrayLength(LOperand* value) {
+  explicit LExternalArrayLength(LOperand* value) {
     inputs_[0] = value;
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel-array-length")
-  DECLARE_HYDROGEN_ACCESSOR(PixelArrayLength)
+  DECLARE_CONCRETE_INSTRUCTION(ExternalArrayLength, "external-array-length")
+  DECLARE_HYDROGEN_ACCESSOR(ExternalArrayLength)
 };
 
 
@@ -1126,6 +1149,19 @@
 };
 
 
+class LLoadNamedFieldPolymorphic: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LLoadNamedFieldPolymorphic(LOperand* object) {
+    inputs_[0] = object;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field-polymorphic")
+  DECLARE_HYDROGEN_ACCESSOR(LoadNamedFieldPolymorphic)
+
+  LOperand* object() { return inputs_[0]; }
+};
+
+
 class LLoadNamedGeneric: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LLoadNamedGeneric(LOperand* object) {
@@ -1163,14 +1199,14 @@
 };
 
 
-class LLoadPixelArrayExternalPointer: public LTemplateInstruction<1, 1, 0> {
+class LLoadExternalArrayPointer: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LLoadPixelArrayExternalPointer(LOperand* object) {
+  explicit LLoadExternalArrayPointer(LOperand* object) {
     inputs_[0] = object;
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
-                               "load-pixel-array-external-pointer")
+  DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer,
+                               "load-external-array-pointer")
 };
 
 
@@ -1189,19 +1225,23 @@
 };
 
 
-class LLoadPixelArrayElement: public LTemplateInstruction<1, 2, 0> {
+class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
  public:
-  LLoadPixelArrayElement(LOperand* external_pointer, LOperand* key) {
+  LLoadKeyedSpecializedArrayElement(LOperand* external_pointer,
+                                    LOperand* key) {
     inputs_[0] = external_pointer;
     inputs_[1] = key;
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayElement,
-                               "load-pixel-array-element")
-  DECLARE_HYDROGEN_ACCESSOR(LoadPixelArrayElement)
+  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement,
+                               "load-keyed-specialized-array-element")
+  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedSpecializedArrayElement)
 
   LOperand* external_pointer() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
+  ExternalArrayType array_type() const {
+    return hydrogen()->array_type();
+  }
 };
 
 
@@ -1418,7 +1458,7 @@
   DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
   DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
 
-  Runtime::Function* function() const { return hydrogen()->function(); }
+  const Runtime::Function* function() const { return hydrogen()->function(); }
   int arity() const { return hydrogen()->argument_count(); }
 };
 
@@ -1456,11 +1496,12 @@
 
 
 // Sometimes truncating conversion from a tagged value to an int32.
-class LDoubleToI: public LTemplateInstruction<1, 1, 1> {
+class LDoubleToI: public LTemplateInstruction<1, 1, 2> {
  public:
-  explicit LDoubleToI(LOperand* value, LOperand* temp1) {
+  LDoubleToI(LOperand* value, LOperand* temp1, LOperand* temp2) {
     inputs_[0] = value;
     temps_[0] = temp1;
+    temps_[1] = temp2;
   }
 
   DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i")
@@ -1471,11 +1512,16 @@
 
 
 // Truncating conversion from a tagged value to an int32.
-class LTaggedToI: public LTemplateInstruction<1, 1, 1> {
+class LTaggedToI: public LTemplateInstruction<1, 1, 3> {
  public:
-  LTaggedToI(LOperand* value, LOperand* temp) {
+  LTaggedToI(LOperand* value,
+             LOperand* temp1,
+             LOperand* temp2,
+             LOperand* temp3) {
     inputs_[0] = value;
-    temps_[0] = temp;
+    temps_[0] = temp1;
+    temps_[1] = temp2;
+    temps_[2] = temp3;
   }
 
   DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
@@ -1591,6 +1637,7 @@
   }
 
   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
+  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
 
   virtual void PrintDataTo(StringStream* stream);
 
@@ -1599,6 +1646,28 @@
   LOperand* value() { return inputs_[2]; }
 };
 
+class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 0> {
+ public:
+  LStoreKeyedSpecializedArrayElement(LOperand* external_pointer,
+                                     LOperand* key,
+                                     LOperand* val) {
+    inputs_[0] = external_pointer;
+    inputs_[1] = key;
+    inputs_[2] = val;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement,
+                               "store-keyed-specialized-array-element")
+  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedSpecializedArrayElement)
+
+  LOperand* external_pointer() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
+  LOperand* value() { return inputs_[2]; }
+  ExternalArrayType array_type() const {
+    return hydrogen()->array_type();
+  }
+};
+
 
 class LStringCharCodeAt: public LTemplateInstruction<1, 2, 0> {
  public:
@@ -1615,6 +1684,19 @@
 };
 
 
+class LStringCharFromCode: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LStringCharFromCode(LOperand* char_code) {
+    inputs_[0] = char_code;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
+  DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
+
+  LOperand* char_code() { return inputs_[0]; }
+};
+
+
 class LStringLength: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LStringLength(LOperand* string) {
@@ -1678,20 +1760,21 @@
 
 class LCheckSmi: public LTemplateInstruction<0, 1, 0> {
  public:
-  LCheckSmi(LOperand* value, Condition condition)
-      : condition_(condition) {
+  explicit LCheckSmi(LOperand* value) {
     inputs_[0] = value;
   }
 
-  Condition condition() const { return condition_; }
+  DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi")
+};
 
-  virtual void CompileToNative(LCodeGen* generator);
-  virtual const char* Mnemonic() const {
-    return (condition_ == eq) ? "check-non-smi" : "check-smi";
+
+class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LCheckNonSmi(LOperand* value) {
+    inputs_[0] = value;
   }
 
- private:
-  Condition condition_;
+  DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi")
 };
 
 
@@ -1725,6 +1808,17 @@
 };
 
 
+class LToFastProperties: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LToFastProperties(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to-fast-properties")
+  DECLARE_HYDROGEN_ACCESSOR(ToFastProperties)
+};
+
+
 class LTypeof: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LTypeof(LOperand* value) {
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index afe9015..75406cf 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -25,6 +25,8 @@
 // (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 "arm/lithium-codegen-arm.h"
 #include "arm/lithium-gap-resolver-arm.h"
 #include "code-stubs.h"
@@ -34,7 +36,7 @@
 namespace internal {
 
 
-class SafepointGenerator : public PostCallGenerator {
+class SafepointGenerator : public CallWrapper {
  public:
   SafepointGenerator(LCodeGen* codegen,
                      LPointerMap* pointers,
@@ -44,7 +46,24 @@
         deoptimization_index_(deoptimization_index) { }
   virtual ~SafepointGenerator() { }
 
-  virtual void Generate() {
+  virtual void BeforeCall(int call_size) {
+    ASSERT(call_size >= 0);
+    // Ensure that we have enough space after the previous safepoint position
+    // for the generated code there.
+    int call_end = codegen_->masm()->pc_offset() + call_size;
+    int prev_jump_end =
+        codegen_->LastSafepointEnd() + Deoptimizer::patch_size();
+    if (call_end < prev_jump_end) {
+      int padding_size = prev_jump_end - call_end;
+      ASSERT_EQ(0, padding_size % Assembler::kInstrSize);
+      while (padding_size > 0) {
+        codegen_->masm()->nop();
+        padding_size -= Assembler::kInstrSize;
+      }
+    }
+  }
+
+  virtual void AfterCall() {
     codegen_->RecordSafepoint(pointers_, deoptimization_index_);
   }
 
@@ -75,6 +94,7 @@
   code->set_stack_slots(StackSlotCount());
   code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
   PopulateDeoptimizationData(code);
+  Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
 }
 
 
@@ -472,7 +492,7 @@
 }
 
 
-void LCodeGen::CallRuntime(Runtime::Function* function,
+void LCodeGen::CallRuntime(const Runtime::Function* function,
                            int num_arguments,
                            LInstruction* instr) {
   ASSERT(instr != NULL);
@@ -571,14 +591,14 @@
   if (length == 0) return;
   ASSERT(FLAG_deopt);
   Handle<DeoptimizationInputData> data =
-      Factory::NewDeoptimizationInputData(length, TENURED);
+      factory()->NewDeoptimizationInputData(length, TENURED);
 
   Handle<ByteArray> translations = translations_.CreateByteArray();
   data->SetTranslationByteArray(*translations);
   data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
 
   Handle<FixedArray> literals =
-      Factory::NewFixedArray(deoptimization_literals_.length(), TENURED);
+      factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
   for (int i = 0; i < deoptimization_literals_.length(); i++) {
     literals->set(i, *deoptimization_literals_[i]);
   }
@@ -740,15 +760,6 @@
       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
       break;
     }
-    case CodeStub::StringCharAt: {
-      StringCharAtStub stub;
-      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
-      break;
-    }
-    case CodeStub::MathPow: {
-      Abort("MathPowStub unimplemented.");
-      break;
-    }
     case CodeStub::NumberToString: {
       NumberToStringStub stub;
       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
@@ -783,55 +794,91 @@
 
 
 void LCodeGen::DoModI(LModI* instr) {
-  class DeferredModI: public LDeferredCode {
-   public:
-    DeferredModI(LCodeGen* codegen, LModI* instr)
-        : LDeferredCode(codegen), instr_(instr) { }
-    virtual void Generate() {
-      codegen()->DoDeferredBinaryOpStub(instr_, Token::MOD);
+  if (instr->hydrogen()->HasPowerOf2Divisor()) {
+    Register dividend = ToRegister(instr->InputAt(0));
+
+    int32_t divisor =
+        HConstant::cast(instr->hydrogen()->right())->Integer32Value();
+
+    if (divisor < 0) divisor = -divisor;
+
+    Label positive_dividend, done;
+    __ cmp(dividend, Operand(0));
+    __ b(pl, &positive_dividend);
+    __ rsb(dividend, dividend, Operand(0));
+    __ and_(dividend, dividend, Operand(divisor - 1));
+    __ rsb(dividend, dividend, Operand(0), SetCC);
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      __ b(ne, &done);
+      DeoptimizeIf(al, instr->environment());
     }
-   private:
-    LModI* instr_;
-  };
+    __ bind(&positive_dividend);
+    __ and_(dividend, dividend, Operand(divisor - 1));
+    __ bind(&done);
+    return;
+  }
+
   // These registers hold untagged 32 bit values.
   Register left = ToRegister(instr->InputAt(0));
   Register right = ToRegister(instr->InputAt(1));
   Register result = ToRegister(instr->result());
-  Register scratch = scratch0();
 
-  Label deoptimize, done;
+  Register scratch = scratch0();
+  Register scratch2 = ToRegister(instr->TempAt(0));
+  DwVfpRegister dividend = ToDoubleRegister(instr->TempAt(1));
+  DwVfpRegister divisor = ToDoubleRegister(instr->TempAt(2));
+  DwVfpRegister quotient = double_scratch0();
+
+  ASSERT(result.is(left));
+
+  ASSERT(!dividend.is(divisor));
+  ASSERT(!dividend.is(quotient));
+  ASSERT(!divisor.is(quotient));
+  ASSERT(!scratch.is(left));
+  ASSERT(!scratch.is(right));
+  ASSERT(!scratch.is(result));
+
+  Label done, vfp_modulo, both_positive, right_negative;
+
   // Check for x % 0.
   if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
-    __ tst(right, Operand(right));
-    __ b(eq, &deoptimize);
+    __ cmp(right, Operand(0));
+    DeoptimizeIf(eq, instr->environment());
   }
 
-  // Check for (0 % -x) that will produce negative zero.
-  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
-    Label ok;
-    __ tst(left, Operand(left));
-    __ b(ne, &ok);
-    __ tst(right, Operand(right));
-    __ b(pl, &ok);
-    __ b(al, &deoptimize);
-    __ bind(&ok);
-  }
-
-  // Try a few common cases before using the stub.
-  Label call_stub;
-  const int kUnfolds = 3;
-  // Skip if either side is negative.
+  // (0 % x) must yield 0 (if x is finite, which is the case here).
   __ cmp(left, Operand(0));
-  __ cmp(right, Operand(0), NegateCondition(mi));
-  __ b(mi, &call_stub);
+  __ b(eq, &done);
+  // Preload right in a vfp register.
+  __ vmov(divisor.low(), right);
+  __ b(lt, &vfp_modulo);
+
+  __ cmp(left, Operand(right));
+  __ b(lt, &done);
+
+  // Check for (positive) power of two on the right hand side.
+  __ JumpIfNotPowerOfTwoOrZeroAndNeg(right,
+                                     scratch,
+                                     &right_negative,
+                                     &both_positive);
+  // Perform modulo operation (scratch contains right - 1).
+  __ and_(result, scratch, Operand(left));
+  __ b(&done);
+
+  __ bind(&right_negative);
+  // Negate right. The sign of the divisor does not matter.
+  __ rsb(right, right, Operand(0));
+
+  __ bind(&both_positive);
+  const int kUnfolds = 3;
   // If the right hand side is smaller than the (nonnegative)
-  // left hand side, it is the result. Else try a few subtractions
-  // of the left hand side.
+  // left hand side, the left hand side is the result.
+  // Else try a few subtractions of the left hand side.
   __ mov(scratch, left);
   for (int i = 0; i < kUnfolds; i++) {
     // Check if the left hand side is less or equal than the
     // the right hand side.
-    __ cmp(scratch, right);
+    __ cmp(scratch, Operand(right));
     __ mov(result, scratch, LeaveCC, lt);
     __ b(lt, &done);
     // If not, reduce the left hand side by the right hand
@@ -839,28 +886,45 @@
     if (i < kUnfolds - 1) __ sub(scratch, scratch, right);
   }
 
-  // Check for power of two on the right hand side.
-  __ JumpIfNotPowerOfTwoOrZero(right, scratch, &call_stub);
-  // Perform modulo operation (scratch contains right - 1).
-  __ and_(result, scratch, Operand(left));
+  __ bind(&vfp_modulo);
+  // Load the arguments in VFP registers.
+  // The divisor value is preloaded before. Be careful that 'right' is only live
+  // on entry.
+  __ vmov(dividend.low(), left);
+  // From here on don't use right as it may have been reallocated (for example
+  // to scratch2).
+  right = no_reg;
 
-  __ bind(&call_stub);
-  // Call the stub. The numbers in r0 and r1 have
-  // to be tagged to Smis. If that is not possible, deoptimize.
-  DeferredModI* deferred = new DeferredModI(this, instr);
-  __ TrySmiTag(left, &deoptimize, scratch);
-  __ TrySmiTag(right, &deoptimize, scratch);
+  __ vcvt_f64_s32(dividend, dividend.low());
+  __ vcvt_f64_s32(divisor, divisor.low());
 
-  __ b(al, deferred->entry());
-  __ bind(deferred->exit());
+  // We do not care about the sign of the divisor.
+  __ vabs(divisor, divisor);
+  // Compute the quotient and round it to a 32bit integer.
+  __ vdiv(quotient, dividend, divisor);
+  __ vcvt_s32_f64(quotient.low(), quotient);
+  __ vcvt_f64_s32(quotient, quotient.low());
 
-  // If the result in r0 is a Smi, untag it, else deoptimize.
-  __ JumpIfNotSmi(result, &deoptimize);
-  __ SmiUntag(result);
+  // Compute the remainder in result.
+  DwVfpRegister double_scratch = dividend;
+  __ vmul(double_scratch, divisor, quotient);
+  __ vcvt_s32_f64(double_scratch.low(), double_scratch);
+  __ vmov(scratch, double_scratch.low());
 
-  __ b(al, &done);
-  __ bind(&deoptimize);
-  DeoptimizeIf(al, instr->environment());
+  if (!instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    __ sub(result, left, scratch);
+  } else {
+    Label ok;
+    // Check for -0.
+    __ sub(scratch2, left, scratch, SetCC);
+    __ b(ne, &ok);
+    __ cmp(left, Operand(0));
+    DeoptimizeIf(mi, instr->environment());
+    __ bind(&ok);
+    // Load the result and we are done.
+    __ mov(result, scratch2);
+  }
+
   __ bind(&done);
 }
 
@@ -884,16 +948,16 @@
 
   // Check for x / 0.
   if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
-    __ tst(right, right);
+    __ cmp(right, Operand(0));
     DeoptimizeIf(eq, instr->environment());
   }
 
   // Check for (0 / -x) that will produce negative zero.
   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
     Label left_not_zero;
-    __ tst(left, Operand(left));
+    __ cmp(left, Operand(0));
     __ b(ne, &left_not_zero);
-    __ tst(right, Operand(right));
+    __ cmp(right, Operand(0));
     DeoptimizeIf(mi, instr->environment());
     __ bind(&left_not_zero);
   }
@@ -1000,7 +1064,7 @@
   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
     // Bail out if the result is supposed to be negative zero.
     Label done;
-    __ tst(left, Operand(left));
+    __ cmp(left, Operand(0));
     __ b(ne, &done);
     if (instr->InputAt(1)->IsConstantOperand()) {
       if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) <= 0) {
@@ -1022,16 +1086,25 @@
   ASSERT(left->Equals(instr->result()));
   ASSERT(left->IsRegister());
   Register result = ToRegister(left);
-  Register right_reg = EmitLoadRegister(right, ip);
+  Operand right_operand(no_reg);
+
+  if (right->IsStackSlot() || right->IsArgument()) {
+    Register right_reg = EmitLoadRegister(right, ip);
+    right_operand = Operand(right_reg);
+  } else {
+    ASSERT(right->IsRegister() || right->IsConstantOperand());
+    right_operand = ToOperand(right);
+  }
+
   switch (instr->op()) {
     case Token::BIT_AND:
-      __ and_(result, ToRegister(left), Operand(right_reg));
+      __ and_(result, ToRegister(left), right_operand);
       break;
     case Token::BIT_OR:
-      __ orr(result, ToRegister(left), Operand(right_reg));
+      __ orr(result, ToRegister(left), right_operand);
       break;
     case Token::BIT_XOR:
-      __ eor(result, ToRegister(left), Operand(right_reg));
+      __ eor(result, ToRegister(left), right_operand);
       break;
     default:
       UNREACHABLE();
@@ -1100,11 +1173,21 @@
 
 
 void LCodeGen::DoSubI(LSubI* instr) {
-  Register left = ToRegister(instr->InputAt(0));
-  Register right = EmitLoadRegister(instr->InputAt(1), ip);
-  ASSERT(instr->InputAt(0)->Equals(instr->result()));
-  __ sub(left, left, right, SetCC);
-  if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+  LOperand* left = instr->InputAt(0);
+  LOperand* right = instr->InputAt(1);
+  ASSERT(left->Equals(instr->result()));
+  bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
+  SBit set_cond = can_overflow ? SetCC : LeaveCC;
+
+  if (right->IsStackSlot() || right->IsArgument()) {
+    Register right_reg = EmitLoadRegister(right, ip);
+    __ sub(ToRegister(left), ToRegister(left), Operand(right_reg), set_cond);
+  } else {
+    ASSERT(right->IsRegister() || right->IsConstantOperand());
+    __ sub(ToRegister(left), ToRegister(left), ToOperand(right), set_cond);
+  }
+
+  if (can_overflow) {
     DeoptimizeIf(vs, instr->environment());
   }
 }
@@ -1137,10 +1220,10 @@
 }
 
 
-void LCodeGen::DoPixelArrayLength(LPixelArrayLength* instr) {
+void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) {
   Register result = ToRegister(instr->result());
   Register array = ToRegister(instr->InputAt(0));
-  __ ldr(result, FieldMemOperand(array, PixelArray::kLengthOffset));
+  __ ldr(result, FieldMemOperand(array, ExternalArray::kLengthOffset));
 }
 
 
@@ -1193,11 +1276,18 @@
   LOperand* left = instr->InputAt(0);
   LOperand* right = instr->InputAt(1);
   ASSERT(left->Equals(instr->result()));
+  bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
+  SBit set_cond = can_overflow ? SetCC : LeaveCC;
 
-  Register right_reg = EmitLoadRegister(right, ip);
-  __ add(ToRegister(left), ToRegister(left), Operand(right_reg), SetCC);
+  if (right->IsStackSlot() || right->IsArgument()) {
+    Register right_reg = EmitLoadRegister(right, ip);
+    __ add(ToRegister(left), ToRegister(left), Operand(right_reg), set_cond);
+  } else {
+    ASSERT(right->IsRegister() || right->IsConstantOperand());
+    __ add(ToRegister(left), ToRegister(left), ToOperand(right), set_cond);
+  }
 
-  if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+  if (can_overflow) {
     DeoptimizeIf(vs, instr->environment());
   }
 }
@@ -1226,7 +1316,8 @@
       __ PrepareCallCFunction(4, scratch0());
       __ vmov(r0, r1, left);
       __ vmov(r2, r3, right);
-      __ CallCFunction(ExternalReference::double_fp_operation(Token::MOD), 4);
+      __ CallCFunction(
+          ExternalReference::double_fp_operation(Token::MOD, isolate()), 4);
       // Move the result in the double result register.
       __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result()));
 
@@ -1865,10 +1956,9 @@
   InstanceofStub stub(InstanceofStub::kArgsInRegisters);
   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
 
-  Label true_value, done;
-  __ tst(r0, r0);
-  __ mov(r0, Operand(Factory::false_value()), LeaveCC, ne);
-  __ mov(r0, Operand(Factory::true_value()), LeaveCC, eq);
+  __ cmp(r0, Operand(0));
+  __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne);
+  __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq);
 }
 
 
@@ -1881,7 +1971,7 @@
 
   InstanceofStub stub(InstanceofStub::kArgsInRegisters);
   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
-  __ tst(r0, Operand(r0));
+  __ cmp(r0, Operand(0));
   EmitBranch(true_block, false_block, eq);
 }
 
@@ -1927,13 +2017,13 @@
   // We use Factory::the_hole_value() on purpose instead of loading from the
   // root array to force relocation to be able to later patch with
   // the cached map.
-  __ mov(ip, Operand(Factory::the_hole_value()));
+  __ mov(ip, Operand(factory()->the_hole_value()));
   __ cmp(map, Operand(ip));
   __ b(ne, &cache_miss);
   // We use Factory::the_hole_value() on purpose instead of loading from the
   // root array to force relocation to be able to later patch
   // with true or false.
-  __ mov(result, Operand(Factory::the_hole_value()));
+  __ mov(result, Operand(factory()->the_hole_value()));
   __ b(&done);
 
   // The inlined call site cache did not match. Check null and string before
@@ -2140,13 +2230,77 @@
 }
 
 
+void LCodeGen::EmitLoadField(Register result,
+                             Register object,
+                             Handle<Map> type,
+                             Handle<String> name) {
+  LookupResult lookup;
+  type->LookupInDescriptors(NULL, *name, &lookup);
+  ASSERT(lookup.IsProperty() && lookup.type() == FIELD);
+  int index = lookup.GetLocalFieldIndexFromMap(*type);
+  int offset = index * kPointerSize;
+  if (index < 0) {
+    // Negative property indices are in-object properties, indexed
+    // from the end of the fixed part of the object.
+    __ ldr(result, FieldMemOperand(object, offset + type->instance_size()));
+  } else {
+    // Non-negative property indices are in the properties array.
+    __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
+    __ ldr(result, FieldMemOperand(result, offset + FixedArray::kHeaderSize));
+  }
+}
+
+
+void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
+  Register object = ToRegister(instr->object());
+  Register result = ToRegister(instr->result());
+  Register scratch = scratch0();
+  int map_count = instr->hydrogen()->types()->length();
+  Handle<String> name = instr->hydrogen()->name();
+  if (map_count == 0) {
+    ASSERT(instr->hydrogen()->need_generic());
+    __ mov(r2, Operand(name));
+    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+    CallCode(ic, RelocInfo::CODE_TARGET, instr);
+  } else {
+    Label done;
+    __ ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
+    for (int i = 0; i < map_count - 1; ++i) {
+      Handle<Map> map = instr->hydrogen()->types()->at(i);
+      Label next;
+      __ cmp(scratch, Operand(map));
+      __ b(ne, &next);
+      EmitLoadField(result, object, map, name);
+      __ b(&done);
+      __ bind(&next);
+    }
+    Handle<Map> map = instr->hydrogen()->types()->last();
+    __ cmp(scratch, Operand(map));
+    if (instr->hydrogen()->need_generic()) {
+      Label generic;
+      __ b(ne, &generic);
+      EmitLoadField(result, object, map, name);
+      __ b(&done);
+      __ bind(&generic);
+      __ mov(r2, Operand(name));
+      Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+      CallCode(ic, RelocInfo::CODE_TARGET, instr);
+    } else {
+      DeoptimizeIf(ne, instr->environment());
+      EmitLoadField(result, object, map, name);
+    }
+    __ bind(&done);
+  }
+}
+
+
 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
   ASSERT(ToRegister(instr->object()).is(r0));
   ASSERT(ToRegister(instr->result()).is(r0));
 
   // Name is always in r2.
   __ mov(r2, Operand(instr->name()));
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2207,7 +2361,7 @@
     __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
     __ cmp(scratch, ip);
     __ b(eq, &done);
-    __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
+    __ LoadRoot(ip, Heap::kExternalPixelArrayMapRootIndex);
     __ cmp(scratch, ip);
     __ b(eq, &done);
     __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
@@ -2218,11 +2372,12 @@
 }
 
 
-void LCodeGen::DoLoadPixelArrayExternalPointer(
-    LLoadPixelArrayExternalPointer* instr) {
+void LCodeGen::DoLoadExternalArrayPointer(
+    LLoadExternalArrayPointer* instr) {
   Register to_reg = ToRegister(instr->result());
   Register from_reg  = ToRegister(instr->InputAt(0));
-  __ ldr(to_reg, FieldMemOperand(from_reg, PixelArray::kExternalPointerOffset));
+  __ ldr(to_reg, FieldMemOperand(from_reg,
+                                 ExternalArray::kExternalPointerOffset));
 }
 
 
@@ -2262,13 +2417,16 @@
 }
 
 
-void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) {
-  Register external_elements = ToRegister(instr->external_pointer());
+void LCodeGen::DoLoadKeyedSpecializedArrayElement(
+    LLoadKeyedSpecializedArrayElement* instr) {
+  ASSERT(instr->array_type() == kExternalPixelArray);
+
+  Register external_pointer = ToRegister(instr->external_pointer());
   Register key = ToRegister(instr->key());
   Register result = ToRegister(instr->result());
 
   // Load the result.
-  __ ldrb(result, MemOperand(external_elements, key));
+  __ ldrb(result, MemOperand(external_pointer, key));
 }
 
 
@@ -2276,7 +2434,7 @@
   ASSERT(ToRegister(instr->object()).is(r1));
   ASSERT(ToRegister(instr->key()).is(r0));
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2368,7 +2526,7 @@
   // stack.
   Label invoke, loop;
   // length is a small non-negative integer, due to the test above.
-  __ tst(length, Operand(length));
+  __ cmp(length, Operand(0));
   __ b(eq, &invoke);
   __ bind(&loop);
   __ ldr(scratch, MemOperand(elements, length, LSL, 2));
@@ -2604,14 +2762,16 @@
   // Move the result back to general purpose register r0.
   __ vmov(result, single_scratch);
 
-  // Test for -0.
-  Label done;
-  __ cmp(result, Operand(0));
-  __ b(ne, &done);
-  __ vmov(scratch1, input.high());
-  __ tst(scratch1, Operand(HeapNumber::kSignMask));
-  DeoptimizeIf(ne, instr->environment());
-  __ bind(&done);
+  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    // Test for -0.
+    Label done;
+    __ cmp(result, Operand(0));
+    __ b(ne, &done);
+    __ vmov(scratch1, input.high());
+    __ tst(scratch1, Operand(HeapNumber::kSignMask));
+    DeoptimizeIf(ne, instr->environment());
+    __ bind(&done);
+  }
 }
 
 
@@ -2628,14 +2788,16 @@
   DeoptimizeIf(ne, instr->environment());
   __ vmov(result, double_scratch0().low());
 
-  // Test for -0.
-  Label done;
-  __ cmp(result, Operand(0));
-  __ b(ne, &done);
-  __ vmov(scratch1, input.high());
-  __ tst(scratch1, Operand(HeapNumber::kSignMask));
-  DeoptimizeIf(ne, instr->environment());
-  __ bind(&done);
+  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    // Test for -0.
+    Label done;
+    __ cmp(result, Operand(0));
+    __ b(ne, &done);
+    __ vmov(scratch1, input.high());
+    __ tst(scratch1, Operand(HeapNumber::kSignMask));
+    DeoptimizeIf(ne, instr->environment());
+    __ bind(&done);
+  }
 }
 
 
@@ -2646,6 +2808,22 @@
 }
 
 
+void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
+  DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
+  Register scratch = scratch0();
+  SwVfpRegister single_scratch = double_scratch0().low();
+  DoubleRegister double_scratch = double_scratch0();
+  ASSERT(ToDoubleRegister(instr->result()).is(input));
+
+  // Add +0 to convert -0 to +0.
+  __ mov(scratch, Operand(0));
+  __ vmov(single_scratch, scratch);
+  __ vcvt_f64_s32(double_scratch, single_scratch);
+  __ vadd(input, input, double_scratch);
+  __ vsqrt(input, input);
+}
+
+
 void LCodeGen::DoPower(LPower* instr) {
   LOperand* left = instr->InputAt(0);
   LOperand* right = instr->InputAt(1);
@@ -2657,14 +2835,16 @@
     __ PrepareCallCFunction(4, scratch);
     __ vmov(r0, r1, ToDoubleRegister(left));
     __ vmov(r2, r3, ToDoubleRegister(right));
-    __ CallCFunction(ExternalReference::power_double_double_function(), 4);
+    __ CallCFunction(
+        ExternalReference::power_double_double_function(isolate()), 4);
   } else if (exponent_type.IsInteger32()) {
     ASSERT(ToRegister(right).is(r0));
     // Prepare arguments and call C function.
     __ PrepareCallCFunction(4, scratch);
     __ mov(r2, ToRegister(right));
     __ vmov(r0, r1, ToDoubleRegister(left));
-    __ CallCFunction(ExternalReference::power_double_int_function(), 4);
+    __ CallCFunction(
+        ExternalReference::power_double_int_function(isolate()), 4);
   } else {
     ASSERT(exponent_type.IsTagged());
     ASSERT(instr->hydrogen()->left()->representation().IsDouble());
@@ -2697,7 +2877,8 @@
     __ PrepareCallCFunction(4, scratch);
     __ vmov(r0, r1, ToDoubleRegister(left));
     __ vmov(r2, r3, result_reg);
-    __ CallCFunction(ExternalReference::power_double_double_function(), 4);
+    __ CallCFunction(
+        ExternalReference::power_double_double_function(isolate()), 4);
   }
   // Store the result in the result register.
   __ GetCFunctionDoubleResult(result_reg);
@@ -2742,6 +2923,9 @@
     case kMathSqrt:
       DoMathSqrt(instr);
       break;
+    case kMathPowHalf:
+      DoMathPowHalf(instr);
+      break;
     case kMathCos:
       DoMathCos(instr);
       break;
@@ -2762,7 +2946,8 @@
   ASSERT(ToRegister(instr->result()).is(r0));
 
   int arity = instr->arity();
-  Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arity, NOT_IN_LOOP);
+  Handle<Code> ic =
+      isolate()->stub_cache()->ComputeKeyedCallInitialize(arity, NOT_IN_LOOP);
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
 }
@@ -2772,7 +2957,8 @@
   ASSERT(ToRegister(instr->result()).is(r0));
 
   int arity = instr->arity();
-  Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP);
+  Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(
+      arity, NOT_IN_LOOP);
   __ mov(r2, Operand(instr->name()));
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
   // Restore context register.
@@ -2795,7 +2981,8 @@
   ASSERT(ToRegister(instr->result()).is(r0));
 
   int arity = instr->arity();
-  Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP);
+  Handle<Code> ic =
+      isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP);
   __ mov(r2, Operand(instr->name()));
   CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
@@ -2813,7 +3000,7 @@
   ASSERT(ToRegister(instr->InputAt(0)).is(r1));
   ASSERT(ToRegister(instr->result()).is(r0));
 
-  Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall));
+  Handle<Code> builtin = isolate()->builtins()->JSConstructCall();
   __ mov(r0, Operand(instr->arity()));
   CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr);
 }
@@ -2862,9 +3049,9 @@
 
   // Name is always in r2.
   __ mov(r2, Operand(instr->name()));
-  Handle<Code> ic(Builtins::builtin(
-      info_->is_strict() ? Builtins::StoreIC_Initialize_Strict
-                         : Builtins::StoreIC_Initialize));
+  Handle<Code> ic = info_->is_strict()
+      ? isolate()->builtins()->StoreIC_Initialize_Strict()
+      : isolate()->builtins()->StoreIC_Initialize();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2901,14 +3088,28 @@
 }
 
 
+void LCodeGen::DoStoreKeyedSpecializedArrayElement(
+    LStoreKeyedSpecializedArrayElement* instr) {
+  ASSERT(instr->array_type() == kExternalPixelArray);
+
+  Register external_pointer = ToRegister(instr->external_pointer());
+  Register key = ToRegister(instr->key());
+  Register value = ToRegister(instr->value());
+
+  // Clamp the value to [0..255].
+  __ Usat(value, 8, Operand(value));
+  __ strb(value, MemOperand(external_pointer, key, LSL, 0));
+}
+
+
 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
   ASSERT(ToRegister(instr->object()).is(r2));
   ASSERT(ToRegister(instr->key()).is(r1));
   ASSERT(ToRegister(instr->value()).is(r0));
 
-  Handle<Code> ic(Builtins::builtin(
-      info_->is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
-                         : Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic = info_->is_strict()
+      ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+      : isolate()->builtins()->KeyedStoreIC_Initialize();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3054,6 +3255,56 @@
 }
 
 
+void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
+  class DeferredStringCharFromCode: public LDeferredCode {
+   public:
+    DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); }
+   private:
+    LStringCharFromCode* instr_;
+  };
+
+  DeferredStringCharFromCode* deferred =
+      new DeferredStringCharFromCode(this, instr);
+
+  ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
+  Register char_code = ToRegister(instr->char_code());
+  Register result = ToRegister(instr->result());
+  ASSERT(!char_code.is(result));
+
+  __ cmp(char_code, Operand(String::kMaxAsciiCharCode));
+  __ b(hi, deferred->entry());
+  __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
+  __ add(result, result, Operand(char_code, LSL, kPointerSizeLog2));
+  __ ldr(result, FieldMemOperand(result, FixedArray::kHeaderSize));
+  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+  __ cmp(result, ip);
+  __ b(eq, deferred->entry());
+  __ bind(deferred->exit());
+}
+
+
+void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
+  Register char_code = ToRegister(instr->char_code());
+  Register result = ToRegister(instr->result());
+
+  // TODO(3095996): Get rid of this. For now, we need to make the
+  // result register contain a valid pointer because it is already
+  // contained in the register pointer map.
+  __ mov(result, Operand(0));
+
+  __ PushSafepointRegisters();
+  __ SmiTag(char_code);
+  __ push(char_code);
+  __ CallRuntimeSaveDoubles(Runtime::kCharFromCode);
+  RecordSafepointWithRegisters(
+      instr->pointer_map(), 1, Safepoint::kNoDeoptimizationIndex);
+  __ StoreToSafepointRegisterSlot(r0, result);
+  __ PopSafepointRegisters();
+}
+
+
 void LCodeGen::DoStringLength(LStringLength* instr) {
   Register string = ToRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
@@ -3266,19 +3517,30 @@
 
 
 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
-  Label done;
   Register input_reg = ToRegister(instr->InputAt(0));
-  Register scratch = scratch0();
-  DoubleRegister dbl_scratch = d0;
-  SwVfpRegister flt_scratch = s0;
-  DoubleRegister dbl_tmp = ToDoubleRegister(instr->TempAt(0));
+  Register scratch1 = scratch0();
+  Register scratch2 = ToRegister(instr->TempAt(0));
+  DwVfpRegister double_scratch = double_scratch0();
+  SwVfpRegister single_scratch = double_scratch.low();
+
+  ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2));
+  ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1));
+
+  Label done;
 
   // Heap number map check.
-  __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
+  __ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset));
   __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
-  __ cmp(scratch, Operand(ip));
+  __ cmp(scratch1, Operand(ip));
 
   if (instr->truncating()) {
+    Register scratch3 = ToRegister(instr->TempAt(1));
+    DwVfpRegister double_scratch2 = ToDoubleRegister(instr->TempAt(2));
+    ASSERT(!scratch3.is(input_reg) &&
+           !scratch3.is(scratch1) &&
+           !scratch3.is(scratch2));
+    // Performs a truncating conversion of a floating point number as used by
+    // the JS bitwise operations.
     Label heap_number;
     __ b(eq, &heap_number);
     // Check for undefined. Undefined is converted to zero for truncating
@@ -3290,36 +3552,38 @@
     __ b(&done);
 
     __ bind(&heap_number);
-    __ sub(ip, input_reg, Operand(kHeapObjectTag));
-    __ vldr(dbl_tmp, ip, HeapNumber::kValueOffset);
-    __ vcmp(dbl_tmp, 0.0);  // Sets overflow bit in FPSCR flags if NaN.
-    __ vcvt_s32_f64(flt_scratch, dbl_tmp);
-    __ vmov(input_reg, flt_scratch);  // 32-bit result of conversion.
-    __ vmrs(pc);  // Move vector status bits to normal status bits.
-    // Overflow bit is set if dbl_tmp is Nan.
-    __ cmn(input_reg, Operand(1), vc);  // 0x7fffffff + 1 -> overflow.
-    __ cmp(input_reg, Operand(1), vc);  // 0x80000000 - 1 -> overflow.
-    DeoptimizeIf(vs, instr->environment());  // Saturation may have occured.
+    __ sub(scratch1, input_reg, Operand(kHeapObjectTag));
+    __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset);
+
+    __ EmitECMATruncate(input_reg,
+                        double_scratch2,
+                        single_scratch,
+                        scratch1,
+                        scratch2,
+                        scratch3);
 
   } else {
+    CpuFeatures::Scope scope(VFP3);
     // Deoptimize if we don't have a heap number.
     DeoptimizeIf(ne, instr->environment());
 
     __ sub(ip, input_reg, Operand(kHeapObjectTag));
-    __ vldr(dbl_tmp, ip, HeapNumber::kValueOffset);
-    __ vcvt_s32_f64(flt_scratch, dbl_tmp);
-    __ vmov(input_reg, flt_scratch);  // 32-bit result of conversion.
-    // Non-truncating conversion means that we cannot lose bits, so we convert
-    // back to check; note that using non-overlapping s and d regs would be
-    // slightly faster.
-    __ vcvt_f64_s32(dbl_scratch, flt_scratch);
-    __ VFPCompareAndSetFlags(dbl_scratch, dbl_tmp);
-    DeoptimizeIf(ne, instr->environment());  // Not equal or unordered.
+    __ vldr(double_scratch, ip, HeapNumber::kValueOffset);
+    __ EmitVFPTruncate(kRoundToZero,
+                       single_scratch,
+                       double_scratch,
+                       scratch1,
+                       scratch2,
+                       kCheckForInexactConversion);
+    DeoptimizeIf(ne, instr->environment());
+    // Load the result.
+    __ vmov(input_reg, single_scratch);
+
     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
-      __ tst(input_reg, Operand(input_reg));
+      __ cmp(input_reg, Operand(0));
       __ b(ne, &done);
-      __ vmov(lr, ip, dbl_tmp);
-      __ tst(ip, Operand(1 << 31));  // Test sign bit.
+      __ vmov(scratch1, double_scratch.high());
+      __ tst(scratch1, Operand(HeapNumber::kSignMask));
       DeoptimizeIf(ne, instr->environment());
     }
   }
@@ -3361,56 +3625,52 @@
 
 
 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
-  LOperand* input = instr->InputAt(0);
-  ASSERT(input->IsDoubleRegister());
-  LOperand* result = instr->result();
-  ASSERT(result->IsRegister());
-
-  DoubleRegister double_input = ToDoubleRegister(input);
-  Register result_reg = ToRegister(result);
-  SwVfpRegister single_scratch = double_scratch0().low();
+  Register result_reg = ToRegister(instr->result());
   Register scratch1 = scratch0();
   Register scratch2 = ToRegister(instr->TempAt(0));
+  DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0));
+  DwVfpRegister double_scratch = double_scratch0();
+  SwVfpRegister single_scratch = double_scratch0().low();
 
-  __ EmitVFPTruncate(kRoundToZero,
-                     single_scratch,
-                     double_input,
-                     scratch1,
-                     scratch2);
+  Label done;
 
-  // Deoptimize if we had a vfp invalid exception.
-  DeoptimizeIf(ne, instr->environment());
-
-  // Retrieve the result.
-  __ vmov(result_reg, single_scratch);
-
-  if (!instr->truncating()) {
-    // Convert result back to double and compare with input
-    // to check if the conversion was exact.
-    __ vmov(single_scratch, result_reg);
-    __ vcvt_f64_s32(double_scratch0(), single_scratch);
-    __ VFPCompareAndSetFlags(double_scratch0(), double_input);
+  if (instr->truncating()) {
+    Register scratch3 = ToRegister(instr->TempAt(1));
+    __ EmitECMATruncate(result_reg,
+                        double_input,
+                        single_scratch,
+                        scratch1,
+                        scratch2,
+                        scratch3);
+  } else {
+    VFPRoundingMode rounding_mode = kRoundToMinusInf;
+    __ EmitVFPTruncate(rounding_mode,
+                       single_scratch,
+                       double_input,
+                       scratch1,
+                       scratch2,
+                       kCheckForInexactConversion);
+    // Deoptimize if we had a vfp invalid exception,
+    // including inexact operation.
     DeoptimizeIf(ne, instr->environment());
-    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
-      Label done;
-      __ cmp(result_reg, Operand(0));
-      __ b(ne, &done);
-      // Check for -0.
-      __ vmov(scratch1, double_input.high());
-      __ tst(scratch1, Operand(HeapNumber::kSignMask));
-      DeoptimizeIf(ne, instr->environment());
-
-      __ bind(&done);
-    }
+    // Retrieve the result.
+    __ vmov(result_reg, single_scratch);
   }
+    __ bind(&done);
 }
 
 
 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
   LOperand* input = instr->InputAt(0);
-  ASSERT(input->IsRegister());
   __ tst(ToRegister(input), Operand(kSmiTagMask));
-  DeoptimizeIf(instr->condition(), instr->environment());
+  DeoptimizeIf(ne, instr->environment());
+}
+
+
+void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
+  LOperand* input = instr->InputAt(0);
+  __ tst(ToRegister(input), Operand(kSmiTagMask));
+  DeoptimizeIf(eq, instr->environment());
 }
 
 
@@ -3459,9 +3719,9 @@
 
 void LCodeGen::LoadHeapObject(Register result,
                               Handle<HeapObject> object) {
-  if (Heap::InNewSpace(*object)) {
+  if (heap()->InNewSpace(*object)) {
     Handle<JSGlobalPropertyCell> cell =
-        Factory::NewJSGlobalPropertyCell(object);
+        factory()->NewJSGlobalPropertyCell(object);
     __ mov(result, Operand(cell));
     __ ldr(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset));
   } else {
@@ -3543,6 +3803,13 @@
 }
 
 
+void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
+  ASSERT(ToRegister(instr->InputAt(0)).is(r0));
+  __ push(r0);
+  CallRuntime(Runtime::kToFastProperties, 1, instr);
+}
+
+
 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
   Label materialized;
   // Registers will be used as follows:
@@ -3603,16 +3870,17 @@
   // space for nested functions that don't need literals cloning.
   Handle<SharedFunctionInfo> shared_info = instr->shared_info();
   bool pretenure = instr->hydrogen()->pretenure();
-  if (shared_info->num_literals() == 0 && !pretenure) {
-    FastNewClosureStub stub;
+  if (!pretenure && shared_info->num_literals() == 0) {
+    FastNewClosureStub stub(
+        shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
     __ mov(r1, Operand(shared_info));
     __ push(r1);
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   } else {
     __ mov(r2, Operand(shared_info));
     __ mov(r1, Operand(pretenure
-                       ? Factory::true_value()
-                       : Factory::false_value()));
+                       ? factory()->true_value()
+                       : factory()->false_value()));
     __ Push(cp, r2, r1);
     CallRuntime(Runtime::kNewClosure, 3, instr);
   }
@@ -3671,14 +3939,14 @@
                                  Handle<String> type_name) {
   Condition final_branch_condition = kNoCondition;
   Register scratch = scratch0();
-  if (type_name->Equals(Heap::number_symbol())) {
+  if (type_name->Equals(heap()->number_symbol())) {
     __ JumpIfSmi(input, true_label);
     __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
     __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
     __ cmp(input, Operand(ip));
     final_branch_condition = eq;
 
-  } else if (type_name->Equals(Heap::string_symbol())) {
+  } else if (type_name->Equals(heap()->string_symbol())) {
     __ JumpIfSmi(input, false_label);
     __ CompareObjectType(input, input, scratch, FIRST_NONSTRING_TYPE);
     __ b(ge, false_label);
@@ -3686,13 +3954,13 @@
     __ tst(ip, Operand(1 << Map::kIsUndetectable));
     final_branch_condition = eq;
 
-  } else if (type_name->Equals(Heap::boolean_symbol())) {
+  } else if (type_name->Equals(heap()->boolean_symbol())) {
     __ CompareRoot(input, Heap::kTrueValueRootIndex);
     __ b(eq, true_label);
     __ CompareRoot(input, Heap::kFalseValueRootIndex);
     final_branch_condition = eq;
 
-  } else if (type_name->Equals(Heap::undefined_symbol())) {
+  } else if (type_name->Equals(heap()->undefined_symbol())) {
     __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
     __ b(eq, true_label);
     __ JumpIfSmi(input, false_label);
@@ -3702,12 +3970,12 @@
     __ tst(ip, Operand(1 << Map::kIsUndetectable));
     final_branch_condition = ne;
 
-  } else if (type_name->Equals(Heap::function_symbol())) {
+  } else if (type_name->Equals(heap()->function_symbol())) {
     __ JumpIfSmi(input, false_label);
     __ CompareObjectType(input, input, scratch, FIRST_FUNCTION_CLASS_TYPE);
     final_branch_condition = ge;
 
-  } else if (type_name->Equals(Heap::object_symbol())) {
+  } else if (type_name->Equals(heap()->object_symbol())) {
     __ JumpIfSmi(input, false_label);
     __ CompareRoot(input, Heap::kNullValueRootIndex);
     __ b(eq, true_label);
diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h
index 23e0c44..caa85d2 100644
--- a/src/arm/lithium-codegen-arm.h
+++ b/src/arm/lithium-codegen-arm.h
@@ -65,6 +65,9 @@
   // Simple accessors.
   MacroAssembler* masm() const { return masm_; }
   CompilationInfo* info() const { return info_; }
+  Isolate* isolate() const { return info_->isolate(); }
+  Factory* factory() const { return isolate()->factory(); }
+  Heap* heap() const { return isolate()->heap(); }
 
   // Support for converting LOperands to assembler types.
   // LOperand must be a register.
@@ -105,6 +108,7 @@
   void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
   void DoDeferredStackCheck(LGoto* instr);
   void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
+  void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
   void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
                                         Label* map_check);
 
@@ -171,13 +175,13 @@
   void CallCode(Handle<Code> code,
                 RelocInfo::Mode mode,
                 LInstruction* instr);
-  void CallRuntime(Runtime::Function* function,
+  void CallRuntime(const Runtime::Function* function,
                    int num_arguments,
                    LInstruction* instr);
   void CallRuntime(Runtime::FunctionId id,
                    int num_arguments,
                    LInstruction* instr) {
-    Runtime::Function* function = Runtime::FunctionForId(id);
+    const Runtime::Function* function = Runtime::FunctionForId(id);
     CallRuntime(function, num_arguments, instr);
   }
 
@@ -210,6 +214,7 @@
   void DoMathFloor(LUnaryMathOperation* instr);
   void DoMathRound(LUnaryMathOperation* instr);
   void DoMathSqrt(LUnaryMathOperation* instr);
+  void DoMathPowHalf(LUnaryMathOperation* instr);
   void DoMathLog(LUnaryMathOperation* instr);
   void DoMathCos(LUnaryMathOperation* instr);
   void DoMathSin(LUnaryMathOperation* instr);
@@ -228,6 +233,9 @@
                                               int arguments,
                                               int deoptimization_index);
   void RecordPosition(int position);
+  int LastSafepointEnd() {
+    return static_cast<int>(safepoints_.GetPcAfterGap());
+  }
 
   static Condition TokenToCondition(Token::Value op, bool is_unsigned);
   void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL);
@@ -256,6 +264,11 @@
   // Caller should branch on equal condition.
   void EmitIsConstructCall(Register temp1, Register temp2);
 
+  void EmitLoadField(Register result,
+                     Register object,
+                     Handle<Map> type,
+                     Handle<String> name);
+
   LChunk* const chunk_;
   MacroAssembler* const masm_;
   CompilationInfo* const info_;
diff --git a/src/arm/lithium-gap-resolver-arm.cc b/src/arm/lithium-gap-resolver-arm.cc
index 1a2326b..02608a6 100644
--- a/src/arm/lithium-gap-resolver-arm.cc
+++ b/src/arm/lithium-gap-resolver-arm.cc
@@ -25,6 +25,8 @@
 // (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 "arm/lithium-gap-resolver-arm.h"
 #include "arm/lithium-codegen-arm.h"
 
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index d431f6a..3a1a8b6 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -43,7 +43,7 @@
     : Assembler(buffer, size),
       generating_stub_(false),
       allow_stub_calls_(true),
-      code_object_(Heap::undefined_value()) {
+      code_object_(HEAP->undefined_value()) {
 }
 
 
@@ -103,7 +103,22 @@
 }
 
 
+int MacroAssembler::CallSize(Register target, Condition cond) {
+#if USE_BLX
+  return kInstrSize;
+#else
+  return 2 * kInstrSize;
+#endif
+}
+
+
 void MacroAssembler::Call(Register target, Condition cond) {
+  // Block constant pool for the call instruction sequence.
+  BlockConstPoolScope block_const_pool(this);
+#ifdef DEBUG
+  int pre_position = pc_offset();
+#endif
+
 #if USE_BLX
   blx(target, cond);
 #else
@@ -111,29 +126,46 @@
   mov(lr, Operand(pc), LeaveCC, cond);
   mov(pc, Operand(target), LeaveCC, cond);
 #endif
+
+#ifdef DEBUG
+  int post_position = pc_offset();
+  CHECK_EQ(pre_position + CallSize(target, cond), post_position);
+#endif
 }
 
 
-void MacroAssembler::Call(intptr_t target, RelocInfo::Mode rmode,
-                          Condition cond) {
+int MacroAssembler::CallSize(
+    intptr_t target, RelocInfo::Mode rmode, Condition cond) {
+  int size = 2 * kInstrSize;
+  Instr mov_instr = cond | MOV | LeaveCC;
+  if (!Operand(target, rmode).is_single_instruction(mov_instr)) {
+    size += kInstrSize;
+  }
+  return size;
+}
+
+
+void MacroAssembler::Call(
+    intptr_t target, RelocInfo::Mode rmode, Condition cond) {
+  // Block constant pool for the call instruction sequence.
+  BlockConstPoolScope block_const_pool(this);
+#ifdef DEBUG
+  int pre_position = pc_offset();
+#endif
+
 #if USE_BLX
   // On ARMv5 and after the recommended call sequence is:
   //  ldr ip, [pc, #...]
   //  blx ip
 
-  // The two instructions (ldr and blx) could be separated by a constant
-  // pool and the code would still work. The issue comes from the
-  // patching code which expect the ldr to be just above the blx.
-  { BlockConstPoolScope block_const_pool(this);
-    // Statement positions are expected to be recorded when the target
-    // address is loaded. The mov method will automatically record
-    // positions when pc is the target, since this is not the case here
-    // we have to do it explicitly.
-    positions_recorder()->WriteRecordedPositions();
+  // Statement positions are expected to be recorded when the target
+  // address is loaded. The mov method will automatically record
+  // positions when pc is the target, since this is not the case here
+  // we have to do it explicitly.
+  positions_recorder()->WriteRecordedPositions();
 
-    mov(ip, Operand(target, rmode), LeaveCC, cond);
-    blx(ip, cond);
-  }
+  mov(ip, Operand(target, rmode), LeaveCC, cond);
+  blx(ip, cond);
 
   ASSERT(kCallTargetAddressOffset == 2 * kInstrSize);
 #else
@@ -141,24 +173,58 @@
   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);
-
   ASSERT(kCallTargetAddressOffset == kInstrSize);
 #endif
+
+#ifdef DEBUG
+  int post_position = pc_offset();
+  CHECK_EQ(pre_position + CallSize(target, rmode, cond), post_position);
+#endif
 }
 
 
-void MacroAssembler::Call(byte* target, RelocInfo::Mode rmode,
-                          Condition cond) {
-  ASSERT(!RelocInfo::IsCodeTarget(rmode));
-  Call(reinterpret_cast<intptr_t>(target), rmode, cond);
+int MacroAssembler::CallSize(
+    byte* target, RelocInfo::Mode rmode, Condition cond) {
+  return CallSize(reinterpret_cast<intptr_t>(target), rmode);
 }
 
 
-void MacroAssembler::Call(Handle<Code> code, RelocInfo::Mode rmode,
-                          Condition cond) {
+void MacroAssembler::Call(
+    byte* target, RelocInfo::Mode rmode, Condition cond) {
+#ifdef DEBUG
+  int pre_position = pc_offset();
+#endif
+
+  ASSERT(!RelocInfo::IsCodeTarget(rmode));
+  Call(reinterpret_cast<intptr_t>(target), rmode, cond);
+
+#ifdef DEBUG
+  int post_position = pc_offset();
+  CHECK_EQ(pre_position + CallSize(target, rmode, cond), post_position);
+#endif
+}
+
+
+int MacroAssembler::CallSize(
+    Handle<Code> code, RelocInfo::Mode rmode, Condition cond) {
+  return CallSize(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
+}
+
+
+void MacroAssembler::Call(
+    Handle<Code> code, RelocInfo::Mode rmode, Condition cond) {
+#ifdef DEBUG
+  int pre_position = pc_offset();
+#endif
+
   ASSERT(RelocInfo::IsCodeTarget(rmode));
   // 'code' is always generated ARM code, never THUMB code
   Call(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
+
+#ifdef DEBUG
+  int post_position = pc_offset();
+  CHECK_EQ(pre_position + CallSize(code, rmode, cond), post_position);
+#endif
 }
 
 
@@ -226,7 +292,7 @@
 
   } else if (!src2.is_single_instruction() &&
              !src2.must_use_constant_pool() &&
-             CpuFeatures::IsSupported(ARMv7) &&
+             Isolate::Current()->cpu_features()->IsSupported(ARMv7) &&
              IsPowerOf2(src2.immediate() + 1)) {
     ubfx(dst, src1, 0, WhichPowerOf2(src2.immediate() + 1), cond);
 
@@ -239,7 +305,7 @@
 void MacroAssembler::Ubfx(Register dst, Register src1, int lsb, int width,
                           Condition cond) {
   ASSERT(lsb < 32);
-  if (!CpuFeatures::IsSupported(ARMv7)) {
+  if (!Isolate::Current()->cpu_features()->IsSupported(ARMv7)) {
     int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
     and_(dst, src1, Operand(mask), LeaveCC, cond);
     if (lsb != 0) {
@@ -254,7 +320,7 @@
 void MacroAssembler::Sbfx(Register dst, Register src1, int lsb, int width,
                           Condition cond) {
   ASSERT(lsb < 32);
-  if (!CpuFeatures::IsSupported(ARMv7)) {
+  if (!Isolate::Current()->cpu_features()->IsSupported(ARMv7)) {
     int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
     and_(dst, src1, Operand(mask), LeaveCC, cond);
     int shift_up = 32 - lsb - width;
@@ -282,7 +348,7 @@
   ASSERT(lsb + width < 32);
   ASSERT(!scratch.is(dst));
   if (width == 0) return;
-  if (!CpuFeatures::IsSupported(ARMv7)) {
+  if (!Isolate::Current()->cpu_features()->IsSupported(ARMv7)) {
     int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
     bic(dst, dst, Operand(mask));
     and_(scratch, src, Operand((1 << width) - 1));
@@ -296,7 +362,7 @@
 
 void MacroAssembler::Bfc(Register dst, int lsb, int width, Condition cond) {
   ASSERT(lsb < 32);
-  if (!CpuFeatures::IsSupported(ARMv7)) {
+  if (!Isolate::Current()->cpu_features()->IsSupported(ARMv7)) {
     int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
     bic(dst, dst, Operand(mask));
   } else {
@@ -307,7 +373,7 @@
 
 void MacroAssembler::Usat(Register dst, int satpos, const Operand& src,
                           Condition cond) {
-  if (!CpuFeatures::IsSupported(ARMv7)) {
+  if (!Isolate::Current()->cpu_features()->IsSupported(ARMv7)) {
     ASSERT(!dst.is(pc) && !src.rm().is(pc));
     ASSERT((satpos >= 0) && (satpos <= 31));
 
@@ -367,7 +433,7 @@
 void MacroAssembler::RecordWriteHelper(Register object,
                                        Register address,
                                        Register scratch) {
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     // Check that the object is not in new space.
     Label not_in_new_space;
     InNewSpace(object, scratch, ne, &not_in_new_space);
@@ -395,8 +461,8 @@
                                 Condition cond,
                                 Label* branch) {
   ASSERT(cond == eq || cond == ne);
-  and_(scratch, object, Operand(ExternalReference::new_space_mask()));
-  cmp(scratch, Operand(ExternalReference::new_space_start()));
+  and_(scratch, object, Operand(ExternalReference::new_space_mask(isolate())));
+  cmp(scratch, Operand(ExternalReference::new_space_start(isolate())));
   b(cond, branch);
 }
 
@@ -429,7 +495,7 @@
 
   // Clobber all input registers when running with the debug-code flag
   // turned on to provoke errors.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     mov(object, Operand(BitCast<int32_t>(kZapValue)));
     mov(scratch0, Operand(BitCast<int32_t>(kZapValue)));
     mov(scratch1, Operand(BitCast<int32_t>(kZapValue)));
@@ -461,7 +527,7 @@
 
   // Clobber all input registers when running with the debug-code flag
   // turned on to provoke errors.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     mov(object, Operand(BitCast<int32_t>(kZapValue)));
     mov(address, Operand(BitCast<int32_t>(kZapValue)));
     mov(scratch, Operand(BitCast<int32_t>(kZapValue)));
@@ -553,7 +619,7 @@
   ASSERT_EQ(dst1.code() + 1, dst2.code());
 
   // Generate two ldr instructions if ldrd is not available.
-  if (CpuFeatures::IsSupported(ARMv7)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(ARMv7)) {
     CpuFeatures::Scope scope(ARMv7);
     ldrd(dst1, dst2, src, cond);
   } else {
@@ -578,7 +644,7 @@
   ASSERT_EQ(src1.code() + 1, src2.code());
 
   // Generate two str instructions if strd is not available.
-  if (CpuFeatures::IsSupported(ARMv7)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(ARMv7)) {
     CpuFeatures::Scope scope(ARMv7);
     strd(src1, src2, dst, cond);
   } else {
@@ -665,7 +731,7 @@
   mov(fp, Operand(sp));  // Setup new frame pointer.
   // Reserve room for saved entry sp and code object.
   sub(sp, sp, Operand(2 * kPointerSize));
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     mov(ip, Operand(0));
     str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset));
   }
@@ -673,9 +739,9 @@
   str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset));
 
   // Save the frame pointer and the context in top.
-  mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
+  mov(ip, Operand(ExternalReference(Isolate::k_c_entry_fp_address, isolate())));
   str(fp, MemOperand(ip));
-  mov(ip, Operand(ExternalReference(Top::k_context_address)));
+  mov(ip, Operand(ExternalReference(Isolate::k_context_address, isolate())));
   str(cp, MemOperand(ip));
 
   // Optionally save all double registers.
@@ -751,11 +817,11 @@
 
   // Clear top frame.
   mov(r3, Operand(0, RelocInfo::NONE));
-  mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
+  mov(ip, Operand(ExternalReference(Isolate::k_c_entry_fp_address, isolate())));
   str(r3, MemOperand(ip));
 
   // Restore current context from top and clear it in debug mode.
-  mov(ip, Operand(ExternalReference(Top::k_context_address)));
+  mov(ip, Operand(ExternalReference(Isolate::k_context_address, isolate())));
   ldr(cp, MemOperand(ip));
 #ifdef DEBUG
   str(r3, MemOperand(ip));
@@ -784,7 +850,7 @@
                                     Register code_reg,
                                     Label* done,
                                     InvokeFlag flag,
-                                    PostCallGenerator* post_call_generator) {
+                                    CallWrapper* call_wrapper) {
   bool definitely_matches = false;
   Label regular_invoke;
 
@@ -837,10 +903,13 @@
     }
 
     Handle<Code> adaptor =
-        Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
+        isolate()->builtins()->ArgumentsAdaptorTrampoline();
     if (flag == CALL_FUNCTION) {
+      if (call_wrapper != NULL) {
+        call_wrapper->BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET));
+      }
       Call(adaptor, RelocInfo::CODE_TARGET);
-      if (post_call_generator != NULL) post_call_generator->Generate();
+      if (call_wrapper != NULL) call_wrapper->AfterCall();
       b(done);
     } else {
       Jump(adaptor, RelocInfo::CODE_TARGET);
@@ -854,14 +923,15 @@
                                 const ParameterCount& expected,
                                 const ParameterCount& actual,
                                 InvokeFlag flag,
-                                PostCallGenerator* post_call_generator) {
+                                CallWrapper* call_wrapper) {
   Label done;
 
   InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag,
-                 post_call_generator);
+                 call_wrapper);
   if (flag == CALL_FUNCTION) {
+    if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(code));
     Call(code);
-    if (post_call_generator != NULL) post_call_generator->Generate();
+    if (call_wrapper != NULL) call_wrapper->AfterCall();
   } else {
     ASSERT(flag == JUMP_FUNCTION);
     Jump(code);
@@ -896,7 +966,7 @@
 void MacroAssembler::InvokeFunction(Register fun,
                                     const ParameterCount& actual,
                                     InvokeFlag flag,
-                                    PostCallGenerator* post_call_generator) {
+                                    CallWrapper* call_wrapper) {
   // Contract with called JS functions requires that function is passed in r1.
   ASSERT(fun.is(r1));
 
@@ -913,7 +983,7 @@
       FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
 
   ParameterCount expected(expected_reg);
-  InvokeCode(code_reg, expected, actual, flag, post_call_generator);
+  InvokeCode(code_reg, expected, actual, flag, call_wrapper);
 }
 
 
@@ -977,7 +1047,7 @@
 void MacroAssembler::DebugBreak() {
   ASSERT(allow_stub_calls());
   mov(r0, Operand(0, RelocInfo::NONE));
-  mov(r1, Operand(ExternalReference(Runtime::kDebugBreak)));
+  mov(r1, Operand(ExternalReference(Runtime::kDebugBreak, isolate())));
   CEntryStub ces(1);
   Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
 }
@@ -1000,7 +1070,7 @@
            && StackHandlerConstants::kPCOffset == 3 * kPointerSize);
     stm(db_w, sp, r3.bit() | fp.bit() | lr.bit());
     // Save the current handler as the next handler.
-    mov(r3, Operand(ExternalReference(Top::k_handler_address)));
+    mov(r3, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
     ldr(r1, MemOperand(r3));
     ASSERT(StackHandlerConstants::kNextOffset == 0);
     push(r1);
@@ -1019,7 +1089,7 @@
            && StackHandlerConstants::kPCOffset == 3 * kPointerSize);
     stm(db_w, sp, r6.bit() | ip.bit() | lr.bit());
     // Save the current handler as the next handler.
-    mov(r7, Operand(ExternalReference(Top::k_handler_address)));
+    mov(r7, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
     ldr(r6, MemOperand(r7));
     ASSERT(StackHandlerConstants::kNextOffset == 0);
     push(r6);
@@ -1032,7 +1102,7 @@
 void MacroAssembler::PopTryHandler() {
   ASSERT_EQ(0, StackHandlerConstants::kNextOffset);
   pop(r1);
-  mov(ip, Operand(ExternalReference(Top::k_handler_address)));
+  mov(ip, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
   add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
   str(r1, MemOperand(ip));
 }
@@ -1048,7 +1118,7 @@
   STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
 
   // Drop the sp to the top of the handler.
-  mov(r3, Operand(ExternalReference(Top::k_handler_address)));
+  mov(r3, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
   ldr(sp, MemOperand(r3));
 
   // Restore the next handler and frame pointer, discard handler state.
@@ -1067,7 +1137,7 @@
   // Restore cp otherwise.
   ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
 #ifdef DEBUG
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     mov(lr, Operand(pc));
   }
 #endif
@@ -1087,7 +1157,7 @@
   }
 
   // Drop sp to the top stack handler.
-  mov(r3, Operand(ExternalReference(Top::k_handler_address)));
+  mov(r3, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
   ldr(sp, MemOperand(r3));
 
   // Unwind the handlers until the ENTRY handler is found.
@@ -1111,7 +1181,8 @@
 
   if (type == OUT_OF_MEMORY) {
     // Set external caught exception to false.
-    ExternalReference external_caught(Top::k_external_caught_exception_address);
+    ExternalReference external_caught(
+        Isolate::k_external_caught_exception_address, isolate());
     mov(r0, Operand(false, RelocInfo::NONE));
     mov(r2, Operand(external_caught));
     str(r0, MemOperand(r2));
@@ -1119,7 +1190,8 @@
     // 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)));
+    mov(r2, Operand(ExternalReference(Isolate::k_pending_exception_address,
+                                      isolate())));
     str(r0, MemOperand(r2));
   }
 
@@ -1140,7 +1212,7 @@
   // Restore cp otherwise.
   ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
 #ifdef DEBUG
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     mov(lr, Operand(pc));
   }
 #endif
@@ -1172,7 +1244,7 @@
   ldr(scratch, FieldMemOperand(scratch, GlobalObject::kGlobalContextOffset));
 
   // Check the context is a global context.
-  if (FLAG_debug_code) {
+  if (emit_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.
@@ -1191,7 +1263,7 @@
   b(eq, &same_contexts);
 
   // Check the context is a global context.
-  if (FLAG_debug_code) {
+  if (emit_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.
@@ -1233,7 +1305,7 @@
                                         Label* gc_required,
                                         AllocationFlags flags) {
   if (!FLAG_inline_new) {
-    if (FLAG_debug_code) {
+    if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
       mov(result, Operand(0x7091));
       mov(scratch1, Operand(0x7191));
@@ -1260,9 +1332,9 @@
   // Also, assert that the registers are numbered such that the values
   // are loaded in the correct order.
   ExternalReference new_space_allocation_top =
-      ExternalReference::new_space_allocation_top_address();
+      ExternalReference::new_space_allocation_top_address(isolate());
   ExternalReference new_space_allocation_limit =
-      ExternalReference::new_space_allocation_limit_address();
+      ExternalReference::new_space_allocation_limit_address(isolate());
   intptr_t top   =
       reinterpret_cast<intptr_t>(new_space_allocation_top.address());
   intptr_t limit =
@@ -1282,7 +1354,7 @@
     // Load allocation top into result and allocation limit into ip.
     ldm(ia, topaddr, result.bit() | ip.bit());
   } else {
-    if (FLAG_debug_code) {
+    if (emit_debug_code()) {
       // Assert that result actually contains top on entry. ip is used
       // immediately below so this use of ip does not cause difference with
       // respect to register content between debug and release mode.
@@ -1316,7 +1388,7 @@
                                         Label* gc_required,
                                         AllocationFlags flags) {
   if (!FLAG_inline_new) {
-    if (FLAG_debug_code) {
+    if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
       mov(result, Operand(0x7091));
       mov(scratch1, Operand(0x7191));
@@ -1340,9 +1412,9 @@
   // Also, assert that the registers are numbered such that the values
   // are loaded in the correct order.
   ExternalReference new_space_allocation_top =
-      ExternalReference::new_space_allocation_top_address();
+      ExternalReference::new_space_allocation_top_address(isolate());
   ExternalReference new_space_allocation_limit =
-      ExternalReference::new_space_allocation_limit_address();
+      ExternalReference::new_space_allocation_limit_address(isolate());
   intptr_t top =
       reinterpret_cast<intptr_t>(new_space_allocation_top.address());
   intptr_t limit =
@@ -1360,7 +1432,7 @@
     // Load allocation top into result and allocation limit into ip.
     ldm(ia, topaddr, result.bit() | ip.bit());
   } else {
-    if (FLAG_debug_code) {
+    if (emit_debug_code()) {
       // Assert that result actually contains top on entry. ip is used
       // immediately below so this use of ip does not cause difference with
       // respect to register content between debug and release mode.
@@ -1385,7 +1457,7 @@
   b(hi, gc_required);
 
   // Update allocation top. result temporarily holds the new top.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     tst(scratch2, Operand(kObjectAlignmentMask));
     Check(eq, "Unaligned allocation in new space");
   }
@@ -1401,7 +1473,7 @@
 void MacroAssembler::UndoAllocationInNewSpace(Register object,
                                               Register scratch) {
   ExternalReference new_space_allocation_top =
-      ExternalReference::new_space_allocation_top_address();
+      ExternalReference::new_space_allocation_top_address(isolate());
 
   // Make sure the object has no tag before resetting top.
   and_(object, object, Operand(~kHeapObjectTagMask));
@@ -1689,7 +1761,7 @@
   // No more valid handles (the result handle was the last one). Restore
   // previous handle scope.
   str(r4, MemOperand(r7, kNextOffset));
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     ldr(r1, MemOperand(r7, kLevelOffset));
     cmp(r1, r6);
     Check(eq, "Unexpected level after return from api call");
@@ -1703,7 +1775,7 @@
   // Check if the function scheduled an exception.
   bind(&leave_exit_frame);
   LoadRoot(r4, Heap::kTheHoleValueRootIndex);
-  mov(ip, Operand(ExternalReference::scheduled_exception_address()));
+  mov(ip, Operand(ExternalReference::scheduled_exception_address(isolate())));
   ldr(r5, MemOperand(ip));
   cmp(r4, r5);
   b(ne, &promote_scheduled_exception);
@@ -1714,8 +1786,11 @@
   mov(pc, lr);
 
   bind(&promote_scheduled_exception);
-  MaybeObject* result = TryTailCallExternalReference(
-      ExternalReference(Runtime::kPromoteScheduledException), 0, 1);
+  MaybeObject* result
+      = TryTailCallExternalReference(
+          ExternalReference(Runtime::kPromoteScheduledException, isolate()),
+          0,
+          1);
   if (result->IsFailure()) {
     return result;
   }
@@ -1725,7 +1800,8 @@
   str(r5, MemOperand(r7, kLimitOffset));
   mov(r4, r0);
   PrepareCallCFunction(0, r5);
-  CallCFunction(ExternalReference::delete_handle_scope_extensions(), 0);
+  CallCFunction(
+      ExternalReference::delete_handle_scope_extensions(isolate()), 0);
   mov(r0, r4);
   jmp(&leave_exit_frame);
 
@@ -1826,7 +1902,7 @@
                                     Register scratch2,
                                     DwVfpRegister double_scratch,
                                     Label *not_int32) {
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
     sub(scratch, source, Operand(kHeapObjectTag));
     vldr(double_scratch, scratch, HeapNumber::kValueOffset);
@@ -1922,7 +1998,7 @@
                                      Register scratch1,
                                      Register scratch2,
                                      CheckForInexactConversion check_inexact) {
-  ASSERT(CpuFeatures::IsSupported(VFP3));
+  ASSERT(Isolate::Current()->cpu_features()->IsSupported(VFP3));
   CpuFeatures::Scope scope(VFP3);
   Register prev_fpscr = scratch1;
   Register scratch = scratch2;
@@ -1962,10 +2038,125 @@
 }
 
 
+void MacroAssembler::EmitOutOfInt32RangeTruncate(Register result,
+                                                 Register input_high,
+                                                 Register input_low,
+                                                 Register scratch) {
+  Label done, normal_exponent, restore_sign;
+
+  // Extract the biased exponent in result.
+  Ubfx(result,
+       input_high,
+       HeapNumber::kExponentShift,
+       HeapNumber::kExponentBits);
+
+  // Check for Infinity and NaNs, which should return 0.
+  cmp(result, Operand(HeapNumber::kExponentMask));
+  mov(result, Operand(0), LeaveCC, eq);
+  b(eq, &done);
+
+  // Express exponent as delta to (number of mantissa bits + 31).
+  sub(result,
+      result,
+      Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 31),
+      SetCC);
+
+  // If the delta is strictly positive, all bits would be shifted away,
+  // which means that we can return 0.
+  b(le, &normal_exponent);
+  mov(result, Operand(0));
+  b(&done);
+
+  bind(&normal_exponent);
+  const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1;
+  // Calculate shift.
+  add(scratch, result, Operand(kShiftBase + HeapNumber::kMantissaBits), SetCC);
+
+  // Save the sign.
+  Register sign = result;
+  result = no_reg;
+  and_(sign, input_high, Operand(HeapNumber::kSignMask));
+
+  // Set the implicit 1 before the mantissa part in input_high.
+  orr(input_high,
+      input_high,
+      Operand(1 << HeapNumber::kMantissaBitsInTopWord));
+  // Shift the mantissa bits to the correct position.
+  // We don't need to clear non-mantissa bits as they will be shifted away.
+  // If they weren't, it would mean that the answer is in the 32bit range.
+  mov(input_high, Operand(input_high, LSL, scratch));
+
+  // Replace the shifted bits with bits from the lower mantissa word.
+  Label pos_shift, shift_done;
+  rsb(scratch, scratch, Operand(32), SetCC);
+  b(&pos_shift, ge);
+
+  // Negate scratch.
+  rsb(scratch, scratch, Operand(0));
+  mov(input_low, Operand(input_low, LSL, scratch));
+  b(&shift_done);
+
+  bind(&pos_shift);
+  mov(input_low, Operand(input_low, LSR, scratch));
+
+  bind(&shift_done);
+  orr(input_high, input_high, Operand(input_low));
+  // Restore sign if necessary.
+  cmp(sign, Operand(0));
+  result = sign;
+  sign = no_reg;
+  rsb(result, input_high, Operand(0), LeaveCC, ne);
+  mov(result, input_high, LeaveCC, eq);
+  bind(&done);
+}
+
+
+void MacroAssembler::EmitECMATruncate(Register result,
+                                      DwVfpRegister double_input,
+                                      SwVfpRegister single_scratch,
+                                      Register scratch,
+                                      Register input_high,
+                                      Register input_low) {
+  CpuFeatures::Scope scope(VFP3);
+  ASSERT(!input_high.is(result));
+  ASSERT(!input_low.is(result));
+  ASSERT(!input_low.is(input_high));
+  ASSERT(!scratch.is(result) &&
+         !scratch.is(input_high) &&
+         !scratch.is(input_low));
+  ASSERT(!single_scratch.is(double_input.low()) &&
+         !single_scratch.is(double_input.high()));
+
+  Label done;
+
+  // Clear cumulative exception flags.
+  ClearFPSCRBits(kVFPExceptionMask, scratch);
+  // Try a conversion to a signed integer.
+  vcvt_s32_f64(single_scratch, double_input);
+  vmov(result, single_scratch);
+  // Retrieve he FPSCR.
+  vmrs(scratch);
+  // Check for overflow and NaNs.
+  tst(scratch, Operand(kVFPOverflowExceptionBit |
+                       kVFPUnderflowExceptionBit |
+                       kVFPInvalidOpExceptionBit));
+  // If we had no exceptions we are done.
+  b(eq, &done);
+
+  // Load the double value and perform a manual truncation.
+  vmov(input_low, input_high, double_input);
+  EmitOutOfInt32RangeTruncate(result,
+                              input_high,
+                              input_low,
+                              scratch);
+  bind(&done);
+}
+
+
 void MacroAssembler::GetLeastBitsFromSmi(Register dst,
                                          Register src,
                                          int num_least_bits) {
-  if (CpuFeatures::IsSupported(ARMv7)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(ARMv7)) {
     ubfx(dst, src, kSmiTagSize, num_least_bits);
   } else {
     mov(dst, Operand(src, ASR, kSmiTagSize));
@@ -1981,7 +2172,8 @@
 }
 
 
-void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
+void MacroAssembler::CallRuntime(const 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
@@ -1997,7 +2189,7 @@
   // should remove this need and make the runtime routine entry code
   // smarter.
   mov(r0, Operand(num_arguments));
-  mov(r1, Operand(ExternalReference(f)));
+  mov(r1, Operand(ExternalReference(f, isolate())));
   CEntryStub stub(1);
   CallStub(&stub);
 }
@@ -2009,9 +2201,9 @@
 
 
 void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
-  Runtime::Function* function = Runtime::FunctionForId(id);
+  const Runtime::Function* function = Runtime::FunctionForId(id);
   mov(r0, Operand(function->nargs));
-  mov(r1, Operand(ExternalReference(function)));
+  mov(r1, Operand(ExternalReference(function, isolate())));
   CEntryStub stub(1);
   stub.SaveDoubles();
   CallStub(&stub);
@@ -2054,7 +2246,9 @@
 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
                                      int num_arguments,
                                      int result_size) {
-  TailCallExternalReference(ExternalReference(fid), num_arguments, result_size);
+  TailCallExternalReference(ExternalReference(fid, isolate()),
+                            num_arguments,
+                            result_size);
 }
 
 
@@ -2083,11 +2277,12 @@
 
 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
                                    InvokeJSFlags flags,
-                                   PostCallGenerator* post_call_generator) {
+                                   CallWrapper* call_wrapper) {
   GetBuiltinEntry(r2, id);
   if (flags == CALL_JS) {
+    if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(r2));
     Call(r2);
-    if (post_call_generator != NULL) post_call_generator->Generate();
+    if (call_wrapper != NULL) call_wrapper->AfterCall();
   } else {
     ASSERT(flags == JUMP_JS);
     Jump(r2);
@@ -2149,14 +2344,14 @@
 
 
 void MacroAssembler::Assert(Condition cond, const char* msg) {
-  if (FLAG_debug_code)
+  if (emit_debug_code())
     Check(cond, msg);
 }
 
 
 void MacroAssembler::AssertRegisterIsRoot(Register reg,
                                           Heap::RootListIndex index) {
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     LoadRoot(ip, index);
     cmp(reg, ip);
     Check(eq, "Register did not match expected root");
@@ -2165,7 +2360,7 @@
 
 
 void MacroAssembler::AssertFastElements(Register elements) {
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     ASSERT(!elements.is(ip));
     Label ok;
     push(elements);
@@ -2253,7 +2448,7 @@
   // (i.e., the static scope chain and runtime context chain do not agree).
   // A variable occurring in such a scope should have slot type LOOKUP and
   // not CONTEXT.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     ldr(ip, MemOperand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
     cmp(dst, ip);
     Check(eq, "Yo dawg, I heard you liked function contexts "
@@ -2278,7 +2473,7 @@
                                                   Register scratch) {
   // Load the initial map. The global functions all have initial maps.
   ldr(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     Label ok, fail;
     CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, false);
     b(&ok);
@@ -2300,6 +2495,18 @@
 }
 
 
+void MacroAssembler::JumpIfNotPowerOfTwoOrZeroAndNeg(
+    Register reg,
+    Register scratch,
+    Label* zero_and_neg,
+    Label* not_power_of_two) {
+  sub(scratch, reg, Operand(1), SetCC);
+  b(mi, zero_and_neg);
+  tst(scratch, reg);
+  b(ne, not_power_of_two);
+}
+
+
 void MacroAssembler::JumpIfNotBothSmi(Register reg1,
                                       Register reg2,
                                       Label* on_not_both_smi) {
@@ -2486,7 +2693,7 @@
 
   // Copy bytes in word size chunks.
   bind(&word_loop);
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     tst(src, Operand(kPointerSize - 1));
     Assert(eq, "Expecting alignment for CopyBytes");
   }
@@ -2585,11 +2792,17 @@
   b(ne, failure);
 }
 
+static const int kRegisterPassedArguments = 4;
 
 void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
   int frame_alignment = ActivationFrameAlignment();
+
+  // Reserve space for Isolate address which is always passed as last parameter
+  num_arguments += 1;
+
   // Up to four simple arguments are passed in registers r0..r3.
-  int stack_passed_arguments = (num_arguments <= 4) ? 0 : num_arguments - 4;
+  int stack_passed_arguments = (num_arguments <= kRegisterPassedArguments) ?
+                               0 : num_arguments - kRegisterPassedArguments;
   if (frame_alignment > kPointerSize) {
     // Make stack end at alignment and make room for num_arguments - 4 words
     // and the original value of sp.
@@ -2606,17 +2819,41 @@
 
 void MacroAssembler::CallCFunction(ExternalReference function,
                                    int num_arguments) {
-  mov(ip, Operand(function));
-  CallCFunction(ip, num_arguments);
+  CallCFunctionHelper(no_reg, function, ip, num_arguments);
+}
+
+void MacroAssembler::CallCFunction(Register function,
+                                   Register scratch,
+                                   int num_arguments) {
+  CallCFunctionHelper(function,
+                      ExternalReference::the_hole_value_location(isolate()),
+                      scratch,
+                      num_arguments);
 }
 
 
-void MacroAssembler::CallCFunction(Register function, int num_arguments) {
+void MacroAssembler::CallCFunctionHelper(Register function,
+                                         ExternalReference function_reference,
+                                         Register scratch,
+                                         int num_arguments) {
+  // Push Isolate address as the last argument.
+  if (num_arguments < kRegisterPassedArguments) {
+    Register arg_to_reg[] = {r0, r1, r2, r3};
+    Register r = arg_to_reg[num_arguments];
+    mov(r, Operand(ExternalReference::isolate_address()));
+  } else {
+    int stack_passed_arguments = num_arguments - kRegisterPassedArguments;
+    // Push Isolate address on the stack after the arguments.
+    mov(scratch, Operand(ExternalReference::isolate_address()));
+    str(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
+  }
+  num_arguments += 1;
+
   // Make sure that the stack is aligned before calling a C function unless
   // running in the simulator. The simulator has its own alignment check which
   // provides more information.
 #if defined(V8_HOST_ARCH_ARM)
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     int frame_alignment = OS::ActivationFrameAlignment();
     int frame_alignment_mask = frame_alignment - 1;
     if (frame_alignment > kPointerSize) {
@@ -2635,8 +2872,13 @@
   // Just call directly. The function called cannot cause a GC, or
   // allow preemption, so the return address in the link register
   // stays correct.
+  if (function.is(no_reg)) {
+    mov(scratch, Operand(function_reference));
+    function = scratch;
+  }
   Call(function);
-  int stack_passed_arguments = (num_arguments <= 4) ? 0 : num_arguments - 4;
+  int stack_passed_arguments = (num_arguments <= kRegisterPassedArguments) ?
+                               0 : num_arguments - kRegisterPassedArguments;
   if (OS::ActivationFrameAlignment() > kPointerSize) {
     ldr(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
   } else {
@@ -2650,7 +2892,7 @@
   const uint32_t kLdrOffsetMask = (1 << 12) - 1;
   const int32_t kPCRegOffset = 2 * kPointerSize;
   ldr(result, MemOperand(ldr_location));
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     // Check that the instruction is a ldr reg, [pc + offset] .
     and_(result, result, Operand(kLdrPCPattern));
     cmp(result, Operand(kLdrPCPattern));
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index aaf4458..2b81c08 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -34,7 +34,7 @@
 namespace internal {
 
 // Forward declaration.
-class PostCallGenerator;
+class CallWrapper;
 
 // ----------------------------------------------------------------------------
 // Static helper functions
@@ -96,8 +96,11 @@
   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);
+  int CallSize(Register target, Condition cond = al);
   void Call(Register target, Condition cond = al);
+  int CallSize(byte* target, RelocInfo::Mode rmode, Condition cond = al);
   void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al);
+  int CallSize(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
   void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
   void Ret(Condition cond = al);
 
@@ -343,7 +346,7 @@
                   const ParameterCount& expected,
                   const ParameterCount& actual,
                   InvokeFlag flag,
-                  PostCallGenerator* post_call_generator = NULL);
+                  CallWrapper* call_wrapper = NULL);
 
   void InvokeCode(Handle<Code> code,
                   const ParameterCount& expected,
@@ -356,7 +359,7 @@
   void InvokeFunction(Register function,
                       const ParameterCount& actual,
                       InvokeFlag flag,
-                      PostCallGenerator* post_call_generator = NULL);
+                      CallWrapper* call_wrapper = NULL);
 
   void InvokeFunction(JSFunction* function,
                       const ParameterCount& actual,
@@ -646,11 +649,11 @@
                       DwVfpRegister double_scratch,
                       Label *not_int32);
 
-// Truncates a double using a specific rounding mode.
-// Clears the z flag (ne condition) if an overflow occurs.
-// If exact_conversion is true, the z flag is also cleared if the conversion
-// was inexact, ie. if the double value could not be converted exactly
-// to a 32bit integer.
+  // Truncates a double using a specific rounding mode.
+  // Clears the z flag (ne condition) if an overflow occurs.
+  // If exact_conversion is true, the z flag is also cleared if the conversion
+  // was inexact, ie. if the double value could not be converted exactly
+  // to a 32bit integer.
   void EmitVFPTruncate(VFPRoundingMode rounding_mode,
                        SwVfpRegister result,
                        DwVfpRegister double_input,
@@ -659,6 +662,27 @@
                        CheckForInexactConversion check
                            = kDontCheckForInexactConversion);
 
+  // Helper for EmitECMATruncate.
+  // This will truncate a floating-point value outside of the singed 32bit
+  // integer range to a 32bit signed integer.
+  // Expects the double value loaded in input_high and input_low.
+  // Exits with the answer in 'result'.
+  // Note that this code does not work for values in the 32bit range!
+  void EmitOutOfInt32RangeTruncate(Register result,
+                                   Register input_high,
+                                   Register input_low,
+                                   Register scratch);
+
+  // Performs a truncating conversion of a floating point number as used by
+  // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
+  // Exits with 'result' holding the answer and all other registers clobbered.
+  void EmitECMATruncate(Register result,
+                        DwVfpRegister double_input,
+                        SwVfpRegister single_scratch,
+                        Register scratch,
+                        Register scratch2,
+                        Register scratch3);
+
   // Count leading zeros in a 32 bit word.  On ARM5 and later it uses the clz
   // instruction.  On pre-ARM5 hardware this routine gives the wrong answer
   // for 0 (31 instead of 32).  Source and scratch can be the same in which case
@@ -684,7 +708,7 @@
                                                Condition cond = al);
 
   // Call a runtime routine.
-  void CallRuntime(Runtime::Function* f, int num_arguments);
+  void CallRuntime(const Runtime::Function* f, int num_arguments);
   void CallRuntimeSaveDoubles(Runtime::FunctionId id);
 
   // Convenience function: Same as above, but takes the fid instead.
@@ -728,7 +752,7 @@
   // return address (unless this is somehow accounted for by the called
   // function).
   void CallCFunction(ExternalReference function, int num_arguments);
-  void CallCFunction(Register function, int num_arguments);
+  void CallCFunction(Register function, Register scratch, int num_arguments);
 
   void GetCFunctionDoubleResult(const DoubleRegister dst);
 
@@ -748,7 +772,7 @@
   // the unresolved list if the name does not resolve.
   void InvokeBuiltin(Builtins::JavaScript id,
                      InvokeJSFlags flags,
-                     PostCallGenerator* post_call_generator = NULL);
+                     CallWrapper* call_wrapper = NULL);
 
   // Store the code object for the given builtin in the target register and
   // setup the function in r1.
@@ -802,6 +826,16 @@
   void JumpIfNotPowerOfTwoOrZero(Register reg,
                                  Register scratch,
                                  Label* not_power_of_two_or_zero);
+  // Check whether the value of reg is a power of two and not zero.
+  // Control falls through if it is, with scratch containing the mask
+  // value (reg - 1).
+  // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is
+  // zero or negative, or jumps to the 'not_power_of_two' label if the value is
+  // strictly positive but not a power of two.
+  void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg,
+                                       Register scratch,
+                                       Label* zero_and_neg,
+                                       Label* not_power_of_two);
 
   // ---------------------------------------------------------------------------
   // Smi utilities
@@ -910,7 +944,13 @@
 
 
  private:
+  void CallCFunctionHelper(Register function,
+                           ExternalReference function_reference,
+                           Register scratch,
+                           int num_arguments);
+
   void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
+  int CallSize(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
   void Call(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
 
   // Helper functions for generating invokes.
@@ -920,7 +960,7 @@
                       Register code_reg,
                       Label* done,
                       InvokeFlag flag,
-                      PostCallGenerator* post_call_generator = NULL);
+                      CallWrapper* call_wrapper = NULL);
 
   // Activation support.
   void EnterFrame(StackFrame::Type type);
@@ -984,11 +1024,15 @@
 // Helper class for generating code or data associated with the code
 // right after a call instruction. As an example this can be used to
 // generate safepoint data after calls for crankshaft.
-class PostCallGenerator {
+class CallWrapper {
  public:
-  PostCallGenerator() { }
-  virtual ~PostCallGenerator() { }
-  virtual void Generate() = 0;
+  CallWrapper() { }
+  virtual ~CallWrapper() { }
+  // Called just before emitting a call. Argument is the size of the generated
+  // call code.
+  virtual void BeforeCall(int call_size) = 0;
+  // Called just after emitting a call, i.e., at the return site for the call.
+  virtual void AfterCall() = 0;
 };
 
 
diff --git a/src/arm/regexp-macro-assembler-arm.cc b/src/arm/regexp-macro-assembler-arm.cc
index 1f6ed67..8d540d4 100644
--- a/src/arm/regexp-macro-assembler-arm.cc
+++ b/src/arm/regexp-macro-assembler-arm.cc
@@ -60,6 +60,7 @@
  * Each call to a public method should retain this convention.
  *
  * The stack will have the following structure:
+ *  - fp[52]  Isolate* isolate   (Address of the current isolate)
  *  - fp[48]  direct_call  (if 1, direct call from JavaScript code,
  *                          if 0, call through the runtime system).
  *  - fp[44]  stack_area_base (High end of the memory area to use as
@@ -368,7 +369,7 @@
     __ add(r1, current_input_offset(), Operand(end_of_input_address()));
 
     ExternalReference function =
-        ExternalReference::re_case_insensitive_compare_uc16();
+        ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate());
     __ CallCFunction(function, argument_count);
 
     // Check if function returned non-zero for success or zero for failure.
@@ -626,7 +627,7 @@
   Label stack_ok;
 
   ExternalReference stack_limit =
-      ExternalReference::address_of_stack_limit();
+      ExternalReference::address_of_stack_limit(masm_->isolate());
   __ mov(r0, Operand(stack_limit));
   __ ldr(r0, MemOperand(r0));
   __ sub(r0, sp, r0, SetCC);
@@ -782,7 +783,7 @@
     __ mov(r0, backtrack_stackpointer());
     __ add(r1, frame_pointer(), Operand(kStackHighEnd));
     ExternalReference grow_stack =
-      ExternalReference::re_grow_stack();
+        ExternalReference::re_grow_stack(masm_->isolate());
     __ CallCFunction(grow_stack, num_arguments);
     // If return NULL, we have failed to grow the stack, and
     // must exit with a stack-overflow exception.
@@ -804,10 +805,10 @@
 
   CodeDesc code_desc;
   masm_->GetCode(&code_desc);
-  Handle<Code> code = Factory::NewCode(code_desc,
+  Handle<Code> code = FACTORY->NewCode(code_desc,
                                        Code::ComputeFlags(Code::REGEXP),
                                        masm_->CodeObject());
-  PROFILE(RegExpCodeCreateEvent(*code, *source));
+  PROFILE(Isolate::Current(), RegExpCodeCreateEvent(*code, *source));
   return Handle<Object>::cast(code);
 }
 
@@ -998,7 +999,7 @@
   __ mov(r1, Operand(masm_->CodeObject()));
   // r0 becomes return address pointer.
   ExternalReference stack_guard_check =
-      ExternalReference::re_check_stack_guard_state();
+      ExternalReference::re_check_stack_guard_state(masm_->isolate());
   CallCFunctionUsingStub(stack_guard_check, num_arguments);
 }
 
@@ -1013,8 +1014,10 @@
 int RegExpMacroAssemblerARM::CheckStackGuardState(Address* return_address,
                                                   Code* re_code,
                                                   Address re_frame) {
-  if (StackGuard::IsStackOverflow()) {
-    Top::StackOverflow();
+  Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
+  ASSERT(isolate == Isolate::Current());
+  if (isolate->stack_guard()->IsStackOverflow()) {
+    isolate->StackOverflow();
     return EXCEPTION;
   }
 
@@ -1158,7 +1161,7 @@
 void RegExpMacroAssemblerARM::CheckPreemption() {
   // Check for preemption.
   ExternalReference stack_limit =
-      ExternalReference::address_of_stack_limit();
+      ExternalReference::address_of_stack_limit(masm_->isolate());
   __ mov(r0, Operand(stack_limit));
   __ ldr(r0, MemOperand(r0));
   __ cmp(sp, r0);
@@ -1168,7 +1171,7 @@
 
 void RegExpMacroAssemblerARM::CheckStackLimit() {
   ExternalReference stack_limit =
-      ExternalReference::address_of_regexp_stack_limit();
+      ExternalReference::address_of_regexp_stack_limit(masm_->isolate());
   __ mov(r0, Operand(stack_limit));
   __ ldr(r0, MemOperand(r0));
   __ cmp(backtrack_stackpointer(), Operand(r0));
diff --git a/src/arm/regexp-macro-assembler-arm.h b/src/arm/regexp-macro-assembler-arm.h
index d9d0b35..b57d0eb 100644
--- a/src/arm/regexp-macro-assembler-arm.h
+++ b/src/arm/regexp-macro-assembler-arm.h
@@ -127,6 +127,7 @@
   static const int kRegisterOutput = kSecondaryReturnAddress + kPointerSize;
   static const int kStackHighEnd = kRegisterOutput + kPointerSize;
   static const int kDirectCall = kStackHighEnd + kPointerSize;
+  static const int kIsolate = kDirectCall + kPointerSize;
 
   // Below the frame pointer.
   // Register parameters stored by setup code.
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index f475a18..46797d9 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -49,12 +49,12 @@
 // 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
+// The ArmDebugger class is used by the simulator while debugging simulated ARM
 // code.
-class Debugger {
+class ArmDebugger {
  public:
-  explicit Debugger(Simulator* sim);
-  ~Debugger();
+  explicit ArmDebugger(Simulator* sim);
+  ~ArmDebugger();
 
   void Stop(Instruction* instr);
   void Debug();
@@ -83,12 +83,12 @@
 };
 
 
-Debugger::Debugger(Simulator* sim) {
+ArmDebugger::ArmDebugger(Simulator* sim) {
   sim_ = sim;
 }
 
 
-Debugger::~Debugger() {
+ArmDebugger::~ArmDebugger() {
 }
 
 
@@ -105,7 +105,7 @@
 }
 
 
-void Debugger::Stop(Instruction* instr) {
+void ArmDebugger::Stop(Instruction* instr) {
   // Get the stop code.
   uint32_t code = instr->SvcValue() & kStopCodeMask;
   // Retrieve the encoded address, which comes just after this stop.
@@ -137,7 +137,7 @@
 }
 
 
-void Debugger::Stop(Instruction* instr) {
+void ArmDebugger::Stop(Instruction* instr) {
   // Get the stop code.
   uint32_t code = instr->SvcValue() & kStopCodeMask;
   // Retrieve the encoded address, which comes just after this stop.
@@ -159,7 +159,7 @@
 #endif
 
 
-int32_t Debugger::GetRegisterValue(int regnum) {
+int32_t ArmDebugger::GetRegisterValue(int regnum) {
   if (regnum == kPCRegister) {
     return sim_->get_pc();
   } else {
@@ -168,12 +168,12 @@
 }
 
 
-double Debugger::GetVFPDoubleRegisterValue(int regnum) {
+double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) {
   return sim_->get_double_from_d_register(regnum);
 }
 
 
-bool Debugger::GetValue(const char* desc, int32_t* value) {
+bool ArmDebugger::GetValue(const char* desc, int32_t* value) {
   int regnum = Registers::Number(desc);
   if (regnum != kNoRegister) {
     *value = GetRegisterValue(regnum);
@@ -189,7 +189,7 @@
 }
 
 
-bool Debugger::GetVFPSingleValue(const char* desc, float* value) {
+bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) {
   bool is_double;
   int regnum = VFPRegisters::Number(desc, &is_double);
   if (regnum != kNoRegister && !is_double) {
@@ -200,7 +200,7 @@
 }
 
 
-bool Debugger::GetVFPDoubleValue(const char* desc, double* value) {
+bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) {
   bool is_double;
   int regnum = VFPRegisters::Number(desc, &is_double);
   if (regnum != kNoRegister && is_double) {
@@ -211,7 +211,7 @@
 }
 
 
-bool Debugger::SetBreakpoint(Instruction* breakpc) {
+bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
   // Check if a breakpoint can be set. If not return without any side-effects.
   if (sim_->break_pc_ != NULL) {
     return false;
@@ -226,7 +226,7 @@
 }
 
 
-bool Debugger::DeleteBreakpoint(Instruction* breakpc) {
+bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
   if (sim_->break_pc_ != NULL) {
     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
   }
@@ -237,21 +237,21 @@
 }
 
 
-void Debugger::UndoBreakpoints() {
+void ArmDebugger::UndoBreakpoints() {
   if (sim_->break_pc_ != NULL) {
     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
   }
 }
 
 
-void Debugger::RedoBreakpoints() {
+void ArmDebugger::RedoBreakpoints() {
   if (sim_->break_pc_ != NULL) {
     sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
   }
 }
 
 
-void Debugger::Debug() {
+void ArmDebugger::Debug() {
   intptr_t last_pc = -1;
   bool done = false;
 
@@ -316,16 +316,26 @@
             }
             for (int i = 0; i < kNumVFPDoubleRegisters; i++) {
               dvalue = GetVFPDoubleRegisterValue(i);
-              PrintF("%3s: %f\n",
-                  VFPRegisters::Name(i, true), dvalue);
+              uint64_t as_words = BitCast<uint64_t>(dvalue);
+              PrintF("%3s: %f 0x%08x %08x\n",
+                     VFPRegisters::Name(i, true),
+                     dvalue,
+                     static_cast<uint32_t>(as_words >> 32),
+                     static_cast<uint32_t>(as_words & 0xffffffff));
             }
           } else {
             if (GetValue(arg1, &value)) {
               PrintF("%s: 0x%08x %d \n", arg1, value, value);
             } else if (GetVFPSingleValue(arg1, &svalue)) {
-              PrintF("%s: %f \n", arg1, svalue);
+              uint32_t as_word = BitCast<uint32_t>(svalue);
+              PrintF("%s: %f 0x%08x\n", arg1, svalue, as_word);
             } else if (GetVFPDoubleValue(arg1, &dvalue)) {
-              PrintF("%s: %f \n", arg1, dvalue);
+              uint64_t as_words = BitCast<uint64_t>(dvalue);
+              PrintF("%s: %f 0x%08x %08x\n",
+                     arg1,
+                     dvalue,
+                     static_cast<uint32_t>(as_words >> 32),
+                     static_cast<uint32_t>(as_words & 0xffffffff));
             } else {
               PrintF("%s unrecognized\n", arg1);
             }
@@ -380,11 +390,24 @@
         end = cur + words;
 
         while (cur < end) {
-          PrintF("  0x%08x:  0x%08x %10d\n",
+          PrintF("  0x%08x:  0x%08x %10d",
                  reinterpret_cast<intptr_t>(cur), *cur, *cur);
+          HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
+          int value = *cur;
+          Heap* current_heap = v8::internal::Isolate::Current()->heap();
+          if (current_heap->Contains(obj) || ((value & 1) == 0)) {
+            PrintF(" (");
+            if ((value & 1) == 0) {
+              PrintF("smi %d", value / 2);
+            } else {
+              obj->ShortPrint();
+            }
+            PrintF(")");
+          }
+          PrintF("\n");
           cur++;
         }
-      } else if (strcmp(cmd, "disasm") == 0) {
+      } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
         disasm::NameConverter converter;
         disasm::Disassembler dasm(converter);
         // use a reasonably large buffer
@@ -398,11 +421,23 @@
           cur = reinterpret_cast<byte*>(sim_->get_pc());
           end = cur + (10 * Instruction::kInstrSize);
         } else if (argc == 2) {
-          int32_t value;
-          if (GetValue(arg1, &value)) {
-            cur = reinterpret_cast<byte*>(sim_->get_pc());
-            // Disassemble <arg1> instructions.
-            end = cur + (value * Instruction::kInstrSize);
+          int regnum = Registers::Number(arg1);
+          if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) {
+            // The argument is an address or a register name.
+            int32_t value;
+            if (GetValue(arg1, &value)) {
+              cur = reinterpret_cast<byte*>(value);
+              // Disassemble 10 instructions at <arg1>.
+              end = cur + (10 * Instruction::kInstrSize);
+            }
+          } else {
+            // The argument is the number of instructions.
+            int32_t value;
+            if (GetValue(arg1, &value)) {
+              cur = reinterpret_cast<byte*>(sim_->get_pc());
+              // Disassemble <arg1> instructions.
+              end = cur + (value * Instruction::kInstrSize);
+            }
           }
         } else {
           int32_t value1;
@@ -524,8 +559,10 @@
         PrintF("mem <address> [<words>]\n");
         PrintF("  dump memory content, default dump 10 words)\n");
         PrintF("disasm [<instructions>]\n");
-        PrintF("disasm [[<address>] <instructions>]\n");
-        PrintF("  disassemble code, default is 10 instructions from pc\n");
+        PrintF("disasm [<address/register>]\n");
+        PrintF("disasm [[<address/register>] <instructions>]\n");
+        PrintF("  disassemble code, default is 10 instructions\n");
+        PrintF("  from pc (alias 'di')\n");
         PrintF("gdb\n");
         PrintF("  enter gdb\n");
         PrintF("break <address>\n");
@@ -539,11 +576,11 @@
         PrintF("    Stops are debug instructions inserted by\n");
         PrintF("    the Assembler::stop() function.\n");
         PrintF("    When hitting a stop, the Simulator will\n");
-        PrintF("    stop and and give control to the Debugger.\n");
+        PrintF("    stop and and give control to the ArmDebugger.\n");
         PrintF("    The first %d stop codes are watched:\n",
                Simulator::kNumOfWatchedStops);
         PrintF("    - They can be enabled / disabled: the Simulator\n");
-        PrintF("       will / won't stop when hitting them.\n");
+        PrintF("      will / won't stop when hitting them.\n");
         PrintF("    - The Simulator keeps track of how many times they \n");
         PrintF("      are met. (See the info command.) Going over a\n");
         PrintF("      disabled stop still increases its counter. \n");
@@ -593,7 +630,9 @@
 }
 
 
-void Simulator::FlushICache(void* start_addr, size_t size) {
+void Simulator::FlushICache(v8::internal::HashMap* i_cache,
+                            void* start_addr,
+                            size_t size) {
   intptr_t start = reinterpret_cast<intptr_t>(start_addr);
   int intra_line = (start & CachePage::kLineMask);
   start -= intra_line;
@@ -602,22 +641,22 @@
   int offset = (start & CachePage::kPageMask);
   while (!AllOnOnePage(start, size - 1)) {
     int bytes_to_flush = CachePage::kPageSize - offset;
-    FlushOnePage(start, bytes_to_flush);
+    FlushOnePage(i_cache, start, bytes_to_flush);
     start += bytes_to_flush;
     size -= bytes_to_flush;
     ASSERT_EQ(0, start & CachePage::kPageMask);
     offset = 0;
   }
   if (size != 0) {
-    FlushOnePage(start, size);
+    FlushOnePage(i_cache, start, size);
   }
 }
 
 
-CachePage* Simulator::GetCachePage(void* page) {
-  v8::internal::HashMap::Entry* entry = i_cache_->Lookup(page,
-                                                         ICacheHash(page),
-                                                         true);
+CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
+  v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
+                                                        ICacheHash(page),
+                                                        true);
   if (entry->value == NULL) {
     CachePage* new_page = new CachePage();
     entry->value = new_page;
@@ -627,25 +666,28 @@
 
 
 // Flush from start up to and not including start + size.
-void Simulator::FlushOnePage(intptr_t start, int size) {
+void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
+                             intptr_t start,
+                             int size) {
   ASSERT(size <= CachePage::kPageSize);
   ASSERT(AllOnOnePage(start, size - 1));
   ASSERT((start & CachePage::kLineMask) == 0);
   ASSERT((size & CachePage::kLineMask) == 0);
   void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
   int offset = (start & CachePage::kPageMask);
-  CachePage* cache_page = GetCachePage(page);
+  CachePage* cache_page = GetCachePage(i_cache, page);
   char* valid_bytemap = cache_page->ValidityByte(offset);
   memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
 }
 
 
-void Simulator::CheckICache(Instruction* instr) {
+void Simulator::CheckICache(v8::internal::HashMap* i_cache,
+                            Instruction* instr) {
   intptr_t address = reinterpret_cast<intptr_t>(instr);
   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
   int offset = (address & CachePage::kPageMask);
-  CachePage* cache_page = GetCachePage(page);
+  CachePage* cache_page = GetCachePage(i_cache, page);
   char* cache_valid_byte = cache_page->ValidityByte(offset);
   bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
   char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
@@ -662,27 +704,18 @@
 }
 
 
-// Create one simulator per thread and keep it in thread local storage.
-static v8::internal::Thread::LocalStorageKey simulator_key;
-
-
-bool Simulator::initialized_ = false;
-
-
 void Simulator::Initialize() {
-  if (initialized_) return;
-  simulator_key = v8::internal::Thread::CreateThreadLocalKey();
-  initialized_ = true;
+  if (Isolate::Current()->simulator_initialized()) return;
+  Isolate::Current()->set_simulator_initialized(true);
   ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference);
 }
 
 
-v8::internal::HashMap* Simulator::i_cache_ = NULL;
-
-
-Simulator::Simulator() {
+Simulator::Simulator() : isolate_(Isolate::Current()) {
+  i_cache_ = isolate_->simulator_i_cache();
   if (i_cache_ == NULL) {
     i_cache_ = new v8::internal::HashMap(&ICacheMatch);
+    isolate_->set_simulator_i_cache(i_cache_);
   }
   Initialize();
   // Setup simulator support first. Some of this information is needed to
@@ -748,11 +781,14 @@
       : external_function_(external_function),
         swi_instruction_(al | (0xf*B24) | kCallRtRedirected),
         type_(type),
-        next_(list_) {
-    Simulator::current()->
-        FlushICache(reinterpret_cast<void*>(&swi_instruction_),
-                      Instruction::kInstrSize);
-    list_ = this;
+        next_(NULL) {
+    Isolate* isolate = Isolate::Current();
+    next_ = isolate->simulator_redirection();
+    Simulator::current(isolate)->
+        FlushICache(isolate->simulator_i_cache(),
+                    reinterpret_cast<void*>(&swi_instruction_),
+                    Instruction::kInstrSize);
+    isolate->set_simulator_redirection(this);
   }
 
   void* address_of_swi_instruction() {
@@ -764,8 +800,9 @@
 
   static Redirection* Get(void* external_function,
                           ExternalReference::Type type) {
-    Redirection* current;
-    for (current = list_; current != NULL; current = current->next_) {
+    Isolate* isolate = Isolate::Current();
+    Redirection* current = isolate->simulator_redirection();
+    for (; current != NULL; current = current->next_) {
       if (current->external_function_ == external_function) return current;
     }
     return new Redirection(external_function, type);
@@ -783,13 +820,9 @@
   uint32_t swi_instruction_;
   ExternalReference::Type type_;
   Redirection* next_;
-  static Redirection* list_;
 };
 
 
-Redirection* Redirection::list_ = NULL;
-
-
 void* Simulator::RedirectExternalReference(void* external_function,
                                            ExternalReference::Type type) {
   Redirection* redirection = Redirection::Get(external_function, type);
@@ -798,14 +831,20 @@
 
 
 // Get the active Simulator for the current thread.
-Simulator* Simulator::current() {
-  Initialize();
-  Simulator* sim = reinterpret_cast<Simulator*>(
-      v8::internal::Thread::GetThreadLocal(simulator_key));
+Simulator* Simulator::current(Isolate* isolate) {
+  v8::internal::Isolate::PerIsolateThreadData* isolate_data =
+      Isolate::CurrentPerIsolateThreadData();
+  if (isolate_data == NULL) {
+    Isolate::EnterDefaultIsolate();
+    isolate_data = Isolate::CurrentPerIsolateThreadData();
+  }
+  ASSERT(isolate_data != NULL);
+
+  Simulator* sim = isolate_data->simulator();
   if (sim == NULL) {
-    // TODO(146): delete the simulator object when a thread goes away.
+    // TODO(146): delete the simulator object when a thread/isolate goes away.
     sim = new Simulator();
-    v8::internal::Thread::SetThreadLocal(simulator_key, sim);
+    isolate_data->set_simulator(sim);
   }
   return sim;
 }
@@ -1533,7 +1572,8 @@
                                         int32_t arg1,
                                         int32_t arg2,
                                         int32_t arg3,
-                                        int32_t arg4);
+                                        int32_t arg4,
+                                        int32_t arg5);
 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
                                          int32_t arg1,
                                          int32_t arg2,
@@ -1564,7 +1604,8 @@
       int32_t arg2 = get_register(r2);
       int32_t arg3 = get_register(r3);
       int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
-      int32_t arg4 = *stack_pointer;
+      int32_t arg4 = stack_pointer[0];
+      int32_t arg5 = stack_pointer[1];
       // This is dodgy but it works because the C entry stubs are never moved.
       // See comment in codegen-arm.cc and bug 1242173.
       int32_t saved_lr = get_register(lr);
@@ -1627,20 +1668,22 @@
             reinterpret_cast<SimulatorRuntimeCall>(external);
         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
           PrintF(
-              "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc",
+              "Call to host function at %p"
+              "args %08x, %08x, %08x, %08x, %08x, %08x",
               FUNCTION_ADDR(target),
               arg0,
               arg1,
               arg2,
               arg3,
-              arg4);
+              arg4,
+              arg5);
           if (!stack_aligned) {
             PrintF(" with unaligned stack %08x\n", get_register(sp));
           }
           PrintF("\n");
         }
         CHECK(stack_aligned);
-        int64_t result = target(arg0, arg1, arg2, arg3, arg4);
+        int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
         int32_t lo_res = static_cast<int32_t>(result);
         int32_t hi_res = static_cast<int32_t>(result >> 32);
         if (::v8::internal::FLAG_trace_sim) {
@@ -1654,7 +1697,7 @@
       break;
     }
     case kBreakpoint: {
-      Debugger dbg(this);
+      ArmDebugger dbg(this);
       dbg.Debug();
       break;
     }
@@ -1668,7 +1711,7 @@
         // Stop if it is enabled, otherwise go on jumping over the stop
         // and the message address.
         if (isEnabledStop(code)) {
-          Debugger dbg(this);
+          ArmDebugger dbg(this);
           dbg.Stop(instr);
         } else {
           set_pc(get_pc() + 2 * Instruction::kInstrSize);
@@ -1976,7 +2019,7 @@
           break;
         }
         case BKPT: {
-          Debugger dbg(this);
+          ArmDebugger dbg(this);
           PrintF("Simulator hit BKPT.\n");
           dbg.Debug();
           break;
@@ -2467,6 +2510,8 @@
 // vmov :Rt = Sn
 // vcvt: Dd = Sm
 // vcvt: Sd = Dm
+// Dd = vabs(Dm)
+// Dd = vneg(Dm)
 // Dd = vadd(Dn, Dm)
 // Dd = vsub(Dn, Dm)
 // Dd = vmul(Dn, Dm)
@@ -2502,6 +2547,11 @@
         double dm_value = get_double_from_d_register(vm);
         double dd_value = fabs(dm_value);
         set_d_register_from_double(vd, dd_value);
+      } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
+        // vneg
+        double dm_value = get_double_from_d_register(vm);
+        double dd_value = -dm_value;
+        set_d_register_from_double(vd, dd_value);
       } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
         DecodeVCVTBetweenDoubleAndSingle(instr);
       } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
@@ -2957,7 +3007,7 @@
 // Executes the current instruction.
 void Simulator::InstructionDecode(Instruction* instr) {
   if (v8::internal::FLAG_check_icache) {
-    CheckICache(instr);
+    CheckICache(isolate_->simulator_i_cache(), instr);
   }
   pc_modified_ = false;
   if (::v8::internal::FLAG_trace_sim) {
@@ -3040,7 +3090,7 @@
       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
       icount_++;
       if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
-        Debugger dbg(this);
+        ArmDebugger dbg(this);
         dbg.Debug();
       } else {
         InstructionDecode(instr);
diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h
index bdf1f8a..b7b1b68 100644
--- a/src/arm/simulator-arm.h
+++ b/src/arm/simulator-arm.h
@@ -49,18 +49,19 @@
   (entry(p0, p1, p2, p3, p4))
 
 typedef int (*arm_regexp_matcher)(String*, int, const byte*, const byte*,
-                                  void*, int*, Address, int);
+                                  void*, int*, Address, int, Isolate*);
 
 
 // Call the generated regexp code directly. The code at the entry address
 // should act as a function matching the type arm_regexp_matcher.
 // The fifth argument is a dummy that reserves the space used for
 // the return address added by the ExitFrame in native calls.
-#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
-  (FUNCTION_CAST<arm_regexp_matcher>(entry)(p0, p1, p2, p3, NULL, p4, p5, p6))
+#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
+  (FUNCTION_CAST<arm_regexp_matcher>(entry)(                              \
+      p0, p1, p2, p3, NULL, p4, p5, p6, p7))
 
 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
-  (reinterpret_cast<TryCatch*>(try_catch_address))
+  reinterpret_cast<TryCatch*>(try_catch_address)
 
 // The stack limit beyond which we will throw stack overflow errors in
 // generated code. Because generated code on arm uses the C stack, we
@@ -123,7 +124,7 @@
 
 class Simulator {
  public:
-  friend class Debugger;
+  friend class ArmDebugger;
   enum Register {
     no_reg = -1,
     r0 = 0, r1, r2, r3, r4, r5, r6, r7,
@@ -147,7 +148,7 @@
 
   // The currently executing Simulator instance. Potentially there can be one
   // for each native thread.
-  static Simulator* current();
+  static Simulator* current(v8::internal::Isolate* isolate);
 
   // Accessors for register state. Reading the pc value adheres to the ARM
   // architecture specification and is off by a 8 from the currently executing
@@ -191,7 +192,8 @@
   uintptr_t PopAddress();
 
   // ICache checking.
-  static void FlushICache(void* start, size_t size);
+  static void FlushICache(v8::internal::HashMap* i_cache, void* start,
+                          size_t size);
 
   // Returns true if pc register contains one of the 'special_values' defined
   // below (bad_lr, end_sim_pc).
@@ -287,9 +289,10 @@
   void InstructionDecode(Instruction* instr);
 
   // ICache.
-  static void CheckICache(Instruction* instr);
-  static void FlushOnePage(intptr_t start, int size);
-  static CachePage* GetCachePage(void* page);
+  static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
+  static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
+                           int size);
+  static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
 
   // Runtime call support.
   static void* RedirectExternalReference(
@@ -333,15 +336,16 @@
   char* stack_;
   bool pc_modified_;
   int icount_;
-  static bool initialized_;
 
   // Icache simulation
-  static v8::internal::HashMap* i_cache_;
+  v8::internal::HashMap* i_cache_;
 
   // Registered breakpoints.
   Instruction* break_pc_;
   Instr break_instr_;
 
+  v8::internal::Isolate* isolate_;
+
   // A stop is watched if its code is less than kNumOfWatchedStops.
   // Only watched stops support enabling/disabling and the counter feature.
   static const uint32_t kNumOfWatchedStops = 256;
@@ -364,15 +368,16 @@
 // When running with the simulator transition into simulated execution at this
 // point.
 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
-  reinterpret_cast<Object*>(Simulator::current()->Call( \
+  reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->Call( \
       FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4))
 
-#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
-  Simulator::current()->Call(entry, 8, p0, p1, p2, p3, NULL, p4, p5, p6)
+#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
+  Simulator::current(Isolate::Current())->Call( \
+      entry, 9, p0, p1, p2, p3, NULL, p4, p5, p6, p7)
 
-#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
-  try_catch_address == \
-      NULL ? NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
+#define TRY_CATCH_FROM_ADDRESS(try_catch_address)                              \
+  try_catch_address == NULL ?                                                  \
+      NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
 
 
 // The simulator has its own stack. Thus it has a different stack limit from
@@ -383,16 +388,16 @@
 class SimulatorStack : public v8::internal::AllStatic {
  public:
   static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) {
-    return Simulator::current()->StackLimit();
+    return Simulator::current(Isolate::Current())->StackLimit();
   }
 
   static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
-    Simulator* sim = Simulator::current();
+    Simulator* sim = Simulator::current(Isolate::Current());
     return sim->PushAddress(try_catch_address);
   }
 
   static inline void UnregisterCTryCatch() {
-    Simulator::current()->PopAddress();
+    Simulator::current(Isolate::Current())->PopAddress();
   }
 };
 
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 60a11f3..9936ac0 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -39,15 +39,16 @@
 #define __ ACCESS_MASM(masm)
 
 
-static void ProbeTable(MacroAssembler* masm,
+static void ProbeTable(Isolate* isolate,
+                       MacroAssembler* masm,
                        Code::Flags flags,
                        StubCache::Table table,
                        Register name,
                        Register offset,
                        Register scratch,
                        Register scratch2) {
-  ExternalReference key_offset(SCTableReference::keyReference(table));
-  ExternalReference value_offset(SCTableReference::valueReference(table));
+  ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
+  ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
 
   uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address());
   uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address());
@@ -101,8 +102,9 @@
                                              Register scratch0,
                                              Register scratch1) {
   ASSERT(name->IsSymbol());
-  __ IncrementCounter(&Counters::negative_lookups, 1, scratch0, scratch1);
-  __ IncrementCounter(&Counters::negative_lookups_miss, 1, scratch0, scratch1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
+  __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
 
   Label done;
 
@@ -198,7 +200,7 @@
     }
   }
   __ bind(&done);
-  __ DecrementCounter(&Counters::negative_lookups_miss, 1, scratch0, scratch1);
+  __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
 }
 
 
@@ -209,6 +211,7 @@
                               Register scratch,
                               Register extra,
                               Register extra2) {
+  Isolate* isolate = masm->isolate();
   Label miss;
 
   // Make sure that code is valid. The shifting code relies on the
@@ -248,7 +251,7 @@
           Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize));
 
   // Probe the primary table.
-  ProbeTable(masm, flags, kPrimary, name, scratch, extra, extra2);
+  ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra, extra2);
 
   // Primary miss: Compute hash for secondary probe.
   __ sub(scratch, scratch, Operand(name));
@@ -258,7 +261,7 @@
           Operand((kSecondaryTableSize - 1) << kHeapObjectTagSize));
 
   // Probe the secondary table.
-  ProbeTable(masm, flags, kSecondary, name, scratch, extra, extra2);
+  ProbeTable(isolate, masm, flags, kSecondary, name, scratch, extra, extra2);
 
   // Cache miss: Fall-through and let caller handle the miss by
   // entering the runtime system.
@@ -286,13 +289,15 @@
 
 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
     MacroAssembler* masm, int index, Register prototype, Label* miss) {
+  Isolate* isolate = masm->isolate();
   // Check we're still in the same context.
   __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
-  __ Move(ip, Top::global());
+  __ Move(ip, isolate->global());
   __ cmp(prototype, ip);
   __ b(ne, miss);
   // Get the global function with the given index.
-  JSFunction* function = JSFunction::cast(Top::global_context()->get(index));
+  JSFunction* function =
+      JSFunction::cast(isolate->global_context()->get(index));
   // Load its initial map. The global functions all have initial maps.
   __ Move(prototype, Handle<Map>(function->initial_map()));
   // Load the prototype from the initial map.
@@ -450,8 +455,10 @@
     __ mov(r2, Operand(Handle<Map>(transition)));
     __ Push(r2, r0);
     __ TailCallExternalReference(
-           ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage)),
-           3, 1);
+        ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
+                          masm->isolate()),
+        3,
+        1);
     return;
   }
 
@@ -505,9 +512,9 @@
   ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
   Code* code = NULL;
   if (kind == Code::LOAD_IC) {
-    code = Builtins::builtin(Builtins::LoadIC_Miss);
+    code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss);
   } else {
-    code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
+    code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss);
   }
 
   Handle<Code> ic(code);
@@ -548,7 +555,7 @@
                                      JSObject* holder_obj) {
   __ push(name);
   InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
-  ASSERT(!Heap::InNewSpace(interceptor));
+  ASSERT(!masm->isolate()->heap()->InNewSpace(interceptor));
   Register scratch = name;
   __ mov(scratch, Operand(Handle<Object>(interceptor)));
   __ push(scratch);
@@ -567,7 +574,8 @@
   PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
 
   ExternalReference ref =
-      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly));
+      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
+                        masm->isolate());
   __ mov(r0, Operand(5));
   __ mov(r1, Operand(ref));
 
@@ -616,7 +624,7 @@
   // Pass the additional arguments FastHandleApiCall expects.
   Object* call_data = optimization.api_call_info()->data();
   Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info());
-  if (Heap::InNewSpace(call_data)) {
+  if (masm->isolate()->heap()->InNewSpace(call_data)) {
     __ Move(r0, api_call_info_handle);
     __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset));
   } else {
@@ -656,8 +664,9 @@
   // garbage collection but instead return the allocation failure
   // object.
   const int kStackUnwindSpace = argc + kFastApiCallArguments + 1;
-  ExternalReference ref =
-      ExternalReference(&fun, ExternalReference::DIRECT_API_CALL);
+  ExternalReference ref = ExternalReference(&fun,
+                                            ExternalReference::DIRECT_API_CALL,
+                                            masm->isolate());
   return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace);
 }
 
@@ -710,7 +719,7 @@
                      name,
                      holder,
                      miss);
-      return Heap::undefined_value();
+      return masm->isolate()->heap()->undefined_value();
     }
   }
 
@@ -729,6 +738,8 @@
     ASSERT(optimization.is_constant_call());
     ASSERT(!lookup->holder()->IsGlobalObject());
 
+    Counters* counters = masm->isolate()->counters();
+
     int depth1 = kInvalidProtoDepth;
     int depth2 = kInvalidProtoDepth;
     bool can_do_fast_api_call = false;
@@ -746,11 +757,11 @@
                             (depth2 != kInvalidProtoDepth);
     }
 
-    __ IncrementCounter(&Counters::call_const_interceptor, 1,
+    __ IncrementCounter(counters->call_const_interceptor(), 1,
                       scratch1, scratch2);
 
     if (can_do_fast_api_call) {
-      __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1,
+      __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1,
                           scratch1, scratch2);
       ReserveSpaceForFastApiCall(masm, scratch1);
     }
@@ -811,7 +822,7 @@
       FreeSpaceForFastApiCall(masm);
     }
 
-    return Heap::undefined_value();
+    return masm->isolate()->heap()->undefined_value();
   }
 
   void CompileRegular(MacroAssembler* masm,
@@ -840,9 +851,9 @@
                              interceptor_holder);
 
     __ CallExternalReference(
-          ExternalReference(
-              IC_Utility(IC::kLoadPropertyWithInterceptorForCall)),
-          5);
+        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
+                          masm->isolate()),
+        5);
 
     // Restore the name_ register.
     __ pop(name_);
@@ -942,7 +953,7 @@
                             Register fval,
                             Register scratch1,
                             Register scratch2) {
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (masm->isolate()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
     __ vmov(s0, ival);
     __ add(scratch1, dst, Operand(wordoffset, LSL, 2));
@@ -1080,7 +1091,7 @@
         !current->IsJSGlobalObject() &&
         !current->IsJSGlobalProxy()) {
       if (!name->IsSymbol()) {
-        MaybeObject* maybe_lookup_result = Heap::LookupSymbol(name);
+        MaybeObject* maybe_lookup_result = heap()->LookupSymbol(name);
         Object* lookup_result = NULL;  // Initialization to please compiler.
         if (!maybe_lookup_result->ToObject(&lookup_result)) {
           set_failure(Failure::cast(maybe_lookup_result));
@@ -1100,7 +1111,7 @@
       __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
       reg = holder_reg;  // from now the object is in holder_reg
       __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
-    } else if (Heap::InNewSpace(prototype)) {
+    } else if (heap()->InNewSpace(prototype)) {
       // Get the map of the current object.
       __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
       __ cmp(scratch1, Operand(Handle<Map>(current->map())));
@@ -1154,7 +1165,7 @@
   __ b(ne, miss);
 
   // Log the check depth.
-  LOG(IntEvent("check-maps-depth", depth + 1));
+  LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1));
 
   // Perform security check for access to the global object.
   ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
@@ -1248,7 +1259,7 @@
   __ push(receiver);
   __ mov(scratch2, sp);  // scratch2 = AccessorInfo::args_
   Handle<AccessorInfo> callback_handle(callback);
-  if (Heap::InNewSpace(callback_handle->data())) {
+  if (heap()->InNewSpace(callback_handle->data())) {
     __ Move(scratch3, callback_handle);
     __ ldr(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset));
   } else {
@@ -1273,7 +1284,9 @@
   // object.
   const int kStackUnwindSpace = 4;
   ExternalReference ref =
-      ExternalReference(&fun, ExternalReference::DIRECT_GETTER_CALL);
+      ExternalReference(&fun,
+                        ExternalReference::DIRECT_GETTER_CALL,
+                        masm()->isolate());
   return masm()->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace);
 }
 
@@ -1402,7 +1415,8 @@
       }
 
       ExternalReference ref =
-          ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
+          ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
+                            masm()->isolate());
       __ TailCallExternalReference(ref, 5, 1);
     }
   } else {  // !compile_followup_inline
@@ -1414,8 +1428,9 @@
     PushInterceptorArguments(masm(), receiver, holder_reg,
                              name_reg, interceptor_holder);
 
-    ExternalReference ref = ExternalReference(
-        IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
+    ExternalReference ref =
+        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
+                          masm()->isolate());
     __ TailCallExternalReference(ref, 5, 1);
   }
 }
@@ -1462,7 +1477,7 @@
   __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
 
   // Check that the cell contains the same function.
-  if (Heap::InNewSpace(function)) {
+  if (heap()->InNewSpace(function)) {
     // We can't embed a pointer to a function in new space so we have
     // to verify that the shared function info is unchanged. This has
     // the nice side effect that multiple closures based on the same
@@ -1486,8 +1501,8 @@
 
 
 MaybeObject* CallStubCompiler::GenerateMissBranch() {
-  MaybeObject* maybe_obj = StubCache::ComputeCallMiss(arguments().immediate(),
-                                                      kind_);
+  MaybeObject* maybe_obj = masm()->isolate()->stub_cache()->ComputeCallMiss(
+      arguments().immediate(), kind_);
   Object* obj;
   if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
@@ -1523,10 +1538,8 @@
 
   // Handle call cache miss.
   __ bind(&miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(FIELD, name);
@@ -1547,7 +1560,7 @@
   // -----------------------------------
 
   // If object is not an array, bail out to regular call.
-  if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value();
+  if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value();
 
   Label miss;
 
@@ -1633,10 +1646,11 @@
         __ b(&call_builtin);
       }
 
+      Isolate* isolate = masm()->isolate();
       ExternalReference new_space_allocation_top =
-          ExternalReference::new_space_allocation_top_address();
+          ExternalReference::new_space_allocation_top_address(isolate);
       ExternalReference new_space_allocation_limit =
-          ExternalReference::new_space_allocation_limit_address();
+          ExternalReference::new_space_allocation_limit_address(isolate);
 
       const int kAllocationDelta = 4;
       // Load top and check if it is the end of elements.
@@ -1676,17 +1690,16 @@
       __ Ret();
     }
     __ bind(&call_builtin);
-    __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
+    __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush,
+                                                   masm()->isolate()),
                                  argc + 1,
                                  1);
   }
 
   // Handle call cache miss.
   __ bind(&miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(function);
@@ -1707,7 +1720,7 @@
   // -----------------------------------
 
   // If object is not an array, bail out to regular call.
-  if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value();
+  if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value();
 
   Label miss, return_undefined, call_builtin;
 
@@ -1763,16 +1776,15 @@
   __ Ret();
 
   __ bind(&call_builtin);
-  __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop),
+  __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop,
+                                                 masm()->isolate()),
                                argc + 1,
                                1);
 
   // Handle call cache miss.
   __ bind(&miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(function);
@@ -1794,7 +1806,7 @@
   // -----------------------------------
 
   // If object is not a string, bail out to regular call.
-  if (!object->IsString() || cell != NULL) return Heap::undefined_value();
+  if (!object->IsString() || cell != NULL) return heap()->undefined_value();
 
   const int argc = arguments().immediate();
 
@@ -1855,10 +1867,8 @@
   // Restore function name in r2.
   __ Move(r2, Handle<String>(name));
   __ bind(&name_miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(function);
@@ -1880,7 +1890,7 @@
   // -----------------------------------
 
   // If object is not a string, bail out to regular call.
-  if (!object->IsString() || cell != NULL) return Heap::undefined_value();
+  if (!object->IsString() || cell != NULL) return heap()->undefined_value();
 
   const int argc = arguments().immediate();
 
@@ -1943,10 +1953,8 @@
   // Restore function name in r2.
   __ Move(r2, Handle<String>(name));
   __ bind(&name_miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(function);
@@ -1971,7 +1979,7 @@
 
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
-  if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
+  if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
 
   Label miss;
   GenerateNameCheck(name, &miss);
@@ -2019,10 +2027,8 @@
 
   __ bind(&miss);
   // r2: function name.
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
@@ -2042,14 +2048,17 @@
   //  -- sp[argc * 4]           : receiver
   // -----------------------------------
 
-  if (!CpuFeatures::IsSupported(VFP3)) return Heap::undefined_value();
+  if (!masm()->isolate()->cpu_features()->IsSupported(VFP3)) {
+      return heap()->undefined_value();
+  }
+
   CpuFeatures::Scope scope_vfp3(VFP3);
 
   const int argc = arguments().immediate();
 
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
-  if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
+  if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
 
   Label miss, slow;
   GenerateNameCheck(name, &miss);
@@ -2166,8 +2175,8 @@
 
   __ bind(&miss);
   // r2: function name.
-  MaybeObject* obj = GenerateMissBranch();
-  if (obj->IsFailure()) return obj;
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
@@ -2191,7 +2200,7 @@
 
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
-  if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
+  if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
 
   Label miss;
   GenerateNameCheck(name, &miss);
@@ -2268,16 +2277,68 @@
 
   __ bind(&miss);
   // r2: function name.
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
 }
 
 
+MaybeObject* CallStubCompiler::CompileFastApiCall(
+    const CallOptimization& optimization,
+    Object* object,
+    JSObject* holder,
+    JSGlobalPropertyCell* cell,
+    JSFunction* function,
+    String* name) {
+  Counters* counters = isolate()->counters();
+
+  ASSERT(optimization.is_simple_api_call());
+  // Bail out if object is a global object as we don't want to
+  // repatch it to global receiver.
+  if (object->IsGlobalObject()) return heap()->undefined_value();
+  if (cell != NULL) return heap()->undefined_value();
+  int depth = optimization.GetPrototypeDepthOfExpectedType(
+            JSObject::cast(object), holder);
+  if (depth == kInvalidProtoDepth) return heap()->undefined_value();
+
+  Label miss, miss_before_stack_reserved;
+
+  GenerateNameCheck(name, &miss_before_stack_reserved);
+
+  // 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.
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(eq, &miss_before_stack_reserved);
+
+  __ IncrementCounter(counters->call_const(), 1, r0, r3);
+  __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3);
+
+  ReserveSpaceForFastApiCall(masm(), r0);
+
+  // Check that the maps haven't changed and find a Holder as a side effect.
+  CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name,
+                  depth, &miss);
+
+  MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc);
+  if (result->IsFailure()) return result;
+
+  __ bind(&miss);
+  FreeSpaceForFastApiCall(masm());
+
+  __ bind(&miss_before_stack_reserved);
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
+
+  // Return the generated code.
+  return GetCode(function);
+}
+
+
 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
                                                    JSObject* holder,
                                                    JSFunction* function,
@@ -2287,22 +2348,18 @@
   //  -- r2    : name
   //  -- lr    : return address
   // -----------------------------------
-  SharedFunctionInfo* function_info = function->shared();
-  if (function_info->HasBuiltinFunctionId()) {
-    BuiltinFunctionId id = function_info->builtin_function_id();
+  if (HasCustomCallGenerator(function)) {
     MaybeObject* maybe_result = CompileCustomCall(
-        id, object, holder, NULL, function, name);
+        object, holder, NULL, function, name);
     Object* result;
     if (!maybe_result->ToObject(&result)) return maybe_result;
     // undefined means bail out to regular compiler.
-    if (!result->IsUndefined()) {
-      return result;
-    }
+    if (!result->IsUndefined()) return result;
   }
 
-  Label miss_in_smi_check;
+  Label miss;
 
-  GenerateNameCheck(name, &miss_in_smi_check);
+  GenerateNameCheck(name, &miss);
 
   // Get the receiver from the stack
   const int argc = arguments().immediate();
@@ -2311,39 +2368,26 @@
   // Check that the receiver isn't a smi.
   if (check != NUMBER_CHECK) {
     __ tst(r1, Operand(kSmiTagMask));
-    __ b(eq, &miss_in_smi_check);
+    __ 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);
 
-  CallOptimization optimization(function);
-  int depth = kInvalidProtoDepth;
-  Label miss;
-
+  SharedFunctionInfo* function_info = function->shared();
   switch (check) {
     case RECEIVER_MAP_CHECK:
-      __ IncrementCounter(&Counters::call_const, 1, r0, r3);
-
-      if (optimization.is_simple_api_call() && !object->IsGlobalObject()) {
-        depth = optimization.GetPrototypeDepthOfExpectedType(
-            JSObject::cast(object), holder);
-      }
-
-      if (depth != kInvalidProtoDepth) {
-        __ IncrementCounter(&Counters::call_const_fast_api, 1, r0, r3);
-        ReserveSpaceForFastApiCall(masm(), r0);
-      }
+      __ IncrementCounter(masm()->isolate()->counters()->call_const(),
+                          1, r0, r3);
 
       // Check that the maps haven't changed.
       CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name,
-                      depth, &miss);
+                      &miss);
 
       // Patch the receiver on the stack with the global proxy if
       // necessary.
       if (object->IsGlobalObject()) {
-        ASSERT(depth == kInvalidProtoDepth);
         __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
         __ str(r3, MemOperand(sp, argc * kPointerSize));
       }
@@ -2416,24 +2460,12 @@
       UNREACHABLE();
   }
 
-  if (depth != kInvalidProtoDepth) {
-    MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc);
-    if (result->IsFailure()) return result;
-  } else {
-    __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
-  }
+  __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
 
   // Handle call cache miss.
   __ bind(&miss);
-  if (depth != kInvalidProtoDepth) {
-    FreeSpaceForFastApiCall(masm());
-  }
-
-  __ bind(&miss_in_smi_check);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(function);
@@ -2485,10 +2517,8 @@
 
   // Handle call cache miss.
   __ bind(&miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(INTERCEPTOR, name);
@@ -2505,11 +2535,9 @@
   //  -- lr    : return address
   // -----------------------------------
 
-  SharedFunctionInfo* function_info = function->shared();
-  if (function_info->HasBuiltinFunctionId()) {
-    BuiltinFunctionId id = function_info->builtin_function_id();
+  if (HasCustomCallGenerator(function)) {
     MaybeObject* maybe_result = CompileCustomCall(
-        id, object, holder, cell, function, name);
+        object, holder, cell, function, name);
     Object* result;
     if (!maybe_result->ToObject(&result)) return maybe_result;
     // undefined means bail out to regular compiler.
@@ -2538,7 +2566,8 @@
   __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
 
   // Jump to the cached code (tail call).
-  __ IncrementCounter(&Counters::call_global_inline, 1, r3, r4);
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->call_global_inline(), 1, r3, r4);
   ASSERT(function->is_compiled());
   Handle<Code> code(function->code());
   ParameterCount expected(function->shared()->formal_parameter_count());
@@ -2555,11 +2584,9 @@
 
   // Handle call cache miss.
   __ bind(&miss);
-  __ IncrementCounter(&Counters::call_global_inline_miss, 1, r1, r3);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  __ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3);
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(NORMAL, name);
@@ -2585,7 +2612,7 @@
                      r1, r2, r3,
                      &miss);
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2628,12 +2655,13 @@
 
   // Do tail-call to the runtime system.
   ExternalReference store_callback_property =
-      ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
+      ExternalReference(IC_Utility(IC::kStoreCallbackProperty),
+                        masm()->isolate());
   __ TailCallExternalReference(store_callback_property, 4, 1);
 
   // Handle store cache miss.
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2676,12 +2704,13 @@
 
   // Do tail-call to the runtime system.
   ExternalReference store_ic_property =
-      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
+      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty),
+                        masm()->isolate());
   __ TailCallExternalReference(store_ic_property, 4, 1);
 
   // Handle store cache miss.
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2718,13 +2747,14 @@
   // Store the value in the cell.
   __ str(r0, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset));
 
-  __ IncrementCounter(&Counters::named_store_global_inline, 1, r4, r3);
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->named_store_global_inline(), 1, r4, r3);
   __ Ret();
 
   // Handle store cache miss.
   __ bind(&miss);
-  __ IncrementCounter(&Counters::named_store_global_inline_miss, 1, r4, r3);
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  __ IncrementCounter(counters->named_store_global_inline_miss(), 1, r4, r3);
+  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2771,7 +2801,7 @@
   GenerateLoadMiss(masm(), Code::LOAD_IC);
 
   // Return the generated code.
-  return GetCode(NONEXISTENT, Heap::empty_string());
+  return GetCode(NONEXISTENT, heap()->empty_string());
 }
 
 
@@ -2906,11 +2936,12 @@
   }
 
   __ mov(r0, r4);
-  __ IncrementCounter(&Counters::named_load_global_stub, 1, r1, r3);
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3);
   __ Ret();
 
   __ bind(&miss);
-  __ IncrementCounter(&Counters::named_load_global_stub_miss, 1, r1, r3);
+  __ IncrementCounter(counters->named_load_global_stub_miss(), 1, r1, r3);
   GenerateLoadMiss(masm(), Code::LOAD_IC);
 
   // Return the generated code.
@@ -3055,7 +3086,9 @@
   //  -- r1    : receiver
   // -----------------------------------
   Label miss;
-  __ IncrementCounter(&Counters::keyed_load_string_length, 1, r2, r3);
+
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_string_length(), 1, r2, r3);
 
   // Check the key is the cached one.
   __ cmp(r0, Operand(Handle<String>(name)));
@@ -3063,7 +3096,7 @@
 
   GenerateLoadStringLength(masm(), r1, r2, r3, &miss, true);
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_string_length, 1, r2, r3);
+  __ DecrementCounter(counters->keyed_load_string_length(), 1, r2, r3);
 
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
@@ -3079,7 +3112,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_load_function_prototype, 1, r2, r3);
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3);
 
   // Check the name hasn't changed.
   __ cmp(r0, Operand(Handle<String>(name)));
@@ -3087,7 +3121,7 @@
 
   GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss);
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_function_prototype, 1, r2, r3);
+  __ DecrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   return GetCode(CALLBACKS, name);
@@ -3143,38 +3177,6 @@
 }
 
 
-MaybeObject* KeyedLoadStubCompiler::CompileLoadPixelArray(JSObject* receiver) {
-  // ----------- S t a t e -------------
-  //  -- lr    : return address
-  //  -- r0    : key
-  //  -- r1    : receiver
-  // -----------------------------------
-  Label miss;
-
-  // Check that the map matches.
-  __ CheckMap(r1, r2, Handle<Map>(receiver->map()), &miss, false);
-
-  GenerateFastPixelArrayLoad(masm(),
-                             r1,
-                             r0,
-                             r2,
-                             r3,
-                             r4,
-                             r5,
-                             r0,
-                             &miss,
-                             &miss,
-                             &miss);
-
-  __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
-
-  // Return the generated code.
-  return GetCode(NORMAL, NULL);
-}
-
-
 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
                                                        int index,
                                                        Map* transition,
@@ -3187,7 +3189,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_store_field, 1, r3, r4);
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->keyed_store_field(), 1, r3, r4);
 
   // Check that the name has not changed.
   __ cmp(r1, Operand(Handle<String>(name)));
@@ -3203,9 +3206,8 @@
                      &miss);
   __ bind(&miss);
 
-  __ DecrementCounter(&Counters::keyed_store_field, 1, r3, r4);
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
-
+  __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4);
+  Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -3248,7 +3250,7 @@
   __ ldr(elements_reg,
          FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
   __ ldr(scratch, FieldMemOperand(elements_reg, HeapObject::kMapOffset));
-  __ cmp(scratch, Operand(Handle<Map>(Factory::fixed_array_map())));
+  __ cmp(scratch, Operand(Handle<Map>(factory()->fixed_array_map())));
   __ b(ne, &miss);
 
   // Check that the key is within bounds.
@@ -3275,48 +3277,7 @@
   __ Ret();
 
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
-
-  // Return the generated code.
-  return GetCode(NORMAL, NULL);
-}
-
-
-MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray(
-    JSObject* receiver) {
-  // ----------- S t a t e -------------
-  //  -- r0    : value
-  //  -- r1    : key
-  //  -- r2    : receiver
-  //  -- r3    : scratch
-  //  -- r4    : scratch
-  //  -- r5    : scratch
-  //  -- r6    : scratch
-  //  -- lr    : return address
-  // -----------------------------------
-  Label miss;
-
-  // Check that the map matches.
-  __ CheckMap(r2, r6, Handle<Map>(receiver->map()), &miss, false);
-
-  GenerateFastPixelArrayStore(masm(),
-                              r2,
-                              r1,
-                              r0,
-                              r3,
-                              r4,
-                              r5,
-                              r6,
-                              true,
-                              true,
-                              &miss,
-                              &miss,
-                              NULL,
-                              &miss);
-
-  __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
+  Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -3452,16 +3413,16 @@
   // Remove caller arguments and receiver from the stack and return.
   __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2));
   __ add(sp, sp, Operand(kPointerSize));
-  __ IncrementCounter(&Counters::constructed_objects, 1, r1, r2);
-  __ IncrementCounter(&Counters::constructed_objects_stub, 1, r1, r2);
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->constructed_objects(), 1, r1, r2);
+  __ IncrementCounter(counters->constructed_objects_stub(), 1, r1, r2);
   __ Jump(lr);
 
   // Jump to the generic stub in case the specialized code cannot handle the
   // construction.
   __ bind(&generic_stub_call);
-  Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
-  Handle<Code> generic_construct_stub(code);
-  __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
+  Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric();
+  __ Jump(code, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
   return GetCode();
@@ -3488,7 +3449,9 @@
 
 
 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
-    ExternalArrayType array_type, Code::Flags flags) {
+    JSObject* receiver_object,
+    ExternalArrayType array_type,
+    Code::Flags flags) {
   // ---------- S t a t e --------------
   //  -- lr     : return address
   //  -- r0     : key
@@ -3505,24 +3468,13 @@
   // Check that the key is a smi.
   __ JumpIfNotSmi(key, &slow);
 
-  // Check that the object is a JS object. Load map into r2.
-  __ CompareObjectType(receiver, r2, r3, FIRST_JS_OBJECT_TYPE);
-  __ b(lt, &slow);
-
-  // 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));
+  // Make sure that we've got the right map.
+  __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ cmp(r2, Operand(Handle<Map>(receiver_object->map())));
   __ b(ne, &slow);
 
-  // Check that the elements array is the appropriate type of
-  // ExternalArray.
   __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
-  __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
-  __ LoadRoot(ip, Heap::RootIndexForExternalArrayType(array_type));
-  __ cmp(r2, ip);
-  __ b(ne, &slow);
+  // r3: elements array
 
   // Check that the index is in range.
   __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
@@ -3530,7 +3482,6 @@
   // Unsigned comparison catches both negative and too-large values.
   __ b(lo, &slow);
 
-  // r3: elements array
   __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
   // r3: base pointer of external storage
 
@@ -3543,6 +3494,7 @@
     case kExternalByteArray:
       __ ldrsb(value, MemOperand(r3, key, LSR, 1));
       break;
+    case kExternalPixelArray:
     case kExternalUnsignedByteArray:
       __ ldrb(value, MemOperand(r3, key, LSR, 1));
       break;
@@ -3557,7 +3509,7 @@
       __ ldr(value, MemOperand(r3, key, LSL, 1));
       break;
     case kExternalFloatArray:
-      if (CpuFeatures::IsSupported(VFP3)) {
+      if (masm()->isolate()->cpu_features()->IsSupported(VFP3)) {
         CpuFeatures::Scope scope(VFP3);
         __ add(r2, r3, Operand(key, LSL, 1));
         __ vldr(s0, r2, 0);
@@ -3596,7 +3548,7 @@
     // Now we can use r0 for the result as key is not needed any more.
     __ mov(r0, r5);
 
-    if (CpuFeatures::IsSupported(VFP3)) {
+    if (masm()->isolate()->cpu_features()->IsSupported(VFP3)) {
       CpuFeatures::Scope scope(VFP3);
       __ vmov(s0, value);
       __ vcvt_f64_s32(d0, s0);
@@ -3611,7 +3563,7 @@
     // The test is different for unsigned int values. Since we need
     // the value to be in the range of a positive smi, we can't
     // handle either of the top two bits being set in the value.
-    if (CpuFeatures::IsSupported(VFP3)) {
+    if (masm()->isolate()->cpu_features()->IsSupported(VFP3)) {
       CpuFeatures::Scope scope(VFP3);
       Label box_int, done;
       __ tst(value, Operand(0xC0000000));
@@ -3675,7 +3627,7 @@
   } else if (array_type == kExternalFloatArray) {
     // For the floating-point array type, we need to always allocate a
     // HeapNumber.
-    if (CpuFeatures::IsSupported(VFP3)) {
+    if (masm()->isolate()->cpu_features()->IsSupported(VFP3)) {
       CpuFeatures::Scope scope(VFP3);
       // Allocate a HeapNumber for the result. Don't use r0 and r1 as
       // AllocateHeapNumber clobbers all registers - also when jumping due to
@@ -3751,7 +3703,9 @@
 
   // Slow case, key and receiver still in r0 and r1.
   __ bind(&slow);
-  __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1, r2, r3);
+  __ IncrementCounter(
+      masm()->isolate()->counters()->keyed_load_external_array_slow(),
+      1, r2, r3);
 
   // ---------- S t a t e --------------
   //  -- lr     : return address
@@ -3768,7 +3722,9 @@
 
 
 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
-    ExternalArrayType array_type, Code::Flags flags) {
+    JSObject* receiver_object,
+    ExternalArrayType array_type,
+    Code::Flags flags) {
   // ---------- S t a t e --------------
   //  -- r0     : value
   //  -- r1     : key
@@ -3786,28 +3742,18 @@
   // Check that the object isn't a smi.
   __ JumpIfSmi(receiver, &slow);
 
-  // Check that the object is a JS object. Load map into r3.
-  __ CompareObjectType(receiver, r3, r4, FIRST_JS_OBJECT_TYPE);
-  __ b(le, &slow);
-
-  // 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(r3, Map::kBitFieldOffset));
-  __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded));
+  // Make sure that we've got the right map.
+  __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ cmp(r3, Operand(Handle<Map>(receiver_object->map())));
   __ b(ne, &slow);
 
+  __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
+
   // Check that the key is a smi.
   __ JumpIfNotSmi(key, &slow);
 
-  // Check that the elements array is the appropriate type of ExternalArray.
-  __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
-  __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
-  __ LoadRoot(ip, Heap::RootIndexForExternalArrayType(array_type));
-  __ cmp(r4, ip);
-  __ b(ne, &slow);
-
-  // Check that the index is in range.
-  __ mov(r4, Operand(key, ASR, kSmiTagSize));  // Untag the index.
+  // Check that the index is in range
+  __ SmiUntag(r4, key);
   __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
   __ cmp(r4, ip);
   // Unsigned comparison catches both negative and too-large values.
@@ -3817,14 +3763,24 @@
   // runtime for all other kinds of values.
   // r3: external array.
   // r4: key (integer).
-  __ JumpIfNotSmi(value, &check_heap_number);
-  __ mov(r5, Operand(value, ASR, kSmiTagSize));  // Untag the value.
+  if (array_type == kExternalPixelArray) {
+    // Double to pixel conversion is only implemented in the runtime for now.
+    __ JumpIfNotSmi(value, &slow);
+  } else {
+    __ JumpIfNotSmi(value, &check_heap_number);
+  }
+  __ SmiUntag(r5, value);
   __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
 
   // r3: base pointer of external storage.
   // r4: key (integer).
   // r5: value (integer).
   switch (array_type) {
+    case kExternalPixelArray:
+      // Clamp the value to [0..255].
+      __ Usat(r5, 8, Operand(r5));
+      __ strb(r5, MemOperand(r3, r4, LSL, 0));
+      break;
     case kExternalByteArray:
     case kExternalUnsignedByteArray:
       __ strb(r5, MemOperand(r3, r4, LSL, 0));
@@ -3849,198 +3805,199 @@
   // Entry registers are intact, r0 holds the value which is the return value.
   __ Ret();
 
+  if (array_type != kExternalPixelArray) {
+    // r3: external array.
+    // r4: index (integer).
+    __ bind(&check_heap_number);
+    __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE);
+    __ b(ne, &slow);
 
-  // r3: external array.
-  // r4: index (integer).
-  __ bind(&check_heap_number);
-  __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE);
-  __ b(ne, &slow);
+    __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
 
-  __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
+    // r3: base pointer of external storage.
+    // r4: key (integer).
 
-  // r3: base pointer of external storage.
-  // r4: key (integer).
+    // The WebGL specification leaves the behavior of storing NaN and
+    // +/-Infinity into integer arrays basically undefined. For more
+    // reproducible behavior, convert these to zero.
+    if (masm()->isolate()->cpu_features()->IsSupported(VFP3)) {
+      CpuFeatures::Scope scope(VFP3);
 
-  // The WebGL specification leaves the behavior of storing NaN and
-  // +/-Infinity into integer arrays basically undefined. For more
-  // reproducible behavior, convert these to zero.
-  if (CpuFeatures::IsSupported(VFP3)) {
-    CpuFeatures::Scope scope(VFP3);
-
-
-    if (array_type == kExternalFloatArray) {
-      // vldr requires offset to be a multiple of 4 so we can not
-      // include -kHeapObjectTag into it.
-      __ sub(r5, r0, Operand(kHeapObjectTag));
-      __ vldr(d0, r5, HeapNumber::kValueOffset);
-      __ add(r5, r3, Operand(r4, LSL, 2));
-      __ vcvt_f32_f64(s0, d0);
-      __ vstr(s0, r5, 0);
-    } else {
-      // Need to perform float-to-int conversion.
-      // Test for NaN or infinity (both give zero).
-      __ ldr(r6, FieldMemOperand(value, HeapNumber::kExponentOffset));
-
-      // Hoisted load.  vldr requires offset to be a multiple of 4 so we can not
-      // include -kHeapObjectTag into it.
-      __ sub(r5, value, Operand(kHeapObjectTag));
-      __ vldr(d0, r5, HeapNumber::kValueOffset);
-
-      __ Sbfx(r6, r6, HeapNumber::kExponentShift, HeapNumber::kExponentBits);
-      // NaNs and Infinities have all-one exponents so they sign extend to -1.
-      __ cmp(r6, Operand(-1));
-      __ mov(r5, Operand(0), LeaveCC, eq);
-
-      // Not infinity or NaN simply convert to int.
-      if (IsElementTypeSigned(array_type)) {
-        __ vcvt_s32_f64(s0, d0, kDefaultRoundToZero, ne);
+      if (array_type == kExternalFloatArray) {
+        // vldr requires offset to be a multiple of 4 so we can not
+        // include -kHeapObjectTag into it.
+        __ sub(r5, r0, Operand(kHeapObjectTag));
+        __ vldr(d0, r5, HeapNumber::kValueOffset);
+        __ add(r5, r3, Operand(r4, LSL, 2));
+        __ vcvt_f32_f64(s0, d0);
+        __ vstr(s0, r5, 0);
       } else {
-        __ vcvt_u32_f64(s0, d0, kDefaultRoundToZero, ne);
+        // Need to perform float-to-int conversion.
+        // Test for NaN or infinity (both give zero).
+        __ ldr(r6, FieldMemOperand(value, HeapNumber::kExponentOffset));
+
+        // Hoisted load.  vldr requires offset to be a multiple of 4 so we can
+        // not include -kHeapObjectTag into it.
+        __ sub(r5, value, Operand(kHeapObjectTag));
+        __ vldr(d0, r5, HeapNumber::kValueOffset);
+
+        __ Sbfx(r6, r6, HeapNumber::kExponentShift, HeapNumber::kExponentBits);
+        // NaNs and Infinities have all-one exponents so they sign extend to -1.
+        __ cmp(r6, Operand(-1));
+        __ mov(r5, Operand(0), LeaveCC, eq);
+
+        // Not infinity or NaN simply convert to int.
+        if (IsElementTypeSigned(array_type)) {
+          __ vcvt_s32_f64(s0, d0, kDefaultRoundToZero, ne);
+        } else {
+          __ vcvt_u32_f64(s0, d0, kDefaultRoundToZero, ne);
+        }
+        __ vmov(r5, s0, ne);
+
+        switch (array_type) {
+          case kExternalByteArray:
+          case kExternalUnsignedByteArray:
+            __ strb(r5, MemOperand(r3, r4, LSL, 0));
+            break;
+          case kExternalShortArray:
+          case kExternalUnsignedShortArray:
+            __ strh(r5, MemOperand(r3, r4, LSL, 1));
+            break;
+          case kExternalIntArray:
+          case kExternalUnsignedIntArray:
+            __ str(r5, MemOperand(r3, r4, LSL, 2));
+            break;
+          default:
+            UNREACHABLE();
+            break;
+        }
       }
-      __ vmov(r5, s0, ne);
 
-      switch (array_type) {
-        case kExternalByteArray:
-        case kExternalUnsignedByteArray:
-          __ strb(r5, MemOperand(r3, r4, LSL, 0));
-          break;
-        case kExternalShortArray:
-        case kExternalUnsignedShortArray:
-          __ strh(r5, MemOperand(r3, r4, LSL, 1));
-          break;
-        case kExternalIntArray:
-        case kExternalUnsignedIntArray:
-          __ str(r5, MemOperand(r3, r4, LSL, 2));
-          break;
-        default:
-          UNREACHABLE();
-          break;
-      }
-    }
-
-    // Entry registers are intact, r0 holds the value which is the return value.
-    __ Ret();
-  } else {
-    // VFP3 is not available do manual conversions.
-    __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset));
-    __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset));
-
-    if (array_type == kExternalFloatArray) {
-      Label done, nan_or_infinity_or_zero;
-      static const int kMantissaInHiWordShift =
-          kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord;
-
-      static const int kMantissaInLoWordShift =
-          kBitsPerInt - kMantissaInHiWordShift;
-
-      // Test for all special exponent values: zeros, subnormal numbers, NaNs
-      // and infinities. All these should be converted to 0.
-      __ mov(r7, Operand(HeapNumber::kExponentMask));
-      __ and_(r9, r5, Operand(r7), SetCC);
-      __ b(eq, &nan_or_infinity_or_zero);
-
-      __ teq(r9, Operand(r7));
-      __ mov(r9, Operand(kBinary32ExponentMask), LeaveCC, eq);
-      __ b(eq, &nan_or_infinity_or_zero);
-
-      // Rebias exponent.
-      __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
-      __ add(r9,
-             r9,
-             Operand(kBinary32ExponentBias - HeapNumber::kExponentBias));
-
-      __ cmp(r9, Operand(kBinary32MaxExponent));
-      __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, gt);
-      __ orr(r5, r5, Operand(kBinary32ExponentMask), LeaveCC, gt);
-      __ b(gt, &done);
-
-      __ cmp(r9, Operand(kBinary32MinExponent));
-      __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, lt);
-      __ b(lt, &done);
-
-      __ and_(r7, r5, Operand(HeapNumber::kSignMask));
-      __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
-      __ orr(r7, r7, Operand(r5, LSL, kMantissaInHiWordShift));
-      __ orr(r7, r7, Operand(r6, LSR, kMantissaInLoWordShift));
-      __ orr(r5, r7, Operand(r9, LSL, kBinary32ExponentShift));
-
-      __ bind(&done);
-      __ str(r5, MemOperand(r3, r4, LSL, 2));
       // Entry registers are intact, r0 holds the value which is the return
       // value.
       __ Ret();
-
-      __ bind(&nan_or_infinity_or_zero);
-      __ and_(r7, r5, Operand(HeapNumber::kSignMask));
-      __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
-      __ orr(r9, r9, r7);
-      __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift));
-      __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift));
-      __ b(&done);
     } else {
-      bool is_signed_type = IsElementTypeSigned(array_type);
-      int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt;
-      int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000;
+      // VFP3 is not available do manual conversions.
+      __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset));
+      __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset));
 
-      Label done, sign;
+      if (array_type == kExternalFloatArray) {
+        Label done, nan_or_infinity_or_zero;
+        static const int kMantissaInHiWordShift =
+            kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord;
 
-      // Test for all special exponent values: zeros, subnormal numbers, NaNs
-      // and infinities. All these should be converted to 0.
-      __ mov(r7, Operand(HeapNumber::kExponentMask));
-      __ and_(r9, r5, Operand(r7), SetCC);
-      __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
-      __ b(eq, &done);
+        static const int kMantissaInLoWordShift =
+            kBitsPerInt - kMantissaInHiWordShift;
 
-      __ teq(r9, Operand(r7));
-      __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
-      __ b(eq, &done);
+        // Test for all special exponent values: zeros, subnormal numbers, NaNs
+        // and infinities. All these should be converted to 0.
+        __ mov(r7, Operand(HeapNumber::kExponentMask));
+        __ and_(r9, r5, Operand(r7), SetCC);
+        __ b(eq, &nan_or_infinity_or_zero);
 
-      // Unbias exponent.
-      __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
-      __ sub(r9, r9, Operand(HeapNumber::kExponentBias), SetCC);
-      // If exponent is negative then result is 0.
-      __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, mi);
-      __ b(mi, &done);
+        __ teq(r9, Operand(r7));
+        __ mov(r9, Operand(kBinary32ExponentMask), LeaveCC, eq);
+        __ b(eq, &nan_or_infinity_or_zero);
 
-      // If exponent is too big then result is minimal value.
-      __ cmp(r9, Operand(meaningfull_bits - 1));
-      __ mov(r5, Operand(min_value), LeaveCC, ge);
-      __ b(ge, &done);
+        // Rebias exponent.
+        __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
+        __ add(r9,
+               r9,
+               Operand(kBinary32ExponentBias - HeapNumber::kExponentBias));
 
-      __ and_(r7, r5, Operand(HeapNumber::kSignMask), SetCC);
-      __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
-      __ orr(r5, r5, Operand(1u << HeapNumber::kMantissaBitsInTopWord));
+        __ cmp(r9, Operand(kBinary32MaxExponent));
+        __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, gt);
+        __ orr(r5, r5, Operand(kBinary32ExponentMask), LeaveCC, gt);
+        __ b(gt, &done);
 
-      __ rsb(r9, r9, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC);
-      __ mov(r5, Operand(r5, LSR, r9), LeaveCC, pl);
-      __ b(pl, &sign);
+        __ cmp(r9, Operand(kBinary32MinExponent));
+        __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, lt);
+        __ b(lt, &done);
 
-      __ rsb(r9, r9, Operand(0, RelocInfo::NONE));
-      __ mov(r5, Operand(r5, LSL, r9));
-      __ rsb(r9, r9, Operand(meaningfull_bits));
-      __ orr(r5, r5, Operand(r6, LSR, r9));
+        __ and_(r7, r5, Operand(HeapNumber::kSignMask));
+        __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
+        __ orr(r7, r7, Operand(r5, LSL, kMantissaInHiWordShift));
+        __ orr(r7, r7, Operand(r6, LSR, kMantissaInLoWordShift));
+        __ orr(r5, r7, Operand(r9, LSL, kBinary32ExponentShift));
 
-      __ bind(&sign);
-      __ teq(r7, Operand(0, RelocInfo::NONE));
-      __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne);
+        __ bind(&done);
+        __ str(r5, MemOperand(r3, r4, LSL, 2));
+        // Entry registers are intact, r0 holds the value which is the return
+        // value.
+        __ Ret();
 
-      __ bind(&done);
-      switch (array_type) {
-        case kExternalByteArray:
-        case kExternalUnsignedByteArray:
-          __ strb(r5, MemOperand(r3, r4, LSL, 0));
-          break;
-        case kExternalShortArray:
-        case kExternalUnsignedShortArray:
-          __ strh(r5, MemOperand(r3, r4, LSL, 1));
-          break;
-        case kExternalIntArray:
-        case kExternalUnsignedIntArray:
-          __ str(r5, MemOperand(r3, r4, LSL, 2));
-          break;
-        default:
-          UNREACHABLE();
-          break;
+        __ bind(&nan_or_infinity_or_zero);
+        __ and_(r7, r5, Operand(HeapNumber::kSignMask));
+        __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
+        __ orr(r9, r9, r7);
+        __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift));
+        __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift));
+        __ b(&done);
+      } else {
+        bool is_signed_type = IsElementTypeSigned(array_type);
+        int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt;
+        int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000;
+
+        Label done, sign;
+
+        // Test for all special exponent values: zeros, subnormal numbers, NaNs
+        // and infinities. All these should be converted to 0.
+        __ mov(r7, Operand(HeapNumber::kExponentMask));
+        __ and_(r9, r5, Operand(r7), SetCC);
+        __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
+        __ b(eq, &done);
+
+        __ teq(r9, Operand(r7));
+        __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
+        __ b(eq, &done);
+
+        // Unbias exponent.
+        __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
+        __ sub(r9, r9, Operand(HeapNumber::kExponentBias), SetCC);
+        // If exponent is negative then result is 0.
+        __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, mi);
+        __ b(mi, &done);
+
+        // If exponent is too big then result is minimal value.
+        __ cmp(r9, Operand(meaningfull_bits - 1));
+        __ mov(r5, Operand(min_value), LeaveCC, ge);
+        __ b(ge, &done);
+
+        __ and_(r7, r5, Operand(HeapNumber::kSignMask), SetCC);
+        __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
+        __ orr(r5, r5, Operand(1u << HeapNumber::kMantissaBitsInTopWord));
+
+        __ rsb(r9, r9, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC);
+        __ mov(r5, Operand(r5, LSR, r9), LeaveCC, pl);
+        __ b(pl, &sign);
+
+        __ rsb(r9, r9, Operand(0, RelocInfo::NONE));
+        __ mov(r5, Operand(r5, LSL, r9));
+        __ rsb(r9, r9, Operand(meaningfull_bits));
+        __ orr(r5, r5, Operand(r6, LSR, r9));
+
+        __ bind(&sign);
+        __ teq(r7, Operand(0, RelocInfo::NONE));
+        __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne);
+
+        __ bind(&done);
+        switch (array_type) {
+          case kExternalByteArray:
+          case kExternalUnsignedByteArray:
+            __ strb(r5, MemOperand(r3, r4, LSL, 0));
+            break;
+          case kExternalShortArray:
+          case kExternalUnsignedShortArray:
+            __ strh(r5, MemOperand(r3, r4, LSL, 1));
+            break;
+          case kExternalIntArray:
+          case kExternalUnsignedIntArray:
+            __ str(r5, MemOperand(r3, r4, LSL, 2));
+            break;
+          default:
+            UNREACHABLE();
+            break;
+        }
       }
     }
   }
diff --git a/src/arm/virtual-frame-arm.cc b/src/arm/virtual-frame-arm.cc
index 544e405..a852d6e 100644
--- a/src/arm/virtual-frame-arm.cc
+++ b/src/arm/virtual-frame-arm.cc
@@ -288,7 +288,7 @@
 }
 
 
-void VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
+void VirtualFrame::CallRuntime(const Runtime::Function* f, int arg_count) {
   SpillAll();
   Forget(arg_count);
   ASSERT(cgen()->HasValidEntryRegisters());
@@ -321,7 +321,8 @@
 
 
 void VirtualFrame::CallLoadIC(Handle<String> name, RelocInfo::Mode mode) {
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      Builtins::kLoadIC_Initialize));
   PopToR0();
   SpillAll();
   __ mov(r2, Operand(name));
@@ -332,9 +333,9 @@
 void VirtualFrame::CallStoreIC(Handle<String> name,
                                bool is_contextual,
                                StrictModeFlag strict_mode) {
-  Handle<Code> ic(Builtins::builtin(
-      (strict_mode == kStrictMode) ? Builtins::StoreIC_Initialize_Strict
-                                   : Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      (strict_mode == kStrictMode) ? Builtins::kStoreIC_Initialize_Strict
+                                   : Builtins::kStoreIC_Initialize));
   PopToR0();
   RelocInfo::Mode mode;
   if (is_contextual) {
@@ -352,7 +353,8 @@
 
 
 void VirtualFrame::CallKeyedLoadIC() {
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      Builtins::kKeyedLoadIC_Initialize));
   PopToR1R0();
   SpillAll();
   CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
@@ -360,9 +362,9 @@
 
 
 void VirtualFrame::CallKeyedStoreIC(StrictModeFlag strict_mode) {
-  Handle<Code> ic(Builtins::builtin(
-      (strict_mode == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
-                                   : Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      (strict_mode == kStrictMode) ? Builtins::kKeyedStoreIC_Initialize_Strict
+                                   : Builtins::kKeyedStoreIC_Initialize));
   PopToR1R0();
   SpillAll();
   EmitPop(r2);
@@ -385,7 +387,8 @@
       ASSERT(dropped_args == 0);
       break;
     case Code::BUILTIN:
-      ASSERT(*code == Builtins::builtin(Builtins::JSConstructCall));
+      ASSERT(*code == Isolate::Current()->builtins()->builtin(
+          Builtins::kJSConstructCall));
       break;
     default:
       UNREACHABLE();
@@ -422,9 +425,6 @@
     { R0_TOS, R1_R0_TOS, R0_R1_TOS, R0_R1_TOS, R1_R0_TOS };
 
 
-bool VirtualFrame::SpilledScope::is_spilled_ = false;
-
-
 void VirtualFrame::Drop(int count) {
   ASSERT(count >= 0);
   ASSERT(height() >= count);
diff --git a/src/arm/virtual-frame-arm.h b/src/arm/virtual-frame-arm.h
index 76470bd..6d67e70 100644
--- a/src/arm/virtual-frame-arm.h
+++ b/src/arm/virtual-frame-arm.h
@@ -55,23 +55,26 @@
   class SpilledScope BASE_EMBEDDED {
    public:
     explicit SpilledScope(VirtualFrame* frame)
-      : old_is_spilled_(is_spilled_) {
+      : old_is_spilled_(
+          Isolate::Current()->is_virtual_frame_in_spilled_scope()) {
       if (frame != NULL) {
-        if (!is_spilled_) {
+        if (!old_is_spilled_) {
           frame->SpillAll();
         } else {
           frame->AssertIsSpilled();
         }
       }
-      is_spilled_ = true;
+      Isolate::Current()->set_is_virtual_frame_in_spilled_scope(true);
     }
     ~SpilledScope() {
-      is_spilled_ = old_is_spilled_;
+      Isolate::Current()->set_is_virtual_frame_in_spilled_scope(
+          old_is_spilled_);
     }
-    static bool is_spilled() { return is_spilled_; }
+    static bool is_spilled() {
+      return Isolate::Current()->is_virtual_frame_in_spilled_scope();
+    }
 
    private:
-    static bool is_spilled_;
     int old_is_spilled_;
 
     SpilledScope() { }
@@ -274,7 +277,7 @@
 
   // Call runtime given the number of arguments expected on (and
   // removed from) the stack.
-  void CallRuntime(Runtime::Function* f, int arg_count);
+  void CallRuntime(const Runtime::Function* f, int arg_count);
   void CallRuntime(Runtime::FunctionId id, int arg_count);
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
diff --git a/src/assembler.cc b/src/assembler.cc
index b0b44fd..0322747 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -55,6 +55,8 @@
 #include "x64/regexp-macro-assembler-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/regexp-macro-assembler-arm.h"
+#elif V8_TARGET_ARCH_MIPS
+#include "mips/regexp-macro-assembler-mips.h"
 #else  // Unknown architecture.
 #error "Unknown architecture."
 #endif  // Target architecture.
@@ -67,6 +69,7 @@
 const double DoubleConstant::min_int = kMinInt;
 const double DoubleConstant::one_half = 0.5;
 const double DoubleConstant::minus_zero = -0.0;
+const double DoubleConstant::nan = OS::nan_value();
 const double DoubleConstant::negative_infinity = -V8_INFINITY;
 const char* RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
 
@@ -139,6 +142,7 @@
 
 const int kSmallPCDeltaBits = kBitsPerByte - kTagBits;
 const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1;
+const int RelocInfo::kMaxSmallPCDelta = kSmallPCDeltaMask;
 
 const int kVariableLengthPCJumpTopTag = 1;
 const int kChunkBits = 7;
@@ -216,7 +220,6 @@
 #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.
@@ -525,7 +528,7 @@
       ASSERT(addr != NULL);
       // Check that we can find the right code object.
       Code* code = Code::GetCodeFromTargetAddress(addr);
-      Object* found = Heap::FindCodeObject(addr);
+      Object* found = HEAP->FindCodeObject(addr);
       ASSERT(found->IsCode());
       ASSERT(code->address() == HeapObject::cast(found)->address());
       break;
@@ -551,153 +554,184 @@
 // -----------------------------------------------------------------------------
 // Implementation of ExternalReference
 
-ExternalReference::ExternalReference(Builtins::CFunctionId id)
-  : address_(Redirect(Builtins::c_function_address(id))) {}
+ExternalReference::ExternalReference(Builtins::CFunctionId id, Isolate* isolate)
+  : address_(Redirect(isolate, Builtins::c_function_address(id))) {}
 
 
 ExternalReference::ExternalReference(
-    ApiFunction* fun, Type type = ExternalReference::BUILTIN_CALL)
-  : address_(Redirect(fun->address(), type)) {}
+    ApiFunction* fun,
+    Type type = ExternalReference::BUILTIN_CALL,
+    Isolate* isolate = NULL)
+  : address_(Redirect(isolate, fun->address(), type)) {}
 
 
-ExternalReference::ExternalReference(Builtins::Name name)
-  : address_(Builtins::builtin_address(name)) {}
+ExternalReference::ExternalReference(Builtins::Name name, Isolate* isolate)
+  : address_(isolate->builtins()->builtin_address(name)) {}
 
 
-ExternalReference::ExternalReference(Runtime::FunctionId id)
-  : address_(Redirect(Runtime::FunctionForId(id)->entry)) {}
+ExternalReference::ExternalReference(Runtime::FunctionId id,
+                                     Isolate* isolate)
+  : address_(Redirect(isolate, Runtime::FunctionForId(id)->entry)) {}
 
 
-ExternalReference::ExternalReference(Runtime::Function* f)
-  : address_(Redirect(f->entry)) {}
+ExternalReference::ExternalReference(const Runtime::Function* f,
+                                     Isolate* isolate)
+  : address_(Redirect(isolate, f->entry)) {}
 
 
-ExternalReference::ExternalReference(const IC_Utility& ic_utility)
-  : address_(Redirect(ic_utility.address())) {}
+ExternalReference ExternalReference::isolate_address() {
+  return ExternalReference(Isolate::Current());
+}
+
+
+ExternalReference::ExternalReference(const IC_Utility& ic_utility,
+                                     Isolate* isolate)
+  : address_(Redirect(isolate, ic_utility.address())) {}
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
-ExternalReference::ExternalReference(const Debug_Address& debug_address)
-  : address_(debug_address.address()) {}
+ExternalReference::ExternalReference(const Debug_Address& debug_address,
+                                     Isolate* isolate)
+  : address_(debug_address.address(isolate)) {}
 #endif
 
 ExternalReference::ExternalReference(StatsCounter* counter)
   : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
 
 
-ExternalReference::ExternalReference(Top::AddressId id)
-  : address_(Top::get_address_from_id(id)) {}
+ExternalReference::ExternalReference(Isolate::AddressId id, Isolate* isolate)
+  : address_(isolate->get_address_from_id(id)) {}
 
 
 ExternalReference::ExternalReference(const SCTableReference& table_ref)
   : address_(table_ref.address()) {}
 
 
-ExternalReference ExternalReference::perform_gc_function() {
-  return ExternalReference(Redirect(FUNCTION_ADDR(Runtime::PerformGC)));
+ExternalReference ExternalReference::perform_gc_function(Isolate* isolate) {
+  return ExternalReference(Redirect(isolate,
+                                    FUNCTION_ADDR(Runtime::PerformGC)));
 }
 
 
-ExternalReference ExternalReference::fill_heap_number_with_random_function() {
-  return
-      ExternalReference(Redirect(FUNCTION_ADDR(V8::FillHeapNumberWithRandom)));
+ExternalReference ExternalReference::fill_heap_number_with_random_function(
+    Isolate* isolate) {
+  return ExternalReference(Redirect(
+      isolate,
+      FUNCTION_ADDR(V8::FillHeapNumberWithRandom)));
 }
 
 
-ExternalReference ExternalReference::delete_handle_scope_extensions() {
-  return ExternalReference(Redirect(FUNCTION_ADDR(
-                           HandleScope::DeleteExtensions)));
+ExternalReference ExternalReference::delete_handle_scope_extensions(
+    Isolate* isolate) {
+  return ExternalReference(Redirect(
+      isolate,
+      FUNCTION_ADDR(HandleScope::DeleteExtensions)));
 }
 
 
-ExternalReference ExternalReference::random_uint32_function() {
-  return ExternalReference(Redirect(FUNCTION_ADDR(V8::Random)));
+ExternalReference ExternalReference::random_uint32_function(
+    Isolate* isolate) {
+  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(V8::Random)));
 }
 
 
-ExternalReference ExternalReference::transcendental_cache_array_address() {
-  return ExternalReference(TranscendentalCache::cache_array_address());
-}
-
-
-ExternalReference ExternalReference::new_deoptimizer_function() {
+ExternalReference ExternalReference::transcendental_cache_array_address(
+    Isolate* isolate) {
   return ExternalReference(
-      Redirect(FUNCTION_ADDR(Deoptimizer::New)));
+      isolate->transcendental_cache()->cache_array_address());
 }
 
 
-ExternalReference ExternalReference::compute_output_frames_function() {
+ExternalReference ExternalReference::new_deoptimizer_function(
+    Isolate* isolate) {
   return ExternalReference(
-      Redirect(FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames)));
+      Redirect(isolate, FUNCTION_ADDR(Deoptimizer::New)));
 }
 
 
-ExternalReference ExternalReference::global_contexts_list() {
-  return ExternalReference(Heap::global_contexts_list_address());
+ExternalReference ExternalReference::compute_output_frames_function(
+    Isolate* isolate) {
+  return ExternalReference(
+      Redirect(isolate, FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames)));
 }
 
 
-ExternalReference ExternalReference::keyed_lookup_cache_keys() {
-  return ExternalReference(KeyedLookupCache::keys_address());
+ExternalReference ExternalReference::global_contexts_list(Isolate* isolate) {
+  return ExternalReference(isolate->heap()->global_contexts_list_address());
 }
 
 
-ExternalReference ExternalReference::keyed_lookup_cache_field_offsets() {
-  return ExternalReference(KeyedLookupCache::field_offsets_address());
+ExternalReference ExternalReference::keyed_lookup_cache_keys(Isolate* isolate) {
+  return ExternalReference(isolate->keyed_lookup_cache()->keys_address());
 }
 
 
-ExternalReference ExternalReference::the_hole_value_location() {
-  return ExternalReference(Factory::the_hole_value().location());
+ExternalReference ExternalReference::keyed_lookup_cache_field_offsets(
+    Isolate* isolate) {
+  return ExternalReference(
+      isolate->keyed_lookup_cache()->field_offsets_address());
 }
 
 
-ExternalReference ExternalReference::arguments_marker_location() {
-  return ExternalReference(Factory::arguments_marker().location());
+ExternalReference ExternalReference::the_hole_value_location(Isolate* isolate) {
+  return ExternalReference(isolate->factory()->the_hole_value().location());
 }
 
 
-ExternalReference ExternalReference::roots_address() {
-  return ExternalReference(Heap::roots_address());
+ExternalReference ExternalReference::arguments_marker_location(
+    Isolate* isolate) {
+  return ExternalReference(isolate->factory()->arguments_marker().location());
 }
 
 
-ExternalReference ExternalReference::address_of_stack_limit() {
-  return ExternalReference(StackGuard::address_of_jslimit());
+ExternalReference ExternalReference::roots_address(Isolate* isolate) {
+  return ExternalReference(isolate->heap()->roots_address());
 }
 
 
-ExternalReference ExternalReference::address_of_real_stack_limit() {
-  return ExternalReference(StackGuard::address_of_real_jslimit());
+ExternalReference ExternalReference::address_of_stack_limit(Isolate* isolate) {
+  return ExternalReference(isolate->stack_guard()->address_of_jslimit());
 }
 
 
-ExternalReference ExternalReference::address_of_regexp_stack_limit() {
-  return ExternalReference(RegExpStack::limit_address());
+ExternalReference ExternalReference::address_of_real_stack_limit(
+    Isolate* isolate) {
+  return ExternalReference(isolate->stack_guard()->address_of_real_jslimit());
 }
 
 
-ExternalReference ExternalReference::new_space_start() {
-  return ExternalReference(Heap::NewSpaceStart());
+ExternalReference ExternalReference::address_of_regexp_stack_limit(
+    Isolate* isolate) {
+  return ExternalReference(isolate->regexp_stack()->limit_address());
 }
 
 
-ExternalReference ExternalReference::new_space_mask() {
-  return ExternalReference(reinterpret_cast<Address>(Heap::NewSpaceMask()));
+ExternalReference ExternalReference::new_space_start(Isolate* isolate) {
+  return ExternalReference(isolate->heap()->NewSpaceStart());
 }
 
 
-ExternalReference ExternalReference::new_space_allocation_top_address() {
-  return ExternalReference(Heap::NewSpaceAllocationTopAddress());
+ExternalReference ExternalReference::new_space_mask(Isolate* isolate) {
+  Address mask = reinterpret_cast<Address>(isolate->heap()->NewSpaceMask());
+  return ExternalReference(mask);
 }
 
 
-ExternalReference ExternalReference::heap_always_allocate_scope_depth() {
-  return ExternalReference(Heap::always_allocate_scope_depth_address());
+ExternalReference ExternalReference::new_space_allocation_top_address(
+    Isolate* isolate) {
+  return ExternalReference(isolate->heap()->NewSpaceAllocationTopAddress());
 }
 
 
-ExternalReference ExternalReference::new_space_allocation_limit_address() {
-  return ExternalReference(Heap::NewSpaceAllocationLimitAddress());
+ExternalReference ExternalReference::heap_always_allocate_scope_depth(
+    Isolate* isolate) {
+  Heap* heap = isolate->heap();
+  return ExternalReference(heap->always_allocate_scope_depth_address());
+}
+
+
+ExternalReference ExternalReference::new_space_allocation_limit_address(
+    Isolate* isolate) {
+  return ExternalReference(isolate->heap()->NewSpaceAllocationLimitAddress());
 }
 
 
@@ -716,8 +750,9 @@
 }
 
 
-ExternalReference ExternalReference::scheduled_exception_address() {
-  return ExternalReference(Top::scheduled_exception_address());
+ExternalReference ExternalReference::scheduled_exception_address(
+    Isolate* isolate) {
+  return ExternalReference(isolate->scheduled_exception_address());
 }
 
 
@@ -745,9 +780,16 @@
 }
 
 
+ExternalReference ExternalReference::address_of_nan() {
+  return ExternalReference(reinterpret_cast<void*>(
+      const_cast<double*>(&DoubleConstant::nan)));
+}
+
+
 #ifndef V8_INTERPRETED_REGEXP
 
-ExternalReference ExternalReference::re_check_stack_guard_state() {
+ExternalReference ExternalReference::re_check_stack_guard_state(
+    Isolate* isolate) {
   Address function;
 #ifdef V8_TARGET_ARCH_X64
   function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState);
@@ -755,19 +797,23 @@
   function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState);
 #elif V8_TARGET_ARCH_ARM
   function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState);
+#elif V8_TARGET_ARCH_MIPS
+  function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
 #else
   UNREACHABLE();
 #endif
-  return ExternalReference(Redirect(function));
+  return ExternalReference(Redirect(isolate, function));
 }
 
-ExternalReference ExternalReference::re_grow_stack() {
+ExternalReference ExternalReference::re_grow_stack(Isolate* isolate) {
   return ExternalReference(
-      Redirect(FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack)));
+      Redirect(isolate, FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack)));
 }
 
-ExternalReference ExternalReference::re_case_insensitive_compare_uc16() {
+ExternalReference ExternalReference::re_case_insensitive_compare_uc16(
+    Isolate* isolate) {
   return ExternalReference(Redirect(
+      isolate,
       FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16)));
 }
 
@@ -776,16 +822,21 @@
       NativeRegExpMacroAssembler::word_character_map_address());
 }
 
-ExternalReference ExternalReference::address_of_static_offsets_vector() {
-  return ExternalReference(OffsetsVector::static_offsets_vector_address());
+ExternalReference ExternalReference::address_of_static_offsets_vector(
+    Isolate* isolate) {
+  return ExternalReference(
+      OffsetsVector::static_offsets_vector_address(isolate));
 }
 
-ExternalReference ExternalReference::address_of_regexp_stack_memory_address() {
-  return ExternalReference(RegExpStack::memory_address());
+ExternalReference ExternalReference::address_of_regexp_stack_memory_address(
+    Isolate* isolate) {
+  return ExternalReference(
+      isolate->regexp_stack()->memory_address());
 }
 
-ExternalReference ExternalReference::address_of_regexp_stack_memory_size() {
-  return ExternalReference(RegExpStack::memory_size_address());
+ExternalReference ExternalReference::address_of_regexp_stack_memory_size(
+    Isolate* isolate) {
+  return ExternalReference(isolate->regexp_stack()->memory_size_address());
 }
 
 #endif  // V8_INTERPRETED_REGEXP
@@ -831,20 +882,26 @@
 }
 
 
-ExternalReference ExternalReference::math_sin_double_function() {
-  return ExternalReference(Redirect(FUNCTION_ADDR(math_sin_double),
+ExternalReference ExternalReference::math_sin_double_function(
+    Isolate* isolate) {
+  return ExternalReference(Redirect(isolate,
+                                    FUNCTION_ADDR(math_sin_double),
                                     FP_RETURN_CALL));
 }
 
 
-ExternalReference ExternalReference::math_cos_double_function() {
-  return ExternalReference(Redirect(FUNCTION_ADDR(math_cos_double),
+ExternalReference ExternalReference::math_cos_double_function(
+    Isolate* isolate) {
+  return ExternalReference(Redirect(isolate,
+                                    FUNCTION_ADDR(math_cos_double),
                                     FP_RETURN_CALL));
 }
 
 
-ExternalReference ExternalReference::math_log_double_function() {
-  return ExternalReference(Redirect(FUNCTION_ADDR(math_log_double),
+ExternalReference ExternalReference::math_log_double_function(
+    Isolate* isolate) {
+  return ExternalReference(Redirect(isolate,
+                                    FUNCTION_ADDR(math_log_double),
                                     FP_RETURN_CALL));
 }
 
@@ -884,14 +941,18 @@
 }
 
 
-ExternalReference ExternalReference::power_double_double_function() {
-  return ExternalReference(Redirect(FUNCTION_ADDR(power_double_double),
+ExternalReference ExternalReference::power_double_double_function(
+    Isolate* isolate) {
+  return ExternalReference(Redirect(isolate,
+                                    FUNCTION_ADDR(power_double_double),
                                     FP_RETURN_CALL));
 }
 
 
-ExternalReference ExternalReference::power_double_int_function() {
-  return ExternalReference(Redirect(FUNCTION_ADDR(power_double_int),
+ExternalReference ExternalReference::power_double_int_function(
+    Isolate* isolate) {
+  return ExternalReference(Redirect(isolate,
+                                    FUNCTION_ADDR(power_double_int),
                                     FP_RETURN_CALL));
 }
 
@@ -903,7 +964,7 @@
 
 
 ExternalReference ExternalReference::double_fp_operation(
-    Token::Value operation) {
+    Token::Value operation, Isolate* isolate) {
   typedef double BinaryFPOperation(double x, double y);
   BinaryFPOperation* function = NULL;
   switch (operation) {
@@ -926,28 +987,28 @@
       UNREACHABLE();
   }
   // Passing true as 2nd parameter indicates that they return an fp value.
-  return ExternalReference(Redirect(FUNCTION_ADDR(function), FP_RETURN_CALL));
+  return ExternalReference(Redirect(isolate,
+                                    FUNCTION_ADDR(function),
+                                    FP_RETURN_CALL));
 }
 
 
-ExternalReference ExternalReference::compare_doubles() {
-  return ExternalReference(Redirect(FUNCTION_ADDR(native_compare_doubles),
+ExternalReference ExternalReference::compare_doubles(Isolate* isolate) {
+  return ExternalReference(Redirect(isolate,
+                                    FUNCTION_ADDR(native_compare_doubles),
                                     BUILTIN_CALL));
 }
 
 
-ExternalReference::ExternalReferenceRedirector*
-    ExternalReference::redirector_ = NULL;
-
-
 #ifdef ENABLE_DEBUGGER_SUPPORT
-ExternalReference ExternalReference::debug_break() {
-  return ExternalReference(Redirect(FUNCTION_ADDR(Debug::Break)));
+ExternalReference ExternalReference::debug_break(Isolate* isolate) {
+  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(Debug::Break)));
 }
 
 
-ExternalReference ExternalReference::debug_step_in_fp_address() {
-  return ExternalReference(Debug::step_in_fp_addr());
+ExternalReference ExternalReference::debug_step_in_fp_address(
+    Isolate* isolate) {
+  return ExternalReference(isolate->debug()->step_in_fp_addr());
 }
 #endif
 
diff --git a/src/assembler.h b/src/assembler.h
index 8ebbfad..62fe04d 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -37,7 +37,6 @@
 
 #include "gdb-jit.h"
 #include "runtime.h"
-#include "top.h"
 #include "token.h"
 
 namespace v8 {
@@ -45,6 +44,19 @@
 
 
 // -----------------------------------------------------------------------------
+// Platform independent assembler base class.
+
+class AssemblerBase: public Malloced {
+ public:
+  explicit AssemblerBase(Isolate* isolate) : isolate_(isolate) {}
+
+  Isolate* isolate() const { return isolate_; }
+
+ private:
+  Isolate* isolate_;
+};
+
+// -----------------------------------------------------------------------------
 // Common double constants.
 
 class DoubleConstant: public AllStatic {
@@ -53,6 +65,7 @@
   static const double one_half;
   static const double minus_zero;
   static const double negative_infinity;
+  static const double nan;
 };
 
 
@@ -192,6 +205,9 @@
   // The maximum size for a call instruction including pc-jump.
   static const int kMaxCallSize = 6;
 
+  // The maximum pc delta that will use the short encoding.
+  static const int kMaxSmallPCDelta;
+
   enum Mode {
     // Please note the order is important (see IsCodeTarget, IsGCRelocMode).
     CONSTRUCT_CALL,  // code target that is a call to a JavaScript constructor.
@@ -317,7 +333,7 @@
   INLINE(void set_call_object(Object* target));
   INLINE(Object** call_object_address());
 
-  template<typename StaticVisitor> inline void Visit();
+  template<typename StaticVisitor> inline void Visit(Heap* heap);
   inline void Visit(ObjectVisitor* v);
 
   // Patch the code with some other code.
@@ -501,121 +517,129 @@
 
   typedef void* ExternalReferenceRedirector(void* original, Type type);
 
-  explicit ExternalReference(Builtins::CFunctionId id);
+  ExternalReference(Builtins::CFunctionId id, Isolate* isolate);
 
-  explicit ExternalReference(ApiFunction* ptr, Type type);
+  ExternalReference(ApiFunction* ptr, Type type, Isolate* isolate);
 
-  explicit ExternalReference(Builtins::Name name);
+  ExternalReference(Builtins::Name name, Isolate* isolate);
 
-  explicit ExternalReference(Runtime::FunctionId id);
+  ExternalReference(Runtime::FunctionId id, Isolate* isolate);
 
-  explicit ExternalReference(Runtime::Function* f);
+  ExternalReference(const Runtime::Function* f, Isolate* isolate);
 
-  explicit ExternalReference(const IC_Utility& ic_utility);
+  ExternalReference(const IC_Utility& ic_utility, Isolate* isolate);
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  explicit ExternalReference(const Debug_Address& debug_address);
+  ExternalReference(const Debug_Address& debug_address, Isolate* isolate);
 #endif
 
   explicit ExternalReference(StatsCounter* counter);
 
-  explicit ExternalReference(Top::AddressId id);
+  ExternalReference(Isolate::AddressId id, Isolate* isolate);
 
   explicit ExternalReference(const SCTableReference& table_ref);
 
+  // Isolate::Current() as an external reference.
+  static ExternalReference isolate_address();
+
   // 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 perform_gc_function();
-  static ExternalReference fill_heap_number_with_random_function();
-  static ExternalReference random_uint32_function();
-  static ExternalReference transcendental_cache_array_address();
-  static ExternalReference delete_handle_scope_extensions();
+  static ExternalReference perform_gc_function(Isolate* isolate);
+  static ExternalReference fill_heap_number_with_random_function(
+      Isolate* isolate);
+  static ExternalReference random_uint32_function(Isolate* isolate);
+  static ExternalReference transcendental_cache_array_address(Isolate* isolate);
+  static ExternalReference delete_handle_scope_extensions(Isolate* isolate);
 
   // Deoptimization support.
-  static ExternalReference new_deoptimizer_function();
-  static ExternalReference compute_output_frames_function();
-  static ExternalReference global_contexts_list();
+  static ExternalReference new_deoptimizer_function(Isolate* isolate);
+  static ExternalReference compute_output_frames_function(Isolate* isolate);
+  static ExternalReference global_contexts_list(Isolate* isolate);
 
   // Static data in the keyed lookup cache.
-  static ExternalReference keyed_lookup_cache_keys();
-  static ExternalReference keyed_lookup_cache_field_offsets();
+  static ExternalReference keyed_lookup_cache_keys(Isolate* isolate);
+  static ExternalReference keyed_lookup_cache_field_offsets(Isolate* isolate);
 
   // Static variable Factory::the_hole_value.location()
-  static ExternalReference the_hole_value_location();
+  static ExternalReference the_hole_value_location(Isolate* isolate);
 
   // Static variable Factory::arguments_marker.location()
-  static ExternalReference arguments_marker_location();
+  static ExternalReference arguments_marker_location(Isolate* isolate);
 
   // Static variable Heap::roots_address()
-  static ExternalReference roots_address();
+  static ExternalReference roots_address(Isolate* isolate);
 
   // Static variable StackGuard::address_of_jslimit()
-  static ExternalReference address_of_stack_limit();
+  static ExternalReference address_of_stack_limit(Isolate* isolate);
 
   // Static variable StackGuard::address_of_real_jslimit()
-  static ExternalReference address_of_real_stack_limit();
+  static ExternalReference address_of_real_stack_limit(Isolate* isolate);
 
   // Static variable RegExpStack::limit_address()
-  static ExternalReference address_of_regexp_stack_limit();
+  static ExternalReference address_of_regexp_stack_limit(Isolate* isolate);
 
   // Static variables for RegExp.
-  static ExternalReference address_of_static_offsets_vector();
-  static ExternalReference address_of_regexp_stack_memory_address();
-  static ExternalReference address_of_regexp_stack_memory_size();
+  static ExternalReference address_of_static_offsets_vector(Isolate* isolate);
+  static ExternalReference address_of_regexp_stack_memory_address(
+      Isolate* isolate);
+  static ExternalReference address_of_regexp_stack_memory_size(
+      Isolate* isolate);
 
   // Static variable Heap::NewSpaceStart()
-  static ExternalReference new_space_start();
-  static ExternalReference new_space_mask();
-  static ExternalReference heap_always_allocate_scope_depth();
+  static ExternalReference new_space_start(Isolate* isolate);
+  static ExternalReference new_space_mask(Isolate* isolate);
+  static ExternalReference heap_always_allocate_scope_depth(Isolate* isolate);
 
   // Used for fast allocation in generated code.
-  static ExternalReference new_space_allocation_top_address();
-  static ExternalReference new_space_allocation_limit_address();
+  static ExternalReference new_space_allocation_top_address(Isolate* isolate);
+  static ExternalReference new_space_allocation_limit_address(Isolate* isolate);
 
-  static ExternalReference double_fp_operation(Token::Value operation);
-  static ExternalReference compare_doubles();
-  static ExternalReference power_double_double_function();
-  static ExternalReference power_double_int_function();
+  static ExternalReference double_fp_operation(Token::Value operation,
+                                               Isolate* isolate);
+  static ExternalReference compare_doubles(Isolate* isolate);
+  static ExternalReference power_double_double_function(Isolate* isolate);
+  static ExternalReference power_double_int_function(Isolate* isolate);
 
   static ExternalReference handle_scope_next_address();
   static ExternalReference handle_scope_limit_address();
   static ExternalReference handle_scope_level_address();
 
-  static ExternalReference scheduled_exception_address();
+  static ExternalReference scheduled_exception_address(Isolate* isolate);
 
   // Static variables containing common double constants.
   static ExternalReference address_of_min_int();
   static ExternalReference address_of_one_half();
   static ExternalReference address_of_minus_zero();
   static ExternalReference address_of_negative_infinity();
+  static ExternalReference address_of_nan();
 
-  static ExternalReference math_sin_double_function();
-  static ExternalReference math_cos_double_function();
-  static ExternalReference math_log_double_function();
+  static ExternalReference math_sin_double_function(Isolate* isolate);
+  static ExternalReference math_cos_double_function(Isolate* isolate);
+  static ExternalReference math_log_double_function(Isolate* isolate);
 
   Address address() const {return reinterpret_cast<Address>(address_);}
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Function Debug::Break()
-  static ExternalReference debug_break();
+  static ExternalReference debug_break(Isolate* isolate);
 
   // Used to check if single stepping is enabled in generated code.
-  static ExternalReference debug_step_in_fp_address();
+  static ExternalReference debug_step_in_fp_address(Isolate* isolate);
 #endif
 
 #ifndef V8_INTERPRETED_REGEXP
   // C functions called from RegExp generated code.
 
   // Function NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()
-  static ExternalReference re_case_insensitive_compare_uc16();
+  static ExternalReference re_case_insensitive_compare_uc16(Isolate* isolate);
 
   // Function RegExpMacroAssembler*::CheckStackGuardState()
-  static ExternalReference re_check_stack_guard_state();
+  static ExternalReference re_check_stack_guard_state(Isolate* isolate);
 
   // Function NativeRegExpMacroAssembler::GrowStack()
-  static ExternalReference re_grow_stack();
+  static ExternalReference re_grow_stack(Isolate* isolate);
 
   // byte NativeRegExpMacroAssembler::word_character_bitmap
   static ExternalReference re_word_character_map();
@@ -625,29 +649,37 @@
   // This lets you register a function that rewrites all external references.
   // Used by the ARM simulator to catch calls to external references.
   static void set_redirector(ExternalReferenceRedirector* redirector) {
-    ASSERT(redirector_ == NULL);  // We can't stack them.
-    redirector_ = redirector;
+    // We can't stack them.
+    ASSERT(Isolate::Current()->external_reference_redirector() == NULL);
+    Isolate::Current()->set_external_reference_redirector(
+        reinterpret_cast<ExternalReferenceRedirectorPointer*>(redirector));
   }
 
  private:
   explicit ExternalReference(void* address)
       : address_(address) {}
 
-  static ExternalReferenceRedirector* redirector_;
-
-  static void* Redirect(void* address,
+  static void* Redirect(Isolate* isolate,
+                        void* address,
                         Type type = ExternalReference::BUILTIN_CALL) {
-    if (redirector_ == NULL) return address;
-    void* answer = (*redirector_)(address, type);
+    ExternalReferenceRedirector* redirector =
+        reinterpret_cast<ExternalReferenceRedirector*>(
+            isolate->external_reference_redirector());
+    if (redirector == NULL) return address;
+    void* answer = (*redirector)(address, type);
     return answer;
   }
 
-  static void* Redirect(Address address_arg,
+  static void* Redirect(Isolate* isolate,
+                        Address address_arg,
                         Type type = ExternalReference::BUILTIN_CALL) {
+    ExternalReferenceRedirector* redirector =
+        reinterpret_cast<ExternalReferenceRedirector*>(
+            isolate->external_reference_redirector());
     void* address = reinterpret_cast<void*>(address_arg);
-    void* answer = (redirector_ == NULL) ?
+    void* answer = (redirector == NULL) ?
                    address :
-                   (*redirector_)(address, type);
+                   (*redirector)(address, type);
     return answer;
   }
 
diff --git a/src/ast-inl.h b/src/ast-inl.h
index eb81c3a..6021fd9 100644
--- a/src/ast-inl.h
+++ b/src/ast-inl.h
@@ -102,6 +102,11 @@
 }
 
 
+bool FunctionLiteral::strict_mode() const {
+  return scope()->is_strict_mode();
+}
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_AST_INL_H_
diff --git a/src/ast.cc b/src/ast.cc
index 772684c..8434357 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -36,13 +36,13 @@
 namespace v8 {
 namespace internal {
 
-unsigned AstNode::current_id_ = 0;
-unsigned AstNode::count_ = 0;
-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);
+AstSentinels::AstSentinels()
+    : this_proxy_(true),
+      identifier_proxy_(false),
+      valid_left_hand_side_sentinel_(),
+      this_property_(&this_proxy_, NULL, 0),
+      call_sentinel_(NULL, NULL, 0) {
+}
 
 
 // ----------------------------------------------------------------------------
@@ -170,7 +170,7 @@
   key_ = key;
   value_ = value;
   Object* k = *key->handle();
-  if (k->IsSymbol() && Heap::Proto_symbol()->Equals(String::cast(k))) {
+  if (k->IsSymbol() && HEAP->Proto_symbol()->Equals(String::cast(k))) {
     kind_ = PROTOTYPE;
   } else if (value_->AsMaterializedLiteral() != NULL) {
     kind_ = MATERIALIZED_LITERAL;
@@ -249,10 +249,11 @@
     uint32_t hash;
     HashMap* table;
     void* key;
+    Factory* factory = Isolate::Current()->factory();
     if (handle->IsSymbol()) {
       Handle<String> name(String::cast(*handle));
       if (name->AsArrayIndex(&hash)) {
-        Handle<Object> key_handle = Factory::NewNumberFromUint(hash);
+        Handle<Object> key_handle = factory->NewNumberFromUint(hash);
         key = key_handle.location();
         table = &elements;
       } else {
@@ -269,7 +270,7 @@
       char arr[100];
       Vector<char> buffer(arr, ARRAY_SIZE(arr));
       const char* str = DoubleToCString(num, buffer);
-      Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
+      Handle<String> name = factory->NewStringFromAscii(CStrVector(str));
       key = name.location();
       hash = name->Hash();
       table = &properties;
@@ -526,12 +527,12 @@
   // Record type feedback from the oracle in the AST.
   is_monomorphic_ = oracle->LoadIsMonomorphic(this);
   if (key()->IsPropertyName()) {
-    if (oracle->LoadIsBuiltin(this, Builtins::LoadIC_ArrayLength)) {
+    if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_ArrayLength)) {
       is_array_length_ = true;
-    } else if (oracle->LoadIsBuiltin(this, Builtins::LoadIC_StringLength)) {
+    } else if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_StringLength)) {
       is_string_length_ = true;
     } else if (oracle->LoadIsBuiltin(this,
-                                     Builtins::LoadIC_FunctionPrototype)) {
+                                     Builtins::kLoadIC_FunctionPrototype)) {
       is_function_prototype_ = true;
     } else {
       Literal* lit_key = key()->AsLiteral();
@@ -540,8 +541,13 @@
       ZoneMapList* types = oracle->LoadReceiverTypes(this, name);
       receiver_types_ = types;
     }
+  } else if (oracle->LoadIsBuiltin(this, Builtins::kKeyedLoadIC_String)) {
+    is_string_access_ = true;
   } else if (is_monomorphic_) {
     monomorphic_receiver_type_ = oracle->LoadMonomorphicReceiverType(this);
+    if (monomorphic_receiver_type_->has_external_array_elements()) {
+      SetExternalArrayType(oracle->GetKeyedLoadExternalArrayType(this));
+    }
   }
 }
 
@@ -559,6 +565,9 @@
   } else if (is_monomorphic_) {
     // Record receiver type for monomorphic keyed loads.
     monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this);
+    if (monomorphic_receiver_type_->has_external_array_elements()) {
+      SetExternalArrayType(oracle->GetKeyedStoreExternalArrayType(this));
+    }
   }
 }
 
@@ -626,7 +635,7 @@
       Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
       // If the function is in new space we assume it's more likely to
       // change and thus prefer the general IC code.
-      if (!Heap::InNewSpace(*candidate) &&
+      if (!HEAP->InNewSpace(*candidate) &&
           CanCallWithoutIC(candidate, arguments()->length())) {
         target_ = candidate;
         return true;
@@ -691,7 +700,7 @@
 
 bool AstVisitor::CheckStackOverflow() {
   if (stack_overflow_) return true;
-  StackLimitCheck check;
+  StackLimitCheck check(isolate_);
   if (!check.HasOverflowed()) return false;
   return (stack_overflow_ = true);
 }
@@ -1062,6 +1071,8 @@
     : label_(label),
       statements_(statements),
       position_(pos),
-      compare_type_(NONE) {}
+      compare_type_(NONE),
+      entry_id_(AstNode::GetNextId()) {
+}
 
 } }  // namespace v8::internal
diff --git a/src/ast.h b/src/ast.h
index 2aee5d7..e9a06ec 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -135,7 +135,10 @@
 
   static const int kNoNumber = -1;
 
-  AstNode() : id_(GetNextId()) { count_++; }
+  AstNode() : id_(GetNextId()) {
+    Isolate* isolate = Isolate::Current();
+    isolate->set_ast_node_count(isolate->ast_node_count() + 1);
+  }
 
   virtual ~AstNode() { }
 
@@ -159,22 +162,28 @@
   // True if the node is simple enough for us to inline calls containing it.
   virtual bool IsInlineable() const { return false; }
 
-  static int Count() { return count_; }
-  static void ResetIds() { current_id_ = 0; }
+  static int Count() { return Isolate::Current()->ast_node_count(); }
+  static void ResetIds() { Isolate::Current()->set_ast_node_id(0); }
   unsigned id() const { return id_; }
 
  protected:
-  static unsigned GetNextId() { return current_id_++; }
+  static unsigned GetNextId() {
+    Isolate* isolate = Isolate::Current();
+    unsigned tmp = isolate->ast_node_id();
+    isolate->set_ast_node_id(tmp + 1);
+    return tmp;
+  }
   static unsigned ReserveIdRange(int n) {
-    unsigned tmp = current_id_;
-    current_id_ += n;
+    Isolate* isolate = Isolate::Current();
+    unsigned tmp = isolate->ast_node_id();
+    isolate->set_ast_node_id(tmp + n);
     return tmp;
   }
 
  private:
-  static unsigned current_id_;
-  static unsigned count_;
   unsigned id_;
+
+  friend class CaseClause;  // Generates AST IDs.
 };
 
 
@@ -333,10 +342,6 @@
  public:
   virtual bool IsValidLeftHandSide() { return true; }
   virtual void Accept(AstVisitor* v) { UNREACHABLE(); }
-  static ValidLeftHandSideSentinel* instance() { return &instance_; }
-
- private:
-  static ValidLeftHandSideSentinel instance_;
 };
 
 
@@ -694,6 +699,8 @@
   int position() { return position_; }
   void set_position(int pos) { position_ = pos; }
 
+  int EntryId() { return entry_id_; }
+
   // Type feedback information.
   void RecordTypeFeedback(TypeFeedbackOracle* oracle);
   bool IsSmiCompare() { return compare_type_ == SMI_ONLY; }
@@ -706,6 +713,7 @@
   int position_;
   enum CompareTypeFeedback { NONE, SMI_ONLY, OBJECT_ONLY };
   CompareTypeFeedback compare_type_;
+  int entry_id_;
 };
 
 
@@ -893,10 +901,17 @@
   virtual bool ToBooleanIsFalse() { return handle_->ToBoolean()->IsFalse(); }
 
   // 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 IsNull() const {
+    ASSERT(!handle_.is_null());
+    return handle_->IsNull();
+  }
+  bool IsTrue() const {
+    ASSERT(!handle_.is_null());
+    return handle_->IsTrue();
+  }
   bool IsFalse() const {
-    return handle_.is_identical_to(Factory::false_value());
+    ASSERT(!handle_.is_null());
+    return handle_->IsFalse();
   }
 
   Handle<Object> handle() const { return handle_; }
@@ -970,11 +985,13 @@
                 int literal_index,
                 bool is_simple,
                 bool fast_elements,
-                int depth)
+                int depth,
+                bool has_function)
       : MaterializedLiteral(literal_index, is_simple, depth),
         constant_properties_(constant_properties),
         properties_(properties),
-        fast_elements_(fast_elements) {}
+        fast_elements_(fast_elements),
+        has_function_(has_function) {}
 
   DECLARE_NODE_TYPE(ObjectLiteral)
 
@@ -985,16 +1002,24 @@
 
   bool fast_elements() const { return fast_elements_; }
 
+  bool has_function() { return has_function_; }
 
   // Mark all computed expressions that are bound to a key that
   // is shadowed by a later occurrence of the same key. For the
   // marked expressions, no store code is emitted.
   void CalculateEmitStore();
 
+  enum Flags {
+    kNoFlags = 0,
+    kFastElements = 1,
+    kHasFunction = 1 << 1
+  };
+
  private:
   Handle<FixedArray> constant_properties_;
   ZoneList<Property*>* properties_;
   bool fast_elements_;
+  bool has_function_;
 };
 
 
@@ -1133,15 +1158,11 @@
 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_;
+
+  friend class AstSentinels;
 };
 
 
@@ -1209,6 +1230,7 @@
         is_monomorphic_(false),
         is_array_length_(false),
         is_string_length_(false),
+        is_string_access_(false),
         is_function_prototype_(false),
         is_arguments_access_(false) { }
 
@@ -1223,6 +1245,7 @@
   bool is_synthetic() const { return type_ == SYNTHETIC; }
 
   bool IsStringLength() const { return is_string_length_; }
+  bool IsStringAccess() const { return is_string_access_; }
   bool IsFunctionPrototype() const { return is_function_prototype_; }
 
   // Marks that this is actually an argument rewritten to a keyed property
@@ -1232,6 +1255,11 @@
   }
   bool is_arguments_access() const { return is_arguments_access_; }
 
+  ExternalArrayType GetExternalArrayType() const { return array_type_; }
+  void SetExternalArrayType(ExternalArrayType array_type) {
+    array_type_ = array_type;
+  }
+
   // Type feedback information.
   void RecordTypeFeedback(TypeFeedbackOracle* oracle);
   virtual bool IsMonomorphic() { return is_monomorphic_; }
@@ -1241,10 +1269,6 @@
     return monomorphic_receiver_type_;
   }
 
-  // Returns a property singleton property access on 'this'.  Used
-  // during preparsing.
-  static Property* this_property() { return &this_property_; }
-
  private:
   Expression* obj_;
   Expression* key_;
@@ -1255,12 +1279,11 @@
   bool is_monomorphic_ : 1;
   bool is_array_length_ : 1;
   bool is_string_length_ : 1;
+  bool is_string_access_ : 1;
   bool is_function_prototype_ : 1;
   bool is_arguments_access_ : 1;
   Handle<Map> monomorphic_receiver_type_;
-
-  // Dummy property used during preparsing.
-  static Property this_property_;
+  ExternalArrayType array_type_;
 };
 
 
@@ -1298,8 +1321,6 @@
   // Bailout support.
   int ReturnId() const { return return_id_; }
 
-  static Call* sentinel() { return &sentinel_; }
-
 #ifdef DEBUG
   // Used to assert that the FullCodeGenerator records the return site.
   bool return_is_recorded_;
@@ -1318,8 +1339,36 @@
   Handle<JSGlobalPropertyCell> cell_;
 
   int return_id_;
+};
 
-  static Call sentinel_;
+
+class AstSentinels {
+ public:
+  ~AstSentinels() { }
+
+  // Returns a property singleton property access on 'this'.  Used
+  // during preparsing.
+  Property* this_property() { return &this_property_; }
+  VariableProxySentinel* this_proxy() { return &this_proxy_; }
+  VariableProxySentinel* identifier_proxy() { return &identifier_proxy_; }
+  ValidLeftHandSideSentinel* valid_left_hand_side_sentinel() {
+    return &valid_left_hand_side_sentinel_;
+  }
+  Call* call_sentinel() { return &call_sentinel_; }
+  EmptyStatement* empty_statement() { return &empty_statement_; }
+
+ private:
+  AstSentinels();
+  VariableProxySentinel this_proxy_;
+  VariableProxySentinel identifier_proxy_;
+  ValidLeftHandSideSentinel valid_left_hand_side_sentinel_;
+  Property this_property_;
+  Call call_sentinel_;
+  EmptyStatement empty_statement_;
+
+  friend class Isolate;
+
+  DISALLOW_COPY_AND_ASSIGN(AstSentinels);
 };
 
 
@@ -1350,7 +1399,7 @@
 class CallRuntime: public Expression {
  public:
   CallRuntime(Handle<String> name,
-              Runtime::Function* function,
+              const Runtime::Function* function,
               ZoneList<Expression*>* arguments)
       : name_(name), function_(function), arguments_(arguments) { }
 
@@ -1359,13 +1408,13 @@
   virtual bool IsInlineable() const;
 
   Handle<String> name() const { return name_; }
-  Runtime::Function* function() const { return function_; }
+  const Runtime::Function* function() const { return function_; }
   ZoneList<Expression*>* arguments() const { return arguments_; }
   bool is_jsruntime() const { return function_ == NULL; }
 
  private:
   Handle<String> name_;
-  Runtime::Function* function_;
+  const Runtime::Function* function_;
   ZoneList<Expression*>* arguments_;
 };
 
@@ -1621,6 +1670,10 @@
   virtual Handle<Map> GetMonomorphicReceiverType() {
     return monomorphic_receiver_type_;
   }
+  ExternalArrayType GetExternalArrayType() const { return array_type_; }
+  void SetExternalArrayType(ExternalArrayType array_type) {
+    array_type_ = array_type;
+  }
 
   // Bailout support.
   int CompoundLoadId() const { return compound_load_id_; }
@@ -1641,6 +1694,7 @@
   bool is_monomorphic_;
   ZoneMapList* receiver_types_;
   Handle<Map> monomorphic_receiver_type_;
+  ExternalArrayType array_type_;
 };
 
 
@@ -1673,8 +1727,7 @@
                   int start_position,
                   int end_position,
                   bool is_expression,
-                  bool contains_loops,
-                  bool strict_mode)
+                  bool contains_loops)
       : name_(name),
         scope_(scope),
         body_(body),
@@ -1688,9 +1741,8 @@
         end_position_(end_position),
         is_expression_(is_expression),
         contains_loops_(contains_loops),
-        strict_mode_(strict_mode),
         function_token_position_(RelocInfo::kNoPosition),
-        inferred_name_(Heap::empty_string()),
+        inferred_name_(HEAP->empty_string()),
         try_full_codegen_(false),
         pretenure_(false) { }
 
@@ -1705,7 +1757,7 @@
   int end_position() const { return end_position_; }
   bool is_expression() const { return is_expression_; }
   bool contains_loops() const { return contains_loops_; }
-  bool strict_mode() const { return strict_mode_; }
+  bool strict_mode() const;
 
   int materialized_literal_count() { return materialized_literal_count_; }
   int expected_property_count() { return expected_property_count_; }
@@ -2138,7 +2190,7 @@
 
 class AstVisitor BASE_EMBEDDED {
  public:
-  AstVisitor() : stack_overflow_(false) { }
+  AstVisitor() : isolate_(Isolate::Current()), stack_overflow_(false) { }
   virtual ~AstVisitor() { }
 
   // Stack overflow check and dynamic dispatch.
@@ -2168,10 +2220,15 @@
   AST_NODE_LIST(DEF_VISIT)
 #undef DEF_VISIT
 
+ protected:
+  Isolate* isolate() { return isolate_; }
+
  private:
+  Isolate* isolate_;
   bool stack_overflow_;
 };
 
+
 } }  // namespace v8::internal
 
 #endif  // V8_AST_H_
diff --git a/src/atomicops.h b/src/atomicops.h
index 72a0d0f..e2057ed 100644
--- a/src/atomicops.h
+++ b/src/atomicops.h
@@ -158,6 +158,8 @@
 #include "atomicops_internals_x86_gcc.h"
 #elif defined(__GNUC__) && defined(V8_HOST_ARCH_ARM)
 #include "atomicops_internals_arm_gcc.h"
+#elif defined(__GNUC__) && defined(V8_HOST_ARCH_MIPS)
+#include "atomicops_internals_mips_gcc.h"
 #else
 #error "Atomic operations are not supported on your platform"
 #endif
diff --git a/src/atomicops_internals_mips_gcc.h b/src/atomicops_internals_mips_gcc.h
new file mode 100644
index 0000000..5113de2
--- /dev/null
+++ b/src/atomicops_internals_mips_gcc.h
@@ -0,0 +1,169 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef V8_ATOMICOPS_INTERNALS_MIPS_GCC_H_
+#define V8_ATOMICOPS_INTERNALS_MIPS_GCC_H_
+
+#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("sync" : : : "memory")
+
+namespace v8 {
+namespace internal {
+
+// Atomically execute:
+//      result = *ptr;
+//      if (*ptr == old_value)
+//        *ptr = new_value;
+//      return result;
+//
+// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
+// Always return the old value of "*ptr"
+//
+// This routine implies no memory barriers.
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev;
+  __asm__ __volatile__("1:\n"
+                       "ll %0, %1\n"  // prev = *ptr
+                       "bne %0, %3, 2f\n"  // if (prev != old_value) goto 2
+                       "nop\n"  // delay slot nop
+                       "sc %2, %1\n"  // *ptr = new_value (with atomic check)
+                       "beqz %2, 1b\n"  // start again on atomic error
+                       "nop\n"  // delay slot nop
+                       "2:\n"
+                       : "=&r" (prev), "=m" (*ptr), "+&r" (new_value)
+                       : "Ir" (old_value), "r" (new_value), "m" (*ptr)
+                       : "memory");
+  return prev;
+}
+
+// Atomically store new_value into *ptr, returning the previous value held in
+// *ptr.  This routine implies no memory barriers.
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 temp, old;
+  __asm__ __volatile__("1:\n"
+                       "ll %1, %2\n"  // old = *ptr
+                       "move %0, %3\n"  // temp = new_value
+                       "sc %0, %2\n"  // *ptr = temp (with atomic check)
+                       "beqz %0, 1b\n"  // start again on atomic error
+                       "nop\n"  // delay slot nop
+                       : "=&r" (temp), "=&r" (old), "=m" (*ptr)
+                       : "r" (new_value), "m" (*ptr)
+                       : "memory");
+
+  return old;
+}
+
+// Atomically increment *ptr by "increment".  Returns the new value of
+// *ptr with the increment applied.  This routine implies no memory barriers.
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  Atomic32 temp, temp2;
+
+  __asm__ __volatile__("1:\n"
+                       "ll %0, %2\n"  // temp = *ptr
+                       "addu %0, %3\n"  // temp = temp + increment
+                       "move %1, %0\n"  // temp2 = temp
+                       "sc %0, %2\n"  // *ptr = temp (with atomic check)
+                       "beqz %0, 1b\n"  // start again on atomic error
+                       "nop\n"  // delay slot nop
+                       : "=&r" (temp), "=&r" (temp2), "=m" (*ptr)
+                       : "Ir" (increment), "m" (*ptr)
+                       : "memory");
+  // temp2 now holds the final value.
+  return temp2;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  Atomic32 res = NoBarrier_AtomicIncrement(ptr, increment);
+  ATOMICOPS_COMPILER_BARRIER();
+  return res;
+}
+
+// "Acquire" operations
+// ensure that no later memory access can be reordered ahead of the operation.
+// "Release" operations ensure that no previous memory access can be reordered
+// after the operation.  "Barrier" operations have both "Acquire" and "Release"
+// semantics.   A MemoryBarrier() has "Barrier" semantics, but does no memory
+// access.
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  ATOMICOPS_COMPILER_BARRIER();
+  return x;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  ATOMICOPS_COMPILER_BARRIER();
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void MemoryBarrier() {
+  ATOMICOPS_COMPILER_BARRIER();
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+} }  // namespace v8::internal
+
+#undef ATOMICOPS_COMPILER_BARRIER
+
+#endif  // V8_ATOMICOPS_INTERNALS_MIPS_GCC_H_
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 8cd29b2..9c9bac7 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -44,100 +44,57 @@
 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(Script::Type type): type_(type), cache_(NULL) { }
 
-  void Initialize(bool create_heap_objects) {
-    cache_ = create_heap_objects ? Heap::empty_fixed_array() : NULL;
-  }
-
-  void Iterate(ObjectVisitor* v) {
-    v->VisitPointer(BitCast<Object**>(&cache_));
-  }
-
-
-  bool Lookup(Vector<const char> name, Handle<SharedFunctionInfo>* handle) {
-    for (int i = 0; i < cache_->length(); i+=2) {
-      SeqAsciiString* str = SeqAsciiString::cast(cache_->get(i));
-      if (str->IsEqualTo(name)) {
-        *handle = Handle<SharedFunctionInfo>(
-            SharedFunctionInfo::cast(cache_->get(i + 1)));
-        return true;
-      }
-    }
-    return false;
-  }
-
-
-  void Add(Vector<const char> name, Handle<SharedFunctionInfo> shared) {
-    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, *shared);
-    Script::cast(shared->script())->set_type(Smi::FromInt(type_));
-  }
-
- private:
-  Script::Type type_;
-  FixedArray* cache_;
-  DISALLOW_COPY_AND_ASSIGN(SourceCodeCache);
-};
-
-static SourceCodeCache extensions_cache(Script::TYPE_EXTENSION);
-// This is for delete, not delete[].
-static List<char*>* delete_these_non_arrays_on_tear_down = NULL;
-// This is for delete[]
-static List<char*>* delete_these_arrays_on_tear_down = NULL;
-
-
-NativesExternalStringResource::NativesExternalStringResource(const char* source)
+NativesExternalStringResource::NativesExternalStringResource(
+    Bootstrapper* bootstrapper,
+    const char* source)
     : data_(source), length_(StrLength(source)) {
-  if (delete_these_non_arrays_on_tear_down == NULL) {
-    delete_these_non_arrays_on_tear_down = new List<char*>(2);
+  if (bootstrapper->delete_these_non_arrays_on_tear_down_ == NULL) {
+    bootstrapper->delete_these_non_arrays_on_tear_down_ = new List<char*>(2);
   }
   // The resources are small objects and we only make a fixed number of
   // them, but let's clean them up on exit for neatness.
-  delete_these_non_arrays_on_tear_down->
+  bootstrapper->delete_these_non_arrays_on_tear_down_->
       Add(reinterpret_cast<char*>(this));
 }
 
 
+Bootstrapper::Bootstrapper()
+    : nesting_(0),
+      extensions_cache_(Script::TYPE_EXTENSION),
+      delete_these_non_arrays_on_tear_down_(NULL),
+      delete_these_arrays_on_tear_down_(NULL) {
+}
+
+
 Handle<String> Bootstrapper::NativesSourceLookup(int index) {
   ASSERT(0 <= index && index < Natives::GetBuiltinsCount());
-  if (Heap::natives_source_cache()->get(index)->IsUndefined()) {
+  Isolate* isolate = Isolate::Current();
+  Factory* factory = isolate->factory();
+  Heap* heap = isolate->heap();
+  if (heap->natives_source_cache()->get(index)->IsUndefined()) {
     if (!Snapshot::IsEnabled() || FLAG_new_snapshot) {
       // We can use external strings for the natives.
       NativesExternalStringResource* resource =
-          new NativesExternalStringResource(
+          new NativesExternalStringResource(this,
               Natives::GetScriptSource(index).start());
       Handle<String> source_code =
-          Factory::NewExternalStringFromAscii(resource);
-      Heap::natives_source_cache()->set(index, *source_code);
+          factory->NewExternalStringFromAscii(resource);
+      heap->natives_source_cache()->set(index, *source_code);
     } else {
       // Old snapshot code can't cope with external strings at all.
       Handle<String> source_code =
-        Factory::NewStringFromAscii(Natives::GetScriptSource(index));
-      Heap::natives_source_cache()->set(index, *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));
+  Handle<Object> cached_source(heap->natives_source_cache()->get(index));
   return Handle<String>::cast(cached_source);
 }
 
 
 void Bootstrapper::Initialize(bool create_heap_objects) {
-  extensions_cache.Initialize(create_heap_objects);
+  extensions_cache_.Initialize(create_heap_objects);
   GCExtension::Register();
   ExternalizeStringExtension::Register();
 }
@@ -146,39 +103,39 @@
 char* Bootstrapper::AllocateAutoDeletedArray(int bytes) {
   char* memory = new char[bytes];
   if (memory != NULL) {
-    if (delete_these_arrays_on_tear_down == NULL) {
-      delete_these_arrays_on_tear_down = new List<char*>(2);
+    if (delete_these_arrays_on_tear_down_ == NULL) {
+      delete_these_arrays_on_tear_down_ = new List<char*>(2);
     }
-    delete_these_arrays_on_tear_down->Add(memory);
+    delete_these_arrays_on_tear_down_->Add(memory);
   }
   return memory;
 }
 
 
 void Bootstrapper::TearDown() {
-  if (delete_these_non_arrays_on_tear_down != NULL) {
-    int len = delete_these_non_arrays_on_tear_down->length();
+  if (delete_these_non_arrays_on_tear_down_ != NULL) {
+    int len = delete_these_non_arrays_on_tear_down_->length();
     ASSERT(len < 20);  // Don't use this mechanism for unbounded allocations.
     for (int i = 0; i < len; i++) {
-      delete delete_these_non_arrays_on_tear_down->at(i);
-      delete_these_non_arrays_on_tear_down->at(i) = NULL;
+      delete delete_these_non_arrays_on_tear_down_->at(i);
+      delete_these_non_arrays_on_tear_down_->at(i) = NULL;
     }
-    delete delete_these_non_arrays_on_tear_down;
-    delete_these_non_arrays_on_tear_down = NULL;
+    delete delete_these_non_arrays_on_tear_down_;
+    delete_these_non_arrays_on_tear_down_ = NULL;
   }
 
-  if (delete_these_arrays_on_tear_down != NULL) {
-    int len = delete_these_arrays_on_tear_down->length();
+  if (delete_these_arrays_on_tear_down_ != NULL) {
+    int len = delete_these_arrays_on_tear_down_->length();
     ASSERT(len < 1000);  // Don't use this mechanism for unbounded allocations.
     for (int i = 0; i < len; i++) {
-      delete[] delete_these_arrays_on_tear_down->at(i);
-      delete_these_arrays_on_tear_down->at(i) = NULL;
+      delete[] delete_these_arrays_on_tear_down_->at(i);
+      delete_these_arrays_on_tear_down_->at(i) = NULL;
     }
-    delete delete_these_arrays_on_tear_down;
-    delete_these_arrays_on_tear_down = NULL;
+    delete delete_these_arrays_on_tear_down_;
+    delete_these_arrays_on_tear_down_ = NULL;
   }
 
-  extensions_cache.Initialize(false);  // Yes, symmetrical
+  extensions_cache_.Initialize(false);  // Yes, symmetrical
 }
 
 
@@ -207,6 +164,10 @@
   void CreateRoots();
   // Creates the empty function.  Used for creating a context from scratch.
   Handle<JSFunction> CreateEmptyFunction();
+  // Creates the ThrowTypeError function. ECMA 5th Ed. 13.2.3
+  Handle<JSFunction> CreateThrowTypeErrorFunction(Builtins::Name builtin);
+
+  void CreateStrictModeFunctionMaps(Handle<JSFunction> empty);
   // Creates the global objects using the global and the template passed in
   // through the API.  We call this regardless of whether we are building a
   // context from scratch or using a deserialized one from the partial snapshot
@@ -260,10 +221,24 @@
     ADD_READONLY_PROTOTYPE,
     ADD_WRITEABLE_PROTOTYPE
   };
+
+  Handle<Map> CreateFunctionMap(PrototypePropertyMode prototype_mode);
+
   Handle<DescriptorArray> ComputeFunctionInstanceDescriptor(
       PrototypePropertyMode prototypeMode);
   void MakeFunctionInstancePrototypeWritable();
 
+  Handle<Map> CreateStrictModeFunctionMap(
+      PrototypePropertyMode prototype_mode,
+      Handle<JSFunction> empty_function,
+      Handle<FixedArray> arguments_callbacks,
+      Handle<FixedArray> caller_callbacks);
+
+  Handle<DescriptorArray> ComputeStrictFunctionInstanceDescriptor(
+      PrototypePropertyMode propertyMode,
+      Handle<FixedArray> arguments,
+      Handle<FixedArray> caller);
+
   static bool CompileBuiltin(int index);
   static bool CompileNative(Vector<const char> name, Handle<String> source);
   static bool CompileScriptCached(Vector<const char> name,
@@ -274,14 +249,21 @@
                                   bool use_runtime_context);
 
   Handle<Context> result_;
-  Handle<JSFunction> empty_function_;
+
+  // Function instance maps. Function literal maps are created initially with
+  // a read only prototype for the processing of JS builtins. Later the function
+  // instance maps are replaced in order to make prototype writable.
+  // These are the final, writable prototype, maps.
+  Handle<Map> function_instance_map_writable_prototype_;
+  Handle<Map> strict_mode_function_instance_map_writable_prototype_;
+
   BootstrapperActive active_;
   friend class Bootstrapper;
 };
 
 
 void Bootstrapper::Iterate(ObjectVisitor* v) {
-  extensions_cache.Iterate(v);
+  extensions_cache_.Iterate(v);
   v->Synchronize("Extensions");
 }
 
@@ -306,16 +288,17 @@
 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);
+  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());
+  Factory* factory = Isolate::Current()->factory();
+  JSGlobalProxy::cast(env->global_proxy())->set_context(*factory->null_value());
   SetObjectPrototype(Handle<JSObject>(env->global_proxy()),
-                     Factory::null_value());
+                     factory->null_value());
   env->set_global_proxy(env->global());
   env->global()->set_global_receiver(env->global());
 }
@@ -339,11 +322,13 @@
                                           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));
+  Isolate* isolate = Isolate::Current();
+  Factory* factory = isolate->factory();
+  Handle<String> symbol = factory->LookupAsciiSymbol(name);
+  Handle<Code> call_code = Handle<Code>(isolate->builtins()->builtin(call));
   Handle<JSFunction> function = prototype.is_null() ?
-    Factory::NewFunctionWithoutPrototype(symbol, call_code) :
-    Factory::NewFunctionWithPrototype(symbol,
+    factory->NewFunctionWithoutPrototype(symbol, call_code) :
+    factory->NewFunctionWithPrototype(symbol,
                                       type,
                                       instance_size,
                                       prototype,
@@ -359,174 +344,305 @@
 
 Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor(
     PrototypePropertyMode prototypeMode) {
-  Handle<DescriptorArray> result = Factory::empty_descriptor_array();
-
-  if (prototypeMode != DONT_ADD_PROTOTYPE) {
-    PropertyAttributes attributes = static_cast<PropertyAttributes>(
-        DONT_ENUM |
-        DONT_DELETE |
-        (prototypeMode == ADD_READONLY_PROTOTYPE ? READ_ONLY : 0));
-    result =
-        Factory::CopyAppendProxyDescriptor(
-            result,
-            Factory::prototype_symbol(),
-            Factory::NewProxy(&Accessors::FunctionPrototype),
-            attributes);
-  }
-
+  Factory* factory = Isolate::Current()->factory();
+  Handle<DescriptorArray> descriptors =
+      factory->NewDescriptorArray(prototypeMode == DONT_ADD_PROTOTYPE ? 4 : 5);
   PropertyAttributes 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 length.
+    Handle<Proxy> proxy = factory->NewProxy(&Accessors::FunctionLength);
+    CallbacksDescriptor d(*factory->length_symbol(), *proxy, attributes);
+    descriptors->Set(0, &d);
+  }
+  {  // Add name.
+    Handle<Proxy> proxy = factory->NewProxy(&Accessors::FunctionName);
+    CallbacksDescriptor d(*factory->name_symbol(), *proxy, attributes);
+    descriptors->Set(1, &d);
+  }
+  {  // Add arguments.
+    Handle<Proxy> proxy = factory->NewProxy(&Accessors::FunctionArguments);
+    CallbacksDescriptor d(*factory->arguments_symbol(), *proxy, attributes);
+    descriptors->Set(2, &d);
+  }
+  {  // Add caller.
+    Handle<Proxy> proxy = factory->NewProxy(&Accessors::FunctionCaller);
+    CallbacksDescriptor d(*factory->caller_symbol(), *proxy, attributes);
+    descriptors->Set(3, &d);
+  }
+  if (prototypeMode != DONT_ADD_PROTOTYPE) {
+    // Add prototype.
+    if (prototypeMode == ADD_WRITEABLE_PROTOTYPE) {
+      attributes = static_cast<PropertyAttributes>(attributes & ~READ_ONLY);
+    }
+    Handle<Proxy> proxy = factory->NewProxy(&Accessors::FunctionPrototype);
+    CallbacksDescriptor d(*factory->prototype_symbol(), *proxy, attributes);
+    descriptors->Set(4, &d);
+  }
+  descriptors->Sort();
+  return descriptors;
+}
 
-  // 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;
+Handle<Map> Genesis::CreateFunctionMap(PrototypePropertyMode prototype_mode) {
+  Handle<Map> map = FACTORY->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
+  Handle<DescriptorArray> descriptors =
+      ComputeFunctionInstanceDescriptor(prototype_mode);
+  map->set_instance_descriptors(*descriptors);
+  map->set_function_with_prototype(prototype_mode != DONT_ADD_PROTOTYPE);
+  return map;
 }
 
 
 Handle<JSFunction> Genesis::CreateEmptyFunction() {
-  // Allocate the map for function instances.
-  Handle<Map> fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
-  global_context()->set_function_instance_map(*fm);
+  // Allocate the map for function instances. Maps are allocated first and their
+  // prototypes patched later, once empty function is created.
+
   // Please note that the prototype property for function instances must be
   // writable.
-  Handle<DescriptorArray> function_map_descriptors =
-      ComputeFunctionInstanceDescriptor(ADD_WRITEABLE_PROTOTYPE);
-  fm->set_instance_descriptors(*function_map_descriptors);
-  fm->set_function_with_prototype(true);
+  global_context()->set_function_instance_map(
+      *CreateFunctionMap(ADD_WRITEABLE_PROTOTYPE));
 
   // Functions with this map will not have a 'prototype' property, and
   // can not be used as constructors.
-  Handle<Map> function_without_prototype_map =
-      Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
   global_context()->set_function_without_prototype_map(
-      *function_without_prototype_map);
-  Handle<DescriptorArray> function_without_prototype_map_descriptors =
-      ComputeFunctionInstanceDescriptor(DONT_ADD_PROTOTYPE);
-  function_without_prototype_map->set_instance_descriptors(
-      *function_without_prototype_map_descriptors);
-  function_without_prototype_map->set_function_with_prototype(false);
+      *CreateFunctionMap(DONT_ADD_PROTOTYPE));
 
-  // 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(ADD_READONLY_PROTOTYPE);
-  fm->set_instance_descriptors(*function_map_descriptors);
-  fm->set_function_with_prototype(true);
+  // Allocate the function map. This map is temporary, used only for processing
+  // of builtins.
+  // Later the map is replaced with writable prototype map, allocated below.
+  global_context()->set_function_map(
+      *CreateFunctionMap(ADD_READONLY_PROTOTYPE));
 
-  Handle<String> object_name = Handle<String>(Heap::Object_symbol());
+  // The final map for functions. Writeable prototype.
+  // This map is installed in MakeFunctionInstancePrototypeWritable.
+  function_instance_map_writable_prototype_ =
+      CreateFunctionMap(ADD_WRITEABLE_PROTOTYPE);
+
+  Isolate* isolate = Isolate::Current();
+  Factory* factory = isolate->factory();
+  Heap* heap = isolate->heap();
+
+  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());
+        factory->NewFunction(object_name, factory->null_value());
     Handle<Map> object_function_map =
-        Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+        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);
+    Handle<JSObject> prototype = factory->NewJSObject(
+        isolate->object_function(),
+        TENURED);
 
     global_context()->set_initial_object_prototype(*prototype);
     SetPrototype(object_fun, prototype);
     object_function_map->
-      set_instance_descriptors(Heap::empty_descriptor_array());
+      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<String> symbol = factory->LookupAsciiSymbol("Empty");
   Handle<JSFunction> empty_function =
-      Factory::NewFunctionWithoutPrototype(symbol);
+      factory->NewFunctionWithoutPrototype(symbol, kNonStrictMode);
 
   // --- E m p t y ---
   Handle<Code> code =
-      Handle<Code>(Builtins::builtin(Builtins::EmptyFunction));
+      Handle<Code>(isolate->builtins()->builtin(
+          Builtins::kEmptyFunction));
   empty_function->set_code(*code);
   empty_function->shared()->set_code(*code);
-  Handle<String> source = Factory::NewStringFromAscii(CStrVector("() {}"));
-  Handle<Script> script = Factory::NewScript(source);
+  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();
+
+  // Set prototypes for the function maps.
   global_context()->function_map()->set_prototype(*empty_function);
   global_context()->function_instance_map()->set_prototype(*empty_function);
   global_context()->function_without_prototype_map()->
       set_prototype(*empty_function);
+  function_instance_map_writable_prototype_->set_prototype(*empty_function);
 
   // Allocate the function map first and then patch the prototype later
-  Handle<Map> empty_fm = Factory::CopyMapDropDescriptors(
+  Handle<Map> function_without_prototype_map(
+      global_context()->function_without_prototype_map());
+  Handle<Map> empty_fm = factory->CopyMapDropDescriptors(
       function_without_prototype_map);
   empty_fm->set_instance_descriptors(
-      *function_without_prototype_map_descriptors);
+      function_without_prototype_map->instance_descriptors());
   empty_fm->set_prototype(global_context()->object_function()->prototype());
   empty_function->set_map(*empty_fm);
   return empty_function;
 }
 
 
+Handle<DescriptorArray> Genesis::ComputeStrictFunctionInstanceDescriptor(
+    PrototypePropertyMode prototypeMode,
+    Handle<FixedArray> arguments,
+    Handle<FixedArray> caller) {
+  Factory* factory = Isolate::Current()->factory();
+  Handle<DescriptorArray> descriptors =
+      factory->NewDescriptorArray(prototypeMode == DONT_ADD_PROTOTYPE ? 4 : 5);
+  PropertyAttributes attributes = static_cast<PropertyAttributes>(
+      DONT_ENUM | DONT_DELETE | READ_ONLY);
+
+  {  // length
+    Handle<Proxy> proxy = factory->NewProxy(&Accessors::FunctionLength);
+    CallbacksDescriptor d(*factory->length_symbol(), *proxy, attributes);
+    descriptors->Set(0, &d);
+  }
+  {  // name
+    Handle<Proxy> proxy = factory->NewProxy(&Accessors::FunctionName);
+    CallbacksDescriptor d(*factory->name_symbol(), *proxy, attributes);
+    descriptors->Set(1, &d);
+  }
+  {  // arguments
+    CallbacksDescriptor d(*factory->arguments_symbol(), *arguments, attributes);
+    descriptors->Set(2, &d);
+  }
+  {  // caller
+    CallbacksDescriptor d(*factory->caller_symbol(), *caller, attributes);
+    descriptors->Set(3, &d);
+  }
+
+  // prototype
+  if (prototypeMode != DONT_ADD_PROTOTYPE) {
+    if (prototypeMode == ADD_WRITEABLE_PROTOTYPE) {
+      attributes = static_cast<PropertyAttributes>(attributes & ~READ_ONLY);
+    }
+    Handle<Proxy> proxy = factory->NewProxy(&Accessors::FunctionPrototype);
+    CallbacksDescriptor d(*factory->prototype_symbol(), *proxy, attributes);
+    descriptors->Set(4, &d);
+  }
+
+  descriptors->Sort();
+  return descriptors;
+}
+
+
+// ECMAScript 5th Edition, 13.2.3
+Handle<JSFunction> Genesis::CreateThrowTypeErrorFunction(
+    Builtins::Name builtin) {
+  Isolate* isolate = Isolate::Current();
+  Factory* factory = isolate->factory();
+
+  Handle<String> name = factory->LookupAsciiSymbol("ThrowTypeError");
+  Handle<JSFunction> throw_type_error =
+      factory->NewFunctionWithoutPrototype(name, kStrictMode);
+  Handle<Code> code = Handle<Code>(
+      isolate->builtins()->builtin(builtin));
+
+  throw_type_error->set_map(global_context()->strict_mode_function_map());
+  throw_type_error->set_code(*code);
+  throw_type_error->shared()->set_code(*code);
+  throw_type_error->shared()->DontAdaptArguments();
+
+  PreventExtensions(throw_type_error);
+
+  return throw_type_error;
+}
+
+
+Handle<Map> Genesis::CreateStrictModeFunctionMap(
+    PrototypePropertyMode prototype_mode,
+    Handle<JSFunction> empty_function,
+    Handle<FixedArray> arguments_callbacks,
+    Handle<FixedArray> caller_callbacks) {
+  Handle<Map> map = FACTORY->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
+  Handle<DescriptorArray> descriptors =
+      ComputeStrictFunctionInstanceDescriptor(prototype_mode,
+                                              arguments_callbacks,
+                                              caller_callbacks);
+  map->set_instance_descriptors(*descriptors);
+  map->set_function_with_prototype(prototype_mode != DONT_ADD_PROTOTYPE);
+  map->set_prototype(*empty_function);
+  return map;
+}
+
+
+void Genesis::CreateStrictModeFunctionMaps(Handle<JSFunction> empty) {
+  // Create the callbacks arrays for ThrowTypeError functions.
+  // The get/set callacks are filled in after the maps are created below.
+  Factory* factory = Isolate::Current()->factory();
+  Handle<FixedArray> arguments = factory->NewFixedArray(2, TENURED);
+  Handle<FixedArray> caller = factory->NewFixedArray(2, TENURED);
+
+  // Allocate map for the strict mode function instances.
+  global_context()->set_strict_mode_function_instance_map(
+      *CreateStrictModeFunctionMap(
+          ADD_WRITEABLE_PROTOTYPE, empty, arguments, caller));
+
+  // Allocate map for the prototype-less strict mode instances.
+  global_context()->set_strict_mode_function_without_prototype_map(
+      *CreateStrictModeFunctionMap(
+          DONT_ADD_PROTOTYPE, empty, arguments, caller));
+
+  // Allocate map for the strict mode functions. This map is temporary, used
+  // only for processing of builtins.
+  // Later the map is replaced with writable prototype map, allocated below.
+  global_context()->set_strict_mode_function_map(
+      *CreateStrictModeFunctionMap(
+          ADD_READONLY_PROTOTYPE, empty, arguments, caller));
+
+  // The final map for the strict mode functions. Writeable prototype.
+  // This map is installed in MakeFunctionInstancePrototypeWritable.
+  strict_mode_function_instance_map_writable_prototype_ =
+      CreateStrictModeFunctionMap(
+          ADD_WRITEABLE_PROTOTYPE, empty, arguments, caller);
+
+  // Create the ThrowTypeError function instances.
+  Handle<JSFunction> arguments_throw =
+      CreateThrowTypeErrorFunction(Builtins::kStrictFunctionArguments);
+  Handle<JSFunction> caller_throw =
+      CreateThrowTypeErrorFunction(Builtins::kStrictFunctionCaller);
+
+  // Complete the callback fixed arrays.
+  arguments->set(0, *arguments_throw);
+  arguments->set(1, *arguments_throw);
+  caller->set(0, *caller_throw);
+  caller->set(1, *caller_throw);
+}
+
+
 static void AddToWeakGlobalContextList(Context* context) {
   ASSERT(context->IsGlobalContext());
+  Heap* heap = Isolate::Current()->heap();
 #ifdef DEBUG
   { // NOLINT
     ASSERT(context->get(Context::NEXT_CONTEXT_LINK)->IsUndefined());
     // Check that context is not in the list yet.
-    for (Object* current = Heap::global_contexts_list();
+    for (Object* current = heap->global_contexts_list();
          !current->IsUndefined();
          current = Context::cast(current)->get(Context::NEXT_CONTEXT_LINK)) {
       ASSERT(current != context);
     }
   }
 #endif
-  context->set(Context::NEXT_CONTEXT_LINK, Heap::global_contexts_list());
-  Heap::set_global_contexts_list(context);
+  context->set(Context::NEXT_CONTEXT_LINK, heap->global_contexts_list());
+  heap->set_global_contexts_list(context);
 }
 
 
 void Genesis::CreateRoots() {
+  Isolate* isolate = Isolate::Current();
   // 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()));
+  global_context_ = Handle<Context>::cast(isolate->global_handles()->Create(
+              *isolate->factory()->NewGlobalContext()));
   AddToWeakGlobalContextList(*global_context_);
-  Top::set_context(*global_context());
+  isolate->set_context(*global_context());
 
   // Allocate the message listeners object.
   {
@@ -569,11 +685,16 @@
     }
   }
 
+  Isolate* isolate = Isolate::Current();
+  Factory* factory = isolate->factory();
+  Heap* heap = isolate->heap();
+
   if (js_global_template.is_null()) {
-    Handle<String> name = Handle<String>(Heap::empty_symbol());
-    Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
+    Handle<String> name = Handle<String>(heap->empty_symbol());
+    Handle<Code> code = Handle<Code>(isolate->builtins()->builtin(
+        Builtins::kIllegal));
     js_global_function =
-        Factory::NewFunction(name, JS_GLOBAL_OBJECT_TYPE,
+        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.
@@ -581,18 +702,21 @@
         Handle<JSObject>(
             JSObject::cast(js_global_function->instance_prototype()));
     SetLocalPropertyNoThrow(
-        prototype, Factory::constructor_symbol(), Top::object_function(), NONE);
+        prototype,
+        factory->constructor_symbol(),
+        isolate->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);
+        factory->CreateApiFunction(js_global_constructor,
+                                   factory->InnerGlobalObject);
   }
 
   js_global_function->initial_map()->set_is_hidden_prototype();
   Handle<GlobalObject> inner_global =
-      Factory::NewGlobalObject(js_global_function);
+      factory->NewGlobalObject(js_global_function);
   if (inner_global_out != NULL) {
     *inner_global_out = inner_global;
   }
@@ -600,10 +724,11 @@
   // Step 2: create or re-initialize the global proxy object.
   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));
+    Handle<String> name = Handle<String>(heap->empty_symbol());
+    Handle<Code> code = Handle<Code>(isolate->builtins()->builtin(
+        Builtins::kIllegal));
     global_proxy_function =
-        Factory::NewFunction(name, JS_GLOBAL_PROXY_TYPE,
+        factory->NewFunction(name, JS_GLOBAL_PROXY_TYPE,
                              JSGlobalProxy::kSize, code, true);
   } else {
     Handle<ObjectTemplateInfo> data =
@@ -611,11 +736,11 @@
     Handle<FunctionTemplateInfo> global_constructor(
             FunctionTemplateInfo::cast(data->constructor()));
     global_proxy_function =
-        Factory::CreateApiFunction(global_constructor,
-                                   Factory::OuterGlobalObject);
+        factory->CreateApiFunction(global_constructor,
+                                   factory->OuterGlobalObject);
   }
 
-  Handle<String> global_name = Factory::LookupAsciiSymbol("global");
+  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);
 
@@ -629,7 +754,7 @@
         Handle<JSGlobalProxy>::cast(global_object));
   } else {
     return Handle<JSGlobalProxy>::cast(
-        Factory::NewJSObject(global_proxy_function, TENURED));
+        factory->NewJSObject(global_proxy_function, TENURED));
   }
 }
 
@@ -654,7 +779,7 @@
   static const PropertyAttributes attributes =
       static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
   ForceSetProperty(builtins_global,
-                   Factory::LookupAsciiSymbol("global"),
+                   FACTORY->LookupAsciiSymbol("global"),
                    inner_global,
                    attributes);
   // Setup the reference from the global object to the builtins object.
@@ -682,33 +807,37 @@
   // object reinitialization.
   global_context()->set_security_token(*inner_global);
 
-  Handle<String> object_name = Handle<String>(Heap::Object_symbol());
+  Isolate* isolate = Isolate::Current();
+  Factory* factory = isolate->factory();
+  Heap* heap = isolate->heap();
+
+  Handle<String> object_name = Handle<String>(heap->Object_symbol());
   SetLocalPropertyNoThrow(inner_global, object_name,
-                          Top::object_function(), DONT_ENUM);
+                          isolate->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.
+                  empty_function, Builtins::kIllegal, 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);
+                        isolate->initial_object_prototype(),
+                        Builtins::kArrayCode, true);
     array_function->shared()->set_construct_stub(
-        Builtins::builtin(Builtins::ArrayConstructCode));
+        isolate->builtins()->builtin(Builtins::kArrayConstructCode));
     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),
+        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
@@ -725,33 +854,33 @@
   {  // --- 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);
+                        isolate->initial_object_prototype(),
+                        Builtins::kIllegal, 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);
+                        isolate->initial_object_prototype(),
+                        Builtins::kIllegal, 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);
+                        isolate->initial_object_prototype(),
+                        Builtins::kIllegal, true);
     string_fun->shared()->set_construct_stub(
-        Builtins::builtin(Builtins::StringConstructCode));
+        isolate->builtins()->builtin(Builtins::kStringConstructCode));
     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),
+        factory->CopyAppendProxyDescriptor(
+            factory->empty_descriptor_array(),
+            factory->length_symbol(),
+            factory->NewProxy(&Accessors::StringLength),
             static_cast<PropertyAttributes>(DONT_ENUM |
                                             DONT_DELETE |
                                             READ_ONLY));
@@ -765,8 +894,8 @@
     // Builtin functions for Date.prototype.
     Handle<JSFunction> date_fun =
         InstallFunction(global, "Date", JS_VALUE_TYPE, JSValue::kSize,
-                        Top::initial_object_prototype(), Builtins::Illegal,
-                        true);
+                        isolate->initial_object_prototype(),
+                        Builtins::kIllegal, true);
 
     global_context()->set_date_function(*date_fun);
   }
@@ -776,8 +905,8 @@
     // Builtin functions for RegExp.prototype.
     Handle<JSFunction> regexp_fun =
         InstallFunction(global, "RegExp", JS_REGEXP_TYPE, JSRegExp::kSize,
-                        Top::initial_object_prototype(), Builtins::Illegal,
-                        true);
+                        isolate->initial_object_prototype(),
+                        Builtins::kIllegal, true);
     global_context()->set_regexp_function(*regexp_fun);
 
     ASSERT(regexp_fun->has_initial_map());
@@ -785,13 +914,13 @@
 
     ASSERT_EQ(0, initial_map->inobject_properties());
 
-    Handle<DescriptorArray> descriptors = Factory::NewDescriptorArray(5);
+    Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(5);
     PropertyAttributes final =
         static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
     int enum_index = 0;
     {
       // ECMA-262, section 15.10.7.1.
-      FieldDescriptor field(Heap::source_symbol(),
+      FieldDescriptor field(heap->source_symbol(),
                             JSRegExp::kSourceFieldIndex,
                             final,
                             enum_index++);
@@ -799,7 +928,7 @@
     }
     {
       // ECMA-262, section 15.10.7.2.
-      FieldDescriptor field(Heap::global_symbol(),
+      FieldDescriptor field(heap->global_symbol(),
                             JSRegExp::kGlobalFieldIndex,
                             final,
                             enum_index++);
@@ -807,7 +936,7 @@
     }
     {
       // ECMA-262, section 15.10.7.3.
-      FieldDescriptor field(Heap::ignore_case_symbol(),
+      FieldDescriptor field(heap->ignore_case_symbol(),
                             JSRegExp::kIgnoreCaseFieldIndex,
                             final,
                             enum_index++);
@@ -815,7 +944,7 @@
     }
     {
       // ECMA-262, section 15.10.7.4.
-      FieldDescriptor field(Heap::multiline_symbol(),
+      FieldDescriptor field(heap->multiline_symbol(),
                             JSRegExp::kMultilineFieldIndex,
                             final,
                             enum_index++);
@@ -825,7 +954,7 @@
       // ECMA-262, section 15.10.7.5.
       PropertyAttributes writable =
           static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
-      FieldDescriptor field(Heap::last_index_symbol(),
+      FieldDescriptor field(heap->last_index_symbol(),
                             JSRegExp::kLastIndexFieldIndex,
                             writable,
                             enum_index++);
@@ -844,13 +973,13 @@
   }
 
   {  // -- J S O N
-    Handle<String> name = Factory::NewStringFromAscii(CStrVector("JSON"));
-    Handle<JSFunction> cons = Factory::NewFunction(
+    Handle<String> name = factory->NewStringFromAscii(CStrVector("JSON"));
+    Handle<JSFunction> cons = factory->NewFunction(
         name,
-        Factory::the_hole_value());
+        factory->the_hole_value());
     cons->SetInstancePrototype(global_context()->initial_object_prototype());
     cons->SetInstanceClassName(*name);
-    Handle<JSObject> json_object = Factory::NewJSObject(cons, TENURED);
+    Handle<JSObject> json_object = factory->NewJSObject(cons, TENURED);
     ASSERT(json_object->IsJSObject());
     SetLocalPropertyNoThrow(global, name, json_object, DONT_ENUM);
     global_context()->set_json_object(*json_object);
@@ -860,14 +989,15 @@
     // 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<String> symbol = factory->LookupAsciiSymbol("Arguments");
+    Handle<Code> code = Handle<Code>(
+        isolate->builtins()->builtin(Builtins::kIllegal));
     Handle<JSObject> prototype =
         Handle<JSObject>(
             JSObject::cast(global_context()->object_function()->prototype()));
 
     Handle<JSFunction> function =
-        Factory::NewFunctionWithPrototype(symbol,
+        factory->NewFunctionWithPrototype(symbol,
                                           JS_OBJECT_TYPE,
                                           JSObject::kHeaderSize,
                                           prototype,
@@ -876,30 +1006,101 @@
     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);
+    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.
-    SetLocalPropertyNoThrow(result, Factory::callee_symbol(),
-                            Factory::undefined_value(),
+    // Note: length must be added as the first property and
+    //       callee must be added as the second property.
+    SetLocalPropertyNoThrow(result, factory->length_symbol(),
+                            factory->undefined_value(),
                             DONT_ENUM);
-    SetLocalPropertyNoThrow(result, Factory::length_symbol(),
-                            Factory::undefined_value(),
+    SetLocalPropertyNoThrow(result, factory->callee_symbol(),
+                            factory->undefined_value(),
                             DONT_ENUM);
 
 #ifdef DEBUG
     LookupResult lookup;
-    result->LocalLookup(Heap::callee_symbol(), &lookup);
+    result->LocalLookup(heap->callee_symbol(), &lookup);
     ASSERT(lookup.IsProperty() && (lookup.type() == FIELD));
-    ASSERT(lookup.GetFieldIndex() == Heap::arguments_callee_index);
+    ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsCalleeIndex);
 
-    result->LocalLookup(Heap::length_symbol(), &lookup);
+    result->LocalLookup(heap->length_symbol(), &lookup);
     ASSERT(lookup.IsProperty() && (lookup.type() == FIELD));
-    ASSERT(lookup.GetFieldIndex() == Heap::arguments_length_index);
+    ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsLengthIndex);
 
-    ASSERT(result->map()->inobject_properties() > Heap::arguments_callee_index);
-    ASSERT(result->map()->inobject_properties() > Heap::arguments_length_index);
+    ASSERT(result->map()->inobject_properties() > Heap::kArgumentsCalleeIndex);
+    ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex);
+
+    // Check the state of the object.
+    ASSERT(result->HasFastProperties());
+    ASSERT(result->HasFastElements());
+#endif
+  }
+
+  {  // --- strict mode arguments boilerplate
+    const PropertyAttributes attributes =
+      static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
+
+    // Create the ThrowTypeError functions.
+    Handle<FixedArray> callee = factory->NewFixedArray(2, TENURED);
+    Handle<FixedArray> caller = factory->NewFixedArray(2, TENURED);
+
+    Handle<JSFunction> callee_throw =
+        CreateThrowTypeErrorFunction(Builtins::kStrictArgumentsCallee);
+    Handle<JSFunction> caller_throw =
+        CreateThrowTypeErrorFunction(Builtins::kStrictArgumentsCaller);
+
+    // Install the ThrowTypeError functions.
+    callee->set(0, *callee_throw);
+    callee->set(1, *callee_throw);
+    caller->set(0, *caller_throw);
+    caller->set(1, *caller_throw);
+
+    // Create the descriptor array for the arguments object.
+    Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(3);
+    {  // length
+      FieldDescriptor d(*factory->length_symbol(), 0, DONT_ENUM);
+      descriptors->Set(0, &d);
+    }
+    {  // callee
+      CallbacksDescriptor d(*factory->callee_symbol(), *callee, attributes);
+      descriptors->Set(1, &d);
+    }
+    {  // caller
+      CallbacksDescriptor d(*factory->caller_symbol(), *caller, attributes);
+      descriptors->Set(2, &d);
+    }
+    descriptors->Sort();
+
+    // Create the map. Allocate one in-object field for length.
+    Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE,
+                                      Heap::kArgumentsObjectSizeStrict);
+    map->set_instance_descriptors(*descriptors);
+    map->set_function_with_prototype(true);
+    map->set_prototype(global_context()->object_function()->prototype());
+    map->set_pre_allocated_property_fields(1);
+    map->set_inobject_properties(1);
+
+    // Copy constructor from the non-strict arguments boilerplate.
+    map->set_constructor(
+      global_context()->arguments_boilerplate()->map()->constructor());
+
+    // Allocate the arguments boilerplate object.
+    Handle<JSObject> result = factory->NewJSObjectFromMap(map);
+    global_context()->set_strict_mode_arguments_boilerplate(*result);
+
+    // Add length property only for strict mode boilerplate.
+    SetLocalPropertyNoThrow(result, factory->length_symbol(),
+                            factory->undefined_value(),
+                            DONT_ENUM);
+
+#ifdef DEBUG
+    LookupResult lookup;
+    result->LocalLookup(heap->length_symbol(), &lookup);
+    ASSERT(lookup.IsProperty() && (lookup.type() == FIELD));
+    ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsLengthIndex);
+
+    ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex);
 
     // Check the state of the object.
     ASSERT(result->HasFastProperties());
@@ -909,15 +1110,16 @@
 
   {  // --- context extension
     // Create a function for the context extension objects.
-    Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
+    Handle<Code> code = Handle<Code>(
+        isolate->builtins()->builtin(Builtins::kIllegal));
     Handle<JSFunction> context_extension_fun =
-        Factory::NewFunction(Factory::empty_symbol(),
+        factory->NewFunction(factory->empty_symbol(),
                              JS_CONTEXT_EXTENSION_OBJECT_TYPE,
                              JSObject::kHeaderSize,
                              code,
                              true);
 
-    Handle<String> name = Factory::LookupAsciiSymbol("context_extension");
+    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);
   }
@@ -926,9 +1128,10 @@
   {
     // Setup the call-as-function delegate.
     Handle<Code> code =
-        Handle<Code>(Builtins::builtin(Builtins::HandleApiCallAsFunction));
+        Handle<Code>(isolate->builtins()->builtin(
+            Builtins::kHandleApiCallAsFunction));
     Handle<JSFunction> delegate =
-        Factory::NewFunction(Factory::empty_symbol(), JS_OBJECT_TYPE,
+        factory->NewFunction(factory->empty_symbol(), JS_OBJECT_TYPE,
                              JSObject::kHeaderSize, code, true);
     global_context()->set_call_as_function_delegate(*delegate);
     delegate->shared()->DontAdaptArguments();
@@ -937,44 +1140,47 @@
   {
     // Setup the call-as-constructor delegate.
     Handle<Code> code =
-        Handle<Code>(Builtins::builtin(Builtins::HandleApiCallAsConstructor));
+        Handle<Code>(isolate->builtins()->builtin(
+            Builtins::kHandleApiCallAsConstructor));
     Handle<JSFunction> delegate =
-        Factory::NewFunction(Factory::empty_symbol(), JS_OBJECT_TYPE,
+        factory->NewFunction(factory->empty_symbol(), JS_OBJECT_TYPE,
                              JSObject::kHeaderSize, code, true);
     global_context()->set_call_as_constructor_delegate(*delegate);
     delegate->shared()->DontAdaptArguments();
   }
 
   // Initialize the out of memory slot.
-  global_context()->set_out_of_memory(Heap::false_value());
+  global_context()->set_out_of_memory(heap->false_value());
 
   // Initialize the data slot.
-  global_context()->set_data(Heap::undefined_value());
+  global_context()->set_data(heap->undefined_value());
 }
 
 
 bool Genesis::CompileBuiltin(int index) {
   Vector<const char> name = Natives::GetScriptName(index);
-  Handle<String> source_code = Bootstrapper::NativesSourceLookup(index);
+  Handle<String> source_code =
+      Isolate::Current()->bootstrapper()->NativesSourceLookup(index);
   return CompileNative(name, source_code);
 }
 
 
 bool Genesis::CompileNative(Vector<const char> name, Handle<String> source) {
   HandleScope scope;
+  Isolate* isolate = Isolate::Current();
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  Debugger::set_compiling_natives(true);
+  isolate->debugger()->set_compiling_natives(true);
 #endif
   bool result = CompileScriptCached(name,
                                     source,
                                     NULL,
                                     NULL,
-                                    Handle<Context>(Top::context()),
+                                    Handle<Context>(isolate->context()),
                                     true);
-  ASSERT(Top::has_pending_exception() != result);
-  if (!result) Top::clear_pending_exception();
+  ASSERT(isolate->has_pending_exception() != result);
+  if (!result) isolate->clear_pending_exception();
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  Debugger::set_compiling_natives(false);
+  isolate->debugger()->set_compiling_natives(false);
 #endif
   return result;
 }
@@ -986,6 +1192,7 @@
                                   v8::Extension* extension,
                                   Handle<Context> top_context,
                                   bool use_runtime_context) {
+  Factory* factory = Isolate::Current()->factory();
   HandleScope scope;
   Handle<SharedFunctionInfo> function_info;
 
@@ -993,7 +1200,7 @@
   // function and insert it into the cache.
   if (cache == NULL || !cache->Lookup(name, &function_info)) {
     ASSERT(source->IsAsciiRepresentation());
-    Handle<String> script_name = Factory::NewStringFromUtf8(name);
+    Handle<String> script_name = factory->NewStringFromUtf8(name);
     function_info = Compiler::Compile(
         source,
         script_name,
@@ -1016,7 +1223,7 @@
                       ? Handle<Context>(top_context->runtime_context())
                       : top_context);
   Handle<JSFunction> fun =
-      Factory::NewFunctionFromSharedFunctionInfo(function_info, context);
+      factory->NewFunctionFromSharedFunctionInfo(function_info, context);
 
   // Call function using either the runtime object or the global
   // object as the receiver. Provide no parameters.
@@ -1033,11 +1240,13 @@
 
 
 #define INSTALL_NATIVE(Type, name, var)                                     \
-  Handle<String> var##_name = Factory::LookupAsciiSymbol(name);             \
+  Handle<String> var##_name = factory->LookupAsciiSymbol(name);             \
   global_context()->set_##var(Type::cast(                                   \
       global_context()->builtins()->GetPropertyNoExceptionThrown(*var##_name)));
 
+
 void Genesis::InstallNativeFunctions() {
+  Factory* factory = Isolate::Current()->factory();
   HandleScope scope;
   INSTALL_NATIVE(JSFunction, "CreateDate", create_date_fun);
   INSTALL_NATIVE(JSFunction, "ToNumber", to_number_fun);
@@ -1060,21 +1269,25 @@
 
 bool Genesis::InstallNatives() {
   HandleScope scope;
+  Isolate* isolate = Isolate::Current();
+  Factory* factory = isolate->factory();
+  Heap* heap = isolate->heap();
 
   // 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<Code> code = Handle<Code>(
+      isolate->builtins()->builtin(Builtins::kIllegal));
   Handle<JSFunction> builtins_fun =
-      Factory::NewFunction(Factory::empty_symbol(), JS_BUILTINS_OBJECT_TYPE,
+      factory->NewFunction(factory->empty_symbol(), JS_BUILTINS_OBJECT_TYPE,
                            JSBuiltinsObject::kSize, code, true);
 
-  Handle<String> name = Factory::LookupAsciiSymbol("builtins");
+  Handle<String> name = factory->LookupAsciiSymbol("builtins");
   builtins_fun->shared()->set_instance_class_name(*name);
 
   // Allocate the builtins object.
   Handle<JSBuiltinsObject> builtins =
-      Handle<JSBuiltinsObject>::cast(Factory::NewGlobalObject(builtins_fun));
+      Handle<JSBuiltinsObject>::cast(factory->NewGlobalObject(builtins_fun));
   builtins->set_builtins(*builtins);
   builtins->set_global_context(*global_context());
   builtins->set_global_receiver(*builtins);
@@ -1085,7 +1298,7 @@
   // global object.
   static const PropertyAttributes attributes =
       static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
-  Handle<String> global_symbol = Factory::LookupAsciiSymbol("global");
+  Handle<String> global_symbol = factory->LookupAsciiSymbol("global");
   Handle<Object> global_obj(global_context()->global());
   SetLocalPropertyNoThrow(builtins, global_symbol, global_obj, attributes);
 
@@ -1094,12 +1307,12 @@
 
   // 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());
+      factory->NewFunction(factory->empty_symbol(), factory->undefined_value());
+  ASSERT(bridge->context() == *isolate->global_context());
 
   // Allocate the builtins context.
   Handle<Context> context =
-    Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, bridge);
+    factory->NewFunctionContext(Context::MIN_CONTEXT_SLOTS, bridge);
   context->set_global(*builtins);  // override builtins global object
 
   global_context()->set_runtime_context(*context);
@@ -1108,113 +1321,113 @@
     // Builtin functions for Script.
     Handle<JSFunction> script_fun =
         InstallFunction(builtins, "Script", JS_VALUE_TYPE, JSValue::kSize,
-                        Top::initial_object_prototype(), Builtins::Illegal,
-                        false);
+                        isolate->initial_object_prototype(),
+                        Builtins::kIllegal, false);
     Handle<JSObject> prototype =
-        Factory::NewJSObject(Top::object_function(), TENURED);
+        factory->NewJSObject(isolate->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<Proxy> proxy_source = factory->NewProxy(&Accessors::ScriptSource);
     Handle<DescriptorArray> script_descriptors =
-        Factory::CopyAppendProxyDescriptor(
-            Factory::empty_descriptor_array(),
-            Factory::LookupAsciiSymbol("source"),
+        factory->CopyAppendProxyDescriptor(
+            factory->empty_descriptor_array(),
+            factory->LookupAsciiSymbol("source"),
             proxy_source,
             common_attributes);
-    Handle<Proxy> proxy_name = Factory::NewProxy(&Accessors::ScriptName);
+    Handle<Proxy> proxy_name = factory->NewProxy(&Accessors::ScriptName);
     script_descriptors =
-        Factory::CopyAppendProxyDescriptor(
+        factory->CopyAppendProxyDescriptor(
             script_descriptors,
-            Factory::LookupAsciiSymbol("name"),
+            factory->LookupAsciiSymbol("name"),
             proxy_name,
             common_attributes);
-    Handle<Proxy> proxy_id = Factory::NewProxy(&Accessors::ScriptId);
+    Handle<Proxy> proxy_id = factory->NewProxy(&Accessors::ScriptId);
     script_descriptors =
-        Factory::CopyAppendProxyDescriptor(
+        factory->CopyAppendProxyDescriptor(
             script_descriptors,
-            Factory::LookupAsciiSymbol("id"),
+            factory->LookupAsciiSymbol("id"),
             proxy_id,
             common_attributes);
     Handle<Proxy> proxy_line_offset =
-        Factory::NewProxy(&Accessors::ScriptLineOffset);
+        factory->NewProxy(&Accessors::ScriptLineOffset);
     script_descriptors =
-        Factory::CopyAppendProxyDescriptor(
+        factory->CopyAppendProxyDescriptor(
             script_descriptors,
-            Factory::LookupAsciiSymbol("line_offset"),
+            factory->LookupAsciiSymbol("line_offset"),
             proxy_line_offset,
             common_attributes);
     Handle<Proxy> proxy_column_offset =
-        Factory::NewProxy(&Accessors::ScriptColumnOffset);
+        factory->NewProxy(&Accessors::ScriptColumnOffset);
     script_descriptors =
-        Factory::CopyAppendProxyDescriptor(
+        factory->CopyAppendProxyDescriptor(
             script_descriptors,
-            Factory::LookupAsciiSymbol("column_offset"),
+            factory->LookupAsciiSymbol("column_offset"),
             proxy_column_offset,
             common_attributes);
-    Handle<Proxy> proxy_data = Factory::NewProxy(&Accessors::ScriptData);
+    Handle<Proxy> proxy_data = factory->NewProxy(&Accessors::ScriptData);
     script_descriptors =
-        Factory::CopyAppendProxyDescriptor(
+        factory->CopyAppendProxyDescriptor(
             script_descriptors,
-            Factory::LookupAsciiSymbol("data"),
+            factory->LookupAsciiSymbol("data"),
             proxy_data,
             common_attributes);
-    Handle<Proxy> proxy_type = Factory::NewProxy(&Accessors::ScriptType);
+    Handle<Proxy> proxy_type = factory->NewProxy(&Accessors::ScriptType);
     script_descriptors =
-        Factory::CopyAppendProxyDescriptor(
+        factory->CopyAppendProxyDescriptor(
             script_descriptors,
-            Factory::LookupAsciiSymbol("type"),
+            factory->LookupAsciiSymbol("type"),
             proxy_type,
             common_attributes);
     Handle<Proxy> proxy_compilation_type =
-        Factory::NewProxy(&Accessors::ScriptCompilationType);
+        factory->NewProxy(&Accessors::ScriptCompilationType);
     script_descriptors =
-        Factory::CopyAppendProxyDescriptor(
+        factory->CopyAppendProxyDescriptor(
             script_descriptors,
-            Factory::LookupAsciiSymbol("compilation_type"),
+            factory->LookupAsciiSymbol("compilation_type"),
             proxy_compilation_type,
             common_attributes);
     Handle<Proxy> proxy_line_ends =
-        Factory::NewProxy(&Accessors::ScriptLineEnds);
+        factory->NewProxy(&Accessors::ScriptLineEnds);
     script_descriptors =
-        Factory::CopyAppendProxyDescriptor(
+        factory->CopyAppendProxyDescriptor(
             script_descriptors,
-            Factory::LookupAsciiSymbol("line_ends"),
+            factory->LookupAsciiSymbol("line_ends"),
             proxy_line_ends,
             common_attributes);
     Handle<Proxy> proxy_context_data =
-        Factory::NewProxy(&Accessors::ScriptContextData);
+        factory->NewProxy(&Accessors::ScriptContextData);
     script_descriptors =
-        Factory::CopyAppendProxyDescriptor(
+        factory->CopyAppendProxyDescriptor(
             script_descriptors,
-            Factory::LookupAsciiSymbol("context_data"),
+            factory->LookupAsciiSymbol("context_data"),
             proxy_context_data,
             common_attributes);
     Handle<Proxy> proxy_eval_from_script =
-        Factory::NewProxy(&Accessors::ScriptEvalFromScript);
+        factory->NewProxy(&Accessors::ScriptEvalFromScript);
     script_descriptors =
-        Factory::CopyAppendProxyDescriptor(
+        factory->CopyAppendProxyDescriptor(
             script_descriptors,
-            Factory::LookupAsciiSymbol("eval_from_script"),
+            factory->LookupAsciiSymbol("eval_from_script"),
             proxy_eval_from_script,
             common_attributes);
     Handle<Proxy> proxy_eval_from_script_position =
-        Factory::NewProxy(&Accessors::ScriptEvalFromScriptPosition);
+        factory->NewProxy(&Accessors::ScriptEvalFromScriptPosition);
     script_descriptors =
-        Factory::CopyAppendProxyDescriptor(
+        factory->CopyAppendProxyDescriptor(
             script_descriptors,
-            Factory::LookupAsciiSymbol("eval_from_script_position"),
+            factory->LookupAsciiSymbol("eval_from_script_position"),
             proxy_eval_from_script_position,
             common_attributes);
     Handle<Proxy> proxy_eval_from_function_name =
-        Factory::NewProxy(&Accessors::ScriptEvalFromFunctionName);
+        factory->NewProxy(&Accessors::ScriptEvalFromFunctionName);
     script_descriptors =
-        Factory::CopyAppendProxyDescriptor(
+        factory->CopyAppendProxyDescriptor(
             script_descriptors,
-            Factory::LookupAsciiSymbol("eval_from_function_name"),
+            factory->LookupAsciiSymbol("eval_from_function_name"),
             proxy_eval_from_function_name,
             common_attributes);
 
@@ -1222,9 +1435,9 @@
     script_map->set_instance_descriptors(*script_descriptors);
 
     // Allocate the empty script.
-    Handle<Script> script = Factory::NewScript(Factory::empty_string());
+    Handle<Script> script = factory->NewScript(factory->empty_string());
     script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
-    Heap::public_set_empty_script(*script);
+    heap->public_set_empty_script(*script);
   }
   {
     // Builtin function for OpaqueReference -- a JSValue-based object,
@@ -1232,10 +1445,11 @@
     // objects, that JavaScript code may not access.
     Handle<JSFunction> opaque_reference_fun =
         InstallFunction(builtins, "OpaqueReference", JS_VALUE_TYPE,
-                        JSValue::kSize, Top::initial_object_prototype(),
-                        Builtins::Illegal, false);
+                        JSValue::kSize,
+                        isolate->initial_object_prototype(),
+                        Builtins::kIllegal, false);
     Handle<JSObject> prototype =
-        Factory::NewJSObject(Top::object_function(), TENURED);
+        factory->NewJSObject(isolate->object_function(), TENURED);
     SetPrototype(opaque_reference_fun, prototype);
     global_context()->set_opaque_reference_function(*opaque_reference_fun);
   }
@@ -1254,23 +1468,23 @@
                         "InternalArray",
                         JS_ARRAY_TYPE,
                         JSArray::kSize,
-                        Top::initial_object_prototype(),
-                        Builtins::ArrayCode,
+                        isolate->initial_object_prototype(),
+                        Builtins::kArrayCode,
                         true);
     Handle<JSObject> prototype =
-        Factory::NewJSObject(Top::object_function(), TENURED);
+        factory->NewJSObject(isolate->object_function(), TENURED);
     SetPrototype(array_function, prototype);
 
     array_function->shared()->set_construct_stub(
-        Builtins::builtin(Builtins::ArrayConstructCode));
+        isolate->builtins()->builtin(Builtins::kArrayConstructCode));
     array_function->shared()->DontAdaptArguments();
 
     // Make "length" magic on instances.
     Handle<DescriptorArray> array_descriptors =
-        Factory::CopyAppendProxyDescriptor(
-            Factory::empty_descriptor_array(),
-            Factory::length_symbol(),
-            Factory::NewProxy(&Accessors::ArrayLength),
+        factory->CopyAppendProxyDescriptor(
+            factory->empty_descriptor_array(),
+            factory->length_symbol(),
+            factory->NewProxy(&Accessors::ArrayLength),
             static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE));
 
     array_function->initial_map()->set_instance_descriptors(
@@ -1307,9 +1521,9 @@
   InstallBuiltinFunctionIds();
 
   // Install Function.prototype.call and apply.
-  { Handle<String> key = Factory::function_class_symbol();
+  { Handle<String> key = factory->function_class_symbol();
     Handle<JSFunction> function =
-        Handle<JSFunction>::cast(GetProperty(Top::global(), key));
+        Handle<JSFunction>::cast(GetProperty(isolate->global(), key));
     Handle<JSObject> proto =
         Handle<JSObject>(JSObject::cast(function->instance_prototype()));
 
@@ -1317,12 +1531,12 @@
     Handle<JSFunction> call =
         InstallFunction(proto, "call", JS_OBJECT_TYPE, JSObject::kHeaderSize,
                         Handle<JSObject>::null(),
-                        Builtins::FunctionCall,
+                        Builtins::kFunctionCall,
                         false);
     Handle<JSFunction> apply =
         InstallFunction(proto, "apply", JS_OBJECT_TYPE, JSObject::kHeaderSize,
                         Handle<JSObject>::null(),
-                        Builtins::FunctionApply,
+                        Builtins::kFunctionApply,
                         false);
 
     // Make sure that Function.prototype.call appears to be compiled.
@@ -1351,7 +1565,7 @@
 
     // Add initial map.
     Handle<Map> initial_map =
-        Factory::NewMap(JS_ARRAY_TYPE, JSRegExpResult::kSize);
+        factory->NewMap(JS_ARRAY_TYPE, JSRegExpResult::kSize);
     initial_map->set_constructor(*array_constructor);
 
     // Set prototype on map.
@@ -1365,13 +1579,13 @@
     ASSERT_EQ(1, array_descriptors->number_of_descriptors());
 
     Handle<DescriptorArray> reresult_descriptors =
-        Factory::NewDescriptorArray(3);
+        factory->NewDescriptorArray(3);
 
     reresult_descriptors->CopyFrom(0, *array_descriptors, 0);
 
     int enum_index = 0;
     {
-      FieldDescriptor index_field(Heap::index_symbol(),
+      FieldDescriptor index_field(heap->index_symbol(),
                                   JSRegExpResult::kIndexIndex,
                                   NONE,
                                   enum_index++);
@@ -1379,7 +1593,7 @@
     }
 
     {
-      FieldDescriptor input_field(Heap::input_symbol(),
+      FieldDescriptor input_field(heap->input_symbol(),
                                   JSRegExpResult::kInputIndex,
                                   NONE,
                                   enum_index++);
@@ -1407,17 +1621,18 @@
 static Handle<JSObject> ResolveBuiltinIdHolder(
     Handle<Context> global_context,
     const char* holder_expr) {
+  Factory* factory = Isolate::Current()->factory();
   Handle<GlobalObject> global(global_context->global());
   const char* period_pos = strchr(holder_expr, '.');
   if (period_pos == NULL) {
     return Handle<JSObject>::cast(
-        GetProperty(global, Factory::LookupAsciiSymbol(holder_expr)));
+        GetProperty(global, factory->LookupAsciiSymbol(holder_expr)));
   }
   ASSERT_EQ(".prototype", period_pos);
   Vector<const char> property(holder_expr,
                               static_cast<int>(period_pos - holder_expr));
   Handle<JSFunction> function = Handle<JSFunction>::cast(
-      GetProperty(global, Factory::LookupSymbol(property)));
+      GetProperty(global, factory->LookupSymbol(property)));
   return Handle<JSObject>(JSObject::cast(function->prototype()));
 }
 
@@ -1425,7 +1640,7 @@
 static void InstallBuiltinFunctionId(Handle<JSObject> holder,
                                      const char* function_name,
                                      BuiltinFunctionId id) {
-  Handle<String> name = Factory::LookupAsciiSymbol(function_name);
+  Handle<String> name = FACTORY->LookupAsciiSymbol(function_name);
   Object* function_object = holder->GetProperty(*name)->ToObjectUnchecked();
   Handle<JSFunction> function(JSFunction::cast(function_object));
   function->shared()->set_function_data(Smi::FromInt(id));
@@ -1457,7 +1672,7 @@
   int array_size = JSFunctionResultCache::kEntriesIndex + 2 * size;
   // Cannot use cast as object is not fully initialized yet.
   JSFunctionResultCache* cache = reinterpret_cast<JSFunctionResultCache*>(
-      *Factory::NewFixedArrayWithHoles(array_size, TENURED));
+      *FACTORY->NewFixedArrayWithHoles(array_size, TENURED));
   cache->set(JSFunctionResultCache::kFactoryIndex, factory);
   cache->MakeZeroSize();
   return cache;
@@ -1471,7 +1686,7 @@
 #undef F
   ;
 
-  Handle<FixedArray> caches = Factory::NewFixedArray(kNumberOfCaches, TENURED);
+  Handle<FixedArray> caches = FACTORY->NewFixedArray(kNumberOfCaches, TENURED);
 
   int index = 0;
 
@@ -1490,19 +1705,17 @@
 
 void Genesis::InitializeNormalizedMapCaches() {
   Handle<FixedArray> array(
-      Factory::NewFixedArray(NormalizedMapCache::kEntries, TENURED));
+      FACTORY->NewFixedArray(NormalizedMapCache::kEntries, TENURED));
   global_context()->set_normalized_map_cache(NormalizedMapCache::cast(*array));
 }
 
 
-int BootstrapperActive::nesting_ = 0;
-
-
 bool Bootstrapper::InstallExtensions(Handle<Context> global_context,
                                      v8::ExtensionConfiguration* extensions) {
+  Isolate* isolate = Isolate::Current();
   BootstrapperActive active;
-  SaveContext saved_context;
-  Top::set_context(*global_context);
+  SaveContext saved_context(isolate);
+  isolate->set_context(*global_context);
   if (!Genesis::InstallExtensions(global_context, extensions)) return false;
   Genesis::InstallSpecialObjects(global_context);
   return true;
@@ -1510,20 +1723,21 @@
 
 
 void Genesis::InstallSpecialObjects(Handle<Context> global_context) {
+  Factory* factory = Isolate::Current()->factory();
   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);
+        factory->LookupAsciiSymbol(FLAG_expose_natives_as);
     SetLocalPropertyNoThrow(js_global, natives_string,
                             Handle<JSObject>(js_global->builtins()), DONT_ENUM);
   }
 
   Handle<Object> Error = GetProperty(js_global, "Error");
   if (Error->IsJSObject()) {
-    Handle<String> name = Factory::LookupAsciiSymbol("stackTraceLimit");
+    Handle<String> name = factory->LookupAsciiSymbol("stackTraceLimit");
     SetLocalPropertyNoThrow(Handle<JSObject>::cast(Error),
                             name,
                             Handle<Smi>(Smi::FromInt(FLAG_stack_trace_limit)),
@@ -1533,18 +1747,19 @@
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // 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) {
+    Debug* debug = Isolate::Current()->debug();
     // If loading fails we just bail out without installing the
     // debugger but without tanking the whole context.
-    if (!Debug::Load()) return;
+    if (!debug->Load()) return;
     // 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(
+    debug->debug_context()->set_security_token(
         global_context->security_token());
 
     Handle<String> debug_string =
-        Factory::LookupAsciiSymbol(FLAG_expose_debug_as);
-    Handle<Object> global_proxy(Debug::debug_context()->global_proxy());
+        factory->LookupAsciiSymbol(FLAG_expose_debug_as);
+    Handle<Object> global_proxy(debug->debug_context()->global_proxy());
     SetLocalPropertyNoThrow(js_global, debug_string, global_proxy, DONT_ENUM);
   }
 #endif
@@ -1553,6 +1768,10 @@
 
 bool Genesis::InstallExtensions(Handle<Context> global_context,
                                 v8::ExtensionConfiguration* extensions) {
+  // TODO(isolates): Extensions on multiple isolates may take a little more
+  //                 effort. (The external API reads 'ignore'-- does that mean
+  //                 we can break the interface?)
+
   // Clear coloring of extension list
   v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension();
   while (current != NULL) {
@@ -1620,17 +1839,18 @@
   for (int i = 0; i < extension->dependency_count(); i++) {
     if (!InstallExtension(extension->dependencies()[i])) return false;
   }
+  Isolate* isolate = Isolate::Current();
   Vector<const char> source = CStrVector(extension->source());
-  Handle<String> source_code = Factory::NewStringFromAscii(source);
+  Handle<String> source_code = isolate->factory()->NewStringFromAscii(source);
   bool result = CompileScriptCached(CStrVector(extension->name()),
                                     source_code,
-                                    &extensions_cache,
+                                    isolate->bootstrapper()->extensions_cache(),
                                     extension,
-                                    Handle<Context>(Top::context()),
+                                    Handle<Context>(isolate->context()),
                                     false);
-  ASSERT(Top::has_pending_exception() != result);
+  ASSERT(isolate->has_pending_exception() != result);
   if (!result) {
-    Top::clear_pending_exception();
+    isolate->clear_pending_exception();
   }
   current->set_state(v8::INSTALLED);
   return result;
@@ -1641,7 +1861,7 @@
   HandleScope scope;
   for (int i = 0; i < Builtins::NumberOfJavaScriptBuiltins(); i++) {
     Builtins::JavaScript id = static_cast<Builtins::JavaScript>(i);
-    Handle<String> name = Factory::LookupAsciiSymbol(Builtins::GetName(id));
+    Handle<String> name = FACTORY->LookupAsciiSymbol(Builtins::GetName(id));
     Object* function_object = builtins->GetPropertyNoExceptionThrown(*name);
     Handle<JSFunction> function
         = Handle<JSFunction>(JSFunction::cast(function_object));
@@ -1690,12 +1910,13 @@
   ASSERT(object->IsInstanceOf(
       FunctionTemplateInfo::cast(object_template->constructor())));
 
+  Isolate* isolate = Isolate::Current();
   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();
+    ASSERT(isolate->has_pending_exception());
+    isolate->clear_pending_exception();
     return false;
   }
   TransferObject(obj, object);
@@ -1743,6 +1964,7 @@
           break;
         }
         case MAP_TRANSITION:
+        case EXTERNAL_ARRAY_TRANSITION:
         case CONSTANT_TRANSITION:
         case NULL_DESCRIPTOR:
           // Ignore non-properties.
@@ -1786,7 +2008,7 @@
   // Cloning the elements array is sufficient.
   Handle<FixedArray> from_elements =
       Handle<FixedArray>(FixedArray::cast(from->elements()));
-  Handle<FixedArray> to_elements = Factory::CopyFixedArray(from_elements);
+  Handle<FixedArray> to_elements = FACTORY->CopyFixedArray(from_elements);
   to->set_elements(*to_elements);
 }
 
@@ -1802,29 +2024,31 @@
 
   // 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);
+  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;
+  // The maps with writable prototype are created in CreateEmptyFunction
+  // and CreateStrictModeFunctionMaps respectively. Initially the maps are
+  // created with read-only prototype for JS builtins processing.
+  ASSERT(!function_instance_map_writable_prototype_.is_null());
+  ASSERT(!strict_mode_function_instance_map_writable_prototype_.is_null());
 
-  Handle<DescriptorArray> function_map_descriptors =
-      ComputeFunctionInstanceDescriptor(ADD_WRITEABLE_PROTOTYPE);
-  Handle<Map> fm = Factory::CopyMapDropDescriptors(Top::function_map());
-  fm->set_instance_descriptors(*function_map_descriptors);
-  fm->set_function_with_prototype(true);
-  Top::context()->global_context()->set_function_map(*fm);
+  // Replace function instance maps to make prototype writable.
+  global_context()->set_function_map(
+    *function_instance_map_writable_prototype_);
+  global_context()->set_strict_mode_function_map(
+    *strict_mode_function_instance_map_writable_prototype_);
 }
 
 
 Genesis::Genesis(Handle<Object> global_object,
                  v8::Handle<v8::ObjectTemplate> global_template,
                  v8::ExtensionConfiguration* extensions) {
+  Isolate* isolate = Isolate::Current();
   result_ = Handle<Context>::null();
   // If V8 isn't running and cannot be initialized, just return.
   if (!V8::IsRunning() && !V8::Initialize(NULL)) return;
@@ -1832,18 +2056,15 @@
   // Before creating the roots we must save the context and restore it
   // on all function exits.
   HandleScope scope;
-  SaveContext saved_context;
+  SaveContext saved_context(isolate);
 
   Handle<Context> new_context = Snapshot::NewContextFromSnapshot();
   if (!new_context.is_null()) {
     global_context_ =
-      Handle<Context>::cast(GlobalHandles::Create(*new_context));
+        Handle<Context>::cast(isolate->global_handles()->Create(*new_context));
     AddToWeakGlobalContextList(*global_context_);
-    Top::set_context(*global_context_);
-    i::Counters::contexts_created_by_snapshot.Increment();
-    JSFunction* empty_function =
-        JSFunction::cast(global_context_->function_map()->prototype());
-    empty_function_ = Handle<JSFunction>(empty_function);
+    isolate->set_context(*global_context_);
+    isolate->counters()->contexts_created_by_snapshot()->Increment();
     Handle<GlobalObject> inner_global;
     Handle<JSGlobalProxy> global_proxy =
         CreateNewGlobals(global_template,
@@ -1858,6 +2079,7 @@
     // We get here if there was no context snapshot.
     CreateRoots();
     Handle<JSFunction> empty_function = CreateEmptyFunction();
+    CreateStrictModeFunctionMaps(empty_function);
     Handle<GlobalObject> inner_global;
     Handle<JSGlobalProxy> global_proxy =
         CreateNewGlobals(global_template, global_object, &inner_global);
@@ -1870,7 +2092,7 @@
     MakeFunctionInstancePrototypeWritable();
 
     if (!ConfigureGlobalObjects(global_template)) return;
-    i::Counters::contexts_created_from_scratch.Increment();
+    isolate->counters()->contexts_created_from_scratch()->Increment();
   }
 
   result_ = global_context_;
@@ -1881,46 +2103,28 @@
 
 // Reserve space for statics needing saving and restoring.
 int Bootstrapper::ArchiveSpacePerThread() {
-  return BootstrapperActive::ArchiveSpacePerThread();
+  return sizeof(NestingCounterType);
 }
 
 
 // Archive statics that are thread local.
 char* Bootstrapper::ArchiveState(char* to) {
-  return BootstrapperActive::ArchiveState(to);
+  *reinterpret_cast<NestingCounterType*>(to) = nesting_;
+  nesting_ = 0;
+  return to + sizeof(NestingCounterType);
 }
 
 
 // Restore statics that are thread local.
 char* Bootstrapper::RestoreState(char* from) {
-  return BootstrapperActive::RestoreState(from);
+  nesting_ = *reinterpret_cast<NestingCounterType*>(from);
+  return from + sizeof(NestingCounterType);
 }
 
 
 // Called when the top-level V8 mutex is destroyed.
 void Bootstrapper::FreeThreadResources() {
-  ASSERT(!BootstrapperActive::IsActive());
-}
-
-
-// Reserve space for statics needing saving and restoring.
-int BootstrapperActive::ArchiveSpacePerThread() {
-  return sizeof(nesting_);
-}
-
-
-// Archive statics that are thread local.
-char* BootstrapperActive::ArchiveState(char* to) {
-  *reinterpret_cast<int*>(to) = nesting_;
-  nesting_ = 0;
-  return to + sizeof(nesting_);
-}
-
-
-// Restore statics that are thread local.
-char* BootstrapperActive::RestoreState(char* from) {
-  nesting_ = *reinterpret_cast<int*>(from);
-  return from + sizeof(nesting_);
+  ASSERT(!IsActive());
 }
 
 } }  // namespace v8::internal
diff --git a/src/bootstrapper.h b/src/bootstrapper.h
index 2b789e2..3e158d6 100644
--- a/src/bootstrapper.h
+++ b/src/bootstrapper.h
@@ -33,73 +33,140 @@
 namespace internal {
 
 
-class BootstrapperActive BASE_EMBEDDED {
+// 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:
-  BootstrapperActive() { nesting_++; }
-  ~BootstrapperActive() { nesting_--; }
+  explicit SourceCodeCache(Script::Type type): type_(type), cache_(NULL) { }
 
-  // Support for thread preemption.
-  static int ArchiveSpacePerThread();
-  static char* ArchiveState(char* to);
-  static char* RestoreState(char* from);
+  void Initialize(bool create_heap_objects) {
+    cache_ = create_heap_objects ? HEAP->empty_fixed_array() : NULL;
+  }
+
+  void Iterate(ObjectVisitor* v) {
+    v->VisitPointer(BitCast<Object**, FixedArray**>(&cache_));
+  }
+
+  bool Lookup(Vector<const char> name, Handle<SharedFunctionInfo>* handle) {
+    for (int i = 0; i < cache_->length(); i+=2) {
+      SeqAsciiString* str = SeqAsciiString::cast(cache_->get(i));
+      if (str->IsEqualTo(name)) {
+        *handle = Handle<SharedFunctionInfo>(
+            SharedFunctionInfo::cast(cache_->get(i + 1)));
+        return true;
+      }
+    }
+    return false;
+  }
+
+  void Add(Vector<const char> name, Handle<SharedFunctionInfo> shared) {
+    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, *shared);
+    Script::cast(shared->script())->set_type(Smi::FromInt(type_));
+  }
 
  private:
-  static bool IsActive() { return nesting_ != 0; }
-  static int nesting_;
-  friend class Bootstrapper;
+  Script::Type type_;
+  FixedArray* cache_;
+  DISALLOW_COPY_AND_ASSIGN(SourceCodeCache);
 };
 
 
 // The Boostrapper is the public interface for creating a JavaScript global
 // context.
-class Bootstrapper : public AllStatic {
+class Bootstrapper {
  public:
   // Requires: Heap::Setup has been called.
-  static void Initialize(bool create_heap_objects);
-  static void TearDown();
+  void Initialize(bool create_heap_objects);
+  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<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);
+  void DetachGlobal(Handle<Context> env);
 
   // Reattach an outer global object to an environment.
-  static void ReattachGlobal(Handle<Context> env, Handle<Object> global_object);
+  void ReattachGlobal(Handle<Context> env, Handle<Object> global_object);
 
   // Traverses the pointers for memory management.
-  static void Iterate(ObjectVisitor* v);
+  void Iterate(ObjectVisitor* v);
 
   // Accessor for the native scripts source code.
-  static Handle<String> NativesSourceLookup(int index);
+  Handle<String> NativesSourceLookup(int index);
 
   // Tells whether bootstrapping is active.
-  static bool IsActive() { return BootstrapperActive::IsActive(); }
+  bool IsActive() const { return nesting_ != 0; }
 
   // Support for thread preemption.
-  static int ArchiveSpacePerThread();
-  static char* ArchiveState(char* to);
-  static char* RestoreState(char* from);
-  static void FreeThreadResources();
+  RLYSTC int ArchiveSpacePerThread();
+  char* ArchiveState(char* to);
+  char* RestoreState(char* from);
+  void FreeThreadResources();
 
   // This will allocate a char array that is deleted when V8 is shut down.
   // It should only be used for strictly finite allocations.
-  static char* AllocateAutoDeletedArray(int bytes);
+  char* AllocateAutoDeletedArray(int bytes);
 
   // Used for new context creation.
-  static bool InstallExtensions(Handle<Context> global_context,
-                                v8::ExtensionConfiguration* extensions);
+  bool InstallExtensions(Handle<Context> global_context,
+                         v8::ExtensionConfiguration* extensions);
+
+  SourceCodeCache* extensions_cache() { return &extensions_cache_; }
+
+ private:
+  typedef int NestingCounterType;
+  NestingCounterType nesting_;
+  SourceCodeCache extensions_cache_;
+  // This is for delete, not delete[].
+  List<char*>* delete_these_non_arrays_on_tear_down_;
+  // This is for delete[]
+  List<char*>* delete_these_arrays_on_tear_down_;
+
+  friend class BootstrapperActive;
+  friend class Isolate;
+  friend class NativesExternalStringResource;
+
+  Bootstrapper();
+
+  DISALLOW_COPY_AND_ASSIGN(Bootstrapper);
+};
+
+
+class BootstrapperActive BASE_EMBEDDED {
+ public:
+  BootstrapperActive() {
+    ++Isolate::Current()->bootstrapper()->nesting_;
+  }
+
+  ~BootstrapperActive() {
+    --Isolate::Current()->bootstrapper()->nesting_;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BootstrapperActive);
 };
 
 
 class NativesExternalStringResource
     : public v8::String::ExternalAsciiStringResource {
  public:
-  explicit NativesExternalStringResource(const char* source);
+  explicit NativesExternalStringResource(Bootstrapper* bootstrapper,
+                                         const char* source);
 
   const char* data() const {
     return data_;
diff --git a/src/builtins.cc b/src/builtins.cc
index 01e8deb..72f9d57 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -107,7 +107,6 @@
 
 }  // namespace
 
-
 // ----------------------------------------------------------------------------
 // Support macro for defining builtins in C++.
 // ----------------------------------------------------------------------------
@@ -123,26 +122,27 @@
 
 #ifdef DEBUG
 
-#define BUILTIN(name)                                                \
-  MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name(           \
-      name##ArgumentsType args);                                     \
-  MUST_USE_RESULT static MaybeObject* Builtin_##name(                \
-      name##ArgumentsType args) {     \
-    args.Verify();                                                   \
-    return Builtin_Impl_##name(args);                                \
-  }                                                                  \
-  MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name(           \
-    name##ArgumentsType args)
+#define BUILTIN(name)                                      \
+  MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \
+      name##ArgumentsType args, Isolate* isolate);         \
+  MUST_USE_RESULT static MaybeObject* Builtin_##name(      \
+      name##ArgumentsType args, Isolate* isolate) {        \
+    ASSERT(isolate == Isolate::Current());                 \
+    args.Verify();                                         \
+    return Builtin_Impl_##name(args, isolate);             \
+  }                                                        \
+  MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \
+      name##ArgumentsType args, Isolate* isolate)
 
 #else  // For release mode.
 
-#define BUILTIN(name)                                                \
-  static MaybeObject* Builtin_##name(name##ArgumentsType args)
+#define BUILTIN(name)                                      \
+  static MaybeObject* Builtin_##name(name##ArgumentsType args, Isolate* isolate)
 
 #endif
 
 
-static inline bool CalledAsConstructor() {
+static inline bool CalledAsConstructor(Isolate* isolate) {
 #ifdef DEBUG
   // Calculate the result using a full stack frame iterator and check
   // that the state of the stack is as we assume it to be in the
@@ -153,7 +153,7 @@
   StackFrame* frame = it.frame();
   bool reference_result = frame->is_construct();
 #endif
-  Address fp = Top::c_entry_fp(Top::GetCurrentThread());
+  Address fp = Isolate::c_entry_fp(isolate->thread_local_top());
   // Because we know fp points to an exit frame we can use the relevant
   // part of ExitFrame::ComputeCallerState directly.
   const int kCallerOffset = ExitFrameConstants::kCallerFPOffset;
@@ -172,30 +172,30 @@
 
 // ----------------------------------------------------------------------------
 
-
 BUILTIN(Illegal) {
   UNREACHABLE();
-  return Heap::undefined_value();  // Make compiler happy.
+  return isolate->heap()->undefined_value();  // Make compiler happy.
 }
 
 
 BUILTIN(EmptyFunction) {
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
 BUILTIN(ArrayCodeGeneric) {
-  Counters::array_function_runtime.Increment();
+  Heap* heap = isolate->heap();
+  isolate->counters()->array_function_runtime()->Increment();
 
   JSArray* array;
-  if (CalledAsConstructor()) {
+  if (CalledAsConstructor(isolate)) {
     array = JSArray::cast(*args.receiver());
   } else {
     // Allocate the JS Array
     JSFunction* constructor =
-        Top::context()->global_context()->array_function();
+        isolate->context()->global_context()->array_function();
     Object* obj;
-    { MaybeObject* maybe_obj = Heap::AllocateJSObject(constructor);
+    { MaybeObject* maybe_obj = heap->AllocateJSObject(constructor);
       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
     }
     array = JSArray::cast(obj);
@@ -212,7 +212,7 @@
       int len = Smi::cast(obj)->value();
       if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) {
         Object* obj;
-        { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(len);
+        { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len);
           if (!maybe_obj->ToObject(&obj)) return maybe_obj;
         }
         array->SetContent(FixedArray::cast(obj));
@@ -235,7 +235,7 @@
   int number_of_elements = args.length() - 1;
   Smi* len = Smi::FromInt(number_of_elements);
   Object* obj;
-  { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(len->value());
+  { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len->value());
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
 
@@ -255,77 +255,81 @@
 }
 
 
-MUST_USE_RESULT static MaybeObject* AllocateJSArray() {
+MUST_USE_RESULT static MaybeObject* AllocateJSArray(Heap* heap) {
   JSFunction* array_function =
-      Top::context()->global_context()->array_function();
+      heap->isolate()->context()->global_context()->array_function();
   Object* result;
-  { MaybeObject* maybe_result = Heap::AllocateJSObject(array_function);
+  { MaybeObject* maybe_result = heap->AllocateJSObject(array_function);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   return result;
 }
 
 
-MUST_USE_RESULT static MaybeObject* AllocateEmptyJSArray() {
+MUST_USE_RESULT static MaybeObject* AllocateEmptyJSArray(Heap* heap) {
   Object* result;
-  { MaybeObject* maybe_result = AllocateJSArray();
+  { MaybeObject* maybe_result = AllocateJSArray(heap);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   JSArray* result_array = JSArray::cast(result);
   result_array->set_length(Smi::FromInt(0));
-  result_array->set_elements(Heap::empty_fixed_array());
+  result_array->set_elements(heap->empty_fixed_array());
   return result_array;
 }
 
 
-static void CopyElements(AssertNoAllocation* no_gc,
+static void CopyElements(Heap* heap,
+                         AssertNoAllocation* no_gc,
                          FixedArray* dst,
                          int dst_index,
                          FixedArray* src,
                          int src_index,
                          int len) {
   ASSERT(dst != src);  // Use MoveElements instead.
-  ASSERT(dst->map() != Heap::fixed_cow_array_map());
+  ASSERT(dst->map() != HEAP->fixed_cow_array_map());
   ASSERT(len > 0);
   CopyWords(dst->data_start() + dst_index,
             src->data_start() + src_index,
             len);
   WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc);
   if (mode == UPDATE_WRITE_BARRIER) {
-    Heap::RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len);
+    heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len);
   }
 }
 
 
-static void MoveElements(AssertNoAllocation* no_gc,
+static void MoveElements(Heap* heap,
+                         AssertNoAllocation* no_gc,
                          FixedArray* dst,
                          int dst_index,
                          FixedArray* src,
                          int src_index,
                          int len) {
-  ASSERT(dst->map() != Heap::fixed_cow_array_map());
+  ASSERT(dst->map() != HEAP->fixed_cow_array_map());
   memmove(dst->data_start() + dst_index,
           src->data_start() + src_index,
           len * kPointerSize);
   WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc);
   if (mode == UPDATE_WRITE_BARRIER) {
-    Heap::RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len);
+    heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len);
   }
 }
 
 
-static void FillWithHoles(FixedArray* dst, int from, int to) {
-  ASSERT(dst->map() != Heap::fixed_cow_array_map());
-  MemsetPointer(dst->data_start() + from, Heap::the_hole_value(), to - from);
+static void FillWithHoles(Heap* heap, FixedArray* dst, int from, int to) {
+  ASSERT(dst->map() != heap->fixed_cow_array_map());
+  MemsetPointer(dst->data_start() + from, heap->the_hole_value(), to - from);
 }
 
 
-static FixedArray* LeftTrimFixedArray(FixedArray* elms, int to_trim) {
-  ASSERT(elms->map() != Heap::fixed_cow_array_map());
+static FixedArray* LeftTrimFixedArray(Heap* heap,
+                                      FixedArray* elms,
+                                      int to_trim) {
+  ASSERT(elms->map() != HEAP->fixed_cow_array_map());
   // For now this trick is only applied to fixed arrays in new and paged space.
   // In large object space the object's start must coincide with chunk
   // and thus the trick is just not applicable.
-  ASSERT(!Heap::lo_space()->Contains(elms));
+  ASSERT(!HEAP->lo_space()->Contains(elms));
 
   STATIC_ASSERT(FixedArray::kMapOffset == 0);
   STATIC_ASSERT(FixedArray::kLengthOffset == kPointerSize);
@@ -336,7 +340,7 @@
   const int len = elms->length();
 
   if (to_trim > FixedArray::kHeaderSize / kPointerSize &&
-      !Heap::new_space()->Contains(elms)) {
+      !heap->new_space()->Contains(elms)) {
     // If we are doing a big trim in old space then we zap the space that was
     // formerly part of the array so that the GC (aided by the card-based
     // remembered set) won't find pointers to new-space there.
@@ -349,9 +353,9 @@
   // Technically in new space this write might be omitted (except for
   // debug mode which iterates through the heap), but to play safer
   // we still do it.
-  Heap::CreateFillerObjectAt(elms->address(), to_trim * kPointerSize);
+  heap->CreateFillerObjectAt(elms->address(), to_trim * kPointerSize);
 
-  former_start[to_trim] = Heap::fixed_array_map();
+  former_start[to_trim] = heap->fixed_array_map();
   former_start[to_trim + 1] = Smi::FromInt(len - to_trim);
 
   return FixedArray::cast(HeapObject::FromAddress(
@@ -359,20 +363,21 @@
 }
 
 
-static bool ArrayPrototypeHasNoElements(Context* global_context,
+static bool ArrayPrototypeHasNoElements(Heap* heap,
+                                        Context* global_context,
                                         JSObject* array_proto) {
   // This method depends on non writability of Object and Array prototype
   // fields.
-  if (array_proto->elements() != Heap::empty_fixed_array()) return false;
+  if (array_proto->elements() != heap->empty_fixed_array()) return false;
   // Hidden prototype
   array_proto = JSObject::cast(array_proto->GetPrototype());
-  ASSERT(array_proto->elements() == Heap::empty_fixed_array());
+  ASSERT(array_proto->elements() == heap->empty_fixed_array());
   // Object.prototype
   Object* proto = array_proto->GetPrototype();
-  if (proto == Heap::null_value()) return false;
+  if (proto == heap->null_value()) return false;
   array_proto = JSObject::cast(proto);
   if (array_proto != global_context->initial_object_prototype()) return false;
-  if (array_proto->elements() != Heap::empty_fixed_array()) return false;
+  if (array_proto->elements() != heap->empty_fixed_array()) return false;
   ASSERT(array_proto->GetPrototype()->IsNull());
   return true;
 }
@@ -380,35 +385,38 @@
 
 MUST_USE_RESULT
 static inline MaybeObject* EnsureJSArrayWithWritableFastElements(
-    Object* receiver) {
+    Heap* heap, Object* receiver) {
   if (!receiver->IsJSArray()) return NULL;
   JSArray* array = JSArray::cast(receiver);
   HeapObject* elms = array->elements();
-  if (elms->map() == Heap::fixed_array_map()) return elms;
-  if (elms->map() == Heap::fixed_cow_array_map()) {
+  if (elms->map() == heap->fixed_array_map()) return elms;
+  if (elms->map() == heap->fixed_cow_array_map()) {
     return array->EnsureWritableFastElements();
   }
   return NULL;
 }
 
 
-static inline bool IsJSArrayFastElementMovingAllowed(JSArray* receiver) {
-  Context* global_context = Top::context()->global_context();
+static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap,
+                                                     JSArray* receiver) {
+  Context* global_context = heap->isolate()->context()->global_context();
   JSObject* array_proto =
       JSObject::cast(global_context->array_function()->prototype());
   return receiver->GetPrototype() == array_proto &&
-         ArrayPrototypeHasNoElements(global_context, array_proto);
+         ArrayPrototypeHasNoElements(heap, global_context, array_proto);
 }
 
 
 MUST_USE_RESULT static MaybeObject* CallJsBuiltin(
+    Isolate* isolate,
     const char* name,
     BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
-  HandleScope handleScope;
+  HandleScope handleScope(isolate);
 
   Handle<Object> js_builtin =
-      GetProperty(Handle<JSObject>(Top::global_context()->builtins()),
-                  name);
+      GetProperty(Handle<JSObject>(
+          isolate->global_context()->builtins()),
+          name);
   ASSERT(js_builtin->IsJSFunction());
   Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin));
   ScopedVector<Object**> argv(args.length() - 1);
@@ -428,11 +436,14 @@
 
 
 BUILTIN(ArrayPush) {
+  Heap* heap = isolate->heap();
   Object* receiver = *args.receiver();
   Object* elms_obj;
   { MaybeObject* maybe_elms_obj =
-        EnsureJSArrayWithWritableFastElements(receiver);
-    if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayPush", args);
+        EnsureJSArrayWithWritableFastElements(heap, receiver);
+    if (maybe_elms_obj == NULL) {
+      return CallJsBuiltin(isolate, "ArrayPush", args);
+    }
     if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
   }
   FixedArray* elms = FixedArray::cast(elms_obj);
@@ -453,16 +464,16 @@
     // New backing storage is needed.
     int capacity = new_length + (new_length >> 1) + 16;
     Object* obj;
-    { MaybeObject* maybe_obj = Heap::AllocateUninitializedFixedArray(capacity);
+    { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity);
       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
     }
     FixedArray* new_elms = FixedArray::cast(obj);
 
     AssertNoAllocation no_gc;
     if (len > 0) {
-      CopyElements(&no_gc, new_elms, 0, elms, 0, len);
+      CopyElements(heap, &no_gc, new_elms, 0, elms, 0, len);
     }
-    FillWithHoles(new_elms, new_length, capacity);
+    FillWithHoles(heap, new_elms, new_length, capacity);
 
     elms = new_elms;
     array->set_elements(elms);
@@ -482,18 +493,19 @@
 
 
 BUILTIN(ArrayPop) {
+  Heap* heap = isolate->heap();
   Object* receiver = *args.receiver();
   Object* elms_obj;
   { MaybeObject* maybe_elms_obj =
-        EnsureJSArrayWithWritableFastElements(receiver);
-    if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayPop", args);
+        EnsureJSArrayWithWritableFastElements(heap, receiver);
+    if (maybe_elms_obj == NULL) return CallJsBuiltin(isolate, "ArrayPop", args);
     if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
   }
   FixedArray* elms = FixedArray::cast(elms_obj);
   JSArray* array = JSArray::cast(receiver);
 
   int len = Smi::cast(array->length())->value();
-  if (len == 0) return Heap::undefined_value();
+  if (len == 0) return heap->undefined_value();
 
   // Get top element
   MaybeObject* top = elms->get(len - 1);
@@ -514,38 +526,40 @@
 
 
 BUILTIN(ArrayShift) {
+  Heap* heap = isolate->heap();
   Object* receiver = *args.receiver();
   Object* elms_obj;
   { MaybeObject* maybe_elms_obj =
-        EnsureJSArrayWithWritableFastElements(receiver);
-    if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayShift", args);
+        EnsureJSArrayWithWritableFastElements(heap, receiver);
+    if (maybe_elms_obj == NULL)
+        return CallJsBuiltin(isolate, "ArrayShift", args);
     if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
   }
-  if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
-    return CallJsBuiltin("ArrayShift", args);
+  if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
+    return CallJsBuiltin(isolate, "ArrayShift", args);
   }
   FixedArray* elms = FixedArray::cast(elms_obj);
   JSArray* array = JSArray::cast(receiver);
   ASSERT(array->HasFastElements());
 
   int len = Smi::cast(array->length())->value();
-  if (len == 0) return Heap::undefined_value();
+  if (len == 0) return heap->undefined_value();
 
   // Get first element
   Object* first = elms->get(0);
   if (first->IsTheHole()) {
-    first = Heap::undefined_value();
+    first = heap->undefined_value();
   }
 
-  if (!Heap::lo_space()->Contains(elms)) {
+  if (!heap->lo_space()->Contains(elms)) {
     // As elms still in the same space they used to be,
     // there is no need to update region dirty mark.
-    array->set_elements(LeftTrimFixedArray(elms, 1), SKIP_WRITE_BARRIER);
+    array->set_elements(LeftTrimFixedArray(heap, elms, 1), SKIP_WRITE_BARRIER);
   } else {
     // Shift the elements.
     AssertNoAllocation no_gc;
-    MoveElements(&no_gc, elms, 0, elms, 1, len - 1);
-    elms->set(len - 1, Heap::the_hole_value());
+    MoveElements(heap, &no_gc, elms, 0, elms, 1, len - 1);
+    elms->set(len - 1, heap->the_hole_value());
   }
 
   // Set the length.
@@ -556,15 +570,17 @@
 
 
 BUILTIN(ArrayUnshift) {
+  Heap* heap = isolate->heap();
   Object* receiver = *args.receiver();
   Object* elms_obj;
   { MaybeObject* maybe_elms_obj =
-        EnsureJSArrayWithWritableFastElements(receiver);
-    if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayUnshift", args);
+        EnsureJSArrayWithWritableFastElements(heap, receiver);
+    if (maybe_elms_obj == NULL)
+        return CallJsBuiltin(isolate, "ArrayUnshift", args);
     if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
   }
-  if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
-    return CallJsBuiltin("ArrayUnshift", args);
+  if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
+    return CallJsBuiltin(isolate, "ArrayUnshift", args);
   }
   FixedArray* elms = FixedArray::cast(elms_obj);
   JSArray* array = JSArray::cast(receiver);
@@ -581,22 +597,22 @@
     // New backing storage is needed.
     int capacity = new_length + (new_length >> 1) + 16;
     Object* obj;
-    { MaybeObject* maybe_obj = Heap::AllocateUninitializedFixedArray(capacity);
+    { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity);
       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
     }
     FixedArray* new_elms = FixedArray::cast(obj);
 
     AssertNoAllocation no_gc;
     if (len > 0) {
-      CopyElements(&no_gc, new_elms, to_add, elms, 0, len);
+      CopyElements(heap, &no_gc, new_elms, to_add, elms, 0, len);
     }
-    FillWithHoles(new_elms, new_length, capacity);
+    FillWithHoles(heap, new_elms, new_length, capacity);
 
     elms = new_elms;
     array->set_elements(elms);
   } else {
     AssertNoAllocation no_gc;
-    MoveElements(&no_gc, elms, to_add, elms, 0, len);
+    MoveElements(heap, &no_gc, elms, to_add, elms, 0, len);
   }
 
   // Add the provided values.
@@ -613,14 +629,15 @@
 
 
 BUILTIN(ArraySlice) {
+  Heap* heap = isolate->heap();
   Object* receiver = *args.receiver();
   FixedArray* elms;
   int len = -1;
   if (receiver->IsJSArray()) {
     JSArray* array = JSArray::cast(receiver);
     if (!array->HasFastElements() ||
-        !IsJSArrayFastElementMovingAllowed(array)) {
-      return CallJsBuiltin("ArraySlice", args);
+        !IsJSArrayFastElementMovingAllowed(heap, array)) {
+      return CallJsBuiltin(isolate, "ArraySlice", args);
     }
 
     elms = FixedArray::cast(array->elements());
@@ -629,28 +646,28 @@
     // Array.slice(arguments, ...) is quite a common idiom (notably more
     // than 50% of invocations in Web apps).  Treat it in C++ as well.
     Map* arguments_map =
-        Top::context()->global_context()->arguments_boilerplate()->map();
+        isolate->context()->global_context()->arguments_boilerplate()->map();
 
     bool is_arguments_object_with_fast_elements =
         receiver->IsJSObject()
         && JSObject::cast(receiver)->map() == arguments_map
         && JSObject::cast(receiver)->HasFastElements();
     if (!is_arguments_object_with_fast_elements) {
-      return CallJsBuiltin("ArraySlice", args);
+      return CallJsBuiltin(isolate, "ArraySlice", args);
     }
     elms = FixedArray::cast(JSObject::cast(receiver)->elements());
     Object* len_obj = JSObject::cast(receiver)
-        ->InObjectPropertyAt(Heap::arguments_length_index);
+        ->InObjectPropertyAt(Heap::kArgumentsLengthIndex);
     if (!len_obj->IsSmi()) {
-      return CallJsBuiltin("ArraySlice", args);
+      return CallJsBuiltin(isolate, "ArraySlice", args);
     }
     len = Smi::cast(len_obj)->value();
     if (len > elms->length()) {
-      return CallJsBuiltin("ArraySlice", args);
+      return CallJsBuiltin(isolate, "ArraySlice", args);
     }
     for (int i = 0; i < len; i++) {
-      if (elms->get(i) == Heap::the_hole_value()) {
-        return CallJsBuiltin("ArraySlice", args);
+      if (elms->get(i) == heap->the_hole_value()) {
+        return CallJsBuiltin(isolate, "ArraySlice", args);
       }
     }
   }
@@ -667,14 +684,14 @@
     if (arg1->IsSmi()) {
       relative_start = Smi::cast(arg1)->value();
     } else if (!arg1->IsUndefined()) {
-      return CallJsBuiltin("ArraySlice", args);
+      return CallJsBuiltin(isolate, "ArraySlice", args);
     }
     if (n_arguments > 1) {
       Object* arg2 = args[2];
       if (arg2->IsSmi()) {
         relative_end = Smi::cast(arg2)->value();
       } else if (!arg2->IsUndefined()) {
-        return CallJsBuiltin("ArraySlice", args);
+        return CallJsBuiltin(isolate, "ArraySlice", args);
       }
     }
   }
@@ -690,23 +707,23 @@
   // Calculate the length of result array.
   int result_len = final - k;
   if (result_len <= 0) {
-    return AllocateEmptyJSArray();
+    return AllocateEmptyJSArray(heap);
   }
 
   Object* result;
-  { MaybeObject* maybe_result = AllocateJSArray();
+  { MaybeObject* maybe_result = AllocateJSArray(heap);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   JSArray* result_array = JSArray::cast(result);
 
   { MaybeObject* maybe_result =
-        Heap::AllocateUninitializedFixedArray(result_len);
+        heap->AllocateUninitializedFixedArray(result_len);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   FixedArray* result_elms = FixedArray::cast(result);
 
   AssertNoAllocation no_gc;
-  CopyElements(&no_gc, result_elms, 0, elms, k, result_len);
+  CopyElements(heap, &no_gc, result_elms, 0, elms, k, result_len);
 
   // Set elements.
   result_array->set_elements(result_elms);
@@ -718,15 +735,17 @@
 
 
 BUILTIN(ArraySplice) {
+  Heap* heap = isolate->heap();
   Object* receiver = *args.receiver();
   Object* elms_obj;
   { MaybeObject* maybe_elms_obj =
-        EnsureJSArrayWithWritableFastElements(receiver);
-    if (maybe_elms_obj == NULL) return CallJsBuiltin("ArraySplice", args);
+        EnsureJSArrayWithWritableFastElements(heap, receiver);
+    if (maybe_elms_obj == NULL)
+        return CallJsBuiltin(isolate, "ArraySplice", args);
     if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
   }
-  if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
-    return CallJsBuiltin("ArraySplice", args);
+  if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
+    return CallJsBuiltin(isolate, "ArraySplice", args);
   }
   FixedArray* elms = FixedArray::cast(elms_obj);
   JSArray* array = JSArray::cast(receiver);
@@ -742,7 +761,7 @@
     if (arg1->IsSmi()) {
       relative_start = Smi::cast(arg1)->value();
     } else if (!arg1->IsUndefined()) {
-      return CallJsBuiltin("ArraySplice", args);
+      return CallJsBuiltin(isolate, "ArraySplice", args);
     }
   }
   int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
@@ -764,7 +783,7 @@
       if (arg2->IsSmi()) {
         value = Smi::cast(arg2)->value();
       } else {
-        return CallJsBuiltin("ArraySplice", args);
+        return CallJsBuiltin(isolate, "ArraySplice", args);
       }
     }
     actual_delete_count = Min(Max(value, 0), len - actual_start);
@@ -773,27 +792,28 @@
   JSArray* result_array = NULL;
   if (actual_delete_count == 0) {
     Object* result;
-    { MaybeObject* maybe_result = AllocateEmptyJSArray();
+    { MaybeObject* maybe_result = AllocateEmptyJSArray(heap);
       if (!maybe_result->ToObject(&result)) return maybe_result;
     }
     result_array = JSArray::cast(result);
   } else {
     // Allocate result array.
     Object* result;
-    { MaybeObject* maybe_result = AllocateJSArray();
+    { MaybeObject* maybe_result = AllocateJSArray(heap);
       if (!maybe_result->ToObject(&result)) return maybe_result;
     }
     result_array = JSArray::cast(result);
 
     { MaybeObject* maybe_result =
-          Heap::AllocateUninitializedFixedArray(actual_delete_count);
+          heap->AllocateUninitializedFixedArray(actual_delete_count);
       if (!maybe_result->ToObject(&result)) return maybe_result;
     }
     FixedArray* result_elms = FixedArray::cast(result);
 
     AssertNoAllocation no_gc;
     // Fill newly created array.
-    CopyElements(&no_gc,
+    CopyElements(heap,
+                 &no_gc,
                  result_elms, 0,
                  elms, actual_start,
                  actual_delete_count);
@@ -811,7 +831,7 @@
 
   if (item_count < actual_delete_count) {
     // Shrink the array.
-    const bool trim_array = !Heap::lo_space()->Contains(elms) &&
+    const bool trim_array = !heap->lo_space()->Contains(elms) &&
       ((actual_start + item_count) <
           (len - actual_delete_count - actual_start));
     if (trim_array) {
@@ -822,15 +842,15 @@
         memmove(start + delta, start, actual_start * kPointerSize);
       }
 
-      elms = LeftTrimFixedArray(elms, delta);
+      elms = LeftTrimFixedArray(heap, elms, delta);
       array->set_elements(elms, SKIP_WRITE_BARRIER);
     } else {
       AssertNoAllocation no_gc;
-      MoveElements(&no_gc,
+      MoveElements(heap, &no_gc,
                    elms, actual_start + item_count,
                    elms, actual_start + actual_delete_count,
                    (len - actual_delete_count - actual_start));
-      FillWithHoles(elms, new_length, len);
+      FillWithHoles(heap, elms, new_length, len);
     }
   } else if (item_count > actual_delete_count) {
     // Currently fixed arrays cannot grow too big, so
@@ -843,7 +863,7 @@
       int capacity = new_length + (new_length >> 1) + 16;
       Object* obj;
       { MaybeObject* maybe_obj =
-            Heap::AllocateUninitializedFixedArray(capacity);
+            heap->AllocateUninitializedFixedArray(capacity);
         if (!maybe_obj->ToObject(&obj)) return maybe_obj;
       }
       FixedArray* new_elms = FixedArray::cast(obj);
@@ -851,22 +871,22 @@
       AssertNoAllocation no_gc;
       // Copy the part before actual_start as is.
       if (actual_start > 0) {
-        CopyElements(&no_gc, new_elms, 0, elms, 0, actual_start);
+        CopyElements(heap, &no_gc, new_elms, 0, elms, 0, actual_start);
       }
       const int to_copy = len - actual_delete_count - actual_start;
       if (to_copy > 0) {
-        CopyElements(&no_gc,
+        CopyElements(heap, &no_gc,
                      new_elms, actual_start + item_count,
                      elms, actual_start + actual_delete_count,
                      to_copy);
       }
-      FillWithHoles(new_elms, new_length, capacity);
+      FillWithHoles(heap, new_elms, new_length, capacity);
 
       elms = new_elms;
       array->set_elements(elms);
     } else {
       AssertNoAllocation no_gc;
-      MoveElements(&no_gc,
+      MoveElements(heap, &no_gc,
                    elms, actual_start + item_count,
                    elms, actual_start + actual_delete_count,
                    (len - actual_delete_count - actual_start));
@@ -887,11 +907,12 @@
 
 
 BUILTIN(ArrayConcat) {
-  Context* global_context = Top::context()->global_context();
+  Heap* heap = isolate->heap();
+  Context* global_context = isolate->context()->global_context();
   JSObject* array_proto =
       JSObject::cast(global_context->array_function()->prototype());
-  if (!ArrayPrototypeHasNoElements(global_context, array_proto)) {
-    return CallJsBuiltin("ArrayConcat", args);
+  if (!ArrayPrototypeHasNoElements(heap, global_context, array_proto)) {
+    return CallJsBuiltin(isolate, "ArrayConcat", args);
   }
 
   // Iterate through all the arguments performing checks
@@ -902,7 +923,7 @@
     Object* arg = args[i];
     if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements()
         || JSArray::cast(arg)->GetPrototype() != array_proto) {
-      return CallJsBuiltin("ArrayConcat", args);
+      return CallJsBuiltin(isolate, "ArrayConcat", args);
     }
 
     int len = Smi::cast(JSArray::cast(arg)->length())->value();
@@ -915,23 +936,23 @@
     ASSERT(result_len >= 0);
 
     if (result_len > FixedArray::kMaxLength) {
-      return CallJsBuiltin("ArrayConcat", args);
+      return CallJsBuiltin(isolate, "ArrayConcat", args);
     }
   }
 
   if (result_len == 0) {
-    return AllocateEmptyJSArray();
+    return AllocateEmptyJSArray(heap);
   }
 
   // Allocate result.
   Object* result;
-  { MaybeObject* maybe_result = AllocateJSArray();
+  { MaybeObject* maybe_result = AllocateJSArray(heap);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   JSArray* result_array = JSArray::cast(result);
 
   { MaybeObject* maybe_result =
-        Heap::AllocateUninitializedFixedArray(result_len);
+        heap->AllocateUninitializedFixedArray(result_len);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   FixedArray* result_elms = FixedArray::cast(result);
@@ -944,7 +965,7 @@
     int len = Smi::cast(array->length())->value();
     if (len > 0) {
       FixedArray* elms = FixedArray::cast(array->elements());
-      CopyElements(&no_gc, result_elms, start_pos, elms, 0, len);
+      CopyElements(heap, &no_gc, result_elms, start_pos, elms, 0, len);
       start_pos += len;
     }
   }
@@ -959,6 +980,38 @@
 
 
 // -----------------------------------------------------------------------------
+// Strict mode poison pills
+
+
+BUILTIN(StrictArgumentsCallee) {
+  HandleScope scope;
+  return isolate->Throw(*isolate->factory()->NewTypeError(
+      "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
+}
+
+
+BUILTIN(StrictArgumentsCaller) {
+  HandleScope scope;
+  return isolate->Throw(*isolate->factory()->NewTypeError(
+      "strict_arguments_caller", HandleVector<Object>(NULL, 0)));
+}
+
+
+BUILTIN(StrictFunctionCaller) {
+  HandleScope scope;
+  return isolate->Throw(*isolate->factory()->NewTypeError(
+      "strict_function_caller", HandleVector<Object>(NULL, 0)));
+}
+
+
+BUILTIN(StrictFunctionArguments) {
+  HandleScope scope;
+  return isolate->Throw(*isolate->factory()->NewTypeError(
+      "strict_function_arguments", HandleVector<Object>(NULL, 0)));
+}
+
+
+// -----------------------------------------------------------------------------
 //
 
 
@@ -968,7 +1021,8 @@
 // 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,
+static inline Object* TypeCheck(Heap* heap,
+                                int argc,
                                 Object** argv,
                                 FunctionTemplateInfo* info) {
   Object* recv = argv[0];
@@ -980,12 +1034,12 @@
 
   Object* holder = recv;
   if (!recv_type->IsUndefined()) {
-    for (; holder != Heap::null_value(); holder = holder->GetPrototype()) {
+    for (; holder != heap->null_value(); holder = holder->GetPrototype()) {
       if (holder->IsInstanceOf(FunctionTemplateInfo::cast(recv_type))) {
         break;
       }
     }
-    if (holder == Heap::null_value()) return holder;
+    if (holder == heap->null_value()) return holder;
   }
   Object* args_obj = sig->args();
   // If there is no argument signature we're done
@@ -998,13 +1052,13 @@
     if (argtype->IsUndefined()) continue;
     Object** arg = &argv[-1 - i];
     Object* current = *arg;
-    for (; current != Heap::null_value(); current = current->GetPrototype()) {
+    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();
+    if (current == heap->null_value()) *arg = heap->undefined_value();
   }
   return holder;
 }
@@ -1012,31 +1066,33 @@
 
 template <bool is_construct>
 MUST_USE_RESULT static MaybeObject* HandleApiCallHelper(
-    BuiltinArguments<NEEDS_CALLED_FUNCTION> args) {
-  ASSERT(is_construct == CalledAsConstructor());
+    BuiltinArguments<NEEDS_CALLED_FUNCTION> args, Isolate* isolate) {
+  ASSERT(is_construct == CalledAsConstructor(isolate));
+  Heap* heap = isolate->heap();
 
-  HandleScope scope;
+  HandleScope scope(isolate);
   Handle<JSFunction> function = args.called_function();
   ASSERT(function->shared()->IsApiFunction());
 
   FunctionTemplateInfo* fun_data = function->shared()->get_api_func_data();
   if (is_construct) {
-    Handle<FunctionTemplateInfo> desc(fun_data);
+    Handle<FunctionTemplateInfo> desc(fun_data, isolate);
     bool pending_exception = false;
-    Factory::ConfigureInstance(desc, Handle<JSObject>::cast(args.receiver()),
-                               &pending_exception);
-    ASSERT(Top::has_pending_exception() == pending_exception);
+    isolate->factory()->ConfigureInstance(
+        desc, Handle<JSObject>::cast(args.receiver()), &pending_exception);
+    ASSERT(isolate->has_pending_exception() == pending_exception);
     if (pending_exception) return Failure::Exception();
     fun_data = *desc;
   }
 
-  Object* raw_holder = TypeCheck(args.length(), &args[0], fun_data);
+  Object* raw_holder = TypeCheck(heap, args.length(), &args[0], 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);
+        isolate->factory()->NewTypeError(
+            "illegal_invocation", HandleVector(&function, 1));
+    return isolate->Throw(*obj);
   }
 
   Object* raw_call_data = fun_data->call_code();
@@ -1048,10 +1104,10 @@
     Object* data_obj = call_data->data();
     Object* result;
 
-    LOG(ApiObjectAccess("call", JSObject::cast(*args.receiver())));
+    LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver())));
     ASSERT(raw_holder->IsJSObject());
 
-    CustomArguments custom;
+    CustomArguments custom(isolate);
     v8::ImplementationUtilities::PrepareArgumentsData(custom.end(),
         data_obj, *function, raw_holder);
 
@@ -1064,17 +1120,18 @@
     v8::Handle<v8::Value> value;
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
-      ExternalCallbackScope call_scope(v8::ToCData<Address>(callback_obj));
+      VMState state(isolate, EXTERNAL);
+      ExternalCallbackScope call_scope(isolate,
+                                       v8::ToCData<Address>(callback_obj));
       value = callback(new_args);
     }
     if (value.IsEmpty()) {
-      result = Heap::undefined_value();
+      result = heap->undefined_value();
     } else {
       result = *reinterpret_cast<Object**>(*value);
     }
 
-    RETURN_IF_SCHEDULED_EXCEPTION();
+    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
     if (!is_construct || result->IsJSObject()) return result;
   }
 
@@ -1083,12 +1140,12 @@
 
 
 BUILTIN(HandleApiCall) {
-  return HandleApiCallHelper<false>(args);
+  return HandleApiCallHelper<false>(args, isolate);
 }
 
 
 BUILTIN(HandleApiCallConstruct) {
-  return HandleApiCallHelper<true>(args);
+  return HandleApiCallHelper<true>(args, isolate);
 }
 
 
@@ -1110,7 +1167,8 @@
 
 
 BUILTIN(FastHandleApiCall) {
-  ASSERT(!CalledAsConstructor());
+  ASSERT(!CalledAsConstructor(isolate));
+  Heap* heap = isolate->heap();
   const bool is_construct = false;
 
   // We expect four more arguments: callback, function, call data, and holder.
@@ -1129,25 +1187,26 @@
   VerifyTypeCheck(Utils::OpenHandle(*new_args.Holder()),
                   Utils::OpenHandle(*new_args.Callee()));
 #endif
-  HandleScope scope;
+  HandleScope scope(isolate);
   Object* result;
   v8::Handle<v8::Value> value;
   {
     // Leaving JavaScript.
-    VMState state(EXTERNAL);
-    ExternalCallbackScope call_scope(v8::ToCData<Address>(callback_obj));
+    VMState state(isolate, EXTERNAL);
+    ExternalCallbackScope call_scope(isolate,
+                                     v8::ToCData<Address>(callback_obj));
     v8::InvocationCallback callback =
         v8::ToCData<v8::InvocationCallback>(callback_obj);
 
     value = callback(new_args);
   }
   if (value.IsEmpty()) {
-    result = Heap::undefined_value();
+    result = heap->undefined_value();
   } else {
     result = *reinterpret_cast<Object**>(*value);
   }
 
-  RETURN_IF_SCHEDULED_EXCEPTION();
+  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   return result;
 }
 
@@ -1156,11 +1215,13 @@
 // API. The object can be called as either a constructor (using new) or just as
 // a function (without new).
 MUST_USE_RESULT static MaybeObject* HandleApiCallAsFunctionOrConstructor(
+    Isolate* isolate,
     bool is_construct_call,
     BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
   // Non-functions are never called as constructors. Even if this is an object
   // called as a constructor the delegate call is not a construct call.
-  ASSERT(!CalledAsConstructor());
+  ASSERT(!CalledAsConstructor(isolate));
+  Heap* heap = isolate->heap();
 
   Handle<Object> receiver = args.at<Object>(0);
 
@@ -1183,11 +1244,10 @@
   // Get the data for the call and perform the callback.
   Object* result;
   {
-    HandleScope scope;
+    HandleScope scope(isolate);
+    LOG(isolate, ApiObjectAccess("call non-function", obj));
 
-    LOG(ApiObjectAccess("call non-function", obj));
-
-    CustomArguments custom;
+    CustomArguments custom(isolate);
     v8::ImplementationUtilities::PrepareArgumentsData(custom.end(),
         call_data->data(), constructor, obj);
     v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
@@ -1198,18 +1258,19 @@
     v8::Handle<v8::Value> value;
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
-      ExternalCallbackScope call_scope(v8::ToCData<Address>(callback_obj));
+      VMState state(isolate, EXTERNAL);
+      ExternalCallbackScope call_scope(isolate,
+                                       v8::ToCData<Address>(callback_obj));
       value = callback(new_args);
     }
     if (value.IsEmpty()) {
-      result = Heap::undefined_value();
+      result = heap->undefined_value();
     } else {
       result = *reinterpret_cast<Object**>(*value);
     }
   }
   // Check for exceptions and return result.
-  RETURN_IF_SCHEDULED_EXCEPTION();
+  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   return result;
 }
 
@@ -1217,14 +1278,14 @@
 // Handle calls to non-function objects created through the API. This delegate
 // function is used when the call is a normal function call.
 BUILTIN(HandleApiCallAsFunction) {
-  return HandleApiCallAsFunctionOrConstructor(false, args);
+  return HandleApiCallAsFunctionOrConstructor(isolate, false, args);
 }
 
 
 // Handle calls to non-function objects created through the API. This delegate
 // function is used when the call is a construct call.
 BUILTIN(HandleApiCallAsConstructor) {
-  return HandleApiCallAsFunctionOrConstructor(true, args);
+  return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
 }
 
 
@@ -1433,73 +1494,112 @@
 }
 #endif
 
-Object* Builtins::builtins_[builtin_count] = { NULL, };
-const char* Builtins::names_[builtin_count] = { NULL, };
+
+Builtins::Builtins() : initialized_(false) {
+  memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
+  memset(names_, 0, sizeof(names_[0]) * builtin_count);
+}
+
+
+Builtins::~Builtins() {
+}
+
 
 #define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
-  Address Builtins::c_functions_[cfunction_count] = {
-    BUILTIN_LIST_C(DEF_ENUM_C)
-  };
+Address const 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] = {
+const char* const Builtins::javascript_names_[id_count] = {
   BUILTINS_LIST_JS(DEF_JS_NAME)
 };
 
-int Builtins::javascript_argc_[id_count] = {
+int const Builtins::javascript_argc_[id_count] = {
   BUILTINS_LIST_JS(DEF_JS_ARGC)
 };
 #undef DEF_JS_NAME
 #undef DEF_JS_ARGC
 
-static bool is_initialized = false;
+struct BuiltinDesc {
+  byte* generator;
+  byte* c_code;
+  const char* s_name;  // name is only used for generating log information.
+  int name;
+  Code::Flags flags;
+  BuiltinExtraArguments extra_args;
+};
+
+class BuiltinFunctionTable {
+ public:
+  BuiltinFunctionTable() {
+    Builtins::InitBuiltinFunctionTable();
+  }
+
+  static const BuiltinDesc* functions() { return functions_; }
+
+ private:
+  static BuiltinDesc functions_[Builtins::builtin_count + 1];
+
+  friend class Builtins;
+};
+
+BuiltinDesc BuiltinFunctionTable::functions_[Builtins::builtin_count + 1];
+
+static const BuiltinFunctionTable builtin_function_table_init;
+
+// Define array of pointers to generators and C builtin functions.
+// We do this in a sort of roundabout way so that we can do the initialization
+// within the lexical scope of Builtins:: and within a context where
+// Code::Flags names a non-abstract type.
+void Builtins::InitBuiltinFunctionTable() {
+  BuiltinDesc* functions = BuiltinFunctionTable::functions_;
+  functions[builtin_count].generator = NULL;
+  functions[builtin_count].c_code = NULL;
+  functions[builtin_count].s_name = NULL;
+  functions[builtin_count].name = builtin_count;
+  functions[builtin_count].flags = static_cast<Code::Flags>(0);
+  functions[builtin_count].extra_args = NO_EXTRA_ARGUMENTS;
+
+#define DEF_FUNCTION_PTR_C(aname, aextra_args)                         \
+    functions->generator = FUNCTION_ADDR(Generate_Adaptor);            \
+    functions->c_code = FUNCTION_ADDR(Builtin_##aname);                \
+    functions->s_name = #aname;                                        \
+    functions->name = c_##aname;                                       \
+    functions->flags = Code::ComputeFlags(Code::BUILTIN);              \
+    functions->extra_args = aextra_args;                               \
+    ++functions;
+
+#define DEF_FUNCTION_PTR_A(aname, kind, state, extra)                       \
+    functions->generator = FUNCTION_ADDR(Generate_##aname);                 \
+    functions->c_code = NULL;                                               \
+    functions->s_name = #aname;                                             \
+    functions->name = k##aname;                                             \
+    functions->flags = Code::ComputeFlags(Code::kind,                       \
+                                          NOT_IN_LOOP,                      \
+                                          state,                            \
+                                          extra);                           \
+    functions->extra_args = NO_EXTRA_ARGUMENTS;                             \
+    ++functions;
+
+  BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
+  BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
+  BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
+
+#undef DEF_FUNCTION_PTR_C
+#undef DEF_FUNCTION_PTR_A
+}
+
 void Builtins::Setup(bool create_heap_objects) {
-  ASSERT(!is_initialized);
+  ASSERT(!initialized_);
+  Heap* heap = Isolate::Current()->heap();
 
   // 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;
-    BuiltinExtraArguments extra_args;
-  };
-
-#define DEF_FUNCTION_PTR_C(name, extra_args) \
-    { FUNCTION_ADDR(Generate_Adaptor),            \
-      FUNCTION_ADDR(Builtin_##name),              \
-      #name,                                      \
-      c_##name,                                   \
-      Code::ComputeFlags(Code::BUILTIN),          \
-      extra_args                                  \
-    },
-
-#define DEF_FUNCTION_PTR_A(name, kind, state, extra)              \
-    { FUNCTION_ADDR(Generate_##name),                             \
-      NULL,                                                       \
-      #name,                                                      \
-      name,                                                       \
-      Code::ComputeFlags(Code::kind, NOT_IN_LOOP, state, extra),  \
-      NO_EXTRA_ARGUMENTS                                          \
-    },
-
-  // 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),
-        NO_EXTRA_ARGUMENTS }
-  };
-
-#undef DEF_FUNCTION_PTR_C
-#undef DEF_FUNCTION_PTR_A
+  const BuiltinDesc* functions = BuiltinFunctionTable::functions();
 
   // For now we generate builtin adaptor code into a stack-allocated
   // buffer, before copying it into individual code objects.
@@ -1527,14 +1627,15 @@
         // This simplifies things because we don't need to retry.
         AlwaysAllocateScope __scope__;
         { MaybeObject* maybe_code =
-              Heap::CreateCode(desc, flags, masm.CodeObject());
+              heap->CreateCode(desc, flags, masm.CodeObject());
           if (!maybe_code->ToObject(&code)) {
             v8::internal::V8::FatalProcessOutOfMemory("CreateCode");
           }
         }
       }
       // Log the event and add the code to the builtins array.
-      PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG,
+      PROFILE(ISOLATE,
+              CodeCreateEvent(Logger::BUILTIN_TAG,
                               Code::cast(code),
                               functions[i].s_name));
       GDBJIT(AddCode(GDBJITInterface::BUILTIN,
@@ -1556,12 +1657,12 @@
   }
 
   // Mark as initialized.
-  is_initialized = true;
+  initialized_ = true;
 }
 
 
 void Builtins::TearDown() {
-  is_initialized = false;
+  initialized_ = false;
 }
 
 
@@ -1571,7 +1672,8 @@
 
 
 const char* Builtins::Lookup(byte* pc) {
-  if (is_initialized) {  // may be called during initialization (disassembler!)
+  // may be called during initialization (disassembler!)
+  if (initialized_) {
     for (int i = 0; i < builtin_count; i++) {
       Code* entry = Code::cast(builtins_[i]);
       if (entry->contains(pc)) {
@@ -1583,4 +1685,23 @@
 }
 
 
+#define DEFINE_BUILTIN_ACCESSOR_C(name, ignore)               \
+Handle<Code> Builtins::name() {                               \
+  Code** code_address =                                       \
+      reinterpret_cast<Code**>(builtin_address(k##name));     \
+  return Handle<Code>(code_address);                          \
+}
+#define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
+Handle<Code> Builtins::name() {                             \
+  Code** code_address =                                     \
+      reinterpret_cast<Code**>(builtin_address(k##name));   \
+  return Handle<Code>(code_address);                        \
+}
+BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
+BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
+BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
+#undef DEFINE_BUILTIN_ACCESSOR_C
+#undef DEFINE_BUILTIN_ACCESSOR_A
+
+
 } }  // namespace v8::internal
diff --git a/src/builtins.h b/src/builtins.h
index 5ea4665..bc0facb 100644
--- a/src/builtins.h
+++ b/src/builtins.h
@@ -58,7 +58,12 @@
   V(FastHandleApiCall, NO_EXTRA_ARGUMENTS)                          \
   V(HandleApiCallConstruct, NEEDS_CALLED_FUNCTION)                  \
   V(HandleApiCallAsFunction, NO_EXTRA_ARGUMENTS)                    \
-  V(HandleApiCallAsConstructor, NO_EXTRA_ARGUMENTS)
+  V(HandleApiCallAsConstructor, NO_EXTRA_ARGUMENTS)                 \
+                                                                    \
+  V(StrictArgumentsCallee, NO_EXTRA_ARGUMENTS)                      \
+  V(StrictArgumentsCaller, NO_EXTRA_ARGUMENTS)                      \
+  V(StrictFunctionCaller, NO_EXTRA_ARGUMENTS)                       \
+  V(StrictFunctionArguments, NO_EXTRA_ARGUMENTS)
 
 
 // Define list of builtins implemented in assembly.
@@ -235,25 +240,28 @@
   V(APPLY_OVERFLOW, 1)
 
 
+class BuiltinFunctionTable;
 class ObjectVisitor;
 
 
-class Builtins : public AllStatic {
+class Builtins {
  public:
+  ~Builtins();
+
   // Generate all builtin code objects. Should be called once during
-  // VM initialization.
-  static void Setup(bool create_heap_objects);
-  static void TearDown();
+  // isolate initialization.
+  void Setup(bool create_heap_objects);
+  void TearDown();
 
   // Garbage collection support.
-  static void IterateBuiltins(ObjectVisitor* v);
+  void IterateBuiltins(ObjectVisitor* v);
 
   // Disassembler support.
-  static const char* Lookup(byte* pc);
+  const char* Lookup(byte* pc);
 
   enum Name {
-#define DEF_ENUM_C(name, ignore) name,
-#define DEF_ENUM_A(name, kind, state, extra) name,
+#define DEF_ENUM_C(name, ignore) k##name,
+#define DEF_ENUM_A(name, kind, state, extra) k##name,
     BUILTIN_LIST_C(DEF_ENUM_C)
     BUILTIN_LIST_A(DEF_ENUM_A)
     BUILTIN_LIST_DEBUG_A(DEF_ENUM_A)
@@ -276,13 +284,22 @@
     id_count
   };
 
-  static Code* builtin(Name name) {
+#define DECLARE_BUILTIN_ACCESSOR_C(name, ignore) Handle<Code> name();
+#define DECLARE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
+  Handle<Code> name();
+  BUILTIN_LIST_C(DECLARE_BUILTIN_ACCESSOR_C)
+  BUILTIN_LIST_A(DECLARE_BUILTIN_ACCESSOR_A)
+  BUILTIN_LIST_DEBUG_A(DECLARE_BUILTIN_ACCESSOR_A)
+#undef DECLARE_BUILTIN_ACCESSOR_C
+#undef DECLARE_BUILTIN_ACCESSOR_A
+
+  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) {
+  Address builtin_address(Name name) {
     return reinterpret_cast<Address>(&builtins_[name]);
   }
 
@@ -292,20 +309,24 @@
 
   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);
+  Handle<Code> GetCode(JavaScript id, bool* resolved);
   static int NumberOfJavaScriptBuiltins() { return id_count; }
 
+  bool is_initialized() const { return initialized_; }
+
  private:
+  Builtins();
+
   // The external C++ functions called from the code.
-  static Address c_functions_[cfunction_count];
+  static Address const 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];
+  Object* builtins_[builtin_count];
+  const char* names_[builtin_count];
+  static const char* const javascript_names_[id_count];
+  static int const javascript_argc_[id_count];
 
   static void Generate_Adaptor(MacroAssembler* masm,
                                CFunctionId id,
@@ -330,8 +351,16 @@
   static void Generate_ArrayConstructCode(MacroAssembler* masm);
 
   static void Generate_StringConstructCode(MacroAssembler* masm);
-
   static void Generate_OnStackReplacement(MacroAssembler* masm);
+
+  static void InitBuiltinFunctionTable();
+
+  bool initialized_;
+
+  friend class BuiltinFunctionTable;
+  friend class Isolate;
+
+  DISALLOW_COPY_AND_ASSIGN(Builtins);
 };
 
 } }  // namespace v8::internal
diff --git a/src/checks.cc b/src/checks.cc
index 3c3d940..320fd6b 100644
--- a/src/checks.cc
+++ b/src/checks.cc
@@ -30,8 +30,8 @@
 #include "v8.h"
 
 #include "platform.h"
-#include "top.h"
 
+// TODO(isolates): is it necessary to lift this?
 static int fatal_error_handler_nesting_depth = 0;
 
 // Contains protection against recursive calls (faults while handling faults).
@@ -52,7 +52,7 @@
   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::Isolate::Current()->PrintStack();
     }
   }
   i::OS::Abort();
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index ba77b21..2ecd336 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -37,9 +37,10 @@
 namespace internal {
 
 bool CodeStub::FindCodeInCache(Code** code_out) {
-  int index = Heap::code_stubs()->FindEntry(GetKey());
+  Heap* heap = Isolate::Current()->heap();
+  int index = heap->code_stubs()->FindEntry(GetKey());
   if (index != NumberDictionary::kNotFound) {
-    *code_out = Code::cast(Heap::code_stubs()->ValueAt(index));
+    *code_out = Code::cast(heap->code_stubs()->ValueAt(index));
     return true;
   }
   return false;
@@ -48,7 +49,7 @@
 
 void CodeStub::GenerateCode(MacroAssembler* masm) {
   // Update the static counter each time a new code stub is generated.
-  Counters::code_stubs.Increment();
+  masm->isolate()->counters()->code_stubs()->Increment();
 
   // Nested stubs are not allowed for leafs.
   AllowStubCallsScope allow_scope(masm, AllowsStubCalls());
@@ -62,9 +63,11 @@
 void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) {
   code->set_major_key(MajorKey());
 
-  PROFILE(CodeCreateEvent(Logger::STUB_TAG, code, GetName()));
+  Isolate* isolate = masm->isolate();
+  PROFILE(isolate, CodeCreateEvent(Logger::STUB_TAG, code, GetName()));
   GDBJIT(AddCode(GDBJITInterface::STUB, GetName(), code));
-  Counters::total_stubs_code_size.Increment(code->instruction_size());
+  Counters* counters = isolate->counters();
+  counters->total_stubs_code_size()->Increment(code->instruction_size());
 
 #ifdef ENABLE_DISASSEMBLER
   if (FLAG_print_code_stubs) {
@@ -84,9 +87,12 @@
 
 
 Handle<Code> CodeStub::GetCode() {
+  Isolate* isolate = Isolate::Current();
+  Factory* factory = isolate->factory();
+  Heap* heap = isolate->heap();
   Code* code;
   if (!FindCodeInCache(&code)) {
-    v8::HandleScope scope;
+    HandleScope scope(isolate);
 
     // Generate the new code.
     MacroAssembler masm(NULL, 256);
@@ -101,22 +107,24 @@
         static_cast<Code::Kind>(GetCodeKind()),
         InLoop(),
         GetICState());
-    Handle<Code> new_object = Factory::NewCode(desc, flags, masm.CodeObject());
+    Handle<Code> new_object = factory->NewCode(
+        desc, flags, masm.CodeObject(), NeedsImmovableCode());
     RecordCodeGeneration(*new_object, &masm);
     FinishCode(*new_object);
 
     // Update the dictionary and the root in Heap.
     Handle<NumberDictionary> dict =
-        Factory::DictionaryAtNumberPut(
-            Handle<NumberDictionary>(Heap::code_stubs()),
+        factory->DictionaryAtNumberPut(
+            Handle<NumberDictionary>(heap->code_stubs()),
             GetKey(),
             new_object);
-    Heap::public_set_code_stubs(*dict);
+    heap->public_set_code_stubs(*dict);
 
     code = *new_object;
   }
 
-  return Handle<Code>(code);
+  ASSERT(!NeedsImmovableCode() || heap->lo_space()->Contains(code));
+  return Handle<Code>(code, isolate);
 }
 
 
@@ -126,6 +134,7 @@
     // Generate the new code.
     MacroAssembler masm(NULL, 256);
     GenerateCode(&masm);
+    Heap* heap = masm.isolate()->heap();
 
     // Create the code object.
     CodeDesc desc;
@@ -138,7 +147,7 @@
         GetICState());
     Object* new_object;
     { MaybeObject* maybe_new_object =
-          Heap::CreateCode(desc, flags, masm.CodeObject());
+          heap->CreateCode(desc, flags, masm.CodeObject());
       if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
     }
     code = Code::cast(new_object);
@@ -147,9 +156,9 @@
 
     // Try to update the code cache but do not fail if unable.
     MaybeObject* maybe_new_object =
-        Heap::code_stubs()->AtNumberPut(GetKey(), code);
+        heap->code_stubs()->AtNumberPut(GetKey(), code);
     if (maybe_new_object->ToObject(&new_object)) {
-      Heap::public_set_code_stubs(NumberDictionary::cast(new_object));
+      heap->public_set_code_stubs(NumberDictionary::cast(new_object));
     }
   }
 
@@ -200,7 +209,8 @@
 const char* InstanceofStub::GetName() {
   if (name_ != NULL) return name_;
   const int kMaxNameLength = 100;
-  name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
+  name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
+      kMaxNameLength);
   if (name_ == NULL) return "OOM";
 
   const char* args = "";
diff --git a/src/code-stubs.h b/src/code-stubs.h
index 96ac733..d408034 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -40,7 +40,6 @@
   V(GenericBinaryOp)                     \
   V(TypeRecordingBinaryOp)               \
   V(StringAdd)                           \
-  V(StringCharAt)                        \
   V(SubString)                           \
   V(StringCompare)                       \
   V(SmiOp)                               \
@@ -81,10 +80,19 @@
 #define CODE_STUB_LIST_ARM(V)
 #endif
 
+// List of code stubs only used on MIPS platforms.
+#ifdef V8_TARGET_ARCH_MIPS
+#define CODE_STUB_LIST_MIPS(V)  \
+  V(RegExpCEntry)
+#else
+#define CODE_STUB_LIST_MIPS(V)
+#endif
+
 // Combined list of code stubs.
 #define CODE_STUB_LIST(V)            \
   CODE_STUB_LIST_ALL_PLATFORMS(V)    \
-  CODE_STUB_LIST_ARM(V)
+  CODE_STUB_LIST_ARM(V)              \
+  CODE_STUB_LIST_MIPS(V)
 
 // Mode to overwrite BinaryExpression values.
 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
@@ -167,7 +175,11 @@
   // Returns a name for logging/debugging purposes.
   virtual const char* GetName() { return MajorName(MajorKey(), false); }
 
-#ifdef DEBUG
+  // Returns whether the code generated for this stub needs to be allocated as
+  // a fixed (non-moveable) code object.
+  virtual bool NeedsImmovableCode() { return false; }
+
+  #ifdef DEBUG
   virtual void Print() { PrintF("%s\n", GetName()); }
 #endif
 
@@ -274,12 +286,17 @@
 
 class FastNewClosureStub : public CodeStub {
  public:
+  explicit FastNewClosureStub(StrictModeFlag strict_mode)
+    : strict_mode_(strict_mode) { }
+
   void Generate(MacroAssembler* masm);
 
  private:
   const char* GetName() { return "FastNewClosureStub"; }
   Major MajorKey() { return FastNewClosure; }
-  int MinorKey() { return 0; }
+  int MinorKey() { return strict_mode_; }
+
+  StrictModeFlag strict_mode_;
 };
 
 
@@ -434,18 +451,6 @@
 };
 
 
-class StringCharAtStub: public CodeStub {
- public:
-  StringCharAtStub() {}
-
- private:
-  Major MajorKey() { return StringCharAt; }
-  int MinorKey() { return 0; }
-
-  void Generate(MacroAssembler* masm);
-};
-
-
 class ICCompareStub: public CodeStub {
  public:
   ICCompareStub(Token::Value op, CompareIC::State state)
@@ -623,6 +628,8 @@
   Major MajorKey() { return CEntry; }
   int MinorKey();
 
+  bool NeedsImmovableCode();
+
   const char* GetName() { return "CEntryStub"; }
 };
 
@@ -661,7 +668,8 @@
  public:
   enum Type {
     READ_ELEMENT,
-    NEW_OBJECT
+    NEW_NON_STRICT,
+    NEW_STRICT
   };
 
   explicit ArgumentsAccessStub(Type type) : type_(type) { }
@@ -676,6 +684,19 @@
   void GenerateReadElement(MacroAssembler* masm);
   void GenerateNewObject(MacroAssembler* masm);
 
+  int GetArgumentsBoilerplateIndex() const {
+  return (type_ == NEW_STRICT)
+      ? Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX
+      : Context::ARGUMENTS_BOILERPLATE_INDEX;
+  }
+
+  int GetArgumentsObjectSize() const {
+    if (type_ == NEW_STRICT)
+      return Heap::kArgumentsObjectSizeStrict;
+    else
+      return Heap::kArgumentsObjectSize;
+  }
+
   const char* GetName() { return "ArgumentsAccessStub"; }
 
 #ifdef DEBUG
diff --git a/src/codegen-inl.h b/src/codegen-inl.h
index 5467789..f7da54a 100644
--- a/src/codegen-inl.h
+++ b/src/codegen-inl.h
@@ -55,8 +55,12 @@
 
 Scope* CodeGenerator::scope() { return info_->function()->scope(); }
 
+bool CodeGenerator::is_strict_mode() {
+  return info_->function()->strict_mode();
+}
+
 StrictModeFlag CodeGenerator::strict_mode_flag() {
-  return info_->function()->strict_mode() ? kStrictMode : kNonStrictMode;
+  return is_strict_mode() ? kStrictMode : kNonStrictMode;
 }
 
 } }  // namespace v8::internal
diff --git a/src/codegen.cc b/src/codegen.cc
index e6fcecd..03f64a1 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -61,9 +61,6 @@
 #undef __
 
 
-CodeGenerator* CodeGeneratorScope::top_ = NULL;
-
-
 void CodeGenerator::ProcessDeferred() {
   while (!deferred_.is_empty()) {
     DeferredCode* code = deferred_.RemoveLast();
@@ -129,7 +126,7 @@
   bool print_json_ast = false;
   const char* ftype;
 
-  if (Bootstrapper::IsActive()) {
+  if (Isolate::Current()->bootstrapper()->IsActive()) {
     print_source = FLAG_print_builtin_source;
     print_ast = FLAG_print_builtin_ast;
     print_json_ast = FLAG_print_builtin_json_ast;
@@ -178,13 +175,17 @@
 Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
                                              Code::Flags flags,
                                              CompilationInfo* info) {
+  Isolate* isolate = info->isolate();
+
   // Allocate and install the code.
   CodeDesc desc;
   masm->GetCode(&desc);
-  Handle<Code> code = Factory::NewCode(desc, flags, masm->CodeObject());
+  Handle<Code> code =
+      isolate->factory()->NewCode(desc, flags, masm->CodeObject());
 
   if (!code.is_null()) {
-    Counters::total_compiled_code_size.Increment(code->instruction_size());
+    isolate->counters()->total_compiled_code_size()->Increment(
+        code->instruction_size());
   }
   return code;
 }
@@ -192,7 +193,7 @@
 
 void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
 #ifdef ENABLE_DISASSEMBLER
-  bool print_code = Bootstrapper::IsActive()
+  bool print_code = Isolate::Current()->bootstrapper()->IsActive()
       ? FLAG_print_builtin_code
       : (FLAG_print_code || (info->IsOptimizing() && FLAG_print_opt_code));
   Vector<const char> filter = CStrVector(FLAG_hydrogen_filter);
@@ -238,7 +239,8 @@
   Handle<Script> script = info->script();
   if (!script->IsUndefined() && !script->source()->IsUndefined()) {
     int len = String::cast(script->source())->length();
-    Counters::total_old_codegen_source_size.Increment(len);
+    Counters* counters = info->isolate()->counters();
+    counters->total_old_codegen_source_size()->Increment(len);
   }
   if (FLAG_trace_codegen) {
     PrintF("Classic Compiler - ");
@@ -251,10 +253,10 @@
   masm.positions_recorder()->StartGDBJITLineInfoRecording();
 #endif
   CodeGenerator cgen(&masm);
-  CodeGeneratorScope scope(&cgen);
+  CodeGeneratorScope scope(Isolate::Current(), &cgen);
   cgen.Generate(info);
   if (cgen.HasStackOverflow()) {
-    ASSERT(!Top::has_pending_exception());
+    ASSERT(!Isolate::Current()->has_pending_exception());
     return false;
   }
 
@@ -279,12 +281,15 @@
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
 
+
+static Vector<const char> kRegexp = CStrVector("regexp");
+
+
 bool CodeGenerator::ShouldGenerateLog(Expression* type) {
   ASSERT(type != NULL);
-  if (!Logger::is_logging() && !CpuProfiler::is_profiling()) return false;
+  if (!LOGGER->is_logging() && !CpuProfiler::is_profiling()) 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;
   }
@@ -317,7 +322,7 @@
   if (globals == 0) return;
 
   // Compute array of global variable and function declarations.
-  Handle<FixedArray> array = Factory::NewFixedArray(2 * globals, TENURED);
+  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();
@@ -374,7 +379,7 @@
 bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
   ZoneList<Expression*>* args = node->arguments();
   Handle<String> name = node->name();
-  Runtime::Function* function = node->function();
+  const Runtime::Function* function = node->function();
   if (function != NULL && function->intrinsic_type == Runtime::INLINE) {
     int lookup_index = static_cast<int>(function->function_id) -
         static_cast<int>(Runtime::kFirstInlineFunction);
@@ -475,8 +480,13 @@
 
 void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
   switch (type_) {
-    case READ_ELEMENT: GenerateReadElement(masm); break;
-    case NEW_OBJECT: GenerateNewObject(masm); break;
+    case READ_ELEMENT:
+      GenerateReadElement(masm);
+      break;
+    case NEW_NON_STRICT:
+    case NEW_STRICT:
+      GenerateNewObject(masm);
+      break;
   }
 }
 
diff --git a/src/codegen.h b/src/codegen.h
index 23b36f0..aa31999 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -92,26 +92,26 @@
 // of active code generators.
 class CodeGeneratorScope BASE_EMBEDDED {
  public:
-  explicit CodeGeneratorScope(CodeGenerator* cgen) {
-    previous_ = top_;
-    top_ = cgen;
+  explicit CodeGeneratorScope(Isolate* isolate, CodeGenerator* cgen)
+      : isolate_(isolate) {
+    previous_ = isolate->current_code_generator();
+    isolate->set_current_code_generator(cgen);
   }
 
   ~CodeGeneratorScope() {
-    top_ = previous_;
+    isolate_->set_current_code_generator(previous_);
   }
 
-  static CodeGenerator* Current() {
-    ASSERT(top_ != NULL);
-    return top_;
+  static CodeGenerator* Current(Isolate* isolate) {
+    ASSERT(isolate->current_code_generator() != NULL);
+    return isolate->current_code_generator();
   }
 
  private:
-  static CodeGenerator* top_;
   CodeGenerator* previous_;
+  Isolate* isolate_;
 };
 
-
 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
 
 // State of used registers in a virtual frame.
diff --git a/src/compilation-cache.cc b/src/compilation-cache.cc
index cccb7a4..5bd8bf3 100644
--- a/src/compilation-cache.cc
+++ b/src/compilation-cache.cc
@@ -33,8 +33,6 @@
 namespace v8 {
 namespace internal {
 
-// The number of sub caches covering the different types to cache.
-static const int kSubCacheCount = 4;
 
 // The number of generations for each sub cache.
 // The number of ScriptGenerations is carefully chosen based on histograms.
@@ -47,162 +45,32 @@
 // Initial size of each compilation cache table allocated.
 static const int kInitialCacheSize = 64;
 
-// Index for the first generation in the cache.
-static const int kFirstGeneration = 0;
 
-// The compilation cache consists of several generational sub-caches which uses
-// this class as a base class. A sub-cache contains a compilation cache tables
-// for each generation of the sub-cache. Since the same source code string has
-// different compiled code for scripts and evals, we use separate sub-caches
-// for different compilation modes, to avoid retrieving the wrong result.
-class CompilationSubCache {
- public:
-  explicit CompilationSubCache(int generations): generations_(generations) {
-    tables_ = NewArray<Object*>(generations);
+CompilationCache::CompilationCache(Isolate* isolate)
+    : isolate_(isolate),
+      script_(isolate, kScriptGenerations),
+      eval_global_(isolate, kEvalGlobalGenerations),
+      eval_contextual_(isolate, kEvalContextualGenerations),
+      reg_exp_(isolate, kRegExpGenerations),
+      enabled_(true),
+      eager_optimizing_set_(NULL) {
+  CompilationSubCache* subcaches[kSubCacheCount] =
+    {&script_, &eval_global_, &eval_contextual_, &reg_exp_};
+  for (int i = 0; i < kSubCacheCount; ++i) {
+    subcaches_[i] = subcaches[i];
   }
-
-  ~CompilationSubCache() { DeleteArray(tables_); }
-
-  // Get the compilation cache tables for a specific generation.
-  Handle<CompilationCacheTable> GetTable(int generation);
-
-  // Accessors for first generation.
-  Handle<CompilationCacheTable> GetFirstTable() {
-    return GetTable(kFirstGeneration);
-  }
-  void SetFirstTable(Handle<CompilationCacheTable> value) {
-    ASSERT(kFirstGeneration < generations_);
-    tables_[kFirstGeneration] = *value;
-  }
-
-  // Age the sub-cache by evicting the oldest generation and creating a new
-  // young generation.
-  void Age();
-
-  // GC support.
-  void Iterate(ObjectVisitor* v);
-  void IterateFunctions(ObjectVisitor* v);
-
-  // Clear this sub-cache evicting all its content.
-  void Clear();
-
-  // Remove given shared function info from sub-cache.
-  void Remove(Handle<SharedFunctionInfo> function_info);
-
-  // Number of generations in this sub-cache.
-  inline int generations() { return generations_; }
-
- private:
-  int generations_;  // Number of generations.
-  Object** tables_;  // Compilation cache tables - one for each generation.
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationSubCache);
-};
-
-
-// Sub-cache for scripts.
-class CompilationCacheScript : public CompilationSubCache {
- public:
-  explicit CompilationCacheScript(int generations)
-      : CompilationSubCache(generations) { }
-
-  Handle<SharedFunctionInfo> Lookup(Handle<String> source,
-                                    Handle<Object> name,
-                                    int line_offset,
-                                    int column_offset);
-  void Put(Handle<String> source, Handle<SharedFunctionInfo> function_info);
-
- private:
-  MUST_USE_RESULT MaybeObject* TryTablePut(
-      Handle<String> source, Handle<SharedFunctionInfo> function_info);
-
-  // Note: Returns a new hash table if operation results in expansion.
-  Handle<CompilationCacheTable> TablePut(
-      Handle<String> source, Handle<SharedFunctionInfo> function_info);
-
-  bool HasOrigin(Handle<SharedFunctionInfo> function_info,
-                 Handle<Object> name,
-                 int line_offset,
-                 int column_offset);
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheScript);
-};
-
-
-// Sub-cache for eval scripts.
-class CompilationCacheEval: public CompilationSubCache {
- public:
-  explicit CompilationCacheEval(int generations)
-      : CompilationSubCache(generations) { }
-
-  Handle<SharedFunctionInfo> Lookup(Handle<String> source,
-                                    Handle<Context> context,
-                                    StrictModeFlag strict_mode);
-
-  void Put(Handle<String> source,
-           Handle<Context> context,
-           Handle<SharedFunctionInfo> function_info);
-
- private:
-  MUST_USE_RESULT MaybeObject* TryTablePut(
-      Handle<String> source,
-      Handle<Context> context,
-      Handle<SharedFunctionInfo> function_info);
-
-
-  // Note: Returns a new hash table if operation results in expansion.
-  Handle<CompilationCacheTable> TablePut(
-      Handle<String> source,
-      Handle<Context> context,
-      Handle<SharedFunctionInfo> function_info);
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEval);
-};
-
-
-// Sub-cache for regular expressions.
-class CompilationCacheRegExp: public CompilationSubCache {
- public:
-  explicit CompilationCacheRegExp(int generations)
-      : CompilationSubCache(generations) { }
-
-  Handle<FixedArray> Lookup(Handle<String> source, JSRegExp::Flags flags);
-
-  void Put(Handle<String> source,
-           JSRegExp::Flags flags,
-           Handle<FixedArray> data);
- private:
-  MUST_USE_RESULT MaybeObject* TryTablePut(Handle<String> source,
-                                           JSRegExp::Flags flags,
-                                           Handle<FixedArray> data);
-
-  // Note: Returns a new hash table if operation results in expansion.
-  Handle<CompilationCacheTable> TablePut(Handle<String> source,
-                                         JSRegExp::Flags flags,
-                                         Handle<FixedArray> data);
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheRegExp);
-};
-
-
-// Statically allocate all the sub-caches.
-static CompilationCacheScript script(kScriptGenerations);
-static CompilationCacheEval eval_global(kEvalGlobalGenerations);
-static CompilationCacheEval eval_contextual(kEvalContextualGenerations);
-static CompilationCacheRegExp reg_exp(kRegExpGenerations);
-static CompilationSubCache* subcaches[kSubCacheCount] =
-    {&script, &eval_global, &eval_contextual, &reg_exp};
-
-
-// Current enable state of the compilation cache.
-static bool enabled = true;
-static inline bool IsEnabled() {
-  return FLAG_compilation_cache && enabled;
 }
 
 
-static Handle<CompilationCacheTable> AllocateTable(int size) {
-  CALL_HEAP_FUNCTION(CompilationCacheTable::Allocate(size),
+CompilationCache::~CompilationCache() {
+  delete eager_optimizing_set_;
+  eager_optimizing_set_ = NULL;
+}
+
+
+static Handle<CompilationCacheTable> AllocateTable(Isolate* isolate, int size) {
+  CALL_HEAP_FUNCTION(isolate,
+                     CompilationCacheTable::Allocate(size),
                      CompilationCacheTable);
 }
 
@@ -211,17 +79,16 @@
   ASSERT(generation < generations_);
   Handle<CompilationCacheTable> result;
   if (tables_[generation]->IsUndefined()) {
-    result = AllocateTable(kInitialCacheSize);
+    result = AllocateTable(isolate(), kInitialCacheSize);
     tables_[generation] = *result;
   } else {
     CompilationCacheTable* table =
         CompilationCacheTable::cast(tables_[generation]);
-    result = Handle<CompilationCacheTable>(table);
+    result = Handle<CompilationCacheTable>(table, isolate());
   }
   return result;
 }
 
-
 void CompilationSubCache::Age() {
   // Age the generations implicitly killing off the oldest.
   for (int i = generations_ - 1; i > 0; i--) {
@@ -229,12 +96,12 @@
   }
 
   // Set the first generation as unborn.
-  tables_[0] = Heap::undefined_value();
+  tables_[0] = isolate()->heap()->undefined_value();
 }
 
 
 void CompilationSubCache::IterateFunctions(ObjectVisitor* v) {
-  Object* undefined = Heap::raw_unchecked_undefined_value();
+  Object* undefined = isolate()->heap()->raw_unchecked_undefined_value();
   for (int i = 0; i < generations_; i++) {
     if (tables_[i] != undefined) {
       reinterpret_cast<CompilationCacheTable*>(tables_[i])->IterateElements(v);
@@ -249,14 +116,14 @@
 
 
 void CompilationSubCache::Clear() {
-  MemsetPointer(tables_, Heap::undefined_value(), generations_);
+  MemsetPointer(tables_, isolate()->heap()->undefined_value(), generations_);
 }
 
 
 void CompilationSubCache::Remove(Handle<SharedFunctionInfo> function_info) {
   // Probe the script generation tables. Make sure not to leak handles
   // into the caller's handle scope.
-  { HandleScope scope;
+  { HandleScope scope(isolate());
     for (int generation = 0; generation < generations(); generation++) {
       Handle<CompilationCacheTable> table = GetTable(generation);
       table->Remove(*function_info);
@@ -265,6 +132,13 @@
 }
 
 
+CompilationCacheScript::CompilationCacheScript(Isolate* isolate,
+                                               int generations)
+    : CompilationSubCache(isolate, generations),
+      script_histogram_(NULL),
+      script_histogram_initialized_(false) { }
+
+
 // 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.
@@ -274,7 +148,7 @@
     int line_offset,
     int column_offset) {
   Handle<Script> script =
-      Handle<Script>(Script::cast(function_info->script()));
+      Handle<Script>(Script::cast(function_info->script()), isolate());
   // If the script name isn't set, the boilerplate script should have
   // an undefined name to have the same origin.
   if (name.is_null()) {
@@ -303,10 +177,10 @@
 
   // Probe the script generation tables. Make sure not to leak handles
   // into the caller's handle scope.
-  { HandleScope scope;
+  { HandleScope scope(isolate());
     for (generation = 0; generation < generations(); generation++) {
       Handle<CompilationCacheTable> table = GetTable(generation);
-      Handle<Object> probe(table->Lookup(*source));
+      Handle<Object> probe(table->Lookup(*source), isolate());
       if (probe->IsSharedFunctionInfo()) {
         Handle<SharedFunctionInfo> function_info =
             Handle<SharedFunctionInfo>::cast(probe);
@@ -320,30 +194,34 @@
     }
   }
 
-  static void* script_histogram = StatsTable::CreateHistogram(
-      "V8.ScriptCache",
-      0,
-      kScriptGenerations,
-      kScriptGenerations + 1);
+  if (!script_histogram_initialized_) {
+    script_histogram_ = isolate()->stats_table()->CreateHistogram(
+        "V8.ScriptCache",
+        0,
+        kScriptGenerations,
+        kScriptGenerations + 1);
+    script_histogram_initialized_ = true;
+  }
 
-  if (script_histogram != NULL) {
+  if (script_histogram_ != NULL) {
     // The level NUMBER_OF_SCRIPT_GENERATIONS is equivalent to a cache miss.
-    StatsTable::AddHistogramSample(script_histogram, generation);
+    isolate()->stats_table()->AddHistogramSample(script_histogram_, generation);
   }
 
   // Once outside the manacles of the handle scope, we need to recheck
   // to see if we actually found a cached script. If so, we return a
   // handle created in the caller's handle scope.
   if (result != NULL) {
-    Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
+    Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result),
+                                      isolate());
     ASSERT(HasOrigin(shared, name, line_offset, column_offset));
     // If the script was found in a later generation, we promote it to
     // the first generation to let it survive longer in the cache.
     if (generation != 0) Put(source, shared);
-    Counters::compilation_cache_hits.Increment();
+    isolate()->counters()->compilation_cache_hits()->Increment();
     return shared;
   } else {
-    Counters::compilation_cache_misses.Increment();
+    isolate()->counters()->compilation_cache_misses()->Increment();
     return Handle<SharedFunctionInfo>::null();
   }
 }
@@ -360,13 +238,15 @@
 Handle<CompilationCacheTable> CompilationCacheScript::TablePut(
     Handle<String> source,
     Handle<SharedFunctionInfo> function_info) {
-  CALL_HEAP_FUNCTION(TryTablePut(source, function_info), CompilationCacheTable);
+  CALL_HEAP_FUNCTION(isolate(),
+                     TryTablePut(source, function_info),
+                     CompilationCacheTable);
 }
 
 
 void CompilationCacheScript::Put(Handle<String> source,
                                  Handle<SharedFunctionInfo> function_info) {
-  HandleScope scope;
+  HandleScope scope(isolate());
   SetFirstTable(TablePut(source, function_info));
 }
 
@@ -380,7 +260,7 @@
   // having cleared the cache.
   Object* result = NULL;
   int generation;
-  { HandleScope scope;
+  { HandleScope scope(isolate());
     for (generation = 0; generation < generations(); generation++) {
       Handle<CompilationCacheTable> table = GetTable(generation);
       result = table->LookupEval(*source, *context, strict_mode);
@@ -391,14 +271,14 @@
   }
   if (result->IsSharedFunctionInfo()) {
     Handle<SharedFunctionInfo>
-        function_info(SharedFunctionInfo::cast(result));
+        function_info(SharedFunctionInfo::cast(result), isolate());
     if (generation != 0) {
       Put(source, context, function_info);
     }
-    Counters::compilation_cache_hits.Increment();
+    isolate()->counters()->compilation_cache_hits()->Increment();
     return function_info;
   } else {
-    Counters::compilation_cache_misses.Increment();
+    isolate()->counters()->compilation_cache_misses()->Increment();
     return Handle<SharedFunctionInfo>::null();
   }
 }
@@ -417,7 +297,8 @@
     Handle<String> source,
     Handle<Context> context,
     Handle<SharedFunctionInfo> function_info) {
-  CALL_HEAP_FUNCTION(TryTablePut(source, context, function_info),
+  CALL_HEAP_FUNCTION(isolate(),
+                     TryTablePut(source, context, function_info),
                      CompilationCacheTable);
 }
 
@@ -425,7 +306,7 @@
 void CompilationCacheEval::Put(Handle<String> source,
                                Handle<Context> context,
                                Handle<SharedFunctionInfo> function_info) {
-  HandleScope scope;
+  HandleScope scope(isolate());
   SetFirstTable(TablePut(source, context, function_info));
 }
 
@@ -437,7 +318,7 @@
   // having cleared the cache.
   Object* result = NULL;
   int generation;
-  { HandleScope scope;
+  { HandleScope scope(isolate());
     for (generation = 0; generation < generations(); generation++) {
       Handle<CompilationCacheTable> table = GetTable(generation);
       result = table->LookupRegExp(*source, flags);
@@ -447,14 +328,14 @@
     }
   }
   if (result->IsFixedArray()) {
-    Handle<FixedArray> data(FixedArray::cast(result));
+    Handle<FixedArray> data(FixedArray::cast(result), isolate());
     if (generation != 0) {
       Put(source, flags, data);
     }
-    Counters::compilation_cache_hits.Increment();
+    isolate()->counters()->compilation_cache_hits()->Increment();
     return data;
   } else {
-    Counters::compilation_cache_misses.Increment();
+    isolate()->counters()->compilation_cache_misses()->Increment();
     return Handle<FixedArray>::null();
   }
 }
@@ -473,14 +354,16 @@
     Handle<String> source,
     JSRegExp::Flags flags,
     Handle<FixedArray> data) {
-  CALL_HEAP_FUNCTION(TryTablePut(source, flags, data), CompilationCacheTable);
+  CALL_HEAP_FUNCTION(isolate(),
+                     TryTablePut(source, flags, data),
+                     CompilationCacheTable);
 }
 
 
 void CompilationCacheRegExp::Put(Handle<String> source,
                                  JSRegExp::Flags flags,
                                  Handle<FixedArray> data) {
-  HandleScope scope;
+  HandleScope scope(isolate());
   SetFirstTable(TablePut(source, flags, data));
 }
 
@@ -488,9 +371,9 @@
 void CompilationCache::Remove(Handle<SharedFunctionInfo> function_info) {
   if (!IsEnabled()) return;
 
-  eval_global.Remove(function_info);
-  eval_contextual.Remove(function_info);
-  script.Remove(function_info);
+  eval_global_.Remove(function_info);
+  eval_contextual_.Remove(function_info);
+  script_.Remove(function_info);
 }
 
 
@@ -502,7 +385,7 @@
     return Handle<SharedFunctionInfo>::null();
   }
 
-  return script.Lookup(source, name, line_offset, column_offset);
+  return script_.Lookup(source, name, line_offset, column_offset);
 }
 
 
@@ -517,9 +400,9 @@
 
   Handle<SharedFunctionInfo> result;
   if (is_global) {
-    result = eval_global.Lookup(source, context, strict_mode);
+    result = eval_global_.Lookup(source, context, strict_mode);
   } else {
-    result = eval_contextual.Lookup(source, context, strict_mode);
+    result = eval_contextual_.Lookup(source, context, strict_mode);
   }
   return result;
 }
@@ -531,7 +414,7 @@
     return Handle<FixedArray>::null();
   }
 
-  return reg_exp.Lookup(source, flags);
+  return reg_exp_.Lookup(source, flags);
 }
 
 
@@ -541,7 +424,7 @@
     return;
   }
 
-  script.Put(source, function_info);
+  script_.Put(source, function_info);
 }
 
 
@@ -553,11 +436,11 @@
     return;
   }
 
-  HandleScope scope;
+  HandleScope scope(isolate());
   if (is_global) {
-    eval_global.Put(source, context, function_info);
+    eval_global_.Put(source, context, function_info);
   } else {
-    eval_contextual.Put(source, context, function_info);
+    eval_contextual_.Put(source, context, function_info);
   }
 }
 
@@ -570,7 +453,7 @@
     return;
   }
 
-  reg_exp.Put(source, flags, data);
+  reg_exp_.Put(source, flags, data);
 }
 
 
@@ -579,9 +462,11 @@
 }
 
 
-static HashMap* EagerOptimizingSet() {
-  static HashMap map(&SourceHashCompare);
-  return &map;
+HashMap* CompilationCache::EagerOptimizingSet() {
+  if (eager_optimizing_set_ == NULL) {
+    eager_optimizing_set_ = new HashMap(&SourceHashCompare);
+  }
+  return eager_optimizing_set_;
 }
 
 
@@ -615,38 +500,39 @@
 
 void CompilationCache::Clear() {
   for (int i = 0; i < kSubCacheCount; i++) {
-    subcaches[i]->Clear();
+    subcaches_[i]->Clear();
   }
 }
 
+
 void CompilationCache::Iterate(ObjectVisitor* v) {
   for (int i = 0; i < kSubCacheCount; i++) {
-    subcaches[i]->Iterate(v);
+    subcaches_[i]->Iterate(v);
   }
 }
 
 
 void CompilationCache::IterateFunctions(ObjectVisitor* v) {
   for (int i = 0; i < kSubCacheCount; i++) {
-    subcaches[i]->IterateFunctions(v);
+    subcaches_[i]->IterateFunctions(v);
   }
 }
 
 
 void CompilationCache::MarkCompactPrologue() {
   for (int i = 0; i < kSubCacheCount; i++) {
-    subcaches[i]->Age();
+    subcaches_[i]->Age();
   }
 }
 
 
 void CompilationCache::Enable() {
-  enabled = true;
+  enabled_ = true;
 }
 
 
 void CompilationCache::Disable() {
-  enabled = false;
+  enabled_ = false;
   Clear();
 }
 
diff --git a/src/compilation-cache.h b/src/compilation-cache.h
index f779a23..887d4e8 100644
--- a/src/compilation-cache.h
+++ b/src/compilation-cache.h
@@ -31,6 +31,152 @@
 namespace v8 {
 namespace internal {
 
+class HashMap;
+
+// The compilation cache consists of several generational sub-caches which uses
+// this class as a base class. A sub-cache contains a compilation cache tables
+// for each generation of the sub-cache. Since the same source code string has
+// different compiled code for scripts and evals, we use separate sub-caches
+// for different compilation modes, to avoid retrieving the wrong result.
+class CompilationSubCache {
+ public:
+  CompilationSubCache(Isolate* isolate, int generations)
+      : isolate_(isolate),
+        generations_(generations) {
+    tables_ = NewArray<Object*>(generations);
+  }
+
+  ~CompilationSubCache() { DeleteArray(tables_); }
+
+  // Index for the first generation in the cache.
+  static const int kFirstGeneration = 0;
+
+  // Get the compilation cache tables for a specific generation.
+  Handle<CompilationCacheTable> GetTable(int generation);
+
+  // Accessors for first generation.
+  Handle<CompilationCacheTable> GetFirstTable() {
+    return GetTable(kFirstGeneration);
+  }
+  void SetFirstTable(Handle<CompilationCacheTable> value) {
+    ASSERT(kFirstGeneration < generations_);
+    tables_[kFirstGeneration] = *value;
+  }
+
+  // Age the sub-cache by evicting the oldest generation and creating a new
+  // young generation.
+  void Age();
+
+  // GC support.
+  void Iterate(ObjectVisitor* v);
+  void IterateFunctions(ObjectVisitor* v);
+
+  // Clear this sub-cache evicting all its content.
+  void Clear();
+
+  // Remove given shared function info from sub-cache.
+  void Remove(Handle<SharedFunctionInfo> function_info);
+
+  // Number of generations in this sub-cache.
+  inline int generations() { return generations_; }
+
+ protected:
+  Isolate* isolate() { return isolate_; }
+
+ private:
+  Isolate* isolate_;
+  int generations_;  // Number of generations.
+  Object** tables_;  // Compilation cache tables - one for each generation.
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationSubCache);
+};
+
+
+// Sub-cache for scripts.
+class CompilationCacheScript : public CompilationSubCache {
+ public:
+  CompilationCacheScript(Isolate* isolate, int generations);
+
+  Handle<SharedFunctionInfo> Lookup(Handle<String> source,
+                                    Handle<Object> name,
+                                    int line_offset,
+                                    int column_offset);
+  void Put(Handle<String> source, Handle<SharedFunctionInfo> function_info);
+
+ private:
+  MUST_USE_RESULT MaybeObject* TryTablePut(
+      Handle<String> source, Handle<SharedFunctionInfo> function_info);
+
+  // Note: Returns a new hash table if operation results in expansion.
+  Handle<CompilationCacheTable> TablePut(
+      Handle<String> source, Handle<SharedFunctionInfo> function_info);
+
+  bool HasOrigin(Handle<SharedFunctionInfo> function_info,
+                 Handle<Object> name,
+                 int line_offset,
+                 int column_offset);
+
+  void* script_histogram_;
+  bool script_histogram_initialized_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheScript);
+};
+
+
+// Sub-cache for eval scripts.
+class CompilationCacheEval: public CompilationSubCache {
+ public:
+  CompilationCacheEval(Isolate* isolate, int generations)
+      : CompilationSubCache(isolate, generations) { }
+
+  Handle<SharedFunctionInfo> Lookup(Handle<String> source,
+                                    Handle<Context> context,
+                                    StrictModeFlag strict_mode);
+
+  void Put(Handle<String> source,
+           Handle<Context> context,
+           Handle<SharedFunctionInfo> function_info);
+
+ private:
+  MUST_USE_RESULT MaybeObject* TryTablePut(
+      Handle<String> source,
+      Handle<Context> context,
+      Handle<SharedFunctionInfo> function_info);
+
+  // Note: Returns a new hash table if operation results in expansion.
+  Handle<CompilationCacheTable> TablePut(
+      Handle<String> source,
+      Handle<Context> context,
+      Handle<SharedFunctionInfo> function_info);
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEval);
+};
+
+
+// Sub-cache for regular expressions.
+class CompilationCacheRegExp: public CompilationSubCache {
+ public:
+  CompilationCacheRegExp(Isolate* isolate, int generations)
+      : CompilationSubCache(isolate, generations) { }
+
+  Handle<FixedArray> Lookup(Handle<String> source, JSRegExp::Flags flags);
+
+  void Put(Handle<String> source,
+           JSRegExp::Flags flags,
+           Handle<FixedArray> data);
+ private:
+  MUST_USE_RESULT MaybeObject* TryTablePut(Handle<String> source,
+                                      JSRegExp::Flags flags,
+                                      Handle<FixedArray> data);
+
+  // Note: Returns a new hash table if operation results in expansion.
+  Handle<CompilationCacheTable> TablePut(Handle<String> source,
+                                         JSRegExp::Flags flags,
+                                         Handle<FixedArray> data);
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheRegExp);
+};
+
 
 // The compilation cache keeps shared function infos for compiled
 // scripts and evals. The shared function infos are looked up using
@@ -41,69 +187,98 @@
   // Finds the script shared function info 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<SharedFunctionInfo> LookupScript(Handle<String> source,
-                                                 Handle<Object> name,
-                                                 int line_offset,
-                                                 int column_offset);
+  Handle<SharedFunctionInfo> LookupScript(Handle<String> source,
+                                          Handle<Object> name,
+                                          int line_offset,
+                                          int column_offset);
 
   // Finds the shared function info 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<SharedFunctionInfo> LookupEval(Handle<String> source,
-                                               Handle<Context> context,
-                                               bool is_global,
-                                               StrictModeFlag strict_mode);
+  Handle<SharedFunctionInfo> LookupEval(Handle<String> source,
+                                        Handle<Context> context,
+                                        bool is_global,
+                                        StrictModeFlag strict_mode);
 
   // 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);
+  Handle<FixedArray> LookupRegExp(Handle<String> source,
+                                  JSRegExp::Flags flags);
 
   // Associate the (source, kind) pair to the shared function
   // info. This may overwrite an existing mapping.
-  static void PutScript(Handle<String> source,
-                        Handle<SharedFunctionInfo> function_info);
+  void PutScript(Handle<String> source,
+                 Handle<SharedFunctionInfo> function_info);
 
   // Associate the (source, context->closure()->shared(), kind) triple
   // with the shared function info. This may overwrite an existing mapping.
-  static void PutEval(Handle<String> source,
-                      Handle<Context> context,
-                      bool is_global,
-                      Handle<SharedFunctionInfo> function_info);
+  void PutEval(Handle<String> source,
+               Handle<Context> context,
+               bool is_global,
+               Handle<SharedFunctionInfo> function_info);
 
   // 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);
+  void PutRegExp(Handle<String> source,
+                 JSRegExp::Flags flags,
+                 Handle<FixedArray> data);
 
   // Support for eager optimization tracking.
-  static bool ShouldOptimizeEagerly(Handle<JSFunction> function);
-  static void MarkForEagerOptimizing(Handle<JSFunction> function);
-  static void MarkForLazyOptimizing(Handle<JSFunction> function);
+  bool ShouldOptimizeEagerly(Handle<JSFunction> function);
+  void MarkForEagerOptimizing(Handle<JSFunction> function);
+  void MarkForLazyOptimizing(Handle<JSFunction> function);
 
   // Reset the eager optimization tracking data.
-  static void ResetEagerOptimizingData();
+  void ResetEagerOptimizingData();
 
   // Clear the cache - also used to initialize the cache at startup.
-  static void Clear();
+  void Clear();
 
   // Remove given shared function info from all caches.
-  static void Remove(Handle<SharedFunctionInfo> function_info);
+  void Remove(Handle<SharedFunctionInfo> function_info);
 
   // GC support.
-  static void Iterate(ObjectVisitor* v);
-  static void IterateFunctions(ObjectVisitor* v);
+  void Iterate(ObjectVisitor* v);
+  void IterateFunctions(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.
-  static void MarkCompactPrologue();
+  void MarkCompactPrologue();
 
   // Enable/disable compilation cache. Used by debugger to disable compilation
   // cache during debugging to make sure new scripts are always compiled.
-  static void Enable();
-  static void Disable();
+  void Enable();
+  void Disable();
+ private:
+  explicit CompilationCache(Isolate* isolate);
+  ~CompilationCache();
+
+  HashMap* EagerOptimizingSet();
+
+  // The number of sub caches covering the different types to cache.
+  static const int kSubCacheCount = 4;
+
+  bool IsEnabled() { return FLAG_compilation_cache && enabled_; }
+
+  Isolate* isolate() { return isolate_; }
+
+  Isolate* isolate_;
+
+  CompilationCacheScript script_;
+  CompilationCacheEval eval_global_;
+  CompilationCacheEval eval_contextual_;
+  CompilationCacheRegExp reg_exp_;
+  CompilationSubCache* subcaches_[kSubCacheCount];
+
+  // Current enable state of the compilation cache.
+  bool enabled_;
+
+  HashMap* eager_optimizing_set_;
+
+  friend class Isolate;
+
+  DISALLOW_COPY_AND_ASSIGN(CompilationCache);
 };
 
 
diff --git a/src/compiler.cc b/src/compiler.cc
index 667432f..1ec4414 100755
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -51,7 +51,8 @@
 
 
 CompilationInfo::CompilationInfo(Handle<Script> script)
-    : flags_(0),
+    : isolate_(script->GetIsolate()),
+      flags_(0),
       function_(NULL),
       scope_(NULL),
       script_(script),
@@ -64,7 +65,8 @@
 
 
 CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info)
-    : flags_(IsLazy::encode(true)),
+    : isolate_(shared_info->GetIsolate()),
+      flags_(IsLazy::encode(true)),
       function_(NULL),
       scope_(NULL),
       shared_info_(shared_info),
@@ -78,7 +80,8 @@
 
 
 CompilationInfo::CompilationInfo(Handle<JSFunction> closure)
-    : flags_(IsLazy::encode(true)),
+    : isolate_(closure->GetIsolate()),
+      flags_(IsLazy::encode(true)),
       function_(NULL),
       scope_(NULL),
       closure_(closure),
@@ -121,10 +124,11 @@
 // break points has actually been set.
 static bool AlwaysFullCompiler() {
 #ifdef ENABLE_DEBUGGER_SUPPORT
+  Isolate* isolate = Isolate::Current();
   if (V8::UseCrankshaft()) {
-    return FLAG_always_full_compiler || Debug::has_break_points();
+    return FLAG_always_full_compiler || isolate->debug()->has_break_points();
   } else {
-    return FLAG_always_full_compiler || Debugger::IsDebuggerActive();
+    return FLAG_always_full_compiler || isolate->debugger()->IsDebuggerActive();
   }
 #else
   return FLAG_always_full_compiler;
@@ -172,6 +176,8 @@
   ASSERT(code->kind() == Code::FUNCTION);
   code->set_optimizable(false);
   info->SetCode(code);
+  Isolate* isolate = code->GetIsolate();
+  isolate->compilation_cache()->MarkForLazyOptimizing(info->closure());
   if (FLAG_trace_opt) {
     PrintF("[disabled optimization for: ");
     info->closure()->PrintName();
@@ -197,6 +203,10 @@
   Handle<Code> code(info->shared_info()->code());
   ASSERT(code->kind() == Code::FUNCTION);
 
+  // We should never arrive here if optimization has been disabled on the
+  // shared function info.
+  ASSERT(!info->shared_info()->optimization_disabled());
+
   // Fall back to using the full code generator if it's not possible
   // to use the Hydrogen-based optimizing compiler. We already have
   // generated code for this from the shared function object.
@@ -248,7 +258,7 @@
   // performance of the hydrogen-based compiler.
   int64_t start = OS::Ticks();
   bool should_recompile = !info->shared_info()->has_deoptimization_support();
-  if (should_recompile || FLAG_time_hydrogen) {
+  if (should_recompile || FLAG_hydrogen_stats) {
     HPhase phase(HPhase::kFullCodeGen);
     CompilationInfo unoptimized(info->shared_info());
     // Note that we use the same AST that we will use for generating the
@@ -286,7 +296,7 @@
   HGraphBuilder builder(info, &oracle);
   HPhase phase(HPhase::kTotal);
   HGraph* graph = builder.CreateGraph();
-  if (Top::has_pending_exception()) {
+  if (info->isolate()->has_pending_exception()) {
     info->SetCode(Handle<Code>::null());
     return false;
   }
@@ -364,11 +374,12 @@
 static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
   CompilationZoneScope zone_scope(DELETE_ON_EXIT);
 
-  PostponeInterruptsScope postpone;
+  Isolate* isolate = info->isolate();
+  PostponeInterruptsScope postpone(isolate);
 
-  ASSERT(!i::Top::global_context().is_null());
+  ASSERT(!isolate->global_context().is_null());
   Handle<Script> script = info->script();
-  script->set_context_data((*i::Top::global_context())->data());
+  script->set_context_data((*isolate->global_context())->data());
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   if (info->is_eval()) {
@@ -381,15 +392,16 @@
       if (!it.done()) {
         script->set_eval_from_shared(
             JSFunction::cast(it.frame()->function())->shared());
+        Code* code = it.frame()->LookupCode(isolate);
         int offset = static_cast<int>(
-            it.frame()->pc() - it.frame()->code()->instruction_start());
+            it.frame()->pc() - code->instruction_start());
         script->set_eval_from_instructions_offset(Smi::FromInt(offset));
       }
     }
   }
 
   // Notify debugger
-  Debugger::OnBeforeCompile(script);
+  isolate->debugger()->OnBeforeCompile(script);
 #endif
 
   // Only allow non-global compiles for eval.
@@ -401,22 +413,22 @@
   // rest of the function into account to avoid overlap with the
   // parsing statistics.
   HistogramTimer* rate = info->is_eval()
-      ? &Counters::compile_eval
-      : &Counters::compile;
+      ? info->isolate()->counters()->compile_eval()
+      : info->isolate()->counters()->compile();
   HistogramTimerScope timer(rate);
 
   // Compile the code.
   FunctionLiteral* lit = info->function();
-  LiveEditFunctionTracker live_edit_tracker(lit);
+  LiveEditFunctionTracker live_edit_tracker(isolate, lit);
   if (!MakeCode(info)) {
-    Top::StackOverflow();
+    isolate->StackOverflow();
     return Handle<SharedFunctionInfo>::null();
   }
 
   // Allocate function.
   ASSERT(!info->code().is_null());
   Handle<SharedFunctionInfo> result =
-      Factory::NewSharedFunctionInfo(
+      isolate->factory()->NewSharedFunctionInfo(
           lit->name(),
           lit->materialized_literal_count(),
           info->code(),
@@ -426,7 +438,7 @@
   Compiler::SetFunctionInfo(result, lit, true, script);
 
   if (script->name()->IsString()) {
-    PROFILE(CodeCreateEvent(
+    PROFILE(isolate, CodeCreateEvent(
         info->is_eval()
             ? Logger::EVAL_TAG
             : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
@@ -437,13 +449,13 @@
                    script,
                    info->code()));
   } else {
-    PROFILE(CodeCreateEvent(
+    PROFILE(isolate, CodeCreateEvent(
         info->is_eval()
             ? Logger::EVAL_TAG
             : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
         *info->code(),
         *result,
-        Heap::empty_string()));
+        isolate->heap()->empty_string()));
     GDBJIT(AddCode(Handle<String>(), script, info->code()));
   }
 
@@ -454,7 +466,8 @@
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Notify debugger
-  Debugger::OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS);
+  isolate->debugger()->OnAfterCompile(
+      script, Debugger::NO_AFTER_COMPILE_FLAGS);
 #endif
 
   live_edit_tracker.RecordFunctionInfo(result, lit);
@@ -471,20 +484,23 @@
                                              ScriptDataImpl* input_pre_data,
                                              Handle<Object> script_data,
                                              NativesFlag natives) {
+  Isolate* isolate = source->GetIsolate();
   int source_length = source->length();
-  Counters::total_load_size.Increment(source_length);
-  Counters::total_compile_size.Increment(source_length);
+  isolate->counters()->total_load_size()->Increment(source_length);
+  isolate->counters()->total_compile_size()->Increment(source_length);
 
   // The VM is in the COMPILER state until exiting this function.
-  VMState state(COMPILER);
+  VMState state(isolate, COMPILER);
+
+  CompilationCache* compilation_cache = isolate->compilation_cache();
 
   // Do a lookup in the compilation cache but not for extensions.
   Handle<SharedFunctionInfo> result;
   if (extension == NULL) {
-    result = CompilationCache::LookupScript(source,
-                                            script_name,
-                                            line_offset,
-                                            column_offset);
+    result = compilation_cache->LookupScript(source,
+                                             script_name,
+                                             line_offset,
+                                             column_offset);
   }
 
   if (result.is_null()) {
@@ -510,7 +526,7 @@
     }
 
     // Create a script object describing the script to be compiled.
-    Handle<Script> script = Factory::NewScript(source);
+    Handle<Script> script = FACTORY->NewScript(source);
     if (natives == NATIVES_CODE) {
       script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
     }
@@ -520,7 +536,7 @@
       script->set_column_offset(Smi::FromInt(column_offset));
     }
 
-    script->set_data(script_data.is_null() ? Heap::undefined_value()
+    script->set_data(script_data.is_null() ? HEAP->undefined_value()
                                            : *script_data);
 
     // Compile the function and add it to the cache.
@@ -528,9 +544,10 @@
     info.MarkAsGlobal();
     info.SetExtension(extension);
     info.SetPreParseData(pre_data);
+    if (natives == NATIVES_CODE) info.MarkAsAllowingNativesSyntax();
     result = MakeFunctionInfo(&info);
     if (extension == NULL && !result.is_null()) {
-      CompilationCache::PutScript(source, result);
+      compilation_cache->PutScript(source, result);
     }
 
     // Get rid of the pre-parsing data (if necessary).
@@ -539,7 +556,7 @@
     }
   }
 
-  if (result.is_null()) Top::ReportPendingMessages();
+  if (result.is_null()) isolate->ReportPendingMessages();
   return result;
 }
 
@@ -548,24 +565,26 @@
                                                  Handle<Context> context,
                                                  bool is_global,
                                                  StrictModeFlag strict_mode) {
+  Isolate* isolate = source->GetIsolate();
   int source_length = source->length();
-  Counters::total_eval_size.Increment(source_length);
-  Counters::total_compile_size.Increment(source_length);
+  isolate->counters()->total_eval_size()->Increment(source_length);
+  isolate->counters()->total_compile_size()->Increment(source_length);
 
   // The VM is in the COMPILER state until exiting this function.
-  VMState state(COMPILER);
+  VMState state(isolate, COMPILER);
 
   // Do a lookup in the compilation cache; if the entry is not there, invoke
   // the compiler and add the result to the cache.
   Handle<SharedFunctionInfo> result;
-  result = CompilationCache::LookupEval(source,
-                                        context,
-                                        is_global,
-                                        strict_mode);
+  CompilationCache* compilation_cache = isolate->compilation_cache();
+  result = compilation_cache->LookupEval(source,
+                                         context,
+                                         is_global,
+                                         strict_mode);
 
   if (result.is_null()) {
     // Create a script object describing the script to be compiled.
-    Handle<Script> script = Factory::NewScript(source);
+    Handle<Script> script = isolate->factory()->NewScript(source);
     CompilationInfo info(script);
     info.MarkAsEval();
     if (is_global) info.MarkAsGlobal();
@@ -573,11 +592,12 @@
     info.SetCallingContext(context);
     result = MakeFunctionInfo(&info);
     if (!result.is_null()) {
+      CompilationCache* compilation_cache = isolate->compilation_cache();
       // If caller is strict mode, the result must be strict as well,
       // but not the other way around. Consider:
       // eval("'use strict'; ...");
       ASSERT(strict_mode == kNonStrictMode || result->strict_mode());
-      CompilationCache::PutEval(source, context, is_global, result);
+      compilation_cache->PutEval(source, context, is_global, result);
     }
   }
 
@@ -589,29 +609,35 @@
   CompilationZoneScope zone_scope(DELETE_ON_EXIT);
 
   // The VM is in the COMPILER state until exiting this function.
-  VMState state(COMPILER);
+  VMState state(info->isolate(), COMPILER);
 
-  PostponeInterruptsScope postpone;
+  Isolate* isolate = info->isolate();
+  PostponeInterruptsScope postpone(isolate);
 
   Handle<SharedFunctionInfo> shared = info->shared_info();
   int compiled_size = shared->end_position() - shared->start_position();
-  Counters::total_compile_size.Increment(compiled_size);
+  isolate->counters()->total_compile_size()->Increment(compiled_size);
 
   // Generate the AST for the lazily compiled function.
   if (ParserApi::Parse(info)) {
     // Measure how long it takes to do the lazy compilation; only take the
     // rest of the function into account to avoid overlap with the lazy
     // parsing statistics.
-    HistogramTimerScope timer(&Counters::compile_lazy);
+    HistogramTimerScope timer(isolate->counters()->compile_lazy());
 
     // Compile the code.
     if (!MakeCode(info)) {
-      if (!Top::has_pending_exception()) {
-        Top::StackOverflow();
+      if (!isolate->has_pending_exception()) {
+        isolate->StackOverflow();
       }
     } else {
       ASSERT(!info->code().is_null());
       Handle<Code> code = info->code();
+      // Set optimizable to false if this is disallowed by the shared
+      // function info, e.g., we might have flushed the code and must
+      // reset this bit when lazy compiling the code again.
+      if (shared->optimization_disabled()) code->set_optimizable(false);
+
       Handle<JSFunction> function = info->closure();
       RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
 
@@ -648,16 +674,18 @@
         ASSERT(shared->is_compiled());
         shared->set_code_age(0);
 
-        if (V8::UseCrankshaft() && info->AllowOptimize()) {
+        if (info->AllowOptimize() && !shared->optimization_disabled()) {
           // If we're asked to always optimize, we compile the optimized
           // version of the function right away - unless the debugger is
           // active as it makes no sense to compile optimized code then.
-          if (FLAG_always_opt && !Debug::has_break_points()) {
+          if (FLAG_always_opt &&
+              !Isolate::Current()->debug()->has_break_points()) {
             CompilationInfo optimized(function);
             optimized.SetOptimizing(AstNode::kNoNumber);
             return CompileLazy(&optimized);
-          } else if (CompilationCache::ShouldOptimizeEagerly(function)) {
-            RuntimeProfiler::OptimizeSoon(*function);
+          } else if (isolate->compilation_cache()->ShouldOptimizeEagerly(
+              function)) {
+            isolate->runtime_profiler()->OptimizeSoon(*function);
           }
         }
       }
@@ -678,20 +706,20 @@
   info.SetFunction(literal);
   info.SetScope(literal->scope());
 
-  LiveEditFunctionTracker live_edit_tracker(literal);
+  LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal);
   // 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 = literal->AllowsLazyCompilation() &&
-      !LiveEditFunctionTracker::IsActive();
+      !LiveEditFunctionTracker::IsActive(info.isolate());
 
   Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
 
   // Generate code
   if (FLAG_lazy && allow_lazy) {
-    Handle<Code> code(Builtins::builtin(Builtins::LazyCompile));
+    Handle<Code> code = info.isolate()->builtins()->LazyCompile();
     info.SetCode(code);
   } else {
     if (V8::UseCrankshaft()) {
@@ -726,7 +754,7 @@
 
   // Create a shared function info object.
   Handle<SharedFunctionInfo> result =
-      Factory::NewSharedFunctionInfo(literal->name(),
+      FACTORY->NewSharedFunctionInfo(literal->name(),
                                      literal->materialized_literal_count(),
                                      info.code(),
                                      scope_info);
@@ -778,20 +806,23 @@
   // Log the code generation. If source information is available include
   // script name and line number. Check explicitly whether logging is
   // enabled as finding the line number is not free.
-  if (Logger::is_logging() || CpuProfiler::is_profiling()) {
+  if (info->isolate()->logger()->is_logging() || CpuProfiler::is_profiling()) {
     Handle<Script> script = info->script();
     Handle<Code> code = info->code();
-    if (*code == Builtins::builtin(Builtins::LazyCompile)) return;
+    if (*code == info->isolate()->builtins()->builtin(Builtins::kLazyCompile))
+      return;
     if (script->name()->IsString()) {
       int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
       USE(line_num);
-      PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
+      PROFILE(info->isolate(),
+              CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
                               *code,
                               *shared,
                               String::cast(script->name()),
                               line_num));
     } else {
-      PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
+      PROFILE(info->isolate(),
+              CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
                               *code,
                               *shared,
                               shared->DebugName()));
diff --git a/src/compiler.h b/src/compiler.h
index e0a437a..a66c540 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -46,6 +46,10 @@
   explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info);
   explicit CompilationInfo(Handle<JSFunction> closure);
 
+  Isolate* isolate() {
+    ASSERT(Isolate::Current() == isolate_);
+    return isolate_;
+  }
   bool is_lazy() const { return (flags_ & IsLazy::mask()) != 0; }
   bool is_eval() const { return (flags_ & IsEval::mask()) != 0; }
   bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; }
@@ -80,6 +84,12 @@
     ASSERT(is_lazy());
     flags_ |= IsInLoop::encode(true);
   }
+  void MarkAsAllowingNativesSyntax() {
+    flags_ |= IsNativesSyntaxAllowed::encode(true);
+  }
+  bool allows_natives_syntax() const {
+    return IsNativesSyntaxAllowed::decode(flags_);
+  }
   void SetFunction(FunctionLiteral* literal) {
     ASSERT(function_ == NULL);
     function_ = literal;
@@ -136,6 +146,8 @@
   }
 
  private:
+  Isolate* isolate_;
+
   // Compilation mode.
   // BASE is generated by the full codegen, optionally prepared for bailouts.
   // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
@@ -174,6 +186,8 @@
   class IsInLoop: public BitField<bool, 3, 1> {};
   // Strict mode - used in eager compilation.
   class IsStrict: public BitField<bool, 4, 1> {};
+  // Native syntax (%-stuff) allowed?
+  class IsNativesSyntaxAllowed: public BitField<bool, 5, 1> {};
 
   unsigned flags_;
 
@@ -278,8 +292,9 @@
   explicit CompilationZoneScope(ZoneScopeMode mode) : ZoneScope(mode) { }
   virtual ~CompilationZoneScope() {
     if (ShouldDeleteOnExit()) {
-      FrameElement::ClearConstantList();
-      Result::ClearConstantList();
+      Isolate* isolate = Isolate::Current();
+      isolate->frame_element_constant_list()->Clear();
+      isolate->result_constant_list()->Clear();
     }
   }
 };
diff --git a/src/contexts.cc b/src/contexts.cc
index 3ad72a1..520f3dd 100644
--- a/src/contexts.cc
+++ b/src/contexts.cc
@@ -55,7 +55,7 @@
 
   // During bootstrapping, the global object might not be set and we
   // have to search the context chain to find the global context.
-  ASSERT(Bootstrapper::IsActive());
+  ASSERT(Isolate::Current()->bootstrapper()->IsActive());
   Context* current = this;
   while (!current->IsGlobalContext()) {
     JSFunction* closure = JSFunction::cast(current->closure());
@@ -76,7 +76,8 @@
 
 Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
                                int* index_, PropertyAttributes* attributes) {
-  Handle<Context> context(this);
+  Isolate* isolate = GetIsolate();
+  Handle<Context> context(this, isolate);
 
   bool follow_context_chain = (flags & FOLLOW_CONTEXT_CHAIN) != 0;
   *index_ = -1;
@@ -97,7 +98,8 @@
 
     // check extension/with object
     if (context->has_extension()) {
-      Handle<JSObject> extension = Handle<JSObject>(context->extension());
+      Handle<JSObject> extension = Handle<JSObject>(context->extension(),
+                                                    isolate);
       // 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.
@@ -122,7 +124,7 @@
 
       // check non-parameter locals in context
       Handle<SerializedScopeInfo> scope_info(
-          context->closure()->shared()->scope_info());
+          context->closure()->shared()->scope_info(), isolate);
       Variable::Mode mode;
       int index = scope_info->ContextSlotIndex(*name, &mode);
       ASSERT(index < 0 || index >= MIN_CONTEXT_SLOTS);
@@ -155,11 +157,12 @@
       int param_index = scope_info->ParameterIndex(*name);
       if (param_index >= 0) {
         // slot found.
-        int index =
-            scope_info->ContextSlotIndex(Heap::arguments_shadow_symbol(), NULL);
+        int index = scope_info->ContextSlotIndex(
+            isolate->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()));
+        Handle<JSObject> arguments(JSObject::cast(context->get(index)),
+                                   isolate);
+        ASSERT(arguments->HasLocalProperty(isolate->heap()->length_symbol()));
         if (FLAG_trace_contexts) {
           PrintF("=> found parameter %d in arguments object\n", param_index);
         }
@@ -188,9 +191,10 @@
     if (context->IsGlobalContext()) {
       follow_context_chain = false;
     } else if (context->is_function_context()) {
-      context = Handle<Context>(Context::cast(context->closure()->context()));
+      context = Handle<Context>(Context::cast(context->closure()->context()),
+                                isolate);
     } else {
-      context = Handle<Context>(context->previous());
+      context = Handle<Context>(context->previous(), isolate);
     }
   } while (follow_context_chain);
 
@@ -252,7 +256,7 @@
 
   // Check that the context belongs to the weak global contexts list.
   bool found = false;
-  Object* context = Heap::global_contexts_list();
+  Object* context = GetHeap()->global_contexts_list();
   while (!context->IsUndefined()) {
     if (context == this) {
       found = true;
@@ -281,7 +285,7 @@
       } else {
         prev->set_next_function_link(element_function->next_function_link());
       }
-      element_function->set_next_function_link(Heap::undefined_value());
+      element_function->set_next_function_link(GetHeap()->undefined_value());
       return;
     }
     prev = element_function;
@@ -298,7 +302,7 @@
 
 
 void Context::ClearOptimizedFunctions() {
-  set(OPTIMIZED_FUNCTIONS_LIST, Heap::undefined_value());
+  set(OPTIMIZED_FUNCTIONS_LIST, GetHeap()->undefined_value());
 }
 
 
@@ -306,14 +310,17 @@
 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();
+  return Isolate::Current()->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();
+  Isolate* isolate = Isolate::Current();
+  return isolate->heap()->gc_state() != Heap::NOT_IN_GC ||
+      isolate->bootstrapper()->IsActive() ||
+      object->IsGlobalObject();
 }
 #endif
 
diff --git a/src/contexts.h b/src/contexts.h
index d0d54d1..e46619e 100644
--- a/src/contexts.h
+++ b/src/contexts.h
@@ -78,11 +78,18 @@
   V(INSTANTIATE_FUN_INDEX, JSFunction, instantiate_fun) \
   V(CONFIGURE_INSTANCE_FUN_INDEX, JSFunction, configure_instance_fun) \
   V(FUNCTION_MAP_INDEX, Map, function_map) \
+  V(STRICT_MODE_FUNCTION_MAP_INDEX, Map, strict_mode_function_map) \
   V(FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, function_without_prototype_map) \
+  V(STRICT_MODE_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \
+    strict_mode_function_without_prototype_map) \
   V(FUNCTION_INSTANCE_MAP_INDEX, Map, function_instance_map) \
+  V(STRICT_MODE_FUNCTION_INSTANCE_MAP_INDEX, Map, \
+    strict_mode_function_instance_map) \
   V(JS_ARRAY_MAP_INDEX, Map, js_array_map)\
   V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map)\
   V(ARGUMENTS_BOILERPLATE_INDEX, JSObject, arguments_boilerplate) \
+  V(STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX, JSObject, \
+    strict_mode_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) \
@@ -182,11 +189,15 @@
     GLOBAL_PROXY_INDEX = MIN_CONTEXT_SLOTS,
     SECURITY_TOKEN_INDEX,
     ARGUMENTS_BOILERPLATE_INDEX,
+    STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX,
     JS_ARRAY_MAP_INDEX,
     REGEXP_RESULT_MAP_INDEX,
     FUNCTION_MAP_INDEX,
+    STRICT_MODE_FUNCTION_MAP_INDEX,
     FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
+    STRICT_MODE_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
     FUNCTION_INSTANCE_MAP_INDEX,
+    STRICT_MODE_FUNCTION_INSTANCE_MAP_INDEX,
     INITIAL_OBJECT_PROTOTYPE_INDEX,
     BOOLEAN_FUNCTION_INDEX,
     NUMBER_FUNCTION_INDEX,
@@ -257,8 +268,7 @@
 
   GlobalObject* global() {
     Object* result = get(GLOBAL_INDEX);
-    ASSERT(Heap::gc_state() != Heap::NOT_IN_GC ||
-           IsBootstrappingOrGlobalObject(result));
+    ASSERT(IsBootstrappingOrGlobalObject(result));
     return reinterpret_cast<GlobalObject*>(result);
   }
   void set_global(GlobalObject* global) { set(GLOBAL_INDEX, global); }
@@ -277,14 +287,10 @@
   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();
-  }
+  inline bool has_out_of_memory();
 
   // Mark the global context with out of memory.
-  void mark_out_of_memory() {
-    global_context()->set_out_of_memory(Heap::true_value());
-  }
+  inline void mark_out_of_memory();
 
   // The exception holder is the object used as a with object in
   // the implementation of a catch block.
diff --git a/src/conversions.cc b/src/conversions.cc
index a348235..c3d7bdf 100644
--- a/src/conversions.cc
+++ b/src/conversions.cc
@@ -109,9 +109,11 @@
 
 // Returns true if a nonspace found and false if the end has reached.
 template <class Iterator, class EndMark>
-static inline bool AdvanceToNonspace(Iterator* current, EndMark end) {
+static inline bool AdvanceToNonspace(ScannerConstants* scanner_constants,
+                                     Iterator* current,
+                                     EndMark end) {
   while (*current != end) {
-    if (!ScannerConstants::kIsWhiteSpace.get(**current)) return true;
+    if (!scanner_constants->IsWhiteSpace(**current)) return true;
     ++*current;
   }
   return false;
@@ -132,7 +134,8 @@
 
 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
 template <int radix_log_2, class Iterator, class EndMark>
-static double InternalStringToIntDouble(Iterator current,
+static double InternalStringToIntDouble(ScannerConstants* scanner_constants,
+                                        Iterator current,
                                         EndMark end,
                                         bool negative,
                                         bool allow_trailing_junk) {
@@ -157,7 +160,8 @@
     } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
       digit = static_cast<char>(*current) - 'A' + 10;
     } else {
-      if (allow_trailing_junk || !AdvanceToNonspace(&current, end)) {
+      if (allow_trailing_junk ||
+          !AdvanceToNonspace(scanner_constants, &current, end)) {
         break;
       } else {
         return JUNK_STRING_VALUE;
@@ -188,7 +192,8 @@
         exponent += radix_log_2;
       }
 
-      if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
+      if (!allow_trailing_junk &&
+          AdvanceToNonspace(scanner_constants, &current, end)) {
         return JUNK_STRING_VALUE;
       }
 
@@ -232,11 +237,16 @@
 
 
 template <class Iterator, class EndMark>
-static double InternalStringToInt(Iterator current, EndMark end, int radix) {
+static double InternalStringToInt(ScannerConstants* scanner_constants,
+                                  Iterator current,
+                                  EndMark end,
+                                  int radix) {
   const bool allow_trailing_junk = true;
   const double empty_string_val = JUNK_STRING_VALUE;
 
-  if (!AdvanceToNonspace(&current, end)) return empty_string_val;
+  if (!AdvanceToNonspace(scanner_constants, &current, end)) {
+    return empty_string_val;
+  }
 
   bool negative = false;
   bool leading_zero = false;
@@ -244,10 +254,14 @@
   if (*current == '+') {
     // Ignore leading sign; skip following spaces.
     ++current;
-    if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
+    if (!AdvanceToNonspace(scanner_constants, &current, end)) {
+      return JUNK_STRING_VALUE;
+    }
   } else if (*current == '-') {
     ++current;
-    if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
+    if (!AdvanceToNonspace(scanner_constants, &current, end)) {
+      return JUNK_STRING_VALUE;
+    }
     negative = true;
   }
 
@@ -298,21 +312,21 @@
     switch (radix) {
       case 2:
         return InternalStringToIntDouble<1>(
-                   current, end, negative, allow_trailing_junk);
+            scanner_constants, current, end, negative, allow_trailing_junk);
       case 4:
         return InternalStringToIntDouble<2>(
-                   current, end, negative, allow_trailing_junk);
+            scanner_constants, current, end, negative, allow_trailing_junk);
       case 8:
         return InternalStringToIntDouble<3>(
-                   current, end, negative, allow_trailing_junk);
+            scanner_constants, current, end, negative, allow_trailing_junk);
 
       case 16:
         return InternalStringToIntDouble<4>(
-                   current, end, negative, allow_trailing_junk);
+            scanner_constants, current, end, negative, allow_trailing_junk);
 
       case 32:
         return InternalStringToIntDouble<5>(
-                   current, end, negative, allow_trailing_junk);
+            scanner_constants, current, end, negative, allow_trailing_junk);
       default:
         UNREACHABLE();
     }
@@ -337,7 +351,8 @@
       if (current == end) break;
     }
 
-    if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
+    if (!allow_trailing_junk &&
+        AdvanceToNonspace(scanner_constants, &current, end)) {
       return JUNK_STRING_VALUE;
     }
 
@@ -402,7 +417,8 @@
     v = v * multiplier + part;
   } while (!done);
 
-  if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
+  if (!allow_trailing_junk &&
+      AdvanceToNonspace(scanner_constants, &current, end)) {
     return JUNK_STRING_VALUE;
   }
 
@@ -416,7 +432,8 @@
 // 2. *current - gets the current character in the sequence.
 // 3. ++current (advances the position).
 template <class Iterator, class EndMark>
-static double InternalStringToDouble(Iterator current,
+static double InternalStringToDouble(ScannerConstants* scanner_constants,
+                                     Iterator current,
                                      EndMark end,
                                      int flags,
                                      double empty_string_val) {
@@ -428,7 +445,9 @@
   // 'parsing_done'.
   // 4. 'current' is not dereferenced after the 'parsing_done' label.
   // 5. Code before 'parsing_done' may rely on 'current != end'.
-  if (!AdvanceToNonspace(&current, end)) return empty_string_val;
+  if (!AdvanceToNonspace(scanner_constants, &current, end)) {
+    return empty_string_val;
+  }
 
   const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
 
@@ -463,7 +482,8 @@
       return JUNK_STRING_VALUE;
     }
 
-    if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
+    if (!allow_trailing_junk &&
+        AdvanceToNonspace(scanner_constants, &current, end)) {
       return JUNK_STRING_VALUE;
     }
 
@@ -485,7 +505,8 @@
         return JUNK_STRING_VALUE;  // "0x".
       }
 
-      return InternalStringToIntDouble<4>(current,
+      return InternalStringToIntDouble<4>(scanner_constants,
+                                          current,
                                           end,
                                           negative,
                                           allow_trailing_junk);
@@ -621,7 +642,8 @@
     exponent += (sign == '-' ? -num : num);
   }
 
-  if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
+  if (!allow_trailing_junk &&
+      AdvanceToNonspace(scanner_constants, &current, end)) {
     return JUNK_STRING_VALUE;
   }
 
@@ -629,7 +651,8 @@
   exponent += insignificant_digits;
 
   if (octal) {
-    return InternalStringToIntDouble<3>(buffer,
+    return InternalStringToIntDouble<3>(scanner_constants,
+                                        buffer,
                                         buffer + buffer_pos,
                                         negative,
                                         allow_trailing_junk);
@@ -649,18 +672,23 @@
 
 
 double StringToDouble(String* str, int flags, double empty_string_val) {
+  ScannerConstants* scanner_constants =
+      Isolate::Current()->scanner_constants();
   StringShape shape(str);
   if (shape.IsSequentialAscii()) {
     const char* begin = SeqAsciiString::cast(str)->GetChars();
     const char* end = begin + str->length();
-    return InternalStringToDouble(begin, end, flags, empty_string_val);
+    return InternalStringToDouble(scanner_constants, begin, end, flags,
+                                  empty_string_val);
   } else if (shape.IsSequentialTwoByte()) {
     const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
     const uc16* end = begin + str->length();
-    return InternalStringToDouble(begin, end, flags, empty_string_val);
+    return InternalStringToDouble(scanner_constants, begin, end, flags,
+                                  empty_string_val);
   } else {
     StringInputBuffer buffer(str);
-    return InternalStringToDouble(StringInputBufferIterator(&buffer),
+    return InternalStringToDouble(scanner_constants,
+                                  StringInputBufferIterator(&buffer),
                                   StringInputBufferIterator::EndMarker(),
                                   flags,
                                   empty_string_val);
@@ -669,18 +697,21 @@
 
 
 double StringToInt(String* str, int radix) {
+  ScannerConstants* scanner_constants =
+      Isolate::Current()->scanner_constants();
   StringShape shape(str);
   if (shape.IsSequentialAscii()) {
     const char* begin = SeqAsciiString::cast(str)->GetChars();
     const char* end = begin + str->length();
-    return InternalStringToInt(begin, end, radix);
+    return InternalStringToInt(scanner_constants, begin, end, radix);
   } else if (shape.IsSequentialTwoByte()) {
     const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
     const uc16* end = begin + str->length();
-    return InternalStringToInt(begin, end, radix);
+    return InternalStringToInt(scanner_constants, begin, end, radix);
   } else {
     StringInputBuffer buffer(str);
-    return InternalStringToInt(StringInputBufferIterator(&buffer),
+    return InternalStringToInt(scanner_constants,
+                               StringInputBufferIterator(&buffer),
                                StringInputBufferIterator::EndMarker(),
                                radix);
   }
@@ -688,16 +719,22 @@
 
 
 double StringToDouble(const char* str, int flags, double empty_string_val) {
+  ScannerConstants* scanner_constants =
+      Isolate::Current()->scanner_constants();
   const char* end = str + StrLength(str);
-  return InternalStringToDouble(str, end, flags, empty_string_val);
+  return InternalStringToDouble(scanner_constants, str, end, flags,
+                                empty_string_val);
 }
 
 
 double StringToDouble(Vector<const char> str,
                       int flags,
                       double empty_string_val) {
+  ScannerConstants* scanner_constants =
+      Isolate::Current()->scanner_constants();
   const char* end = str.start() + str.length();
-  return InternalStringToDouble(str.start(), end, flags, empty_string_val);
+  return InternalStringToDouble(scanner_constants, str.start(), end, flags,
+                                empty_string_val);
 }
 
 
@@ -1066,4 +1103,23 @@
 }
 
 
+static Mutex* dtoa_lock_one = OS::CreateMutex();
+static Mutex* dtoa_lock_zero = OS::CreateMutex();
+
+
 } }  // namespace v8::internal
+
+
+extern "C" {
+void ACQUIRE_DTOA_LOCK(int n) {
+  ASSERT(n == 0 || n == 1);
+  (n == 0 ? v8::internal::dtoa_lock_zero : v8::internal::dtoa_lock_one)->Lock();
+}
+
+
+void FREE_DTOA_LOCK(int n) {
+  ASSERT(n == 0 || n == 1);
+  (n == 0 ? v8::internal::dtoa_lock_zero : v8::internal::dtoa_lock_one)->
+      Unlock();
+}
+}
diff --git a/src/counters.cc b/src/counters.cc
index 239a5f7..faad6d4 100644
--- a/src/counters.cc
+++ b/src/counters.cc
@@ -28,14 +28,22 @@
 #include "v8.h"
 
 #include "counters.h"
+#include "isolate.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;
+StatsTable::StatsTable()
+    : lookup_function_(NULL),
+      create_histogram_function_(NULL),
+      add_histogram_sample_function_(NULL) {}
+
+
+int* StatsCounter::FindLocationInStatsTable() const {
+  return Isolate::Current()->stats_table()->FindLocation(name_);
+}
+
 
 // Start the timer.
 void StatsCounterTimer::Start() {
@@ -71,8 +79,15 @@
 
     // Compute the delta between start and stop, in milliseconds.
     int milliseconds = static_cast<int>(stop_time_ - start_time_) / 1000;
-    StatsTable::AddHistogramSample(histogram_, milliseconds);
+    Isolate::Current()->stats_table()->
+        AddHistogramSample(histogram_, milliseconds);
   }
 }
 
+
+void* HistogramTimer::CreateHistogram() const {
+  return Isolate::Current()->stats_table()->
+      CreateHistogram(name_, 0, 10000, 50);
+}
+
 } }  // namespace v8::internal
diff --git a/src/counters.h b/src/counters.h
index 048fdaa..6498a02 100644
--- a/src/counters.h
+++ b/src/counters.h
@@ -38,27 +38,27 @@
 // counters for monitoring.  Counters can be looked up and
 // manipulated by name.
 
-class StatsTable : public AllStatic {
+class StatsTable {
  public:
   // Register an application-defined function where
   // counters can be looked up.
-  static void SetCounterFunction(CounterLookupCallback f) {
+  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) {
+  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) {
+  void SetAddHistogramSampleFunction(AddHistogramSampleCallback f) {
     add_histogram_sample_function_ = f;
   }
 
-  static bool HasCounterFunction() {
+  bool HasCounterFunction() const {
     return lookup_function_ != NULL;
   }
 
@@ -68,7 +68,7 @@
   // 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) {
+  int* FindLocation(const char* name) {
     if (!lookup_function_) return NULL;
     return lookup_function_(name);
   }
@@ -78,25 +78,31 @@
   // 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) {
+  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) {
+  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_;
+  StatsTable();
+
+  CounterLookupCallback lookup_function_;
+  CreateHistogramCallback create_histogram_function_;
+  AddHistogramSampleCallback add_histogram_sample_function_;
+
+  friend class Isolate;
+
+  DISALLOW_COPY_AND_ASSIGN(StatsTable);
 };
 
 // StatsCounters are dynamically created values which can be tracked in
@@ -166,9 +172,12 @@
     if (lookup_done_)
       return ptr_;
     lookup_done_ = true;
-    ptr_ = StatsTable::FindLocation(name_);
+    ptr_ = FindLocationInStatsTable();
     return ptr_;
   }
+
+ private:
+  int* FindLocationInStatsTable() const;
 };
 
 // StatsCounterTimer t = { { L"t:foo", NULL, false }, 0, 0 };
@@ -216,10 +225,13 @@
   void* GetHistogram() {
     if (!lookup_done_) {
       lookup_done_ = true;
-      histogram_ = StatsTable::CreateHistogram(name_, 0, 10000, 50);
+      histogram_ = CreateHistogram();
     }
     return histogram_;
   }
+
+ private:
+  void* CreateHistogram() const;
 };
 
 // Helper class for scoping a HistogramTimer.
diff --git a/src/cpu-profiler-inl.h b/src/cpu-profiler-inl.h
index 440dedc..a7fffe0 100644
--- a/src/cpu-profiler-inl.h
+++ b/src/cpu-profiler-inl.h
@@ -41,8 +41,8 @@
 
 void CodeCreateEventRecord::UpdateCodeMap(CodeMap* code_map) {
   code_map->AddCode(start, entry, size);
-  if (sfi_address != NULL) {
-    entry->set_shared_id(code_map->GetSFITag(sfi_address));
+  if (shared != NULL) {
+    entry->set_shared_id(code_map->GetSharedId(shared));
   }
 }
 
@@ -57,7 +57,7 @@
 }
 
 
-void SFIMoveEventRecord::UpdateCodeMap(CodeMap* code_map) {
+void SharedFunctionInfoMoveEventRecord::UpdateCodeMap(CodeMap* code_map) {
   code_map->MoveCode(from, to);
 }
 
diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc
index ad04a00..ef51950 100644
--- a/src/cpu-profiler.cc
+++ b/src/cpu-profiler.cc
@@ -46,8 +46,9 @@
 static const int kTickSamplesBufferChunksCount = 16;
 
 
-ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
-    : Thread("v8:ProfEvntProc"),
+ProfilerEventsProcessor::ProfilerEventsProcessor(Isolate* isolate,
+                                                 ProfileGenerator* generator)
+    : Thread(isolate, "v8:ProfEvntProc"),
       generator_(generator),
       running_(true),
       ticks_buffer_(sizeof(TickSampleEventRecord),
@@ -69,7 +70,7 @@
   rec->start = start;
   rec->entry = generator_->NewCodeEntry(tag, prefix, name);
   rec->size = 1;
-  rec->sfi_address = NULL;
+  rec->shared = NULL;
   events_buffer_.Enqueue(evt_rec);
 }
 
@@ -80,7 +81,7 @@
                                               int line_number,
                                               Address start,
                                               unsigned size,
-                                              Address sfi_address) {
+                                              Address shared) {
   if (FilterOutCodeCreateEvent(tag)) return;
   CodeEventsContainer evt_rec;
   CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
@@ -89,7 +90,7 @@
   rec->start = start;
   rec->entry = generator_->NewCodeEntry(tag, name, resource_name, line_number);
   rec->size = size;
-  rec->sfi_address = sfi_address;
+  rec->shared = shared;
   events_buffer_.Enqueue(evt_rec);
 }
 
@@ -106,7 +107,7 @@
   rec->start = start;
   rec->entry = generator_->NewCodeEntry(tag, name);
   rec->size = size;
-  rec->sfi_address = NULL;
+  rec->shared = NULL;
   events_buffer_.Enqueue(evt_rec);
 }
 
@@ -123,7 +124,7 @@
   rec->start = start;
   rec->entry = generator_->NewCodeEntry(tag, args_count);
   rec->size = size;
-  rec->sfi_address = NULL;
+  rec->shared = NULL;
   events_buffer_.Enqueue(evt_rec);
 }
 
@@ -149,10 +150,12 @@
 }
 
 
-void ProfilerEventsProcessor::SFIMoveEvent(Address from, Address to) {
+void ProfilerEventsProcessor::SharedFunctionInfoMoveEvent(Address from,
+                                                          Address to) {
   CodeEventsContainer evt_rec;
-  SFIMoveEventRecord* rec = &evt_rec.SFIMoveEventRecord_;
-  rec->type = CodeEventRecord::SFI_MOVE;
+  SharedFunctionInfoMoveEventRecord* rec =
+      &evt_rec.SharedFunctionInfoMoveEventRecord_;
+  rec->type = CodeEventRecord::SHARED_FUNC_MOVE;
   rec->order = ++enqueue_order_;
   rec->from = from;
   rec->to = to;
@@ -181,7 +184,7 @@
 void ProfilerEventsProcessor::AddCurrentStack() {
   TickSampleEventRecord record;
   TickSample* sample = &record.sample;
-  sample->state = Top::current_vm_state();
+  sample->state = Isolate::Current()->current_vm_state();
   sample->pc = reinterpret_cast<Address>(sample);  // Not NULL.
   sample->tos = NULL;
   sample->frames_count = 0;
@@ -270,82 +273,106 @@
 }
 
 
-CpuProfiler* CpuProfiler::singleton_ = NULL;
-Atomic32 CpuProfiler::is_profiling_ = false;
-
 void CpuProfiler::StartProfiling(const char* title) {
-  ASSERT(singleton_ != NULL);
-  singleton_->StartCollectingProfile(title);
+  ASSERT(Isolate::Current()->cpu_profiler() != NULL);
+  Isolate::Current()->cpu_profiler()->StartCollectingProfile(title);
 }
 
 
 void CpuProfiler::StartProfiling(String* title) {
-  ASSERT(singleton_ != NULL);
-  singleton_->StartCollectingProfile(title);
+  ASSERT(Isolate::Current()->cpu_profiler() != NULL);
+  Isolate::Current()->cpu_profiler()->StartCollectingProfile(title);
 }
 
 
 CpuProfile* CpuProfiler::StopProfiling(const char* title) {
-  return is_profiling() ? singleton_->StopCollectingProfile(title) : NULL;
+  return is_profiling() ?
+      Isolate::Current()->cpu_profiler()->StopCollectingProfile(title) : NULL;
 }
 
 
 CpuProfile* CpuProfiler::StopProfiling(Object* security_token, String* title) {
   return is_profiling() ?
-      singleton_->StopCollectingProfile(security_token, title) : NULL;
+      Isolate::Current()->cpu_profiler()->StopCollectingProfile(
+          security_token, title) : NULL;
 }
 
 
 int CpuProfiler::GetProfilesCount() {
-  ASSERT(singleton_ != NULL);
+  ASSERT(Isolate::Current()->cpu_profiler() != NULL);
   // The count of profiles doesn't depend on a security token.
-  return singleton_->profiles_->Profiles(
+  return Isolate::Current()->cpu_profiler()->profiles_->Profiles(
       TokenEnumerator::kNoSecurityToken)->length();
 }
 
 
 CpuProfile* CpuProfiler::GetProfile(Object* security_token, int index) {
-  ASSERT(singleton_ != NULL);
-  const int token = singleton_->token_enumerator_->GetTokenId(security_token);
-  return singleton_->profiles_->Profiles(token)->at(index);
+  ASSERT(Isolate::Current()->cpu_profiler() != NULL);
+  CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
+  const int token = profiler->token_enumerator_->GetTokenId(security_token);
+  return profiler->profiles_->Profiles(token)->at(index);
 }
 
 
 CpuProfile* CpuProfiler::FindProfile(Object* security_token, unsigned uid) {
-  ASSERT(singleton_ != NULL);
-  const int token = singleton_->token_enumerator_->GetTokenId(security_token);
-  return singleton_->profiles_->GetProfile(token, uid);
+  ASSERT(Isolate::Current()->cpu_profiler() != NULL);
+  CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
+  const int token = profiler->token_enumerator_->GetTokenId(security_token);
+  return profiler->profiles_->GetProfile(token, uid);
 }
 
 
-TickSample* CpuProfiler::TickSampleEvent() {
-  if (CpuProfiler::is_profiling()) {
-    return singleton_->processor_->TickSampleEvent();
+TickSample* CpuProfiler::TickSampleEvent(Isolate* isolate) {
+  if (CpuProfiler::is_profiling(isolate)) {
+    return isolate->cpu_profiler()->processor_->TickSampleEvent();
   } else {
     return NULL;
   }
 }
 
 
+void CpuProfiler::DeleteAllProfiles() {
+  Isolate* isolate = Isolate::Current();
+  ASSERT(isolate->cpu_profiler() != NULL);
+  if (is_profiling())
+    isolate->cpu_profiler()->StopProcessor();
+  isolate->cpu_profiler()->ResetProfiles();
+}
+
+
+void CpuProfiler::DeleteProfile(CpuProfile* profile) {
+  ASSERT(Isolate::Current()->cpu_profiler() != NULL);
+  Isolate::Current()->cpu_profiler()->profiles_->RemoveProfile(profile);
+  delete profile;
+}
+
+
+bool CpuProfiler::HasDetachedProfiles() {
+  ASSERT(Isolate::Current()->cpu_profiler() != NULL);
+  return Isolate::Current()->cpu_profiler()->profiles_->HasDetachedProfiles();
+}
+
+
 void CpuProfiler::CallbackEvent(String* name, Address entry_point) {
-  singleton_->processor_->CallbackCreateEvent(
+  Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
       Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point);
 }
 
 
 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
                            Code* code, const char* comment) {
-  singleton_->processor_->CodeCreateEvent(
+  Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
       tag, comment, code->address(), code->ExecutableSize());
 }
 
 
 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
                            Code* code, String* name) {
-  singleton_->processor_->CodeCreateEvent(
+  Isolate* isolate = Isolate::Current();
+  isolate->cpu_profiler()->processor_->CodeCreateEvent(
       tag,
       name,
-      Heap::empty_string(),
+      isolate->heap()->empty_string(),
       v8::CpuProfileNode::kNoLineNumberInfo,
       code->address(),
       code->ExecutableSize(),
@@ -357,10 +384,11 @@
                                   Code* code,
                                   SharedFunctionInfo* shared,
                                   String* name) {
-  singleton_->processor_->CodeCreateEvent(
+  Isolate* isolate = Isolate::Current();
+  isolate->cpu_profiler()->processor_->CodeCreateEvent(
       tag,
       name,
-      Heap::empty_string(),
+      isolate->heap()->empty_string(),
       v8::CpuProfileNode::kNoLineNumberInfo,
       code->address(),
       code->ExecutableSize(),
@@ -372,7 +400,7 @@
                                   Code* code,
                                   SharedFunctionInfo* shared,
                                   String* source, int line) {
-  singleton_->processor_->CodeCreateEvent(
+  Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
       tag,
       shared->DebugName(),
       source,
@@ -385,7 +413,7 @@
 
 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
                            Code* code, int args_count) {
-  singleton_->processor_->CodeCreateEvent(
+  Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
       tag,
       args_count,
       code->address(),
@@ -394,28 +422,29 @@
 
 
 void CpuProfiler::CodeMoveEvent(Address from, Address to) {
-  singleton_->processor_->CodeMoveEvent(from, to);
+  Isolate::Current()->cpu_profiler()->processor_->CodeMoveEvent(from, to);
 }
 
 
 void CpuProfiler::CodeDeleteEvent(Address from) {
-  singleton_->processor_->CodeDeleteEvent(from);
+  Isolate::Current()->cpu_profiler()->processor_->CodeDeleteEvent(from);
 }
 
 
-void CpuProfiler::SFIMoveEvent(Address from, Address to) {
-  singleton_->processor_->SFIMoveEvent(from, to);
+void CpuProfiler::SharedFunctionInfoMoveEvent(Address from, Address to) {
+  CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
+  profiler->processor_->SharedFunctionInfoMoveEvent(from, to);
 }
 
 
 void CpuProfiler::GetterCallbackEvent(String* name, Address entry_point) {
-  singleton_->processor_->CallbackCreateEvent(
+  Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
       Logger::CALLBACK_TAG, "get ", name, entry_point);
 }
 
 
 void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
-  singleton_->processor_->RegExpCodeCreateEvent(
+  Isolate::Current()->cpu_profiler()->processor_->RegExpCodeCreateEvent(
       Logger::REG_EXP_TAG,
       "RegExp: ",
       source,
@@ -425,7 +454,7 @@
 
 
 void CpuProfiler::SetterCallbackEvent(String* name, Address entry_point) {
-  singleton_->processor_->CallbackCreateEvent(
+  Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
       Logger::CALLBACK_TAG, "set ", name, entry_point);
 }
 
@@ -435,7 +464,9 @@
       next_profile_uid_(1),
       token_enumerator_(new TokenEnumerator()),
       generator_(NULL),
-      processor_(NULL) {
+      processor_(NULL),
+      need_to_stop_sampler_(false),
+      is_profiling_(false) {
 }
 
 
@@ -445,6 +476,11 @@
 }
 
 
+void CpuProfiler::ResetProfiles() {
+  delete profiles_;
+  profiles_ = new CpuProfilesCollection();
+}
+
 void CpuProfiler::StartCollectingProfile(const char* title) {
   if (profiles_->StartProfiling(title, next_profile_uid_++)) {
     StartProcessorIfNotStarted();
@@ -460,27 +496,32 @@
 
 void CpuProfiler::StartProcessorIfNotStarted() {
   if (processor_ == NULL) {
+    Isolate* isolate = Isolate::Current();
+
     // Disable logging when using the new implementation.
-    saved_logging_nesting_ = Logger::logging_nesting_;
-    Logger::logging_nesting_ = 0;
+    saved_logging_nesting_ = isolate->logger()->logging_nesting_;
+    isolate->logger()->logging_nesting_ = 0;
     generator_ = new ProfileGenerator(profiles_);
-    processor_ = new ProfilerEventsProcessor(generator_);
+    processor_ = new ProfilerEventsProcessor(isolate, generator_);
     NoBarrier_Store(&is_profiling_, true);
     processor_->Start();
     // Enumerate stuff we already have in the heap.
-    if (Heap::HasBeenSetup()) {
+    if (isolate->heap()->HasBeenSetup()) {
       if (!FLAG_prof_browser_mode) {
         bool saved_log_code_flag = FLAG_log_code;
         FLAG_log_code = true;
-        Logger::LogCodeObjects();
+        isolate->logger()->LogCodeObjects();
         FLAG_log_code = saved_log_code_flag;
       }
-      Logger::LogCompiledFunctions();
-      Logger::LogAccessorCallbacks();
+      isolate->logger()->LogCompiledFunctions();
+      isolate->logger()->LogAccessorCallbacks();
     }
     // Enable stack sampling.
-    Sampler* sampler = reinterpret_cast<Sampler*>(Logger::ticker_);
-    if (!sampler->IsActive()) sampler->Start();
+    Sampler* sampler = reinterpret_cast<Sampler*>(isolate->logger()->ticker_);
+    if (!sampler->IsActive()) {
+      sampler->Start();
+      need_to_stop_sampler_ = true;
+    }
     sampler->IncreaseProfilingDepth();
   }
 }
@@ -511,19 +552,26 @@
 
 
 void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
-  if (profiles_->IsLastProfile(title)) {
-    Sampler* sampler = reinterpret_cast<Sampler*>(Logger::ticker_);
-    sampler->DecreaseProfilingDepth();
+  if (profiles_->IsLastProfile(title)) StopProcessor();
+}
+
+
+void CpuProfiler::StopProcessor() {
+  Logger* logger = Isolate::Current()->logger();
+  Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
+  sampler->DecreaseProfilingDepth();
+  if (need_to_stop_sampler_) {
     sampler->Stop();
-    processor_->Stop();
-    processor_->Join();
-    delete processor_;
-    delete generator_;
-    processor_ = NULL;
-    NoBarrier_Store(&is_profiling_, false);
-    generator_ = NULL;
-    Logger::logging_nesting_ = saved_logging_nesting_;
+    need_to_stop_sampler_ = false;
   }
+  processor_->Stop();
+  processor_->Join();
+  delete processor_;
+  delete generator_;
+  processor_ = NULL;
+  NoBarrier_Store(&is_profiling_, false);
+  generator_ = NULL;
+  logger->logging_nesting_ = saved_logging_nesting_;
 }
 
 } }  // namespace v8::internal
@@ -535,8 +583,9 @@
 
 void CpuProfiler::Setup() {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (singleton_ == NULL) {
-    singleton_ = new CpuProfiler();
+  Isolate* isolate = Isolate::Current();
+  if (isolate->cpu_profiler() == NULL) {
+    isolate->set_cpu_profiler(new CpuProfiler());
   }
 #endif
 }
@@ -544,10 +593,11 @@
 
 void CpuProfiler::TearDown() {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (singleton_ != NULL) {
-    delete singleton_;
+  Isolate* isolate = Isolate::Current();
+  if (isolate->cpu_profiler() != NULL) {
+    delete isolate->cpu_profiler();
   }
-  singleton_ = NULL;
+  isolate->set_cpu_profiler(NULL);
 #endif
 }
 
diff --git a/src/cpu-profiler.h b/src/cpu-profiler.h
index 1ebbfeb..e04cf85 100644
--- a/src/cpu-profiler.h
+++ b/src/cpu-profiler.h
@@ -46,11 +46,11 @@
 class ProfileGenerator;
 class TokenEnumerator;
 
-#define CODE_EVENTS_TYPE_LIST(V)                \
-  V(CODE_CREATION, CodeCreateEventRecord)       \
-  V(CODE_MOVE,     CodeMoveEventRecord)         \
-  V(CODE_DELETE,   CodeDeleteEventRecord)       \
-  V(SFI_MOVE,      SFIMoveEventRecord)
+#define CODE_EVENTS_TYPE_LIST(V)                                   \
+  V(CODE_CREATION,    CodeCreateEventRecord)                       \
+  V(CODE_MOVE,        CodeMoveEventRecord)                         \
+  V(CODE_DELETE,      CodeDeleteEventRecord)                       \
+  V(SHARED_FUNC_MOVE, SharedFunctionInfoMoveEventRecord)
 
 
 class CodeEventRecord {
@@ -73,7 +73,7 @@
   Address start;
   CodeEntry* entry;
   unsigned size;
-  Address sfi_address;
+  Address shared;
 
   INLINE(void UpdateCodeMap(CodeMap* code_map));
 };
@@ -96,7 +96,7 @@
 };
 
 
-class SFIMoveEventRecord : public CodeEventRecord {
+class SharedFunctionInfoMoveEventRecord : public CodeEventRecord {
  public:
   Address from;
   Address to;
@@ -133,7 +133,8 @@
 // methods called by event producers: VM and stack sampler threads.
 class ProfilerEventsProcessor : public Thread {
  public:
-  explicit ProfilerEventsProcessor(ProfileGenerator* generator);
+  explicit ProfilerEventsProcessor(Isolate* isolate,
+                                   ProfileGenerator* generator);
   virtual ~ProfilerEventsProcessor() {}
 
   // Thread control.
@@ -149,7 +150,7 @@
                        String* name,
                        String* resource_name, int line_number,
                        Address start, unsigned size,
-                       Address sfi_address);
+                       Address shared);
   void CodeCreateEvent(Logger::LogEventsAndTags tag,
                        const char* name,
                        Address start, unsigned size);
@@ -158,7 +159,7 @@
                        Address start, unsigned size);
   void CodeMoveEvent(Address from, Address to);
   void CodeDeleteEvent(Address from);
-  void SFIMoveEvent(Address from, Address to);
+  void SharedFunctionInfoMoveEvent(Address from, Address to);
   void RegExpCodeCreateEvent(Logger::LogEventsAndTags tag,
                              const char* prefix, String* name,
                              Address start, unsigned size);
@@ -196,21 +197,23 @@
 } }  // namespace v8::internal
 
 
-#define PROFILE(Call)                                  \
-  LOG(Call);                                           \
+#define PROFILE(isolate, Call)                         \
+  LOG(isolate, Call);                                  \
   do {                                                 \
     if (v8::internal::CpuProfiler::is_profiling()) {   \
       v8::internal::CpuProfiler::Call;                 \
     }                                                  \
   } while (false)
 #else
-#define PROFILE(Call) LOG(Call)
+#define PROFILE(isolate, Call) LOG(isolate, Call)
 #endif  // ENABLE_LOGGING_AND_PROFILING
 
 
 namespace v8 {
 namespace internal {
 
+
+// TODO(isolates): isolatify this class.
 class CpuProfiler {
  public:
   static void Setup();
@@ -224,9 +227,12 @@
   static int GetProfilesCount();
   static CpuProfile* GetProfile(Object* security_token, int index);
   static CpuProfile* FindProfile(Object* security_token, unsigned uid);
+  static void DeleteAllProfiles();
+  static void DeleteProfile(CpuProfile* profile);
+  static bool HasDetachedProfiles();
 
   // Invoked from stack sampler (thread or signal handler.)
-  static TickSample* TickSampleEvent();
+  static TickSample* TickSampleEvent(Isolate* isolate);
 
   // Must be called via PROFILE macro, otherwise will crash when
   // profiling is not enabled.
@@ -251,10 +257,17 @@
   static void GetterCallbackEvent(String* name, Address entry_point);
   static void RegExpCodeCreateEvent(Code* code, String* source);
   static void SetterCallbackEvent(String* name, Address entry_point);
-  static void SFIMoveEvent(Address from, Address to);
+  static void SharedFunctionInfoMoveEvent(Address from, Address to);
+
+  // TODO(isolates): this doesn't have to use atomics anymore.
 
   static INLINE(bool is_profiling()) {
-    return NoBarrier_Load(&is_profiling_);
+    return is_profiling(Isolate::Current());
+  }
+
+  static INLINE(bool is_profiling(Isolate* isolate)) {
+    CpuProfiler* profiler = isolate->cpu_profiler();
+    return profiler != NULL && NoBarrier_Load(&profiler->is_profiling_);
   }
 
  private:
@@ -266,6 +279,8 @@
   CpuProfile* StopCollectingProfile(const char* title);
   CpuProfile* StopCollectingProfile(Object* security_token, String* title);
   void StopProcessorIfLastProfile(const char* title);
+  void StopProcessor();
+  void ResetProfiles();
 
   CpuProfilesCollection* profiles_;
   unsigned next_profile_uid_;
@@ -273,9 +288,8 @@
   ProfileGenerator* generator_;
   ProfilerEventsProcessor* processor_;
   int saved_logging_nesting_;
-
-  static CpuProfiler* singleton_;
-  static Atomic32 is_profiling_;
+  bool need_to_stop_sampler_;
+  Atomic32 is_profiling_;
 
 #else
   static INLINE(bool is_profiling()) { return false; }
diff --git a/src/d8-debug.cc b/src/d8-debug.cc
index 8a3886c..3df8693 100644
--- a/src/d8-debug.cc
+++ b/src/d8-debug.cc
@@ -159,7 +159,7 @@
 
 
 void RunRemoteDebugger(int port) {
-  RemoteDebugger debugger(port);
+  RemoteDebugger debugger(i::Isolate::Current(), port);
   debugger.Run();
 }
 
@@ -186,11 +186,11 @@
   }
 
   // Start the receiver thread.
-  ReceiverThread receiver(this);
+  ReceiverThread receiver(isolate_, this);
   receiver.Start();
 
   // Start the keyboard thread.
-  KeyboardThread keyboard(this);
+  KeyboardThread keyboard(isolate_, this);
   keyboard.Start();
   PrintPrompt();
 
diff --git a/src/d8-debug.h b/src/d8-debug.h
index 4e33e6f..ceb9e36 100644
--- a/src/d8-debug.h
+++ b/src/d8-debug.h
@@ -53,11 +53,11 @@
 // Remote debugging class.
 class RemoteDebugger {
  public:
-  explicit RemoteDebugger(int port)
+  RemoteDebugger(i::Isolate* isolate, int port)
       : port_(port),
         event_access_(i::OS::CreateMutex()),
         event_available_(i::OS::CreateSemaphore(0)),
-        head_(NULL), tail_(NULL) {}
+        head_(NULL), tail_(NULL), isolate_(isolate) {}
   void Run();
 
   // Handle events from the subordinate threads.
@@ -89,6 +89,7 @@
   i::Semaphore* event_available_;
   RemoteDebuggerEvent* head_;
   RemoteDebuggerEvent* tail_;
+  i::Isolate* isolate_;
 
   friend class ReceiverThread;
 };
@@ -97,8 +98,8 @@
 // Thread reading from debugged V8 instance.
 class ReceiverThread: public i::Thread {
  public:
-  explicit ReceiverThread(RemoteDebugger* remote_debugger)
-      : Thread("d8:ReceiverThrd"),
+  ReceiverThread(i::Isolate* isolate, RemoteDebugger* remote_debugger)
+      : Thread(isolate, "d8:ReceiverThrd"),
         remote_debugger_(remote_debugger) {}
   ~ReceiverThread() {}
 
@@ -112,8 +113,8 @@
 // Thread reading keyboard input.
 class KeyboardThread: public i::Thread {
  public:
-  explicit KeyboardThread(RemoteDebugger* remote_debugger)
-      : Thread("d8:KeyboardThrd"),
+  explicit KeyboardThread(i::Isolate* isolate, RemoteDebugger* remote_debugger)
+      : Thread(isolate, "d8:KeyboardThrd"),
         remote_debugger_(remote_debugger) {}
   ~KeyboardThread() {}
 
diff --git a/src/d8-posix.cc b/src/d8-posix.cc
index 335bd2b..a7a4049 100644
--- a/src/d8-posix.cc
+++ b/src/d8-posix.cc
@@ -375,8 +375,10 @@
 // a parent process hangs on waiting while a child process is already a zombie.
 // See http://code.google.com/p/v8/issues/detail?id=401.
 #if defined(WNOWAIT) && !defined(ANDROID) && !defined(__APPLE__)
+#if !defined(__FreeBSD__)
 #define HAS_WAITID 1
 #endif
+#endif
 
 
 // Get exit status of child.
diff --git a/src/d8.cc b/src/d8.cc
index 349ec90..7de82b7 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -29,6 +29,8 @@
 #include <stdlib.h>
 #include <errno.h>
 
+#include "v8.h"
+
 #include "d8.h"
 #include "d8-debug.h"
 #include "debug.h"
@@ -441,24 +443,25 @@
 
   i::JSArguments js_args = i::FLAG_js_arguments;
   i::Handle<i::FixedArray> arguments_array =
-      i::Factory::NewFixedArray(js_args.argc());
+      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]));
+        FACTORY->NewStringFromUtf8(i::CStrVector(js_args[j]));
     arguments_array->set(j, *arg);
   }
   i::Handle<i::JSArray> arguments_jsarray =
-      i::Factory::NewJSArrayWithElements(arguments_array);
+      FACTORY->NewJSArrayWithElements(arguments_array);
   global_template->Set(String::New("arguments"),
                        Utils::ToLocal(arguments_jsarray));
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Install the debugger object in the utility scope
-  i::Debug::Load();
-  i::Handle<i::JSObject> debug
-      = i::Handle<i::JSObject>(i::Debug::debug_context()->global());
+  i::Debug* debug = i::Isolate::Current()->debug();
+  debug->Load();
+  i::Handle<i::JSObject> js_debug
+      = i::Handle<i::JSObject>(debug->debug_context()->global());
   utility_context_->Global()->Set(String::New("$debug"),
-                                  Utils::ToLocal(debug));
+                                  Utils::ToLocal(js_debug));
 #endif
 
   // Run the d8 shell utility script in the utility context
@@ -490,7 +493,7 @@
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Set the security token of the debug context to allow access.
-  i::Debug::debug_context()->set_security_token(i::Heap::undefined_value());
+  debug->debug_context()->set_security_token(HEAP->undefined_value());
 
   // Start the debugger agent if requested.
   if (i::FLAG_debugger_agent) {
@@ -606,8 +609,8 @@
 
 class ShellThread : public i::Thread {
  public:
-  ShellThread(int no, i::Vector<const char> files)
-    : Thread("d8:ShellThread"),
+  ShellThread(i::Isolate* isolate, int no, i::Vector<const char> files)
+    : Thread(isolate, "d8:ShellThread"),
       no_(no), files_(files) { }
   virtual void Run();
  private:
@@ -739,7 +742,8 @@
         const char* files = ReadChars(argv[++i], &size);
         if (files == NULL) return 1;
         ShellThread* thread =
-            new ShellThread(threads.length(),
+            new ShellThread(i::Isolate::Current(),
+                            threads.length(),
                             i::Vector<const char>(files, size));
         thread->Start();
         threads.Add(thread);
diff --git a/src/d8.gyp b/src/d8.gyp
index 3283e38..901fd65 100644
--- a/src/d8.gyp
+++ b/src/d8.gyp
@@ -38,7 +38,10 @@
         '../src',
       ],
       'defines': [
+        'ENABLE_LOGGING_AND_PROFILING',
         'ENABLE_DEBUGGER_SUPPORT',
+        'ENABLE_VMSTATE_TRACKING',
+        'V8_FAST_TLS',
       ],
       'sources': [
         'd8.cc',
diff --git a/src/data-flow.h b/src/data-flow.h
index 79d760f..573d7d8 100644
--- a/src/data-flow.h
+++ b/src/data-flow.h
@@ -90,7 +90,7 @@
   explicit BitVector(int length)
       : length_(length),
         data_length_(SizeFor(length)),
-        data_(Zone::NewArray<uint32_t>(data_length_)) {
+        data_(ZONE->NewArray<uint32_t>(data_length_)) {
     ASSERT(length > 0);
     Clear();
   }
@@ -98,7 +98,7 @@
   BitVector(const BitVector& other)
       : length_(other.length()),
         data_length_(SizeFor(length_)),
-        data_(Zone::NewArray<uint32_t>(data_length_)) {
+        data_(ZONE->NewArray<uint32_t>(data_length_)) {
     CopyFrom(other);
   }
 
@@ -237,7 +237,7 @@
 
   explicit SparseSet(int universe_size)
       : dense_(4),
-        sparse_(Zone::NewArray<int>(universe_size)) {
+        sparse_(ZONE->NewArray<int>(universe_size)) {
 #ifdef DEBUG
     size_ = universe_size;
     iterator_count_ = 0;
diff --git a/src/dateparser.h b/src/dateparser.h
index 40e56f3..51109ee 100644
--- a/src/dateparser.h
+++ b/src/dateparser.h
@@ -70,7 +70,8 @@
     explicit InputReader(Vector<Char> s)
         : index_(0),
           buffer_(s),
-          has_read_number_(false) {
+          has_read_number_(false),
+          scanner_constants_(Isolate::Current()->scanner_constants()) {
       Next();
     }
 
@@ -121,7 +122,7 @@
     }
 
     bool SkipWhiteSpace() {
-      if (ScannerConstants::kIsWhiteSpace.get(ch_)) {
+      if (scanner_constants_->IsWhiteSpace(ch_)) {
         Next();
         return true;
       }
@@ -157,6 +158,7 @@
     Vector<Char> buffer_;
     bool has_read_number_;
     uint32_t ch_;
+    ScannerConstants* scanner_constants_;
   };
 
   enum KeywordType { INVALID, MONTH_NAME, TIME_ZONE_NAME, AM_PM };
diff --git a/src/debug-agent.cc b/src/debug-agent.cc
index 6901079..498b88a 100644
--- a/src/debug-agent.cc
+++ b/src/debug-agent.cc
@@ -38,11 +38,11 @@
 // Public V8 debugger API message handler function. This function just delegates
 // to the debugger agent through it's data parameter.
 void DebuggerAgentMessageHandler(const v8::Debug::Message& message) {
-  DebuggerAgent::instance_->DebuggerMessage(message);
+  DebuggerAgent* agent = Isolate::Current()->debugger_agent_instance();
+  ASSERT(agent != NULL);
+  agent->DebuggerMessage(message);
 }
 
-// static
-DebuggerAgent* DebuggerAgent::instance_ = NULL;
 
 // Debugger agent main thread.
 void DebuggerAgent::Run() {
@@ -102,20 +102,21 @@
   listening_->Wait();
 }
 
+static const char* kCreateSessionMessage =
+    "Remote debugging session already active\r\n";
+
 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, StrLength(message));
+    client->Send(kCreateSessionMessage, StrLength(kCreateSessionMessage));
     delete client;
     return;
   }
 
   // Create a new session and hook up the debug message handler.
-  session_ = new DebuggerAgentSession(this, client);
+  session_ = new DebuggerAgentSession(isolate(), this, client);
   v8::Debug::SetMessageHandler2(DebuggerAgentMessageHandler);
   session_->Start();
 }
@@ -224,8 +225,8 @@
 }
 
 
-const char* DebuggerAgentUtil::kContentLength = "Content-Length";
-int DebuggerAgentUtil::kContentLengthSize =
+const char* const DebuggerAgentUtil::kContentLength = "Content-Length";
+const int DebuggerAgentUtil::kContentLengthSize =
     StrLength(kContentLength);
 
 
diff --git a/src/debug-agent.h b/src/debug-agent.h
index 4cedb83..a25002e 100644
--- a/src/debug-agent.h
+++ b/src/debug-agent.h
@@ -43,18 +43,18 @@
 // handles connection from a remote debugger.
 class DebuggerAgent: public Thread {
  public:
-  explicit DebuggerAgent(const char* name, int port)
-      : Thread(name),
+  DebuggerAgent(Isolate* isolate, const char* name, int port)
+      : Thread(isolate, name),
         name_(StrDup(name)), port_(port),
         server_(OS::CreateSocket()), terminate_(false),
         session_access_(OS::CreateMutex()), session_(NULL),
         terminate_now_(OS::CreateSemaphore(0)),
         listening_(OS::CreateSemaphore(0)) {
-    ASSERT(instance_ == NULL);
-    instance_ = this;
+    ASSERT(Isolate::Current()->debugger_agent_instance() == NULL);
+    Isolate::Current()->set_debugger_agent_instance(this);
   }
   ~DebuggerAgent() {
-     instance_ = NULL;
+     Isolate::Current()->set_debugger_agent_instance(NULL);
      delete server_;
   }
 
@@ -77,8 +77,6 @@
   Semaphore* terminate_now_;  // Semaphore to signal termination.
   Semaphore* listening_;
 
-  static DebuggerAgent* instance_;
-
   friend class DebuggerAgentSession;
   friend void DebuggerAgentMessageHandler(const v8::Debug::Message& message);
 
@@ -90,8 +88,8 @@
 // debugger and sends debugger events/responses to the remote debugger.
 class DebuggerAgentSession: public Thread {
  public:
-  DebuggerAgentSession(DebuggerAgent* agent, Socket* client)
-      : Thread("v8:DbgAgntSessn"),
+  DebuggerAgentSession(Isolate* isolate, DebuggerAgent* agent, Socket* client)
+      : Thread(isolate, "v8:DbgAgntSessn"),
         agent_(agent), client_(client) {}
 
   void DebuggerMessage(Vector<uint16_t> message);
@@ -112,8 +110,8 @@
 // Utility methods factored out to be used by the D8 shell as well.
 class DebuggerAgentUtil {
  public:
-  static const char* kContentLength;
-  static int kContentLengthSize;
+  static const char* const kContentLength;
+  static const int kContentLengthSize;
 
   static SmartPointer<char> ReceiveMessage(const Socket* conn);
   static bool SendConnectMessage(const Socket* conn,
diff --git a/src/debug.cc b/src/debug.cc
index d91ad92..bc532ef 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -51,6 +51,26 @@
 namespace internal {
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
+
+
+Debug::Debug(Isolate* isolate)
+    : has_break_points_(false),
+      script_cache_(NULL),
+      debug_info_list_(NULL),
+      disable_break_(false),
+      break_on_exception_(false),
+      break_on_uncaught_exception_(false),
+      debug_break_return_(NULL),
+      debug_break_slot_(NULL),
+      isolate_(isolate) {
+  memset(registers_, 0, sizeof(JSCallerSavedBuffer));
+}
+
+
+Debug::~Debug() {
+}
+
+
 static void PrintLn(v8::Local<v8::Value> value) {
   v8::Local<v8::String> s = value->ToString();
   ScopedVector<char> data(s->Length() + 1);
@@ -64,22 +84,28 @@
 
 
 static Handle<Code> ComputeCallDebugBreak(int argc, Code::Kind kind) {
-  CALL_HEAP_FUNCTION(StubCache::ComputeCallDebugBreak(argc, kind), Code);
-}
-
-
-static Handle<Code> ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind) {
+  Isolate* isolate = Isolate::Current();
   CALL_HEAP_FUNCTION(
-      StubCache::ComputeCallDebugPrepareStepIn(argc, kind), Code);
+      isolate,
+      isolate->stub_cache()->ComputeCallDebugBreak(argc, kind),
+      Code);
 }
 
 
-static v8::Handle<v8::Context> GetDebugEventContext() {
-  Handle<Context> context = Debug::debugger_entry()->GetContext();
-  // Top::context() may have been NULL when "script collected" event occured.
-  if (*context == NULL) {
-    return v8::Local<v8::Context>();
-  }
+static Handle<Code> ComputeCallDebugPrepareStepIn(int argc,  Code::Kind kind) {
+  Isolate* isolate = Isolate::Current();
+  CALL_HEAP_FUNCTION(
+      isolate,
+      isolate->stub_cache()->ComputeCallDebugPrepareStepIn(argc, kind),
+      Code);
+}
+
+
+static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) {
+  Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
+  // Isolate::context() may have been NULL when "script collected" event
+  // occured.
+  if (context.is_null()) return v8::Local<v8::Context>();
   Handle<Context> global_context(context->global_context());
   return v8::Utils::ToLocal(global_context);
 }
@@ -535,11 +561,6 @@
 }
 
 
-bool Debug::has_break_points_ = false;
-ScriptCache* Debug::script_cache_ = NULL;
-DebugInfoListNode* Debug::debug_info_list_ = NULL;
-
-
 // Threading support.
 void Debug::ThreadInit() {
   thread_local_.break_count_ = 0;
@@ -552,16 +573,13 @@
   thread_local_.step_into_fp_ = 0;
   thread_local_.step_out_fp_ = 0;
   thread_local_.after_break_target_ = 0;
+  // TODO(isolates): frames_are_dropped_?
   thread_local_.debugger_entry_ = NULL;
   thread_local_.pending_interrupts_ = 0;
   thread_local_.restarter_frame_function_pointer_ = NULL;
 }
 
 
-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));
@@ -584,7 +602,7 @@
 
 
 int Debug::ArchiveSpacePerThread() {
-  return sizeof(ThreadLocal) + sizeof(registers_);
+  return sizeof(ThreadLocal) + sizeof(JSCallerSavedBuffer);
 }
 
 
@@ -614,22 +632,8 @@
 const int Debug::kFrameDropperFrameSize = 4;
 
 
-
-
-
-// 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_ = false;
-
-Handle<Context> Debug::debug_context_ = Handle<Context>();
-Code* Debug::debug_break_return_ = NULL;
-Code* Debug::debug_break_slot_ = NULL;
-
-
 void ScriptCache::Add(Handle<Script> script) {
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
   // Create an entry in the hash map for the script.
   int id = Smi::cast(script->id())->value();
   HashMap::Entry* entry =
@@ -642,15 +646,18 @@
   // Globalize the script object, make it weak and use the location of the
   // global handle as the value in the hash map.
   Handle<Script> script_ =
-      Handle<Script>::cast((GlobalHandles::Create(*script)));
-  GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()),
-                          this, ScriptCache::HandleWeakScript);
+      Handle<Script>::cast(
+          (global_handles->Create(*script)));
+  global_handles->MakeWeak(
+      reinterpret_cast<Object**>(script_.location()),
+      this,
+      ScriptCache::HandleWeakScript);
   entry->value = script_.location();
 }
 
 
 Handle<FixedArray> ScriptCache::GetScripts() {
-  Handle<FixedArray> instances = Factory::NewFixedArray(occupancy());
+  Handle<FixedArray> instances = FACTORY->NewFixedArray(occupancy());
   int count = 0;
   for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
     ASSERT(entry->value != NULL);
@@ -664,21 +671,23 @@
 
 
 void ScriptCache::ProcessCollectedScripts() {
+  Debugger* debugger = Isolate::Current()->debugger();
   for (int i = 0; i < collected_scripts_.length(); i++) {
-    Debugger::OnScriptCollected(collected_scripts_[i]);
+    debugger->OnScriptCollected(collected_scripts_[i]);
   }
   collected_scripts_.Clear();
 }
 
 
 void ScriptCache::Clear() {
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
   // Iterate the script cache to get rid of all the weak handles.
   for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
     ASSERT(entry != NULL);
     Object** location = reinterpret_cast<Object**>(entry->value);
     ASSERT((*location)->IsScript());
-    GlobalHandles::ClearWeakness(location);
-    GlobalHandles::Destroy(location);
+    global_handles->ClearWeakness(location);
+    global_handles->Destroy(location);
   }
   // Clear the content of the hash map.
   HashMap::Clear();
@@ -708,17 +717,18 @@
   if (create_heap_objects) {
     // Get code to handle debug break on return.
     debug_break_return_ =
-        Builtins::builtin(Builtins::Return_DebugBreak);
+        isolate_->builtins()->builtin(Builtins::kReturn_DebugBreak);
     ASSERT(debug_break_return_->IsCode());
     // Get code to handle debug break in debug break slots.
     debug_break_slot_ =
-        Builtins::builtin(Builtins::Slot_DebugBreak);
+        isolate_->builtins()->builtin(Builtins::kSlot_DebugBreak);
     ASSERT(debug_break_slot_->IsCode());
   }
 }
 
 
 void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) {
+  Debug* debug = Isolate::Current()->debug();
   DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data);
   // We need to clear all breakpoints associated with the function to restore
   // original code and avoid patching the code twice later because
@@ -726,9 +736,9 @@
   // Runtime::FindSharedFunctionInfoInScript.
   BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
   it.ClearAllDebugBreak();
-  RemoveDebugInfo(node->debug_info());
+  debug->RemoveDebugInfo(node->debug_info());
 #ifdef DEBUG
-  node = Debug::debug_info_list_;
+  node = debug->debug_info_list_;
   while (node != NULL) {
     ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data));
     node = node->next();
@@ -738,20 +748,27 @@
 
 
 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
   // 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);
+  debug_info_ = Handle<DebugInfo>::cast(
+      (global_handles->Create(debug_info)));
+  global_handles->MakeWeak(
+      reinterpret_cast<Object**>(debug_info_.location()),
+      this,
+      Debug::HandleWeakDebugInfo);
 }
 
 
 DebugInfoListNode::~DebugInfoListNode() {
-  GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location()));
+  Isolate::Current()->global_handles()->Destroy(
+      reinterpret_cast<Object**>(debug_info_.location()));
 }
 
 
 bool Debug::CompileDebuggerScript(int index) {
-  HandleScope scope;
+  Isolate* isolate = Isolate::Current();
+  Factory* factory = isolate->factory();
+  HandleScope scope(isolate);
 
   // Bail out if the index is invalid.
   if (index == -1) {
@@ -759,33 +776,31 @@
   }
 
   // Find source and name for the requested script.
-  Handle<String> source_code = Bootstrapper::NativesSourceLookup(index);
+  Handle<String> source_code =
+      isolate->bootstrapper()->NativesSourceLookup(index);
   Vector<const char> name = Natives::GetScriptName(index);
-  Handle<String> script_name = Factory::NewStringFromAscii(name);
+  Handle<String> script_name = factory->NewStringFromAscii(name);
 
   // Compile the script.
-  bool allow_natives_syntax = FLAG_allow_natives_syntax;
-  FLAG_allow_natives_syntax = true;
   Handle<SharedFunctionInfo> function_info;
   function_info = Compiler::Compile(source_code,
                                     script_name,
                                     0, 0, NULL, NULL,
                                     Handle<String>::null(),
                                     NATIVES_CODE);
-  FLAG_allow_natives_syntax = allow_natives_syntax;
 
   // Silently ignore stack overflows during compilation.
   if (function_info.is_null()) {
-    ASSERT(Top::has_pending_exception());
-    Top::clear_pending_exception();
+    ASSERT(isolate->has_pending_exception());
+    isolate->clear_pending_exception();
     return false;
   }
 
   // Execute the shared function in the debugger context.
-  Handle<Context> context = Top::global_context();
+  Handle<Context> context = isolate->global_context();
   bool caught_exception = false;
   Handle<JSFunction> function =
-      Factory::NewFunctionFromSharedFunctionInfo(function_info, context);
+      factory->NewFunctionFromSharedFunctionInfo(function_info, context);
   Handle<Object> result =
       Execution::TryCall(function, Handle<Object>(context->global()),
                          0, NULL, &caught_exception);
@@ -810,38 +825,44 @@
   // Return if debugger is already loaded.
   if (IsLoaded()) return true;
 
+  ASSERT(Isolate::Current() == isolate_);
+  Debugger* debugger = isolate_->debugger();
+
   // 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())
+  if (debugger->compiling_natives() ||
+      debugger->is_loading_debugger())
     return false;
-  Debugger::set_loading_debugger(true);
+  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;
+  PostponeInterruptsScope postpone(isolate_);
 
   // Create the debugger context.
-  HandleScope scope;
+  HandleScope scope(isolate_);
   Handle<Context> context =
-      Bootstrapper::CreateEnvironment(Handle<Object>::null(),
-                                      v8::Handle<ObjectTemplate>(),
-                                      NULL);
+      isolate_->bootstrapper()->CreateEnvironment(
+          Handle<Object>::null(),
+          v8::Handle<ObjectTemplate>(),
+          NULL);
 
   // Use the debugger context.
-  SaveContext save;
-  Top::set_context(*context);
+  SaveContext save(isolate_);
+  isolate_->set_context(*context);
 
   // Expose the builtins object in the debugger context.
-  Handle<String> key = Factory::LookupAsciiSymbol("builtins");
+  Handle<String> key = isolate_->factory()->LookupAsciiSymbol("builtins");
   Handle<GlobalObject> global = Handle<GlobalObject>(context->global());
   RETURN_IF_EMPTY_HANDLE_VALUE(
+      isolate_,
       SetProperty(global, key, Handle<Object>(global->builtins()),
                   NONE, kNonStrictMode),
       false);
 
   // Compile the JavaScript for the debugger in the debugger context.
-  Debugger::set_compiling_natives(true);
+  debugger->set_compiling_natives(true);
   bool caught_exception =
       !CompileDebuggerScript(Natives::GetIndex("mirror")) ||
       !CompileDebuggerScript(Natives::GetIndex("debug"));
@@ -851,11 +872,11 @@
         !CompileDebuggerScript(Natives::GetIndex("liveedit"));
   }
 
-  Debugger::set_compiling_natives(false);
+  debugger->set_compiling_natives(false);
 
   // Make sure we mark the debugger as not loading before we might
   // return.
-  Debugger::set_loading_debugger(false);
+  debugger->set_loading_debugger(false);
 
   // Check for caught exceptions.
   if (caught_exception) return false;
@@ -877,7 +898,8 @@
   DestroyScriptCache();
 
   // Clear debugger context global handle.
-  GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location()));
+  Isolate::Current()->global_handles()->Destroy(
+      reinterpret_cast<Object**>(debug_context_.location()));
   debug_context_ = Handle<Context>();
 }
 
@@ -895,30 +917,35 @@
 }
 
 
-Object* Debug::Break(Arguments args) {
-  HandleScope scope;
+// This remains a static method so that generated code can call it.
+Object* Debug::Break(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+
+  Debug* debug = isolate->debug();
+  Heap* heap = isolate->heap();
+  HandleScope scope(isolate);
   ASSERT(args.length() == 0);
 
-  thread_local_.frame_drop_mode_ = FRAMES_UNTOUCHED;
+  debug->thread_local_.frame_drop_mode_ = FRAMES_UNTOUCHED;
 
   // 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();
+  if (debug->disable_break() || !debug->Load()) {
+    debug->SetAfterBreakTarget(frame);
+    return heap->undefined_value();
   }
 
   // Enter the debugger.
   EnterDebugger debugger;
   if (debugger.FailedToEnter()) {
-    return Heap::undefined_value();
+    return heap->undefined_value();
   }
 
   // Postpone interrupt during breakpoint processing.
-  PostponeInterruptsScope postpone;
+  PostponeInterruptsScope postpone(isolate);
 
   // Get the debug info (create it if it does not exist).
   Handle<SharedFunctionInfo> shared =
@@ -931,71 +958,76 @@
   break_location_iterator.FindBreakLocationFromAddress(frame->pc());
 
   // Check whether step next reached a new statement.
-  if (!StepNextContinue(&break_location_iterator, frame)) {
+  if (!debug->StepNextContinue(&break_location_iterator, frame)) {
     // Decrease steps left if performing multiple steps.
-    if (thread_local_.step_count_ > 0) {
-      thread_local_.step_count_--;
+    if (debug->thread_local_.step_count_ > 0) {
+      debug->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());
+  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);
+    break_points_hit = debug->CheckBreakPoints(break_point_objects);
   }
 
   // If step out is active skip everything until the frame where we need to step
   // out to is reached, unless real breakpoint is hit.
-  if (Debug::StepOutActive() && frame->fp() != Debug::step_out_fp() &&
+  if (debug->StepOutActive() && frame->fp() != debug->step_out_fp() &&
       break_points_hit->IsUndefined() ) {
       // Step count should always be 0 for StepOut.
-      ASSERT(thread_local_.step_count_ == 0);
+      ASSERT(debug->thread_local_.step_count_ == 0);
   } else if (!break_points_hit->IsUndefined() ||
-             (thread_local_.last_step_action_ != StepNone &&
-              thread_local_.step_count_ == 0)) {
+             (debug->thread_local_.last_step_action_ != StepNone &&
+              debug->thread_local_.step_count_ == 0)) {
     // Notify debugger if a real break point is triggered or if performing
     // single stepping with no more steps to perform. Otherwise do another step.
 
     // Clear all current stepping setup.
-    ClearStepping();
+    debug->ClearStepping();
 
     // Notify the debug event listeners.
-    Debugger::OnDebugBreak(break_points_hit, false);
-  } else if (thread_local_.last_step_action_ != StepNone) {
+    isolate->debugger()->OnDebugBreak(break_points_hit, false);
+  } else if (debug->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_;
+    StepAction step_action = debug->thread_local_.last_step_action_;
+    int step_count = debug->thread_local_.step_count_;
 
     // Clear all current stepping setup.
-    ClearStepping();
+    debug->ClearStepping();
 
     // Set up for the remaining steps.
-    PrepareStep(step_action, step_count);
+    debug->PrepareStep(step_action, step_count);
   }
 
-  if (thread_local_.frame_drop_mode_ == FRAMES_UNTOUCHED) {
-    SetAfterBreakTarget(frame);
-  } else if (thread_local_.frame_drop_mode_ == FRAME_DROPPED_IN_IC_CALL) {
+  if (debug->thread_local_.frame_drop_mode_ == FRAMES_UNTOUCHED) {
+    debug->SetAfterBreakTarget(frame);
+  } else if (debug->thread_local_.frame_drop_mode_ ==
+      FRAME_DROPPED_IN_IC_CALL) {
     // We must have been calling IC stub. Do not go there anymore.
-    Code* plain_return = Builtins::builtin(Builtins::PlainReturn_LiveEdit);
-    thread_local_.after_break_target_ = plain_return->entry();
-  } else if (thread_local_.frame_drop_mode_ ==
+    Code* plain_return =
+        Isolate::Current()->builtins()->builtin(
+            Builtins::kPlainReturn_LiveEdit);
+    debug->thread_local_.after_break_target_ = plain_return->entry();
+  } else if (debug->thread_local_.frame_drop_mode_ ==
       FRAME_DROPPED_IN_DEBUG_SLOT_CALL) {
     // Debug break slot stub does not return normally, instead it manually
     // cleans the stack and jumps. We should patch the jump address.
-    Code* plain_return = Builtins::builtin(Builtins::FrameDropper_LiveEdit);
-    thread_local_.after_break_target_ = plain_return->entry();
-  } else if (thread_local_.frame_drop_mode_ == FRAME_DROPPED_IN_DIRECT_CALL) {
+    Code* plain_return = Isolate::Current()->builtins()->builtin(
+        Builtins::kFrameDropper_LiveEdit);
+    debug->thread_local_.after_break_target_ = plain_return->entry();
+  } else if (debug->thread_local_.frame_drop_mode_ ==
+      FRAME_DROPPED_IN_DIRECT_CALL) {
     // Nothing to do, after_break_target is not used here.
   } else {
     UNREACHABLE();
   }
 
-  return Heap::undefined_value();
+  return heap->undefined_value();
 }
 
 
@@ -1003,56 +1035,59 @@
 // 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);
+  Factory* factory = isolate_->factory();
 
-  // If there are multiple break points they are in a FixedArray.
+  // Count the number of break points hit. If there are multiple break points
+  // they are in a FixedArray.
+  Handle<FixedArray> break_points_hit;
+  int break_points_hit_count = 0;
   ASSERT(!break_point_objects->IsUndefined());
   if (break_point_objects->IsFixedArray()) {
     Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
+    break_points_hit = factory->NewFixedArray(array->length());
     for (int i = 0; i < array->length(); i++) {
       Handle<Object> o(array->get(i));
       if (CheckBreakPoint(o)) {
-        SetElement(break_points_hit,
-                   break_points_hit_count++,
-                   o,
-                   kNonStrictMode);
+        break_points_hit->set(break_points_hit_count++, *o);
       }
     }
   } else {
+    break_points_hit = factory->NewFixedArray(1);
     if (CheckBreakPoint(break_point_objects)) {
-      SetElement(break_points_hit,
-                 break_points_hit_count++,
-                 break_point_objects,
-                 kNonStrictMode);
+      break_points_hit->set(break_points_hit_count++, *break_point_objects);
     }
   }
 
   // Return undefined if no break points were triggered.
   if (break_points_hit_count == 0) {
-    return Factory::undefined_value();
+    return factory->undefined_value();
   }
-  return break_points_hit;
+  // Return break points hit as a JSArray.
+  Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
+  result->set_length(Smi::FromInt(break_points_hit_count));
+  return result;
 }
 
 
 // Check whether a single break point object is triggered.
 bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
-  HandleScope scope;
+  ASSERT(Isolate::Current() == isolate_);
+  Factory* factory = isolate_->factory();
+  HandleScope scope(isolate_);
 
   // 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).
+  // Get the function IsBreakPointTriggered (defined in debug-debugger.js).
   Handle<String> is_break_point_triggered_symbol =
-      Factory::LookupAsciiSymbol("IsBreakPointTriggered");
+      factory->LookupAsciiSymbol("IsBreakPointTriggered");
   Handle<JSFunction> check_break_point =
     Handle<JSFunction>(JSFunction::cast(
         debug_context()->global()->GetPropertyNoExceptionThrown(
             *is_break_point_triggered_symbol)));
 
   // Get the break id as an object.
-  Handle<Object> break_id = Factory::NewNumberFromInt(Debug::break_id());
+  Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
 
   // Call HandleBreakPointx.
   bool caught_exception = false;
@@ -1062,8 +1097,7 @@
     reinterpret_cast<Object**>(break_point_object.location())
   };
   Handle<Object> result = Execution::TryCall(check_break_point,
-                                             Top::builtins(), argc, argv,
-                                             &caught_exception);
+      isolate_->js_builtins_object(), argc, argv, &caught_exception);
 
   // If exception or non boolean result handle as not triggered
   if (caught_exception || !result->IsBoolean()) {
@@ -1071,7 +1105,8 @@
   }
 
   // Return whether the break point is triggered.
-  return *result == Heap::true_value();
+  ASSERT(!result.is_null());
+  return (*result)->IsTrue();
 }
 
 
@@ -1092,7 +1127,7 @@
 void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared,
                           Handle<Object> break_point_object,
                           int* source_position) {
-  HandleScope scope;
+  HandleScope scope(isolate_);
 
   if (!EnsureDebugInfo(shared)) {
     // Return if retrieving debug info failed.
@@ -1116,7 +1151,7 @@
 
 
 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
-  HandleScope scope;
+  HandleScope scope(isolate_);
 
   DebugInfoListNode* node = debug_info_list_;
   while (node != NULL) {
@@ -1222,7 +1257,8 @@
 
 
 void Debug::PrepareStep(StepAction step_action, int step_count) {
-  HandleScope scope;
+  ASSERT(Isolate::Current() == isolate_);
+  HandleScope scope(isolate_);
   ASSERT(Debug::InDebugger());
 
   // Remember this step action and count.
@@ -1370,8 +1406,10 @@
       // Reverse lookup required as the minor key cannot be retrieved
       // from the code object.
       Handle<Object> obj(
-          Heap::code_stubs()->SlowReverseLookup(*call_function_stub));
-      ASSERT(*obj != Heap::undefined_value());
+          isolate_->heap()->code_stubs()->SlowReverseLookup(
+              *call_function_stub));
+      ASSERT(!obj.is_null());
+      ASSERT(!(*obj)->IsUndefined());
       ASSERT(obj->IsSmi());
       // Get the STUB key and extract major and minor key.
       uint32_t key = Smi::cast(*obj)->value();
@@ -1489,18 +1527,16 @@
         return ComputeCallDebugBreak(code->arguments_count(), code->kind());
 
       case Code::LOAD_IC:
-        return Handle<Code>(Builtins::builtin(Builtins::LoadIC_DebugBreak));
+        return Isolate::Current()->builtins()->LoadIC_DebugBreak();
 
       case Code::STORE_IC:
-        return Handle<Code>(Builtins::builtin(Builtins::StoreIC_DebugBreak));
+        return Isolate::Current()->builtins()->StoreIC_DebugBreak();
 
       case Code::KEYED_LOAD_IC:
-        return Handle<Code>(
-            Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak));
+        return Isolate::Current()->builtins()->KeyedLoadIC_DebugBreak();
 
       case Code::KEYED_STORE_IC:
-        return Handle<Code>(
-            Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak));
+        return Isolate::Current()->builtins()->KeyedStoreIC_DebugBreak();
 
       default:
         UNREACHABLE();
@@ -1508,13 +1544,13 @@
   }
   if (RelocInfo::IsConstructCall(mode)) {
     Handle<Code> result =
-        Handle<Code>(Builtins::builtin(Builtins::ConstructCall_DebugBreak));
+        Isolate::Current()->builtins()->ConstructCall_DebugBreak();
     return result;
   }
   if (code->kind() == Code::STUB) {
     ASSERT(code->major_key() == CodeStub::CallFunction);
     Handle<Code> result =
-        Handle<Code>(Builtins::builtin(Builtins::StubNoRegisters_DebugBreak));
+        Isolate::Current()->builtins()->StubNoRegisters_DebugBreak();
     return result;
   }
 
@@ -1526,13 +1562,15 @@
 // 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());
+  Isolate* isolate = Isolate::Current();
+  Heap* heap = isolate->heap();
+  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());
+    return Handle<Object>(heap->undefined_value());
   }
   Handle<FixedArray> locations =
-      Factory::NewFixedArray(debug_info->GetBreakPointCount());
+      isolate->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()) {
@@ -1578,13 +1616,13 @@
 
   // Flood the function with one-shot break points if it is called from where
   // step into was requested.
-  if (fp == Debug::step_in_fp()) {
+  if (fp == step_in_fp()) {
     // Don't allow step into functions in the native context.
     if (!function->IsBuiltin()) {
       if (function->shared()->code() ==
-          Builtins::builtin(Builtins::FunctionApply) ||
+          Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply) ||
           function->shared()->code() ==
-          Builtins::builtin(Builtins::FunctionCall)) {
+          Isolate::Current()->builtins()->builtin(Builtins::kFunctionCall)) {
         // Handle function.apply and function.call separately to flood the
         // function to be called and not the code for Builtins::FunctionApply or
         // Builtins::FunctionCall. The receiver of call/apply is the target
@@ -1678,7 +1716,7 @@
   }
 
   // Create the debug info object.
-  Handle<DebugInfo> debug_info = Factory::NewDebugInfo(shared);
+  Handle<DebugInfo> debug_info = FACTORY->NewDebugInfo(shared);
 
   // Add debug info to the list.
   DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
@@ -1705,7 +1743,8 @@
       } else {
         prev->set_next(current->next());
       }
-      current->debug_info()->shared()->set_debug_info(Heap::undefined_value());
+      current->debug_info()->shared()->set_debug_info(
+              isolate_->heap()->undefined_value());
       delete current;
 
       // If there are no more debug info objects there are not more break
@@ -1723,7 +1762,8 @@
 
 
 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
-  HandleScope scope;
+  ASSERT(Isolate::Current() == isolate_);
+  HandleScope scope(isolate_);
 
   // Get the executing function in which the debug break occurred.
   Handle<SharedFunctionInfo> shared =
@@ -1737,7 +1777,7 @@
   Handle<Code> original_code(debug_info->original_code());
 #ifdef DEBUG
   // Get the code which is actually executing.
-  Handle<Code> frame_code(frame->code());
+  Handle<Code> frame_code(frame->LookupCode(isolate_));
   ASSERT(frame_code.is_identical_to(code));
 #endif
 
@@ -1806,7 +1846,7 @@
 
 
 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
-  HandleScope scope;
+  HandleScope scope(isolate_);
 
   // Get the executing function in which the debug break occurred.
   Handle<SharedFunctionInfo> shared =
@@ -1819,7 +1859,7 @@
   Handle<Code> code(debug_info->code());
 #ifdef DEBUG
   // Get the code which is actually executing.
-  Handle<Code> frame_code(frame->code());
+  Handle<Code> frame_code(frame->LookupCode(Isolate::Current()));
   ASSERT(frame_code.is_identical_to(code));
 #endif
 
@@ -1850,19 +1890,20 @@
 
 
 bool Debug::IsDebugGlobal(GlobalObject* global) {
-  return IsLoaded() && global == Debug::debug_context()->global();
+  return IsLoaded() && global == debug_context()->global();
 }
 
 
 void Debug::ClearMirrorCache() {
-  PostponeInterruptsScope postpone;
-  HandleScope scope;
-  ASSERT(Top::context() == *Debug::debug_context());
+  ASSERT(Isolate::Current() == isolate_);
+  PostponeInterruptsScope postpone(isolate_);
+  HandleScope scope(isolate_);
+  ASSERT(isolate_->context() == *Debug::debug_context());
 
   // Clear the mirror cache.
   Handle<String> function_name =
-      Factory::LookupSymbol(CStrVector("ClearMirrorCache"));
-  Handle<Object> fun(Top::global()->GetPropertyNoExceptionThrown(
+      isolate_->factory()->LookupSymbol(CStrVector("ClearMirrorCache"));
+  Handle<Object> fun(Isolate::Current()->global()->GetPropertyNoExceptionThrown(
       *function_name));
   ASSERT(fun->IsJSFunction());
   bool caught_exception;
@@ -1874,13 +1915,15 @@
 
 
 void Debug::CreateScriptCache() {
-  HandleScope scope;
+  ASSERT(Isolate::Current() == isolate_);
+  Heap* heap = isolate_->heap();
+  HandleScope scope(isolate_);
 
   // 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 are no longer referenced.
-  Heap::CollectAllGarbage(false);
-  Heap::CollectAllGarbage(false);
+  heap->CollectAllGarbage(false);
+  heap->CollectAllGarbage(false);
 
   ASSERT(script_cache_ == NULL);
   script_cache_ = new ScriptCache();
@@ -1914,6 +1957,7 @@
 
 
 Handle<FixedArray> Debug::GetLoadedScripts() {
+  ASSERT(Isolate::Current() == isolate_);
   // Create and fill the script cache when the loaded scripts is requested for
   // the first time.
   if (script_cache_ == NULL) {
@@ -1923,12 +1967,12 @@
   // If the script cache is not active just return an empty array.
   ASSERT(script_cache_ != NULL);
   if (script_cache_ == NULL) {
-    Factory::NewFixedArray(0);
+    isolate_->factory()->NewFixedArray(0);
   }
 
   // Perform GC to get unreferenced scripts evicted from the cache before
   // returning the content.
-  Heap::CollectAllGarbage(false);
+  isolate_->heap()->CollectAllGarbage(false);
 
   // Get the scripts from the cache.
   return script_cache_->GetScripts();
@@ -1943,51 +1987,66 @@
 }
 
 
-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;
-v8::Debug::MessageHandler2 Debugger::message_handler_ = NULL;
-bool Debugger::debugger_unload_pending_ = false;
-v8::Debug::HostDispatchHandler Debugger::host_dispatch_handler_ = NULL;
-Mutex* Debugger::dispatch_handler_access_ = OS::CreateMutex();
-v8::Debug::DebugMessageDispatchHandler
-    Debugger::debug_message_dispatch_handler_ = NULL;
-MessageDispatchHelperThread* Debugger::message_dispatch_helper_thread_ = NULL;
-int Debugger::host_dispatch_micros_ = 100 * 1000;
-DebuggerAgent* Debugger::agent_ = NULL;
-LockingCommandMessageQueue Debugger::command_queue_(kQueueInitialSize);
-Semaphore* Debugger::command_received_ = OS::CreateSemaphore(0);
-LockingCommandMessageQueue Debugger::event_command_queue_(kQueueInitialSize);
+Debugger::Debugger()
+    : debugger_access_(OS::CreateMutex()),
+      event_listener_(Handle<Object>()),
+      event_listener_data_(Handle<Object>()),
+      compiling_natives_(false),
+      is_loading_debugger_(false),
+      never_unload_debugger_(false),
+      message_handler_(NULL),
+      debugger_unload_pending_(false),
+      host_dispatch_handler_(NULL),
+      dispatch_handler_access_(OS::CreateMutex()),
+      debug_message_dispatch_handler_(NULL),
+      message_dispatch_helper_thread_(NULL),
+      host_dispatch_micros_(100 * 1000),
+      agent_(NULL),
+      command_queue_(kQueueInitialSize),
+      command_received_(OS::CreateSemaphore(0)),
+      event_command_queue_(kQueueInitialSize) {
+}
+
+
+Debugger::~Debugger() {
+  delete debugger_access_;
+  debugger_access_ = 0;
+  delete dispatch_handler_access_;
+  dispatch_handler_access_ = 0;
+  delete command_received_;
+  command_received_ = 0;
+}
 
 
 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
                                       int argc, Object*** argv,
                                       bool* caught_exception) {
-  ASSERT(Top::context() == *Debug::debug_context());
+  ASSERT(Isolate::Current() == isolate_);
+  ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
 
   // Create the execution state object.
-  Handle<String> constructor_str = Factory::LookupSymbol(constructor_name);
-  Handle<Object> constructor(Top::global()->GetPropertyNoExceptionThrown(
-      *constructor_str));
+  Handle<String> constructor_str =
+      isolate_->factory()->LookupSymbol(constructor_name);
+  Handle<Object> constructor(
+      isolate_->global()->GetPropertyNoExceptionThrown(*constructor_str));
   ASSERT(constructor->IsJSFunction());
   if (!constructor->IsJSFunction()) {
     *caught_exception = true;
-    return Factory::undefined_value();
+    return isolate_->factory()->undefined_value();
   }
   Handle<Object> js_object = Execution::TryCall(
       Handle<JSFunction>::cast(constructor),
-      Handle<JSObject>(Debug::debug_context()->global()), argc, argv,
-      caught_exception);
+      Handle<JSObject>(isolate_->debug()->debug_context()->global()),
+      argc, argv, caught_exception);
   return js_object;
 }
 
 
 Handle<Object> Debugger::MakeExecutionState(bool* caught_exception) {
+  ASSERT(Isolate::Current() == isolate_);
   // Create the execution state object.
-  Handle<Object> break_id = Factory::NewNumberFromInt(Debug::break_id());
+  Handle<Object> break_id = isolate_->factory()->NewNumberFromInt(
+      isolate_->debug()->break_id());
   const int argc = 1;
   Object** argv[argc] = { break_id.location() };
   return MakeJSObject(CStrVector("MakeExecutionState"),
@@ -1998,6 +2057,7 @@
 Handle<Object> Debugger::MakeBreakEvent(Handle<Object> exec_state,
                                         Handle<Object> break_points_hit,
                                         bool* caught_exception) {
+  ASSERT(Isolate::Current() == isolate_);
   // Create the new break event object.
   const int argc = 2;
   Object** argv[argc] = { exec_state.location(),
@@ -2013,12 +2073,14 @@
                                             Handle<Object> exception,
                                             bool uncaught,
                                             bool* caught_exception) {
+  ASSERT(Isolate::Current() == isolate_);
+  Factory* factory = isolate_->factory();
   // 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()};
+                          uncaught ? factory->true_value().location() :
+                                     factory->false_value().location()};
   return MakeJSObject(CStrVector("MakeExceptionEvent"),
                       argc, argv, caught_exception);
 }
@@ -2026,6 +2088,7 @@
 
 Handle<Object> Debugger::MakeNewFunctionEvent(Handle<Object> function,
                                               bool* caught_exception) {
+  ASSERT(Isolate::Current() == isolate_);
   // Create the new function event object.
   const int argc = 1;
   Object** argv[argc] = { function.location() };
@@ -2037,14 +2100,16 @@
 Handle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
                                           bool before,
                                           bool* caught_exception) {
+  ASSERT(Isolate::Current() == isolate_);
+  Factory* factory = isolate_->factory();
   // 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() };
+                          before ? factory->true_value().location() :
+                                   factory->false_value().location() };
 
   return MakeJSObject(CStrVector("MakeCompileEvent"),
                       argc,
@@ -2055,6 +2120,7 @@
 
 Handle<Object> Debugger::MakeScriptCollectedEvent(int id,
                                                   bool* caught_exception) {
+  ASSERT(Isolate::Current() == isolate_);
   // Create the script collected event object.
   Handle<Object> exec_state = MakeExecutionState(caught_exception);
   Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id));
@@ -2069,20 +2135,22 @@
 
 
 void Debugger::OnException(Handle<Object> exception, bool uncaught) {
-  HandleScope scope;
+  ASSERT(Isolate::Current() == isolate_);
+  HandleScope scope(isolate_);
+  Debug* debug = isolate_->debug();
 
   // Bail out based on state or if there is no listener for this event
-  if (Debug::InDebugger()) return;
+  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;
+    if (!(debug->break_on_uncaught_exception() ||
+          debug->break_on_exception())) return;
   } else {
     // Caught exceptions are reported is activated.
-    if (!Debug::break_on_exception()) return;
+    if (!debug->break_on_exception()) return;
   }
 
   // Enter the debugger.
@@ -2090,7 +2158,7 @@
   if (debugger.FailedToEnter()) return;
 
   // Clear all current stepping setup.
-  Debug::ClearStepping();
+  debug->ClearStepping();
   // Create the event data object.
   bool caught_exception = false;
   Handle<Object> exec_state = MakeExecutionState(&caught_exception);
@@ -2112,16 +2180,17 @@
 
 void Debugger::OnDebugBreak(Handle<Object> break_points_hit,
                             bool auto_continue) {
-  HandleScope scope;
+  ASSERT(Isolate::Current() == isolate_);
+  HandleScope scope(isolate_);
 
   // Debugger has already been entered by caller.
-  ASSERT(Top::context() == *Debug::debug_context());
+  ASSERT(isolate_->context() == *isolate_->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());
+  ASSERT(Isolate::Current()->context() == *isolate_->debug()->debug_context());
 
   // Create the event data object.
   bool caught_exception = false;
@@ -2144,10 +2213,11 @@
 
 
 void Debugger::OnBeforeCompile(Handle<Script> script) {
-  HandleScope scope;
+  ASSERT(Isolate::Current() == isolate_);
+  HandleScope scope(isolate_);
 
   // Bail out based on state or if there is no listener for this event
-  if (Debug::InDebugger()) return;
+  if (isolate_->debug()->InDebugger()) return;
   if (compiling_natives()) return;
   if (!EventActive(v8::BeforeCompile)) return;
 
@@ -2173,10 +2243,12 @@
 // Handle debugger actions when a new script is compiled.
 void Debugger::OnAfterCompile(Handle<Script> script,
                               AfterCompileFlags after_compile_flags) {
-  HandleScope scope;
+  ASSERT(Isolate::Current() == isolate_);
+  HandleScope scope(isolate_);
+  Debug* debug = isolate_->debug();
 
   // Add the newly compiled script to the script cache.
-  Debug::AddScriptToScriptCache(script);
+  debug->AddScriptToScriptCache(script);
 
   // No more to do if not debugging.
   if (!IsDebuggerActive()) return;
@@ -2185,7 +2257,7 @@
   if (compiling_natives()) return;
 
   // Store whether in debugger before entering debugger.
-  bool in_debugger = Debug::InDebugger();
+  bool in_debugger = debug->InDebugger();
 
   // Enter the debugger.
   EnterDebugger debugger;
@@ -2196,9 +2268,9 @@
 
   // Get the function UpdateScriptBreakPoints (defined in debug-debugger.js).
   Handle<String> update_script_break_points_symbol =
-      Factory::LookupAsciiSymbol("UpdateScriptBreakPoints");
+      isolate_->factory()->LookupAsciiSymbol("UpdateScriptBreakPoints");
   Handle<Object> update_script_break_points =
-      Handle<Object>(Debug::debug_context()->global()->
+      Handle<Object>(debug->debug_context()->global()->
           GetPropertyNoExceptionThrown(*update_script_break_points_symbol));
   if (!update_script_break_points->IsJSFunction()) {
     return;
@@ -2215,7 +2287,7 @@
   Object** argv[argc] = { reinterpret_cast<Object**>(wrapper.location()) };
   Handle<Object> result = Execution::TryCall(
       Handle<JSFunction>::cast(update_script_break_points),
-      Top::builtins(), argc, argv,
+      Isolate::Current()->js_builtins_object(), argc, argv,
       &caught_exception);
   if (caught_exception) {
     return;
@@ -2240,7 +2312,8 @@
 
 
 void Debugger::OnScriptCollected(int id) {
-  HandleScope scope;
+  ASSERT(Isolate::Current() == isolate_);
+  HandleScope scope(isolate_);
 
   // No more to do if not debugging.
   if (!IsDebuggerActive()) return;
@@ -2269,11 +2342,12 @@
 void Debugger::ProcessDebugEvent(v8::DebugEvent event,
                                  Handle<JSObject> event_data,
                                  bool auto_continue) {
-  HandleScope scope;
+  ASSERT(Isolate::Current() == isolate_);
+  HandleScope scope(isolate_);
 
   // Clear any pending debug break if this is a real break.
   if (!auto_continue) {
-    Debug::clear_interrupt_pending(DEBUGBREAK);
+    isolate_->debug()->clear_interrupt_pending(DEBUGBREAK);
   }
 
   // Create the execution state.
@@ -2344,6 +2418,7 @@
                                    Handle<Object> exec_state,
                                    Handle<Object> event_data) {
   ASSERT(event_listener_->IsJSFunction());
+  ASSERT(Isolate::Current() == isolate_);
   Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_));
 
   // Invoke the JavaScript debug event listener.
@@ -2353,25 +2428,29 @@
                           Handle<Object>::cast(event_data).location(),
                           event_listener_data_.location() };
   bool caught_exception = false;
-  Execution::TryCall(fun, Top::global(), argc, argv, &caught_exception);
+  Execution::TryCall(fun, isolate_->global(), argc, argv, &caught_exception);
   // Silently ignore exceptions from debug event listeners.
 }
 
 
 Handle<Context> Debugger::GetDebugContext() {
-    never_unload_debugger_ = true;
-    EnterDebugger debugger;
-    return Debug::debug_context();
+  ASSERT(Isolate::Current() == isolate_);
+  never_unload_debugger_ = true;
+  EnterDebugger debugger;
+  return isolate_->debug()->debug_context();
 }
 
 
 void Debugger::UnloadDebugger() {
+  ASSERT(Isolate::Current() == isolate_);
+  Debug* debug = isolate_->debug();
+
   // Make sure that there are no breakpoints left.
-  Debug::ClearAllBreakPoints();
+  debug->ClearAllBreakPoints();
 
   // Unload the debugger if feasible.
   if (!never_unload_debugger_) {
-    Debug::Unload();
+    debug->Unload();
   }
 
   // Clear the flag indicating that the debugger should be unloaded.
@@ -2383,9 +2462,10 @@
                                     Handle<JSObject> exec_state,
                                     Handle<JSObject> event_data,
                                     bool auto_continue) {
-  HandleScope scope;
+  ASSERT(Isolate::Current() == isolate_);
+  HandleScope scope(isolate_);
 
-  if (!Debug::Load()) return;
+  if (!isolate_->debug()->Load()) return;
 
   // Process the individual events.
   bool sendEventMessage = false;
@@ -2414,8 +2494,8 @@
   // The debug command interrupt flag might have been set when the command was
   // added. It should be enough to clear the flag only once while we are in the
   // debugger.
-  ASSERT(Debug::InDebugger());
-  StackGuard::Continue(DEBUGCOMMAND);
+  ASSERT(isolate_->debug()->InDebugger());
+  isolate_->stack_guard()->Continue(DEBUGCOMMAND);
 
   // Notify the debugger that a debug event has occurred unless auto continue is
   // active in which case no event is send.
@@ -2478,7 +2558,7 @@
 
     // Get the command from the queue.
     CommandMessage command = command_queue_.Get();
-    Logger::DebugTag("Got request from command queue, in interactive loop.");
+    LOGGER->DebugTag("Got request from command queue, in interactive loop.");
     if (!Debugger::IsDebuggerActive()) {
       // Delete command text and user data.
       command.Dispose();
@@ -2552,17 +2632,19 @@
 
 void Debugger::SetEventListener(Handle<Object> callback,
                                 Handle<Object> data) {
-  HandleScope scope;
+  ASSERT(Isolate::Current() == isolate_);
+  HandleScope scope(isolate_);
+  GlobalHandles* global_handles = isolate_->global_handles();
 
   // Clear the global handles for the event listener and the event listener data
   // object.
   if (!event_listener_.is_null()) {
-    GlobalHandles::Destroy(
+    global_handles->Destroy(
         reinterpret_cast<Object**>(event_listener_.location()));
     event_listener_ = Handle<Object>();
   }
   if (!event_listener_data_.is_null()) {
-    GlobalHandles::Destroy(
+    global_handles->Destroy(
         reinterpret_cast<Object**>(event_listener_data_.location()));
     event_listener_data_ = Handle<Object>();
   }
@@ -2570,11 +2652,13 @@
   // 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));
+    event_listener_ = Handle<Object>::cast(
+        global_handles->Create(*callback));
     if (data.is_null()) {
-      data = Factory::undefined_value();
+      data = isolate_->factory()->undefined_value();
     }
-    event_listener_data_ = Handle<Object>::cast(GlobalHandles::Create(*data));
+    event_listener_data_ = Handle<Object>::cast(
+        global_handles->Create(*data));
   }
 
   ListenersChanged();
@@ -2582,6 +2666,7 @@
 
 
 void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) {
+  ASSERT(Isolate::Current() == isolate_);
   ScopedLock with(debugger_access_);
 
   message_handler_ = handler;
@@ -2589,7 +2674,7 @@
   if (handler == NULL) {
     // Send an empty command to the debugger if in a break to make JavaScript
     // run again if the debugger is closed.
-    if (Debug::InDebugger()) {
+    if (isolate_->debug()->InDebugger()) {
       ProcessCommand(Vector<const uint16_t>::empty());
     }
   }
@@ -2597,12 +2682,13 @@
 
 
 void Debugger::ListenersChanged() {
+  ASSERT(Isolate::Current() == isolate_);
   if (IsDebuggerActive()) {
     // Disable the compilation cache when the debugger is active.
-    CompilationCache::Disable();
+    isolate_->compilation_cache()->Disable();
     debugger_unload_pending_ = false;
   } else {
-    CompilationCache::Enable();
+    isolate_->compilation_cache()->Enable();
     // Unload the debugger if event listener and message handler cleared.
     // Schedule this for later, because we may be in non-V8 thread.
     debugger_unload_pending_ = true;
@@ -2612,6 +2698,7 @@
 
 void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
                                       int period) {
+  ASSERT(Isolate::Current() == isolate_);
   host_dispatch_handler_ = handler;
   host_dispatch_micros_ = period * 1000;
 }
@@ -2619,11 +2706,12 @@
 
 void Debugger::SetDebugMessageDispatchHandler(
     v8::Debug::DebugMessageDispatchHandler handler, bool provide_locker) {
+  ASSERT(Isolate::Current() == isolate_);
   ScopedLock with(dispatch_handler_access_);
   debug_message_dispatch_handler_ = handler;
 
   if (provide_locker && message_dispatch_helper_thread_ == NULL) {
-    message_dispatch_helper_thread_ = new MessageDispatchHelperThread;
+    message_dispatch_helper_thread_ = new MessageDispatchHelperThread(isolate_);
     message_dispatch_helper_thread_->Start();
   }
 }
@@ -2632,6 +2720,7 @@
 // Calls the registered debug message handler. This callback is part of the
 // public API.
 void Debugger::InvokeMessageHandler(MessageImpl message) {
+  ASSERT(Isolate::Current() == isolate_);
   ScopedLock with(debugger_access_);
 
   if (message_handler_ != NULL) {
@@ -2646,18 +2735,19 @@
 // by the API client thread.
 void Debugger::ProcessCommand(Vector<const uint16_t> command,
                               v8::Debug::ClientData* client_data) {
+  ASSERT(Isolate::Current() == isolate_);
   // Need to cast away const.
   CommandMessage message = CommandMessage::New(
       Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
                        command.length()),
       client_data);
-  Logger::DebugTag("Put command on command_queue.");
+  LOGGER->DebugTag("Put command on command_queue.");
   command_queue_.Put(message);
   command_received_->Signal();
 
   // Set the debug command break flag to have the command processed.
-  if (!Debug::InDebugger()) {
-    StackGuard::DebugCommand();
+  if (!isolate_->debug()->InDebugger()) {
+    isolate_->stack_guard()->DebugCommand();
   }
 
   MessageDispatchHelperThread* dispatch_thread;
@@ -2675,22 +2765,25 @@
 
 
 bool Debugger::HasCommands() {
+  ASSERT(Isolate::Current() == isolate_);
   return !command_queue_.IsEmpty();
 }
 
 
 void Debugger::EnqueueDebugCommand(v8::Debug::ClientData* client_data) {
+  ASSERT(Isolate::Current() == isolate_);
   CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data);
   event_command_queue_.Put(message);
 
   // Set the debug command break flag to have the command processed.
-  if (!Debug::InDebugger()) {
-    StackGuard::DebugCommand();
+  if (!isolate_->debug()->InDebugger()) {
+    isolate_->stack_guard()->DebugCommand();
   }
 }
 
 
 bool Debugger::IsDebuggerActive() {
+  ASSERT(Isolate::Current() == isolate_);
   ScopedLock with(debugger_access_);
 
   return message_handler_ != NULL || !event_listener_.is_null();
@@ -2700,27 +2793,28 @@
 Handle<Object> Debugger::Call(Handle<JSFunction> fun,
                               Handle<Object> data,
                               bool* pending_exception) {
+  ASSERT(Isolate::Current() == isolate_);
   // When calling functions in the debugger prevent it from beeing unloaded.
   Debugger::never_unload_debugger_ = true;
 
   // Enter the debugger.
   EnterDebugger debugger;
   if (debugger.FailedToEnter()) {
-    return Factory::undefined_value();
+    return isolate_->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();
+    return isolate_->factory()->undefined_value();
   }
 
   static const int kArgc = 2;
   Object** argv[kArgc] = { exec_state.location(), data.location() };
   Handle<Object> result = Execution::Call(
       fun,
-      Handle<Object>(Debug::debug_context_->global_proxy()),
+      Handle<Object>(isolate_->debug()->debug_context_->global_proxy()),
       kArgc,
       argv,
       pending_exception);
@@ -2735,6 +2829,7 @@
 
 bool Debugger::StartAgent(const char* name, int port,
                           bool wait_for_connection) {
+  ASSERT(Isolate::Current() == isolate_);
   if (wait_for_connection) {
     // Suspend V8 if it is already running or set V8 to suspend whenever
     // it starts.
@@ -2748,7 +2843,7 @@
 
   if (Socket::Setup()) {
     if (agent_ == NULL) {
-      agent_ = new DebuggerAgent(name, port);
+      agent_ = new DebuggerAgent(isolate_, name, port);
       agent_->Start();
     }
     return true;
@@ -2759,6 +2854,7 @@
 
 
 void Debugger::StopAgent() {
+  ASSERT(Isolate::Current() == isolate_);
   if (agent_ != NULL) {
     agent_->Shutdown();
     agent_->Join();
@@ -2769,12 +2865,14 @@
 
 
 void Debugger::WaitForAgent() {
+  ASSERT(Isolate::Current() == isolate_);
   if (agent_ != NULL)
     agent_->WaitUntilListening();
 }
 
 
 void Debugger::CallMessageDispatchHandler() {
+  ASSERT(Isolate::Current() == isolate_);
   v8::Debug::DebugMessageDispatchHandler handler;
   {
     ScopedLock with(dispatch_handler_access_);
@@ -2878,10 +2976,11 @@
 
 
 v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
-  v8::Handle<v8::Context> context = GetDebugEventContext();
-  // Top::context() may be NULL when "script collected" event occures.
+  Isolate* isolate = Isolate::Current();
+  v8::Handle<v8::Context> context = GetDebugEventContext(isolate);
+  // Isolate::context() may be NULL when "script collected" event occures.
   ASSERT(!context.IsEmpty() || event_ == v8::ScriptCollected);
-  return GetDebugEventContext();
+  return GetDebugEventContext(isolate);
 }
 
 
@@ -2918,7 +3017,7 @@
 
 
 v8::Handle<v8::Context> EventDetailsImpl::GetEventContext() const {
-  return GetDebugEventContext();
+  return GetDebugEventContext(Isolate::Current());
 }
 
 
@@ -3027,7 +3126,7 @@
 CommandMessage LockingCommandMessageQueue::Get() {
   ScopedLock sl(lock_);
   CommandMessage result = queue_.Get();
-  Logger::DebugEvent("Get", result.text());
+  LOGGER->DebugEvent("Get", result.text());
   return result;
 }
 
@@ -3035,7 +3134,7 @@
 void LockingCommandMessageQueue::Put(const CommandMessage& message) {
   ScopedLock sl(lock_);
   queue_.Put(message);
-  Logger::DebugEvent("Put", message.text());
+  LOGGER->DebugEvent("Put", message.text());
 }
 
 
@@ -3045,8 +3144,8 @@
 }
 
 
-MessageDispatchHelperThread::MessageDispatchHelperThread()
-    : Thread("v8:MsgDispHelpr"),
+MessageDispatchHelperThread::MessageDispatchHelperThread(Isolate* isolate)
+    : Thread(isolate, "v8:MsgDispHelpr"),
       sem_(OS::CreateSemaphore(0)), mutex_(OS::CreateMutex()),
       already_signalled_(false) {
 }
@@ -3079,7 +3178,7 @@
     }
     {
       Locker locker;
-      Debugger::CallMessageDispatchHandler();
+      Isolate::Current()->debugger()->CallMessageDispatchHandler();
     }
   }
 }
diff --git a/src/debug.h b/src/debug.h
index 85c4d53..d512595 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -28,6 +28,7 @@
 #ifndef V8_DEBUG_H_
 #define V8_DEBUG_H_
 
+#include "arguments.h"
 #include "assembler.h"
 #include "debug-agent.h"
 #include "execution.h"
@@ -210,7 +211,6 @@
   DebugInfoListNode* next_;
 };
 
-
 // This class contains the debugger support. The main purpose is to handle
 // setting break points in the code.
 //
@@ -220,33 +220,33 @@
 // 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);
+  void Setup(bool create_heap_objects);
+  bool Load();
+  void Unload();
+  bool IsLoaded() { return !debug_context_.is_null(); }
+  bool InDebugger() { return thread_local_.debugger_entry_ != NULL; }
+  void PreemptionWhileInDebugger();
+  void Iterate(ObjectVisitor* v);
 
-  static Object* Break(Arguments args);
-  static void SetBreakPoint(Handle<SharedFunctionInfo> shared,
-                            Handle<Object> break_point_object,
-                            int* source_position);
-  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 bool IsBreakOnException(ExceptionBreakType type);
-  static void PrepareStep(StepAction step_action, int step_count);
-  static void ClearStepping();
-  static bool StepNextContinue(BreakLocationIterator* break_location_iterator,
-                               JavaScriptFrame* frame);
+  static Object* Break(RUNTIME_CALLING_CONVENTION);
+  void SetBreakPoint(Handle<SharedFunctionInfo> shared,
+                     Handle<Object> break_point_object,
+                     int* source_position);
+  void ClearBreakPoint(Handle<Object> break_point_object);
+  void ClearAllBreakPoints();
+  void FloodWithOneShot(Handle<SharedFunctionInfo> shared);
+  void FloodHandlerWithOneShot();
+  void ChangeBreakOnException(ExceptionBreakType type, bool enable);
+  bool IsBreakOnException(ExceptionBreakType type);
+  void PrepareStep(StepAction step_action, int step_count);
+  void ClearStepping();
+  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);
+  bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared);
 
   // Returns true if the current stub call is patched to call the debugger.
   static bool IsDebugBreak(Address addr);
@@ -266,66 +266,66 @@
       Handle<SharedFunctionInfo> shared);
 
   // Getter for the debug_context.
-  inline static Handle<Context> debug_context() { return debug_context_; }
+  inline Handle<Context> debug_context() { return debug_context_; }
 
   // Check whether a global object is the debug global object.
-  static bool IsDebugGlobal(GlobalObject* global);
+  bool IsDebugGlobal(GlobalObject* global);
 
   // Check whether this frame is just about to return.
-  static bool IsBreakAtReturn(JavaScriptFrame* frame);
+  bool IsBreakAtReturn(JavaScriptFrame* frame);
 
   // Fast check to see if any break points are active.
-  inline static bool has_break_points() { return has_break_points_; }
+  inline 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() {
+  void NewBreak(StackFrame::Id break_frame_id);
+  void SetBreak(StackFrame::Id break_frame_id, int break_id);
+  StackFrame::Id break_frame_id() {
     return thread_local_.break_frame_id_;
   }
-  static int break_id() { return thread_local_.break_id_; }
+  int break_id() { return thread_local_.break_id_; }
 
-  static bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
-  static void HandleStepIn(Handle<JSFunction> function,
-                           Handle<Object> holder,
-                           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_; }
+  bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
+  void HandleStepIn(Handle<JSFunction> function,
+                    Handle<Object> holder,
+                    Address fp,
+                    bool is_constructor);
+  Address step_in_fp() { return thread_local_.step_into_fp_; }
+  Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; }
 
-  static bool StepOutActive() { return thread_local_.step_out_fp_ != 0; }
-  static Address step_out_fp() { return thread_local_.step_out_fp_; }
+  bool StepOutActive() { return thread_local_.step_out_fp_ != 0; }
+  Address step_out_fp() { return thread_local_.step_out_fp_; }
 
-  static EnterDebugger* debugger_entry() {
+  EnterDebugger* debugger_entry() {
     return thread_local_.debugger_entry_;
   }
-  static void set_debugger_entry(EnterDebugger* entry) {
+  void set_debugger_entry(EnterDebugger* entry) {
     thread_local_.debugger_entry_ = entry;
   }
 
   // Check whether any of the specified interrupts are pending.
-  static bool is_interrupt_pending(InterruptFlag what) {
+  bool is_interrupt_pending(InterruptFlag what) {
     return (thread_local_.pending_interrupts_ & what) != 0;
   }
 
   // Set specified interrupts as pending.
-  static void set_interrupts_pending(InterruptFlag what) {
+  void set_interrupts_pending(InterruptFlag what) {
     thread_local_.pending_interrupts_ |= what;
   }
 
   // Clear specified interrupts from pending.
-  static void clear_interrupt_pending(InterruptFlag what) {
+  void clear_interrupt_pending(InterruptFlag what) {
     thread_local_.pending_interrupts_ &= ~static_cast<int>(what);
   }
 
   // Getter and setter for the disable break state.
-  static bool disable_break() { return disable_break_; }
-  static void set_disable_break(bool disable_break) {
+  bool disable_break() { return disable_break_; }
+  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() {
+  bool break_on_exception() { return break_on_exception_; }
+  bool break_on_uncaught_exception() {
     return break_on_uncaught_exception_;
   }
 
@@ -337,34 +337,35 @@
   };
 
   // Support for setting the address to jump to when returning from break point.
-  static Address* after_break_target_address() {
+  Address* after_break_target_address() {
     return reinterpret_cast<Address*>(&thread_local_.after_break_target_);
   }
-  static Address* restarter_frame_function_pointer_address() {
+  Address* restarter_frame_function_pointer_address() {
     Object*** address = &thread_local_.restarter_frame_function_pointer_;
     return reinterpret_cast<Address*>(address);
   }
 
   // Support for saving/restoring registers when handling debug break calls.
-  static Object** register_address(int r) {
+  Object** register_address(int r) {
     return &registers_[r];
   }
 
   // Access to the debug break on return code.
-  static Code* debug_break_return() { return debug_break_return_; }
-  static Code** debug_break_return_address() {
+  Code* debug_break_return() { return debug_break_return_; }
+  Code** debug_break_return_address() {
     return &debug_break_return_;
   }
 
   // Access to the debug break in debug break slot code.
-  static Code* debug_break_slot() { return debug_break_slot_; }
-  static Code** debug_break_slot_address() {
+  Code* debug_break_slot() { return debug_break_slot_; }
+  Code** debug_break_slot_address() {
     return &debug_break_slot_;
   }
 
   static const int kEstimatedNofDebugInfoEntries = 16;
   static const int kEstimatedNofBreakPointsInFunction = 16;
 
+  // Passed to MakeWeak.
   static void HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data);
 
   friend class Debugger;
@@ -372,22 +373,22 @@
   friend void CheckDebuggerUnloaded(bool check_functions);  // In test-debug.cc
 
   // Threading support.
-  static char* ArchiveDebug(char* to);
-  static char* RestoreDebug(char* from);
+  char* ArchiveDebug(char* to);
+  char* RestoreDebug(char* from);
   static int ArchiveSpacePerThread();
-  static void FreeThreadResources() { }
+  void FreeThreadResources() { }
 
   // Mirror cache handling.
-  static void ClearMirrorCache();
+  void ClearMirrorCache();
 
   // Script cache handling.
-  static void CreateScriptCache();
-  static void DestroyScriptCache();
-  static void AddScriptToScriptCache(Handle<Script> script);
-  static Handle<FixedArray> GetLoadedScripts();
+  void CreateScriptCache();
+  void DestroyScriptCache();
+  void AddScriptToScriptCache(Handle<Script> script);
+  Handle<FixedArray> GetLoadedScripts();
 
   // Garbage collection notifications.
-  static void AfterGarbageCollection();
+  void AfterGarbageCollection();
 
   // Code generator routines.
   static void GenerateSlot(MacroAssembler* masm);
@@ -424,7 +425,7 @@
     FRAME_DROPPED_IN_DIRECT_CALL
   };
 
-  static void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
+  void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
                                     FrameDropMode mode,
                                     Object** restarter_frame_function_pointer);
 
@@ -445,35 +446,38 @@
   static const bool kFrameDropperSupported;
 
  private:
+  explicit Debug(Isolate* isolate);
+  ~Debug();
+
   static bool CompileDebuggerScript(int index);
-  static void ClearOneShot();
-  static void ActivateStepIn(StackFrame* frame);
-  static void ClearStepIn();
-  static void ActivateStepOut(StackFrame* frame);
-  static void ClearStepOut();
-  static void ClearStepNext();
+  void ClearOneShot();
+  void ActivateStepIn(StackFrame* frame);
+  void ClearStepIn();
+  void ActivateStepOut(StackFrame* frame);
+  void ClearStepOut();
+  void ClearStepNext();
   // Returns whether the compile succeeded.
-  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);
+  void RemoveDebugInfo(Handle<DebugInfo> debug_info);
+  void SetAfterBreakTarget(JavaScriptFrame* frame);
+  Handle<Object> CheckBreakPoints(Handle<Object> break_point);
+  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_;
+  Handle<Context> debug_context_;
 
   // Boolean state indicating whether any break points are set.
-  static bool has_break_points_;
+  bool has_break_points_;
 
   // Cache of all scripts in the heap.
-  static ScriptCache* script_cache_;
+  ScriptCache* script_cache_;
 
   // List of active debug info objects.
-  static DebugInfoListNode* debug_info_list_;
+  DebugInfoListNode* debug_info_list_;
 
-  static bool disable_break_;
-  static bool break_on_exception_;
-  static bool break_on_uncaught_exception_;
+  bool disable_break_;
+  bool break_on_exception_;
+  bool break_on_uncaught_exception_;
 
   // Per-thread data.
   class ThreadLocal {
@@ -526,15 +530,19 @@
   };
 
   // Storage location for registers when handling debug break calls
-  static JSCallerSavedBuffer registers_;
-  static ThreadLocal thread_local_;
-  static void ThreadInit();
+  JSCallerSavedBuffer registers_;
+  ThreadLocal thread_local_;
+  void ThreadInit();
 
   // Code to call for handling debug break on return.
-  static Code* debug_break_return_;
+  Code* debug_break_return_;
 
   // Code to call for handling debug break in debug break slots.
-  static Code* debug_break_slot_;
+  Code* debug_break_slot_;
+
+  Isolate* isolate_;
+
+  friend class Isolate;
 
   DISALLOW_COPY_AND_ASSIGN(Debug);
 };
@@ -680,95 +688,97 @@
 
 class Debugger {
  public:
-  static void DebugRequest(const uint16_t* json_request, int length);
+  ~Debugger();
 
-  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 Handle<Object> MakeScriptCollectedEvent(int id,
-                                                 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);
+  void DebugRequest(const uint16_t* json_request, int length);
+
+  Handle<Object> MakeJSObject(Vector<const char> constructor_name,
+                              int argc, Object*** argv,
+                              bool* caught_exception);
+  Handle<Object> MakeExecutionState(bool* caught_exception);
+  Handle<Object> MakeBreakEvent(Handle<Object> exec_state,
+                                Handle<Object> break_points_hit,
+                                bool* caught_exception);
+  Handle<Object> MakeExceptionEvent(Handle<Object> exec_state,
+                                    Handle<Object> exception,
+                                    bool uncaught,
+                                    bool* caught_exception);
+  Handle<Object> MakeNewFunctionEvent(Handle<Object> func,
+                                      bool* caught_exception);
+  Handle<Object> MakeCompileEvent(Handle<Script> script,
+                                  bool before,
+                                  bool* caught_exception);
+  Handle<Object> MakeScriptCollectedEvent(int id,
+                                          bool* caught_exception);
+  void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
+  void OnException(Handle<Object> exception, bool uncaught);
+  void OnBeforeCompile(Handle<Script> script);
 
   enum AfterCompileFlags {
     NO_AFTER_COMPILE_FLAGS,
     SEND_WHEN_DEBUGGING
   };
-  static void OnAfterCompile(Handle<Script> script,
-                             AfterCompileFlags after_compile_flags);
-  static void OnNewFunction(Handle<JSFunction> fun);
-  static void OnScriptCollected(int id);
-  static void ProcessDebugEvent(v8::DebugEvent event,
-                                Handle<JSObject> event_data,
-                                bool auto_continue);
-  static void NotifyMessageHandler(v8::DebugEvent event,
-                                   Handle<JSObject> exec_state,
-                                   Handle<JSObject> event_data,
-                                   bool auto_continue);
-  static void SetEventListener(Handle<Object> callback, Handle<Object> data);
-  static void SetMessageHandler(v8::Debug::MessageHandler2 handler);
-  static void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
-                                     int period);
-  static void SetDebugMessageDispatchHandler(
+  void OnAfterCompile(Handle<Script> script,
+                      AfterCompileFlags after_compile_flags);
+  void OnNewFunction(Handle<JSFunction> fun);
+  void OnScriptCollected(int id);
+  void ProcessDebugEvent(v8::DebugEvent event,
+                         Handle<JSObject> event_data,
+                         bool auto_continue);
+  void NotifyMessageHandler(v8::DebugEvent event,
+                            Handle<JSObject> exec_state,
+                            Handle<JSObject> event_data,
+                            bool auto_continue);
+  void SetEventListener(Handle<Object> callback, Handle<Object> data);
+  void SetMessageHandler(v8::Debug::MessageHandler2 handler);
+  void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
+                              int period);
+  void SetDebugMessageDispatchHandler(
       v8::Debug::DebugMessageDispatchHandler handler,
       bool provide_locker);
 
   // Invoke the message handler function.
-  static void InvokeMessageHandler(MessageImpl message);
+  void InvokeMessageHandler(MessageImpl message);
 
   // Add a debugger command to the command queue.
-  static void ProcessCommand(Vector<const uint16_t> command,
-                             v8::Debug::ClientData* client_data = NULL);
+  void ProcessCommand(Vector<const uint16_t> command,
+                      v8::Debug::ClientData* client_data = NULL);
 
   // Check whether there are commands in the command queue.
-  static bool HasCommands();
+  bool HasCommands();
 
   // Enqueue a debugger command to the command queue for event listeners.
-  static void EnqueueDebugCommand(v8::Debug::ClientData* client_data = NULL);
+  void EnqueueDebugCommand(v8::Debug::ClientData* client_data = NULL);
 
-  static Handle<Object> Call(Handle<JSFunction> fun,
-                             Handle<Object> data,
-                             bool* pending_exception);
+  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,
-                         bool wait_for_connection = false);
+  bool StartAgent(const char* name, int port,
+                  bool wait_for_connection = false);
 
   // Stop the debugger agent.
-  static void StopAgent();
+  void StopAgent();
 
   // Blocks until the agent has started listening for connections
-  static void WaitForAgent();
+  void WaitForAgent();
 
-  static void CallMessageDispatchHandler();
+  void CallMessageDispatchHandler();
 
-  static Handle<Context> GetDebugContext();
+  Handle<Context> GetDebugContext();
 
   // Unload the debugger if possible. Only called when no debugger is currently
   // active.
-  static void UnloadDebugger();
+  void UnloadDebugger();
   friend void ForceUnloadDebugger();  // In test-debug.cc
 
-  inline static bool EventActive(v8::DebugEvent event) {
+  inline bool EventActive(v8::DebugEvent event) {
     ScopedLock with(debugger_access_);
 
     // Check whether the message handler was been cleared.
     if (debugger_unload_pending_) {
-      if (Debug::debugger_entry() == NULL) {
+      if (isolate_->debug()->debugger_entry() == NULL) {
         UnloadDebugger();
       }
     }
@@ -786,52 +796,58 @@
     return !compiling_natives_ && Debugger::IsDebuggerActive();
   }
 
-  static void set_compiling_natives(bool compiling_natives) {
+  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_; }
+  bool compiling_natives() const { return compiling_natives_; }
+  void set_loading_debugger(bool v) { is_loading_debugger_ = v; }
+  bool is_loading_debugger() const { return is_loading_debugger_; }
 
-  static bool IsDebuggerActive();
+  bool IsDebuggerActive();
 
  private:
-  static void CallEventCallback(v8::DebugEvent event,
-                                Handle<Object> exec_state,
-                                Handle<Object> event_data,
-                                v8::Debug::ClientData* client_data);
-  static void CallCEventCallback(v8::DebugEvent event,
-                                 Handle<Object> exec_state,
-                                 Handle<Object> event_data,
-                                 v8::Debug::ClientData* client_data);
-  static void CallJSEventCallback(v8::DebugEvent event,
-                                  Handle<Object> exec_state,
-                                  Handle<Object> event_data);
-  static void ListenersChanged();
+  Debugger();
 
-  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 v8::Debug::MessageHandler2 message_handler_;
-  static bool debugger_unload_pending_;  // Was message handler cleared?
-  static v8::Debug::HostDispatchHandler host_dispatch_handler_;
-  static Mutex* dispatch_handler_access_;  // Mutex guarding dispatch handler.
-  static v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_;
-  static MessageDispatchHelperThread* message_dispatch_helper_thread_;
-  static int host_dispatch_micros_;
+  void CallEventCallback(v8::DebugEvent event,
+                         Handle<Object> exec_state,
+                         Handle<Object> event_data,
+                         v8::Debug::ClientData* client_data);
+  void CallCEventCallback(v8::DebugEvent event,
+                          Handle<Object> exec_state,
+                          Handle<Object> event_data,
+                          v8::Debug::ClientData* client_data);
+  void CallJSEventCallback(v8::DebugEvent event,
+                           Handle<Object> exec_state,
+                           Handle<Object> event_data);
+  void ListenersChanged();
 
-  static DebuggerAgent* agent_;
+  Mutex* debugger_access_;  // Mutex guarding debugger variables.
+  Handle<Object> event_listener_;  // Global handle to listener.
+  Handle<Object> event_listener_data_;
+  bool compiling_natives_;  // Are we compiling natives?
+  bool is_loading_debugger_;  // Are we loading the debugger?
+  bool never_unload_debugger_;  // Can we unload the debugger?
+  v8::Debug::MessageHandler2 message_handler_;
+  bool debugger_unload_pending_;  // Was message handler cleared?
+  v8::Debug::HostDispatchHandler host_dispatch_handler_;
+  Mutex* dispatch_handler_access_;  // Mutex guarding dispatch handler.
+  v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_;
+  MessageDispatchHelperThread* message_dispatch_helper_thread_;
+  int host_dispatch_micros_;
+
+  DebuggerAgent* agent_;
 
   static const int kQueueInitialSize = 4;
-  static LockingCommandMessageQueue command_queue_;
-  static Semaphore* command_received_;  // Signaled for each command received.
+  LockingCommandMessageQueue command_queue_;
+  Semaphore* command_received_;  // Signaled for each command received.
+  LockingCommandMessageQueue event_command_queue_;
 
-  static LockingCommandMessageQueue event_command_queue_;
+  Isolate* isolate_;
 
   friend class EnterDebugger;
+  friend class Isolate;
+
+  DISALLOW_COPY_AND_ASSIGN(Debugger);
 };
 
 
@@ -842,38 +858,44 @@
 class EnterDebugger BASE_EMBEDDED {
  public:
   EnterDebugger()
-      : prev_(Debug::debugger_entry()),
-        has_js_frames_(!it_.done()) {
-    ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(PREEMPT));
-    ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(DEBUGBREAK));
+      : isolate_(Isolate::Current()),
+        prev_(isolate_->debug()->debugger_entry()),
+        has_js_frames_(!it_.done()),
+        save_(isolate_) {
+    Debug* debug = isolate_->debug();
+    ASSERT(prev_ != NULL || !debug->is_interrupt_pending(PREEMPT));
+    ASSERT(prev_ != NULL || !debug->is_interrupt_pending(DEBUGBREAK));
 
     // Link recursive debugger entry.
-    Debug::set_debugger_entry(this);
+    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();
+    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());
+      debug->NewBreak(it_.frame()->id());
     } else {
-      Debug::NewBreak(StackFrame::NO_ID);
+      debug->NewBreak(StackFrame::NO_ID);
     }
 
     // Make sure that debugger is loaded and enter the debugger context.
-    load_failed_ = !Debug::Load();
+    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());
+      isolate_->set_context(*debug->debug_context());
     }
   }
 
   ~EnterDebugger() {
+    ASSERT(Isolate::Current() == isolate_);
+    Debug* debug = isolate_->debug();
+
     // Restore to the previous break state.
-    Debug::SetBreak(break_frame_id_, break_id_);
+    debug->SetBreak(break_frame_id_, break_id_);
 
     // Check for leaving the debugger.
     if (prev_ == NULL) {
@@ -881,43 +903,43 @@
       // pending exception as clearing the mirror cache calls back into
       // JavaScript. This can happen if the v8::Debug::Call is used in which
       // case the exception should end up in the calling code.
-      if (!Top::has_pending_exception()) {
+      if (!isolate_->has_pending_exception()) {
         // Try to avoid any pending debug break breaking in the clear mirror
         // cache JavaScript code.
-        if (StackGuard::IsDebugBreak()) {
-          Debug::set_interrupts_pending(DEBUGBREAK);
-          StackGuard::Continue(DEBUGBREAK);
+        if (isolate_->stack_guard()->IsDebugBreak()) {
+          debug->set_interrupts_pending(DEBUGBREAK);
+          isolate_->stack_guard()->Continue(DEBUGBREAK);
         }
-        Debug::ClearMirrorCache();
+        debug->ClearMirrorCache();
       }
 
       // Request preemption and debug break when leaving the last debugger entry
       // if any of these where recorded while debugging.
-      if (Debug::is_interrupt_pending(PREEMPT)) {
+      if (debug->is_interrupt_pending(PREEMPT)) {
         // This re-scheduling of preemption is to avoid starvation in some
         // debugging scenarios.
-        Debug::clear_interrupt_pending(PREEMPT);
-        StackGuard::Preempt();
+        debug->clear_interrupt_pending(PREEMPT);
+        isolate_->stack_guard()->Preempt();
       }
-      if (Debug::is_interrupt_pending(DEBUGBREAK)) {
-        Debug::clear_interrupt_pending(DEBUGBREAK);
-        StackGuard::DebugBreak();
+      if (debug->is_interrupt_pending(DEBUGBREAK)) {
+        debug->clear_interrupt_pending(DEBUGBREAK);
+        isolate_->stack_guard()->DebugBreak();
       }
 
       // If there are commands in the queue when leaving the debugger request
       // that these commands are processed.
-      if (Debugger::HasCommands()) {
-        StackGuard::DebugCommand();
+      if (isolate_->debugger()->HasCommands()) {
+        isolate_->stack_guard()->DebugCommand();
       }
 
       // If leaving the debugger with the debugger no longer active unload it.
-      if (!Debugger::IsDebuggerActive()) {
-        Debugger::UnloadDebugger();
+      if (!isolate_->debugger()->IsDebuggerActive()) {
+        isolate_->debugger()->UnloadDebugger();
       }
     }
 
     // Leaving this debugger entry.
-    Debug::set_debugger_entry(prev_);
+    debug->set_debugger_entry(prev_);
   }
 
   // Check whether the debugger could be entered.
@@ -930,6 +952,7 @@
   inline Handle<Context> GetContext() { return save_.context(); }
 
  private:
+  Isolate* isolate_;
   EnterDebugger* prev_;  // Previous debugger entry if entered recursively.
   JavaScriptFrameIterator it_;
   const bool has_js_frames_;  // Were there any JavaScript frames?
@@ -943,15 +966,17 @@
 // Stack allocated class for disabling break.
 class DisableBreak BASE_EMBEDDED {
  public:
-  explicit DisableBreak(bool disable_break)  {
-    prev_disable_break_ = Debug::disable_break();
-    Debug::set_disable_break(disable_break);
+  explicit DisableBreak(bool disable_break) : isolate_(Isolate::Current()) {
+    prev_disable_break_ = isolate_->debug()->disable_break();
+    isolate_->debug()->set_disable_break(disable_break);
   }
   ~DisableBreak() {
-    Debug::set_disable_break(prev_disable_break_);
+    ASSERT(Isolate::Current() == isolate_);
+    isolate_->debug()->set_disable_break(prev_disable_break_);
   }
 
  private:
+  Isolate* isolate_;
   // The previous state of the disable break used to restore the value when this
   // object is destructed.
   bool prev_disable_break_;
@@ -976,17 +1001,18 @@
     return Debug_Address(Debug::k_restarter_frame_function_pointer);
   }
 
-  Address address() const {
+  Address address(Isolate* isolate) const {
+    Debug* debug = isolate->debug();
     switch (id_) {
       case Debug::k_after_break_target_address:
-        return reinterpret_cast<Address>(Debug::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());
+        return reinterpret_cast<Address>(debug->debug_break_return_address());
       case Debug::k_debug_break_slot_address:
-        return reinterpret_cast<Address>(Debug::debug_break_slot_address());
+        return reinterpret_cast<Address>(debug->debug_break_slot_address());
       case Debug::k_restarter_frame_function_pointer:
         return reinterpret_cast<Address>(
-            Debug::restarter_frame_function_pointer_address());
+            debug->restarter_frame_function_pointer_address());
       default:
         UNREACHABLE();
         return NULL;
@@ -1002,7 +1028,7 @@
 // to do this via v8::Debug::HostDispatchHandler
 class MessageDispatchHelperThread: public Thread {
  public:
-  MessageDispatchHelperThread();
+  explicit MessageDispatchHelperThread(Isolate* isolate);
   ~MessageDispatchHelperThread();
 
   void Schedule();
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index af2f42e..4372af0 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -39,30 +39,50 @@
 namespace v8 {
 namespace internal {
 
-LargeObjectChunk* Deoptimizer::eager_deoptimization_entry_code_ = NULL;
-LargeObjectChunk* Deoptimizer::lazy_deoptimization_entry_code_ = NULL;
-Deoptimizer* Deoptimizer::current_ = NULL;
-DeoptimizingCodeListNode* Deoptimizer::deoptimizing_code_list_ = NULL;
+DeoptimizerData::DeoptimizerData() {
+  eager_deoptimization_entry_code_ = NULL;
+  lazy_deoptimization_entry_code_ = NULL;
+  current_ = NULL;
+  deoptimizing_code_list_ = NULL;
+}
 
 
+DeoptimizerData::~DeoptimizerData() {
+  if (eager_deoptimization_entry_code_ != NULL) {
+    eager_deoptimization_entry_code_->Free(EXECUTABLE);
+    eager_deoptimization_entry_code_ = NULL;
+  }
+  if (lazy_deoptimization_entry_code_ != NULL) {
+    lazy_deoptimization_entry_code_->Free(EXECUTABLE);
+    lazy_deoptimization_entry_code_ = NULL;
+  }
+}
+
 Deoptimizer* Deoptimizer::New(JSFunction* function,
                               BailoutType type,
                               unsigned bailout_id,
                               Address from,
-                              int fp_to_sp_delta) {
-  Deoptimizer* deoptimizer =
-      new Deoptimizer(function, type, bailout_id, from, fp_to_sp_delta);
-  ASSERT(current_ == NULL);
-  current_ = deoptimizer;
+                              int fp_to_sp_delta,
+                              Isolate* isolate) {
+  ASSERT(isolate == Isolate::Current());
+  Deoptimizer* deoptimizer = new Deoptimizer(isolate,
+                                             function,
+                                             type,
+                                             bailout_id,
+                                             from,
+                                             fp_to_sp_delta);
+  ASSERT(isolate->deoptimizer_data()->current_ == NULL);
+  isolate->deoptimizer_data()->current_ = deoptimizer;
   return deoptimizer;
 }
 
 
-Deoptimizer* Deoptimizer::Grab() {
-  Deoptimizer* result = current_;
+Deoptimizer* Deoptimizer::Grab(Isolate* isolate) {
+  ASSERT(isolate == Isolate::Current());
+  Deoptimizer* result = isolate->deoptimizer_data()->current_;
   ASSERT(result != NULL);
   result->DeleteFrameDescriptions();
-  current_ = NULL;
+  isolate->deoptimizer_data()->current_ = NULL;
   return result;
 }
 
@@ -155,7 +175,7 @@
   AssertNoAllocation no_allocation;
 
   // Run through the list of all global contexts and deoptimize.
-  Object* global = Heap::global_contexts_list();
+  Object* global = Isolate::Current()->heap()->global_contexts_list();
   while (!global->IsUndefined()) {
     VisitAllOptimizedFunctionsForGlobalObject(Context::cast(global)->global(),
                                               visitor);
@@ -170,7 +190,7 @@
       reinterpret_cast<DeoptimizingCodeListNode*>(data);
   RemoveDeoptimizingCode(*node->code());
 #ifdef DEBUG
-  node = Deoptimizer::deoptimizing_code_list_;
+  node = Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_;
   while (node != NULL) {
     ASSERT(node != reinterpret_cast<DeoptimizingCodeListNode*>(data));
     node = node->next();
@@ -179,17 +199,20 @@
 }
 
 
-void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) {
+void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer,
+                                      Isolate* isolate) {
   deoptimizer->DoComputeOutputFrames();
 }
 
 
-Deoptimizer::Deoptimizer(JSFunction* function,
+Deoptimizer::Deoptimizer(Isolate* isolate,
+                         JSFunction* function,
                          BailoutType type,
                          unsigned bailout_id,
                          Address from,
                          int fp_to_sp_delta)
-    : function_(function),
+    : isolate_(isolate),
+      function_(function),
       bailout_id_(bailout_id),
       bailout_type_(type),
       from_(from),
@@ -228,7 +251,7 @@
     ASSERT(optimized_code_->kind() == Code::OPTIMIZED_FUNCTION);
     ASSERT(!optimized_code_->contains(from));
   }
-  ASSERT(Heap::allow_allocation(false));
+  ASSERT(HEAP->allow_allocation(false));
   unsigned size = ComputeInputFrameSize();
   input_ = new(size) FrameDescription(size, function);
 }
@@ -249,7 +272,7 @@
   delete[] output_;
   input_ = NULL;
   output_ = NULL;
-  ASSERT(!Heap::allow_allocation(true));
+  ASSERT(!HEAP->allow_allocation(true));
 }
 
 
@@ -257,16 +280,17 @@
   ASSERT(id >= 0);
   if (id >= kNumberOfEntries) return NULL;
   LargeObjectChunk* base = NULL;
+  DeoptimizerData* data = Isolate::Current()->deoptimizer_data();
   if (type == EAGER) {
-    if (eager_deoptimization_entry_code_ == NULL) {
-      eager_deoptimization_entry_code_ = CreateCode(type);
+    if (data->eager_deoptimization_entry_code_ == NULL) {
+      data->eager_deoptimization_entry_code_ = CreateCode(type);
     }
-    base = eager_deoptimization_entry_code_;
+    base = data->eager_deoptimization_entry_code_;
   } else {
-    if (lazy_deoptimization_entry_code_ == NULL) {
-      lazy_deoptimization_entry_code_ = CreateCode(type);
+    if (data->lazy_deoptimization_entry_code_ == NULL) {
+      data->lazy_deoptimization_entry_code_ = CreateCode(type);
     }
-    base = lazy_deoptimization_entry_code_;
+    base = data->lazy_deoptimization_entry_code_;
   }
   return
       static_cast<Address>(base->GetStartAddress()) + (id * table_entry_size_);
@@ -275,10 +299,11 @@
 
 int Deoptimizer::GetDeoptimizationId(Address addr, BailoutType type) {
   LargeObjectChunk* base = NULL;
+  DeoptimizerData* data = Isolate::Current()->deoptimizer_data();
   if (type == EAGER) {
-    base = eager_deoptimization_entry_code_;
+    base = data->eager_deoptimization_entry_code_;
   } else {
-    base = lazy_deoptimization_entry_code_;
+    base = data->lazy_deoptimization_entry_code_;
   }
   if (base == NULL ||
       addr < base->GetStartAddress() ||
@@ -292,23 +317,6 @@
 }
 
 
-void Deoptimizer::Setup() {
-  // Do nothing yet.
-}
-
-
-void Deoptimizer::TearDown() {
-  if (eager_deoptimization_entry_code_ != NULL) {
-    eager_deoptimization_entry_code_->Free(EXECUTABLE);
-    eager_deoptimization_entry_code_ = NULL;
-  }
-  if (lazy_deoptimization_entry_code_ != NULL) {
-    lazy_deoptimization_entry_code_->Free(EXECUTABLE);
-    lazy_deoptimization_entry_code_ = NULL;
-  }
-}
-
-
 int Deoptimizer::GetOutputInfo(DeoptimizationOutputData* data,
                                unsigned id,
                                SharedFunctionInfo* shared) {
@@ -335,9 +343,10 @@
 }
 
 
-int Deoptimizer::GetDeoptimizedCodeCount() {
+int Deoptimizer::GetDeoptimizedCodeCount(Isolate* isolate) {
   int length = 0;
-  DeoptimizingCodeListNode* node = Deoptimizer::deoptimizing_code_list_;
+  DeoptimizingCodeListNode* node =
+      isolate->deoptimizer_data()->deoptimizing_code_list_;
   while (node != NULL) {
     length++;
     node = node->next();
@@ -445,7 +454,7 @@
   int tos_index = stack_index + extra_slot_count;
   int index = (frame->ComputeExpressionsCount() - 1) - tos_index;
   if (FLAG_trace_deopt) PrintF("Allocating a new heap number: %e\n", val);
-  Handle<Object> num = Factory::NewNumber(val);
+  Handle<Object> num = isolate_->factory()->NewNumber(val);
   frame->SetExpression(index, *num);
 }
 
@@ -625,10 +634,11 @@
         PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- ",
                output_[frame_index]->GetTop() + output_offset,
                output_offset);
-        Heap::arguments_marker()->ShortPrint();
+        isolate_->heap()->arguments_marker()->ShortPrint();
         PrintF(" ; arguments object\n");
       }
-      intptr_t value = reinterpret_cast<intptr_t>(Heap::arguments_marker());
+      intptr_t value = reinterpret_cast<intptr_t>(
+          isolate_->heap()->arguments_marker());
       output_[frame_index]->SetFrameSlot(output_offset, value);
       return;
     }
@@ -923,10 +933,9 @@
   // references. This is fine because the deoptimizer's code section
   // isn't meant to be serialized at all.
   ASSERT(!Serializer::enabled());
-  bool old_debug_code = FLAG_debug_code;
-  FLAG_debug_code = false;
 
   MacroAssembler masm(NULL, 16 * KB);
+  masm.set_emit_debug_code(false);
   GenerateDeoptimizationEntries(&masm, kNumberOfEntries, type);
   CodeDesc desc;
   masm.GetCode(&desc);
@@ -935,13 +944,13 @@
   LargeObjectChunk* chunk = LargeObjectChunk::New(desc.instr_size, EXECUTABLE);
   memcpy(chunk->GetStartAddress(), desc.buffer, desc.instr_size);
   CPU::FlushICache(chunk->GetStartAddress(), desc.instr_size);
-  FLAG_debug_code = old_debug_code;
   return chunk;
 }
 
 
 Code* Deoptimizer::FindDeoptimizingCodeFromAddress(Address addr) {
-  DeoptimizingCodeListNode* node = Deoptimizer::deoptimizing_code_list_;
+  DeoptimizingCodeListNode* node =
+      Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_;
   while (node != NULL) {
     if (node->code()->contains(addr)) return *node->code();
     node = node->next();
@@ -951,15 +960,16 @@
 
 
 void Deoptimizer::RemoveDeoptimizingCode(Code* code) {
-  ASSERT(deoptimizing_code_list_ != NULL);
+  DeoptimizerData* data = Isolate::Current()->deoptimizer_data();
+  ASSERT(data->deoptimizing_code_list_ != NULL);
   // Run through the code objects to find this one and remove it.
   DeoptimizingCodeListNode* prev = NULL;
-  DeoptimizingCodeListNode* current = deoptimizing_code_list_;
+  DeoptimizingCodeListNode* current = data->deoptimizing_code_list_;
   while (current != NULL) {
     if (*current->code() == code) {
       // Unlink from list. If prev is NULL we are looking at the first element.
       if (prev == NULL) {
-        deoptimizing_code_list_ = current->next();
+        data->deoptimizing_code_list_ = current->next();
       } else {
         prev->set_next(current->next());
       }
@@ -1046,7 +1056,8 @@
 
 Handle<ByteArray> TranslationBuffer::CreateByteArray() {
   int length = contents_.length();
-  Handle<ByteArray> result = Factory::NewByteArray(length, TENURED);
+  Handle<ByteArray> result =
+      Isolate::Current()->factory()->NewByteArray(length, TENURED);
   memcpy(result->GetDataStartAddress(), contents_.ToVector().start(), length);
   return result;
 }
@@ -1169,16 +1180,18 @@
 
 
 DeoptimizingCodeListNode::DeoptimizingCodeListNode(Code* code): next_(NULL) {
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
   // Globalize the code object and make it weak.
-  code_ = Handle<Code>::cast((GlobalHandles::Create(code)));
-  GlobalHandles::MakeWeak(reinterpret_cast<Object**>(code_.location()),
-                          this,
-                          Deoptimizer::HandleWeakDeoptimizedCode);
+  code_ = Handle<Code>::cast(global_handles->Create(code));
+  global_handles->MakeWeak(reinterpret_cast<Object**>(code_.location()),
+                           this,
+                           Deoptimizer::HandleWeakDeoptimizedCode);
 }
 
 
 DeoptimizingCodeListNode::~DeoptimizingCodeListNode() {
-  GlobalHandles::Destroy(reinterpret_cast<Object**>(code_.location()));
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
+  global_handles->Destroy(reinterpret_cast<Object**>(code_.location()));
 }
 
 
diff --git a/src/deoptimizer.h b/src/deoptimizer.h
index 1d4f477..a53de3d 100644
--- a/src/deoptimizer.h
+++ b/src/deoptimizer.h
@@ -93,6 +93,31 @@
 };
 
 
+class Deoptimizer;
+
+
+class DeoptimizerData {
+ public:
+  DeoptimizerData();
+  ~DeoptimizerData();
+
+ private:
+  LargeObjectChunk* eager_deoptimization_entry_code_;
+  LargeObjectChunk* lazy_deoptimization_entry_code_;
+  Deoptimizer* current_;
+
+  // List of deoptimized code which still have references from active stack
+  // frames. These code objects are needed by the deoptimizer when deoptimizing
+  // a frame for which the code object for the function function has been
+  // changed from the code present when deoptimizing was done.
+  DeoptimizingCodeListNode* deoptimizing_code_list_;
+
+  friend class Deoptimizer;
+
+  DISALLOW_COPY_AND_ASSIGN(DeoptimizerData);
+};
+
+
 class Deoptimizer : public Malloced {
  public:
   enum BailoutType {
@@ -107,8 +132,16 @@
                           BailoutType type,
                           unsigned bailout_id,
                           Address from,
-                          int fp_to_sp_delta);
-  static Deoptimizer* Grab();
+                          int fp_to_sp_delta,
+                          Isolate* isolate);
+  static Deoptimizer* Grab(Isolate* isolate);
+
+  // Makes sure that there is enough room in the relocation
+  // information of a code object to perform lazy deoptimization
+  // patching. If there is not enough room a new relocation
+  // information object is allocated and comments are added until it
+  // is big enough.
+  static void EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code);
 
   // Deoptimize the function now. Its current optimized code will never be run
   // again and any activations of the optimized code will get deoptimized when
@@ -159,7 +192,7 @@
 
   void InsertHeapNumberValues(int index, JavaScriptFrame* frame);
 
-  static void ComputeOutputFrames(Deoptimizer* deoptimizer);
+  static void ComputeOutputFrames(Deoptimizer* deoptimizer, Isolate* isolate);
 
   static Address GetDeoptimizationEntry(int id, BailoutType type);
   static int GetDeoptimizationId(Address addr, BailoutType type);
@@ -167,9 +200,6 @@
                            unsigned node_id,
                            SharedFunctionInfo* shared);
 
-  static void Setup();
-  static void TearDown();
-
   // Code generation support.
   static int input_offset() { return OFFSET_OF(Deoptimizer, input_); }
   static int output_count_offset() {
@@ -177,7 +207,7 @@
   }
   static int output_offset() { return OFFSET_OF(Deoptimizer, output_); }
 
-  static int GetDeoptimizedCodeCount();
+  static int GetDeoptimizedCodeCount(Isolate* isolate);
 
   static const int kNotDeoptimizationEntry = -1;
 
@@ -218,7 +248,8 @@
  private:
   static const int kNumberOfEntries = 4096;
 
-  Deoptimizer(JSFunction* function,
+  Deoptimizer(Isolate* isolate,
+              JSFunction* function,
               BailoutType type,
               unsigned bailout_id,
               Address from,
@@ -264,16 +295,7 @@
   static Code* FindDeoptimizingCodeFromAddress(Address addr);
   static void RemoveDeoptimizingCode(Code* code);
 
-  static LargeObjectChunk* eager_deoptimization_entry_code_;
-  static LargeObjectChunk* lazy_deoptimization_entry_code_;
-  static Deoptimizer* current_;
-
-  // List of deoptimized code which still have references from active stack
-  // frames. These code objects are needed by the deoptimizer when deoptimizing
-  // a frame for which the code object for the function function has been
-  // changed from the code present when deoptimizing was done.
-  static DeoptimizingCodeListNode* deoptimizing_code_list_;
-
+  Isolate* isolate_;
   JSFunction* function_;
   Code* optimized_code_;
   unsigned bailout_id_;
@@ -304,7 +326,9 @@
                    JSFunction* function);
 
   void* operator new(size_t size, uint32_t frame_size) {
-    return malloc(size + frame_size);
+    // Subtracts kPointerSize, as the member frame_content_ already supplies
+    // the first element of the area to store the frame.
+    return malloc(size + frame_size - kPointerSize);
   }
 
   void operator delete(void* description) {
@@ -388,7 +412,7 @@
   }
 
   static int frame_content_offset() {
-    return sizeof(FrameDescription);
+    return OFFSET_OF(FrameDescription, frame_content_);
   }
 
  private:
@@ -407,6 +431,10 @@
   // deoptimizing.
   intptr_t continuation_;
 
+  // This must be at the end of the object as the object is allocated larger
+  // than it's definition indicate to extend this array.
+  intptr_t frame_content_[1];
+
   intptr_t* GetFrameSlotPointer(unsigned offset) {
     ASSERT(offset < frame_size_);
     return reinterpret_cast<intptr_t*>(
diff --git a/src/disasm.h b/src/disasm.h
index 6ecd1c8..f7f2d41 100644
--- a/src/disasm.h
+++ b/src/disasm.h
@@ -44,6 +44,9 @@
   virtual const char* NameOfAddress(byte* addr) const;
   virtual const char* NameOfConstant(byte* addr) const;
   virtual const char* NameInCode(byte* addr) const;
+
+ protected:
+  v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
 };
 
 
diff --git a/src/disassembler.cc b/src/disassembler.cc
index 243abf0..d142ef6 100644
--- a/src/disassembler.cc
+++ b/src/disassembler.cc
@@ -65,24 +65,24 @@
   Code* code() const { return code_; }
  private:
   Code* code_;
+
+  EmbeddedVector<char, 128> v8_buffer_;
 };
 
 
 const char* V8NameConverter::NameOfAddress(byte* pc) const {
-  static v8::internal::EmbeddedVector<char, 128> buffer;
-
-  const char* name = Builtins::Lookup(pc);
+  const char* name = Isolate::Current()->builtins()->Lookup(pc);
   if (name != NULL) {
-    OS::SNPrintF(buffer, "%s  (%p)", name, pc);
-    return buffer.start();
+    OS::SNPrintF(v8_buffer_, "%s  (%p)", name, pc);
+    return v8_buffer_.start();
   }
 
   if (code_ != NULL) {
     int offs = static_cast<int>(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();
+      OS::SNPrintF(v8_buffer_, "%d  (%p)", offs, pc);
+      return v8_buffer_.start();
     }
   }
 
@@ -115,6 +115,7 @@
   NoHandleAllocation ha;
   AssertNoAllocation no_alloc;
   ExternalReferenceEncoder ref_encoder;
+  Heap* heap = HEAP;
 
   v8::internal::EmbeddedVector<char, 128> decode_buffer;
   v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer;
@@ -256,8 +257,8 @@
         } 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()) {
+          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();
diff --git a/src/execution.cc b/src/execution.cc
index de8f0a4..98c8b68 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -42,14 +42,39 @@
 namespace internal {
 
 
+StackGuard::StackGuard()
+    : isolate_(NULL) {
+}
+
+
+void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) {
+  ASSERT(isolate_ != NULL);
+  // Ignore attempts to interrupt when interrupts are postponed.
+  if (should_postpone_interrupts(lock)) return;
+  thread_local_.jslimit_ = kInterruptLimit;
+  thread_local_.climit_ = kInterruptLimit;
+  isolate_->heap()->SetStackLimits();
+}
+
+
+void StackGuard::reset_limits(const ExecutionAccess& lock) {
+  ASSERT(isolate_ != NULL);
+  thread_local_.jslimit_ = thread_local_.real_jslimit_;
+  thread_local_.climit_ = thread_local_.real_climit_;
+  isolate_->heap()->SetStackLimits();
+}
+
+
 static Handle<Object> Invoke(bool construct,
                              Handle<JSFunction> func,
                              Handle<Object> receiver,
                              int argc,
                              Object*** args,
                              bool* has_pending_exception) {
+  Isolate* isolate = func->GetIsolate();
+
   // Entering JavaScript.
-  VMState state(JS);
+  VMState state(isolate, JS);
 
   // Placeholder for return value.
   MaybeObject* value = reinterpret_cast<Object*>(kZapValue);
@@ -85,7 +110,7 @@
   {
     // Save and restore context around invocation and block the
     // allocation of handles without explicit handle scopes.
-    SaveContext save;
+    SaveContext save(isolate);
     NoHandleAllocation na;
     JSEntryFunction entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
 
@@ -103,20 +128,20 @@
 
   // Update the pending exception flag and return the value.
   *has_pending_exception = value->IsException();
-  ASSERT(*has_pending_exception == Top::has_pending_exception());
+  ASSERT(*has_pending_exception == Isolate::Current()->has_pending_exception());
   if (*has_pending_exception) {
-    Top::ReportPendingMessages();
-    if (Top::pending_exception() == Failure::OutOfMemoryException()) {
-      if (!HandleScopeImplementer::instance()->ignore_out_of_memory()) {
+    isolate->ReportPendingMessages();
+    if (isolate->pending_exception() == Failure::OutOfMemoryException()) {
+      if (!isolate->handle_scope_implementer()->ignore_out_of_memory()) {
         V8::FatalProcessOutOfMemory("JS", true);
       }
     }
     return Handle<Object>();
   } else {
-    Top::clear_pending_message();
+    isolate->clear_pending_message();
   }
 
-  return Handle<Object>(value->ToObjectUnchecked());
+  return Handle<Object>(value->ToObjectUnchecked(), isolate);
 }
 
 
@@ -131,7 +156,8 @@
 
 Handle<Object> Execution::New(Handle<JSFunction> func, int argc,
                               Object*** args, bool* pending_exception) {
-  return Invoke(true, func, Top::global(), argc, args, pending_exception);
+  return Invoke(true, func, Isolate::Current()->global(), argc, args,
+                pending_exception);
 }
 
 
@@ -153,18 +179,20 @@
 
   if (*caught_exception) {
     ASSERT(catcher.HasCaught());
-    ASSERT(Top::has_pending_exception());
-    ASSERT(Top::external_caught_exception());
-    if (Top::pending_exception() == Heap::termination_exception()) {
-      result = Factory::termination_exception();
+    Isolate* isolate = Isolate::Current();
+    ASSERT(isolate->has_pending_exception());
+    ASSERT(isolate->external_caught_exception());
+    if (isolate->pending_exception() ==
+        isolate->heap()->termination_exception()) {
+      result = isolate->factory()->termination_exception();
     } else {
       result = v8::Utils::OpenHandle(*catcher.Exception());
     }
-    Top::OptionalRescheduleException(true);
+    isolate->OptionalRescheduleException(true);
   }
 
-  ASSERT(!Top::has_pending_exception());
-  ASSERT(!Top::external_caught_exception());
+  ASSERT(!Isolate::Current()->has_pending_exception());
+  ASSERT(!Isolate::Current()->external_caught_exception());
   return result;
 }
 
@@ -178,7 +206,7 @@
   // Regular expressions can be called as functions in both Firefox
   // and Safari so we allow it too.
   if (object->IsJSRegExp()) {
-    Handle<String> exec = Factory::exec_symbol();
+    Handle<String> exec = FACTORY->exec_symbol();
     // TODO(lrn): Bug 617.  We should use the default function here, not the
     // one on the RegExp object.
     Object* exec_function;
@@ -186,7 +214,7 @@
       // This can lose an exception, but the alternative is to put a failure
       // object in a handle, which is not GC safe.
       if (!maybe_exec_function->ToObject(&exec_function)) {
-        return Factory::undefined_value();
+        return FACTORY->undefined_value();
       }
     }
     return Handle<Object>(exec_function);
@@ -197,10 +225,10 @@
   if (object->IsHeapObject() &&
       HeapObject::cast(*object)->map()->has_instance_call_handler()) {
     return Handle<JSFunction>(
-        Top::global_context()->call_as_function_delegate());
+        Isolate::Current()->global_context()->call_as_function_delegate());
   }
 
-  return Factory::undefined_value();
+  return FACTORY->undefined_value();
 }
 
 
@@ -215,26 +243,22 @@
   if (object->IsHeapObject() &&
       HeapObject::cast(*object)->map()->has_instance_call_handler()) {
     return Handle<JSFunction>(
-        Top::global_context()->call_as_constructor_delegate());
+        Isolate::Current()->global_context()->call_as_constructor_delegate());
   }
 
-  return Factory::undefined_value();
+  return FACTORY->undefined_value();
 }
 
 
-// Static state for stack guards.
-StackGuard::ThreadLocal StackGuard::thread_local_;
-
-
 bool StackGuard::IsStackOverflow() {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   return (thread_local_.jslimit_ != kInterruptLimit &&
           thread_local_.climit_ != kInterruptLimit);
 }
 
 
 void StackGuard::EnableInterrupts() {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   if (has_pending_interrupts(access)) {
     set_interrupt_limits(access);
   }
@@ -242,7 +266,7 @@
 
 
 void StackGuard::SetStackLimit(uintptr_t limit) {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   // If the current limits are special (eg due to a pending interrupt) then
   // leave them alone.
   uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(limit);
@@ -258,92 +282,92 @@
 
 
 void StackGuard::DisableInterrupts() {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   reset_limits(access);
 }
 
 
 bool StackGuard::IsInterrupted() {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   return thread_local_.interrupt_flags_ & INTERRUPT;
 }
 
 
 void StackGuard::Interrupt() {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   thread_local_.interrupt_flags_ |= INTERRUPT;
   set_interrupt_limits(access);
 }
 
 
 bool StackGuard::IsPreempted() {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   return thread_local_.interrupt_flags_ & PREEMPT;
 }
 
 
 void StackGuard::Preempt() {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   thread_local_.interrupt_flags_ |= PREEMPT;
   set_interrupt_limits(access);
 }
 
 
 bool StackGuard::IsTerminateExecution() {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   return thread_local_.interrupt_flags_ & TERMINATE;
 }
 
 
 void StackGuard::TerminateExecution() {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   thread_local_.interrupt_flags_ |= TERMINATE;
   set_interrupt_limits(access);
 }
 
 
 bool StackGuard::IsRuntimeProfilerTick() {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   return thread_local_.interrupt_flags_ & RUNTIME_PROFILER_TICK;
 }
 
 
 void StackGuard::RequestRuntimeProfilerTick() {
   // Ignore calls if we're not optimizing or if we can't get the lock.
-  if (FLAG_opt && ExecutionAccess::TryLock()) {
+  if (FLAG_opt && ExecutionAccess::TryLock(isolate_)) {
     thread_local_.interrupt_flags_ |= RUNTIME_PROFILER_TICK;
     if (thread_local_.postpone_interrupts_nesting_ == 0) {
       thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
-      Heap::SetStackLimits();
+      isolate_->heap()->SetStackLimits();
     }
-    ExecutionAccess::Unlock();
+    ExecutionAccess::Unlock(isolate_);
   }
 }
 
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
 bool StackGuard::IsDebugBreak() {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   return thread_local_.interrupt_flags_ & DEBUGBREAK;
 }
 
 
 void StackGuard::DebugBreak() {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   thread_local_.interrupt_flags_ |= DEBUGBREAK;
   set_interrupt_limits(access);
 }
 
 
 bool StackGuard::IsDebugCommand() {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
 }
 
 
 void StackGuard::DebugCommand() {
   if (FLAG_debugger_auto_break) {
-    ExecutionAccess access;
+    ExecutionAccess access(isolate_);
     thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
     set_interrupt_limits(access);
   }
@@ -351,7 +375,7 @@
 #endif
 
 void StackGuard::Continue(InterruptFlag after_what) {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
   if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) {
     reset_limits(access);
@@ -359,36 +383,34 @@
 }
 
 
-int StackGuard::ArchiveSpacePerThread() {
-  return sizeof(ThreadLocal);
-}
-
-
 char* StackGuard::ArchiveStackGuard(char* to) {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
   ThreadLocal blank;
+
+  // Set the stack limits using the old thread_local_.
+  // TODO(isolates): This was the old semantics of constructing a ThreadLocal
+  //                 (as the ctor called SetStackLimits, which looked at the
+  //                 current thread_local_ from StackGuard)-- but is this
+  //                 really what was intended?
+  isolate_->heap()->SetStackLimits();
   thread_local_ = blank;
+
   return to + sizeof(ThreadLocal);
 }
 
 
 char* StackGuard::RestoreStackGuard(char* from) {
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
   memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
-  Heap::SetStackLimits();
+  isolate_->heap()->SetStackLimits();
   return from + sizeof(ThreadLocal);
 }
 
 
-static internal::Thread::LocalStorageKey stack_limit_key =
-    internal::Thread::CreateThreadLocalKey();
-
-
 void StackGuard::FreeThreadResources() {
-  Thread::SetThreadLocal(
-      stack_limit_key,
-      reinterpret_cast<void*>(thread_local_.real_climit_));
+  Isolate::CurrentPerIsolateThreadData()->set_stack_limit(
+      thread_local_.real_climit_);
 }
 
 
@@ -400,11 +422,11 @@
   nesting_ = 0;
   postpone_interrupts_nesting_ = 0;
   interrupt_flags_ = 0;
-  Heap::SetStackLimits();
 }
 
 
-void StackGuard::ThreadLocal::Initialize() {
+bool StackGuard::ThreadLocal::Initialize() {
+  bool should_set_stack_limits = false;
   if (real_climit_ == kIllegalLimit) {
     // Takes the address of the limit variable in order to find out where
     // the top of stack is right now.
@@ -415,37 +437,41 @@
     jslimit_ = SimulatorStack::JsLimitFromCLimit(limit);
     real_climit_ = limit;
     climit_ = limit;
-    Heap::SetStackLimits();
+    should_set_stack_limits = true;
   }
   nesting_ = 0;
   postpone_interrupts_nesting_ = 0;
   interrupt_flags_ = 0;
+  return should_set_stack_limits;
 }
 
 
 void StackGuard::ClearThread(const ExecutionAccess& lock) {
   thread_local_.Clear();
+  isolate_->heap()->SetStackLimits();
 }
 
 
 void StackGuard::InitThread(const ExecutionAccess& lock) {
-  thread_local_.Initialize();
-  void* stored_limit = Thread::GetThreadLocal(stack_limit_key);
+  if (thread_local_.Initialize()) isolate_->heap()->SetStackLimits();
+  uintptr_t stored_limit =
+      Isolate::CurrentPerIsolateThreadData()->stack_limit();
   // You should hold the ExecutionAccess lock when you call this.
-  if (stored_limit != NULL) {
-    StackGuard::SetStackLimit(reinterpret_cast<intptr_t>(stored_limit));
+  if (stored_limit != 0) {
+    StackGuard::SetStackLimit(stored_limit);
   }
 }
 
 
 // --- 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);                             \
+#define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception)            \
+  do {                                                                         \
+    Object** args[argc] = argv;                                                \
+    ASSERT(has_pending_exception != NULL);                                     \
+    return Call(Isolate::Current()->name##_fun(),                              \
+                Isolate::Current()->js_builtins_object(), argc, args,          \
+                has_pending_exception);                                        \
   } while (false)
 
 
@@ -461,7 +487,7 @@
     double value = obj->Number();
     result = !((value == 0) || isnan(value));
   }
-  return Handle<Object>(Heap::ToBoolean(result));
+  return Handle<Object>(HEAP->ToBoolean(result));
 }
 
 
@@ -502,7 +528,7 @@
 
 
 Handle<Object> Execution::NewDate(double time, bool* exc) {
-  Handle<Object> time_obj = Factory::NewNumber(time);
+  Handle<Object> time_obj = FACTORY->NewNumber(time);
   RETURN_NATIVE_CALL(create_date, 1, { time_obj.location() }, exc);
 }
 
@@ -513,11 +539,10 @@
 Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
                                         Handle<String> flags,
                                         bool* exc) {
+  Handle<JSFunction> function = Handle<JSFunction>(
+      pattern->GetIsolate()->global_context()->regexp_function());
   Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral(
-      Handle<JSFunction>(Top::global_context()->regexp_function()),
-      pattern,
-      flags,
-      exc);
+      function, pattern, flags, exc);
   if (*exc) return Handle<JSRegExp>();
   return Handle<JSRegExp>::cast(re_obj);
 }
@@ -526,17 +551,18 @@
 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();
+    return FACTORY->undefined_value();
   }
 
   Handle<Object> char_at =
-      GetProperty(Top::builtins(), Factory::char_at_symbol());
+      GetProperty(Isolate::Current()->js_builtins_object(),
+                  FACTORY->char_at_symbol());
   if (!char_at->IsJSFunction()) {
-    return Factory::undefined_value();
+    return FACTORY->undefined_value();
   }
 
   bool caught_exception;
-  Handle<Object> index_object = Factory::NewNumberFromInt(int_index);
+  Handle<Object> index_object = FACTORY->NewNumberFromInt(int_index);
   Object** index_arg[] = { index_object.location() };
   Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
                                   string,
@@ -544,7 +570,7 @@
                                   index_arg,
                                   &caught_exception);
   if (caught_exception) {
-    return Factory::undefined_value();
+    return FACTORY->undefined_value();
   }
   return result;
 }
@@ -554,13 +580,15 @@
     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()->
-      GetElementNoExceptionThrown(serial_number);
+  Object* elm =
+      Isolate::Current()->global_context()->function_cache()->
+          GetElementNoExceptionThrown(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);
+      Call(Isolate::Current()->instantiate_fun(),
+           Isolate::Current()->js_builtins_object(), 1, args, exc);
   if (*exc) return Handle<JSFunction>::null();
   return Handle<JSFunction>::cast(result);
 }
@@ -588,7 +616,8 @@
   } else {
     Object** args[1] = { Handle<Object>::cast(data).location() };
     Handle<Object> result =
-        Call(Top::instantiate_fun(), Top::builtins(), 1, args, exc);
+        Call(Isolate::Current()->instantiate_fun(),
+             Isolate::Current()->js_builtins_object(), 1, args, exc);
     if (*exc) return Handle<JSObject>::null();
     return Handle<JSObject>::cast(result);
   }
@@ -599,7 +628,8 @@
                                   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);
+  Execution::Call(Isolate::Current()->configure_instance_fun(),
+                  Isolate::Current()->js_builtins_object(), 2, args, exc);
 }
 
 
@@ -613,50 +643,57 @@
                           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();
+  Handle<Object> result =
+      TryCall(Isolate::Current()->get_stack_trace_line_fun(),
+              Isolate::Current()->js_builtins_object(), argc, args,
+              &caught_exception);
+  if (caught_exception || !result->IsString()) return FACTORY->empty_symbol();
   return Handle<String>::cast(result);
 }
 
 
 static Object* RuntimePreempt() {
+  Isolate* isolate = Isolate::Current();
+
   // Clear the preempt request flag.
-  StackGuard::Continue(PREEMPT);
+  isolate->stack_guard()->Continue(PREEMPT);
 
   ContextSwitcher::PreemptionReceived();
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  if (Debug::InDebugger()) {
+  if (isolate->debug()->InDebugger()) {
     // If currently in the debugger don't do any actual preemption but record
     // that preemption occoured while in the debugger.
-    Debug::PreemptionWhileInDebugger();
+    isolate->debug()->PreemptionWhileInDebugger();
   } else {
     // Perform preemption.
     v8::Unlocker unlocker;
     Thread::YieldCPU();
   }
 #else
-  // Perform preemption.
-  v8::Unlocker unlocker;
-  Thread::YieldCPU();
+  { // NOLINT
+    // Perform preemption.
+    v8::Unlocker unlocker;
+    Thread::YieldCPU();
+  }
 #endif
 
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
 Object* Execution::DebugBreakHelper() {
+  Isolate* isolate = Isolate::Current();
+
   // Just continue if breaks are disabled.
-  if (Debug::disable_break()) {
-    return Heap::undefined_value();
+  if (isolate->debug()->disable_break()) {
+    return isolate->heap()->undefined_value();
   }
 
   // Ignore debug break during bootstrapping.
-  if (Bootstrapper::IsActive()) {
-    return Heap::undefined_value();
+  if (isolate->bootstrapper()->IsActive()) {
+    return isolate->heap()->undefined_value();
   }
 
   {
@@ -666,32 +703,33 @@
     if (fun && fun->IsJSFunction()) {
       // Don't stop in builtin functions.
       if (JSFunction::cast(fun)->IsBuiltin()) {
-        return Heap::undefined_value();
+        return isolate->heap()->undefined_value();
       }
       GlobalObject* global = JSFunction::cast(fun)->context()->global();
       // Don't stop in debugger functions.
-      if (Debug::IsDebugGlobal(global)) {
-        return Heap::undefined_value();
+      if (isolate->debug()->IsDebugGlobal(global)) {
+        return isolate->heap()->undefined_value();
       }
     }
   }
 
   // Collect the break state before clearing the flags.
   bool debug_command_only =
-      StackGuard::IsDebugCommand() && !StackGuard::IsDebugBreak();
+      isolate->stack_guard()->IsDebugCommand() &&
+      !isolate->stack_guard()->IsDebugBreak();
 
   // Clear the debug break request flag.
-  StackGuard::Continue(DEBUGBREAK);
+  isolate->stack_guard()->Continue(DEBUGBREAK);
 
   ProcessDebugMesssages(debug_command_only);
 
   // Return to continue execution.
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 void Execution::ProcessDebugMesssages(bool debug_command_only) {
   // Clear the debug command request flag.
-  StackGuard::Continue(DEBUGCOMMAND);
+  Isolate::Current()->stack_guard()->Continue(DEBUGCOMMAND);
 
   HandleScope scope;
   // Enter the debugger. Just continue if we fail to enter the debugger.
@@ -702,34 +740,37 @@
 
   // Notify the debug event listeners. Indicate auto continue if the break was
   // a debug command break.
-  Debugger::OnDebugBreak(Factory::undefined_value(), debug_command_only);
+  Isolate::Current()->debugger()->OnDebugBreak(FACTORY->undefined_value(),
+                                               debug_command_only);
 }
 
 
 #endif
 
 MaybeObject* Execution::HandleStackGuardInterrupt() {
-  Counters::stack_interrupts.Increment();
-  if (StackGuard::IsRuntimeProfilerTick()) {
-    Counters::runtime_profiler_ticks.Increment();
-    StackGuard::Continue(RUNTIME_PROFILER_TICK);
-    RuntimeProfiler::OptimizeNow();
+  Isolate* isolate = Isolate::Current();
+  StackGuard* stack_guard = isolate->stack_guard();
+  isolate->counters()->stack_interrupts()->Increment();
+  if (stack_guard->IsRuntimeProfilerTick()) {
+    isolate->counters()->runtime_profiler_ticks()->Increment();
+    stack_guard->Continue(RUNTIME_PROFILER_TICK);
+    isolate->runtime_profiler()->OptimizeNow();
   }
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  if (StackGuard::IsDebugBreak() || StackGuard::IsDebugCommand()) {
+  if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) {
     DebugBreakHelper();
   }
 #endif
-  if (StackGuard::IsPreempted()) RuntimePreempt();
-  if (StackGuard::IsTerminateExecution()) {
-    StackGuard::Continue(TERMINATE);
-    return Top::TerminateExecution();
+  if (stack_guard->IsPreempted()) RuntimePreempt();
+  if (stack_guard->IsTerminateExecution()) {
+    stack_guard->Continue(TERMINATE);
+    return isolate->TerminateExecution();
   }
-  if (StackGuard::IsInterrupted()) {
-    StackGuard::Continue(INTERRUPT);
-    return Top::StackOverflow();
+  if (stack_guard->IsInterrupted()) {
+    stack_guard->Continue(INTERRUPT);
+    return isolate->StackOverflow();
   }
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 } }  // namespace v8::internal
diff --git a/src/execution.h b/src/execution.h
index cb07807..d4b80d2 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -146,71 +146,74 @@
 
 
 class ExecutionAccess;
+class Isolate;
 
 
 // StackGuard contains the handling of the limits that are used to limit the
 // number of nested invocations of JavaScript and the stack size used in each
 // invocation.
-class StackGuard : public AllStatic {
+class StackGuard {
  public:
   // Pass the address beyond which the stack should not grow.  The stack
   // is assumed to grow downwards.
-  static void SetStackLimit(uintptr_t limit);
+  void SetStackLimit(uintptr_t limit);
 
   // Threading support.
-  static char* ArchiveStackGuard(char* to);
-  static char* RestoreStackGuard(char* from);
-  static int ArchiveSpacePerThread();
-  static void FreeThreadResources();
+  char* ArchiveStackGuard(char* to);
+  char* RestoreStackGuard(char* from);
+  static int ArchiveSpacePerThread() { return sizeof(ThreadLocal); }
+  void FreeThreadResources();
   // Sets up the default stack guard for this thread if it has not
   // already been set up.
-  static void InitThread(const ExecutionAccess& lock);
+  void InitThread(const ExecutionAccess& lock);
   // Clears the stack guard for this thread so it does not look as if
   // it has been set up.
-  static void ClearThread(const ExecutionAccess& lock);
+  void ClearThread(const ExecutionAccess& lock);
 
-  static bool IsStackOverflow();
-  static bool IsPreempted();
-  static void Preempt();
-  static bool IsInterrupted();
-  static void Interrupt();
-  static bool IsTerminateExecution();
-  static void TerminateExecution();
-  static bool IsRuntimeProfilerTick();
-  static void RequestRuntimeProfilerTick();
+  bool IsStackOverflow();
+  bool IsPreempted();
+  void Preempt();
+  bool IsInterrupted();
+  void Interrupt();
+  bool IsTerminateExecution();
+  void TerminateExecution();
+  bool IsRuntimeProfilerTick();
+  void RequestRuntimeProfilerTick();
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  static bool IsDebugBreak();
-  static void DebugBreak();
-  static bool IsDebugCommand();
-  static void DebugCommand();
+  bool IsDebugBreak();
+  void DebugBreak();
+  bool IsDebugCommand();
+  void DebugCommand();
 #endif
-  static void Continue(InterruptFlag after_what);
+  void Continue(InterruptFlag after_what);
 
   // This provides an asynchronous read of the stack limits 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() {
+  uintptr_t climit() {
     return thread_local_.climit_;
   }
-  static uintptr_t real_climit() {
+  uintptr_t real_climit() {
     return thread_local_.real_climit_;
   }
-  static uintptr_t jslimit() {
+  uintptr_t jslimit() {
     return thread_local_.jslimit_;
   }
-  static uintptr_t real_jslimit() {
+  uintptr_t real_jslimit() {
     return thread_local_.real_jslimit_;
   }
-  static Address address_of_jslimit() {
+  Address address_of_jslimit() {
     return reinterpret_cast<Address>(&thread_local_.jslimit_);
   }
-  static Address address_of_real_jslimit() {
+  Address address_of_real_jslimit() {
     return reinterpret_cast<Address>(&thread_local_.real_jslimit_);
   }
 
  private:
+  StackGuard();
+
   // You should hold the ExecutionAccess lock when calling this method.
-  static bool has_pending_interrupts(const ExecutionAccess& lock) {
+  bool has_pending_interrupts(const ExecutionAccess& lock) {
     // Sanity check: We shouldn't be asking about pending interrupts
     // unless we're not postponing them anymore.
     ASSERT(!should_postpone_interrupts(lock));
@@ -218,30 +221,20 @@
   }
 
   // You should hold the ExecutionAccess lock when calling this method.
-  static bool should_postpone_interrupts(const ExecutionAccess& lock) {
+  bool should_postpone_interrupts(const ExecutionAccess& lock) {
     return thread_local_.postpone_interrupts_nesting_ > 0;
   }
 
   // You should hold the ExecutionAccess lock when calling this method.
-  static void set_interrupt_limits(const ExecutionAccess& lock) {
-    // Ignore attempts to interrupt when interrupts are postponed.
-    if (should_postpone_interrupts(lock)) return;
-    thread_local_.jslimit_ = kInterruptLimit;
-    thread_local_.climit_ = kInterruptLimit;
-    Heap::SetStackLimits();
-  }
+  inline void set_interrupt_limits(const ExecutionAccess& lock);
 
   // Reset limits to actual values. For example after handling interrupt.
   // You should hold the ExecutionAccess lock when calling this method.
-  static void reset_limits(const ExecutionAccess& lock) {
-    thread_local_.jslimit_ = thread_local_.real_jslimit_;
-    thread_local_.climit_ = thread_local_.real_climit_;
-    Heap::SetStackLimits();
-  }
+  inline void reset_limits(const ExecutionAccess& lock);
 
   // Enable or disable interrupts.
-  static void EnableInterrupts();
-  static void DisableInterrupts();
+  void EnableInterrupts();
+  void DisableInterrupts();
 
 #ifdef V8_TARGET_ARCH_X64
   static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe);
@@ -256,9 +249,11 @@
     ThreadLocal() { Clear(); }
     // You should hold the ExecutionAccess lock when you call Initialize or
     // Clear.
-    void Initialize();
     void Clear();
 
+    // Returns true if the heap's stack limits should be set, false if not.
+    bool Initialize();
+
     // The stack limit is split into a JavaScript and a C++ stack limit. These
     // two are the same except when running on a simulator where the C++ and
     // JavaScript stacks are separate. Each of the two stack limits have two
@@ -278,45 +273,19 @@
     int interrupt_flags_;
   };
 
-  static ThreadLocal thread_local_;
+  // TODO(isolates): Technically this could be calculated directly from a
+  //                 pointer to StackGuard.
+  Isolate* isolate_;
+  ThreadLocal thread_local_;
 
+  friend class Isolate;
   friend class StackLimitCheck;
   friend class PostponeInterruptsScope;
+
+  DISALLOW_COPY_AND_ASSIGN(StackGuard);
 };
 
 
-// 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();
-    }
-  }
-};
-
 } }  // namespace v8::internal
 
 #endif  // V8_EXECUTION_H_
diff --git a/src/extensions/externalize-string-extension.cc b/src/extensions/externalize-string-extension.cc
index 8b4bdbd..b3f83fe 100644
--- a/src/extensions/externalize-string-extension.cc
+++ b/src/extensions/externalize-string-extension.cc
@@ -100,7 +100,7 @@
         data, string->length());
     result = string->MakeExternal(resource);
     if (result && !string->IsSymbol()) {
-      i::ExternalStringTable::AddString(*string);
+      HEAP->external_string_table()->AddString(*string);
     }
     if (!result) delete resource;
   } else {
@@ -110,7 +110,7 @@
         data, string->length());
     result = string->MakeExternal(resource);
     if (result && !string->IsSymbol()) {
-      i::ExternalStringTable::AddString(*string);
+      HEAP->external_string_table()->AddString(*string);
     }
     if (!result) delete resource;
   }
diff --git a/src/extensions/gc-extension.cc b/src/extensions/gc-extension.cc
index 63daa05..3740c27 100644
--- a/src/extensions/gc-extension.cc
+++ b/src/extensions/gc-extension.cc
@@ -45,7 +45,7 @@
   if (args.Length() >= 1 && args[0]->IsBoolean()) {
     compact = args[0]->BooleanValue();
   }
-  Heap::CollectAllGarbage(compact);
+  HEAP->CollectAllGarbage(compact);
   return v8::Undefined();
 }
 
diff --git a/src/factory.cc b/src/factory.cc
index 96c757a..7dee66f 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -41,35 +41,43 @@
 
 Handle<FixedArray> Factory::NewFixedArray(int size, PretenureFlag pretenure) {
   ASSERT(0 <= size);
-  CALL_HEAP_FUNCTION(Heap::AllocateFixedArray(size, pretenure), FixedArray);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateFixedArray(size, pretenure),
+      FixedArray);
 }
 
 
 Handle<FixedArray> Factory::NewFixedArrayWithHoles(int size,
                                                    PretenureFlag pretenure) {
   ASSERT(0 <= size);
-  CALL_HEAP_FUNCTION(Heap::AllocateFixedArrayWithHoles(size, pretenure),
-                     FixedArray);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateFixedArrayWithHoles(size, pretenure),
+      FixedArray);
 }
 
 
 Handle<StringDictionary> Factory::NewStringDictionary(int at_least_space_for) {
   ASSERT(0 <= at_least_space_for);
-  CALL_HEAP_FUNCTION(StringDictionary::Allocate(at_least_space_for),
+  CALL_HEAP_FUNCTION(isolate(),
+                     StringDictionary::Allocate(at_least_space_for),
                      StringDictionary);
 }
 
 
 Handle<NumberDictionary> Factory::NewNumberDictionary(int at_least_space_for) {
   ASSERT(0 <= at_least_space_for);
-  CALL_HEAP_FUNCTION(NumberDictionary::Allocate(at_least_space_for),
+  CALL_HEAP_FUNCTION(isolate(),
+                     NumberDictionary::Allocate(at_least_space_for),
                      NumberDictionary);
 }
 
 
 Handle<DescriptorArray> Factory::NewDescriptorArray(int number_of_descriptors) {
   ASSERT(0 <= number_of_descriptors);
-  CALL_HEAP_FUNCTION(DescriptorArray::Allocate(number_of_descriptors),
+  CALL_HEAP_FUNCTION(isolate(),
+                     DescriptorArray::Allocate(number_of_descriptors),
                      DescriptorArray);
 }
 
@@ -78,7 +86,8 @@
     int deopt_entry_count,
     PretenureFlag pretenure) {
   ASSERT(deopt_entry_count > 0);
-  CALL_HEAP_FUNCTION(DeoptimizationInputData::Allocate(deopt_entry_count,
+  CALL_HEAP_FUNCTION(isolate(),
+                     DeoptimizationInputData::Allocate(deopt_entry_count,
                                                        pretenure),
                      DeoptimizationInputData);
 }
@@ -88,7 +97,8 @@
     int deopt_entry_count,
     PretenureFlag pretenure) {
   ASSERT(deopt_entry_count > 0);
-  CALL_HEAP_FUNCTION(DeoptimizationOutputData::Allocate(deopt_entry_count,
+  CALL_HEAP_FUNCTION(isolate(),
+                     DeoptimizationOutputData::Allocate(deopt_entry_count,
                                                         pretenure),
                      DeoptimizationOutputData);
 }
@@ -96,96 +106,137 @@
 
 // Symbols are created in the old generation (data space).
 Handle<String> Factory::LookupSymbol(Vector<const char> string) {
-  CALL_HEAP_FUNCTION(Heap::LookupSymbol(string), String);
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->LookupSymbol(string),
+                     String);
 }
 
 Handle<String> Factory::LookupAsciiSymbol(Vector<const char> string) {
-  CALL_HEAP_FUNCTION(Heap::LookupAsciiSymbol(string), String);
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->LookupAsciiSymbol(string),
+                     String);
 }
 
 Handle<String> Factory::LookupTwoByteSymbol(Vector<const uc16> string) {
-  CALL_HEAP_FUNCTION(Heap::LookupTwoByteSymbol(string), String);
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->LookupTwoByteSymbol(string),
+                     String);
 }
 
 
 Handle<String> Factory::NewStringFromAscii(Vector<const char> string,
                                            PretenureFlag pretenure) {
-  CALL_HEAP_FUNCTION(Heap::AllocateStringFromAscii(string, pretenure), String);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateStringFromAscii(string, pretenure),
+      String);
 }
 
 Handle<String> Factory::NewStringFromUtf8(Vector<const char> string,
                                           PretenureFlag pretenure) {
-  CALL_HEAP_FUNCTION(Heap::AllocateStringFromUtf8(string, pretenure), String);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateStringFromUtf8(string, pretenure),
+      String);
 }
 
 
 Handle<String> Factory::NewStringFromTwoByte(Vector<const uc16> string,
                                              PretenureFlag pretenure) {
-  CALL_HEAP_FUNCTION(Heap::AllocateStringFromTwoByte(string, pretenure),
-                     String);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateStringFromTwoByte(string, pretenure),
+      String);
 }
 
 
 Handle<String> Factory::NewRawAsciiString(int length,
                                           PretenureFlag pretenure) {
-  CALL_HEAP_FUNCTION(Heap::AllocateRawAsciiString(length, pretenure), String);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateRawAsciiString(length, pretenure),
+      String);
 }
 
 
 Handle<String> Factory::NewRawTwoByteString(int length,
                                             PretenureFlag pretenure) {
-  CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(length, pretenure), String);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateRawTwoByteString(length, pretenure),
+      String);
 }
 
 
 Handle<String> Factory::NewConsString(Handle<String> first,
                                       Handle<String> second) {
-  CALL_HEAP_FUNCTION(Heap::AllocateConsString(*first, *second), String);
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->AllocateConsString(*first, *second),
+                     String);
 }
 
 
 Handle<String> Factory::NewSubString(Handle<String> str,
                                      int begin,
                                      int end) {
-  CALL_HEAP_FUNCTION(str->SubString(begin, end), String);
+  CALL_HEAP_FUNCTION(isolate(),
+                     str->SubString(begin, end),
+                     String);
 }
 
 
 Handle<String> Factory::NewExternalStringFromAscii(
     ExternalAsciiString::Resource* resource) {
-  CALL_HEAP_FUNCTION(Heap::AllocateExternalStringFromAscii(resource), String);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateExternalStringFromAscii(resource),
+      String);
 }
 
 
 Handle<String> Factory::NewExternalStringFromTwoByte(
     ExternalTwoByteString::Resource* resource) {
-  CALL_HEAP_FUNCTION(Heap::AllocateExternalStringFromTwoByte(resource), String);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateExternalStringFromTwoByte(resource),
+      String);
 }
 
 
 Handle<Context> Factory::NewGlobalContext() {
-  CALL_HEAP_FUNCTION(Heap::AllocateGlobalContext(), Context);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateGlobalContext(),
+      Context);
 }
 
 
 Handle<Context> Factory::NewFunctionContext(int length,
                                             Handle<JSFunction> closure) {
-  CALL_HEAP_FUNCTION(Heap::AllocateFunctionContext(length, *closure), Context);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->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);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateWithContext(*previous,
+                                             *extension,
+                                             is_catch_context),
+      Context);
 }
 
 
 Handle<Struct> Factory::NewStruct(InstanceType type) {
-  CALL_HEAP_FUNCTION(Heap::AllocateStruct(type), Struct);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateStruct(type),
+      Struct);
 }
 
 
@@ -200,34 +251,35 @@
 Handle<Script> Factory::NewScript(Handle<String> source) {
   // Generate id for this script.
   int id;
-  if (Heap::last_script_id()->IsUndefined()) {
+  Heap* heap = isolate()->heap();
+  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 = Smi::cast(heap->last_script_id())->value();
     id++;
     if (!Smi::IsValid(id)) {
       id = 0;
     }
   }
-  Heap::SetLastScriptId(Smi::FromInt(id));
+  heap->SetLastScriptId(Smi::FromInt(id));
 
   // Create and initialize script object.
-  Handle<Proxy> wrapper = Factory::NewProxy(0, TENURED);
+  Handle<Proxy> wrapper = NewProxy(0, TENURED);
   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_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_data(Heap::undefined_value());
-  script->set_context_data(Heap::undefined_value());
+  script->set_data(heap->undefined_value());
+  script->set_context_data(heap->undefined_value());
   script->set_type(Smi::FromInt(Script::TYPE_NORMAL));
   script->set_compilation_type(Smi::FromInt(Script::COMPILATION_TYPE_HOST));
   script->set_wrapper(*wrapper);
-  script->set_line_ends(Heap::undefined_value());
-  script->set_eval_from_shared(Heap::undefined_value());
+  script->set_line_ends(heap->undefined_value());
+  script->set_eval_from_shared(heap->undefined_value());
   script->set_eval_from_instructions_offset(Smi::FromInt(0));
 
   return script;
@@ -235,7 +287,9 @@
 
 
 Handle<Proxy> Factory::NewProxy(Address addr, PretenureFlag pretenure) {
-  CALL_HEAP_FUNCTION(Heap::AllocateProxy(addr, pretenure), Proxy);
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->AllocateProxy(addr, pretenure),
+                     Proxy);
 }
 
 
@@ -246,17 +300,10 @@
 
 Handle<ByteArray> Factory::NewByteArray(int length, PretenureFlag pretenure) {
   ASSERT(0 <= length);
-  CALL_HEAP_FUNCTION(Heap::AllocateByteArray(length, pretenure), ByteArray);
-}
-
-
-Handle<PixelArray> Factory::NewPixelArray(int length,
-                                          uint8_t* external_pointer,
-                                          PretenureFlag pretenure) {
-  ASSERT(0 <= length);
-  CALL_HEAP_FUNCTION(Heap::AllocatePixelArray(length,
-                                              external_pointer,
-                                              pretenure), PixelArray);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateByteArray(length, pretenure),
+      ByteArray);
 }
 
 
@@ -265,32 +312,43 @@
                                                 void* external_pointer,
                                                 PretenureFlag pretenure) {
   ASSERT(0 <= length);
-  CALL_HEAP_FUNCTION(Heap::AllocateExternalArray(length,
-                                                 array_type,
-                                                 external_pointer,
-                                                 pretenure), ExternalArray);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateExternalArray(length,
+                                               array_type,
+                                               external_pointer,
+                                               pretenure),
+      ExternalArray);
 }
 
 
 Handle<JSGlobalPropertyCell> Factory::NewJSGlobalPropertyCell(
     Handle<Object> value) {
-  CALL_HEAP_FUNCTION(Heap::AllocateJSGlobalPropertyCell(*value),
-                     JSGlobalPropertyCell);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateJSGlobalPropertyCell(*value),
+      JSGlobalPropertyCell);
 }
 
 
 Handle<Map> Factory::NewMap(InstanceType type, int instance_size) {
-  CALL_HEAP_FUNCTION(Heap::AllocateMap(type, instance_size), Map);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateMap(type, instance_size),
+      Map);
 }
 
 
 Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
-  CALL_HEAP_FUNCTION(Heap::AllocateFunctionPrototype(*function), JSObject);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateFunctionPrototype(*function),
+      JSObject);
 }
 
 
 Handle<Map> Factory::CopyMapDropDescriptors(Handle<Map> src) {
-  CALL_HEAP_FUNCTION(src->CopyDropDescriptors(), Map);
+  CALL_HEAP_FUNCTION(isolate(), src->CopyDropDescriptors(), Map);
 }
 
 
@@ -320,27 +378,33 @@
 
 
 Handle<Map> Factory::CopyMapDropTransitions(Handle<Map> src) {
-  CALL_HEAP_FUNCTION(src->CopyDropTransitions(), Map);
+  CALL_HEAP_FUNCTION(isolate(), src->CopyDropTransitions(), Map);
 }
 
 
 Handle<Map> Factory::GetFastElementsMap(Handle<Map> src) {
-  CALL_HEAP_FUNCTION(src->GetFastElementsMap(), Map);
+  CALL_HEAP_FUNCTION(isolate(), src->GetFastElementsMap(), Map);
 }
 
 
 Handle<Map> Factory::GetSlowElementsMap(Handle<Map> src) {
-  CALL_HEAP_FUNCTION(src->GetSlowElementsMap(), Map);
+  CALL_HEAP_FUNCTION(isolate(), src->GetSlowElementsMap(), Map);
 }
 
 
-Handle<Map> Factory::GetPixelArrayElementsMap(Handle<Map> src) {
-  CALL_HEAP_FUNCTION(src->GetPixelArrayElementsMap(), Map);
+Handle<Map> Factory::GetExternalArrayElementsMap(
+    Handle<Map> src,
+    ExternalArrayType array_type,
+    bool safe_to_add_transition) {
+  CALL_HEAP_FUNCTION(isolate(),
+                     src->GetExternalArrayElementsMap(array_type,
+                                                      safe_to_add_transition),
+                     Map);
 }
 
 
 Handle<FixedArray> Factory::CopyFixedArray(Handle<FixedArray> array) {
-  CALL_HEAP_FUNCTION(array->Copy(), FixedArray);
+  CALL_HEAP_FUNCTION(isolate(), array->Copy(), FixedArray);
 }
 
 
@@ -348,10 +412,12 @@
     Handle<SharedFunctionInfo> function_info,
     Handle<Map> function_map,
     PretenureFlag pretenure) {
-  CALL_HEAP_FUNCTION(Heap::AllocateFunction(*function_map,
-                                            *function_info,
-                                            Heap::the_hole_value(),
-                                            pretenure),
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateFunction(*function_map,
+                                          *function_info,
+                                          isolate()->heap()->the_hole_value(),
+                                          pretenure),
                      JSFunction);
 }
 
@@ -361,11 +427,15 @@
     Handle<Context> context,
     PretenureFlag pretenure) {
   Handle<JSFunction> result = BaseNewFunctionFromSharedFunctionInfo(
-      function_info, Top::function_map(), pretenure);
+      function_info,
+      function_info->strict_mode()
+          ? isolate()->strict_mode_function_map()
+          : isolate()->function_map(),
+      pretenure);
+
   result->set_context(*context);
   int number_of_literals = function_info->num_literals();
-  Handle<FixedArray> literals =
-      Factory::NewFixedArray(number_of_literals, pretenure);
+  Handle<FixedArray> literals = NewFixedArray(number_of_literals, pretenure);
   if (number_of_literals > 0) {
     // Store the object, regexp and array functions in the literals
     // array prefix.  These functions will be used when creating
@@ -374,7 +444,7 @@
                   context->global_context());
   }
   result->set_literals(*literals);
-  result->set_next_function_link(Heap::undefined_value());
+  result->set_next_function_link(isolate()->heap()->undefined_value());
 
   if (V8::UseCrankshaft() &&
       FLAG_always_opt &&
@@ -389,23 +459,32 @@
 
 Handle<Object> Factory::NewNumber(double value,
                                   PretenureFlag pretenure) {
-  CALL_HEAP_FUNCTION(Heap::NumberFromDouble(value, pretenure), Object);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->NumberFromDouble(value, pretenure), Object);
 }
 
 
 Handle<Object> Factory::NewNumberFromInt(int value) {
-  CALL_HEAP_FUNCTION(Heap::NumberFromInt32(value), Object);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->NumberFromInt32(value), Object);
 }
 
 
 Handle<Object> Factory::NewNumberFromUint(uint32_t value) {
-  CALL_HEAP_FUNCTION(Heap::NumberFromUint32(value), Object);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->NumberFromUint32(value), Object);
 }
 
 
 Handle<JSObject> Factory::NewNeanderObject() {
-  CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(Heap::neander_map()),
-                     JSObject);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateJSObjectFromMap(
+          isolate()->heap()->neander_map()),
+      JSObject);
 }
 
 
@@ -455,11 +534,11 @@
 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());
+  Handle<FixedArray> array = NewFixedArray(args.length());
   for (int i = 0; i < args.length(); i++) {
     array->set(i, *args[i]);
   }
-  Handle<JSArray> object = Factory::NewJSArrayWithElements(array);
+  Handle<JSArray> object = NewJSArrayWithElements(array);
   Handle<Object> result = NewError(maker, type, object);
   return result.EscapeFrom(&scope);
 }
@@ -480,15 +559,15 @@
 Handle<Object> Factory::NewError(const char* maker,
                                  const char* type,
                                  Handle<JSArray> args) {
-  Handle<String> make_str = Factory::LookupAsciiSymbol(maker);
-  Handle<Object> fun_obj(Top::builtins()->GetPropertyNoExceptionThrown(
-      *make_str));
+  Handle<String> make_str = LookupAsciiSymbol(maker);
+  Handle<Object> fun_obj(
+      isolate()->js_builtins_object()->GetPropertyNoExceptionThrown(*make_str));
   // If the builtins haven't been properly configured yet this error
   // constructor may not have been defined.  Bail out.
   if (!fun_obj->IsJSFunction())
-    return Factory::undefined_value();
+    return undefined_value();
   Handle<JSFunction> fun = Handle<JSFunction>::cast(fun_obj);
-  Handle<Object> type_obj = Factory::LookupAsciiSymbol(type);
+  Handle<Object> type_obj = LookupAsciiSymbol(type);
   Object** argv[2] = { type_obj.location(),
                        Handle<Object>::cast(args).location() };
 
@@ -496,10 +575,7 @@
   // 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);
+      isolate()->js_builtins_object(), 2, argv, &caught_exception);
   return result;
 }
 
@@ -511,21 +587,17 @@
 
 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()->GetPropertyNoExceptionThrown(*constr)));
+  Handle<String> constr = LookupAsciiSymbol(constructor);
+  Handle<JSFunction> fun = Handle<JSFunction>(
+      JSFunction::cast(isolate()->js_builtins_object()->
+                       GetPropertyNoExceptionThrown(*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);
+      isolate()->js_builtins_object(), 1, argv, &caught_exception);
   return result;
 }
 
@@ -586,15 +658,15 @@
   // property that refers to the function.
   SetPrototypeProperty(function, prototype);
   // Currently safe because it is only invoked from Genesis.
-  SetLocalPropertyNoThrow(
-      prototype, Factory::constructor_symbol(), function, DONT_ENUM);
+  SetLocalPropertyNoThrow(prototype, constructor_symbol(), function, DONT_ENUM);
   return function;
 }
 
 
 Handle<JSFunction> Factory::NewFunctionWithoutPrototype(Handle<String> name,
                                                         Handle<Code> code) {
-  Handle<JSFunction> function = NewFunctionWithoutPrototype(name);
+  Handle<JSFunction> function = NewFunctionWithoutPrototype(name,
+                                                            kNonStrictMode);
   function->shared()->set_code(*code);
   function->set_code(*code);
   ASSERT(!function->has_initial_map());
@@ -605,18 +677,26 @@
 
 Handle<Code> Factory::NewCode(const CodeDesc& desc,
                               Code::Flags flags,
-                              Handle<Object> self_ref) {
-  CALL_HEAP_FUNCTION(Heap::CreateCode(desc, flags, self_ref), Code);
+                              Handle<Object> self_ref,
+                              bool immovable) {
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->CreateCode(
+                         desc, flags, self_ref, immovable),
+                     Code);
 }
 
 
 Handle<Code> Factory::CopyCode(Handle<Code> code) {
-  CALL_HEAP_FUNCTION(Heap::CopyCode(*code), Code);
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->CopyCode(*code),
+                     Code);
 }
 
 
 Handle<Code> Factory::CopyCode(Handle<Code> code, Vector<byte> reloc_info) {
-  CALL_HEAP_FUNCTION(Heap::CopyCode(*code, reloc_info), Code);
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->CopyCode(*code, reloc_info),
+                     Code);
 }
 
 
@@ -637,13 +717,15 @@
     Handle<String> key,
     Handle<Object> value,
     PropertyAttributes attributes) {
-  CALL_HEAP_FUNCTION(DoCopyInsert(*array, *key, *value, attributes),
+  CALL_HEAP_FUNCTION(isolate(),
+                     DoCopyInsert(*array, *key, *value, attributes),
                      DescriptorArray);
 }
 
 
 Handle<String> Factory::SymbolFromString(Handle<String> value) {
-  CALL_HEAP_FUNCTION(Heap::LookupSymbol(*value), String);
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->LookupSymbol(*value), String);
 }
 
 
@@ -708,35 +790,43 @@
 
 Handle<JSObject> Factory::NewJSObject(Handle<JSFunction> constructor,
                                       PretenureFlag pretenure) {
-  CALL_HEAP_FUNCTION(Heap::AllocateJSObject(*constructor, pretenure), JSObject);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateJSObject(*constructor, pretenure), JSObject);
 }
 
 
 Handle<GlobalObject> Factory::NewGlobalObject(
     Handle<JSFunction> constructor) {
-  CALL_HEAP_FUNCTION(Heap::AllocateGlobalObject(*constructor),
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->AllocateGlobalObject(*constructor),
                      GlobalObject);
 }
 
 
 
 Handle<JSObject> Factory::NewJSObjectFromMap(Handle<Map> map) {
-  CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(*map, NOT_TENURED),
-                     JSObject);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateJSObjectFromMap(*map, NOT_TENURED),
+      JSObject);
 }
 
 
-Handle<JSArray> Factory::NewJSArray(int length,
+Handle<JSArray> Factory::NewJSArray(int capacity,
                                     PretenureFlag pretenure) {
-  Handle<JSObject> obj = NewJSObject(Top::array_function(), pretenure);
-  CALL_HEAP_FUNCTION(Handle<JSArray>::cast(obj)->Initialize(length), JSArray);
+  Handle<JSObject> obj = NewJSObject(isolate()->array_function(), pretenure);
+  CALL_HEAP_FUNCTION(isolate(),
+                     Handle<JSArray>::cast(obj)->Initialize(capacity),
+                     JSArray);
 }
 
 
 Handle<JSArray> Factory::NewJSArrayWithElements(Handle<FixedArray> elements,
                                                 PretenureFlag pretenure) {
   Handle<JSArray> result =
-      Handle<JSArray>::cast(NewJSObject(Top::array_function(), pretenure));
+      Handle<JSArray>::cast(NewJSObject(isolate()->array_function(),
+                                        pretenure));
   result->SetContent(*elements);
   return result;
 }
@@ -770,24 +860,27 @@
     Handle<Object> script,
     Handle<Object> stack_trace,
     Handle<Object> stack_frames) {
-  CALL_HEAP_FUNCTION(Heap::AllocateJSMessageObject(*type,
-                                                   *arguments,
-                                                   start_position,
-                                                   end_position,
-                                                   *script,
-                                                   *stack_trace,
-                                                   *stack_frames),
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->AllocateJSMessageObject(*type,
+                         *arguments,
+                         start_position,
+                         end_position,
+                         *script,
+                         *stack_trace,
+                         *stack_frames),
                      JSMessageObject);
 }
 
 Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) {
-  CALL_HEAP_FUNCTION(Heap::AllocateSharedFunctionInfo(*name),
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->AllocateSharedFunctionInfo(*name),
                      SharedFunctionInfo);
 }
 
 
 Handle<String> Factory::NumberToString(Handle<Object> number) {
-  CALL_HEAP_FUNCTION(Heap::NumberToString(*number), String);
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->NumberToString(*number), String);
 }
 
 
@@ -795,54 +888,65 @@
     Handle<NumberDictionary> dictionary,
     uint32_t key,
     Handle<Object> value) {
-  CALL_HEAP_FUNCTION(dictionary->AtNumberPut(key, *value), NumberDictionary);
+  CALL_HEAP_FUNCTION(isolate(),
+                     dictionary->AtNumberPut(key, *value),
+                     NumberDictionary);
 }
 
 
 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);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateFunction(*isolate()->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());
+  fun->set_context(isolate()->context()->global_context());
   return fun;
 }
 
 
 Handle<JSFunction> Factory::NewFunctionWithoutPrototypeHelper(
-    Handle<String> name) {
+    Handle<String> name,
+    StrictModeFlag strict_mode) {
   Handle<SharedFunctionInfo> function_share = NewSharedFunctionInfo(name);
-  CALL_HEAP_FUNCTION(Heap::AllocateFunction(
-                         *Top::function_without_prototype_map(),
+  Handle<Map> map = strict_mode == kStrictMode
+      ? isolate()->strict_mode_function_without_prototype_map()
+      : isolate()->function_without_prototype_map();
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->AllocateFunction(
+                         *map,
                          *function_share,
                          *the_hole_value()),
                      JSFunction);
 }
 
 
-Handle<JSFunction> Factory::NewFunctionWithoutPrototype(Handle<String> name) {
-  Handle<JSFunction> fun = NewFunctionWithoutPrototypeHelper(name);
-  fun->set_context(Top::context()->global_context());
+Handle<JSFunction> Factory::NewFunctionWithoutPrototype(
+    Handle<String> name,
+    StrictModeFlag strict_mode) {
+  Handle<JSFunction> fun = NewFunctionWithoutPrototypeHelper(name, strict_mode);
+  fun->set_context(isolate()->context()->global_context());
   return fun;
 }
 
 
 Handle<Object> Factory::ToObject(Handle<Object> object) {
-  CALL_HEAP_FUNCTION(object->ToObject(), Object);
+  CALL_HEAP_FUNCTION(isolate(), object->ToObject(), Object);
 }
 
 
 Handle<Object> Factory::ToObject(Handle<Object> object,
                                  Handle<Context> global_context) {
-  CALL_HEAP_FUNCTION(object->ToObject(*global_context), Object);
+  CALL_HEAP_FUNCTION(isolate(), object->ToObject(*global_context), Object);
 }
 
 
@@ -859,13 +963,13 @@
   // debug info object to avoid allocation while setting up the debug info
   // object.
   Handle<FixedArray> break_points(
-      Factory::NewFixedArray(Debug::kEstimatedNofBreakPointsInFunction));
+      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));
+      Handle<DebugInfo>::cast(NewStruct(DEBUG_INFO_TYPE));
   debug_info->set_shared(*shared);
   debug_info->set_original_code(*original_code);
   debug_info->set_code(*code);
@@ -881,15 +985,16 @@
 
 Handle<JSObject> Factory::NewArgumentsObject(Handle<Object> callee,
                                              int length) {
-  CALL_HEAP_FUNCTION(Heap::AllocateArgumentsObject(*callee, length), JSObject);
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateArgumentsObject(*callee, length), JSObject);
 }
 
 
 Handle<JSFunction> Factory::CreateApiFunction(
     Handle<FunctionTemplateInfo> obj, ApiInstanceType instance_type) {
-  Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::HandleApiCall));
-  Handle<Code> construct_stub =
-      Handle<Code>(Builtins::builtin(Builtins::JSConstructStubApi));
+  Handle<Code> code = isolate()->builtins()->HandleApiCall();
+  Handle<Code> construct_stub = isolate()->builtins()->JSConstructStubApi();
 
   int internal_field_count = 0;
   if (!obj->instance_template()->IsUndefined()) {
@@ -921,11 +1026,11 @@
   ASSERT(type != INVALID_TYPE);
 
   Handle<JSFunction> result =
-      Factory::NewFunction(Factory::empty_symbol(),
-                           type,
-                           instance_size,
-                           code,
-                           true);
+      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()) {
@@ -973,7 +1078,7 @@
   while (true) {
     Handle<Object> props = Handle<Object>(obj->property_accessors());
     if (!props->IsUndefined()) {
-      array = Factory::CopyAppendCallbackDescriptors(array, props);
+      array = CopyAppendCallbackDescriptors(array, props);
     }
     Handle<Object> parent = Handle<Object>(obj->parent_template());
     if (parent->IsUndefined()) break;
@@ -989,7 +1094,8 @@
 
 
 Handle<MapCache> Factory::NewMapCache(int at_least_space_for) {
-  CALL_HEAP_FUNCTION(MapCache::Allocate(at_least_space_for), MapCache);
+  CALL_HEAP_FUNCTION(isolate(),
+                     MapCache::Allocate(at_least_space_for), MapCache);
 }
 
 
@@ -1009,7 +1115,8 @@
 Handle<MapCache> Factory::AddToMapCache(Handle<Context> context,
                                         Handle<FixedArray> keys,
                                         Handle<Map> map) {
-  CALL_HEAP_FUNCTION(UpdateMapCacheWith(*context, *keys, *map), MapCache);
+  CALL_HEAP_FUNCTION(isolate(),
+                     UpdateMapCacheWith(*context, *keys, *map), MapCache);
 }
 
 
@@ -1058,8 +1165,8 @@
   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::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));
diff --git a/src/factory.h b/src/factory.h
index 7547f7c..71bfdc4 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -29,6 +29,7 @@
 #define V8_FACTORY_H_
 
 #include "globals.h"
+#include "handles.h"
 #include "heap.h"
 
 namespace v8 {
@@ -36,34 +37,34 @@
 
 // Interface for handle based allocation.
 
-class Factory : public AllStatic {
+class Factory {
  public:
   // Allocate a new fixed array with undefined entries.
-  static Handle<FixedArray> NewFixedArray(
+  Handle<FixedArray> NewFixedArray(
       int size,
       PretenureFlag pretenure = NOT_TENURED);
 
   // Allocate a new fixed array with non-existing entries (the hole).
-  static Handle<FixedArray> NewFixedArrayWithHoles(
+  Handle<FixedArray> NewFixedArrayWithHoles(
       int size,
       PretenureFlag pretenure = NOT_TENURED);
 
-  static Handle<NumberDictionary> NewNumberDictionary(int at_least_space_for);
+  Handle<NumberDictionary> NewNumberDictionary(int at_least_space_for);
 
-  static Handle<StringDictionary> NewStringDictionary(int at_least_space_for);
+  Handle<StringDictionary> NewStringDictionary(int at_least_space_for);
 
-  static Handle<DescriptorArray> NewDescriptorArray(int number_of_descriptors);
-  static Handle<DeoptimizationInputData> NewDeoptimizationInputData(
+  Handle<DescriptorArray> NewDescriptorArray(int number_of_descriptors);
+  Handle<DeoptimizationInputData> NewDeoptimizationInputData(
       int deopt_entry_count,
       PretenureFlag pretenure);
-  static Handle<DeoptimizationOutputData> NewDeoptimizationOutputData(
+  Handle<DeoptimizationOutputData> NewDeoptimizationOutputData(
       int deopt_entry_count,
       PretenureFlag pretenure);
 
-  static Handle<String> LookupSymbol(Vector<const char> str);
-  static Handle<String> LookupAsciiSymbol(Vector<const char> str);
-  static Handle<String> LookupTwoByteSymbol(Vector<const uc16> str);
-  static Handle<String> LookupAsciiSymbol(const char* str) {
+  Handle<String> LookupSymbol(Vector<const char> str);
+  Handle<String> LookupAsciiSymbol(Vector<const char> str);
+  Handle<String> LookupTwoByteSymbol(Vector<const uc16> str);
+  Handle<String> LookupAsciiSymbol(const char* str) {
     return LookupSymbol(CStrVector(str));
   }
 
@@ -90,236 +91,236 @@
   //     two byte.
   //
   // ASCII strings are pretenured when used as keys in the SourceCodeCache.
-  static Handle<String> NewStringFromAscii(
+  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(
+  Handle<String> NewStringFromUtf8(
       Vector<const char> str,
       PretenureFlag pretenure = NOT_TENURED);
 
-  static Handle<String> NewStringFromTwoByte(
+  Handle<String> NewStringFromTwoByte(
       Vector<const uc16> str,
       PretenureFlag pretenure = NOT_TENURED);
 
   // Allocates and partially initializes an ASCII or TwoByte String. The
   // characters of the string are uninitialized. Currently used in regexp code
   // only, where they are pretenured.
-  static Handle<String> NewRawAsciiString(
+  Handle<String> NewRawAsciiString(
       int length,
       PretenureFlag pretenure = NOT_TENURED);
-  static Handle<String> NewRawTwoByteString(
+  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);
+  Handle<String> NewConsString(Handle<String> first,
+                               Handle<String> second);
 
   // Create a new string object which holds a substring of a string.
-  static Handle<String> NewSubString(Handle<String> str,
-                                     int begin,
-                                     int end);
+  Handle<String> NewSubString(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(
+  Handle<String> NewExternalStringFromAscii(
       ExternalAsciiString::Resource* resource);
-  static Handle<String> NewExternalStringFromTwoByte(
+  Handle<String> NewExternalStringFromTwoByte(
       ExternalTwoByteString::Resource* resource);
 
   // Create a global (but otherwise uninitialized) context.
-  static Handle<Context> NewGlobalContext();
+  Handle<Context> NewGlobalContext();
 
   // Create a function context.
-  static Handle<Context> NewFunctionContext(int length,
-                                            Handle<JSFunction> closure);
+  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);
+  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);
+  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);
+  Handle<Struct> NewStruct(InstanceType type);
 
-  static Handle<AccessorInfo> NewAccessorInfo();
+  Handle<AccessorInfo> NewAccessorInfo();
 
-  static Handle<Script> NewScript(Handle<String> source);
+  Handle<Script> NewScript(Handle<String> source);
 
   // Proxies are pretenured when allocated by the bootstrapper.
-  static Handle<Proxy> NewProxy(Address addr,
-                                PretenureFlag pretenure = NOT_TENURED);
+  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);
+  Handle<Proxy> NewProxy(const AccessorDescriptor* proxy);
 
-  static Handle<ByteArray> NewByteArray(int length,
-                                        PretenureFlag pretenure = NOT_TENURED);
+  Handle<ByteArray> NewByteArray(int length,
+                                 PretenureFlag pretenure = NOT_TENURED);
 
-  static Handle<PixelArray> NewPixelArray(
-      int length,
-      uint8_t* external_pointer,
-      PretenureFlag pretenure = NOT_TENURED);
-
-  static Handle<ExternalArray> NewExternalArray(
+  Handle<ExternalArray> NewExternalArray(
       int length,
       ExternalArrayType array_type,
       void* external_pointer,
       PretenureFlag pretenure = NOT_TENURED);
 
-  static Handle<JSGlobalPropertyCell> NewJSGlobalPropertyCell(
+  Handle<JSGlobalPropertyCell> NewJSGlobalPropertyCell(
       Handle<Object> value);
 
-  static Handle<Map> NewMap(InstanceType type, int instance_size);
+  Handle<Map> NewMap(InstanceType type, int instance_size);
 
-  static Handle<JSObject> NewFunctionPrototype(Handle<JSFunction> function);
+  Handle<JSObject> NewFunctionPrototype(Handle<JSFunction> function);
 
-  static Handle<Map> CopyMapDropDescriptors(Handle<Map> map);
+  Handle<Map> CopyMapDropDescriptors(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);
+  Handle<Map> CopyMap(Handle<Map> map, int extra_inobject_props);
 
-  static Handle<Map> CopyMapDropTransitions(Handle<Map> map);
+  Handle<Map> CopyMapDropTransitions(Handle<Map> map);
 
-  static Handle<Map> GetFastElementsMap(Handle<Map> map);
+  Handle<Map> GetFastElementsMap(Handle<Map> map);
 
-  static Handle<Map> GetSlowElementsMap(Handle<Map> map);
+  Handle<Map> GetSlowElementsMap(Handle<Map> map);
 
-  static Handle<Map> GetPixelArrayElementsMap(Handle<Map> map);
+  Handle<Map> GetExternalArrayElementsMap(Handle<Map> map,
+                                          ExternalArrayType array_type,
+                                          bool safe_to_add_transition);
 
-  static Handle<FixedArray> CopyFixedArray(Handle<FixedArray> array);
+  Handle<FixedArray> CopyFixedArray(Handle<FixedArray> array);
 
   // Numbers (eg, literals) are pretenured by the parser.
-  static Handle<Object> NewNumber(double value,
-                                  PretenureFlag pretenure = NOT_TENURED);
+  Handle<Object> NewNumber(double value,
+                           PretenureFlag pretenure = NOT_TENURED);
 
-  static Handle<Object> NewNumberFromInt(int value);
-  static Handle<Object> NewNumberFromUint(uint32_t value);
+  Handle<Object> NewNumberFromInt(int value);
+  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();
+  Handle<JSObject> NewNeanderObject();
 
-  static Handle<JSObject> NewArgumentsObject(Handle<Object> callee, int length);
+  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);
+  Handle<JSObject> NewJSObject(Handle<JSFunction> constructor,
+                               PretenureFlag pretenure = NOT_TENURED);
 
   // Global objects are pretenured.
-  static Handle<GlobalObject> NewGlobalObject(Handle<JSFunction> constructor);
+  Handle<GlobalObject> NewGlobalObject(Handle<JSFunction> constructor);
 
   // JS objects are pretenured when allocated by the bootstrapper and
   // runtime.
-  static Handle<JSObject> NewJSObjectFromMap(Handle<Map> map);
+  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);
+  Handle<JSArray> NewJSArray(int capacity,
+                             PretenureFlag pretenure = NOT_TENURED);
 
-  static Handle<JSArray> NewJSArrayWithElements(
+  Handle<JSArray> NewJSArrayWithElements(
       Handle<FixedArray> elements,
       PretenureFlag pretenure = NOT_TENURED);
 
-  static Handle<JSFunction> NewFunction(Handle<String> name,
-                                        Handle<Object> prototype);
+  Handle<JSFunction> NewFunction(Handle<String> name,
+                                 Handle<Object> prototype);
 
-  static Handle<JSFunction> NewFunctionWithoutPrototype(Handle<String> name);
+  Handle<JSFunction> NewFunctionWithoutPrototype(
+      Handle<String> name,
+      StrictModeFlag strict_mode);
 
-  static Handle<JSFunction> NewFunction(Handle<Object> super, bool is_global);
+  Handle<JSFunction> NewFunction(Handle<Object> super, bool is_global);
 
-  static Handle<JSFunction> BaseNewFunctionFromSharedFunctionInfo(
+  Handle<JSFunction> BaseNewFunctionFromSharedFunctionInfo(
       Handle<SharedFunctionInfo> function_info,
       Handle<Map> function_map,
       PretenureFlag pretenure);
 
-  static Handle<JSFunction> NewFunctionFromSharedFunctionInfo(
+  Handle<JSFunction> NewFunctionFromSharedFunctionInfo(
       Handle<SharedFunctionInfo> function_info,
       Handle<Context> context,
       PretenureFlag pretenure = TENURED);
 
-  static Handle<Code> NewCode(const CodeDesc& desc,
-                              Code::Flags flags,
-                              Handle<Object> self_reference);
+  Handle<Code> NewCode(const CodeDesc& desc,
+                       Code::Flags flags,
+                       Handle<Object> self_reference,
+                       bool immovable = false);
 
-  static Handle<Code> CopyCode(Handle<Code> code);
+  Handle<Code> CopyCode(Handle<Code> code);
 
-  static Handle<Code> CopyCode(Handle<Code> code, Vector<byte> reloc_info);
+  Handle<Code> CopyCode(Handle<Code> code, Vector<byte> reloc_info);
 
-  static Handle<Object> ToObject(Handle<Object> object);
-  static Handle<Object> ToObject(Handle<Object> object,
-                                 Handle<Context> global_context);
+  Handle<Object> ToObject(Handle<Object> object);
+  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);
+  Handle<Object> NewError(const char* maker, const char* type,
+                          Handle<JSArray> args);
+  Handle<Object> NewError(const char* maker, const char* type,
+                          Vector< Handle<Object> > args);
+  Handle<Object> NewError(const char* type,
+                          Vector< Handle<Object> > args);
+  Handle<Object> NewError(Handle<String> message);
+  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);
+  Handle<Object> NewTypeError(const char* type,
+                              Vector< Handle<Object> > args);
+  Handle<Object> NewTypeError(Handle<String> message);
 
-  static Handle<Object> NewRangeError(const char* type,
-                                      Vector< Handle<Object> > args);
-  static Handle<Object> NewRangeError(Handle<String> message);
+  Handle<Object> NewRangeError(const char* type,
+                               Vector< Handle<Object> > args);
+  Handle<Object> NewRangeError(Handle<String> message);
 
-  static Handle<Object> NewSyntaxError(const char* type, Handle<JSArray> args);
-  static Handle<Object> NewSyntaxError(Handle<String> message);
+  Handle<Object> NewSyntaxError(const char* type, Handle<JSArray> args);
+  Handle<Object> NewSyntaxError(Handle<String> message);
 
-  static Handle<Object> NewReferenceError(const char* type,
-                                          Vector< Handle<Object> > args);
-  static Handle<Object> NewReferenceError(Handle<String> message);
+  Handle<Object> NewReferenceError(const char* type,
+                                   Vector< Handle<Object> > args);
+  Handle<Object> NewReferenceError(Handle<String> message);
 
-  static Handle<Object> NewEvalError(const char* type,
-                                     Vector< Handle<Object> > args);
+  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);
+  Handle<JSFunction> NewFunction(Handle<String> name,
+                                 InstanceType type,
+                                 int instance_size,
+                                 Handle<Code> code,
+                                 bool force_initial_map);
 
-  static Handle<JSFunction> NewFunction(Handle<Map> function_map,
+  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);
+  Handle<JSFunction> NewFunctionWithPrototype(Handle<String> name,
+                                              InstanceType type,
+                                              int instance_size,
+                                              Handle<JSObject> prototype,
+                                              Handle<Code> code,
+                                              bool force_initial_map);
 
-  static Handle<JSFunction> NewFunctionWithoutPrototype(Handle<String> name,
-                                                        Handle<Code> code);
+  Handle<JSFunction> NewFunctionWithoutPrototype(Handle<String> name,
+                                                 Handle<Code> code);
 
-  static Handle<DescriptorArray> CopyAppendProxyDescriptor(
+  Handle<DescriptorArray> CopyAppendProxyDescriptor(
       Handle<DescriptorArray> array,
       Handle<String> key,
       Handle<Object> value,
       PropertyAttributes attributes);
 
-  static Handle<String> NumberToString(Handle<Object> number);
+  Handle<String> NumberToString(Handle<Object> number);
 
   enum ApiInstanceType {
     JavaScriptObject,
@@ -327,47 +328,47 @@
     OuterGlobalObject
   };
 
-  static Handle<JSFunction> CreateApiFunction(
+  Handle<JSFunction> CreateApiFunction(
       Handle<FunctionTemplateInfo> data,
       ApiInstanceType type = JavaScriptObject);
 
-  static Handle<JSFunction> InstallMembers(Handle<JSFunction> function);
+  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);
+  void ConfigureInstance(Handle<FunctionTemplateInfo> desc,
+                         Handle<JSObject> instance,
+                         bool* pending_exception);
 
 #define ROOT_ACCESSOR(type, name, camel_name)                                  \
-  static inline Handle<type> name() {                                          \
+  inline Handle<type> name() {                                                 \
     return Handle<type>(BitCast<type**>(                                       \
-        &Heap::roots_[Heap::k##camel_name##RootIndex]));                       \
+        &isolate()->heap()->roots_[Heap::k##camel_name##RootIndex]));          \
   }
   ROOT_LIST(ROOT_ACCESSOR)
 #undef ROOT_ACCESSOR_ACCESSOR
 
-#define SYMBOL_ACCESSOR(name, str) \
-  static inline Handle<String> name() {                                        \
+#define SYMBOL_ACCESSOR(name, str)                                             \
+  inline Handle<String> name() {                                               \
     return Handle<String>(BitCast<String**>(                                   \
-        &Heap::roots_[Heap::k##name##RootIndex]));                             \
+        &isolate()->heap()->roots_[Heap::k##name##RootIndex]));                \
   }
   SYMBOL_LIST(SYMBOL_ACCESSOR)
 #undef SYMBOL_ACCESSOR
 
-  static Handle<String> hidden_symbol() {
-    return Handle<String>(&Heap::hidden_symbol_);
+  Handle<String> hidden_symbol() {
+    return Handle<String>(&isolate()->heap()->hidden_symbol_);
   }
 
-  static Handle<SharedFunctionInfo> NewSharedFunctionInfo(
+  Handle<SharedFunctionInfo> NewSharedFunctionInfo(
       Handle<String> name,
       int number_of_literals,
       Handle<Code> code,
       Handle<SerializedScopeInfo> scope_info);
-  static Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
+  Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
 
-  static Handle<JSMessageObject> NewJSMessageObject(
+  Handle<JSMessageObject> NewJSMessageObject(
       Handle<String> type,
       Handle<JSArray> arguments,
       int start_position,
@@ -376,54 +377,57 @@
       Handle<Object> stack_trace,
       Handle<Object> stack_frames);
 
-  static Handle<NumberDictionary> DictionaryAtNumberPut(
+  Handle<NumberDictionary> DictionaryAtNumberPut(
       Handle<NumberDictionary>,
       uint32_t key,
       Handle<Object> value);
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  static Handle<DebugInfo> NewDebugInfo(Handle<SharedFunctionInfo> shared);
+  Handle<DebugInfo> NewDebugInfo(Handle<SharedFunctionInfo> shared);
 #endif
 
   // 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);
+  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);
+  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);
+  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);
+  Isolate* isolate() { return reinterpret_cast<Isolate*>(this); }
 
-  static Handle<JSFunction> NewFunctionWithoutPrototypeHelper(
-      Handle<String> name);
+  Handle<JSFunction> NewFunctionHelper(Handle<String> name,
+                                       Handle<Object> prototype);
 
-  static Handle<DescriptorArray> CopyAppendCallbackDescriptors(
+  Handle<JSFunction> NewFunctionWithoutPrototypeHelper(
+      Handle<String> name,
+      StrictModeFlag strict_mode);
+
+  Handle<DescriptorArray> CopyAppendCallbackDescriptors(
       Handle<DescriptorArray> array,
       Handle<Object> descriptors);
 
   // Create a new map cache.
-  static Handle<MapCache> NewMapCache(int at_least_space_for);
+  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);
+  Handle<MapCache> AddToMapCache(Handle<Context> context,
+                                 Handle<FixedArray> keys,
+                                 Handle<Map> map);
 };
 
 
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 2566766..0bc6409 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -97,7 +97,11 @@
 #define FLAG FLAG_FULL
 
 // Flags for Crankshaft.
-DEFINE_bool(crankshaft, true, "use crankshaft")
+#ifdef V8_TARGET_ARCH_MIPS
+  DEFINE_bool(crankshaft, false, "use crankshaft")
+#else
+  DEFINE_bool(crankshaft, true, "use crankshaft")
+#endif
 DEFINE_string(hydrogen_filter, "", "hydrogen use/trace filter")
 DEFINE_bool(use_hydrogen, true, "use generated hydrogen for compilation")
 DEFINE_bool(build_lithium, true, "use lithium chunk builder")
@@ -111,7 +115,7 @@
 DEFINE_bool(limit_inlining, true, "limit code size growth from inlining")
 DEFINE_bool(eliminate_empty_blocks, true, "eliminate empty blocks")
 DEFINE_bool(loop_invariant_code_motion, true, "loop invariant code motion")
-DEFINE_bool(time_hydrogen, false, "timing for hydrogen")
+DEFINE_bool(hydrogen_stats, false, "print statistics for hydrogen")
 DEFINE_bool(trace_hydrogen, false, "trace generated hydrogen to file")
 DEFINE_bool(trace_inlining, false, "trace inlining decisions")
 DEFINE_bool(trace_alloc, false, "trace register allocator")
@@ -161,6 +165,8 @@
             "enable use of VFP3 instructions if available (ARM only)")
 DEFINE_bool(enable_armv7, true,
             "enable use of ARMv7 instructions if available (ARM only)")
+DEFINE_bool(enable_fpu, true,
+            "enable use of MIPS FPU instructions if available (MIPS only)")
 
 // bootstrapper.cc
 DEFINE_string(expose_natives_as, NULL, "expose natives in global object")
@@ -447,6 +453,8 @@
             "report heap spill statistics along with heap_stats "
             "(requires heap_stats)")
 
+DEFINE_bool(trace_isolates, false, "trace isolate state changes")
+
 // VM state
 DEFINE_bool(log_state_changes, false, "Log state changes.")
 
diff --git a/src/frame-element.cc b/src/frame-element.cc
index ee7be95..f629900 100644
--- a/src/frame-element.cc
+++ b/src/frame-element.cc
@@ -33,10 +33,5 @@
 namespace v8 {
 namespace internal {
 
-FrameElement::ZoneObjectList* FrameElement::ConstantList() {
-  static ZoneObjectList list(10);
-  return &list;
-}
-
 
 } }  // namespace v8::internal
diff --git a/src/frame-element.h b/src/frame-element.h
index ae5d6a1..0c7d010 100644
--- a/src/frame-element.h
+++ b/src/frame-element.h
@@ -106,20 +106,9 @@
     return result;
   }
 
-  // Static indirection table for handles to constants.  If a frame
-  // element represents a constant, the data contains an index into
-  // this table of handles to the actual constants.
-  typedef ZoneList<Handle<Object> > ZoneObjectList;
-
-  static ZoneObjectList* ConstantList();
-
   static bool ConstantPoolOverflowed() {
-    return !DataField::is_valid(ConstantList()->length());
-  }
-
-  // Clear the constants indirection table.
-  static void ClearConstantList() {
-    ConstantList()->Clear();
+    return !DataField::is_valid(
+        Isolate::Current()->frame_element_constant_list()->length());
   }
 
   bool is_synced() const { return SyncedField::decode(value_); }
@@ -164,7 +153,8 @@
 
   Handle<Object> handle() const {
     ASSERT(is_constant());
-    return ConstantList()->at(DataField::decode(value_));
+    return Isolate::Current()->frame_element_constant_list()->
+        at(DataField::decode(value_));
   }
 
   int index() const {
@@ -232,12 +222,14 @@
 
   // Used to construct constant elements.
   FrameElement(Handle<Object> value, SyncFlag is_synced, TypeInfo info) {
+    ZoneObjectList* constant_list =
+        Isolate::Current()->frame_element_constant_list();
     value_ = TypeField::encode(CONSTANT)
         | CopiedField::encode(false)
         | SyncedField::encode(is_synced != NOT_SYNCED)
         | TypeInfoField::encode(info.ToInt())
-        | DataField::encode(ConstantList()->length());
-    ConstantList()->Add(value);
+        | DataField::encode(constant_list->length());
+    constant_list->Add(value);
   }
 
   Type type() const { return TypeField::decode(value_); }
diff --git a/src/frames-inl.h b/src/frames-inl.h
index 78bb646..e6eaec0 100644
--- a/src/frames-inl.h
+++ b/src/frames-inl.h
@@ -29,6 +29,8 @@
 #define V8_FRAMES_INL_H_
 
 #include "frames.h"
+#include "isolate.h"
+#include "v8memory.h"
 
 #if V8_TARGET_ARCH_IA32
 #include "ia32/frames-ia32.h"
@@ -91,6 +93,11 @@
 }
 
 
+inline Code* StackFrame::GetContainingCode(Isolate* isolate, Address pc) {
+  return isolate->pc_to_code_cache()->GetCacheEntry(pc)->code;
+}
+
+
 inline Object* StandardFrame::GetExpression(int index) const {
   return Memory::Object_at(GetExpressionAddress(index));
 }
diff --git a/src/frames.cc b/src/frames.cc
index 24ea8dd..79aa250 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -35,13 +35,10 @@
 #include "safepoint-table.h"
 #include "scopeinfo.h"
 #include "string-stream.h"
-#include "top.h"
 
 namespace v8 {
 namespace internal {
 
-PcToCodeCache::PcToCodeCacheEntry
-    PcToCodeCache::cache_[PcToCodeCache::kPcToCodeCacheSize];
 
 int SafeStackFrameIterator::active_count_ = 0;
 
@@ -77,7 +74,8 @@
 #define INITIALIZE_SINGLETON(type, field) field##_(this),
 StackFrameIterator::StackFrameIterator()
     : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
-      frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()),
+      frame_(NULL), handler_(NULL),
+      thread_(Isolate::Current()->thread_local_top()),
       fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
   Reset();
 }
@@ -87,10 +85,11 @@
       fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
   Reset();
 }
-StackFrameIterator::StackFrameIterator(bool use_top, Address fp, Address sp)
+StackFrameIterator::StackFrameIterator(Isolate* isolate,
+                                       bool use_top, Address fp, Address sp)
     : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
       frame_(NULL), handler_(NULL),
-      thread_(use_top ? Top::GetCurrentThread() : NULL),
+      thread_(use_top ? isolate->thread_local_top() : NULL),
       fp_(use_top ? NULL : fp), sp_(sp),
       advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
                &StackFrameIterator::AdvanceWithoutHandler) {
@@ -138,8 +137,10 @@
   StackFrame::State state;
   StackFrame::Type type;
   if (thread_ != NULL) {
-    type = ExitFrame::GetStateForFramePointer(Top::c_entry_fp(thread_), &state);
-    handler_ = StackHandler::FromAddress(Top::handler(thread_));
+    type = ExitFrame::GetStateForFramePointer(
+        Isolate::c_entry_fp(thread_), &state);
+    handler_ = StackHandler::FromAddress(
+        Isolate::handler(thread_));
   } else {
     ASSERT(fp_ != NULL);
     state.fp = fp_;
@@ -221,22 +222,25 @@
 
 
 SafeStackFrameIterator::SafeStackFrameIterator(
+    Isolate* isolate,
     Address fp, Address sp, Address low_bound, Address high_bound) :
     maintainer_(),
     stack_validator_(low_bound, high_bound),
-    is_valid_top_(IsValidTop(low_bound, high_bound)),
+    is_valid_top_(IsValidTop(isolate, low_bound, high_bound)),
     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) {
+    iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
 }
 
 
-bool SafeStackFrameIterator::IsValidTop(Address low_bound, Address high_bound) {
-  Address fp = Top::c_entry_fp(Top::GetCurrentThread());
+bool SafeStackFrameIterator::IsValidTop(Isolate* isolate,
+                                        Address low_bound, Address high_bound) {
+  ThreadLocalTop* top = isolate->thread_local_top();
+  Address fp = Isolate::c_entry_fp(top);
   ExitFrameValidator validator(low_bound, high_bound);
   if (!validator.IsValidFP(fp)) return false;
-  return Top::handler(Top::GetCurrentThread()) != NULL;
+  return Isolate::handler(top) != NULL;
 }
 
 
@@ -312,8 +316,9 @@
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
 SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
+    Isolate* isolate,
     Address fp, Address sp, Address low_bound, Address high_bound) :
-    SafeJavaScriptFrameIterator(fp, sp, low_bound, high_bound) {
+    SafeJavaScriptFrameIterator(isolate, fp, sp, low_bound, high_bound) {
   if (!done() && !frame()->is_java_script()) Advance();
 }
 
@@ -331,7 +336,9 @@
 Code* StackFrame::GetSafepointData(Address pc,
                                    SafepointEntry* safepoint_entry,
                                    unsigned* stack_slots) {
-  PcToCodeCache::PcToCodeCacheEntry* entry = PcToCodeCache::GetCacheEntry(pc);
+  Isolate* isolate = Isolate::Current();
+  PcToCodeCache::PcToCodeCacheEntry* entry =
+      isolate->pc_to_code_cache()->GetCacheEntry(pc);
   SafepointEntry cached_safepoint_entry = entry->safepoint_entry;
   if (!entry->safepoint_entry.is_valid()) {
     entry->safepoint_entry = entry->code->GetSafepointEntry(pc);
@@ -386,7 +393,8 @@
     // into the heap to determine the state. This is safe as long
     // as nobody tries to GC...
     if (SafeStackFrameIterator::is_active()) return JAVA_SCRIPT;
-    Code::Kind kind = GetContainingCode(*(state->pc_address))->kind();
+    Code::Kind kind = GetContainingCode(Isolate::Current(),
+                                        *(state->pc_address))->kind();
     ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
     return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
   }
@@ -402,7 +410,7 @@
 
 
 Code* EntryFrame::unchecked_code() const {
-  return Heap::raw_unchecked_js_entry_code();
+  return HEAP->raw_unchecked_js_entry_code();
 }
 
 
@@ -425,7 +433,7 @@
 
 
 Code* EntryConstructFrame::unchecked_code() const {
-  return Heap::raw_unchecked_js_construct_entry_code();
+  return HEAP->raw_unchecked_js_construct_entry_code();
 }
 
 
@@ -457,7 +465,7 @@
 void ExitFrame::Iterate(ObjectVisitor* v) const {
   // The arguments are traversed as part of the expression stack of
   // the calling frame.
-  IteratePc(v, pc_address(), code());
+  IteratePc(v, pc_address(), LookupCode(Isolate::Current()));
   v->VisitPointer(&code_slot());
 }
 
@@ -630,15 +638,10 @@
 }
 
 
-int JavaScriptFrame::GetProvidedParametersCount() const {
-  return ComputeParametersCount();
-}
-
-
 Address JavaScriptFrame::GetCallerStackPointer() const {
   int arguments;
-  if (Heap::gc_state() != Heap::NOT_IN_GC ||
-      SafeStackFrameIterator::is_active()) {
+  if (SafeStackFrameIterator::is_active() ||
+      HEAP->gc_state() != Heap::NOT_IN_GC) {
     // If the we are currently iterating the safe stack the
     // arguments for frames are traversed as if they were
     // expression stack elements of the calling frame. The reason for
@@ -667,7 +670,7 @@
 
 void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
   ASSERT(functions->length() == 0);
-  Code* code_pointer = code();
+  Code* code_pointer = LookupCode(Isolate::Current());
   int offset = static_cast<int>(pc() - code_pointer->address());
   FrameSummary summary(receiver(),
                        JSFunction::cast(function()),
@@ -786,7 +789,7 @@
   // back to a slow search in this case to find the original optimized
   // code object.
   if (!code->contains(pc())) {
-    code = PcToCodeCache::GcSafeFindCodeForPc(pc());
+    code = Isolate::Current()->pc_to_code_cache()->GcSafeFindCodeForPc(pc());
   }
   ASSERT(code != NULL);
   ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
@@ -847,7 +850,8 @@
 
 
 Code* ArgumentsAdaptorFrame::unchecked_code() const {
-  return Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline);
+  return Isolate::Current()->builtins()->builtin(
+      Builtins::kArgumentsAdaptorTrampoline);
 }
 
 
@@ -1041,14 +1045,14 @@
   ASSERT(!it.done());
   StackHandler* handler = it.handler();
   ASSERT(handler->is_entry());
-  handler->Iterate(v, code());
+  handler->Iterate(v, LookupCode(Isolate::Current()));
 #ifdef DEBUG
   // Make sure that the entry frame does not contain more than one
   // stack handler.
   it.Advance();
   ASSERT(it.done());
 #endif
-  IteratePc(v, pc_address(), code());
+  IteratePc(v, pc_address(), LookupCode(Isolate::Current()));
 }
 
 
@@ -1065,7 +1069,7 @@
     v->VisitPointers(base, reinterpret_cast<Object**>(address));
     base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
     // Traverse the pointers in the handler itself.
-    handler->Iterate(v, code());
+    handler->Iterate(v, LookupCode(Isolate::Current()));
   }
   v->VisitPointers(base, limit);
 }
@@ -1073,7 +1077,7 @@
 
 void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
   IterateExpressions(v);
-  IteratePc(v, pc_address(), code());
+  IteratePc(v, pc_address(), LookupCode(Isolate::Current()));
   IterateArguments(v);
 }
 
@@ -1092,7 +1096,7 @@
   // Internal frames only have object pointers on the expression stack
   // as they never have any arguments.
   IterateExpressions(v);
-  IteratePc(v, pc_address(), code());
+  IteratePc(v, pc_address(), LookupCode(Isolate::Current()));
 }
 
 
@@ -1122,14 +1126,15 @@
 
 
 Code* PcToCodeCache::GcSafeFindCodeForPc(Address pc) {
+  Heap* heap = isolate_->heap();
   // Check if the pc points into a large object chunk.
-  LargeObjectChunk* chunk = Heap::lo_space()->FindChunkContainingPc(pc);
+  LargeObjectChunk* chunk = heap->lo_space()->FindChunkContainingPc(pc);
   if (chunk != NULL) return GcSafeCastToCode(chunk->GetObject(), pc);
 
   // Iterate through the 8K page until we reach the end or find an
   // object starting after the pc.
   Page* page = Page::FromAddress(pc);
-  HeapObjectIterator iterator(page, Heap::GcSafeSizeOfOldObjectFunction());
+  HeapObjectIterator iterator(page, heap->GcSafeSizeOfOldObjectFunction());
   HeapObject* previous = NULL;
   while (true) {
     HeapObject* next = iterator.next();
@@ -1142,14 +1147,14 @@
 
 
 PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) {
-  Counters::pc_to_code.Increment();
+  isolate_->counters()->pc_to_code()->Increment();
   ASSERT(IsPowerOf2(kPcToCodeCacheSize));
   uint32_t hash = ComputeIntegerHash(
       static_cast<uint32_t>(reinterpret_cast<uintptr_t>(pc)));
   uint32_t index = hash & (kPcToCodeCacheSize - 1);
   PcToCodeCacheEntry* entry = cache(index);
   if (entry->pc == pc) {
-    Counters::pc_to_code_cached.Increment();
+    isolate_->counters()->pc_to_code_cached()->Increment();
     ASSERT(entry->code == GcSafeFindCodeForPc(pc));
   } else {
     // Because this code may be interrupted by a profiling signal that
@@ -1176,11 +1181,8 @@
 }
 
 
-int JSCallerSavedCode(int n) {
-  static int reg_code[kNumJSCallerSaved];
-  static bool initialized = false;
-  if (!initialized) {
-    initialized = true;
+struct JSCallerSavedCodeData {
+  JSCallerSavedCodeData() {
     int i = 0;
     for (int r = 0; r < kNumRegs; r++)
       if ((kJSCallerSaved & (1 << r)) != 0)
@@ -1188,8 +1190,16 @@
 
     ASSERT(i == kNumJSCallerSaved);
   }
+  int reg_code[kNumJSCallerSaved];
+};
+
+
+static const JSCallerSavedCodeData kCallerSavedCodeData;
+
+
+int JSCallerSavedCode(int n) {
   ASSERT(0 <= n && n < kNumJSCallerSaved);
-  return reg_code[n];
+  return kCallerSavedCodeData.reg_code[n];
 }
 
 
diff --git a/src/frames.h b/src/frames.h
index 5378709..bee95cc 100644
--- a/src/frames.h
+++ b/src/frames.h
@@ -28,6 +28,7 @@
 #ifndef V8_FRAMES_H_
 #define V8_FRAMES_H_
 
+#include "handles.h"
 #include "safepoint-table.h"
 
 namespace v8 {
@@ -44,11 +45,10 @@
 
 // Forward declarations.
 class StackFrameIterator;
-class Top;
 class ThreadLocalTop;
+class Isolate;
 
-
-class PcToCodeCache : AllStatic {
+class PcToCodeCache {
  public:
   struct PcToCodeCacheEntry {
     Address pc;
@@ -56,22 +56,28 @@
     SafepointEntry safepoint_entry;
   };
 
-  static PcToCodeCacheEntry* cache(int index) {
-    return &cache_[index];
+  explicit PcToCodeCache(Isolate* isolate) : isolate_(isolate) {
+    Flush();
   }
 
-  static Code* GcSafeFindCodeForPc(Address pc);
-  static Code* GcSafeCastToCode(HeapObject* object, Address pc);
+  Code* GcSafeFindCodeForPc(Address pc);
+  Code* GcSafeCastToCode(HeapObject* object, Address pc);
 
-  static void FlushPcToCodeCache() {
+  void Flush() {
     memset(&cache_[0], 0, sizeof(cache_));
   }
 
-  static PcToCodeCacheEntry* GetCacheEntry(Address pc);
+  PcToCodeCacheEntry* GetCacheEntry(Address pc);
 
  private:
+  PcToCodeCacheEntry* cache(int index) { return &cache_[index]; }
+
+  Isolate* isolate_;
+
   static const int kPcToCodeCacheSize = 1024;
-  static PcToCodeCacheEntry cache_[kPcToCodeCacheSize];
+  PcToCodeCacheEntry cache_[kPcToCodeCacheSize];
+
+  DISALLOW_COPY_AND_ASSIGN(PcToCodeCache);
 };
 
 
@@ -199,12 +205,12 @@
   virtual Code* unchecked_code() const = 0;
 
   // Get the code associated with this frame.
-  Code* code() const { return GetContainingCode(pc()); }
+  Code* LookupCode(Isolate* isolate) const {
+    return GetContainingCode(isolate, pc());
+  }
 
   // Get the code object that contains the given pc.
-  static Code* GetContainingCode(Address pc) {
-    return PcToCodeCache::GetCacheEntry(pc)->code;
-  }
+  static inline Code* GetContainingCode(Isolate* isolate, Address pc);
 
   // Get the code object containing the given pc and fill in the
   // safepoint entry and the number of stack slots. The pc must be at
@@ -452,12 +458,6 @@
   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;
 
@@ -618,7 +618,7 @@
   // 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);
+  StackFrameIterator(Isolate* isolate, bool use_top, Address fp, Address sp);
 
   StackFrame* frame() const {
     ASSERT(!done());
@@ -681,6 +681,13 @@
     if (!done()) Advance();
   }
 
+  JavaScriptFrameIteratorTemp(Isolate* isolate,
+                              Address fp, Address sp,
+                              Address low_bound, Address high_bound) :
+      iterator_(isolate, fp, sp, low_bound, high_bound) {
+    if (!done()) Advance();
+  }
+
   inline JavaScriptFrame* frame() const;
 
   bool done() const { return iterator_.done(); }
@@ -718,7 +725,8 @@
 
 class SafeStackFrameIterator BASE_EMBEDDED {
  public:
-  SafeStackFrameIterator(Address fp, Address sp,
+  SafeStackFrameIterator(Isolate* isolate,
+                         Address fp, Address sp,
                          Address low_bound, Address high_bound);
 
   StackFrame* frame() const {
@@ -768,7 +776,8 @@
   bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
   bool IsValidFrame(StackFrame* frame) const;
   bool IsValidCaller(StackFrame* frame);
-  static bool IsValidTop(Address low_bound, Address high_bound);
+  static bool IsValidTop(Isolate* isolate,
+                         Address low_bound, Address high_bound);
 
   // This is a nasty hack to make sure the active count is incremented
   // before the constructor for the embedded iterator is invoked. This
@@ -782,6 +791,7 @@
   };
 
   ActiveCountMaintainer maintainer_;
+  // TODO(isolates): this is dangerous.
   static int active_count_;
   StackAddressValidator stack_validator_;
   const bool is_valid_top_;
@@ -799,7 +809,8 @@
 
 class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
  public:
-  explicit SafeStackTraceFrameIterator(Address fp, Address sp,
+  explicit SafeStackTraceFrameIterator(Isolate* isolate,
+                                       Address fp, Address sp,
                                        Address low_bound, Address high_bound);
   void Advance();
 };
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index b3dc95b..d509cd5 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -275,10 +275,11 @@
 #define __ ACCESS_MASM(masm())
 
 bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
+  Isolate* isolate = info->isolate();
   Handle<Script> script = info->script();
   if (!script->IsUndefined() && !script->source()->IsUndefined()) {
     int len = String::cast(script->source())->length();
-    Counters::total_full_codegen_source_size.Increment(len);
+    isolate->counters()->total_full_codegen_source_size()->Increment(len);
   }
   if (FLAG_trace_codegen) {
     PrintF("Full Compiler - ");
@@ -293,7 +294,7 @@
   FullCodeGenerator cgen(&masm);
   cgen.Generate(info);
   if (cgen.HasStackOverflow()) {
-    ASSERT(!Top::has_pending_exception());
+    ASSERT(!isolate->has_pending_exception());
     return false;
   }
   unsigned table_offset = cgen.EmitStackCheckTable();
@@ -343,7 +344,8 @@
   if (!info_->HasDeoptimizationSupport()) return;
   int length = bailout_entries_.length();
   Handle<DeoptimizationOutputData> data =
-      Factory::NewDeoptimizationOutputData(length, TENURED);
+      isolate()->factory()->
+      NewDeoptimizationOutputData(length, TENURED);
   for (int i = 0; i < length; i++) {
     data->SetAstId(i, Smi::FromInt(bailout_entries_[i].id));
     data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state));
@@ -545,7 +547,8 @@
   // Compute array of global variable and function declarations.
   // Do nothing in case of no declared global functions or variables.
   if (globals > 0) {
-    Handle<FixedArray> array = Factory::NewFixedArray(2 * globals, TENURED);
+    Handle<FixedArray> array =
+        isolate()->factory()->NewFixedArray(2 * globals, TENURED);
     for (int j = 0, i = 0; i < length; i++) {
       Declaration* decl = declarations->at(i);
       Variable* var = decl->proxy()->var();
@@ -596,7 +599,7 @@
 void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
   if (FLAG_debug_info) {
 #ifdef ENABLE_DEBUGGER_SUPPORT
-    if (!Debugger::IsDebuggerActive()) {
+    if (!isolate()->debugger()->IsDebuggerActive()) {
       CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
     } else {
       // Check if the statement will be breakable without adding a debug break
@@ -624,7 +627,7 @@
 void FullCodeGenerator::SetExpressionPosition(Expression* expr, int pos) {
   if (FLAG_debug_info) {
 #ifdef ENABLE_DEBUGGER_SUPPORT
-    if (!Debugger::IsDebuggerActive()) {
+    if (!isolate()->debugger()->IsDebuggerActive()) {
       CodeGenerator::RecordPositions(masm_, pos);
     } else {
       // Check if the expression will be breakable without adding a debug break
@@ -694,7 +697,7 @@
 void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) {
   ZoneList<Expression*>* args = node->arguments();
   Handle<String> name = node->name();
-  Runtime::Function* function = node->function();
+  const Runtime::Function* function = node->function();
   ASSERT(function != NULL);
   ASSERT(function->intrinsic_type == Runtime::INLINE);
   InlineFunctionGenerator generator =
diff --git a/src/full-codegen.h b/src/full-codegen.h
index 5fb11b4..d6ed1b9 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -501,9 +501,9 @@
 
   Handle<Script> script() { return info_->script(); }
   bool is_eval() { return info_->is_eval(); }
-  bool is_strict() { return function()->strict_mode(); }
+  bool is_strict_mode() { return function()->strict_mode(); }
   StrictModeFlag strict_mode_flag() {
-    return is_strict() ? kStrictMode : kNonStrictMode;
+    return is_strict_mode() ? kStrictMode : kNonStrictMode;
   }
   FunctionLiteral* function() { return info_->function(); }
   Scope* scope() { return info_->scope(); }
@@ -553,6 +553,8 @@
       codegen_->set_new_context(old_);
     }
 
+    Isolate* isolate() const { return codegen_->isolate(); }
+
     // Convert constant control flow (true or false) to the result expected for
     // this expression context.
     virtual void Plug(bool flag) const = 0;
diff --git a/src/func-name-inferrer.cc b/src/func-name-inferrer.cc
index f12d026..c094251 100644
--- a/src/func-name-inferrer.cc
+++ b/src/func-name-inferrer.cc
@@ -38,21 +38,22 @@
   // 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))) {
+  if (name->length() > 0 && Runtime::IsUpperCaseChar(
+      Isolate::Current()->runtime_state(), name->Get(0))) {
     names_stack_.Add(name);
   }
 }
 
 
 void FuncNameInferrer::PushLiteralName(Handle<String> name) {
-  if (IsOpen() && !Heap::prototype_symbol()->Equals(*name)) {
+  if (IsOpen() && !HEAP->prototype_symbol()->Equals(*name)) {
     names_stack_.Add(name);
   }
 }
 
 
 void FuncNameInferrer::PushVariableName(Handle<String> name) {
-  if (IsOpen() && !Heap::result_symbol()->Equals(*name)) {
+  if (IsOpen() && !HEAP->result_symbol()->Equals(*name)) {
     names_stack_.Add(name);
   }
 }
@@ -60,7 +61,7 @@
 
 Handle<String> FuncNameInferrer::MakeNameFromStack() {
   if (names_stack_.is_empty()) {
-    return Factory::empty_string();
+    return FACTORY->empty_string();
   } else {
     return MakeNameFromStackHelper(1, names_stack_.at(0));
   }
@@ -72,8 +73,8 @@
   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));
+    Handle<String> curr = FACTORY->NewConsString(dot_, names_stack_.at(pos));
+    return MakeNameFromStackHelper(pos + 1, FACTORY->NewConsString(prev, curr));
   }
 }
 
diff --git a/src/func-name-inferrer.h b/src/func-name-inferrer.h
index a35034e..5aa2b35 100644
--- a/src/func-name-inferrer.h
+++ b/src/func-name-inferrer.h
@@ -47,7 +47,7 @@
       : entries_stack_(10),
         names_stack_(5),
         funcs_to_infer_(4),
-        dot_(Factory::NewStringFromAscii(CStrVector("."))) {
+        dot_(FACTORY->NewStringFromAscii(CStrVector("."))) {
   }
 
   // Returns whether we have entered name collection state.
diff --git a/src/gdb-jit.cc b/src/gdb-jit.cc
index 5136ded..c8dbf5d 100644
--- a/src/gdb-jit.cc
+++ b/src/gdb-jit.cc
@@ -26,6 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #ifdef ENABLE_GDB_JIT_INTERFACE
+#include "v8.h"
 #include "gdb-jit.h"
 
 #include "bootstrapper.h"
diff --git a/src/global-handles.cc b/src/global-handles.cc
index 18cdc5a..4d13859 100644
--- a/src/global-handles.cc
+++ b/src/global-handles.cc
@@ -35,12 +35,19 @@
 namespace v8 {
 namespace internal {
 
+
+ObjectGroup::~ObjectGroup() {
+  if (info_ != NULL) info_->Dispose();
+}
+
+
 class GlobalHandles::Node : public Malloced {
  public:
 
   void Initialize(Object* object) {
     // Set the initial value of the handle.
     object_ = object;
+    class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
     state_  = NORMAL;
     parameter_or_next_free_.parameter = NULL;
     callback_ = NULL;
@@ -57,7 +64,7 @@
   }
 
   ~Node() {
-    if (state_ != DESTROYED) Destroy();
+    if (state_ != DESTROYED) Destroy(Isolate::Current()->global_handles());
 #ifdef DEBUG
     // Zap the values for eager trapping.
     object_ = NULL;
@@ -66,11 +73,11 @@
 #endif
   }
 
-  void Destroy() {
+  void Destroy(GlobalHandles* global_handles) {
     if (state_ == WEAK || IsNearDeath()) {
-      GlobalHandles::number_of_weak_handles_--;
+      global_handles->number_of_weak_handles_--;
       if (object_->IsJSGlobalObject()) {
-        GlobalHandles::number_of_global_object_weak_handles_--;
+        global_handles->number_of_global_object_weak_handles_--;
       }
     }
     state_ = DESTROYED;
@@ -101,13 +108,15 @@
   Handle<Object> handle() { return Handle<Object>(&object_); }
 
   // Make this handle weak.
-  void MakeWeak(void* parameter, WeakReferenceCallback callback) {
-    LOG(HandleEvent("GlobalHandle::MakeWeak", handle().location()));
+  void MakeWeak(GlobalHandles* global_handles, void* parameter,
+                WeakReferenceCallback callback) {
+    LOG(global_handles->isolate(),
+        HandleEvent("GlobalHandle::MakeWeak", handle().location()));
     ASSERT(state_ != DESTROYED);
     if (state_ != WEAK && !IsNearDeath()) {
-      GlobalHandles::number_of_weak_handles_++;
+      global_handles->number_of_weak_handles_++;
       if (object_->IsJSGlobalObject()) {
-        GlobalHandles::number_of_global_object_weak_handles_++;
+        global_handles->number_of_global_object_weak_handles_++;
       }
     }
     state_ = WEAK;
@@ -115,13 +124,14 @@
     callback_ = callback;
   }
 
-  void ClearWeakness() {
-    LOG(HandleEvent("GlobalHandle::ClearWeakness", handle().location()));
+  void ClearWeakness(GlobalHandles* global_handles) {
+    LOG(global_handles->isolate(),
+        HandleEvent("GlobalHandle::ClearWeakness", handle().location()));
     ASSERT(state_ != DESTROYED);
     if (state_ == WEAK || IsNearDeath()) {
-      GlobalHandles::number_of_weak_handles_--;
+      global_handles->number_of_weak_handles_--;
       if (object_->IsJSGlobalObject()) {
-        GlobalHandles::number_of_global_object_weak_handles_--;
+        global_handles->number_of_global_object_weak_handles_--;
       }
     }
     state_ = NORMAL;
@@ -137,6 +147,14 @@
     return state_ == WEAK;
   }
 
+  bool CanBeRetainer() {
+    return state_ != DESTROYED && state_ != NEAR_DEATH;
+  }
+
+  void SetWrapperClassId(uint16_t class_id) {
+    class_id_ = class_id;
+  }
+
   // Returns the id for this weak handle.
   void set_parameter(void* parameter) {
     ASSERT(state_ != DESTROYED);
@@ -150,12 +168,13 @@
   // Returns the callback for this weak handle.
   WeakReferenceCallback callback() { return callback_; }
 
-  bool PostGarbageCollectionProcessing() {
+  bool PostGarbageCollectionProcessing(Isolate* isolate,
+                                       GlobalHandles* global_handles) {
     if (state_ != Node::PENDING) return false;
-    LOG(HandleEvent("GlobalHandle::Processing", handle().location()));
+    LOG(isolate, HandleEvent("GlobalHandle::Processing", handle().location()));
     WeakReferenceCallback func = callback();
     if (func == NULL) {
-      Destroy();
+      Destroy(global_handles);
       return false;
     }
     void* par = parameter();
@@ -167,9 +186,9 @@
       // Forbid reuse of destroyed nodes as they might be already deallocated.
       // It's fine though to reuse nodes that were destroyed in weak callback
       // as those cannot be deallocated until we are back from the callback.
-      set_first_free(NULL);
-      if (first_deallocated()) {
-        first_deallocated()->set_next(head());
+      global_handles->set_first_free(NULL);
+      if (global_handles->first_deallocated()) {
+        global_handles->first_deallocated()->set_next(global_handles->head());
       }
       // Check that we are not passing a finalized external string to
       // the callback.
@@ -178,7 +197,7 @@
       ASSERT(!object_->IsExternalTwoByteString() ||
              ExternalTwoByteString::cast(object_)->resource() != NULL);
       // Leaving V8.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       func(object, par);
     }
     // Absense of explicit cleanup or revival of weak handle
@@ -190,6 +209,8 @@
   // Place the handle address first to avoid offset computation.
   Object* object_;  // Storage for object pointer.
 
+  uint16_t class_id_;
+
   // Transition diagram:
   // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED }
   enum State {
@@ -199,7 +220,7 @@
     NEAR_DEATH,  // Callback has informed the handle is near death.
     DESTROYED
   };
-  State state_;
+  State state_ : 4;  // Need one more bit for MSVC as it treats enums as signed.
 
  private:
   // Handle specific callback.
@@ -219,7 +240,7 @@
 };
 
 
-class GlobalHandles::Pool BASE_EMBEDDED {
+class GlobalHandles::Pool {
   public:
     Pool() {
       current_ = new Chunk();
@@ -277,11 +298,27 @@
 };
 
 
-static GlobalHandles::Pool pool_;
+GlobalHandles::GlobalHandles(Isolate* isolate)
+    : isolate_(isolate),
+      number_of_weak_handles_(0),
+      number_of_global_object_weak_handles_(0),
+      head_(NULL),
+      first_free_(NULL),
+      first_deallocated_(NULL),
+      pool_(new Pool()),
+      post_gc_processing_count_(0),
+      object_groups_(4) {
+}
+
+
+GlobalHandles::~GlobalHandles() {
+  delete pool_;
+  pool_ = 0;
+}
 
 
 Handle<Object> GlobalHandles::Create(Object* value) {
-  Counters::global_handles.Increment();
+  isolate_->counters()->global_handles()->Increment();
   Node* result;
   if (first_free()) {
     // Take the first node in the free list.
@@ -295,7 +332,7 @@
     set_head(result);
   } else {
     // Allocate a new node.
-    result = pool_.Allocate();
+    result = pool_->Allocate();
     result->set_next(head());
     set_head(result);
   }
@@ -305,10 +342,10 @@
 
 
 void GlobalHandles::Destroy(Object** location) {
-  Counters::global_handles.Decrement();
+  isolate_->counters()->global_handles()->Decrement();
   if (location == NULL) return;
   Node* node = Node::FromLocation(location);
-  node->Destroy();
+  node->Destroy(this);
   // Link the destroyed.
   node->set_next_free(first_free());
   set_first_free(node);
@@ -318,12 +355,12 @@
 void GlobalHandles::MakeWeak(Object** location, void* parameter,
                              WeakReferenceCallback callback) {
   ASSERT(callback != NULL);
-  Node::FromLocation(location)->MakeWeak(parameter, callback);
+  Node::FromLocation(location)->MakeWeak(this, parameter, callback);
 }
 
 
 void GlobalHandles::ClearWeakness(Object** location) {
-  Node::FromLocation(location)->ClearWeakness();
+  Node::FromLocation(location)->ClearWeakness(this);
 }
 
 
@@ -337,6 +374,11 @@
 }
 
 
+void GlobalHandles::SetWrapperClassId(Object** location, uint16_t class_id) {
+  Node::FromLocation(location)->SetWrapperClassId(class_id);
+}
+
+
 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) {
   // Traversal of GC roots in the global handle list that are marked as
   // WEAK or PENDING.
@@ -365,27 +407,26 @@
     if (current->state_ == Node::WEAK) {
       if (f(&current->object_)) {
         current->state_ = Node::PENDING;
-        LOG(HandleEvent("GlobalHandle::Pending", current->handle().location()));
+        LOG(isolate_,
+            HandleEvent("GlobalHandle::Pending", current->handle().location()));
       }
     }
   }
 }
 
 
-int post_gc_processing_count = 0;
-
 bool 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);
-  const int initial_post_gc_processing_count = ++post_gc_processing_count;
+  ASSERT(isolate_->heap()->gc_state() == Heap::NOT_IN_GC);
+  const int initial_post_gc_processing_count = ++post_gc_processing_count_;
   bool next_gc_likely_to_collect_more = false;
   Node** p = &head_;
   while (*p != NULL) {
-    if ((*p)->PostGarbageCollectionProcessing()) {
-      if (initial_post_gc_processing_count != post_gc_processing_count) {
+    if ((*p)->PostGarbageCollectionProcessing(isolate_, this)) {
+      if (initial_post_gc_processing_count != post_gc_processing_count_) {
         // Weak callback triggered another GC and another round of
         // PostGarbageCollection processing.  The current node might
         // have been deleted in that round, so we need to bail out (or
@@ -435,22 +476,25 @@
 }
 
 
+void GlobalHandles::IterateAllRootsWithClassIds(ObjectVisitor* v) {
+  for (Node* current = head_; current != NULL; current = current->next()) {
+    if (current->class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId &&
+        current->CanBeRetainer()) {
+      v->VisitEmbedderReference(&current->object_, current->class_id_);
+    }
+  }
+}
+
+
 void GlobalHandles::TearDown() {
   // Reset all the lists.
   set_head(NULL);
   set_first_free(NULL);
   set_first_deallocated(NULL);
-  pool_.Release();
+  pool_->Release();
 }
 
 
-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;
-GlobalHandles::Node* GlobalHandles::first_deallocated_ = NULL;
-
 void GlobalHandles::RecordStats(HeapStats* stats) {
   *stats->global_handle_count = 0;
   *stats->weak_global_handle_count = 0;
@@ -509,26 +553,44 @@
 
 #endif
 
-List<ObjectGroup*>* GlobalHandles::ObjectGroups() {
-  // Lazily initialize the list to avoid startup time static constructors.
-  static List<ObjectGroup*> groups(4);
-  return &groups;
+
+
+void GlobalHandles::AddObjectGroup(Object*** handles,
+                                   size_t length,
+                                   v8::RetainedObjectInfo* info) {
+  ObjectGroup* new_entry = new ObjectGroup(length, info);
+  for (size_t i = 0; i < length; ++i) {
+    new_entry->objects_.Add(handles[i]);
+  }
+  object_groups_.Add(new_entry);
 }
 
-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::AddImplicitReferences(HeapObject* parent,
+                                          Object*** children,
+                                          size_t length) {
+  ImplicitRefGroup* new_entry = new ImplicitRefGroup(parent, length);
+  for (size_t i = 0; i < length; ++i) {
+    new_entry->children_.Add(children[i]);
+  }
+  implicit_ref_groups_.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);
+  for (int i = 0; i < object_groups_.length(); i++) {
+    delete object_groups_.at(i);
   }
-  object_groups->Clear();
+  object_groups_.Clear();
 }
 
+
+void GlobalHandles::RemoveImplicitRefGroups() {
+  for (int i = 0; i < implicit_ref_groups_.length(); i++) {
+    delete implicit_ref_groups_.at(i);
+  }
+  implicit_ref_groups_.Clear();
+}
+
+
 } }  // namespace v8::internal
diff --git a/src/global-handles.h b/src/global-handles.h
index 37b2b44..a6afb2d 100644
--- a/src/global-handles.h
+++ b/src/global-handles.h
@@ -39,31 +39,54 @@
 // 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_(static_cast<int>(capacity)) { }
+  ObjectGroup(size_t capacity, v8::RetainedObjectInfo* info)
+      : objects_(static_cast<int>(capacity)),
+        info_(info) { }
+  ~ObjectGroup();
 
   List<Object**> objects_;
+  v8::RetainedObjectInfo* info_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ObjectGroup);
+};
+
+
+// An implicit references group consists of two parts: a parent object and
+// a list of children objects.  If the parent is alive, all the children
+// are alive too.
+class ImplicitRefGroup : public Malloced {
+ public:
+  ImplicitRefGroup() : children_(4) {}
+  ImplicitRefGroup(HeapObject* parent, size_t capacity)
+      : parent_(parent),
+        children_(static_cast<int>(capacity)) { }
+
+  HeapObject* parent_;
+  List<Object**> children_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ImplicitRefGroup);
 };
 
 
 typedef void (*WeakReferenceGuest)(Object* object, void* parameter);
 
-class GlobalHandles : public AllStatic {
+class GlobalHandles {
  public:
+  ~GlobalHandles();
+
   // Creates a new global handle that is alive until Destroy is called.
-  static Handle<Object> Create(Object* value);
+  Handle<Object> Create(Object* value);
 
   // Destroy a global handle.
-  static void Destroy(Object** location);
+  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
@@ -71,23 +94,25 @@
   // 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);
+  void MakeWeak(Object** location,
+                void* parameter,
+                WeakReferenceCallback callback);
+
+  static void SetWrapperClassId(Object** location, uint16_t class_id);
 
   // Returns the current number of weak handles.
-  static int NumberOfWeakHandles() { return number_of_weak_handles_; }
+  int NumberOfWeakHandles() { return number_of_weak_handles_; }
 
-  static void RecordStats(HeapStats* stats);
+  void RecordStats(HeapStats* stats);
 
   // Returns the current number of weak handles to global objects.
   // These handles are also included in NumberOfWeakHandles().
-  static int NumberOfGlobalObjectWeakHandles() {
+  int NumberOfGlobalObjectWeakHandles() {
     return number_of_global_object_weak_handles_;
   }
 
   // Clear the weakness of a global handle.
-  static void ClearWeakness(Object** location);
+  void ClearWeakness(Object** location);
 
   // Tells whether global handle is near death.
   static bool IsNearDeath(Object** location);
@@ -97,65 +122,89 @@
 
   // Process pending weak handles.
   // Returns true if next major GC is likely to collect more garbage.
-  static bool PostGarbageCollectionProcessing();
+  bool PostGarbageCollectionProcessing();
 
   // Iterates over all strong handles.
-  static void IterateStrongRoots(ObjectVisitor* v);
+  void IterateStrongRoots(ObjectVisitor* v);
 
   // Iterates over all handles.
-  static void IterateAllRoots(ObjectVisitor* v);
+  void IterateAllRoots(ObjectVisitor* v);
+
+  // Iterates over all handles that have embedder-assigned class ID.
+  void IterateAllRootsWithClassIds(ObjectVisitor* v);
 
   // Iterates over all weak roots in heap.
-  static void IterateWeakRoots(ObjectVisitor* v);
+  void IterateWeakRoots(ObjectVisitor* v);
 
   // Iterates over weak roots that are bound to a given callback.
-  static void IterateWeakRoots(WeakReferenceGuest f,
-                               WeakReferenceCallback callback);
+  void IterateWeakRoots(WeakReferenceGuest f,
+                        WeakReferenceCallback callback);
 
   // Find all weak handles satisfying the callback predicate, mark
   // them as pending.
-  static void IdentifyWeakHandles(WeakSlotCallback f);
+  void IdentifyWeakHandles(WeakSlotCallback f);
 
   // Add an object group.
-  // Should only used in GC callback function before a collection.
+  // Should be 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);
+  void AddObjectGroup(Object*** handles,
+                      size_t length,
+                      v8::RetainedObjectInfo* info);
+
+  // Add an implicit references' group.
+  // Should be only used in GC callback function before a collection.
+  // All groups are destroyed after a mark-compact collection.
+  void AddImplicitReferences(HeapObject* parent,
+                             Object*** children,
+                             size_t length);
 
   // Returns the object groups.
-  static List<ObjectGroup*>* ObjectGroups();
+  List<ObjectGroup*>* object_groups() { return &object_groups_; }
+
+  // Returns the implicit references' groups.
+  List<ImplicitRefGroup*>* implicit_ref_groups() {
+    return &implicit_ref_groups_;
+  }
 
   // Remove bags, this should only happen after GC.
-  static void RemoveObjectGroups();
+  void RemoveObjectGroups();
+  void RemoveImplicitRefGroups();
 
   // Tear down the global handle structure.
-  static void TearDown();
+  void TearDown();
+
+  Isolate* isolate() { return isolate_; }
 
 #ifdef DEBUG
-  static void PrintStats();
-  static void Print();
+  void PrintStats();
+  void Print();
 #endif
   class Pool;
  private:
+  explicit GlobalHandles(Isolate* isolate);
+
   // Internal node structure, one for each global handle.
   class Node;
 
+  Isolate* isolate_;
+
   // Field always containing the number of weak and near-death handles.
-  static int number_of_weak_handles_;
+  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_;
+  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; }
+  Node* head_;
+  Node* head() { return head_; }
+  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; }
+  Node* first_free_;
+  Node* first_free() { return first_free_; }
+  void set_first_free(Node* value) { first_free_ = value; }
 
   // List of deallocated nodes.
   // Deallocated nodes form a prefix of all the nodes and
@@ -168,11 +217,20 @@
   //    node          node        ...         node       node
   //      .next      -> .next ->                .next ->
   //   <- .next_free <- .next_free           <- .next_free
-  static Node* first_deallocated_;
-  static Node* first_deallocated() { return first_deallocated_; }
-  static void set_first_deallocated(Node* value) {
+  Node* first_deallocated_;
+  Node* first_deallocated() { return first_deallocated_; }
+  void set_first_deallocated(Node* value) {
     first_deallocated_ = value;
   }
+
+  Pool* pool_;
+  int post_gc_processing_count_;
+  List<ObjectGroup*> object_groups_;
+  List<ImplicitRefGroup*> implicit_ref_groups_;
+
+  friend class Isolate;
+
+  DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
 };
 
 
diff --git a/src/globals.h b/src/globals.h
index 9b24bf6..5ab9806 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -54,7 +54,7 @@
 #if CAN_USE_UNALIGNED_ACCESSES
 #define V8_HOST_CAN_READ_UNALIGNED 1
 #endif
-#elif defined(_MIPS_ARCH_MIPS32R2)
+#elif defined(__MIPSEL__)
 #define V8_HOST_ARCH_MIPS 1
 #define V8_HOST_ARCH_32_BIT 1
 #else
@@ -72,7 +72,7 @@
 #define V8_TARGET_ARCH_IA32 1
 #elif defined(__ARMEL__)
 #define V8_TARGET_ARCH_ARM 1
-#elif defined(_MIPS_ARCH_MIPS32R2)
+#elif defined(__MIPSEL__)
 #define V8_TARGET_ARCH_MIPS 1
 #else
 #error Target architecture was not detected as supported by v8
diff --git a/src/handles-inl.h b/src/handles-inl.h
index c0f2fda..a5c81ce 100644
--- a/src/handles-inl.h
+++ b/src/handles-inl.h
@@ -29,17 +29,33 @@
 #ifndef V8_HANDLES_INL_H_
 #define V8_HANDLES_INL_H_
 
+#include "api.h"
 #include "apiutils.h"
 #include "handles.h"
-#include "api.h"
+#include "isolate.h"
 
 namespace v8 {
 namespace internal {
 
+inline Isolate* GetIsolateForHandle(Object* obj) {
+  return Isolate::Current();
+}
+
+inline Isolate* GetIsolateForHandle(HeapObject* obj) {
+  return obj->GetIsolate();
+}
+
 template<typename T>
 Handle<T>::Handle(T* obj) {
   ASSERT(!obj->IsFailure());
-  location_ = HandleScope::CreateHandle(obj);
+  location_ = HandleScope::CreateHandle(obj, GetIsolateForHandle(obj));
+}
+
+
+template<typename T>
+Handle<T>::Handle(T* obj, Isolate* isolate) {
+  ASSERT(!obj->IsFailure());
+  location_ = HandleScope::CreateHandle(obj, isolate);
 }
 
 
@@ -51,10 +67,91 @@
 }
 
 
+HandleScope::HandleScope() {
+  Isolate* isolate = Isolate::Current();
+  v8::ImplementationUtilities::HandleScopeData* current =
+      isolate->handle_scope_data();
+  isolate_ = isolate;
+  prev_next_ = current->next;
+  prev_limit_ = current->limit;
+  current->level++;
+}
+
+
+HandleScope::HandleScope(Isolate* isolate) {
+  ASSERT(isolate == Isolate::Current());
+  v8::ImplementationUtilities::HandleScopeData* current =
+      isolate->handle_scope_data();
+  isolate_ = isolate;
+  prev_next_ = current->next;
+  prev_limit_ = current->limit;
+  current->level++;
+}
+
+
+HandleScope::~HandleScope() {
+  CloseScope();
+}
+
+void HandleScope::CloseScope() {
+  ASSERT(isolate_ == Isolate::Current());
+  v8::ImplementationUtilities::HandleScopeData* current =
+      isolate_->handle_scope_data();
+  current->next = prev_next_;
+  current->level--;
+  if (current->limit != prev_limit_) {
+    current->limit = prev_limit_;
+    DeleteExtensions(isolate_);
+  }
+#ifdef DEBUG
+  ZapRange(prev_next_, prev_limit_);
+#endif
+}
+
+
+template <typename T>
+Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) {
+  T* value = *handle_value;
+  // Throw away all handles in the current scope.
+  CloseScope();
+  v8::ImplementationUtilities::HandleScopeData* current =
+      isolate_->handle_scope_data();
+  // Allocate one handle in the parent scope.
+  ASSERT(current->level > 0);
+  Handle<T> result(CreateHandle<T>(value, isolate_));
+  // Reinitialize the current scope (so that it's ready
+  // to be used or closed again).
+  prev_next_ = current->next;
+  prev_limit_ = current->limit;
+  current->level++;
+  return result;
+}
+
+
+template <typename T>
+T** HandleScope::CreateHandle(T* value, Isolate* isolate) {
+  ASSERT(isolate == Isolate::Current());
+  v8::ImplementationUtilities::HandleScopeData* current =
+      isolate->handle_scope_data();
+
+  internal::Object** cur = current->next;
+  if (cur == current->limit) cur = Extend();
+  // Update the current next field, set the value in the created
+  // handle, and return the result.
+  ASSERT(cur < current->limit);
+  current->next = cur + 1;
+
+  T** result = reinterpret_cast<T**>(cur);
+  *result = value;
+  return result;
+}
+
+
 #ifdef DEBUG
 inline NoHandleAllocation::NoHandleAllocation() {
   v8::ImplementationUtilities::HandleScopeData* current =
-      v8::ImplementationUtilities::CurrentHandleScope();
+      Isolate::Current()->handle_scope_data();
+
   // Shrink the current handle scope to make it impossible to do
   // handle allocations without an explicit handle scope.
   current->limit = current->next;
@@ -67,10 +164,10 @@
 inline NoHandleAllocation::~NoHandleAllocation() {
   // Restore state in current handle scope to re-enable handle
   // allocations.
-  v8::ImplementationUtilities::HandleScopeData* current =
-      v8::ImplementationUtilities::CurrentHandleScope();
-  ASSERT_EQ(0, current->level);
-  current->level = level_;
+  v8::ImplementationUtilities::HandleScopeData* data =
+      Isolate::Current()->handle_scope_data();
+  ASSERT_EQ(0, data->level);
+  data->level = level_;
 }
 #endif
 
diff --git a/src/handles.cc b/src/handles.cc
index efef095..97a06d9 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -45,57 +45,62 @@
 namespace internal {
 
 
-v8::ImplementationUtilities::HandleScopeData HandleScope::current_ =
-    { NULL, NULL, 0 };
-
-
 int HandleScope::NumberOfHandles() {
-  int n = HandleScopeImplementer::instance()->blocks()->length();
+  Isolate* isolate = Isolate::Current();
+  HandleScopeImplementer* impl = isolate->handle_scope_implementer();
+  int n = impl->blocks()->length();
   if (n == 0) return 0;
   return ((n - 1) * kHandleBlockSize) + static_cast<int>(
-      (current_.next - HandleScopeImplementer::instance()->blocks()->last()));
+      (isolate->handle_scope_data()->next - impl->blocks()->last()));
 }
 
 
 Object** HandleScope::Extend() {
-  Object** result = current_.next;
+  Isolate* isolate = Isolate::Current();
+  v8::ImplementationUtilities::HandleScopeData* current =
+      isolate->handle_scope_data();
 
-  ASSERT(result == current_.limit);
+  Object** 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_.level == 0) {
+  if (current->level == 0) {
     Utils::ReportApiFailure("v8::HandleScope::CreateHandle()",
                             "Cannot create a handle without a HandleScope");
     return NULL;
   }
-  HandleScopeImplementer* impl = HandleScopeImplementer::instance();
+  HandleScopeImplementer* impl = isolate->handle_scope_implementer();
   // 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()) {
     Object** limit = &impl->blocks()->last()[kHandleBlockSize];
-    if (current_.limit != limit) {
-      current_.limit = limit;
-      ASSERT(limit - current_.next < kHandleBlockSize);
+    if (current->limit != limit) {
+      current->limit = limit;
+      ASSERT(limit - current->next < kHandleBlockSize);
     }
   }
 
   // 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 (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_.limit = &result[kHandleBlockSize];
+    current->limit = &result[kHandleBlockSize];
   }
 
   return result;
 }
 
 
-void HandleScope::DeleteExtensions() {
-  HandleScopeImplementer::instance()->DeleteExtensions(current_.limit);
+void HandleScope::DeleteExtensions(Isolate* isolate) {
+  ASSERT(isolate == Isolate::Current());
+  v8::ImplementationUtilities::HandleScopeData* current =
+      isolate->handle_scope_data();
+  isolate->handle_scope_implementer()->DeleteExtensions(current->limit);
 }
 
 
@@ -108,37 +113,44 @@
 
 
 Address HandleScope::current_level_address() {
-  return reinterpret_cast<Address>(&current_.level);
+  return reinterpret_cast<Address>(
+      &Isolate::Current()->handle_scope_data()->level);
 }
 
 
 Address HandleScope::current_next_address() {
-  return reinterpret_cast<Address>(&current_.next);
+  return reinterpret_cast<Address>(
+      &Isolate::Current()->handle_scope_data()->next);
 }
 
 
 Address HandleScope::current_limit_address() {
-  return reinterpret_cast<Address>(&current_.limit);
+  return reinterpret_cast<Address>(
+      &Isolate::Current()->handle_scope_data()->limit);
 }
 
 
 Handle<FixedArray> AddKeysFromJSArray(Handle<FixedArray> content,
                                       Handle<JSArray> array) {
-  CALL_HEAP_FUNCTION(content->AddKeysFromJSArray(*array), FixedArray);
+  CALL_HEAP_FUNCTION(content->GetIsolate(),
+                     content->AddKeysFromJSArray(*array), FixedArray);
 }
 
 
 Handle<FixedArray> UnionOfKeys(Handle<FixedArray> first,
                                Handle<FixedArray> second) {
-  CALL_HEAP_FUNCTION(first->UnionOfKeys(*second), FixedArray);
+  CALL_HEAP_FUNCTION(first->GetIsolate(),
+                     first->UnionOfKeys(*second), FixedArray);
 }
 
 
 Handle<JSGlobalProxy> ReinitializeJSGlobalProxy(
     Handle<JSFunction> constructor,
     Handle<JSGlobalProxy> global) {
-  CALL_HEAP_FUNCTION(Heap::ReinitializeJSGlobalProxy(*constructor, *global),
-                     JSGlobalProxy);
+  CALL_HEAP_FUNCTION(
+      constructor->GetIsolate(),
+      constructor->GetHeap()->ReinitializeJSGlobalProxy(*constructor, *global),
+      JSGlobalProxy);
 }
 
 
@@ -153,7 +165,8 @@
   func->shared()->set_expected_nof_properties(nof);
   if (func->has_initial_map()) {
     Handle<Map> new_initial_map =
-        Factory::CopyMapDropTransitions(Handle<Map>(func->initial_map()));
+        func->GetIsolate()->factory()->CopyMapDropTransitions(
+            Handle<Map>(func->initial_map()));
     new_initial_map->set_unused_property_fields(nof);
     func->set_initial_map(*new_initial_map);
   }
@@ -161,7 +174,8 @@
 
 
 void SetPrototypeProperty(Handle<JSFunction> func, Handle<JSObject> value) {
-  CALL_HEAP_FUNCTION_VOID(func->SetPrototype(*value));
+  CALL_HEAP_FUNCTION_VOID(func->GetIsolate(),
+                          func->SetPrototype(*value));
 }
 
 
@@ -193,20 +207,23 @@
 void NormalizeProperties(Handle<JSObject> object,
                          PropertyNormalizationMode mode,
                          int expected_additional_properties) {
-  CALL_HEAP_FUNCTION_VOID(object->NormalizeProperties(
-      mode,
-      expected_additional_properties));
+  CALL_HEAP_FUNCTION_VOID(object->GetIsolate(),
+                          object->NormalizeProperties(
+                              mode,
+                              expected_additional_properties));
 }
 
 
 void NormalizeElements(Handle<JSObject> object) {
-  CALL_HEAP_FUNCTION_VOID(object->NormalizeElements());
+  CALL_HEAP_FUNCTION_VOID(object->GetIsolate(),
+                          object->NormalizeElements());
 }
 
 
 void TransformToFastProperties(Handle<JSObject> object,
                                int unused_property_fields) {
   CALL_HEAP_FUNCTION_VOID(
+      object->GetIsolate(),
       object->TransformToFastProperties(unused_property_fields));
 }
 
@@ -215,24 +232,26 @@
                          uint32_t index,
                          Handle<Object> value,
                          PropertyDetails details) {
-  CALL_HEAP_FUNCTION_VOID(dictionary->Set(index, *value, details));
+  CALL_HEAP_FUNCTION_VOID(dictionary->GetIsolate(),
+                          dictionary->Set(index, *value, details));
 }
 
 
 void FlattenString(Handle<String> string) {
-  CALL_HEAP_FUNCTION_VOID(string->TryFlatten());
+  CALL_HEAP_FUNCTION_VOID(string->GetIsolate(), string->TryFlatten());
 }
 
 
 Handle<String> FlattenGetString(Handle<String> string) {
-  CALL_HEAP_FUNCTION(string->TryFlatten(), String);
+  CALL_HEAP_FUNCTION(string->GetIsolate(), string->TryFlatten(), String);
 }
 
 
 Handle<Object> SetPrototype(Handle<JSFunction> function,
                             Handle<Object> prototype) {
   ASSERT(function->should_have_prototype());
-  CALL_HEAP_FUNCTION(Accessors::FunctionSetPrototype(*function,
+  CALL_HEAP_FUNCTION(function->GetIsolate(),
+                     Accessors::FunctionSetPrototype(*function,
                                                      *prototype,
                                                      NULL),
                      Object);
@@ -244,7 +263,8 @@
                            Handle<Object> value,
                            PropertyAttributes attributes,
                            StrictModeFlag strict_mode) {
-  CALL_HEAP_FUNCTION(object->SetProperty(*key, *value, attributes, strict_mode),
+  CALL_HEAP_FUNCTION(object->GetIsolate(),
+                     object->SetProperty(*key, *value, attributes, strict_mode),
                      Object);
 }
 
@@ -254,8 +274,11 @@
                            Handle<Object> value,
                            PropertyAttributes attributes,
                            StrictModeFlag strict_mode) {
+  Isolate* isolate = Isolate::Current();
   CALL_HEAP_FUNCTION(
-      Runtime::SetObjectProperty(object, key, value, attributes, strict_mode),
+      isolate,
+      Runtime::SetObjectProperty(
+          isolate, object, key, value, attributes, strict_mode),
       Object);
 }
 
@@ -264,9 +287,11 @@
                                 Handle<Object> key,
                                 Handle<Object> value,
                                 PropertyAttributes attributes) {
+  Isolate* isolate = object->GetIsolate();
   CALL_HEAP_FUNCTION(
+      isolate,
       Runtime::ForceSetObjectProperty(
-          object, key, value, attributes),
+          isolate, object, key, value, attributes),
       Object);
 }
 
@@ -275,14 +300,18 @@
                                      Handle<String> key,
                                      Handle<Object> value,
                                      PropertyDetails details) {
-  CALL_HEAP_FUNCTION(object->SetNormalizedProperty(*key, *value, details),
+  CALL_HEAP_FUNCTION(object->GetIsolate(),
+                     object->SetNormalizedProperty(*key, *value, details),
                      Object);
 }
 
 
 Handle<Object> ForceDeleteProperty(Handle<JSObject> object,
                                    Handle<Object> key) {
-  CALL_HEAP_FUNCTION(Runtime::ForceDeleteObjectProperty(object, key), Object);
+  Isolate* isolate = object->GetIsolate();
+  CALL_HEAP_FUNCTION(isolate,
+                     Runtime::ForceDeleteObjectProperty(isolate, object, key),
+                     Object);
 }
 
 
@@ -291,8 +320,10 @@
     Handle<String> key,
     Handle<Object> value,
     PropertyAttributes attributes) {
-  CALL_HEAP_FUNCTION(object->
-      SetLocalPropertyIgnoreAttributes(*key, *value, attributes), Object);
+  CALL_HEAP_FUNCTION(
+    object->GetIsolate(),
+    object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes),
+    Object);
 }
 
 
@@ -300,10 +331,11 @@
                              Handle<String> key,
                              Handle<Object> value,
                              PropertyAttributes attributes) {
-  ASSERT(!Top::has_pending_exception());
+  Isolate* isolate = object->GetIsolate();
+  ASSERT(!isolate->has_pending_exception());
   CHECK(!SetLocalPropertyIgnoreAttributes(
         object, key, value, attributes).is_null());
-  CHECK(!Top::has_pending_exception());
+  CHECK(!isolate->has_pending_exception());
 }
 
 
@@ -312,7 +344,8 @@
                                           Handle<Object> value,
                                           PropertyAttributes attributes,
                                           StrictModeFlag strict_mode) {
-  CALL_HEAP_FUNCTION(object->SetPropertyWithInterceptor(*key,
+  CALL_HEAP_FUNCTION(object->GetIsolate(),
+                     object->SetPropertyWithInterceptor(*key,
                                                         *value,
                                                         attributes,
                                                         strict_mode),
@@ -322,20 +355,24 @@
 
 Handle<Object> GetProperty(Handle<JSObject> obj,
                            const char* name) {
-  Handle<String> str = Factory::LookupAsciiSymbol(name);
-  CALL_HEAP_FUNCTION(obj->GetProperty(*str), Object);
+  Isolate* isolate = obj->GetIsolate();
+  Handle<String> str = isolate->factory()->LookupAsciiSymbol(name);
+  CALL_HEAP_FUNCTION(isolate, obj->GetProperty(*str), Object);
 }
 
 
 Handle<Object> GetProperty(Handle<Object> obj,
                            Handle<Object> key) {
-  CALL_HEAP_FUNCTION(Runtime::GetObjectProperty(obj, key), Object);
+  Isolate* isolate = Isolate::Current();
+  CALL_HEAP_FUNCTION(isolate,
+                     Runtime::GetObjectProperty(isolate, obj, key), Object);
 }
 
 
 Handle<Object> GetElement(Handle<Object> obj,
                           uint32_t index) {
-  CALL_HEAP_FUNCTION(Runtime::GetElement(obj, index), Object);
+  Isolate* isolate = Isolate::Current();
+  CALL_HEAP_FUNCTION(isolate, Runtime::GetElement(obj, index), Object);
 }
 
 
@@ -343,7 +380,9 @@
                                           Handle<JSObject> holder,
                                           Handle<String> name,
                                           PropertyAttributes* attributes) {
-  CALL_HEAP_FUNCTION(holder->GetPropertyWithInterceptor(*receiver,
+  Isolate* isolate = receiver->GetIsolate();
+  CALL_HEAP_FUNCTION(isolate,
+                     holder->GetPropertyWithInterceptor(*receiver,
                                                         *name,
                                                         attributes),
                      Object);
@@ -358,15 +397,22 @@
 
 Handle<Object> SetPrototype(Handle<JSObject> obj, Handle<Object> value) {
   const bool skip_hidden_prototypes = false;
-  CALL_HEAP_FUNCTION(obj->SetPrototype(*value, skip_hidden_prototypes), Object);
+  CALL_HEAP_FUNCTION(obj->GetIsolate(),
+                     obj->SetPrototype(*value, skip_hidden_prototypes), Object);
+}
+
+
+Handle<Object> PreventExtensions(Handle<JSObject> object) {
+  CALL_HEAP_FUNCTION(object->GetIsolate(), object->PreventExtensions(), Object);
 }
 
 
 Handle<Object> GetHiddenProperties(Handle<JSObject> obj,
                                    bool create_if_needed) {
+  Isolate* isolate = obj->GetIsolate();
   Object* holder = obj->BypassGlobalProxy();
-  if (holder->IsUndefined()) return Factory::undefined_value();
-  obj = Handle<JSObject>(JSObject::cast(holder));
+  if (holder->IsUndefined()) return isolate->factory()->undefined_value();
+  obj = Handle<JSObject>(JSObject::cast(holder), isolate);
 
   if (obj->HasFastProperties()) {
     // If the object has fast properties, check whether the first slot
@@ -375,10 +421,11 @@
     // code zero) it will always occupy the first entry if present.
     DescriptorArray* descriptors = obj->map()->instance_descriptors();
     if ((descriptors->number_of_descriptors() > 0) &&
-        (descriptors->GetKey(0) == Heap::hidden_symbol()) &&
+        (descriptors->GetKey(0) == isolate->heap()->hidden_symbol()) &&
         descriptors->IsProperty(0)) {
       ASSERT(descriptors->GetType(0) == FIELD);
-      return Handle<Object>(obj->FastPropertyAt(descriptors->GetFieldIndex(0)));
+      return Handle<Object>(obj->FastPropertyAt(descriptors->GetFieldIndex(0)),
+                            isolate);
     }
   }
 
@@ -389,32 +436,39 @@
     // Hidden properties object not found. Allocate a new hidden properties
     // object if requested. Otherwise return the undefined value.
     if (create_if_needed) {
-      Handle<Object> hidden_obj = Factory::NewJSObject(Top::object_function());
-      CALL_HEAP_FUNCTION(obj->SetHiddenPropertiesObject(*hidden_obj), Object);
+      Handle<Object> hidden_obj =
+          isolate->factory()->NewJSObject(isolate->object_function());
+      CALL_HEAP_FUNCTION(isolate,
+                         obj->SetHiddenPropertiesObject(*hidden_obj), Object);
     } else {
-      return Factory::undefined_value();
+      return isolate->factory()->undefined_value();
     }
   }
-  return Handle<Object>(obj->GetHiddenPropertiesObject());
+  return Handle<Object>(obj->GetHiddenPropertiesObject(), isolate);
 }
 
 
 Handle<Object> DeleteElement(Handle<JSObject> obj,
                              uint32_t index) {
-  CALL_HEAP_FUNCTION(obj->DeleteElement(index, JSObject::NORMAL_DELETION),
+  CALL_HEAP_FUNCTION(obj->GetIsolate(),
+                     obj->DeleteElement(index, JSObject::NORMAL_DELETION),
                      Object);
 }
 
 
 Handle<Object> DeleteProperty(Handle<JSObject> obj,
                               Handle<String> prop) {
-  CALL_HEAP_FUNCTION(obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION),
+  CALL_HEAP_FUNCTION(obj->GetIsolate(),
+                     obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION),
                      Object);
 }
 
 
 Handle<Object> LookupSingleCharacterStringFromCode(uint32_t index) {
-  CALL_HEAP_FUNCTION(Heap::LookupSingleCharacterStringFromCode(index), Object);
+  Isolate* isolate = Isolate::Current();
+  CALL_HEAP_FUNCTION(
+      isolate,
+      isolate->heap()->LookupSingleCharacterStringFromCode(index), Object);
 }
 
 
@@ -422,7 +476,8 @@
                          int start,
                          int end,
                          PretenureFlag pretenure) {
-  CALL_HEAP_FUNCTION(str->SubString(start, end, pretenure), String);
+  CALL_HEAP_FUNCTION(str->GetIsolate(),
+                     str->SubString(start, end, pretenure), String);
 }
 
 
@@ -430,7 +485,7 @@
                           uint32_t index,
                           Handle<Object> value,
                           StrictModeFlag strict_mode) {
-  if (object->HasPixelElements() || object->HasExternalArrayElements()) {
+  if (object->HasExternalArrayElements()) {
     if (!value->IsSmi() && !value->IsHeapNumber() && !value->IsUndefined()) {
       bool has_exception;
       Handle<Object> number = Execution::ToNumber(value, &has_exception);
@@ -438,7 +493,8 @@
       value = number;
     }
   }
-  CALL_HEAP_FUNCTION(object->SetElement(index, *value, strict_mode), Object);
+  CALL_HEAP_FUNCTION(object->GetIsolate(),
+                     object->SetElement(index, *value, strict_mode), Object);
 }
 
 
@@ -446,20 +502,22 @@
                              uint32_t index,
                              Handle<Object> value,
                              StrictModeFlag strict_mode) {
-  ASSERT(!object->HasPixelElements());
   ASSERT(!object->HasExternalArrayElements());
-  CALL_HEAP_FUNCTION(object->SetElement(index, *value, strict_mode, false),
+  CALL_HEAP_FUNCTION(object->GetIsolate(),
+                     object->SetElement(index, *value, strict_mode, false),
                      Object);
 }
 
 
 Handle<JSObject> Copy(Handle<JSObject> obj) {
-  CALL_HEAP_FUNCTION(Heap::CopyJSObject(*obj), JSObject);
+  Isolate* isolate = obj->GetIsolate();
+  CALL_HEAP_FUNCTION(isolate,
+                     isolate->heap()->CopyJSObject(*obj), JSObject);
 }
 
 
 Handle<Object> SetAccessor(Handle<JSObject> obj, Handle<AccessorInfo> info) {
-  CALL_HEAP_FUNCTION(obj->DefineAccessor(*info), Object);
+  CALL_HEAP_FUNCTION(obj->GetIsolate(), obj->DefineAccessor(*info), Object);
 }
 
 
@@ -480,8 +538,9 @@
   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();
+  Isolate* isolate = Isolate::Current();
+  isolate->global_handles()->Destroy(cache.location());
+  isolate->counters()->script_wrappers()->Decrement();
 }
 
 
@@ -491,19 +550,20 @@
     return Handle<JSValue>(
         reinterpret_cast<JSValue**>(script->wrapper()->proxy()));
   }
-
+  Isolate* isolate = Isolate::Current();
   // Construct a new script wrapper.
-  Counters::script_wrappers.Increment();
-  Handle<JSFunction> constructor = Top::script_function();
+  isolate->counters()->script_wrappers()->Increment();
+  Handle<JSFunction> constructor = isolate->script_function();
   Handle<JSValue> result =
-      Handle<JSValue>::cast(Factory::NewJSObject(constructor));
+      Handle<JSValue>::cast(isolate->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);
+  Handle<Object> handle = isolate->global_handles()->Create(*result);
+  isolate->global_handles()->MakeWeak(handle.location(), NULL,
+                                      &ClearWrapperCache);
   script->wrapper()->set_proxy(reinterpret_cast<Address>(handle.location()));
   return result;
 }
@@ -514,20 +574,22 @@
 void InitScriptLineEnds(Handle<Script> script) {
   if (!script->line_ends()->IsUndefined()) return;
 
+  Isolate* isolate = script->GetIsolate();
+
   if (!script->source()->IsString()) {
     ASSERT(script->source()->IsUndefined());
-    Handle<FixedArray> empty = Factory::NewFixedArray(0);
+    Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
     script->set_line_ends(*empty);
     ASSERT(script->line_ends()->IsFixedArray());
     return;
   }
 
-  Handle<String> src(String::cast(script->source()));
+  Handle<String> src(String::cast(script->source()), isolate);
 
   Handle<FixedArray> array = CalculateLineEnds(src, true);
 
-  if (*array != Heap::empty_fixed_array()) {
-    array->set_map(Heap::fixed_cow_array_map());
+  if (*array != isolate->heap()->empty_fixed_array()) {
+    array->set_map(isolate->heap()->fixed_cow_array_map());
   }
 
   script->set_line_ends(*array);
@@ -536,11 +598,12 @@
 
 
 template <typename SourceChar>
-static void CalculateLineEnds(List<int>* line_ends,
+static void CalculateLineEnds(Isolate* isolate,
+                              List<int>* line_ends,
                               Vector<const SourceChar> src,
                               bool with_last_line) {
   const int src_len = src.length();
-  StringSearch<char, SourceChar> search(CStrVector("\n"));
+  StringSearch<char, SourceChar> search(isolate, CStrVector("\n"));
 
   // Find and record line ends.
   int position = 0;
@@ -565,17 +628,24 @@
   // length of (unpacked) code.
   int line_count_estimate = src->length() >> 4;
   List<int> line_ends(line_count_estimate);
+  Isolate* isolate = src->GetIsolate();
   {
     AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid.
     // Dispatch on type of strings.
     if (src->IsAsciiRepresentation()) {
-      CalculateLineEnds(&line_ends, src->ToAsciiVector(), with_last_line);
+      CalculateLineEnds(isolate,
+                        &line_ends,
+                        src->ToAsciiVector(),
+                        with_last_line);
     } else {
-      CalculateLineEnds(&line_ends, src->ToUC16Vector(), with_last_line);
+      CalculateLineEnds(isolate,
+                        &line_ends,
+                        src->ToUC16Vector(),
+                        with_last_line);
     }
   }
   int line_count = line_ends.length();
-  Handle<FixedArray> array = Factory::NewFixedArray(line_count);
+  Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
   for (int i = 0; i < line_count; i++) {
     array->set(i, Smi::FromInt(line_ends[i]));
   }
@@ -641,17 +711,18 @@
 // Compute the property keys from the interceptor.
 v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSObject> receiver,
                                                  Handle<JSObject> object) {
+  Isolate* isolate = receiver->GetIsolate();
   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
-  CustomArguments args(interceptor->data(), *receiver, *object);
+  CustomArguments args(isolate, interceptor->data(), *receiver, *object);
   v8::AccessorInfo info(args.end());
   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));
+    LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object));
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       result = enum_fun(info);
     }
   }
@@ -662,17 +733,18 @@
 // Compute the element keys from the interceptor.
 v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSObject> receiver,
                                                    Handle<JSObject> object) {
+  Isolate* isolate = receiver->GetIsolate();
   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
-  CustomArguments args(interceptor->data(), *receiver, *object);
+  CustomArguments args(isolate, interceptor->data(), *receiver, *object);
   v8::AccessorInfo info(args.end());
   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));
+    LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object));
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       result = enum_fun(info);
     }
   }
@@ -693,31 +765,33 @@
 Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
                                           KeyCollectionType type) {
   USE(ContainsOnlyValidKeys);
-  Handle<FixedArray> content = Factory::empty_fixed_array();
-  Handle<JSObject> arguments_boilerplate =
-      Handle<JSObject>(
-          Top::context()->global_context()->arguments_boilerplate());
-  Handle<JSFunction> arguments_function =
-      Handle<JSFunction>(
-          JSFunction::cast(arguments_boilerplate->map()->constructor()));
+  Isolate* isolate = object->GetIsolate();
+  Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
+  Handle<JSObject> arguments_boilerplate = Handle<JSObject>(
+      isolate->context()->global_context()->arguments_boilerplate(),
+      isolate);
+  Handle<JSFunction> arguments_function = Handle<JSFunction>(
+      JSFunction::cast(arguments_boilerplate->map()->constructor()),
+      isolate);
 
   // Only collect keys if access is permitted.
   for (Handle<Object> p = object;
-       *p != Heap::null_value();
-       p = Handle<Object>(p->GetPrototype())) {
-    Handle<JSObject> current(JSObject::cast(*p));
+       *p != isolate->heap()->null_value();
+       p = Handle<Object>(p->GetPrototype(), isolate)) {
+    Handle<JSObject> current(JSObject::cast(*p), isolate);
 
     // Check access rights if required.
     if (current->IsAccessCheckNeeded() &&
-        !Top::MayNamedAccess(*current, Heap::undefined_value(),
-                             v8::ACCESS_KEYS)) {
-      Top::ReportFailedAccessCheck(*current, v8::ACCESS_KEYS);
+        !isolate->MayNamedAccess(*current,
+                                 isolate->heap()->undefined_value(),
+                                 v8::ACCESS_KEYS)) {
+      isolate->ReportFailedAccessCheck(*current, v8::ACCESS_KEYS);
       break;
     }
 
     // Compute the element keys.
     Handle<FixedArray> element_keys =
-        Factory::NewFixedArray(current->NumberOfEnumElements());
+        isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
     current->GetEnumElementKeys(*element_keys);
     content = UnionOfKeys(content, element_keys);
     ASSERT(ContainsOnlyValidKeys(content));
@@ -771,28 +845,31 @@
 
 
 Handle<JSArray> GetKeysFor(Handle<JSObject> object) {
-  Counters::for_in.Increment();
+  Isolate* isolate = object->GetIsolate();
+  isolate->counters()->for_in()->Increment();
   Handle<FixedArray> elements = GetKeysInFixedArrayFor(object,
                                                        INCLUDE_PROTOS);
-  return Factory::NewJSArrayWithElements(elements);
+  return isolate->factory()->NewJSArrayWithElements(elements);
 }
 
 
 Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
                                        bool cache_result) {
   int index = 0;
+  Isolate* isolate = object->GetIsolate();
   if (object->HasFastProperties()) {
     if (object->map()->instance_descriptors()->HasEnumCache()) {
-      Counters::enum_cache_hits.Increment();
+      isolate->counters()->enum_cache_hits()->Increment();
       DescriptorArray* desc = object->map()->instance_descriptors();
-      return Handle<FixedArray>(FixedArray::cast(desc->GetEnumCache()));
+      return Handle<FixedArray>(FixedArray::cast(desc->GetEnumCache()),
+                                isolate);
     }
-    Counters::enum_cache_misses.Increment();
+    isolate->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);
+    Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum);
+    Handle<FixedArray> sort_array = isolate->factory()->NewFixedArray(num_enum);
     Handle<DescriptorArray> descs =
-        Handle<DescriptorArray>(object->map()->instance_descriptors());
+        Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
     for (int i = 0; i < descs->number_of_descriptors(); i++) {
       if (descs->IsProperty(i) && !descs->IsDontEnum(i)) {
         (*storage)->set(index, descs->GetKey(i));
@@ -804,7 +881,8 @@
     (*storage)->SortPairs(*sort_array, sort_array->length());
     if (cache_result) {
       Handle<FixedArray> bridge_storage =
-          Factory::NewFixedArray(DescriptorArray::kEnumCacheBridgeLength);
+          isolate->factory()->NewFixedArray(
+              DescriptorArray::kEnumCacheBridgeLength);
       DescriptorArray* desc = object->map()->instance_descriptors();
       desc->SetEnumCache(*bridge_storage, *storage);
     }
@@ -812,8 +890,8 @@
     return storage;
   } else {
     int num_enum = object->NumberOfEnumProperties();
-    Handle<FixedArray> storage = Factory::NewFixedArray(num_enum);
-    Handle<FixedArray> sort_array = Factory::NewFixedArray(num_enum);
+    Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum);
+    Handle<FixedArray> sort_array = isolate->factory()->NewFixedArray(num_enum);
     object->property_dictionary()->CopyEnumKeysTo(*storage, *sort_array);
     return storage;
   }
@@ -830,10 +908,12 @@
                               ClearExceptionFlag flag) {
   // Compile the source information to a code object.
   ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled());
-  ASSERT(!Top::has_pending_exception());
+  ASSERT(!info->isolate()->has_pending_exception());
   bool result = Compiler::CompileLazy(info);
-  ASSERT(result != Top::has_pending_exception());
-  if (!result && flag == CLEAR_EXCEPTION) Top::clear_pending_exception();
+  ASSERT(result != Isolate::Current()->has_pending_exception());
+  if (!result && flag == CLEAR_EXCEPTION) {
+    info->isolate()->clear_pending_exception();
+  }
   return result;
 }
 
@@ -882,34 +962,4 @@
   return CompileLazyHelper(&info, flag);
 }
 
-
-OptimizedObjectForAddingMultipleProperties::
-OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,
-                                           int expected_additional_properties,
-                                           bool condition) {
-  object_ = object;
-  if (condition && object_->HasFastProperties() && !object->IsJSGlobalProxy()) {
-    // Normalize the properties of object to avoid n^2 behavior
-    // when extending the object multiple properties. Indicate the number of
-    // properties to be added.
-    unused_property_fields_ = object->map()->unused_property_fields();
-    NormalizeProperties(object_,
-                        KEEP_INOBJECT_PROPERTIES,
-                        expected_additional_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_);
-  }
-}
-
 } }  // namespace v8::internal
diff --git a/src/handles.h b/src/handles.h
index bb51968..a357a00 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -44,6 +44,7 @@
  public:
   INLINE(explicit Handle(T** location)) { location_ = location; }
   INLINE(explicit Handle(T* obj));
+  INLINE(Handle(T* obj, Isolate* isolate));
 
   INLINE(Handle()) : location_(NULL) {}
 
@@ -82,7 +83,7 @@
   }
 
   static Handle<T> null() { return Handle<T>(); }
-  bool is_null() { return location_ == NULL; }
+  bool is_null() const { return location_ == NULL; }
 
   // Closes the given scope, but lets this handle escape. See
   // implementation in api.h.
@@ -107,34 +108,20 @@
 // for which the handle scope has been deleted is undefined.
 class HandleScope {
  public:
-  HandleScope() : prev_next_(current_.next), prev_limit_(current_.limit) {
-    current_.level++;
-  }
+  inline HandleScope();
+  explicit inline HandleScope(Isolate* isolate);
 
-  ~HandleScope() {
-    CloseScope();
-  }
+  inline ~HandleScope();
 
   // Counts the number of allocated handles.
   static int NumberOfHandles();
 
   // Creates a new handle with the given value.
   template <typename T>
-  static inline T** CreateHandle(T* value) {
-    internal::Object** cur = current_.next;
-    if (cur == current_.limit) cur = Extend();
-    // Update the current next field, set the value in the created
-    // handle, and return the result.
-    ASSERT(cur < current_.limit);
-    current_.next = cur + 1;
-
-    T** result = reinterpret_cast<T**>(cur);
-    *result = value;
-    return result;
-  }
+  static inline T** CreateHandle(T* value, Isolate* isolate);
 
   // Deallocates any extensions used by the current scope.
-  static void DeleteExtensions();
+  static void DeleteExtensions(Isolate* isolate);
 
   static Address current_next_address();
   static Address current_limit_address();
@@ -145,20 +132,9 @@
   // a Handle backed by the parent scope holding the
   // value of the argument handle.
   template <typename T>
-  Handle<T> CloseAndEscape(Handle<T> handle_value) {
-    T* value = *handle_value;
-    // Throw away all handles in the current scope.
-    CloseScope();
-    // Allocate one handle in the parent scope.
-    ASSERT(current_.level > 0);
-    Handle<T> result(CreateHandle<T>(value));
-    // Reinitialize the current scope (so that it's ready
-    // to be used or closed again).
-    prev_next_ = current_.next;
-    prev_limit_ = current_.limit;
-    current_.level++;
-    return result;
-  }
+  Handle<T> CloseAndEscape(Handle<T> handle_value);
+
+  Isolate* isolate() { return isolate_; }
 
  private:
   // Prevent heap allocation or illegal handle scopes.
@@ -167,21 +143,9 @@
   void* operator new(size_t size);
   void operator delete(void* size_t);
 
-  inline void CloseScope() {
-    current_.next = prev_next_;
-    current_.level--;
-    if (current_.limit != prev_limit_) {
-      current_.limit = prev_limit_;
-      DeleteExtensions();
-    }
-#ifdef DEBUG
-    ZapRange(prev_next_, prev_limit_);
-#endif
-  }
+  inline void CloseScope();
 
-  static v8::ImplementationUtilities::HandleScopeData current_;
-  // Holds values on entry. The prev_next_ value is never NULL
-  // on_entry, but is set to NULL when this scope is closed.
+  Isolate* isolate_;
   Object** prev_next_;
   Object** prev_limit_;
 
@@ -264,10 +228,10 @@
                                           PropertyAttributes attributes,
                                           StrictModeFlag strict_mode);
 
-Handle<Object> SetElement(Handle<JSObject> object,
-                          uint32_t index,
-                          Handle<Object> value,
-                          StrictModeFlag strict_mode);
+MUST_USE_RESULT Handle<Object> SetElement(Handle<JSObject> object,
+                                          uint32_t index,
+                                          Handle<Object> value,
+                                          StrictModeFlag strict_mode);
 
 Handle<Object> SetOwnElement(Handle<JSObject> object,
                              uint32_t index,
@@ -370,6 +334,7 @@
 Handle<Object> SetPrototype(Handle<JSFunction> function,
                             Handle<Object> prototype);
 
+Handle<Object> PreventExtensions(Handle<JSObject> object);
 
 // Does lazy compilation of the given function. Returns true on success and
 // false if the compilation resulted in a stack overflow.
@@ -402,25 +367,6 @@
 #endif
 };
 
-
-// ----------------------------------------------------------------------------
-
-
-// Stack allocated wrapper call for optimizing adding multiple
-// properties to an object.
-class OptimizedObjectForAddingMultipleProperties BASE_EMBEDDED {
- public:
-  OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,
-                                             int expected_property_count,
-                                             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/src/hashmap.h b/src/hashmap.h
index 2798988..bb3e3ce 100644
--- a/src/hashmap.h
+++ b/src/hashmap.h
@@ -55,9 +55,9 @@
 
   // 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);
+  explicit HashMap(MatchFun match,
+                   Allocator* allocator = &DefaultAllocator,
+                   uint32_t initial_capacity = 8);
 
   ~HashMap();
 
diff --git a/src/heap-inl.h b/src/heap-inl.h
index 7b91e87..99737ed 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -30,11 +30,20 @@
 
 #include "heap.h"
 #include "objects.h"
+#include "isolate.h"
 #include "v8-counters.h"
 
 namespace v8 {
 namespace internal {
 
+void PromotionQueue::insert(HeapObject* target, int size) {
+  *(--rear_) = reinterpret_cast<intptr_t>(target);
+  *(--rear_) = size;
+  // Assert no overflow into live objects.
+  ASSERT(reinterpret_cast<Address>(rear_) >= HEAP->new_space()->top());
+}
+
+
 int Heap::MaxObjectSizeInPagedSpace() {
   return Page::kMaxHeapObjectSize;
 }
@@ -146,8 +155,8 @@
       Heap::allocation_timeout_-- <= 0) {
     return Failure::RetryAfterGC(space);
   }
-  Counters::objs_since_last_full.Increment();
-  Counters::objs_since_last_young.Increment();
+  isolate_->counters()->objs_since_last_full()->Increment();
+  isolate_->counters()->objs_since_last_young()->Increment();
 #endif
   MaybeObject* result;
   if (NEW_SPACE == space) {
@@ -214,8 +223,8 @@
 
 MaybeObject* Heap::AllocateRawMap() {
 #ifdef DEBUG
-  Counters::objs_since_last_full.Increment();
-  Counters::objs_since_last_young.Increment();
+  isolate_->counters()->objs_since_last_full()->Increment();
+  isolate_->counters()->objs_since_last_young()->Increment();
 #endif
   MaybeObject* result = map_space_->AllocateRaw(Map::kSize);
   if (result->IsFailure()) old_gen_exhausted_ = true;
@@ -232,8 +241,8 @@
 
 MaybeObject* Heap::AllocateRawCell() {
 #ifdef DEBUG
-  Counters::objs_since_last_full.Increment();
-  Counters::objs_since_last_young.Increment();
+  isolate_->counters()->objs_since_last_full()->Increment();
+  isolate_->counters()->objs_since_last_young()->Increment();
 #endif
   MaybeObject* result = cell_space_->AllocateRaw(JSGlobalPropertyCell::kSize);
   if (result->IsFailure()) old_gen_exhausted_ = true;
@@ -341,7 +350,7 @@
        remaining--) {
     Memory::Object_at(dst) = Memory::Object_at(src);
 
-    if (Heap::InNewSpace(Memory::Object_at(dst))) {
+    if (InNewSpace(Memory::Object_at(dst))) {
       marks |= page->GetRegionMaskForAddress(dst);
     }
 
@@ -387,8 +396,13 @@
 }
 
 
+void Heap::ScavengePointer(HeapObject** p) {
+  ScavengeObject(p, *p);
+}
+
+
 void Heap::ScavengeObject(HeapObject** p, HeapObject* object) {
-  ASSERT(InFromSpace(object));
+  ASSERT(HEAP->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
@@ -461,10 +475,15 @@
   roots_[kLastScriptIdRootIndex] = last_script_id;
 }
 
+Isolate* Heap::isolate() {
+  return reinterpret_cast<Isolate*>(reinterpret_cast<intptr_t>(this) -
+      reinterpret_cast<size_t>(reinterpret_cast<Isolate*>(4)->heap()) + 4);
+}
+
 
 #ifdef DEBUG
 #define GC_GREEDY_CHECK() \
-  if (FLAG_gc_greedy) v8::internal::Heap::GarbageCollectionGreedyCheck()
+  if (FLAG_gc_greedy) HEAP->GarbageCollectionGreedyCheck()
 #else
 #define GC_GREEDY_CHECK() { }
 #endif
@@ -477,7 +496,7 @@
 // Warning: Do not use the identifiers __object__, __maybe_object__ or
 // __scope__ in a call to this macro.
 
-#define CALL_AND_RETRY(FUNCTION_CALL, RETURN_VALUE, RETURN_EMPTY)         \
+#define CALL_AND_RETRY(ISOLATE, FUNCTION_CALL, RETURN_VALUE, RETURN_EMPTY)\
   do {                                                                    \
     GC_GREEDY_CHECK();                                                    \
     MaybeObject* __maybe_object__ = FUNCTION_CALL;                        \
@@ -487,16 +506,16 @@
       v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_0", true);\
     }                                                                     \
     if (!__maybe_object__->IsRetryAfterGC()) RETURN_EMPTY;                \
-    Heap::CollectGarbage(                                                 \
-        Failure::cast(__maybe_object__)->allocation_space());             \
+    ISOLATE->heap()->CollectGarbage(Failure::cast(__maybe_object__)->     \
+                                    allocation_space());                  \
     __maybe_object__ = FUNCTION_CALL;                                     \
     if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE;            \
     if (__maybe_object__->IsOutOfMemory()) {                              \
       v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_1", true);\
     }                                                                     \
     if (!__maybe_object__->IsRetryAfterGC()) RETURN_EMPTY;                \
-    Counters::gc_last_resort_from_handles.Increment();                    \
-    Heap::CollectAllAvailableGarbage();                                   \
+    ISOLATE->counters()->gc_last_resort_from_handles()->Increment();      \
+    ISOLATE->heap()->CollectAllAvailableGarbage();                        \
     {                                                                     \
       AlwaysAllocateScope __scope__;                                      \
       __maybe_object__ = FUNCTION_CALL;                                   \
@@ -511,14 +530,17 @@
   } while (false)
 
 
-#define CALL_HEAP_FUNCTION(FUNCTION_CALL, TYPE)                \
-  CALL_AND_RETRY(FUNCTION_CALL,                                \
-                 return Handle<TYPE>(TYPE::cast(__object__)),  \
+// TODO(isolates): cache isolate: either accept as a parameter or
+//                 set to some known symbol (__CUR_ISOLATE__?)
+#define CALL_HEAP_FUNCTION(ISOLATE, FUNCTION_CALL, TYPE)       \
+  CALL_AND_RETRY(ISOLATE,                                      \
+                 FUNCTION_CALL,                                \
+                 return Handle<TYPE>(TYPE::cast(__object__), ISOLATE),  \
                  return Handle<TYPE>())
 
 
-#define CALL_HEAP_FUNCTION_VOID(FUNCTION_CALL) \
-  CALL_AND_RETRY(FUNCTION_CALL, return, return)
+#define CALL_HEAP_FUNCTION_VOID(ISOLATE, FUNCTION_CALL) \
+  CALL_AND_RETRY(ISOLATE, FUNCTION_CALL, return, return)
 
 
 #ifdef DEBUG
@@ -534,7 +556,7 @@
 
 void ExternalStringTable::AddString(String* string) {
   ASSERT(string->IsExternalString());
-  if (Heap::InNewSpace(string)) {
+  if (heap_->InNewSpace(string)) {
     new_space_strings_.Add(string);
   } else {
     old_space_strings_.Add(string);
@@ -559,12 +581,12 @@
 void ExternalStringTable::Verify() {
 #ifdef DEBUG
   for (int i = 0; i < new_space_strings_.length(); ++i) {
-    ASSERT(Heap::InNewSpace(new_space_strings_[i]));
-    ASSERT(new_space_strings_[i] != Heap::raw_unchecked_null_value());
+    ASSERT(heap_->InNewSpace(new_space_strings_[i]));
+    ASSERT(new_space_strings_[i] != HEAP->raw_unchecked_null_value());
   }
   for (int i = 0; i < old_space_strings_.length(); ++i) {
-    ASSERT(!Heap::InNewSpace(old_space_strings_[i]));
-    ASSERT(old_space_strings_[i] != Heap::raw_unchecked_null_value());
+    ASSERT(!heap_->InNewSpace(old_space_strings_[i]));
+    ASSERT(old_space_strings_[i] != HEAP->raw_unchecked_null_value());
   }
 #endif
 }
@@ -572,7 +594,7 @@
 
 void ExternalStringTable::AddOldString(String* string) {
   ASSERT(string->IsExternalString());
-  ASSERT(!Heap::InNewSpace(string));
+  ASSERT(!heap_->InNewSpace(string));
   old_space_strings_.Add(string);
 }
 
@@ -582,6 +604,100 @@
   Verify();
 }
 
+
+void Heap::ClearInstanceofCache() {
+  set_instanceof_cache_function(the_hole_value());
+}
+
+
+Object* Heap::ToBoolean(bool condition) {
+  return condition ? true_value() : false_value();
+}
+
+
+void Heap::CompletelyClearInstanceofCache() {
+  set_instanceof_cache_map(the_hole_value());
+  set_instanceof_cache_function(the_hole_value());
+}
+
+
+MaybeObject* TranscendentalCache::Get(Type type, double input) {
+  SubCache* cache = caches_[type];
+  if (cache == NULL) {
+    caches_[type] = cache = new SubCache(type);
+  }
+  return cache->Get(input);
+}
+
+
+Address TranscendentalCache::cache_array_address() {
+  return reinterpret_cast<Address>(caches_);
+}
+
+
+double TranscendentalCache::SubCache::Calculate(double input) {
+  switch (type_) {
+    case ACOS:
+      return acos(input);
+    case ASIN:
+      return asin(input);
+    case ATAN:
+      return atan(input);
+    case COS:
+      return cos(input);
+    case EXP:
+      return exp(input);
+    case LOG:
+      return log(input);
+    case SIN:
+      return sin(input);
+    case TAN:
+      return tan(input);
+    default:
+      return 0.0;  // Never happens.
+  }
+}
+
+
+MaybeObject* TranscendentalCache::SubCache::Get(double input) {
+  Converter c;
+  c.dbl = input;
+  int hash = Hash(c);
+  Element e = elements_[hash];
+  if (e.in[0] == c.integers[0] &&
+      e.in[1] == c.integers[1]) {
+    ASSERT(e.output != NULL);
+    isolate_->counters()->transcendental_cache_hit()->Increment();
+    return e.output;
+  }
+  double answer = Calculate(input);
+  isolate_->counters()->transcendental_cache_miss()->Increment();
+  Object* heap_number;
+  { MaybeObject* maybe_heap_number =
+        isolate_->heap()->AllocateHeapNumber(answer);
+    if (!maybe_heap_number->ToObject(&heap_number)) return maybe_heap_number;
+  }
+  elements_[hash].in[0] = c.integers[0];
+  elements_[hash].in[1] = c.integers[1];
+  elements_[hash].output = heap_number;
+  return heap_number;
+}
+
+
+Heap* _inline_get_heap_() {
+  return HEAP;
+}
+
+
+void MarkCompactCollector::SetMark(HeapObject* obj) {
+  tracer_->increment_marked_count();
+#ifdef DEBUG
+  UpdateLiveObjectCount(obj);
+#endif
+  obj->SetMark();
+}
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_HEAP_INL_H_
diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc
index 07b631f..4815f82 100644
--- a/src/heap-profiler.cc
+++ b/src/heap-profiler.cc
@@ -72,14 +72,14 @@
     String* constructor = GetConstructorNameForHeapProfile(
         JSObject::cast(js_obj));
     // Differentiate Object and Array instances.
-    if (fine_grain && (constructor == Heap::Object_symbol() ||
-                       constructor == Heap::Array_symbol())) {
+    if (fine_grain && (constructor == HEAP->Object_symbol() ||
+                       constructor == HEAP->Array_symbol())) {
       return JSObjectsCluster(constructor, obj);
     } else {
       return JSObjectsCluster(constructor);
     }
   } else if (obj->IsString()) {
-    return JSObjectsCluster(Heap::String_symbol());
+    return JSObjectsCluster(HEAP->String_symbol());
   } else if (obj->IsJSGlobalPropertyCell()) {
     return JSObjectsCluster(JSObjectsCluster::GLOBAL_PROPERTY);
   } else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) {
@@ -112,10 +112,10 @@
   int size = obj->Size();
   // If 'properties' and 'elements' are non-empty (thus, non-shared),
   // take their size into account.
-  if (obj->properties() != Heap::empty_fixed_array()) {
+  if (obj->properties() != HEAP->empty_fixed_array()) {
     size += obj->properties()->Size();
   }
-  if (obj->elements() != Heap::empty_fixed_array()) {
+  if (obj->elements() != HEAP->empty_fixed_array()) {
     size += obj->elements()->Size();
   }
   // For functions, also account non-empty context and literals sizes.
@@ -174,7 +174,8 @@
     HeapStringAllocator allocator;
     StringStream stream(&allocator);
     cluster.Print(&stream);
-    LOG(HeapSampleJSRetainersEvent(
+    LOG(ISOLATE,
+        HeapSampleJSRetainersEvent(
         *(stream.ToCString()), *(retainers.ToCString())));
   }
 };
@@ -315,8 +316,6 @@
 }
 
 
-HeapProfiler* HeapProfiler::singleton_ = NULL;
-
 HeapProfiler::HeapProfiler()
     : snapshots_(new HeapSnapshotsCollection()),
       next_snapshot_uid_(1) {
@@ -327,12 +326,20 @@
   delete snapshots_;
 }
 
+
+void HeapProfiler::ResetSnapshots() {
+  delete snapshots_;
+  snapshots_ = new HeapSnapshotsCollection();
+}
+
+
 #endif  // ENABLE_LOGGING_AND_PROFILING
 
 void HeapProfiler::Setup() {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (singleton_ == NULL) {
-    singleton_ = new HeapProfiler();
+  Isolate* isolate = Isolate::Current();
+  if (isolate->heap_profiler() == NULL) {
+    isolate->set_heap_profiler(new HeapProfiler());
   }
 #endif
 }
@@ -340,8 +347,9 @@
 
 void HeapProfiler::TearDown() {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  delete singleton_;
-  singleton_ = NULL;
+  Isolate* isolate = Isolate::Current();
+  delete isolate->heap_profiler();
+  isolate->set_heap_profiler(NULL);
 #endif
 }
 
@@ -351,16 +359,39 @@
 HeapSnapshot* HeapProfiler::TakeSnapshot(const char* name,
                                          int type,
                                          v8::ActivityControl* control) {
-  ASSERT(singleton_ != NULL);
-  return singleton_->TakeSnapshotImpl(name, type, control);
+  ASSERT(Isolate::Current()->heap_profiler() != NULL);
+  return Isolate::Current()->heap_profiler()->TakeSnapshotImpl(name,
+                                                               type,
+                                                               control);
 }
 
 
 HeapSnapshot* HeapProfiler::TakeSnapshot(String* name,
                                          int type,
                                          v8::ActivityControl* control) {
-  ASSERT(singleton_ != NULL);
-  return singleton_->TakeSnapshotImpl(name, type, control);
+  ASSERT(Isolate::Current()->heap_profiler() != NULL);
+  return Isolate::Current()->heap_profiler()->TakeSnapshotImpl(name,
+                                                               type,
+                                                               control);
+}
+
+
+void HeapProfiler::DefineWrapperClass(
+    uint16_t class_id, v8::HeapProfiler::WrapperInfoCallback callback) {
+  ASSERT(class_id != v8::HeapProfiler::kPersistentHandleNoClassId);
+  if (wrapper_callbacks_.length() <= class_id) {
+    wrapper_callbacks_.AddBlock(
+        NULL, class_id - wrapper_callbacks_.length() + 1);
+  }
+  wrapper_callbacks_[class_id] = callback;
+}
+
+
+v8::RetainedObjectInfo* HeapProfiler::ExecuteWrapperClassCallback(
+    uint16_t class_id, Object** wrapper) {
+  if (wrapper_callbacks_.length() <= class_id) return NULL;
+  return wrapper_callbacks_[class_id](
+      class_id, Utils::ToLocal(Handle<Object>(wrapper)));
 }
 
 
@@ -373,13 +404,13 @@
   bool generation_completed = true;
   switch (s_type) {
     case HeapSnapshot::kFull: {
-      Heap::CollectAllGarbage(true);
+      HEAP->CollectAllGarbage(true);
       HeapSnapshotGenerator generator(result, control);
       generation_completed = generator.GenerateSnapshot();
       break;
     }
     case HeapSnapshot::kAggregated: {
-      Heap::CollectAllGarbage(true);
+      HEAP->CollectAllGarbage(true);
       AggregatedHeapSnapshot agg_snapshot;
       AggregatedHeapSnapshotGenerator generator(&agg_snapshot);
       generator.GenerateSnapshot();
@@ -401,31 +432,40 @@
 HeapSnapshot* HeapProfiler::TakeSnapshotImpl(String* name,
                                              int type,
                                              v8::ActivityControl* control) {
-  return TakeSnapshotImpl(snapshots_->GetName(name), type, control);
+  return TakeSnapshotImpl(snapshots_->names()->GetName(name), type, control);
 }
 
 
 int HeapProfiler::GetSnapshotsCount() {
-  ASSERT(singleton_ != NULL);
-  return singleton_->snapshots_->snapshots()->length();
+  HeapProfiler* profiler = Isolate::Current()->heap_profiler();
+  ASSERT(profiler != NULL);
+  return profiler->snapshots_->snapshots()->length();
 }
 
 
 HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
-  ASSERT(singleton_ != NULL);
-  return singleton_->snapshots_->snapshots()->at(index);
+  HeapProfiler* profiler = Isolate::Current()->heap_profiler();
+  ASSERT(profiler != NULL);
+  return profiler->snapshots_->snapshots()->at(index);
 }
 
 
 HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
-  ASSERT(singleton_ != NULL);
-  return singleton_->snapshots_->GetSnapshot(uid);
+  HeapProfiler* profiler = Isolate::Current()->heap_profiler();
+  ASSERT(profiler != NULL);
+  return profiler->snapshots_->GetSnapshot(uid);
+}
+
+
+void HeapProfiler::DeleteAllSnapshots() {
+  HeapProfiler* profiler = Isolate::Current()->heap_profiler();
+  ASSERT(profiler != NULL);
+  profiler->ResetSnapshots();
 }
 
 
 void HeapProfiler::ObjectMoveEvent(Address from, Address to) {
-  ASSERT(singleton_ != NULL);
-  singleton_->snapshots_->ObjectMoveEvent(from, to);
+  snapshots_->ObjectMoveEvent(from, to);
 }
 
 
@@ -443,7 +483,8 @@
   HeapStringAllocator allocator;
   StringStream stream(&allocator);
   cluster.Print(&stream);
-  LOG(HeapSampleJSConstructorEvent(*(stream.ToCString()),
+  LOG(ISOLATE,
+      HeapSampleJSConstructorEvent(*(stream.ToCString()),
                                    number_and_size.number(),
                                    number_and_size.bytes()));
 }
@@ -662,7 +703,7 @@
       aggregator_(NULL) {
   JSObjectsCluster roots(JSObjectsCluster::ROOTS);
   ReferencesExtractor extractor(roots, this);
-  Heap::IterateRoots(&extractor, VISIT_ONLY_STRONG);
+  HEAP->IterateRoots(&extractor, VISIT_ONLY_STRONG);
 }
 
 
@@ -732,15 +773,18 @@
   String* constructor = GetConstructorNameForHeapProfile(JSObject::cast(obj));
   SmartPointer<char> s_name(
       constructor->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL));
-  LOG(HeapSampleJSProducerEvent(GetConstructorName(*s_name),
+  LOG(ISOLATE,
+      HeapSampleJSProducerEvent(GetConstructorName(*s_name),
                                 reinterpret_cast<Address*>(trace)));
 }
 
 
 void HeapProfiler::WriteSample() {
-  LOG(HeapSampleBeginEvent("Heap", "allocated"));
-  LOG(HeapSampleStats(
-      "Heap", "allocated", Heap::CommittedMemory(), Heap::SizeOfObjects()));
+  Isolate* isolate = Isolate::Current();
+  LOG(isolate, HeapSampleBeginEvent("Heap", "allocated"));
+  LOG(isolate,
+      HeapSampleStats(
+          "Heap", "allocated", HEAP->CommittedMemory(), HEAP->SizeOfObjects()));
 
   AggregatedHeapSnapshot snapshot;
   AggregatedHeapSnapshotGenerator generator(&snapshot);
@@ -751,7 +795,8 @@
        i <= AggregatedHeapSnapshotGenerator::kAllStringsType;
        ++i) {
     if (info[i].bytes() > 0) {
-      LOG(HeapSampleItemEvent(info[i].name(), info[i].number(),
+      LOG(isolate,
+          HeapSampleItemEvent(info[i].name(), info[i].number(),
                               info[i].bytes()));
     }
   }
@@ -759,10 +804,10 @@
   snapshot.js_cons_profile()->PrintStats();
   snapshot.js_retainer_profile()->PrintStats();
 
-  GlobalHandles::IterateWeakRoots(PrintProducerStackTrace,
-                                  StackWeakReferenceCallback);
+  isolate->global_handles()->IterateWeakRoots(PrintProducerStackTrace,
+                                              StackWeakReferenceCallback);
 
-  LOG(HeapSampleEndEvent("Heap", "allocated"));
+  LOG(isolate, HeapSampleEndEvent("Heap", "allocated"));
 }
 
 
@@ -872,7 +917,8 @@
             const NumberAndSizeInfo& number_and_size) {
     const char* name = cluster.GetSpecialCaseName();
     if (name == NULL) {
-      name = snapshot_->collection()->GetFunctionName(cluster.constructor());
+      name = snapshot_->collection()->names()->GetFunctionName(
+          cluster.constructor());
     }
     AddEntryFromAggregatedSnapshot(snapshot_,
                                    root_child_index_,
@@ -1013,7 +1059,8 @@
     JSObjectsCluster cluster = HeapObjectAsCluster(obj);
     const char* name = cluster.GetSpecialCaseName();
     if (name == NULL) {
-      name = snapshot_->collection()->GetFunctionName(cluster.constructor());
+      name = snapshot_->collection()->names()->GetFunctionName(
+          cluster.constructor());
     }
     return AddEntryFromAggregatedSnapshot(
         snapshot_, root_child_index_, HeapEntry::kObject, name,
@@ -1094,8 +1141,6 @@
 }
 
 
-bool ProducerHeapProfile::can_log_ = false;
-
 void ProducerHeapProfile::Setup() {
   can_log_ = true;
 }
@@ -1115,10 +1160,10 @@
     stack[i++] = it.frame()->pc();
   }
   stack[i] = NULL;
-  Handle<Object> handle = GlobalHandles::Create(obj);
-  GlobalHandles::MakeWeak(handle.location(),
-                          static_cast<void*>(stack.start()),
-                          StackWeakReferenceCallback);
+  Handle<Object> handle = isolate_->global_handles()->Create(obj);
+  isolate_->global_handles()->MakeWeak(handle.location(),
+                                       static_cast<void*>(stack.start()),
+                                       StackWeakReferenceCallback);
 }
 
 
diff --git a/src/heap-profiler.h b/src/heap-profiler.h
index 20ba457..89a2e8a 100644
--- a/src/heap-profiler.h
+++ b/src/heap-profiler.h
@@ -28,6 +28,7 @@
 #ifndef V8_HEAP_PROFILER_H_
 #define V8_HEAP_PROFILER_H_
 
+#include "isolate.h"
 #include "zone-inl.h"
 
 namespace v8 {
@@ -38,14 +39,15 @@
 class HeapSnapshot;
 class HeapSnapshotsCollection;
 
-#define HEAP_PROFILE(Call)                             \
-  do {                                                 \
-    if (v8::internal::HeapProfiler::is_profiling()) {  \
-      v8::internal::HeapProfiler::Call;                \
-    }                                                  \
+#define HEAP_PROFILE(heap, call)                                             \
+  do {                                                                       \
+    v8::internal::HeapProfiler* profiler = heap->isolate()->heap_profiler(); \
+    if (profiler != NULL && profiler->is_profiling()) {                      \
+      profiler->call;                                                        \
+    }                                                                        \
   } while (false)
 #else
-#define HEAP_PROFILE(Call) ((void) 0)
+#define HEAP_PROFILE(heap, call) ((void) 0)
 #endif  // ENABLE_LOGGING_AND_PROFILING
 
 // The HeapProfiler writes data to the log files, which can be postprocessed
@@ -65,11 +67,17 @@
   static int GetSnapshotsCount();
   static HeapSnapshot* GetSnapshot(int index);
   static HeapSnapshot* FindSnapshot(unsigned uid);
+  static void DeleteAllSnapshots();
 
-  static void ObjectMoveEvent(Address from, Address to);
+  void ObjectMoveEvent(Address from, Address to);
 
-  static INLINE(bool is_profiling()) {
-    return singleton_ != NULL && singleton_->snapshots_->is_tracking_objects();
+  void DefineWrapperClass(
+      uint16_t class_id, v8::HeapProfiler::WrapperInfoCallback callback);
+
+  v8::RetainedObjectInfo* ExecuteWrapperClassCallback(uint16_t class_id,
+                                                      Object** wrapper);
+  INLINE(bool is_profiling()) {
+    return snapshots_->is_tracking_objects();
   }
 
   // Obsolete interface.
@@ -85,11 +93,12 @@
   HeapSnapshot* TakeSnapshotImpl(String* name,
                                  int type,
                                  v8::ActivityControl* control);
+  void ResetSnapshots();
 
   HeapSnapshotsCollection* snapshots_;
   unsigned next_snapshot_uid_;
+  List<v8::HeapProfiler::WrapperInfoCallback> wrapper_callbacks_;
 
-  static HeapProfiler* singleton_;
 #endif  // ENABLE_LOGGING_AND_PROFILING
 };
 
@@ -148,10 +157,10 @@
     // We use symbols that are illegal JS identifiers to identify special cases.
     // Their actual value is irrelevant for us.
     switch (special) {
-      case ROOTS: return Heap::result_symbol();
-      case GLOBAL_PROPERTY: return Heap::code_symbol();
-      case CODE: return Heap::arguments_shadow_symbol();
-      case SELF: return Heap::catch_var_symbol();
+      case ROOTS: return HEAP->result_symbol();
+      case GLOBAL_PROPERTY: return HEAP->code_symbol();
+      case CODE: return HEAP->arguments_shadow_symbol();
+      case SELF: return HEAP->catch_var_symbol();
       default:
         UNREACHABLE();
         return NULL;
@@ -341,7 +350,6 @@
 
 class HeapEntriesMap;
 class HeapEntriesAllocator;
-class HeapSnapshot;
 
 class AggregatedHeapSnapshotGenerator {
  public:
@@ -362,16 +370,23 @@
 };
 
 
-class ProducerHeapProfile : public AllStatic {
+class ProducerHeapProfile {
  public:
-  static void Setup();
-  static void RecordJSObjectAllocation(Object* obj) {
+  void Setup();
+  void RecordJSObjectAllocation(Object* obj) {
     if (FLAG_log_producers) DoRecordJSObjectAllocation(obj);
   }
 
  private:
-  static void DoRecordJSObjectAllocation(Object* obj);
-  static bool can_log_;
+  ProducerHeapProfile() : can_log_(false) { }
+
+  void DoRecordJSObjectAllocation(Object* obj);
+  Isolate* isolate_;
+  bool can_log_;
+
+  friend class Isolate;
+
+  DISALLOW_COPY_AND_ASSIGN(ProducerHeapProfile);
 };
 
 #endif  // ENABLE_LOGGING_AND_PROFILING
diff --git a/src/heap.cc b/src/heap.cc
index 34ab9aa..5d1a66e 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -49,119 +49,114 @@
 #include "regexp-macro-assembler.h"
 #include "arm/regexp-macro-assembler-arm.h"
 #endif
-
+#if V8_TARGET_ARCH_MIPS && !V8_INTERPRETED_REGEXP
+#include "regexp-macro-assembler.h"
+#include "mips/regexp-macro-assembler-mips.h"
+#endif
 
 namespace v8 {
 namespace internal {
 
 
-String* Heap::hidden_symbol_;
-Object* Heap::roots_[Heap::kRootListLength];
-Object* Heap::global_contexts_list_;
-
-
-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;
-CellSpace* Heap::cell_space_ = NULL;
-LargeObjectSpace* Heap::lo_space_ = NULL;
-
 static const intptr_t kMinimumPromotionLimit = 2 * MB;
 static const intptr_t kMinimumAllocationLimit = 8 * MB;
 
-intptr_t Heap::old_gen_promotion_limit_ = kMinimumPromotionLimit;
-intptr_t Heap::old_gen_allocation_limit_ = kMinimumAllocationLimit;
 
-int Heap::old_gen_exhausted_ = false;
+static Mutex* gc_initializer_mutex = OS::CreateMutex();
 
-int Heap::amount_of_external_allocated_memory_ = 0;
-int Heap::amount_of_external_allocated_memory_at_last_global_gc_ = 0;
 
+Heap::Heap()
+    : isolate_(NULL),
 // semispace_size_ should be a power of 2 and old_generation_size_ should be
 // a multiple of Page::kPageSize.
 #if defined(ANDROID)
-static const int default_max_semispace_size_  = 2*MB;
-intptr_t Heap::max_old_generation_size_ = 192*MB;
-int Heap::initial_semispace_size_ = 128*KB;
-intptr_t Heap::code_range_size_ = 0;
-intptr_t Heap::max_executable_size_ = max_old_generation_size_;
+      reserved_semispace_size_(2*MB),
+      max_semispace_size_(2*MB),
+      initial_semispace_size_(128*KB),
+      max_old_generation_size_(192*MB),
+      max_executable_size_(max_old_generation_size_),
+      code_range_size_(0),
 #elif defined(V8_TARGET_ARCH_X64)
-static const int default_max_semispace_size_  = 16*MB;
-intptr_t Heap::max_old_generation_size_ = 1*GB;
-int Heap::initial_semispace_size_ = 1*MB;
-intptr_t Heap::code_range_size_ = 512*MB;
-intptr_t Heap::max_executable_size_ = 256*MB;
+      reserved_semispace_size_(16*MB),
+      max_semispace_size_(16*MB),
+      initial_semispace_size_(1*MB),
+      max_old_generation_size_(1*GB),
+      max_executable_size_(256*MB),
+      code_range_size_(512*MB),
 #else
-static const int default_max_semispace_size_  = 8*MB;
-intptr_t Heap::max_old_generation_size_ = 512*MB;
-int Heap::initial_semispace_size_ = 512*KB;
-intptr_t Heap::code_range_size_ = 0;
-intptr_t Heap::max_executable_size_ = 128*MB;
+      reserved_semispace_size_(8*MB),
+      max_semispace_size_(8*MB),
+      initial_semispace_size_(512*KB),
+      max_old_generation_size_(512*MB),
+      max_executable_size_(128*MB),
+      code_range_size_(0),
 #endif
-
-// Allow build-time customization of the max semispace size. Building
-// V8 with snapshots and a non-default max semispace size is much
-// easier if you can define it as part of the build environment.
-#if defined(V8_MAX_SEMISPACE_SIZE)
-int Heap::max_semispace_size_ = V8_MAX_SEMISPACE_SIZE;
-#else
-int Heap::max_semispace_size_ = default_max_semispace_size_;
-#endif
-
-// The snapshot semispace size will be the default semispace size if
-// snapshotting is used and will be the requested semispace size as
-// set up by ConfigureHeap otherwise.
-int Heap::reserved_semispace_size_ = Heap::max_semispace_size_;
-
-List<Heap::GCPrologueCallbackPair> Heap::gc_prologue_callbacks_;
-List<Heap::GCEpilogueCallbackPair> Heap::gc_epilogue_callbacks_;
-
-GCCallback Heap::global_gc_prologue_callback_ = NULL;
-GCCallback Heap::global_gc_epilogue_callback_ = NULL;
-HeapObjectCallback Heap::gc_safe_size_of_old_object_ = NULL;
-
 // Variables set based on semispace_size_ and old_generation_size_ in
-// ConfigureHeap.
-
+// ConfigureHeap (survived_since_last_expansion_, external_allocation_limit_)
 // Will be 4 * reserved_semispace_size_ to ensure that young
 // generation can be aligned to its size.
-int Heap::survived_since_last_expansion_ = 0;
-intptr_t Heap::external_allocation_limit_ = 0;
-
-Heap::HeapState Heap::gc_state_ = NOT_IN_GC;
-
-int Heap::mc_count_ = 0;
-int Heap::ms_count_ = 0;
-unsigned int Heap::gc_count_ = 0;
-
-GCTracer* Heap::tracer_ = NULL;
-
-int Heap::unflattened_strings_length_ = 0;
-
-int Heap::always_allocate_scope_depth_ = 0;
-int Heap::linear_allocation_scope_depth_ = 0;
-int Heap::contexts_disposed_ = 0;
-
-int Heap::young_survivors_after_last_gc_ = 0;
-int Heap::high_survival_rate_period_length_ = 0;
-double Heap::survival_rate_ = 0;
-Heap::SurvivalRateTrend Heap::previous_survival_rate_trend_ = Heap::STABLE;
-Heap::SurvivalRateTrend Heap::survival_rate_trend_ = Heap::STABLE;
-
+      survived_since_last_expansion_(0),
+      always_allocate_scope_depth_(0),
+      linear_allocation_scope_depth_(0),
+      contexts_disposed_(0),
+      new_space_(this),
+      old_pointer_space_(NULL),
+      old_data_space_(NULL),
+      code_space_(NULL),
+      map_space_(NULL),
+      cell_space_(NULL),
+      lo_space_(NULL),
+      gc_state_(NOT_IN_GC),
+      mc_count_(0),
+      ms_count_(0),
+      gc_count_(0),
+      unflattened_strings_length_(0),
 #ifdef DEBUG
-bool Heap::allocation_allowed_ = true;
-
-int Heap::allocation_timeout_ = 0;
-bool Heap::disallow_allocation_failure_ = false;
+      allocation_allowed_(true),
+      allocation_timeout_(0),
+      disallow_allocation_failure_(false),
+      debug_utils_(NULL),
 #endif  // DEBUG
+      old_gen_promotion_limit_(kMinimumPromotionLimit),
+      old_gen_allocation_limit_(kMinimumAllocationLimit),
+      external_allocation_limit_(0),
+      amount_of_external_allocated_memory_(0),
+      amount_of_external_allocated_memory_at_last_global_gc_(0),
+      old_gen_exhausted_(false),
+      hidden_symbol_(NULL),
+      global_gc_prologue_callback_(NULL),
+      global_gc_epilogue_callback_(NULL),
+      gc_safe_size_of_old_object_(NULL),
+      tracer_(NULL),
+      young_survivors_after_last_gc_(0),
+      high_survival_rate_period_length_(0),
+      survival_rate_(0),
+      previous_survival_rate_trend_(Heap::STABLE),
+      survival_rate_trend_(Heap::STABLE),
+      max_gc_pause_(0),
+      max_alive_after_gc_(0),
+      min_in_mutator_(kMaxInt),
+      alive_after_last_gc_(0),
+      last_gc_end_timestamp_(0.0),
+      page_watermark_invalidated_mark_(1 << Page::WATERMARK_INVALIDATED),
+      number_idle_notifications_(0),
+      last_idle_notification_gc_count_(0),
+      last_idle_notification_gc_count_init_(false),
+      configured_(false),
+      is_safe_to_read_maps_(true) {
+  // Allow build-time customization of the max semispace size. Building
+  // V8 with snapshots and a non-default max semispace size is much
+  // easier if you can define it as part of the build environment.
+#if defined(V8_MAX_SEMISPACE_SIZE)
+  max_semispace_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE;
+#endif
 
-intptr_t GCTracer::alive_after_last_gc_ = 0;
-double GCTracer::last_gc_end_timestamp_ = 0.0;
-int GCTracer::max_gc_pause_ = 0;
-intptr_t GCTracer::max_alive_after_gc_ = 0;
-int GCTracer::min_in_mutator_ = kMaxInt;
+  memset(roots_, 0, sizeof(roots_[0]) * kRootListLength);
+  global_contexts_list_ = NULL;
+  mark_compact_collector_.heap_ = this;
+  external_string_table_.heap_ = this;
+}
+
 
 intptr_t Heap::Capacity() {
   if (!HasBeenSetup()) return 0;
@@ -190,7 +185,7 @@
 intptr_t Heap::CommittedMemoryExecutable() {
   if (!HasBeenSetup()) return 0;
 
-  return MemoryAllocator::SizeExecutable();
+  return isolate()->memory_allocator()->SizeExecutable();
 }
 
 
@@ -217,8 +212,8 @@
 
 
 int Heap::GcSafeSizeOfOldObject(HeapObject* object) {
-  ASSERT(!Heap::InNewSpace(object));  // Code only works for old objects.
-  ASSERT(!MarkCompactCollector::are_map_pointers_encoded());
+  ASSERT(!HEAP->InNewSpace(object));  // Code only works for old objects.
+  ASSERT(!HEAP->mark_compact_collector()->are_map_pointers_encoded());
   MapWord map_word = object->map_word();
   map_word.ClearMark();
   map_word.ClearOverflow();
@@ -227,8 +222,8 @@
 
 
 int Heap::GcSafeSizeOfOldObjectWithEncodedMap(HeapObject* object) {
-  ASSERT(!Heap::InNewSpace(object));  // Code only works for old objects.
-  ASSERT(MarkCompactCollector::are_map_pointers_encoded());
+  ASSERT(!HEAP->InNewSpace(object));  // Code only works for old objects.
+  ASSERT(HEAP->mark_compact_collector()->are_map_pointers_encoded());
   uint32_t marker = Memory::uint32_at(object->address());
   if (marker == MarkCompactCollector::kSingleFreeEncoding) {
     return kIntSize;
@@ -236,7 +231,7 @@
     return Memory::int_at(object->address() + kIntSize);
   } else {
     MapWord map_word = object->map_word();
-    Address map_address = map_word.DecodeMapAddress(Heap::map_space());
+    Address map_address = map_word.DecodeMapAddress(HEAP->map_space());
     Map* map = reinterpret_cast<Map*>(HeapObject::FromAddress(map_address));
     return object->SizeFromMap(map);
   }
@@ -246,19 +241,20 @@
 GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space) {
   // Is global GC requested?
   if (space != NEW_SPACE || FLAG_gc_global) {
-    Counters::gc_compactor_caused_by_request.Increment();
+    isolate_->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();
+    isolate_->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();
+    isolate_->counters()->
+        gc_compactor_caused_by_oldspace_exhaustion()->Increment();
     return MARK_COMPACTOR;
   }
 
@@ -271,8 +267,9 @@
   // 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();
+  if (isolate_->memory_allocator()->MaxAvailable() <= new_space_.Size()) {
+    isolate_->counters()->
+        gc_compactor_caused_by_oldspace_exhaustion()->Increment();
     return MARK_COMPACTOR;
   }
 
@@ -317,8 +314,8 @@
   if (!FLAG_trace_gc_verbose) return;
   PrintF("Memory allocator,   used: %8" V8_PTR_PREFIX "d"
              ", available: %8" V8_PTR_PREFIX "d\n",
-         MemoryAllocator::Size(),
-         MemoryAllocator::Available());
+         isolate_->memory_allocator()->Size(),
+         isolate_->memory_allocator()->Available());
   PrintF("New space,          used: %8" V8_PTR_PREFIX "d"
              ", available: %8" V8_PTR_PREFIX "d\n",
          Heap::new_space_.Size(),
@@ -383,7 +380,7 @@
 
 
 void Heap::GarbageCollectionPrologue() {
-  TranscendentalCache::Clear();
+  isolate_->transcendental_cache()->Clear();
   ClearJSFunctionResultCaches();
   gc_count_++;
   unflattened_strings_length_ = 0;
@@ -424,21 +421,24 @@
     Verify();
   }
 
-  if (FLAG_print_global_handles) GlobalHandles::Print();
+  if (FLAG_print_global_handles) isolate_->global_handles()->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(static_cast<int>(SizeOfObjects()));
+  isolate_->counters()->alive_after_last_gc()->Set(
+      static_cast<int>(SizeOfObjects()));
 
-  Counters::symbol_table_capacity.Set(symbol_table()->Capacity());
-  Counters::number_of_symbols.Set(symbol_table()->NumberOfElements());
+  isolate_->counters()->symbol_table_capacity()->Set(
+      symbol_table()->Capacity());
+  isolate_->counters()->number_of_symbols()->Set(
+      symbol_table()->NumberOfElements());
 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
   ReportStatisticsAfterGC();
 #endif
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  Debug::AfterGarbageCollection();
+  isolate_->debug()->AfterGarbageCollection();
 #endif
 }
 
@@ -447,9 +447,9 @@
   // 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.
-  MarkCompactCollector::SetForceCompaction(force_compaction);
+  mark_compact_collector_.SetForceCompaction(force_compaction);
   CollectGarbage(OLD_POINTER_SPACE);
-  MarkCompactCollector::SetForceCompaction(false);
+  mark_compact_collector_.SetForceCompaction(false);
 }
 
 
@@ -457,7 +457,7 @@
   // 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.
-  MarkCompactCollector::SetForceCompaction(true);
+  mark_compact_collector()->SetForceCompaction(true);
 
   // Major GC would invoke weak handle callbacks on weakly reachable
   // handles, but won't collect weakly reachable objects until next
@@ -473,13 +473,13 @@
       break;
     }
   }
-  MarkCompactCollector::SetForceCompaction(false);
+  mark_compact_collector()->SetForceCompaction(false);
 }
 
 
 bool Heap::CollectGarbage(AllocationSpace space, GarbageCollector collector) {
   // The VM is in the GC state until exiting this function.
-  VMState state(GC);
+  VMState state(isolate_, GC);
 
 #ifdef DEBUG
   // Reset the allocation timeout to the GC interval, but make sure to
@@ -492,7 +492,7 @@
 
   bool next_gc_likely_to_collect_more = false;
 
-  { GCTracer tracer;
+  { GCTracer tracer(this);
     GarbageCollectionPrologue();
     // The GC count was incremented in the prologue.  Tell the tracer about
     // it.
@@ -502,8 +502,8 @@
     tracer.set_collector(collector);
 
     HistogramTimer* rate = (collector == SCAVENGER)
-        ? &Counters::gc_scavenger
-        : &Counters::gc_compactor;
+        ? isolate_->counters()->gc_scavenger()
+        : isolate_->counters()->gc_compactor();
     rate->Start();
     next_gc_likely_to_collect_more =
         PerformGarbageCollection(collector, &tracer);
@@ -522,7 +522,7 @@
 
 
 void Heap::PerformScavenge() {
-  GCTracer tracer;
+  GCTracer tracer(this);
   PerformGarbageCollection(SCAVENGER, &tracer);
 }
 
@@ -531,7 +531,6 @@
 // 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++) {
@@ -548,7 +547,7 @@
 static void VerifySymbolTable() {
 #ifdef DEBUG
   SymbolTableVerifier verifier;
-  Heap::symbol_table()->IterateElements(&verifier);
+  HEAP->symbol_table()->IterateElements(&verifier);
 #endif  // DEBUG
 }
 
@@ -633,7 +632,7 @@
 
 
 void Heap::ClearJSFunctionResultCaches() {
-  if (Bootstrapper::IsActive()) return;
+  if (isolate_->bootstrapper()->IsActive()) return;
 
   Object* context = global_contexts_list_;
   while (!context->IsUndefined()) {
@@ -651,8 +650,9 @@
 }
 
 
+
 void Heap::ClearNormalizedMapCaches() {
-  if (Bootstrapper::IsActive()) return;
+  if (isolate_->bootstrapper()->IsActive()) return;
 
   Object* context = global_contexts_list_;
   while (!context->IsUndefined()) {
@@ -709,7 +709,7 @@
   bool next_gc_likely_to_collect_more = false;
 
   if (collector != SCAVENGER) {
-    PROFILE(CodeMovingGCEvent());
+    PROFILE(isolate_, CodeMovingGCEvent());
   }
 
   VerifySymbolTable();
@@ -768,13 +768,13 @@
     UpdateSurvivalRateTrend(start_new_space_size);
   }
 
-  Counters::objs_since_last_young.Set(0);
+  isolate_->counters()->objs_since_last_young()->Set(0);
 
   if (collector == MARK_COMPACTOR) {
     DisableAssertNoAllocation allow_allocation;
     GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL);
     next_gc_likely_to_collect_more =
-        GlobalHandles::PostGarbageCollectionProcessing();
+        isolate_->global_handles()->PostGarbageCollectionProcessing();
   }
 
   // Update relocatables.
@@ -808,11 +808,11 @@
 
 void Heap::MarkCompact(GCTracer* tracer) {
   gc_state_ = MARK_COMPACT;
-  LOG(ResourceEvent("markcompact", "begin"));
+  LOG(isolate_, ResourceEvent("markcompact", "begin"));
 
-  MarkCompactCollector::Prepare(tracer);
+  mark_compact_collector_.Prepare(tracer);
 
-  bool is_compacting = MarkCompactCollector::IsCompacting();
+  bool is_compacting = mark_compact_collector_.IsCompacting();
 
   if (is_compacting) {
     mc_count_++;
@@ -823,15 +823,17 @@
 
   MarkCompactPrologue(is_compacting);
 
-  MarkCompactCollector::CollectGarbage();
+  is_safe_to_read_maps_ = false;
+  mark_compact_collector_.CollectGarbage();
+  is_safe_to_read_maps_ = true;
 
-  LOG(ResourceEvent("markcompact", "end"));
+  LOG(isolate_, ResourceEvent("markcompact", "end"));
 
   gc_state_ = NOT_IN_GC;
 
   Shrink();
 
-  Counters::objs_since_last_full.Set(0);
+  isolate_->counters()->objs_since_last_full()->Set(0);
 
   contexts_disposed_ = 0;
 }
@@ -840,11 +842,11 @@
 void Heap::MarkCompactPrologue(bool is_compacting) {
   // At any old GC clear the keyed lookup cache to enable collection of unused
   // maps.
-  KeyedLookupCache::Clear();
-  ContextSlotCache::Clear();
-  DescriptorLookupCache::Clear();
+  isolate_->keyed_lookup_cache()->Clear();
+  isolate_->context_slot_cache()->Clear();
+  isolate_->descriptor_lookup_cache()->Clear();
 
-  CompilationCache::MarkCompactPrologue();
+  isolate_->compilation_cache()->MarkCompactPrologue();
 
   CompletelyClearInstanceofCache();
 
@@ -868,6 +870,7 @@
 // Helper class for copying HeapObjects
 class ScavengeVisitor: public ObjectVisitor {
  public:
+  explicit ScavengeVisitor(Heap* heap) : heap_(heap) {}
 
   void VisitPointer(Object** p) { ScavengePointer(p); }
 
@@ -879,48 +882,15 @@
  private:
   void ScavengePointer(Object** p) {
     Object* object = *p;
-    if (!Heap::InNewSpace(object)) return;
+    if (!heap_->InNewSpace(object)) return;
     Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p),
                          reinterpret_cast<HeapObject*>(object));
   }
+
+  Heap* heap_;
 };
 
 
-// A queue of objects promoted during scavenge. Each object is accompanied
-// by it's size to avoid dereferencing a map pointer for scanning.
-class PromotionQueue {
- public:
-  void Initialize(Address start_address) {
-    front_ = rear_ = reinterpret_cast<intptr_t*>(start_address);
-  }
-
-  bool is_empty() { return front_ <= rear_; }
-
-  void insert(HeapObject* target, int size) {
-    *(--rear_) = reinterpret_cast<intptr_t>(target);
-    *(--rear_) = size;
-    // Assert no overflow into live objects.
-    ASSERT(reinterpret_cast<Address>(rear_) >= Heap::new_space()->top());
-  }
-
-  void remove(HeapObject** target, int* size) {
-    *target = reinterpret_cast<HeapObject*>(*(--front_));
-    *size = static_cast<int>(*(--front_));
-    // Assert no underflow.
-    ASSERT(front_ >= rear_);
-  }
-
- private:
-  // The front of the queue is higher in memory than the rear.
-  intptr_t* front_;
-  intptr_t* rear_;
-};
-
-
-// Shared state read by the scavenge collector and set by ScavengeObject.
-static PromotionQueue promotion_queue;
-
-
 #ifdef DEBUG
 // Visitor class to verify pointers in code or data space do not point into
 // new space.
@@ -929,7 +899,7 @@
   void VisitPointers(Object** start, Object**end) {
     for (Object** current = start; current < end; current++) {
       if ((*current)->IsHeapObject()) {
-        ASSERT(!Heap::InNewSpace(HeapObject::cast(*current)));
+        ASSERT(!HEAP->InNewSpace(HeapObject::cast(*current)));
       }
     }
   }
@@ -940,12 +910,12 @@
   // Verify that there are no pointers to new space in spaces where we
   // do not expect them.
   VerifyNonPointerSpacePointersVisitor v;
-  HeapObjectIterator code_it(Heap::code_space());
+  HeapObjectIterator code_it(HEAP->code_space());
   for (HeapObject* object = code_it.next();
        object != NULL; object = code_it.next())
     object->Iterate(&v);
 
-  HeapObjectIterator data_it(Heap::old_data_space());
+  HeapObjectIterator data_it(HEAP->old_data_space());
   for (HeapObject* object = data_it.next();
        object != NULL; object = data_it.next())
     object->Iterate(&v);
@@ -971,7 +941,7 @@
 
   gc_state_ = SCAVENGE;
 
-  Page::FlipMeaningOfInvalidatedWatermarkFlag();
+  Page::FlipMeaningOfInvalidatedWatermarkFlag(this);
 #ifdef DEBUG
   VerifyPageWatermarkValidity(old_pointer_space_, ALL_VALID);
   VerifyPageWatermarkValidity(map_space_, ALL_VALID);
@@ -986,10 +956,10 @@
   map_space_->FlushTopPageWatermark();
 
   // Implements Cheney's copying algorithm
-  LOG(ResourceEvent("scavenge", "begin"));
+  LOG(isolate_, ResourceEvent("scavenge", "begin"));
 
   // Clear descriptor cache.
-  DescriptorLookupCache::Clear();
+  isolate_->descriptor_lookup_cache()->Clear();
 
   // Used for updating survived_since_last_expansion_ at function end.
   intptr_t survived_watermark = PromotedSpaceSize();
@@ -1019,16 +989,17 @@
   // frees up its size in bytes from the top of the new space, and
   // objects are at least one pointer in size.
   Address new_space_front = new_space_.ToSpaceLow();
-  promotion_queue.Initialize(new_space_.ToSpaceHigh());
+  promotion_queue_.Initialize(new_space_.ToSpaceHigh());
 
-  ScavengeVisitor scavenge_visitor;
+  is_safe_to_read_maps_ = false;
+  ScavengeVisitor scavenge_visitor(this);
   // Copy roots.
   IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE);
 
   // Copy objects reachable from the old generation.  By definition,
   // there are no intergenerational pointers in code or data spaces.
   IterateDirtyRegions(old_pointer_space_,
-                      &IteratePointersInDirtyRegion,
+                      &Heap::IteratePointersInDirtyRegion,
                       &ScavengePointer,
                       WATERMARK_CAN_BE_INVALID);
 
@@ -1060,10 +1031,12 @@
       &UpdateNewSpaceReferenceInExternalStringTableEntry);
 
   LiveObjectList::UpdateReferencesForScavengeGC();
-  RuntimeProfiler::UpdateSamplesAfterScavenge();
+  isolate()->runtime_profiler()->UpdateSamplesAfterScavenge();
 
   ASSERT(new_space_front == new_space_.top());
 
+  is_safe_to_read_maps_ = true;
+
   // Set age mark.
   new_space_.set_age_mark(new_space_.top());
 
@@ -1071,18 +1044,19 @@
   IncrementYoungSurvivorsCounter(static_cast<int>(
       (PromotedSpaceSize() - survived_watermark) + new_space_.Size()));
 
-  LOG(ResourceEvent("scavenge", "end"));
+  LOG(isolate_, ResourceEvent("scavenge", "end"));
 
   gc_state_ = NOT_IN_GC;
 }
 
 
-String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Object** p) {
+String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap,
+                                                                Object** p) {
   MapWord first_word = HeapObject::cast(*p)->map_word();
 
   if (!first_word.IsForwardingAddress()) {
     // Unreachable external string can be finalized.
-    FinalizeExternalString(String::cast(*p));
+    heap->FinalizeExternalString(String::cast(*p));
     return NULL;
   }
 
@@ -1093,48 +1067,49 @@
 
 void Heap::UpdateNewSpaceReferencesInExternalStringTable(
     ExternalStringTableUpdaterCallback updater_func) {
-  ExternalStringTable::Verify();
+  external_string_table_.Verify();
 
-  if (ExternalStringTable::new_space_strings_.is_empty()) return;
+  if (external_string_table_.new_space_strings_.is_empty()) return;
 
-  Object** start = &ExternalStringTable::new_space_strings_[0];
-  Object** end = start + ExternalStringTable::new_space_strings_.length();
+  Object** start = &external_string_table_.new_space_strings_[0];
+  Object** end = start + external_string_table_.new_space_strings_.length();
   Object** last = start;
 
   for (Object** p = start; p < end; ++p) {
-    ASSERT(Heap::InFromSpace(*p));
-    String* target = updater_func(p);
+    ASSERT(InFromSpace(*p));
+    String* target = updater_func(this, p);
 
     if (target == NULL) continue;
 
     ASSERT(target->IsExternalString());
 
-    if (Heap::InNewSpace(target)) {
+    if (InNewSpace(target)) {
       // String is still in new space.  Update the table entry.
       *last = target;
       ++last;
     } else {
       // String got promoted.  Move it to the old string list.
-      ExternalStringTable::AddOldString(target);
+      external_string_table_.AddOldString(target);
     }
   }
 
   ASSERT(last <= end);
-  ExternalStringTable::ShrinkNewStrings(static_cast<int>(last - start));
+  external_string_table_.ShrinkNewStrings(static_cast<int>(last - start));
 }
 
 
-static Object* ProcessFunctionWeakReferences(Object* function,
+static Object* ProcessFunctionWeakReferences(Heap* heap,
+                                             Object* function,
                                              WeakObjectRetainer* retainer) {
-  Object* head = Heap::undefined_value();
+  Object* head = heap->undefined_value();
   JSFunction* tail = NULL;
   Object* candidate = function;
-  while (!candidate->IsUndefined()) {
+  while (candidate != heap->undefined_value()) {
     // Check whether to keep the candidate in the list.
     JSFunction* candidate_function = reinterpret_cast<JSFunction*>(candidate);
     Object* retain = retainer->RetainAs(candidate);
     if (retain != NULL) {
-      if (head->IsUndefined()) {
+      if (head == heap->undefined_value()) {
         // First element in the list.
         head = candidate_function;
       } else {
@@ -1151,7 +1126,7 @@
 
   // Terminate the list if there is one or more elements.
   if (tail != NULL) {
-    tail->set_next_function_link(Heap::undefined_value());
+    tail->set_next_function_link(heap->undefined_value());
   }
 
   return head;
@@ -1162,18 +1137,19 @@
   Object* head = undefined_value();
   Context* tail = NULL;
   Object* candidate = global_contexts_list_;
-  while (!candidate->IsUndefined()) {
+  while (candidate != undefined_value()) {
     // Check whether to keep the candidate in the list.
     Context* candidate_context = reinterpret_cast<Context*>(candidate);
     Object* retain = retainer->RetainAs(candidate);
     if (retain != NULL) {
-      if (head->IsUndefined()) {
+      if (head == undefined_value()) {
         // First element in the list.
         head = candidate_context;
       } else {
         // Subsequent elements in the list.
         ASSERT(tail != NULL);
-        tail->set_unchecked(Context::NEXT_CONTEXT_LINK,
+        tail->set_unchecked(this,
+                            Context::NEXT_CONTEXT_LINK,
                             candidate_context,
                             UPDATE_WRITE_BARRIER);
       }
@@ -1183,9 +1159,11 @@
       // Process the weak list of optimized functions for the context.
       Object* function_list_head =
           ProcessFunctionWeakReferences(
+              this,
               candidate_context->get(Context::OPTIMIZED_FUNCTIONS_LIST),
               retainer);
-      candidate_context->set_unchecked(Context::OPTIMIZED_FUNCTIONS_LIST,
+      candidate_context->set_unchecked(this,
+                                       Context::OPTIMIZED_FUNCTIONS_LIST,
                                        function_list_head,
                                        UPDATE_WRITE_BARRIER);
     }
@@ -1195,21 +1173,22 @@
 
   // Terminate the list if there is one or more elements.
   if (tail != NULL) {
-    tail->set_unchecked(Context::NEXT_CONTEXT_LINK,
+    tail->set_unchecked(this,
+                        Context::NEXT_CONTEXT_LINK,
                         Heap::undefined_value(),
                         UPDATE_WRITE_BARRIER);
   }
 
   // Update the head of the list of contexts.
-  Heap::global_contexts_list_ = head;
+  global_contexts_list_ = head;
 }
 
 
 class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> {
  public:
-  static inline void VisitPointer(Object** p) {
+  static inline void VisitPointer(Heap* heap, Object** p) {
     Object* object = *p;
-    if (!Heap::InNewSpace(object)) return;
+    if (!heap->InNewSpace(object)) return;
     Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p),
                          reinterpret_cast<HeapObject*>(object));
   }
@@ -1230,10 +1209,10 @@
     }
 
     // Promote and process all the to-be-promoted objects.
-    while (!promotion_queue.is_empty()) {
+    while (!promotion_queue_.is_empty()) {
       HeapObject* target;
       int size;
-      promotion_queue.remove(&target, &size);
+      promotion_queue_.remove(&target, &size);
 
       // Promoted object might be already partially visited
       // during dirty regions iteration. Thus we search specificly
@@ -1303,7 +1282,7 @@
   enum SizeRestriction { SMALL, UNKNOWN_SIZE };
 
 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
-  static void RecordCopiedObject(HeapObject* obj) {
+  static void RecordCopiedObject(Heap* heap, HeapObject* obj) {
     bool should_record = false;
 #ifdef DEBUG
     should_record = FLAG_heap_stats;
@@ -1312,10 +1291,10 @@
     should_record = should_record || FLAG_log_gc;
 #endif
     if (should_record) {
-      if (Heap::new_space()->Contains(obj)) {
-        Heap::new_space()->RecordAllocation(obj);
+      if (heap->new_space()->Contains(obj)) {
+        heap->new_space()->RecordAllocation(obj);
       } else {
-        Heap::new_space()->RecordPromotion(obj);
+        heap->new_space()->RecordPromotion(obj);
       }
     }
   }
@@ -1324,24 +1303,28 @@
   // 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.
-  INLINE(static HeapObject* MigrateObject(HeapObject* source,
+  INLINE(static HeapObject* MigrateObject(Heap* heap,
+                                          HeapObject* source,
                                           HeapObject* target,
                                           int size)) {
     // Copy the content of source to target.
-    Heap::CopyBlock(target->address(), source->address(), size);
+    heap->CopyBlock(target->address(), source->address(), size);
 
     // Set the forwarding address.
     source->set_map_word(MapWord::FromForwardingAddress(target));
 
 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
     // Update NewSpace stats if necessary.
-    RecordCopiedObject(target);
+    RecordCopiedObject(heap, target);
 #endif
-    HEAP_PROFILE(ObjectMoveEvent(source->address(), target->address()));
+    HEAP_PROFILE(heap, ObjectMoveEvent(source->address(), target->address()));
 #if defined(ENABLE_LOGGING_AND_PROFILING)
-    if (Logger::is_logging() || CpuProfiler::is_profiling()) {
+    Isolate* isolate = heap->isolate();
+    if (isolate->logger()->is_logging() ||
+        isolate->cpu_profiler()->is_profiling()) {
       if (target->IsSharedFunctionInfo()) {
-        PROFILE(SFIMoveEvent(source->address(), target->address()));
+        PROFILE(isolate, SharedFunctionInfoMoveEvent(
+            source->address(), target->address()));
       }
     }
 #endif
@@ -1358,36 +1341,37 @@
            (object_size <= Page::kMaxHeapObjectSize));
     ASSERT(object->Size() == object_size);
 
-    if (Heap::ShouldBePromoted(object->address(), object_size)) {
+    Heap* heap = map->heap();
+    if (heap->ShouldBePromoted(object->address(), object_size)) {
       MaybeObject* maybe_result;
 
       if ((size_restriction != SMALL) &&
           (object_size > Page::kMaxHeapObjectSize)) {
-        maybe_result = Heap::lo_space()->AllocateRawFixedArray(object_size);
+        maybe_result = heap->lo_space()->AllocateRawFixedArray(object_size);
       } else {
         if (object_contents == DATA_OBJECT) {
-          maybe_result = Heap::old_data_space()->AllocateRaw(object_size);
+          maybe_result = heap->old_data_space()->AllocateRaw(object_size);
         } else {
-          maybe_result = Heap::old_pointer_space()->AllocateRaw(object_size);
+          maybe_result = heap->old_pointer_space()->AllocateRaw(object_size);
         }
       }
 
       Object* result = NULL;  // Initialization to please compiler.
       if (maybe_result->ToObject(&result)) {
         HeapObject* target = HeapObject::cast(result);
-        *slot = MigrateObject(object, target, object_size);
+        *slot = MigrateObject(heap, object , target, object_size);
 
         if (object_contents == POINTER_OBJECT) {
-          promotion_queue.insert(target, object_size);
+          heap->promotion_queue()->insert(target, object_size);
         }
 
-        Heap::tracer()->increment_promoted_objects_size(object_size);
+        heap->tracer()->increment_promoted_objects_size(object_size);
         return;
       }
     }
     Object* result =
-        Heap::new_space()->AllocateRaw(object_size)->ToObjectUnchecked();
-    *slot = MigrateObject(object, HeapObject::cast(result), object_size);
+        heap->new_space()->AllocateRaw(object_size)->ToObjectUnchecked();
+    *slot = MigrateObject(heap, object, HeapObject::cast(result), object_size);
     return;
   }
 
@@ -1438,13 +1422,14 @@
                                                HeapObject* object) {
     ASSERT(IsShortcutCandidate(map->instance_type()));
 
-    if (ConsString::cast(object)->unchecked_second() == Heap::empty_string()) {
+    if (ConsString::cast(object)->unchecked_second() ==
+        map->heap()->empty_string()) {
       HeapObject* first =
           HeapObject::cast(ConsString::cast(object)->unchecked_first());
 
       *slot = first;
 
-      if (!Heap::InNewSpace(first)) {
+      if (!map->heap()->InNewSpace(first)) {
         object->set_map_word(MapWord::FromForwardingAddress(first));
         return;
       }
@@ -1495,7 +1480,7 @@
 
 
 void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
-  ASSERT(InFromSpace(object));
+  ASSERT(HEAP->InFromSpace(object));
   MapWord first_word = object->map_word();
   ASSERT(!first_word.IsForwardingAddress());
   Map* map = first_word.ToMap();
@@ -1503,11 +1488,6 @@
 }
 
 
-void Heap::ScavengePointer(HeapObject** p) {
-  ScavengeObject(p, *p);
-}
-
-
 MaybeObject* Heap::AllocatePartialMap(InstanceType instance_type,
                                       int instance_size) {
   Object* result;
@@ -1519,9 +1499,8 @@
   reinterpret_cast<Map*>(result)->set_map(raw_unchecked_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_visitor_id(
-          StaticVisitorBase::GetVisitorId(instance_type, instance_size));
+  reinterpret_cast<Map*>(result)->set_visitor_id(
+        StaticVisitorBase::GetVisitorId(instance_type, instance_size));
   reinterpret_cast<Map*>(result)->set_inobject_properties(0);
   reinterpret_cast<Map*>(result)->set_pre_allocated_property_fields(0);
   reinterpret_cast<Map*>(result)->set_unused_property_fields(0);
@@ -1630,6 +1609,7 @@
     if (!maybe_obj->ToObject(&obj)) return false;
   }
   set_null_value(obj);
+  Oddball::cast(obj)->set_kind(Oddball::kNull);
 
   // Allocate the empty descriptor array.
   { MaybeObject* maybe_obj = AllocateEmptyFixedArray();
@@ -1707,10 +1687,10 @@
   set_empty_byte_array(ByteArray::cast(obj));
 
   { MaybeObject* maybe_obj =
-        AllocateMap(PIXEL_ARRAY_TYPE, PixelArray::kAlignedSize);
+        AllocateMap(EXTERNAL_PIXEL_ARRAY_TYPE, ExternalArray::kAlignedSize);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
-  set_pixel_array_map(Map::cast(obj));
+  set_external_pixel_array_map(Map::cast(obj));
 
   { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_BYTE_ARRAY_TYPE,
                                          ExternalArray::kAlignedSize);
@@ -1821,7 +1801,7 @@
   }
   set_message_object_map(Map::cast(obj));
 
-  ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
+  ASSERT(!InNewSpace(empty_fixed_array()));
   return true;
 }
 
@@ -1874,12 +1854,13 @@
 
 
 MaybeObject* Heap::CreateOddball(const char* to_string,
-                                 Object* to_number) {
+                                 Object* to_number,
+                                 byte kind) {
   Object* result;
   { MaybeObject* maybe_result = Allocate(oddball_map(), OLD_DATA_SPACE);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
-  return Oddball::cast(result)->Initialize(to_string, to_number);
+  return Oddball::cast(result)->Initialize(to_string, to_number, kind);
 }
 
 
@@ -1891,7 +1872,7 @@
   }
   set_neander_map(Map::cast(obj));
 
-  { MaybeObject* maybe_obj = Heap::AllocateJSObjectFromMap(neander_map());
+  { MaybeObject* maybe_obj = AllocateJSObjectFromMap(neander_map());
     if (!maybe_obj->ToObject(&obj)) return false;
   }
   Object* elements;
@@ -1906,20 +1887,6 @@
 }
 
 
-void Heap::CreateCEntryStub() {
-  CEntryStub stub(1);
-  set_c_entry_code(*stub.GetCode());
-}
-
-
-#if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP
-void Heap::CreateRegExpCEntryStub() {
-  RegExpCEntryStub stub;
-  set_re_c_entry_code(*stub.GetCode());
-}
-#endif
-
-
 void Heap::CreateJSEntryStub() {
   JSEntryStub stub;
   set_js_entry_code(*stub.GetCode());
@@ -1932,14 +1899,6 @@
 }
 
 
-#if V8_TARGET_ARCH_ARM
-void Heap::CreateDirectCEntryStub() {
-  DirectCEntryStub stub;
-  set_direct_c_entry_code(*stub.GetCode());
-}
-#endif
-
-
 void Heap::CreateFixedStubs() {
   // Here we create roots for fixed stubs. They are needed at GC
   // for cooking and uncooking (check out frames.cc).
@@ -1947,22 +1906,15 @@
   // stub cache for these stubs.
   HandleScope scope;
   // gcc-4.4 has problem generating correct code of following snippet:
-  // {  CEntryStub stub;
-  //    c_entry_code_ = *stub.GetCode();
+  // {  JSEntryStub stub;
+  //    js_entry_code_ = *stub.GetCode();
   // }
-  // {  DebuggerStatementStub stub;
-  //    debugger_statement_code_ = *stub.GetCode();
+  // {  JSConstructEntryStub stub;
+  //    js_construct_entry_code_ = *stub.GetCode();
   // }
   // To workaround the problem, make separate functions without inlining.
-  Heap::CreateCEntryStub();
   Heap::CreateJSEntryStub();
   Heap::CreateJSConstructEntryStub();
-#if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP
-  Heap::CreateRegExpCEntryStub();
-#endif
-#if V8_TARGET_ARCH_ARM
-  Heap::CreateDirectCEntryStub();
-#endif
 }
 
 
@@ -1985,6 +1937,7 @@
     if (!maybe_obj->ToObject(&obj)) return false;
   }
   set_undefined_value(obj);
+  Oddball::cast(obj)->set_kind(Oddball::kUndefined);
   ASSERT(!InNewSpace(undefined_value()));
 
   // Allocate initial symbol table.
@@ -2004,39 +1957,50 @@
 
   // Allocate the null_value
   { MaybeObject* maybe_obj =
-        Oddball::cast(null_value())->Initialize("null", Smi::FromInt(0));
+        Oddball::cast(null_value())->Initialize("null",
+                                                Smi::FromInt(0),
+                                                Oddball::kNull);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
 
-  { MaybeObject* maybe_obj = CreateOddball("true", Smi::FromInt(1));
+  { MaybeObject* maybe_obj = CreateOddball("true",
+                                           Smi::FromInt(1),
+                                           Oddball::kTrue);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
   set_true_value(obj);
 
-  { MaybeObject* maybe_obj = CreateOddball("false", Smi::FromInt(0));
+  { MaybeObject* maybe_obj = CreateOddball("false",
+                                           Smi::FromInt(0),
+                                           Oddball::kFalse);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
   set_false_value(obj);
 
-  { MaybeObject* maybe_obj = CreateOddball("hole", Smi::FromInt(-1));
+  { MaybeObject* maybe_obj = CreateOddball("hole",
+                                           Smi::FromInt(-1),
+                                           Oddball::kTheHole);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
   set_the_hole_value(obj);
 
   { MaybeObject* maybe_obj = CreateOddball("arguments_marker",
-                                           Smi::FromInt(-4));
+                                           Smi::FromInt(-4),
+                                           Oddball::kArgumentMarker);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
   set_arguments_marker(obj);
 
-  { MaybeObject* maybe_obj =
-        CreateOddball("no_interceptor_result_sentinel", Smi::FromInt(-2));
+  { MaybeObject* maybe_obj = CreateOddball("no_interceptor_result_sentinel",
+                                           Smi::FromInt(-2),
+                                           Oddball::kOther);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
   set_no_interceptor_result_sentinel(obj);
 
-  { MaybeObject* maybe_obj =
-        CreateOddball("termination_exception", Smi::FromInt(-3));
+  { MaybeObject* maybe_obj = CreateOddball("termination_exception",
+                                           Smi::FromInt(-3),
+                                           Oddball::kOther);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
   set_termination_exception(obj);
@@ -2098,7 +2062,8 @@
   { MaybeObject* maybe_obj = StringDictionary::Allocate(Runtime::kNumFunctions);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
-  { MaybeObject* maybe_obj = Runtime::InitializeIntrinsicFunctionNames(obj);
+  { MaybeObject* maybe_obj = Runtime::InitializeIntrinsicFunctionNames(this,
+                                                                       obj);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
   set_intrinsic_function_names(StringDictionary::cast(obj));
@@ -2118,20 +2083,20 @@
   }
   set_natives_source_cache(FixedArray::cast(obj));
 
-  // Handling of script id generation is in Factory::NewScript.
+  // Handling of script id generation is in FACTORY->NewScript.
   set_last_script_id(undefined_value());
 
   // Initialize keyed lookup cache.
-  KeyedLookupCache::Clear();
+  isolate_->keyed_lookup_cache()->Clear();
 
   // Initialize context slot cache.
-  ContextSlotCache::Clear();
+  isolate_->context_slot_cache()->Clear();
 
   // Initialize descriptor cache.
-  DescriptorLookupCache::Clear();
+  isolate_->descriptor_lookup_cache()->Clear();
 
   // Initialize compilation cache.
-  CompilationCache::Clear();
+  isolate_->compilation_cache()->Clear();
 
   return true;
 }
@@ -2155,7 +2120,7 @@
   // Flush the number to string cache.
   int len = number_string_cache()->length();
   for (int i = 0; i < len; i++) {
-    number_string_cache()->set_undefined(i);
+    number_string_cache()->set_undefined(this, i);
   }
 }
 
@@ -2207,7 +2172,7 @@
 
 MaybeObject* Heap::NumberToString(Object* number,
                                   bool check_number_string_cache) {
-  Counters::number_to_string_runtime.Increment();
+  isolate_->counters()->number_to_string_runtime()->Increment();
   if (check_number_string_cache) {
     Object* cached = GetNumberStringCache(number);
     if (cached != undefined_value()) {
@@ -2257,6 +2222,8 @@
       return kExternalUnsignedIntArrayMapRootIndex;
     case kExternalFloatArray:
       return kExternalFloatArrayMapRootIndex;
+    case kExternalPixelArray:
+      return kExternalPixelArrayMapRootIndex;
     default:
       UNREACHABLE();
       return kUndefinedValueRootIndex;
@@ -2308,10 +2275,11 @@
 
   SharedFunctionInfo* share = SharedFunctionInfo::cast(result);
   share->set_name(name);
-  Code* illegal = Builtins::builtin(Builtins::Illegal);
+  Code* illegal = isolate_->builtins()->builtin(Builtins::kIllegal);
   share->set_code(illegal);
   share->set_scope_info(SerializedScopeInfo::Empty());
-  Code* construct_stub = Builtins::builtin(Builtins::JSConstructStubGeneric);
+  Code* construct_stub = isolate_->builtins()->builtin(
+      Builtins::kJSConstructStubGeneric);
   share->set_construct_stub(construct_stub);
   share->set_expected_nof_properties(0);
   share->set_length(0);
@@ -2369,20 +2337,21 @@
 
 
 MUST_USE_RESULT static inline MaybeObject* MakeOrFindTwoCharacterString(
+    Heap* heap,
     uint32_t c1,
     uint32_t c2) {
   String* symbol;
   // Numeric strings have a different hash algorithm not known by
   // LookupTwoCharsSymbolIfExists, so we skip this step for such strings.
   if ((!Between(c1, '0', '9') || !Between(c2, '0', '9')) &&
-      Heap::symbol_table()->LookupTwoCharsSymbolIfExists(c1, c2, &symbol)) {
+      heap->symbol_table()->LookupTwoCharsSymbolIfExists(c1, c2, &symbol)) {
     return symbol;
   // Now we know the length is 2, we might as well make use of that fact
   // when building the new string.
   } else if ((c1 | c2) <= String::kMaxAsciiCharCodeU) {  // We can do this
     ASSERT(IsPowerOf2(String::kMaxAsciiCharCodeU + 1));  // because of this.
     Object* result;
-    { MaybeObject* maybe_result = Heap::AllocateRawAsciiString(2);
+    { MaybeObject* maybe_result = heap->AllocateRawAsciiString(2);
       if (!maybe_result->ToObject(&result)) return maybe_result;
     }
     char* dest = SeqAsciiString::cast(result)->GetChars();
@@ -2391,7 +2360,7 @@
     return result;
   } else {
     Object* result;
-    { MaybeObject* maybe_result = Heap::AllocateRawTwoByteString(2);
+    { MaybeObject* maybe_result = heap->AllocateRawTwoByteString(2);
       if (!maybe_result->ToObject(&result)) return maybe_result;
     }
     uc16* dest = SeqTwoByteString::cast(result)->GetChars();
@@ -2421,7 +2390,7 @@
   if (length == 2) {
     unsigned c1 = first->Get(0);
     unsigned c2 = second->Get(0);
-    return MakeOrFindTwoCharacterString(c1, c2);
+    return MakeOrFindTwoCharacterString(this, c1, c2);
   }
 
   bool first_is_ascii = first->IsAsciiRepresentation();
@@ -2431,7 +2400,7 @@
   // Make sure that an out of memory exception is thrown if the length
   // of the new cons string is too large.
   if (length > String::kMaxLength || length < 0) {
-    Top::context()->mark_out_of_memory();
+    isolate()->context()->mark_out_of_memory();
     return Failure::OutOfMemoryException();
   }
 
@@ -2443,7 +2412,7 @@
     is_ascii_data_in_two_byte_string =
         first->HasOnlyAsciiChars() && second->HasOnlyAsciiChars();
     if (is_ascii_data_in_two_byte_string) {
-      Counters::string_add_runtime_ext_to_ascii.Increment();
+      isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment();
     }
   }
 
@@ -2484,6 +2453,7 @@
         char* dest = SeqAsciiString::cast(result)->GetChars();
         String::WriteToFlat(first, dest, 0, first_length);
         String::WriteToFlat(second, dest + first_length, 0, second_length);
+        isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment();
         return result;
       }
 
@@ -2525,15 +2495,14 @@
   int length = end - start;
 
   if (length == 1) {
-    return Heap::LookupSingleCharacterStringFromCode(
-        buffer->Get(start));
+    return LookupSingleCharacterStringFromCode(buffer->Get(start));
   } else if (length == 2) {
     // Optimization for 2-byte strings often used as keys in a decompression
     // dictionary.  Check whether we already have the string in the symbol
     // table to prevent creation of many unneccesary strings.
     unsigned c1 = buffer->Get(start);
     unsigned c2 = buffer->Get(start + 1);
-    return MakeOrFindTwoCharacterString(c1, c2);
+    return MakeOrFindTwoCharacterString(this, c1, c2);
   }
 
   // Make an attempt to flatten the buffer to reduce access time.
@@ -2565,7 +2534,7 @@
     ExternalAsciiString::Resource* resource) {
   size_t length = resource->length();
   if (length > static_cast<size_t>(String::kMaxLength)) {
-    Top::context()->mark_out_of_memory();
+    isolate()->context()->mark_out_of_memory();
     return Failure::OutOfMemoryException();
   }
 
@@ -2588,7 +2557,7 @@
     ExternalTwoByteString::Resource* resource) {
   size_t length = resource->length();
   if (length > static_cast<size_t>(String::kMaxLength)) {
-    Top::context()->mark_out_of_memory();
+    isolate()->context()->mark_out_of_memory();
     return Failure::OutOfMemoryException();
   }
 
@@ -2598,7 +2567,7 @@
   bool is_ascii = length <= kAsciiCheckLengthLimit &&
       String::IsAscii(resource->data(), static_cast<int>(length));
   Map* map = is_ascii ?
-      Heap::external_string_with_ascii_data_map() : Heap::external_string_map();
+      external_string_with_ascii_data_map() : external_string_map();
   Object* result;
   { MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
     if (!maybe_result->ToObject(&result)) return maybe_result;
@@ -2615,8 +2584,8 @@
 
 MaybeObject* 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;
+    Object* value = single_character_string_cache()->get(code);
+    if (value != undefined_value()) return value;
 
     char buffer[1];
     buffer[0] = static_cast<char>(code);
@@ -2624,12 +2593,12 @@
     MaybeObject* maybe_result = LookupSymbol(Vector<const char>(buffer, 1));
 
     if (!maybe_result->ToObject(&result)) return maybe_result;
-    Heap::single_character_string_cache()->set(code, result);
+    single_character_string_cache()->set(code, result);
     return result;
   }
 
   Object* result;
-  { MaybeObject* maybe_result = Heap::AllocateRawTwoByteString(1);
+  { MaybeObject* maybe_result = AllocateRawTwoByteString(1);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   String* answer = String::cast(result);
@@ -2691,24 +2660,6 @@
 }
 
 
-MaybeObject* Heap::AllocatePixelArray(int length,
-                                 uint8_t* external_pointer,
-                                 PretenureFlag pretenure) {
-  AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
-  Object* result;
-  { MaybeObject* maybe_result =
-        AllocateRaw(PixelArray::kAlignedSize, space, OLD_DATA_SPACE);
-    if (!maybe_result->ToObject(&result)) return maybe_result;
-  }
-
-  reinterpret_cast<PixelArray*>(result)->set_map(pixel_array_map());
-  reinterpret_cast<PixelArray*>(result)->set_length(length);
-  reinterpret_cast<PixelArray*>(result)->set_external_pointer(external_pointer);
-
-  return result;
-}
-
-
 MaybeObject* Heap::AllocateExternalArray(int length,
                                          ExternalArrayType array_type,
                                          void* external_pointer,
@@ -2733,7 +2684,8 @@
 
 MaybeObject* Heap::CreateCode(const CodeDesc& desc,
                               Code::Flags flags,
-                              Handle<Object> self_reference) {
+                              Handle<Object> self_reference,
+                              bool immovable) {
   // Allocate ByteArray before the Code object, so that we do not risk
   // leaving uninitialized Code object (and breaking the heap).
   Object* reloc_info;
@@ -2741,12 +2693,14 @@
     if (!maybe_reloc_info->ToObject(&reloc_info)) return maybe_reloc_info;
   }
 
-  // Compute size
+  // Compute size.
   int body_size = RoundUp(desc.instr_size, kObjectAlignment);
   int obj_size = Code::SizeFor(body_size);
   ASSERT(IsAligned(static_cast<intptr_t>(obj_size), kCodeAlignment));
   MaybeObject* maybe_result;
-  if (obj_size > MaxObjectSizeInPagedSpace()) {
+  // Large code objects and code objects which should stay at a fixed address
+  // are allocated in large object space.
+  if (obj_size > MaxObjectSizeInPagedSpace() || immovable) {
     maybe_result = lo_space_->AllocateRawCode(obj_size);
   } else {
     maybe_result = code_space_->AllocateRaw(obj_size);
@@ -2758,7 +2712,8 @@
   // Initialize the object
   HeapObject::cast(result)->set_map(code_map());
   Code* code = Code::cast(result);
-  ASSERT(!CodeRange::exists() || CodeRange::contains(code->address()));
+  ASSERT(!isolate_->code_range()->exists() ||
+      isolate_->code_range()->contains(code->address()));
   code->set_instruction_size(desc.instr_size);
   code->set_relocation_info(ByteArray::cast(reloc_info));
   code->set_flags(flags);
@@ -2804,7 +2759,8 @@
   CopyBlock(new_addr, old_addr, obj_size);
   // Relocate the copy.
   Code* new_code = Code::cast(result);
-  ASSERT(!CodeRange::exists() || CodeRange::contains(code->address()));
+  ASSERT(!isolate_->code_range()->exists() ||
+      isolate_->code_range()->contains(code->address()));
   new_code->Relocate(new_addr - old_addr);
   return new_code;
 }
@@ -2853,7 +2809,8 @@
   memcpy(new_code->relocation_start(), reloc_info.start(), reloc_info.length());
 
   // Relocate the copy.
-  ASSERT(!CodeRange::exists() || CodeRange::contains(code->address()));
+  ASSERT(!isolate_->code_range()->exists() ||
+      isolate_->code_range()->contains(code->address()));
   new_code->Relocate(new_addr - old_addr);
 
 #ifdef DEBUG
@@ -2877,7 +2834,7 @@
   }
   HeapObject::cast(result)->set_map(map);
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  ProducerHeapProfile::RecordJSObjectAllocation(result);
+  isolate_->producer_heap_profile()->RecordJSObjectAllocation(result);
 #endif
   return result;
 }
@@ -2939,22 +2896,34 @@
   // To get fast allocation and map sharing for arguments objects we
   // allocate them based on an arguments boilerplate.
 
+  JSObject* boilerplate;
+  int arguments_object_size;
+  bool strict_mode_callee = callee->IsJSFunction() &&
+                            JSFunction::cast(callee)->shared()->strict_mode();
+  if (strict_mode_callee) {
+    boilerplate =
+        isolate()->context()->global_context()->
+            strict_mode_arguments_boilerplate();
+    arguments_object_size = kArgumentsObjectSizeStrict;
+  } else {
+    boilerplate =
+        isolate()->context()->global_context()->arguments_boilerplate();
+    arguments_object_size = kArgumentsObjectSize;
+  }
+
   // 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();
-
   // Check that the size of the boilerplate matches our
   // expectations. The ArgumentsAccessStub::GenerateNewObject relies
   // on the size being a known constant.
-  ASSERT(kArgumentsObjectSize == boilerplate->map()->instance_size());
+  ASSERT(arguments_object_size == boilerplate->map()->instance_size());
 
   // Do the allocation.
   Object* result;
   { MaybeObject* maybe_result =
-        AllocateRaw(kArgumentsObjectSize, NEW_SPACE, OLD_POINTER_SPACE);
+        AllocateRaw(arguments_object_size, NEW_SPACE, OLD_POINTER_SPACE);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
 
@@ -2963,14 +2932,17 @@
   // barrier here.
   CopyBlock(HeapObject::cast(result)->address(),
             boilerplate->address(),
-            kArgumentsObjectSize);
+            JSObject::kHeaderSize);
 
-  // Set the two properties.
-  JSObject::cast(result)->InObjectPropertyAtPut(arguments_callee_index,
-                                                callee);
-  JSObject::cast(result)->InObjectPropertyAtPut(arguments_length_index,
+  // Set the length property.
+  JSObject::cast(result)->InObjectPropertyAtPut(kArgumentsLengthIndex,
                                                 Smi::FromInt(length),
                                                 SKIP_WRITE_BARRIER);
+  // Set the callee property for non-strict mode arguments object only.
+  if (!strict_mode_callee) {
+    JSObject::cast(result)->InObjectPropertyAtPut(kArgumentsCalleeIndex,
+                                                  callee);
+  }
 
   // Check the state of the object
   ASSERT(JSObject::cast(result)->HasFastProperties());
@@ -3002,8 +2974,7 @@
   int instance_size = fun->shared()->CalculateInstanceSize();
   int in_object_properties = fun->shared()->CalculateInObjectProperties();
   Object* map_obj;
-  { MaybeObject* maybe_map_obj =
-        Heap::AllocateMap(JS_OBJECT_TYPE, instance_size);
+  { MaybeObject* maybe_map_obj = AllocateMap(JS_OBJECT_TYPE, instance_size);
     if (!maybe_map_obj->ToObject(&map_obj)) return maybe_map_obj;
   }
 
@@ -3199,7 +3170,7 @@
     PropertyDetails d =
         PropertyDetails(details.attributes(), CALLBACKS, details.index());
     Object* value = descs->GetCallbacksObject(i);
-    { MaybeObject* maybe_value = Heap::AllocateJSGlobalPropertyCell(value);
+    { MaybeObject* maybe_value = AllocateJSGlobalPropertyCell(value);
       if (!maybe_value->ToObject(&value)) return maybe_value;
     }
 
@@ -3225,7 +3196,7 @@
 
   // Setup the global object as a normalized object.
   global->set_map(new_map);
-  global->map()->set_instance_descriptors(Heap::empty_descriptor_array());
+  global->map()->set_instance_descriptors(empty_descriptor_array());
   global->set_properties(dictionary);
 
   // Make sure result is a global object with properties in dictionary.
@@ -3264,7 +3235,7 @@
     { MaybeObject* maybe_clone = new_space_.AllocateRaw(object_size);
       if (!maybe_clone->ToObject(&clone)) return maybe_clone;
     }
-    ASSERT(Heap::InNewSpace(clone));
+    ASSERT(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(HeapObject::cast(clone)->address(),
@@ -3294,7 +3265,7 @@
   }
   // Return the new clone.
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  ProducerHeapProfile::RecordJSObjectAllocation(clone);
+  isolate_->producer_heap_profile()->RecordJSObjectAllocation(clone);
 #endif
   return clone;
 }
@@ -3350,7 +3321,7 @@
   // Count the number of characters in the UTF-8 string and check if
   // it is an ASCII string.
   Access<ScannerConstants::Utf8Decoder>
-      decoder(ScannerConstants::utf8_decoder());
+      decoder(isolate_->scanner_constants()->utf8_decoder());
   decoder->Reset(string.start(), string.length());
   int chars = 0;
   while (decoder->has_more()) {
@@ -3403,12 +3374,24 @@
 
   // Find the corresponding symbol map for strings.
   Map* map = string->map();
-  if (map == ascii_string_map()) return ascii_symbol_map();
-  if (map == string_map()) return symbol_map();
-  if (map == cons_string_map()) return cons_symbol_map();
-  if (map == cons_ascii_string_map()) return cons_ascii_symbol_map();
-  if (map == external_string_map()) return external_symbol_map();
-  if (map == external_ascii_string_map()) return external_ascii_symbol_map();
+  if (map == ascii_string_map()) {
+    return ascii_symbol_map();
+  }
+  if (map == string_map()) {
+    return symbol_map();
+  }
+  if (map == cons_string_map()) {
+    return cons_symbol_map();
+  }
+  if (map == cons_ascii_string_map()) {
+    return cons_ascii_symbol_map();
+  }
+  if (map == external_string_map()) {
+    return external_symbol_map();
+  }
+  if (map == external_ascii_string_map()) {
+    return external_ascii_symbol_map();
+  }
   if (map == external_string_with_ascii_data_map()) {
     return external_symbol_with_ascii_data_map();
   }
@@ -3582,7 +3565,7 @@
   { MaybeObject* maybe_obj = AllocateRawFixedArray(len);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
-  if (Heap::InNewSpace(obj)) {
+  if (InNewSpace(obj)) {
     HeapObject* dst = HeapObject::cast(obj);
     dst->set_map(map);
     CopyBlock(dst->address() + kPointerSize,
@@ -3614,7 +3597,7 @@
   array->set_map(fixed_array_map());
   array->set_length(length);
   // Initialize body.
-  ASSERT(!Heap::InNewSpace(undefined_value()));
+  ASSERT(!InNewSpace(undefined_value()));
   MemsetPointer(array->data_start(), undefined_value(), length);
   return result;
 }
@@ -3645,20 +3628,21 @@
 
 
 MUST_USE_RESULT static MaybeObject* AllocateFixedArrayWithFiller(
+    Heap* heap,
     int length,
     PretenureFlag pretenure,
     Object* filler) {
   ASSERT(length >= 0);
-  ASSERT(Heap::empty_fixed_array()->IsFixedArray());
-  if (length == 0) return Heap::empty_fixed_array();
+  ASSERT(heap->empty_fixed_array()->IsFixedArray());
+  if (length == 0) return heap->empty_fixed_array();
 
-  ASSERT(!Heap::InNewSpace(filler));
+  ASSERT(!heap->InNewSpace(filler));
   Object* result;
-  { MaybeObject* maybe_result = Heap::AllocateRawFixedArray(length, pretenure);
+  { MaybeObject* maybe_result = heap->AllocateRawFixedArray(length, pretenure);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
 
-  HeapObject::cast(result)->set_map(Heap::fixed_array_map());
+  HeapObject::cast(result)->set_map(heap->fixed_array_map());
   FixedArray* array = FixedArray::cast(result);
   array->set_length(length);
   MemsetPointer(array->data_start(), filler, length);
@@ -3667,13 +3651,19 @@
 
 
 MaybeObject* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) {
-  return AllocateFixedArrayWithFiller(length, pretenure, undefined_value());
+  return AllocateFixedArrayWithFiller(this,
+                                      length,
+                                      pretenure,
+                                      undefined_value());
 }
 
 
 MaybeObject* Heap::AllocateFixedArrayWithHoles(int length,
                                                PretenureFlag pretenure) {
-  return AllocateFixedArrayWithFiller(length, pretenure, the_hole_value());
+  return AllocateFixedArrayWithFiller(this,
+                                      length,
+                                      pretenure,
+                                      the_hole_value());
 }
 
 
@@ -3693,7 +3683,7 @@
 
 MaybeObject* Heap::AllocateHashTable(int length, PretenureFlag pretenure) {
   Object* result;
-  { MaybeObject* maybe_result = Heap::AllocateFixedArray(length, pretenure);
+  { MaybeObject* maybe_result = AllocateFixedArray(length, pretenure);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   reinterpret_cast<HeapObject*>(result)->set_map(hash_table_map());
@@ -3705,7 +3695,7 @@
 MaybeObject* Heap::AllocateGlobalContext() {
   Object* result;
   { MaybeObject* maybe_result =
-        Heap::AllocateFixedArray(Context::GLOBAL_CONTEXT_SLOTS);
+        AllocateFixedArray(Context::GLOBAL_CONTEXT_SLOTS);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   Context* context = reinterpret_cast<Context*>(result);
@@ -3719,7 +3709,7 @@
 MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) {
   ASSERT(length >= Context::MIN_CONTEXT_SLOTS);
   Object* result;
-  { MaybeObject* maybe_result = Heap::AllocateFixedArray(length);
+  { MaybeObject* maybe_result = AllocateFixedArray(length);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   Context* context = reinterpret_cast<Context*>(result);
@@ -3740,12 +3730,12 @@
                                        JSObject* extension,
                                        bool is_catch_context) {
   Object* result;
-  { MaybeObject* maybe_result =
-        Heap::AllocateFixedArray(Context::MIN_CONTEXT_SLOTS);
+  { MaybeObject* maybe_result = AllocateFixedArray(Context::MIN_CONTEXT_SLOTS);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   Context* context = reinterpret_cast<Context*>(result);
-  context->set_map(is_catch_context ? catch_context_map() : context_map());
+  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);
@@ -3761,7 +3751,8 @@
 MaybeObject* Heap::AllocateStruct(InstanceType type) {
   Map* map;
   switch (type) {
-#define MAKE_CASE(NAME, Name, name) case NAME##_TYPE: map = name##_map(); break;
+#define MAKE_CASE(NAME, Name, name) \
+    case NAME##_TYPE: map = name##_map(); break;
 STRUCT_LIST(MAKE_CASE)
 #undef MAKE_CASE
     default:
@@ -3772,7 +3763,7 @@
   AllocationSpace space =
       (size > MaxObjectSizeInPagedSpace()) ? LO_SPACE : OLD_POINTER_SPACE;
   Object* result;
-  { MaybeObject* maybe_result = Heap::Allocate(map, space);
+  { MaybeObject* maybe_result = Allocate(map, space);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   Struct::cast(result)->InitializeBody(size);
@@ -3786,8 +3777,11 @@
   static const int kIdlesBeforeMarkCompact = 8;
   static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1;
   static const unsigned int kGCsBetweenCleanup = 4;
-  static int number_idle_notifications = 0;
-  static unsigned int last_gc_count = gc_count_;
+
+  if (!last_idle_notification_gc_count_init_) {
+    last_idle_notification_gc_count_ = gc_count_;
+    last_idle_notification_gc_count_init_ = true;
+  }
 
   bool uncommit = true;
   bool finished = false;
@@ -3796,56 +3790,56 @@
   // GCs have taken place. This allows another round of cleanup based
   // on idle notifications if enough work has been carried out to
   // provoke a number of garbage collections.
-  if (gc_count_ - last_gc_count < kGCsBetweenCleanup) {
-    number_idle_notifications =
-        Min(number_idle_notifications + 1, kMaxIdleCount);
+  if (gc_count_ - last_idle_notification_gc_count_ < kGCsBetweenCleanup) {
+    number_idle_notifications_ =
+        Min(number_idle_notifications_ + 1, kMaxIdleCount);
   } else {
-    number_idle_notifications = 0;
-    last_gc_count = gc_count_;
+    number_idle_notifications_ = 0;
+    last_idle_notification_gc_count_ = gc_count_;
   }
 
-  if (number_idle_notifications == kIdlesBeforeScavenge) {
+  if (number_idle_notifications_ == kIdlesBeforeScavenge) {
     if (contexts_disposed_ > 0) {
-      HistogramTimerScope scope(&Counters::gc_context);
+      HistogramTimerScope scope(isolate_->counters()->gc_context());
       CollectAllGarbage(false);
     } else {
       CollectGarbage(NEW_SPACE);
     }
     new_space_.Shrink();
-    last_gc_count = gc_count_;
-  } else if (number_idle_notifications == kIdlesBeforeMarkSweep) {
+    last_idle_notification_gc_count_ = gc_count_;
+  } else if (number_idle_notifications_ == kIdlesBeforeMarkSweep) {
     // Before doing the mark-sweep collections we clear the
     // compilation cache to avoid hanging on to source code and
     // generated code for cached functions.
-    CompilationCache::Clear();
+    isolate_->compilation_cache()->Clear();
 
     CollectAllGarbage(false);
     new_space_.Shrink();
-    last_gc_count = gc_count_;
+    last_idle_notification_gc_count_ = gc_count_;
 
-  } else if (number_idle_notifications == kIdlesBeforeMarkCompact) {
+  } else if (number_idle_notifications_ == kIdlesBeforeMarkCompact) {
     CollectAllGarbage(true);
     new_space_.Shrink();
-    last_gc_count = gc_count_;
+    last_idle_notification_gc_count_ = gc_count_;
+    number_idle_notifications_ = 0;
     finished = true;
-
   } else if (contexts_disposed_ > 0) {
     if (FLAG_expose_gc) {
       contexts_disposed_ = 0;
     } else {
-      HistogramTimerScope scope(&Counters::gc_context);
+      HistogramTimerScope scope(isolate_->counters()->gc_context());
       CollectAllGarbage(false);
-      last_gc_count = gc_count_;
+      last_idle_notification_gc_count_ = gc_count_;
     }
     // If this is the first idle notification, we reset the
     // notification count to avoid letting idle notifications for
     // context disposal garbage collections start a potentially too
     // aggressive idle GC cycle.
-    if (number_idle_notifications <= 1) {
-      number_idle_notifications = 0;
+    if (number_idle_notifications_ <= 1) {
+      number_idle_notifications_ = 0;
       uncommit = false;
     }
-  } else if (number_idle_notifications > kIdlesBeforeMarkCompact) {
+  } else if (number_idle_notifications_ > kIdlesBeforeMarkCompact) {
     // If we have received more than kIdlesBeforeMarkCompact idle
     // notifications we do not perform any cleanup because we don't
     // expect to gain much by doing so.
@@ -3855,7 +3849,7 @@
   // Make sure that we have no pending context disposals and
   // conditionally uncommit from space.
   ASSERT(contexts_disposed_ == 0);
-  if (uncommit) Heap::UncommitFromSpace();
+  if (uncommit) UncommitFromSpace();
   return finished;
 }
 
@@ -3864,7 +3858,7 @@
 
 void Heap::Print() {
   if (!HasBeenSetup()) return;
-  Top::PrintStack();
+  isolate()->PrintStack();
   AllSpaces spaces;
   for (Space* space = spaces.next(); space != NULL; space = spaces.next())
     space->Print();
@@ -3897,11 +3891,11 @@
 
   PrintF("\n");
   PrintF("Number of handles : %d\n", HandleScope::NumberOfHandles());
-  GlobalHandles::PrintStats();
+  isolate_->global_handles()->PrintStats();
   PrintF("\n");
 
   PrintF("Heap statistics : ");
-  MemoryAllocator::ReportStatistics();
+  isolate_->memory_allocator()->ReportStatistics();
   PrintF("To space : ");
   new_space_.ReportStatistics();
   PrintF("Old pointer space : ");
@@ -3984,7 +3978,7 @@
     Address start = page->ObjectAreaStart();
     Address end = page->AllocationWatermark();
 
-    Heap::IterateDirtyRegions(Page::kAllRegionsDirtyMarks,
+    HEAP->IterateDirtyRegions(Page::kAllRegionsDirtyMarks,
                               start,
                               end,
                               visit_dirty_region,
@@ -4005,7 +3999,7 @@
         // When we are not in GC the Heap::InNewSpace() predicate
         // checks that pointers which satisfy predicate point into
         // the active semispace.
-        Heap::InNewSpace(*slot);
+        HEAP->InNewSpace(*slot);
         slot_address += kPointerSize;
       }
     }
@@ -4126,7 +4120,8 @@
 #endif  // DEBUG
 
 
-bool Heap::IteratePointersInDirtyRegion(Address start,
+bool Heap::IteratePointersInDirtyRegion(Heap* heap,
+                                        Address start,
                                         Address end,
                                         ObjectSlotCallback copy_object_func) {
   Address slot_address = start;
@@ -4134,10 +4129,10 @@
 
   while (slot_address < end) {
     Object** slot = reinterpret_cast<Object**>(slot_address);
-    if (Heap::InNewSpace(*slot)) {
+    if (heap->InNewSpace(*slot)) {
       ASSERT((*slot)->IsHeapObject());
       copy_object_func(reinterpret_cast<HeapObject**>(slot));
-      if (Heap::InNewSpace(*slot)) {
+      if (heap->InNewSpace(*slot)) {
         ASSERT((*slot)->IsHeapObject());
         pointers_to_new_space_found = true;
       }
@@ -4171,14 +4166,16 @@
   Address map_address = start;
   bool pointers_to_new_space_found = false;
 
+  Heap* heap = HEAP;
   while (map_address < end) {
-    ASSERT(!Heap::InNewSpace(Memory::Object_at(map_address)));
+    ASSERT(!heap->InNewSpace(Memory::Object_at(map_address)));
     ASSERT(Memory::Object_at(map_address)->IsMap());
 
     Address pointer_fields_start = map_address + Map::kPointerFieldsBeginOffset;
     Address pointer_fields_end = map_address + Map::kPointerFieldsEndOffset;
 
-    if (Heap::IteratePointersInDirtyRegion(pointer_fields_start,
+    if (Heap::IteratePointersInDirtyRegion(heap,
+                                           pointer_fields_start,
                                            pointer_fields_end,
                                            copy_object_func)) {
       pointers_to_new_space_found = true;
@@ -4192,6 +4189,7 @@
 
 
 bool Heap::IteratePointersInDirtyMapsRegion(
+    Heap* heap,
     Address start,
     Address end,
     ObjectSlotCallback copy_object_func) {
@@ -4211,7 +4209,8 @@
         Min(prev_map + Map::kPointerFieldsEndOffset, end);
 
     contains_pointers_to_new_space =
-      IteratePointersInDirtyRegion(pointer_fields_start,
+      IteratePointersInDirtyRegion(heap,
+                                   pointer_fields_start,
                                    pointer_fields_end,
                                    copy_object_func)
         || contains_pointers_to_new_space;
@@ -4233,7 +4232,8 @@
         Min(end, map_aligned_end + Map::kPointerFieldsEndOffset);
 
     contains_pointers_to_new_space =
-      IteratePointersInDirtyRegion(pointer_fields_start,
+      IteratePointersInDirtyRegion(heap,
+                                   pointer_fields_start,
                                    pointer_fields_end,
                                    copy_object_func)
         || contains_pointers_to_new_space;
@@ -4253,10 +4253,10 @@
 
   while (slot_address < end) {
     Object** slot = reinterpret_cast<Object**>(slot_address);
-    if (Heap::InFromSpace(*slot)) {
+    if (InFromSpace(*slot)) {
       ASSERT((*slot)->IsHeapObject());
       callback(reinterpret_cast<HeapObject**>(slot));
-      if (Heap::InNewSpace(*slot)) {
+      if (InNewSpace(*slot)) {
         ASSERT((*slot)->IsHeapObject());
         marks |= page->GetRegionMaskForAddress(slot_address);
       }
@@ -4295,7 +4295,7 @@
   Address region_end = Min(second_region, area_end);
 
   if (marks & mask) {
-    if (visit_dirty_region(region_start, region_end, copy_object_func)) {
+    if (visit_dirty_region(this, region_start, region_end, copy_object_func)) {
       newmarks |= mask;
     }
   }
@@ -4307,7 +4307,10 @@
 
   while (region_end <= area_end) {
     if (marks & mask) {
-      if (visit_dirty_region(region_start, region_end, copy_object_func)) {
+      if (visit_dirty_region(this,
+                             region_start,
+                             region_end,
+                             copy_object_func)) {
         newmarks |= mask;
       }
     }
@@ -4323,7 +4326,7 @@
     // with region end. Check whether region covering last part of area is
     // dirty.
     if (marks & mask) {
-      if (visit_dirty_region(region_start, area_end, copy_object_func)) {
+      if (visit_dirty_region(this, region_start, area_end, copy_object_func)) {
         newmarks |= mask;
       }
     }
@@ -4389,7 +4392,7 @@
   v->Synchronize("symbol_table");
   if (mode != VISIT_ALL_IN_SCAVENGE) {
     // Scavenge collections have special processing for this.
-    ExternalStringTable::Iterate(v);
+    external_string_table_.Iterate(v);
   }
   v->Synchronize("external_string_table");
 }
@@ -4402,42 +4405,42 @@
   v->VisitPointer(BitCast<Object**>(&hidden_symbol_));
   v->Synchronize("symbol");
 
-  Bootstrapper::Iterate(v);
+  isolate_->bootstrapper()->Iterate(v);
   v->Synchronize("bootstrapper");
-  Top::Iterate(v);
+  isolate_->Iterate(v);
   v->Synchronize("top");
   Relocatable::Iterate(v);
   v->Synchronize("relocatable");
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  Debug::Iterate(v);
+  isolate_->debug()->Iterate(v);
 #endif
   v->Synchronize("debug");
-  CompilationCache::Iterate(v);
+  isolate_->compilation_cache()->Iterate(v);
   v->Synchronize("compilationcache");
 
   // Iterate over local handles in handle scopes.
-  HandleScopeImplementer::Iterate(v);
+  isolate_->handle_scope_implementer()->Iterate(v);
   v->Synchronize("handlescope");
 
   // Iterate over the builtin code objects and code stubs in the
   // heap. Note that it is not necessary to iterate over code objects
   // on scavenge collections.
   if (mode != VISIT_ALL_IN_SCAVENGE) {
-    Builtins::IterateBuiltins(v);
+    isolate_->builtins()->IterateBuiltins(v);
   }
   v->Synchronize("builtins");
 
   // Iterate over global handles.
   if (mode == VISIT_ONLY_STRONG) {
-    GlobalHandles::IterateStrongRoots(v);
+    isolate_->global_handles()->IterateStrongRoots(v);
   } else {
-    GlobalHandles::IterateAllRoots(v);
+    isolate_->global_handles()->IterateAllRoots(v);
   }
   v->Synchronize("globalhandles");
 
   // Iterate over pointers being held by inactive threads.
-  ThreadManager::Iterate(v);
+  isolate_->thread_manager()->Iterate(v);
   v->Synchronize("threadmanager");
 
   // Iterate over the pointers the Serialization/Deserialization code is
@@ -4456,10 +4459,6 @@
 }
 
 
-// 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.
@@ -4506,7 +4505,7 @@
   // The old generation is paged.
   max_old_generation_size_ = RoundUp(max_old_generation_size_, Page::kPageSize);
 
-  heap_configured = true;
+  configured_ = true;
   return true;
 }
 
@@ -4534,11 +4533,13 @@
   *stats->cell_space_size = cell_space_->Size();
   *stats->cell_space_capacity = cell_space_->Capacity();
   *stats->lo_space_size = lo_space_->Size();
-  GlobalHandles::RecordStats(stats);
-  *stats->memory_allocator_size = MemoryAllocator::Size();
+  isolate_->global_handles()->RecordStats(stats);
+  *stats->memory_allocator_size = isolate()->memory_allocator()->Size();
   *stats->memory_allocator_capacity =
-      MemoryAllocator::Size() + MemoryAllocator::Available();
+      isolate()->memory_allocator()->Size() +
+      isolate()->memory_allocator()->Available();
   *stats->os_error = OS::GetLastError();
+      isolate()->memory_allocator()->Available();
   if (take_snapshot) {
     HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
     for (HeapObject* obj = iterator.next();
@@ -4570,8 +4571,177 @@
       - amount_of_external_allocated_memory_at_last_global_gc_;
 }
 
+#ifdef DEBUG
+
+// Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject.
+static const int kMarkTag = 2;
+
+
+class HeapDebugUtils {
+ public:
+  explicit HeapDebugUtils(Heap* heap)
+    : search_for_any_global_(false),
+      search_target_(NULL),
+      found_target_(false),
+      object_stack_(20),
+      heap_(heap) {
+  }
+
+  class MarkObjectVisitor : public ObjectVisitor {
+   public:
+    explicit MarkObjectVisitor(HeapDebugUtils* utils) : utils_(utils) { }
+
+    void VisitPointers(Object** start, Object** end) {
+      // Copy all HeapObject pointers in [start, end)
+      for (Object** p = start; p < end; p++) {
+        if ((*p)->IsHeapObject())
+          utils_->MarkObjectRecursively(p);
+      }
+    }
+
+    HeapDebugUtils* utils_;
+  };
+
+  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;
+    }
+
+    // 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);
+
+    MarkObjectVisitor mark_visitor(this);
+
+    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();
+  }
+
+
+  class UnmarkObjectVisitor : public ObjectVisitor {
+   public:
+    explicit UnmarkObjectVisitor(HeapDebugUtils* utils) : utils_(utils) { }
+
+    void VisitPointers(Object** start, Object** end) {
+      // Copy all HeapObject pointers in [start, end)
+      for (Object** p = start; p < end; p++) {
+        if ((*p)->IsHeapObject())
+          utils_->UnmarkObjectRecursively(p);
+      }
+    }
+
+    HeapDebugUtils* utils_;
+  };
+
+
+  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));
+
+    UnmarkObjectVisitor unmark_visitor(this);
+
+    obj->IterateBody(Map::cast(map_p)->instance_type(),
+                     obj->SizeFromMap(Map::cast(map_p)),
+                     &unmark_visitor);
+  }
+
+
+  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:
+    explicit MarkRootVisitor(HeapDebugUtils* utils) : utils_(utils) { }
+
+    void VisitPointers(Object** start, Object** end) {
+      // Visit all HeapObject pointers in [start, end)
+      for (Object** p = start; p < end; p++) {
+        if ((*p)->IsHeapObject())
+          utils_->MarkRootObjectRecursively(p);
+      }
+    }
+
+    HeapDebugUtils* utils_;
+  };
+
+  bool search_for_any_global_;
+  Object* search_target_;
+  bool found_target_;
+  List<Object*> object_stack_;
+  Heap* heap_;
+
+  friend class Heap;
+};
+
+#endif
 
 bool Heap::Setup(bool create_heap_objects) {
+#ifdef DEBUG
+  debug_utils_ = new HeapDebugUtils(this);
+#endif
+
   // 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.
@@ -4580,13 +4750,19 @@
   // 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 (!configured_) {
     if (!ConfigureHeapDefault()) return false;
   }
 
-  ScavengingVisitor::Initialize();
-  NewSpaceScavenger::Initialize();
-  MarkCompactCollector::Initialize();
+  gc_initializer_mutex->Lock();
+  static bool initialized_gc = false;
+  if (!initialized_gc) {
+      initialized_gc = true;
+      ScavengingVisitor::Initialize();
+      NewSpaceScavenger::Initialize();
+      MarkCompactCollector::Initialize();
+  }
+  gc_initializer_mutex->Unlock();
 
   MarkMapPointersAsEncoded(false);
 
@@ -4594,9 +4770,11 @@
   // space.  The chunk is double the size of the requested reserved
   // new space size to ensure that we can find a pair of semispaces that
   // are contiguous and aligned to their size.
-  if (!MemoryAllocator::Setup(MaxReserved(), MaxExecutableSize())) return false;
+  if (!isolate_->memory_allocator()->Setup(MaxReserved(), MaxExecutableSize()))
+      return false;
   void* chunk =
-      MemoryAllocator::ReserveInitialChunk(4 * reserved_semispace_size_);
+      isolate_->memory_allocator()->ReserveInitialChunk(
+          4 * reserved_semispace_size_);
   if (chunk == NULL) return false;
 
   // Align the pair of semispaces to their size, which must be a power
@@ -4609,13 +4787,19 @@
 
   // Initialize old pointer space.
   old_pointer_space_ =
-      new OldSpace(max_old_generation_size_, OLD_POINTER_SPACE, NOT_EXECUTABLE);
+      new OldSpace(this,
+                   max_old_generation_size_,
+                   OLD_POINTER_SPACE,
+                   NOT_EXECUTABLE);
   if (old_pointer_space_ == NULL) return false;
   if (!old_pointer_space_->Setup(NULL, 0)) return false;
 
   // Initialize old data space.
   old_data_space_ =
-      new OldSpace(max_old_generation_size_, OLD_DATA_SPACE, NOT_EXECUTABLE);
+      new OldSpace(this,
+                   max_old_generation_size_,
+                   OLD_DATA_SPACE,
+                   NOT_EXECUTABLE);
   if (old_data_space_ == NULL) return false;
   if (!old_data_space_->Setup(NULL, 0)) return false;
 
@@ -4624,18 +4808,18 @@
   // On 64-bit platform(s), we put all code objects in a 2 GB range of
   // virtual address space, so that they can call each other with near calls.
   if (code_range_size_ > 0) {
-    if (!CodeRange::Setup(code_range_size_)) {
+    if (!isolate_->code_range()->Setup(code_range_size_)) {
       return false;
     }
   }
 
   code_space_ =
-      new OldSpace(max_old_generation_size_, CODE_SPACE, EXECUTABLE);
+      new OldSpace(this, max_old_generation_size_, CODE_SPACE, EXECUTABLE);
   if (code_space_ == NULL) return false;
   if (!code_space_->Setup(NULL, 0)) return false;
 
   // Initialize map space.
-  map_space_ = new MapSpace(FLAG_use_big_map_space
+  map_space_ = new MapSpace(this, FLAG_use_big_map_space
       ? max_old_generation_size_
       : MapSpace::kMaxMapPageIndex * Page::kPageSize,
       FLAG_max_map_space_pages,
@@ -4644,14 +4828,14 @@
   if (!map_space_->Setup(NULL, 0)) return false;
 
   // Initialize global property cell space.
-  cell_space_ = new CellSpace(max_old_generation_size_, CELL_SPACE);
+  cell_space_ = new CellSpace(this, max_old_generation_size_, CELL_SPACE);
   if (cell_space_ == NULL) return false;
   if (!cell_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);
+  lo_space_ = new LargeObjectSpace(this, LO_SPACE);
   if (lo_space_ == NULL) return false;
   if (!lo_space_->Setup()) return false;
 
@@ -4666,12 +4850,12 @@
     global_contexts_list_ = undefined_value();
   }
 
-  LOG(IntPtrTEvent("heap-capacity", Capacity()));
-  LOG(IntPtrTEvent("heap-available", Available()));
+  LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity()));
+  LOG(isolate_, IntPtrTEvent("heap-available", Available()));
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
   // This should be called only after initial objects have been created.
-  ProducerHeapProfile::Setup();
+  isolate_->producer_heap_profile()->Setup();
 #endif
 
   return true;
@@ -4679,6 +4863,8 @@
 
 
 void Heap::SetStackLimits() {
+  ASSERT(isolate_ != NULL);
+  ASSERT(isolate_ == isolate());
   // On 64 bit machines, pointers are generally out of range of Smis.  We write
   // something that looks like an out of range Smi to the GC.
 
@@ -4686,10 +4872,10 @@
   // These are actually addresses, but the tag makes the GC ignore it.
   roots_[kStackLimitRootIndex] =
       reinterpret_cast<Object*>(
-          (StackGuard::jslimit() & ~kSmiTagMask) | kSmiTag);
+          (isolate_->stack_guard()->jslimit() & ~kSmiTagMask) | kSmiTag);
   roots_[kRealStackLimitRootIndex] =
       reinterpret_cast<Object*>(
-          (StackGuard::real_jslimit() & ~kSmiTagMask) | kSmiTag);
+          (isolate_->stack_guard()->real_jslimit() & ~kSmiTagMask) | kSmiTag);
 }
 
 
@@ -4699,16 +4885,16 @@
     PrintF("gc_count=%d ", gc_count_);
     PrintF("mark_sweep_count=%d ", ms_count_);
     PrintF("mark_compact_count=%d ", mc_count_);
-    PrintF("max_gc_pause=%d ", GCTracer::get_max_gc_pause());
-    PrintF("min_in_mutator=%d ", GCTracer::get_min_in_mutator());
+    PrintF("max_gc_pause=%d ", get_max_gc_pause());
+    PrintF("min_in_mutator=%d ", get_min_in_mutator());
     PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ",
-           GCTracer::get_max_alive_after_gc());
+           get_max_alive_after_gc());
     PrintF("\n\n");
   }
 
-  GlobalHandles::TearDown();
+  isolate_->global_handles()->TearDown();
 
-  ExternalStringTable::TearDown();
+  external_string_table_.TearDown();
 
   new_space_.TearDown();
 
@@ -4748,7 +4934,12 @@
     lo_space_ = NULL;
   }
 
-  MemoryAllocator::TearDown();
+  isolate_->memory_allocator()->TearDown();
+
+#ifdef DEBUG
+  delete debug_utils_;
+  debug_utils_ = NULL;
+#endif
 }
 
 
@@ -4837,7 +5028,7 @@
 void Heap::PrintHandles() {
   PrintF("Handles:\n");
   PrintHandleVisitor v;
-  HandleScopeImplementer::Iterate(&v);
+  isolate_->handle_scope_implementer()->Iterate(&v);
 }
 
 #endif
@@ -4846,19 +5037,19 @@
 Space* AllSpaces::next() {
   switch (counter_++) {
     case NEW_SPACE:
-      return Heap::new_space();
+      return HEAP->new_space();
     case OLD_POINTER_SPACE:
-      return Heap::old_pointer_space();
+      return HEAP->old_pointer_space();
     case OLD_DATA_SPACE:
-      return Heap::old_data_space();
+      return HEAP->old_data_space();
     case CODE_SPACE:
-      return Heap::code_space();
+      return HEAP->code_space();
     case MAP_SPACE:
-      return Heap::map_space();
+      return HEAP->map_space();
     case CELL_SPACE:
-      return Heap::cell_space();
+      return HEAP->cell_space();
     case LO_SPACE:
-      return Heap::lo_space();
+      return HEAP->lo_space();
     default:
       return NULL;
   }
@@ -4868,15 +5059,15 @@
 PagedSpace* PagedSpaces::next() {
   switch (counter_++) {
     case OLD_POINTER_SPACE:
-      return Heap::old_pointer_space();
+      return HEAP->old_pointer_space();
     case OLD_DATA_SPACE:
-      return Heap::old_data_space();
+      return HEAP->old_data_space();
     case CODE_SPACE:
-      return Heap::code_space();
+      return HEAP->code_space();
     case MAP_SPACE:
-      return Heap::map_space();
+      return HEAP->map_space();
     case CELL_SPACE:
-      return Heap::cell_space();
+      return HEAP->cell_space();
     default:
       return NULL;
   }
@@ -4887,11 +5078,11 @@
 OldSpace* OldSpaces::next() {
   switch (counter_++) {
     case OLD_POINTER_SPACE:
-      return Heap::old_pointer_space();
+      return HEAP->old_pointer_space();
     case OLD_DATA_SPACE:
-      return Heap::old_data_space();
+      return HEAP->old_data_space();
     case CODE_SPACE:
-      return Heap::code_space();
+      return HEAP->code_space();
     default:
       return NULL;
   }
@@ -4946,25 +5137,25 @@
 
   switch (current_space_) {
     case NEW_SPACE:
-      iterator_ = new SemiSpaceIterator(Heap::new_space(), size_func_);
+      iterator_ = new SemiSpaceIterator(HEAP->new_space(), size_func_);
       break;
     case OLD_POINTER_SPACE:
-      iterator_ = new HeapObjectIterator(Heap::old_pointer_space(), size_func_);
+      iterator_ = new HeapObjectIterator(HEAP->old_pointer_space(), size_func_);
       break;
     case OLD_DATA_SPACE:
-      iterator_ = new HeapObjectIterator(Heap::old_data_space(), size_func_);
+      iterator_ = new HeapObjectIterator(HEAP->old_data_space(), size_func_);
       break;
     case CODE_SPACE:
-      iterator_ = new HeapObjectIterator(Heap::code_space(), size_func_);
+      iterator_ = new HeapObjectIterator(HEAP->code_space(), size_func_);
       break;
     case MAP_SPACE:
-      iterator_ = new HeapObjectIterator(Heap::map_space(), size_func_);
+      iterator_ = new HeapObjectIterator(HEAP->map_space(), size_func_);
       break;
     case CELL_SPACE:
-      iterator_ = new HeapObjectIterator(Heap::cell_space(), size_func_);
+      iterator_ = new HeapObjectIterator(HEAP->cell_space(), size_func_);
       break;
     case LO_SPACE:
-      iterator_ = new LargeObjectIterator(Heap::lo_space(), size_func_);
+      iterator_ = new LargeObjectIterator(HEAP->lo_space(), size_func_);
       break;
   }
 
@@ -4998,16 +5189,17 @@
 
  private:
   void MarkFreeListNodes() {
-    Heap::old_pointer_space()->MarkFreeListNodes();
-    Heap::old_data_space()->MarkFreeListNodes();
-    MarkCodeSpaceFreeListNodes();
-    Heap::map_space()->MarkFreeListNodes();
-    Heap::cell_space()->MarkFreeListNodes();
+    Heap* heap = HEAP;
+    heap->old_pointer_space()->MarkFreeListNodes();
+    heap->old_data_space()->MarkFreeListNodes();
+    MarkCodeSpaceFreeListNodes(heap);
+    heap->map_space()->MarkFreeListNodes();
+    heap->cell_space()->MarkFreeListNodes();
   }
 
-  void MarkCodeSpaceFreeListNodes() {
+  void MarkCodeSpaceFreeListNodes(Heap* heap) {
     // For code space, using FreeListNode::IsFreeListNode is OK.
-    HeapObjectIterator iter(Heap::code_space());
+    HeapObjectIterator iter(heap->code_space());
     for (HeapObject* obj = iter.next_object();
          obj != NULL;
          obj = iter.next_object()) {
@@ -5069,7 +5261,7 @@
       obj->SetMark();
     }
     UnmarkingVisitor visitor;
-    Heap::IterateRoots(&visitor, VISIT_ALL);
+    HEAP->IterateRoots(&visitor, VISIT_ALL);
     while (visitor.can_process())
       visitor.ProcessNext();
   }
@@ -5372,7 +5564,7 @@
 }
 
 
-GCTracer::GCTracer()
+GCTracer::GCTracer(Heap* heap)
     : start_time_(0.0),
       start_size_(0),
       gc_count_(0),
@@ -5381,14 +5573,16 @@
       marked_count_(0),
       allocated_since_last_gc_(0),
       spent_in_mutator_(0),
-      promoted_objects_size_(0) {
+      promoted_objects_size_(0),
+      heap_(heap) {
   // 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();
+  previous_has_compacted_ = heap_->mark_compact_collector_.HasCompacted();
+  previous_marked_count_ =
+      heap_->mark_compact_collector_.previous_marked_count();
   if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return;
   start_time_ = OS::TimeCurrentMillis();
-  start_size_ = Heap::SizeOfObjects();
+  start_size_ = heap_->SizeOfObjects();
 
   for (int i = 0; i < Scope::kNumberOfScopes; i++) {
     scopes_[i] = 0;
@@ -5396,10 +5590,11 @@
 
   in_free_list_or_wasted_before_gc_ = CountTotalHolesSize();
 
-  allocated_since_last_gc_ = Heap::SizeOfObjects() - alive_after_last_gc_;
+  allocated_since_last_gc_ =
+      heap_->SizeOfObjects() - heap_->alive_after_last_gc_;
 
-  if (last_gc_end_timestamp_ > 0) {
-    spent_in_mutator_ = Max(start_time_ - last_gc_end_timestamp_, 0.0);
+  if (heap_->last_gc_end_timestamp_ > 0) {
+    spent_in_mutator_ = Max(start_time_ - heap_->last_gc_end_timestamp_, 0.0);
   }
 }
 
@@ -5408,20 +5603,21 @@
   // Printf ONE line iff flag is set.
   if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return;
 
-  bool first_gc = (last_gc_end_timestamp_ == 0);
+  bool first_gc = (heap_->last_gc_end_timestamp_ == 0);
 
-  alive_after_last_gc_ = Heap::SizeOfObjects();
-  last_gc_end_timestamp_ = OS::TimeCurrentMillis();
+  heap_->alive_after_last_gc_ = heap_->SizeOfObjects();
+  heap_->last_gc_end_timestamp_ = OS::TimeCurrentMillis();
 
-  int time = static_cast<int>(last_gc_end_timestamp_ - start_time_);
+  int time = static_cast<int>(heap_->last_gc_end_timestamp_ - start_time_);
 
   // Update cumulative GC statistics if required.
   if (FLAG_print_cumulative_gc_stat) {
-    max_gc_pause_ = Max(max_gc_pause_, time);
-    max_alive_after_gc_ = Max(max_alive_after_gc_, alive_after_last_gc_);
+    heap_->max_gc_pause_ = Max(heap_->max_gc_pause_, time);
+    heap_->max_alive_after_gc_ = Max(heap_->max_alive_after_gc_,
+                                     heap_->alive_after_last_gc_);
     if (!first_gc) {
-      min_in_mutator_ = Min(min_in_mutator_,
-                            static_cast<int>(spent_in_mutator_));
+      heap_->min_in_mutator_ = Min(heap_->min_in_mutator_,
+                                   static_cast<int>(spent_in_mutator_));
     }
   }
 
@@ -5446,7 +5642,8 @@
         PrintF("s");
         break;
       case MARK_COMPACTOR:
-        PrintF(MarkCompactCollector::HasCompacted() ? "mc" : "ms");
+        PrintF("%s",
+               heap_->mark_compact_collector_.HasCompacted() ? "mc" : "ms");
         break;
       default:
         UNREACHABLE();
@@ -5460,7 +5657,7 @@
     PrintF("compact=%d ", static_cast<int>(scopes_[Scope::MC_COMPACT]));
 
     PrintF("total_size_before=%" V8_PTR_PREFIX "d ", start_size_);
-    PrintF("total_size_after=%" V8_PTR_PREFIX "d ", Heap::SizeOfObjects());
+    PrintF("total_size_after=%" V8_PTR_PREFIX "d ", heap_->SizeOfObjects());
     PrintF("holes_size_before=%" V8_PTR_PREFIX "d ",
            in_free_list_or_wasted_before_gc_);
     PrintF("holes_size_after=%" V8_PTR_PREFIX "d ", CountTotalHolesSize());
@@ -5472,7 +5669,7 @@
   }
 
 #if defined(ENABLE_LOGGING_AND_PROFILING)
-  Heap::PrintShortHeapStatistics();
+  heap_->PrintShortHeapStatistics();
 #endif
 }
 
@@ -5482,8 +5679,8 @@
     case SCAVENGER:
       return "Scavenge";
     case MARK_COMPACTOR:
-      return MarkCompactCollector::HasCompacted() ? "Mark-compact"
-                                                  : "Mark-sweep";
+      return heap_->mark_compact_collector_.HasCompacted() ? "Mark-compact"
+                                                           : "Mark-sweep";
   }
   return "Unknown GC";
 }
@@ -5503,13 +5700,13 @@
   if ((key.map == map) && key.name->Equals(name)) {
     return field_offsets_[index];
   }
-  return -1;
+  return kNotFound;
 }
 
 
 void KeyedLookupCache::Update(Map* map, String* name, int field_offset) {
   String* symbol;
-  if (Heap::LookupSymbolIfExists(name, &symbol)) {
+  if (HEAP->LookupSymbolIfExists(name, &symbol)) {
     int index = Hash(map, symbol);
     Key& key = keys_[index];
     key.map = map;
@@ -5524,35 +5721,24 @@
 }
 
 
-KeyedLookupCache::Key KeyedLookupCache::keys_[KeyedLookupCache::kLength];
-
-
-int KeyedLookupCache::field_offsets_[KeyedLookupCache::kLength];
-
-
 void DescriptorLookupCache::Clear() {
   for (int index = 0; index < kLength; index++) keys_[index].array = NULL;
 }
 
 
-DescriptorLookupCache::Key
-DescriptorLookupCache::keys_[DescriptorLookupCache::kLength];
-
-int DescriptorLookupCache::results_[DescriptorLookupCache::kLength];
-
-
 #ifdef DEBUG
 void Heap::GarbageCollectionGreedyCheck() {
   ASSERT(FLAG_gc_greedy);
-  if (Bootstrapper::IsActive()) return;
+  if (isolate_->bootstrapper()->IsActive()) return;
   if (disallow_allocation_failure()) return;
   CollectGarbage(NEW_SPACE);
 }
 #endif
 
 
-TranscendentalCache::TranscendentalCache(TranscendentalCache::Type t)
-  : type_(t) {
+TranscendentalCache::SubCache::SubCache(Type t)
+  : type_(t),
+    isolate_(Isolate::Current()) {
   uint32_t in0 = 0xffffffffu;  // Bit-pattern for a NaN that isn't
   uint32_t in1 = 0xffffffffu;  // generated by the FPU.
   for (int i = 0; i < kCacheSize; i++) {
@@ -5563,9 +5749,6 @@
 }
 
 
-TranscendentalCache* TranscendentalCache::caches_[kNumberOfCaches];
-
-
 void TranscendentalCache::Clear() {
   for (int i = 0; i < kNumberOfCaches; i++) {
     if (caches_[i] != NULL) {
@@ -5579,8 +5762,8 @@
 void ExternalStringTable::CleanUp() {
   int last = 0;
   for (int i = 0; i < new_space_strings_.length(); ++i) {
-    if (new_space_strings_[i] == Heap::raw_unchecked_null_value()) continue;
-    if (Heap::InNewSpace(new_space_strings_[i])) {
+    if (new_space_strings_[i] == heap_->raw_unchecked_null_value()) continue;
+    if (heap_->InNewSpace(new_space_strings_[i])) {
       new_space_strings_[last++] = new_space_strings_[i];
     } else {
       old_space_strings_.Add(new_space_strings_[i]);
@@ -5589,8 +5772,8 @@
   new_space_strings_.Rewind(last);
   last = 0;
   for (int i = 0; i < old_space_strings_.length(); ++i) {
-    if (old_space_strings_[i] == Heap::raw_unchecked_null_value()) continue;
-    ASSERT(!Heap::InNewSpace(old_space_strings_[i]));
+    if (old_space_strings_[i] == heap_->raw_unchecked_null_value()) continue;
+    ASSERT(!heap_->InNewSpace(old_space_strings_[i]));
     old_space_strings_[last++] = old_space_strings_[i];
   }
   old_space_strings_.Rewind(last);
@@ -5604,7 +5787,4 @@
 }
 
 
-List<Object*> ExternalStringTable::new_space_strings_;
-List<Object*> ExternalStringTable::old_space_strings_;
-
 } }  // namespace v8::internal
diff --git a/src/heap.h b/src/heap.h
index 6aa8339..88074d7 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -32,6 +32,7 @@
 
 #include "globals.h"
 #include "list.h"
+#include "mark-compact.h"
 #include "spaces.h"
 #include "splay-tree-inl.h"
 #include "v8-counters.h"
@@ -39,9 +40,14 @@
 namespace v8 {
 namespace internal {
 
+// TODO(isolates): remove HEAP here
+#define HEAP (_inline_get_heap_())
+class Heap;
+inline Heap* _inline_get_heap_();
+
 
 // Defines all the roots in Heap.
-#define UNCONDITIONAL_STRONG_ROOT_LIST(V)                                      \
+#define STRONG_ROOT_LIST(V)                                      \
   /* Put the byte array map early.  We need it to be in place by the time   */ \
   /* the deserializer hits the next page, since it wants to put a byte      */ \
   /* array in the unused space at the end of the page.                      */ \
@@ -89,7 +95,7 @@
   V(Map, external_ascii_string_map, ExternalAsciiStringMap)                    \
   V(Map, undetectable_string_map, UndetectableStringMap)                       \
   V(Map, undetectable_ascii_string_map, UndetectableAsciiStringMap)            \
-  V(Map, pixel_array_map, PixelArrayMap)                                       \
+  V(Map, external_pixel_array_map, ExternalPixelArrayMap)                      \
   V(Map, external_byte_array_map, ExternalByteArrayMap)                        \
   V(Map, external_unsigned_byte_array_map, ExternalUnsignedByteArrayMap)       \
   V(Map, external_short_array_map, ExternalShortArrayMap)                      \
@@ -114,26 +120,12 @@
   V(NumberDictionary, non_monomorphic_cache, NonMonomorphicCache)              \
   V(Code, js_entry_code, JsEntryCode)                                          \
   V(Code, js_construct_entry_code, JsConstructEntryCode)                       \
-  V(Code, c_entry_code, CEntryCode)                                            \
   V(FixedArray, natives_source_cache, NativesSourceCache)                      \
   V(Object, last_script_id, LastScriptId)                                      \
   V(Script, empty_script, EmptyScript)                                         \
   V(Smi, real_stack_limit, RealStackLimit)                                     \
   V(StringDictionary, intrinsic_function_names, IntrinsicFunctionNames)        \
 
-#if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP
-#define STRONG_ROOT_LIST(V)                                                    \
-  UNCONDITIONAL_STRONG_ROOT_LIST(V)                                            \
-  V(Code, re_c_entry_code, RegExpCEntryCode)                                   \
-  V(Code, direct_c_entry_code, DirectCEntryCode)
-#elif V8_TARGET_ARCH_ARM
-#define STRONG_ROOT_LIST(V)                                                    \
-  UNCONDITIONAL_STRONG_ROOT_LIST(V)                                            \
-  V(Code, direct_c_entry_code, DirectCEntryCode)
-#else
-#define STRONG_ROOT_LIST(V) UNCONDITIONAL_STRONG_ROOT_LIST(V)
-#endif
-
 #define ROOT_LIST(V)                                  \
   STRONG_ROOT_LIST(V)                                 \
   V(SymbolTable, symbol_table, SymbolTable)
@@ -185,8 +177,6 @@
   V(InitializeConstGlobal_symbol, "InitializeConstGlobal")               \
   V(KeyedLoadSpecialized_symbol, "KeyedLoadSpecialized")                 \
   V(KeyedStoreSpecialized_symbol, "KeyedStoreSpecialized")               \
-  V(KeyedLoadPixelArray_symbol, "KeyedLoadPixelArray")                   \
-  V(KeyedStorePixelArray_symbol, "KeyedStorePixelArray")                 \
   V(stack_overflow_symbol, "kStackOverflowBoilerplate")                  \
   V(illegal_access_symbol, "illegal access")                             \
   V(out_of_memory_symbol, "out-of-memory")                               \
@@ -215,18 +205,42 @@
   V(identity_hash_symbol, "v8::IdentityHash")                            \
   V(closure_symbol, "(closure)")                                         \
   V(use_strict, "use strict")                                            \
-  V(KeyedLoadExternalArray_symbol, "KeyedLoadExternalArray")             \
-  V(KeyedStoreExternalArray_symbol, "KeyedStoreExternalArray")
+  V(KeyedLoadExternalByteArray_symbol, "KeyedLoadExternalByteArray")     \
+  V(KeyedLoadExternalUnsignedByteArray_symbol,                           \
+      "KeyedLoadExternalUnsignedByteArray")                              \
+  V(KeyedLoadExternalShortArray_symbol,                                  \
+      "KeyedLoadExternalShortArray")                                     \
+  V(KeyedLoadExternalUnsignedShortArray_symbol,                          \
+      "KeyedLoadExternalUnsignedShortArray")                             \
+  V(KeyedLoadExternalIntArray_symbol, "KeyedLoadExternalIntArray")       \
+  V(KeyedLoadExternalUnsignedIntArray_symbol,                            \
+       "KeyedLoadExternalUnsignedIntArray")                              \
+  V(KeyedLoadExternalFloatArray_symbol, "KeyedLoadExternalFloatArray")   \
+  V(KeyedLoadExternalPixelArray_symbol, "KeyedLoadExternalPixelArray")   \
+  V(KeyedStoreExternalByteArray_symbol, "KeyedStoreExternalByteArray")   \
+  V(KeyedStoreExternalUnsignedByteArray_symbol,                          \
+        "KeyedStoreExternalUnsignedByteArray")                           \
+  V(KeyedStoreExternalShortArray_symbol, "KeyedStoreExternalShortArray") \
+  V(KeyedStoreExternalUnsignedShortArray_symbol,                         \
+        "KeyedStoreExternalUnsignedShortArray")                          \
+  V(KeyedStoreExternalIntArray_symbol, "KeyedStoreExternalIntArray")     \
+  V(KeyedStoreExternalUnsignedIntArray_symbol,                           \
+        "KeyedStoreExternalUnsignedIntArray")                            \
+  V(KeyedStoreExternalFloatArray_symbol, "KeyedStoreExternalFloatArray") \
+  V(KeyedStoreExternalPixelArray_symbol, "KeyedStoreExternalPixelArray")
 
 // Forward declarations.
 class GCTracer;
 class HeapStats;
+class Isolate;
 class WeakObjectRetainer;
 
 
-typedef String* (*ExternalStringTableUpdaterCallback)(Object** pointer);
+typedef String* (*ExternalStringTableUpdaterCallback)(Heap* heap,
+                                                      Object** pointer);
 
-typedef bool (*DirtyRegionCallback)(Address start,
+typedef bool (*DirtyRegionCallback)(Heap* heap,
+                                    Address start,
                                     Address end,
                                     ObjectSlotCallback copy_object_func);
 
@@ -234,103 +248,178 @@
 // 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 {
+#ifdef DEBUG
+class HeapDebugUtils;
+#endif
+
+
+// A queue of objects promoted during scavenge. Each object is accompanied
+// by it's size to avoid dereferencing a map pointer for scanning.
+class PromotionQueue {
+ public:
+  PromotionQueue() : front_(NULL), rear_(NULL) { }
+
+  void Initialize(Address start_address) {
+    front_ = rear_ = reinterpret_cast<intptr_t*>(start_address);
+  }
+
+  bool is_empty() { return front_ <= rear_; }
+
+  inline void insert(HeapObject* target, int size);
+
+  void remove(HeapObject** target, int* size) {
+    *target = reinterpret_cast<HeapObject*>(*(--front_));
+    *size = static_cast<int>(*(--front_));
+    // Assert no underflow.
+    ASSERT(front_ >= rear_);
+  }
+
+ private:
+  // The front of the queue is higher in memory than the rear.
+  intptr_t* front_;
+  intptr_t* rear_;
+
+  DISALLOW_COPY_AND_ASSIGN(PromotionQueue);
+};
+
+
+// External strings table is a place where all external strings are
+// registered.  We need to keep track of such strings to properly
+// finalize them.
+class ExternalStringTable {
+ public:
+  // Registers an external string.
+  inline void AddString(String* string);
+
+  inline void Iterate(ObjectVisitor* v);
+
+  // Restores internal invariant and gets rid of collected strings.
+  // Must be called after each Iterate() that modified the strings.
+  void CleanUp();
+
+  // Destroys all allocated memory.
+  void TearDown();
+
+ private:
+  ExternalStringTable() { }
+
+  friend class Heap;
+
+  inline void Verify();
+
+  inline void AddOldString(String* string);
+
+  // Notifies the table that only a prefix of the new list is valid.
+  inline void ShrinkNewStrings(int position);
+
+  // To speed up scavenge collections new space string are kept
+  // separate from old space strings.
+  List<Object*> new_space_strings_;
+  List<Object*> old_space_strings_;
+
+  Heap* heap_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExternalStringTable);
+};
+
+
+class Heap {
  public:
   // Configure heap size before setup. Return false if the heap has been
   // setup already.
-  static bool ConfigureHeap(int max_semispace_size,
-                            int max_old_gen_size,
-                            int max_executable_size);
-  static bool ConfigureHeapDefault();
+  bool ConfigureHeap(int max_semispace_size,
+                     int max_old_gen_size,
+                     int max_executable_size);
+  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);
+  bool Setup(bool create_heap_objects);
 
   // Destroys all memory allocated by the heap.
-  static void TearDown();
+  void TearDown();
 
   // Set the stack limit in the roots_ array.  Some architectures generate
   // code that looks here, because it is faster than loading from the static
   // jslimit_/real_jslimit_ variable in the StackGuard.
-  static void SetStackLimits();
+  void SetStackLimits();
 
   // Returns whether Setup has been called.
-  static bool HasBeenSetup();
+  bool HasBeenSetup();
 
   // Returns the maximum amount of memory reserved for the heap.  For
   // the young generation, we reserve 4 times the amount needed for a
   // semi space.  The young generation consists of two semi spaces and
   // we reserve twice the amount needed for those in order to ensure
   // that new space can be aligned to its size.
-  static intptr_t MaxReserved() {
+  intptr_t MaxReserved() {
     return 4 * reserved_semispace_size_ + max_old_generation_size_;
   }
-  static int MaxSemiSpaceSize() { return max_semispace_size_; }
-  static int ReservedSemiSpaceSize() { return reserved_semispace_size_; }
-  static int InitialSemiSpaceSize() { return initial_semispace_size_; }
-  static intptr_t MaxOldGenerationSize() { return max_old_generation_size_; }
-  static intptr_t MaxExecutableSize() { return max_executable_size_; }
+  int MaxSemiSpaceSize() { return max_semispace_size_; }
+  int ReservedSemiSpaceSize() { return reserved_semispace_size_; }
+  int InitialSemiSpaceSize() { return initial_semispace_size_; }
+  intptr_t MaxOldGenerationSize() { return max_old_generation_size_; }
+  intptr_t MaxExecutableSize() { return max_executable_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 intptr_t Capacity();
+  intptr_t Capacity();
 
   // Returns the amount of memory currently committed for the heap.
-  static intptr_t CommittedMemory();
+  intptr_t CommittedMemory();
 
   // Returns the amount of executable memory currently committed for the heap.
-  static intptr_t CommittedMemoryExecutable();
+  intptr_t CommittedMemoryExecutable();
 
   // 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 intptr_t Available();
+  intptr_t Available();
 
   // Returns the maximum object size in paged space.
-  static inline int MaxObjectSizeInPagedSpace();
+  inline int MaxObjectSizeInPagedSpace();
 
   // Returns of size of all objects residing in the heap.
-  static intptr_t SizeOfObjects();
+  intptr_t 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 uintptr_t NewSpaceMask() { return new_space_.mask(); }
-  static Address NewSpaceTop() { return new_space_.top(); }
+  Address NewSpaceStart() { return new_space_.start(); }
+  uintptr_t NewSpaceMask() { return new_space_.mask(); }
+  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 CellSpace* cell_space() { return cell_space_; }
-  static LargeObjectSpace* lo_space() { return lo_space_; }
+  NewSpace* new_space() { return &new_space_; }
+  OldSpace* old_pointer_space() { return old_pointer_space_; }
+  OldSpace* old_data_space() { return old_data_space_; }
+  OldSpace* code_space() { return code_space_; }
+  MapSpace* map_space() { return map_space_; }
+  CellSpace* cell_space() { return cell_space_; }
+  LargeObjectSpace* lo_space() { return lo_space_; }
 
-  static bool always_allocate() { return always_allocate_scope_depth_ != 0; }
-  static Address always_allocate_scope_depth_address() {
+  bool always_allocate() { return always_allocate_scope_depth_ != 0; }
+  Address always_allocate_scope_depth_address() {
     return reinterpret_cast<Address>(&always_allocate_scope_depth_);
   }
-  static bool linear_allocation() {
+  bool linear_allocation() {
     return linear_allocation_scope_depth_ != 0;
   }
 
-  static Address* NewSpaceAllocationTopAddress() {
+  Address* NewSpaceAllocationTopAddress() {
     return new_space_.allocation_top_address();
   }
-  static Address* NewSpaceAllocationLimitAddress() {
+  Address* NewSpaceAllocationLimitAddress() {
     return new_space_.allocation_limit_address();
   }
 
   // Uncommit unused semi space.
-  static bool UncommitFromSpace() { return new_space_.UncommitFromSpace(); }
+  bool UncommitFromSpace() { return new_space_.UncommitFromSpace(); }
 
 #ifdef ENABLE_HEAP_PROTECTION
   // Protect/unprotect the heap by marking all spaces read-only/writable.
-  static void Protect();
-  static void Unprotect();
+  void Protect();
+  void Unprotect();
 #endif
 
   // Allocates and initializes a new JavaScript object based on a
@@ -338,71 +427,65 @@
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
   // Please note this does not perform a garbage collection.
-  MUST_USE_RESULT static MaybeObject* AllocateJSObject(
+  MUST_USE_RESULT MaybeObject* AllocateJSObject(
       JSFunction* constructor, PretenureFlag pretenure = NOT_TENURED);
 
   // Allocates and initializes a new global object based on a constructor.
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
   // Please note this does not perform a garbage collection.
-  MUST_USE_RESULT static MaybeObject* AllocateGlobalObject(
-      JSFunction* constructor);
+  MUST_USE_RESULT MaybeObject* AllocateGlobalObject(JSFunction* constructor);
 
   // Returns a deep copy of the JavaScript object.
   // Properties and elements are copied too.
   // Returns failure if allocation failed.
-  MUST_USE_RESULT static MaybeObject* CopyJSObject(JSObject* source);
+  MUST_USE_RESULT MaybeObject* 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.
-  MUST_USE_RESULT static MaybeObject* AllocateFunctionPrototype(
-      JSFunction* function);
+  MUST_USE_RESULT MaybeObject* 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.
-  MUST_USE_RESULT static MaybeObject* ReinitializeJSGlobalProxy(
-      JSFunction* constructor,
-      JSGlobalProxy* global);
+  MUST_USE_RESULT MaybeObject* 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.
-  MUST_USE_RESULT static MaybeObject* AllocateJSObjectFromMap(
+  MUST_USE_RESULT MaybeObject* 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.
-  MUST_USE_RESULT static MaybeObject* Allocate(Map* map, AllocationSpace space);
+  MUST_USE_RESULT MaybeObject* 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.
-  MUST_USE_RESULT static MaybeObject* AllocateMap(InstanceType instance_type,
-                                             int instance_size);
+  MUST_USE_RESULT MaybeObject* AllocateMap(InstanceType instance_type,
+                                           int instance_size);
 
   // Allocates a partial map for bootstrapping.
-  MUST_USE_RESULT static MaybeObject* AllocatePartialMap(
-      InstanceType instance_type,
-      int instance_size);
+  MUST_USE_RESULT MaybeObject* AllocatePartialMap(InstanceType instance_type,
+                                                  int instance_size);
 
   // Allocate a map for the specified function
-  MUST_USE_RESULT static MaybeObject* AllocateInitialMap(JSFunction* fun);
+  MUST_USE_RESULT MaybeObject* AllocateInitialMap(JSFunction* fun);
 
   // Allocates an empty code cache.
-  MUST_USE_RESULT static MaybeObject* AllocateCodeCache();
+  MUST_USE_RESULT MaybeObject* AllocateCodeCache();
 
   // Clear the Instanceof cache (used when a prototype changes).
-  static void ClearInstanceofCache() {
-    set_instanceof_cache_function(the_hole_value());
-  }
+  inline void ClearInstanceofCache();
 
   // Allocates and fully initializes a String.  There are two String
   // encodings: ASCII and two byte. One should choose between the three string
@@ -422,16 +505,16 @@
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
   // Please note this does not perform a garbage collection.
-  MUST_USE_RESULT static MaybeObject* AllocateStringFromAscii(
+  MUST_USE_RESULT MaybeObject* AllocateStringFromAscii(
       Vector<const char> str,
       PretenureFlag pretenure = NOT_TENURED);
-  MUST_USE_RESULT static inline MaybeObject* AllocateStringFromUtf8(
+  MUST_USE_RESULT inline MaybeObject* AllocateStringFromUtf8(
       Vector<const char> str,
       PretenureFlag pretenure = NOT_TENURED);
-  MUST_USE_RESULT static MaybeObject* AllocateStringFromUtf8Slow(
+  MUST_USE_RESULT MaybeObject* AllocateStringFromUtf8Slow(
       Vector<const char> str,
       PretenureFlag pretenure = NOT_TENURED);
-  MUST_USE_RESULT static MaybeObject* AllocateStringFromTwoByte(
+  MUST_USE_RESULT MaybeObject* AllocateStringFromTwoByte(
       Vector<const uc16> str,
       PretenureFlag pretenure = NOT_TENURED);
 
@@ -439,27 +522,25 @@
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
   // Please note this function does not perform a garbage collection.
-  MUST_USE_RESULT static inline MaybeObject* AllocateSymbol(
-      Vector<const char> str,
-      int chars,
-      uint32_t hash_field);
+  MUST_USE_RESULT inline MaybeObject* AllocateSymbol(Vector<const char> str,
+                                                     int chars,
+                                                     uint32_t hash_field);
 
-  MUST_USE_RESULT static inline MaybeObject* AllocateAsciiSymbol(
+  MUST_USE_RESULT inline MaybeObject* AllocateAsciiSymbol(
         Vector<const char> str,
         uint32_t hash_field);
 
-  MUST_USE_RESULT static inline MaybeObject* AllocateTwoByteSymbol(
+  MUST_USE_RESULT inline MaybeObject* AllocateTwoByteSymbol(
         Vector<const uc16> str,
         uint32_t hash_field);
 
-  MUST_USE_RESULT static MaybeObject* AllocateInternalSymbol(
+  MUST_USE_RESULT MaybeObject* AllocateInternalSymbol(
       unibrow::CharacterStream* buffer, int chars, uint32_t hash_field);
 
-  MUST_USE_RESULT static MaybeObject* AllocateExternalSymbol(
+  MUST_USE_RESULT MaybeObject* 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
@@ -467,10 +548,10 @@
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
   // Please note this does not perform a garbage collection.
-  MUST_USE_RESULT static MaybeObject* AllocateRawAsciiString(
+  MUST_USE_RESULT MaybeObject* AllocateRawAsciiString(
       int length,
       PretenureFlag pretenure = NOT_TENURED);
-  MUST_USE_RESULT static MaybeObject* AllocateRawTwoByteString(
+  MUST_USE_RESULT MaybeObject* AllocateRawTwoByteString(
       int length,
       PretenureFlag pretenure = NOT_TENURED);
 
@@ -478,35 +559,27 @@
   // 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.
-  MUST_USE_RESULT static MaybeObject* LookupSingleCharacterStringFromCode(
+  MUST_USE_RESULT MaybeObject* 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.
-  MUST_USE_RESULT static MaybeObject* AllocateByteArray(int length,
-                                                   PretenureFlag pretenure);
+  MUST_USE_RESULT MaybeObject* 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.
-  MUST_USE_RESULT static MaybeObject* AllocateByteArray(int length);
-
-  // Allocate a pixel array of the specified length
-  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
-  // failed.
-  // Please note this does not perform a garbage collection.
-  MUST_USE_RESULT static MaybeObject* AllocatePixelArray(int length,
-                                                    uint8_t* external_pointer,
-                                                    PretenureFlag pretenure);
+  MUST_USE_RESULT MaybeObject* AllocateByteArray(int length);
 
   // Allocates an external array of the specified length and type.
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
   // Please note this does not perform a garbage collection.
-  MUST_USE_RESULT static MaybeObject* AllocateExternalArray(
+  MUST_USE_RESULT MaybeObject* AllocateExternalArray(
       int length,
       ExternalArrayType array_type,
       void* external_pointer,
@@ -516,132 +589,130 @@
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
   // Please note this does not perform a garbage collection.
-  MUST_USE_RESULT static MaybeObject* AllocateJSGlobalPropertyCell(
-      Object* value);
+  MUST_USE_RESULT MaybeObject* AllocateJSGlobalPropertyCell(Object* value);
 
   // 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.
-  MUST_USE_RESULT static MaybeObject* AllocateFixedArray(
-      int length,
-      PretenureFlag pretenure);
+  MUST_USE_RESULT MaybeObject* AllocateFixedArray(int length,
+                                                  PretenureFlag pretenure);
   // Allocates a fixed array initialized with undefined values
-  MUST_USE_RESULT static MaybeObject* AllocateFixedArray(int length);
+  MUST_USE_RESULT MaybeObject* AllocateFixedArray(int length);
 
   // Allocates an uninitialized fixed array. It must be filled by the caller.
   //
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
   // Please note this does not perform a garbage collection.
-  MUST_USE_RESULT static MaybeObject* AllocateUninitializedFixedArray(
-      int length);
+  MUST_USE_RESULT MaybeObject* AllocateUninitializedFixedArray(int length);
 
   // Make a copy of src and return it. Returns
   // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed.
-  MUST_USE_RESULT static inline MaybeObject* CopyFixedArray(FixedArray* src);
+  MUST_USE_RESULT inline MaybeObject* CopyFixedArray(FixedArray* src);
 
   // Make a copy of src, set the map, and return the copy. Returns
   // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed.
-  MUST_USE_RESULT static MaybeObject* CopyFixedArrayWithMap(FixedArray* src,
-                                                            Map* map);
+  MUST_USE_RESULT MaybeObject* CopyFixedArrayWithMap(FixedArray* src, Map* map);
 
   // 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.
-  MUST_USE_RESULT static MaybeObject* AllocateFixedArrayWithHoles(
+  MUST_USE_RESULT MaybeObject* AllocateFixedArrayWithHoles(
       int length,
       PretenureFlag pretenure = NOT_TENURED);
 
   // AllocateHashTable is identical to AllocateFixedArray except
   // that the resulting object has hash_table_map as map.
-  MUST_USE_RESULT static MaybeObject* AllocateHashTable(
+  MUST_USE_RESULT MaybeObject* AllocateHashTable(
       int length, PretenureFlag pretenure = NOT_TENURED);
 
   // Allocate a global (but otherwise uninitialized) context.
-  MUST_USE_RESULT static MaybeObject* AllocateGlobalContext();
+  MUST_USE_RESULT MaybeObject* AllocateGlobalContext();
 
   // Allocate a function context.
-  MUST_USE_RESULT static MaybeObject* AllocateFunctionContext(
-      int length,
-      JSFunction* closure);
+  MUST_USE_RESULT MaybeObject* AllocateFunctionContext(int length,
+                                                       JSFunction* closure);
 
   // Allocate a 'with' context.
-  MUST_USE_RESULT static MaybeObject* AllocateWithContext(
-      Context* previous,
-      JSObject* extension,
-      bool is_catch_context);
+  MUST_USE_RESULT MaybeObject* AllocateWithContext(Context* previous,
+                                                   JSObject* extension,
+                                                   bool is_catch_context);
 
   // Allocates a new utility object in the old generation.
-  MUST_USE_RESULT static MaybeObject* AllocateStruct(InstanceType type);
+  MUST_USE_RESULT MaybeObject* AllocateStruct(InstanceType type);
 
   // 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.
-  MUST_USE_RESULT static MaybeObject* AllocateFunction(
+  MUST_USE_RESULT MaybeObject* AllocateFunction(
       Map* function_map,
       SharedFunctionInfo* shared,
       Object* prototype,
       PretenureFlag pretenure = TENURED);
 
-  // Indicies for direct access into argument objects.
+  // Arguments object size.
   static const int kArgumentsObjectSize =
       JSObject::kHeaderSize + 2 * kPointerSize;
-  static const int arguments_callee_index = 0;
-  static const int arguments_length_index = 1;
+  // Strict mode arguments has no callee so it is smaller.
+  static const int kArgumentsObjectSizeStrict =
+      JSObject::kHeaderSize + 1 * kPointerSize;
+  // Indicies for direct access into argument objects.
+  static const int kArgumentsLengthIndex = 0;
+  // callee is only valid in non-strict mode.
+  static const int kArgumentsCalleeIndex = 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.
-  MUST_USE_RESULT static MaybeObject* AllocateArgumentsObject(Object* callee,
-                                                              int length);
+  MUST_USE_RESULT MaybeObject* AllocateArgumentsObject(
+      Object* callee, int length);
 
   // Same as NewNumberFromDouble, but may return a preallocated/immutable
   // number object (e.g., minus_zero_value_, nan_value_)
-  MUST_USE_RESULT static MaybeObject* NumberFromDouble(
+  MUST_USE_RESULT MaybeObject* NumberFromDouble(
       double value, PretenureFlag pretenure = NOT_TENURED);
 
   // Allocated a HeapNumber from value.
-  MUST_USE_RESULT static MaybeObject* AllocateHeapNumber(
+  MUST_USE_RESULT MaybeObject* AllocateHeapNumber(
       double value,
       PretenureFlag pretenure);
-  // pretenure = NOT_TENURED.
-  MUST_USE_RESULT static MaybeObject* AllocateHeapNumber(double value);
+  // pretenure = NOT_TENURED
+  MUST_USE_RESULT MaybeObject* AllocateHeapNumber(double 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.
-  MUST_USE_RESULT static inline MaybeObject* NumberFromInt32(int32_t value);
+  MUST_USE_RESULT inline MaybeObject* 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.
-  MUST_USE_RESULT static inline MaybeObject* NumberFromUint32(uint32_t value);
+  MUST_USE_RESULT inline MaybeObject* 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.
-  MUST_USE_RESULT static MaybeObject* AllocateProxy(
-      Address proxy,
-      PretenureFlag pretenure = NOT_TENURED);
+  MUST_USE_RESULT MaybeObject* 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.
-  MUST_USE_RESULT static MaybeObject* AllocateSharedFunctionInfo(Object* name);
+  MUST_USE_RESULT MaybeObject* AllocateSharedFunctionInfo(Object* name);
 
   // Allocates a new JSMessageObject object.
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
   // Please note that this does not perform a garbage collection.
-  MUST_USE_RESULT static MaybeObject* AllocateJSMessageObject(
+  MUST_USE_RESULT MaybeObject* AllocateJSMessageObject(
       String* type,
       JSArray* arguments,
       int start_position,
@@ -654,8 +725,8 @@
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
   // Please note this does not perform a garbage collection.
-  MUST_USE_RESULT static MaybeObject* AllocateConsString(String* first,
-                                                         String* second);
+  MUST_USE_RESULT MaybeObject* AllocateConsString(String* first,
+                                                  String* second);
 
   // Allocates a new sub string object which is a substring of an underlying
   // string buffer stretching from the index start (inclusive) to the index
@@ -663,7 +734,7 @@
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
   // Please note this does not perform a garbage collection.
-  MUST_USE_RESULT static MaybeObject* AllocateSubString(
+  MUST_USE_RESULT MaybeObject* AllocateSubString(
       String* buffer,
       int start,
       int end,
@@ -674,28 +745,27 @@
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
   // Please note this does not perform a garbage collection.
-  MUST_USE_RESULT static MaybeObject* AllocateExternalStringFromAscii(
+  MUST_USE_RESULT MaybeObject* AllocateExternalStringFromAscii(
       ExternalAsciiString::Resource* resource);
-  MUST_USE_RESULT static MaybeObject* AllocateExternalStringFromTwoByte(
+  MUST_USE_RESULT MaybeObject* AllocateExternalStringFromTwoByte(
       ExternalTwoByteString::Resource* resource);
 
   // Finalizes an external string by deleting the associated external
   // data and clearing the resource pointer.
-  static inline void FinalizeExternalString(String* string);
+  inline void FinalizeExternalString(String* string);
 
   // 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.
-  MUST_USE_RESULT static inline MaybeObject* AllocateRaw(
-      int size_in_bytes,
-      AllocationSpace space,
-      AllocationSpace retry_space);
+  MUST_USE_RESULT inline MaybeObject* 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);
+  void CreateFillerObjectAt(Address addr, int size);
 
   // Makes a new native code object
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
@@ -703,36 +773,36 @@
   // 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.
-  MUST_USE_RESULT static MaybeObject* CreateCode(const CodeDesc& desc,
-                                                 Code::Flags flags,
-                                                 Handle<Object> self_reference);
+  MUST_USE_RESULT MaybeObject* CreateCode(const CodeDesc& desc,
+                                          Code::Flags flags,
+                                          Handle<Object> self_reference,
+                                          bool immovable = false);
 
-  MUST_USE_RESULT static MaybeObject* CopyCode(Code* code);
+  MUST_USE_RESULT MaybeObject* CopyCode(Code* code);
 
   // Copy the code and scope info part of the code object, but insert
   // the provided data as the relocation information.
-  MUST_USE_RESULT static MaybeObject* CopyCode(Code* code,
-                                               Vector<byte> reloc_info);
+  MUST_USE_RESULT MaybeObject* CopyCode(Code* code, Vector<byte> reloc_info);
 
   // 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.
-  MUST_USE_RESULT static MaybeObject* LookupSymbol(Vector<const char> str);
-  MUST_USE_RESULT static MaybeObject* LookupAsciiSymbol(Vector<const char> str);
-  MUST_USE_RESULT static MaybeObject* LookupTwoByteSymbol(
+  MUST_USE_RESULT MaybeObject* LookupSymbol(Vector<const char> str);
+  MUST_USE_RESULT MaybeObject* LookupAsciiSymbol(Vector<const char> str);
+  MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol(
       Vector<const uc16> str);
-  MUST_USE_RESULT static MaybeObject* LookupAsciiSymbol(const char* str) {
+  MUST_USE_RESULT MaybeObject* LookupAsciiSymbol(const char* str) {
     return LookupSymbol(CStrVector(str));
   }
-  MUST_USE_RESULT static MaybeObject* LookupSymbol(String* str);
-  static bool LookupSymbolIfExists(String* str, String** symbol);
-  static bool LookupTwoCharsSymbolIfExists(String* str, String** symbol);
+  MUST_USE_RESULT MaybeObject* LookupSymbol(String* str);
+  bool LookupSymbolIfExists(String* str, String** symbol);
+  bool LookupTwoCharsSymbolIfExists(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);
+  Map* SymbolMapForString(String* str);
 
   // Tries to flatten a string before compare operation.
   //
@@ -741,60 +811,60 @@
   // string might stay non-flat even when not a failure is returned.
   //
   // Please note this function does not perform a garbage collection.
-  MUST_USE_RESULT static inline MaybeObject* PrepareForCompare(String* str);
+  MUST_USE_RESULT inline MaybeObject* PrepareForCompare(String* str);
 
   // Converts the given boolean condition to JavaScript boolean value.
-  static Object* ToBoolean(bool condition) {
-    return condition ? true_value() : false_value();
-  }
+  inline Object* ToBoolean(bool condition);
 
   // 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();
+  void GarbageCollectionPrologue();
+  void GarbageCollectionEpilogue();
 
   // Performs garbage collection operation.
   // Returns whether there is a chance that another major GC could
   // collect more garbage.
-  static bool CollectGarbage(AllocationSpace space, GarbageCollector collector);
+  bool CollectGarbage(AllocationSpace space, GarbageCollector collector);
 
   // Performs garbage collection operation.
   // Returns whether there is a chance that another major GC could
   // collect more garbage.
-  inline static bool CollectGarbage(AllocationSpace space);
+  inline bool CollectGarbage(AllocationSpace space);
 
   // Performs a full garbage collection. Force compaction if the
   // parameter is true.
-  static void CollectAllGarbage(bool force_compaction);
+  void CollectAllGarbage(bool force_compaction);
 
   // Last hope GC, should try to squeeze as much as possible.
-  static void CollectAllAvailableGarbage();
+  void CollectAllAvailableGarbage();
 
   // Notify the heap that a context has been disposed.
-  static int NotifyContextDisposed() { return ++contexts_disposed_; }
+  int NotifyContextDisposed() { return ++contexts_disposed_; }
 
   // Utility to invoke the scavenger. This is needed in test code to
   // ensure correct callback for weak global handles.
-  static void PerformScavenge();
+  void PerformScavenge();
+
+  PromotionQueue* promotion_queue() { return &promotion_queue_; }
 
 #ifdef DEBUG
   // Utility used with flag gc-greedy.
-  static void GarbageCollectionGreedyCheck();
+  void GarbageCollectionGreedyCheck();
 #endif
 
-  static void AddGCPrologueCallback(
+  void AddGCPrologueCallback(
       GCEpilogueCallback callback, GCType gc_type_filter);
-  static void RemoveGCPrologueCallback(GCEpilogueCallback callback);
+  void RemoveGCPrologueCallback(GCEpilogueCallback callback);
 
-  static void AddGCEpilogueCallback(
+  void AddGCEpilogueCallback(
       GCEpilogueCallback callback, GCType gc_type_filter);
-  static void RemoveGCEpilogueCallback(GCEpilogueCallback callback);
+  void RemoveGCEpilogueCallback(GCEpilogueCallback callback);
 
-  static void SetGlobalGCPrologueCallback(GCCallback callback) {
+  void SetGlobalGCPrologueCallback(GCCallback callback) {
     ASSERT((callback == NULL) ^ (global_gc_prologue_callback_ == NULL));
     global_gc_prologue_callback_ = callback;
   }
-  static void SetGlobalGCEpilogueCallback(GCCallback callback) {
+  void SetGlobalGCEpilogueCallback(GCCallback callback) {
     ASSERT((callback == NULL) ^ (global_gc_epilogue_callback_ == NULL));
     global_gc_epilogue_callback_ = callback;
   }
@@ -802,10 +872,10 @@
   // Heap root getters.  We have versions with and without type::cast() here.
   // You can't use type::cast during GC because the assert fails.
 #define ROOT_ACCESSOR(type, name, camel_name)                                  \
-  static inline type* name() {                                                 \
+  type* name() {                                                               \
     return type::cast(roots_[k##camel_name##RootIndex]);                       \
   }                                                                            \
-  static inline type* raw_unchecked_##name() {                                 \
+  type* raw_unchecked_##name() {                                               \
     return reinterpret_cast<type*>(roots_[k##camel_name##RootIndex]);          \
   }
   ROOT_LIST(ROOT_ACCESSOR)
@@ -813,13 +883,13 @@
 
 // Utility type maps
 #define STRUCT_MAP_ACCESSOR(NAME, Name, name)                                  \
-    static inline Map* name##_map() {                                          \
+    Map* name##_map() {                                                        \
       return Map::cast(roots_[k##Name##MapRootIndex]);                         \
     }
   STRUCT_LIST(STRUCT_MAP_ACCESSOR)
 #undef STRUCT_MAP_ACCESSOR
 
-#define SYMBOL_ACCESSOR(name, str) static inline String* name() {              \
+#define SYMBOL_ACCESSOR(name, str) String* name() {                            \
     return String::cast(roots_[k##name##RootIndex]);                           \
   }
   SYMBOL_LIST(SYMBOL_ACCESSOR)
@@ -827,19 +897,19 @@
 
   // 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_; }
+  String* hidden_symbol() { return hidden_symbol_; }
 
-  static void set_global_contexts_list(Object* object) {
+  void set_global_contexts_list(Object* object) {
     global_contexts_list_ = object;
   }
-  static Object* global_contexts_list() { return global_contexts_list_; }
+  Object* global_contexts_list() { return global_contexts_list_; }
 
   // Iterates over all roots in the heap.
-  static void IterateRoots(ObjectVisitor* v, VisitMode mode);
+  void IterateRoots(ObjectVisitor* v, VisitMode mode);
   // Iterates over all strong roots in the heap.
-  static void IterateStrongRoots(ObjectVisitor* v, VisitMode mode);
+  void IterateStrongRoots(ObjectVisitor* v, VisitMode mode);
   // Iterates over all the other roots in the heap.
-  static void IterateWeakRoots(ObjectVisitor* v, VisitMode mode);
+  void IterateWeakRoots(ObjectVisitor* v, VisitMode mode);
 
   enum ExpectedPageWatermarkState {
     WATERMARK_SHOULD_BE_VALID,
@@ -853,7 +923,7 @@
   // can_preallocate_during_iteration should be set to true.
   // All pages will be marked as having invalid watermark upon
   // iteration completion.
-  static void IterateDirtyRegions(
+  void IterateDirtyRegions(
       PagedSpace* space,
       DirtyRegionCallback visit_dirty_region,
       ObjectSlotCallback callback,
@@ -863,22 +933,23 @@
   // Page::kRegionSize aligned by Page::kRegionAlignmentMask and covering
   // memory interval from start to top. For each dirty region call a
   // visit_dirty_region callback. Return updated bitvector of dirty marks.
-  static uint32_t IterateDirtyRegions(uint32_t marks,
-                                      Address start,
-                                      Address end,
-                                      DirtyRegionCallback visit_dirty_region,
-                                      ObjectSlotCallback callback);
+  uint32_t IterateDirtyRegions(uint32_t marks,
+                               Address start,
+                               Address end,
+                               DirtyRegionCallback visit_dirty_region,
+                               ObjectSlotCallback callback);
 
   // Iterate pointers to from semispace of new space found in memory interval
   // from start to end.
   // Update dirty marks for page containing start address.
-  static void IterateAndMarkPointersToFromSpace(Address start,
-                                                Address end,
-                                                ObjectSlotCallback callback);
+  void IterateAndMarkPointersToFromSpace(Address start,
+                                         Address end,
+                                         ObjectSlotCallback callback);
 
   // Iterate pointers to new space found in memory interval from start to end.
   // Return true if pointers to new space was found.
-  static bool IteratePointersInDirtyRegion(Address start,
+  static bool IteratePointersInDirtyRegion(Heap* heap,
+                                           Address start,
                                            Address end,
                                            ObjectSlotCallback callback);
 
@@ -886,127 +957,127 @@
   // Iterate pointers to new space found in memory interval from start to end.
   // This interval is considered to belong to the map space.
   // Return true if pointers to new space was found.
-  static bool IteratePointersInDirtyMapsRegion(Address start,
+  static bool IteratePointersInDirtyMapsRegion(Heap* heap,
+                                               Address start,
                                                Address end,
                                                ObjectSlotCallback callback);
 
 
   // 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);
+  inline bool InNewSpace(Object* object);
+  inline bool InFromSpace(Object* object);
+  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);
+  bool Contains(Address addr);
+  bool Contains(HeapObject* value);
 
   // Checks whether an address/object in a space.
   // Currently used by tests, serialization and heap verification only.
-  static bool InSpace(Address addr, AllocationSpace space);
-  static bool InSpace(HeapObject* value, AllocationSpace space);
+  bool InSpace(Address addr, AllocationSpace space);
+  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);
+  inline OldSpace* TargetSpace(HeapObject* object);
+  inline AllocationSpace TargetSpaceId(InstanceType type);
 
   // Sets the stub_cache_ (only used when expanding the dictionary).
-  static void public_set_code_stubs(NumberDictionary* value) {
+  void public_set_code_stubs(NumberDictionary* value) {
     roots_[kCodeStubsRootIndex] = value;
   }
 
   // Support for computing object sizes for old objects during GCs. Returns
   // a function that is guaranteed to be safe for computing object sizes in
   // the current GC phase.
-  static HeapObjectCallback GcSafeSizeOfOldObjectFunction() {
+  HeapObjectCallback GcSafeSizeOfOldObjectFunction() {
     return gc_safe_size_of_old_object_;
   }
 
   // Sets the non_monomorphic_cache_ (only used when expanding the dictionary).
-  static void public_set_non_monomorphic_cache(NumberDictionary* value) {
+  void public_set_non_monomorphic_cache(NumberDictionary* value) {
     roots_[kNonMonomorphicCacheRootIndex] = value;
   }
 
-  static void public_set_empty_script(Script* script) {
+  void public_set_empty_script(Script* script) {
     roots_[kEmptyScriptRootIndex] = script;
   }
 
   // Update the next script id.
-  static inline void SetLastScriptId(Object* last_script_id);
+  inline void SetLastScriptId(Object* last_script_id);
 
   // Generated code can embed this address to get access to the roots.
-  static Object** roots_address() { return roots_; }
+  Object** roots_address() { return roots_; }
 
   // Get address of global contexts list for serialization support.
-  static Object** global_contexts_list_address() {
+  Object** global_contexts_list_address() {
     return &global_contexts_list_;
   }
 
 #ifdef DEBUG
-  static void Print();
-  static void PrintHandles();
+  void Print();
+  void PrintHandles();
 
   // Verify the heap is in its normal state before or after a GC.
-  static void Verify();
+  void Verify();
 
   // Report heap statistics.
-  static void ReportHeapStatistics(const char* title);
-  static void ReportCodeStatistics(const char* title);
+  void ReportHeapStatistics(const char* title);
+  void ReportCodeStatistics(const char* title);
 
   // Fill in bogus values in from space
-  static void ZapFromSpace();
+  void ZapFromSpace();
 #endif
 
 #if defined(ENABLE_LOGGING_AND_PROFILING)
   // Print short heap statistics.
-  static void PrintShortHeapStatistics();
+  void PrintShortHeapStatistics();
 #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.
-  MUST_USE_RESULT static MaybeObject* CreateSymbol(const char* str,
-                                                   int length,
-                                                   int hash);
-  MUST_USE_RESULT static MaybeObject* CreateSymbol(String* str);
+  MUST_USE_RESULT MaybeObject* CreateSymbol(
+      const char* str, int length, int hash);
+  MUST_USE_RESULT MaybeObject* CreateSymbol(String* str);
 
   // Write barrier support for address[offset] = o.
-  static inline void RecordWrite(Address address, int offset);
+  inline void RecordWrite(Address address, int offset);
 
   // Write barrier support for address[start : start + len[ = o.
-  static inline void RecordWrites(Address address, int start, int len);
+  inline void RecordWrites(Address address, int start, int len);
 
   // Given an address occupied by a live code object, return that object.
-  static Object* FindCodeObject(Address a);
+  Object* FindCodeObject(Address a);
 
   // Invoke Shrink on shrinkable spaces.
-  static void Shrink();
+  void Shrink();
 
   enum HeapState { NOT_IN_GC, SCAVENGE, MARK_COMPACT };
-  static inline HeapState gc_state() { return gc_state_; }
+  inline HeapState gc_state() { return gc_state_; }
 
 #ifdef DEBUG
-  static bool IsAllocationAllowed() { return allocation_allowed_; }
-  static inline bool allow_allocation(bool enable);
+  bool IsAllocationAllowed() { return allocation_allowed_; }
+  inline bool allow_allocation(bool enable);
 
-  static bool disallow_allocation_failure() {
+  bool disallow_allocation_failure() {
     return disallow_allocation_failure_;
   }
 
-  static void TracePathToObject(Object* target);
-  static void TracePathToGlobal();
+  void TracePathToObject(Object* target);
+  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 ScavengePointer(HeapObject** p);
   static inline void ScavengeObject(HeapObject** p, HeapObject* object);
 
   // Commits from space if it is uncommitted.
-  static void EnsureFromSpaceIsCommitted();
+  void EnsureFromSpaceIsCommitted();
 
   // Support for partial snapshots.  After calling this we can allocate a
   // certain number of bytes using only linear allocation (with a
@@ -1014,7 +1085,7 @@
   // or causing a GC.  It returns true of space was reserved or false if a GC is
   // needed.  For paged spaces the space requested must include the space wasted
   // at the end of each page when allocating linearly.
-  static void ReserveSpace(
+  void ReserveSpace(
     int new_space_size,
     int pointer_space_size,
     int data_space_size,
@@ -1027,45 +1098,44 @@
   // Support for the API.
   //
 
-  static bool CreateApiObjects();
+  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);
+  Object* GetNumberStringCache(Object* number);
 
   // Update the cache with a new number-string pair.
-  static void SetNumberStringCache(Object* number, String* str);
+  void SetNumberStringCache(Object* number, String* str);
 
   // Adjusts the amount of registered external memory.
   // Returns the adjusted value.
-  static inline int AdjustAmountOfExternalAllocatedMemory(int change_in_bytes);
+  inline int AdjustAmountOfExternalAllocatedMemory(int change_in_bytes);
 
   // Allocate uninitialized fixed array.
-  MUST_USE_RESULT static MaybeObject* AllocateRawFixedArray(int length);
-  MUST_USE_RESULT static MaybeObject* AllocateRawFixedArray(
-      int length,
-      PretenureFlag pretenure);
+  MUST_USE_RESULT MaybeObject* AllocateRawFixedArray(int length);
+  MUST_USE_RESULT MaybeObject* AllocateRawFixedArray(int length,
+                                                     PretenureFlag pretenure);
 
   // 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() {
+  bool OldGenerationPromotionLimitReached() {
     return (PromotedSpaceSize() + PromotedExternalMemorySize())
            > old_gen_promotion_limit_;
   }
 
-  static intptr_t OldGenerationSpaceAvailable() {
+  intptr_t OldGenerationSpaceAvailable() {
     return old_gen_allocation_limit_ -
            (PromotedSpaceSize() + PromotedExternalMemorySize());
   }
 
   // True if we have reached the allocation limit in the old generation that
   // should artificially cause a GC right now.
-  static bool OldGenerationAllocationLimitReached() {
+  bool OldGenerationAllocationLimitReached() {
     return OldGenerationSpaceAvailable() < 0;
   }
 
   // Can be called when the embedding application is idle.
-  static bool IdleNotification();
+  bool IdleNotification();
 
   // Declare all the root indices.
   enum RootListIndex {
@@ -1087,76 +1157,109 @@
     kRootListLength
   };
 
-  MUST_USE_RESULT static MaybeObject* NumberToString(
-      Object* number,
-      bool check_number_string_cache = true);
+  MUST_USE_RESULT MaybeObject* NumberToString(
+      Object* number, bool check_number_string_cache = true);
 
-  static Map* MapForExternalArrayType(ExternalArrayType array_type);
-  static RootListIndex RootIndexForExternalArrayType(
+  Map* MapForExternalArrayType(ExternalArrayType array_type);
+  RootListIndex RootIndexForExternalArrayType(
       ExternalArrayType array_type);
 
-  static void RecordStats(HeapStats* stats, bool take_snapshot = false);
+  void RecordStats(HeapStats* stats, bool take_snapshot = false);
 
   // Copy block of memory from src to dst. Size of block should be aligned
   // by pointer size.
   static inline void CopyBlock(Address dst, Address src, int byte_size);
 
-  static inline void CopyBlockToOldSpaceAndUpdateRegionMarks(Address dst,
-                                                             Address src,
-                                                             int byte_size);
+  inline void CopyBlockToOldSpaceAndUpdateRegionMarks(Address dst,
+                                                      Address src,
+                                                      int byte_size);
 
   // Optimized version of memmove for blocks with pointer size aligned sizes and
   // pointer size aligned addresses.
   static inline void MoveBlock(Address dst, Address src, int byte_size);
 
-  static inline void MoveBlockToOldSpaceAndUpdateRegionMarks(Address dst,
-                                                             Address src,
-                                                             int byte_size);
+  inline void MoveBlockToOldSpaceAndUpdateRegionMarks(Address dst,
+                                                      Address src,
+                                                      int byte_size);
 
   // Check new space expansion criteria and expand semispaces if it was hit.
-  static void CheckNewSpaceExpansionCriteria();
+  void CheckNewSpaceExpansionCriteria();
 
-  static inline void IncrementYoungSurvivorsCounter(int survived) {
+  inline void IncrementYoungSurvivorsCounter(int survived) {
     young_survivors_after_last_gc_ = survived;
     survived_since_last_expansion_ += survived;
   }
 
-  static void UpdateNewSpaceReferencesInExternalStringTable(
+  void UpdateNewSpaceReferencesInExternalStringTable(
       ExternalStringTableUpdaterCallback updater_func);
 
-  static void ProcessWeakReferences(WeakObjectRetainer* retainer);
+  void ProcessWeakReferences(WeakObjectRetainer* retainer);
 
   // 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);
+  inline bool ShouldBePromoted(Address old_address, int object_size);
 
-  static int MaxObjectSizeInNewSpace() { return kMaxObjectSizeInNewSpace; }
+  int MaxObjectSizeInNewSpace() { return kMaxObjectSizeInNewSpace; }
 
-  static void ClearJSFunctionResultCaches();
+  void ClearJSFunctionResultCaches();
 
-  static void ClearNormalizedMapCaches();
+  void ClearNormalizedMapCaches();
 
-  static GCTracer* tracer() { return tracer_; }
+  GCTracer* tracer() { return tracer_; }
+
+  // Returns maximum GC pause.
+  int get_max_gc_pause() { return max_gc_pause_; }
+
+  // Returns maximum size of objects alive after GC.
+  intptr_t get_max_alive_after_gc() { return max_alive_after_gc_; }
+
+  // Returns minimal interval between two subsequent collections.
+  int get_min_in_mutator() { return min_in_mutator_; }
+
+  MarkCompactCollector* mark_compact_collector() {
+    return &mark_compact_collector_;
+  }
+
+  ExternalStringTable* external_string_table() {
+    return &external_string_table_;
+  }
+
+  inline Isolate* isolate();
+  bool is_safe_to_read_maps() { return is_safe_to_read_maps_; }
+
+  void CallGlobalGCPrologueCallback() {
+    if (global_gc_prologue_callback_ != NULL) global_gc_prologue_callback_();
+  }
+
+  void CallGlobalGCEpilogueCallback() {
+    if (global_gc_epilogue_callback_ != NULL) global_gc_epilogue_callback_();
+  }
 
  private:
-  static int reserved_semispace_size_;
-  static int max_semispace_size_;
-  static int initial_semispace_size_;
-  static intptr_t max_old_generation_size_;
-  static intptr_t max_executable_size_;
-  static intptr_t code_range_size_;
+  Heap();
+
+  // This can be calculated directly from a pointer to the heap; however, it is
+  // more expedient to get at the isolate directly from within Heap methods.
+  Isolate* isolate_;
+
+  int reserved_semispace_size_;
+  int max_semispace_size_;
+  int initial_semispace_size_;
+  intptr_t max_old_generation_size_;
+  intptr_t max_executable_size_;
+  intptr_t code_range_size_;
 
   // For keeping track of how much data has survived
   // scavenge since last new space expansion.
-  static int survived_since_last_expansion_;
+  int survived_since_last_expansion_;
 
-  static int always_allocate_scope_depth_;
-  static int linear_allocation_scope_depth_;
+  int always_allocate_scope_depth_;
+  int linear_allocation_scope_depth_;
 
   // For keeping track of context disposals.
-  static int contexts_disposed_;
+  int contexts_disposed_;
 
 #if defined(V8_TARGET_ARCH_X64)
   static const int kMaxObjectSizeInNewSpace = 1024*KB;
@@ -1164,76 +1267,78 @@
   static const int kMaxObjectSizeInNewSpace = 512*KB;
 #endif
 
-  static NewSpace new_space_;
-  static OldSpace* old_pointer_space_;
-  static OldSpace* old_data_space_;
-  static OldSpace* code_space_;
-  static MapSpace* map_space_;
-  static CellSpace* cell_space_;
-  static LargeObjectSpace* lo_space_;
-  static HeapState gc_state_;
+  NewSpace new_space_;
+  OldSpace* old_pointer_space_;
+  OldSpace* old_data_space_;
+  OldSpace* code_space_;
+  MapSpace* map_space_;
+  CellSpace* cell_space_;
+  LargeObjectSpace* lo_space_;
+  HeapState gc_state_;
 
   // Returns the size of object residing in non new spaces.
-  static intptr_t PromotedSpaceSize();
+  intptr_t PromotedSpaceSize();
 
   // Returns the amount of external memory registered since last global gc.
-  static int PromotedExternalMemorySize();
+  int PromotedExternalMemorySize();
 
-  static int mc_count_;  // how many mark-compact collections happened
-  static int ms_count_;  // how many mark-sweep collections happened
-  static unsigned int gc_count_;  // how many gc happened
+  int mc_count_;  // how many mark-compact collections happened
+  int ms_count_;  // how many mark-sweep collections happened
+  unsigned int gc_count_;  // how many gc happened
 
   // Total length of the strings we failed to flatten since the last GC.
-  static int unflattened_strings_length_;
+  int unflattened_strings_length_;
 
 #define ROOT_ACCESSOR(type, name, camel_name)                                  \
-  static inline void set_##name(type* value) {                                 \
+  inline void set_##name(type* value) {                                 \
     roots_[k##camel_name##RootIndex] = value;                                  \
   }
   ROOT_LIST(ROOT_ACCESSOR)
 #undef ROOT_ACCESSOR
 
 #ifdef DEBUG
-  static bool allocation_allowed_;
+  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_;
+  int allocation_timeout_;
 
   // Do we expect to be able to handle allocation failure at this
   // time?
-  static bool disallow_allocation_failure_;
+  bool disallow_allocation_failure_;
+
+  HeapDebugUtils* debug_utils_;
 #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 intptr_t old_gen_promotion_limit_;
+  intptr_t 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 intptr_t old_gen_allocation_limit_;
+  intptr_t old_gen_allocation_limit_;
 
   // Limit on the amount of externally allocated memory allowed
   // between global GCs. If reached a global GC is forced.
-  static intptr_t external_allocation_limit_;
+  intptr_t external_allocation_limit_;
 
   // The amount of external memory registered through the API kept alive
   // by global handles
-  static int amount_of_external_allocated_memory_;
+  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_;
+  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_;
+  int old_gen_exhausted_;
 
-  static Object* roots_[kRootListLength];
+  Object* roots_[kRootListLength];
 
-  static Object* global_contexts_list_;
+  Object* global_contexts_list_;
 
   struct StringTypeTable {
     InstanceType type;
@@ -1258,7 +1363,7 @@
 
   // The special hidden symbol which is an empty string, but does not match
   // any string when looked up in properties.
-  static String* hidden_symbol_;
+  String* hidden_symbol_;
 
   // GC callback function, called before and after mark-compact GC.
   // Allocations in the callback function are disallowed.
@@ -1272,7 +1377,7 @@
     GCPrologueCallback callback;
     GCType gc_type;
   };
-  static List<GCPrologueCallbackPair> gc_prologue_callbacks_;
+  List<GCPrologueCallbackPair> gc_prologue_callbacks_;
 
   struct GCEpilogueCallbackPair {
     GCEpilogueCallbackPair(GCEpilogueCallback callback, GCType gc_type)
@@ -1284,91 +1389,91 @@
     GCEpilogueCallback callback;
     GCType gc_type;
   };
-  static List<GCEpilogueCallbackPair> gc_epilogue_callbacks_;
+  List<GCEpilogueCallbackPair> gc_epilogue_callbacks_;
 
-  static GCCallback global_gc_prologue_callback_;
-  static GCCallback global_gc_epilogue_callback_;
+  GCCallback global_gc_prologue_callback_;
+  GCCallback global_gc_epilogue_callback_;
 
   // Support for computing object sizes during GC.
-  static HeapObjectCallback gc_safe_size_of_old_object_;
+  HeapObjectCallback gc_safe_size_of_old_object_;
   static int GcSafeSizeOfOldObject(HeapObject* object);
   static int GcSafeSizeOfOldObjectWithEncodedMap(HeapObject* object);
 
   // Update the GC state. Called from the mark-compact collector.
-  static void MarkMapPointersAsEncoded(bool encoded) {
+  void MarkMapPointersAsEncoded(bool encoded) {
     gc_safe_size_of_old_object_ = encoded
         ? &GcSafeSizeOfOldObjectWithEncodedMap
         : &GcSafeSizeOfOldObject;
   }
 
   // Checks whether a global GC is necessary
-  static GarbageCollector SelectGarbageCollector(AllocationSpace space);
+  GarbageCollector SelectGarbageCollector(AllocationSpace space);
 
   // Performs garbage collection
   // Returns whether there is a chance another major GC could
   // collect more garbage.
-  static bool PerformGarbageCollection(GarbageCollector collector,
-                                       GCTracer* tracer);
+  bool PerformGarbageCollection(GarbageCollector collector,
+                                GCTracer* tracer);
+
+  static const intptr_t kMinimumPromotionLimit = 2 * MB;
+  static const intptr_t kMinimumAllocationLimit = 8 * MB;
+
+  inline void UpdateOldSpaceLimits();
 
   // 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).
-  MUST_USE_RESULT static inline MaybeObject* AllocateRawMap();
+  MUST_USE_RESULT inline MaybeObject* AllocateRawMap();
 
   // Allocate an uninitialized object in the global property cell space.
-  MUST_USE_RESULT static inline MaybeObject* AllocateRawCell();
+  MUST_USE_RESULT inline MaybeObject* AllocateRawCell();
 
   // Initializes a JSObject based on its map.
-  static void InitializeJSObjectFromMap(JSObject* obj,
-                                        FixedArray* properties,
-                                        Map* map);
+  void InitializeJSObjectFromMap(JSObject* obj,
+                                 FixedArray* properties,
+                                 Map* map);
 
-  static bool CreateInitialMaps();
-  static bool CreateInitialObjects();
+  bool CreateInitialMaps();
+  bool CreateInitialObjects();
 
   // These five Create*EntryStub functions are here and forced to not be inlined
   // because of a gcc-4.4 bug that assigns wrong vtable entries.
-  NO_INLINE(static void CreateCEntryStub());
-  NO_INLINE(static void CreateJSEntryStub());
-  NO_INLINE(static void CreateJSConstructEntryStub());
-  NO_INLINE(static void CreateRegExpCEntryStub());
-  NO_INLINE(static void CreateDirectCEntryStub());
+  NO_INLINE(void CreateJSEntryStub());
+  NO_INLINE(void CreateJSConstructEntryStub());
 
-  static void CreateFixedStubs();
+  void CreateFixedStubs();
 
-  MUST_USE_RESULT static MaybeObject* CreateOddball(const char* to_string,
-                                                    Object* to_number);
+  MaybeObject* CreateOddball(const char* to_string,
+                             Object* to_number,
+                             byte kind);
 
   // Allocate empty fixed array.
-  MUST_USE_RESULT static MaybeObject* AllocateEmptyFixedArray();
+  MUST_USE_RESULT MaybeObject* AllocateEmptyFixedArray();
 
   // Performs a minor collection in new generation.
-  static void Scavenge();
+  void Scavenge();
 
   static String* UpdateNewSpaceReferenceInExternalStringTableEntry(
+      Heap* heap,
       Object** pointer);
 
-  static Address DoScavenge(ObjectVisitor* scavenge_visitor,
-                            Address new_space_front);
+  Address DoScavenge(ObjectVisitor* scavenge_visitor, Address new_space_front);
 
   // Performs a major collection in the whole heap.
-  static void MarkCompact(GCTracer* tracer);
+  void MarkCompact(GCTracer* tracer);
 
   // Code to be run before and after mark-compact.
-  static void MarkCompactPrologue(bool is_compacting);
+  void MarkCompactPrologue(bool is_compacting);
 
   // Completely clear the Instanceof cache (to stop it keeping objects alive
   // around a GC).
-  static void CompletelyClearInstanceofCache() {
-    set_instanceof_cache_map(the_hole_value());
-    set_instanceof_cache_function(the_hole_value());
-  }
+  inline void CompletelyClearInstanceofCache();
 
 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
   // Record statistics before and after garbage collection.
-  static void ReportStatisticsBeforeGC();
-  static void ReportStatisticsAfterGC();
+  void ReportStatisticsBeforeGC();
+  void ReportStatisticsAfterGC();
 #endif
 
   // Slow part of scavenge object.
@@ -1380,39 +1485,39 @@
   // 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.
-  MUST_USE_RESULT static inline MaybeObject* InitializeFunction(
+  MUST_USE_RESULT inline MaybeObject* InitializeFunction(
       JSFunction* function,
       SharedFunctionInfo* shared,
       Object* prototype);
 
-  static GCTracer* tracer_;
+  GCTracer* tracer_;
 
 
   // Initializes the number to string cache based on the max semispace size.
-  MUST_USE_RESULT static MaybeObject* InitializeNumberStringCache();
+  MUST_USE_RESULT MaybeObject* InitializeNumberStringCache();
   // Flush the number to string cache.
-  static void FlushNumberStringCache();
+  void FlushNumberStringCache();
 
-  static void UpdateSurvivalRateTrend(int start_new_space_size);
+  void UpdateSurvivalRateTrend(int start_new_space_size);
 
   enum SurvivalRateTrend { INCREASING, STABLE, DECREASING, FLUCTUATING };
 
   static const int kYoungSurvivalRateThreshold = 90;
   static const int kYoungSurvivalRateAllowedDeviation = 15;
 
-  static int young_survivors_after_last_gc_;
-  static int high_survival_rate_period_length_;
-  static double survival_rate_;
-  static SurvivalRateTrend previous_survival_rate_trend_;
-  static SurvivalRateTrend survival_rate_trend_;
+  int young_survivors_after_last_gc_;
+  int high_survival_rate_period_length_;
+  double survival_rate_;
+  SurvivalRateTrend previous_survival_rate_trend_;
+  SurvivalRateTrend survival_rate_trend_;
 
-  static void set_survival_rate_trend(SurvivalRateTrend survival_rate_trend) {
+  void set_survival_rate_trend(SurvivalRateTrend survival_rate_trend) {
     ASSERT(survival_rate_trend != FLUCTUATING);
     previous_survival_rate_trend_ = survival_rate_trend_;
     survival_rate_trend_ = survival_rate_trend;
   }
 
-  static SurvivalRateTrend survival_rate_trend() {
+  SurvivalRateTrend survival_rate_trend() {
     if (survival_rate_trend_ == STABLE) {
       return STABLE;
     } else if (previous_survival_rate_trend_ == STABLE) {
@@ -1424,7 +1529,7 @@
     }
   }
 
-  static bool IsStableOrIncreasingSurvivalTrend() {
+  bool IsStableOrIncreasingSurvivalTrend() {
     switch (survival_rate_trend()) {
       case STABLE:
       case INCREASING:
@@ -1434,22 +1539,64 @@
     }
   }
 
-  static bool IsIncreasingSurvivalTrend() {
+  bool IsIncreasingSurvivalTrend() {
     return survival_rate_trend() == INCREASING;
   }
 
-  static bool IsHighSurvivalRate() {
+  bool IsHighSurvivalRate() {
     return high_survival_rate_period_length_ > 0;
   }
 
   static const int kInitialSymbolTableSize = 2048;
   static const int kInitialEvalCacheSize = 64;
 
+  // Maximum GC pause.
+  int max_gc_pause_;
+
+  // Maximum size of objects alive after GC.
+  intptr_t max_alive_after_gc_;
+
+  // Minimal interval between two subsequent collections.
+  int min_in_mutator_;
+
+  // Size of objects alive after last GC.
+  intptr_t alive_after_last_gc_;
+
+  double last_gc_end_timestamp_;
+
+  MarkCompactCollector mark_compact_collector_;
+
+  // This field contains the meaning of the WATERMARK_INVALIDATED flag.
+  // Instead of clearing this flag from all pages we just flip
+  // its meaning at the beginning of a scavenge.
+  intptr_t page_watermark_invalidated_mark_;
+
+  int number_idle_notifications_;
+  unsigned int last_idle_notification_gc_count_;
+  bool last_idle_notification_gc_count_init_;
+
+  // Shared state read by the scavenge collector and set by ScavengeObject.
+  PromotionQueue promotion_queue_;
+
+  // Flag is set when the heap has been configured.  The heap can be repeatedly
+  // configured through the API until it is setup.
+  bool configured_;
+
+  ExternalStringTable external_string_table_;
+
+  bool is_safe_to_read_maps_;
+
   friend class Factory;
+  friend class GCTracer;
   friend class DisallowAllocationFailure;
   friend class AlwaysAllocateScope;
   friend class LinearAllocationScope;
+  friend class Page;
+  friend class Isolate;
   friend class MarkCompactCollector;
+  friend class MapCompact;
+
+  DISALLOW_COPY_AND_ASSIGN(Heap);
 };
 
 
@@ -1493,13 +1640,13 @@
     // 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_++;
+    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);
+    HEAP->always_allocate_scope_depth_--;
+    ASSERT(HEAP->always_allocate_scope_depth_ == 0);
   }
 };
 
@@ -1507,12 +1654,12 @@
 class LinearAllocationScope {
  public:
   LinearAllocationScope() {
-    Heap::linear_allocation_scope_depth_++;
+    HEAP->linear_allocation_scope_depth_++;
   }
 
   ~LinearAllocationScope() {
-    Heap::linear_allocation_scope_depth_--;
-    ASSERT(Heap::linear_allocation_scope_depth_ >= 0);
+    HEAP->linear_allocation_scope_depth_--;
+    ASSERT(HEAP->linear_allocation_scope_depth_ >= 0);
   }
 };
 
@@ -1529,7 +1676,7 @@
     for (Object** current = start; current < end; current++) {
       if ((*current)->IsHeapObject()) {
         HeapObject* object = HeapObject::cast(*current);
-        ASSERT(Heap::Contains(object));
+        ASSERT(HEAP->Contains(object));
         ASSERT(object->map()->IsMap());
       }
     }
@@ -1547,10 +1694,10 @@
     for (Object** current = start; current < end; current++) {
       if ((*current)->IsHeapObject()) {
         HeapObject* object = HeapObject::cast(*current);
-        ASSERT(Heap::Contains(object));
+        ASSERT(HEAP->Contains(object));
         ASSERT(object->map()->IsMap());
-        if (Heap::InNewSpace(object)) {
-          ASSERT(Heap::InToSpace(object));
+        if (HEAP->InNewSpace(object)) {
+          ASSERT(HEAP->InToSpace(object));
           Address addr = reinterpret_cast<Address>(current);
           ASSERT(Page::FromAddress(addr)->IsRegionDirty(addr));
         }
@@ -1664,28 +1811,37 @@
 class KeyedLookupCache {
  public:
   // Lookup field offset for (map, name). If absent, -1 is returned.
-  static int Lookup(Map* map, String* name);
+  int Lookup(Map* map, String* name);
 
   // Update an element in the cache.
-  static void Update(Map* map, String* name, int field_offset);
+  void Update(Map* map, String* name, int field_offset);
 
   // Clear the cache.
-  static void Clear();
+  void Clear();
 
   static const int kLength = 64;
   static const int kCapacityMask = kLength - 1;
   static const int kMapHashShift = 2;
+  static const int kNotFound = -1;
 
  private:
+  KeyedLookupCache() {
+    for (int i = 0; i < kLength; ++i) {
+      keys_[i].map = NULL;
+      keys_[i].name = NULL;
+      field_offsets_[i] = kNotFound;
+    }
+  }
+
   static inline int Hash(Map* map, String* name);
 
   // Get the address of the keys and field_offsets arrays.  Used in
   // generated code to perform cache lookups.
-  static Address keys_address() {
+  Address keys_address() {
     return reinterpret_cast<Address>(&keys_);
   }
 
-  static Address field_offsets_address() {
+  Address field_offsets_address() {
     return reinterpret_cast<Address>(&field_offsets_);
   }
 
@@ -1693,10 +1849,13 @@
     Map* map;
     String* name;
   };
-  static Key keys_[kLength];
-  static int field_offsets_[kLength];
+
+  Key keys_[kLength];
+  int field_offsets_[kLength];
 
   friend class ExternalReference;
+  friend class Isolate;
+  DISALLOW_COPY_AND_ASSIGN(KeyedLookupCache);
 };
 
 
@@ -1708,7 +1867,7 @@
  public:
   // Lookup descriptor index for (map, name).
   // If absent, kAbsent is returned.
-  static int Lookup(DescriptorArray* array, String* name) {
+  int Lookup(DescriptorArray* array, String* name) {
     if (!StringShape(name).IsSymbol()) return kAbsent;
     int index = Hash(array, name);
     Key& key = keys_[index];
@@ -1717,7 +1876,7 @@
   }
 
   // Update an element in the cache.
-  static void Update(DescriptorArray* array, String* name, int result) {
+  void Update(DescriptorArray* array, String* name, int result) {
     ASSERT(result != kAbsent);
     if (StringShape(name).IsSymbol()) {
       int index = Hash(array, name);
@@ -1729,10 +1888,18 @@
   }
 
   // Clear the cache.
-  static void Clear();
+  void Clear();
 
   static const int kAbsent = -2;
  private:
+  DescriptorLookupCache() {
+    for (int i = 0; i < kLength; ++i) {
+      keys_[i].array = NULL;
+      keys_[i].name = NULL;
+      results_[i] = kAbsent;
+    }
+  }
+
   static int Hash(DescriptorArray* array, String* name) {
     // Uses only lower 32 bits if pointers are larger.
     uint32_t array_hash =
@@ -1748,55 +1915,11 @@
     String* name;
   };
 
-  static Key keys_[kLength];
-  static int results_[kLength];
-};
+  Key keys_[kLength];
+  int results_[kLength];
 
-
-// ----------------------------------------------------------------------------
-// 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_;
+  friend class Isolate;
+  DISALLOW_COPY_AND_ASSIGN(DescriptorLookupCache);
 };
 
 
@@ -1813,11 +1936,11 @@
 class DisallowAllocationFailure {
  public:
   DisallowAllocationFailure() {
-    old_state_ = Heap::disallow_allocation_failure_;
-    Heap::disallow_allocation_failure_ = true;
+    old_state_ = HEAP->disallow_allocation_failure_;
+    HEAP->disallow_allocation_failure_ = true;
   }
   ~DisallowAllocationFailure() {
-    Heap::disallow_allocation_failure_ = old_state_;
+    HEAP->disallow_allocation_failure_ = old_state_;
   }
  private:
   bool old_state_;
@@ -1826,11 +1949,11 @@
 class AssertNoAllocation {
  public:
   AssertNoAllocation() {
-    old_state_ = Heap::allow_allocation(false);
+    old_state_ = HEAP->allow_allocation(false);
   }
 
   ~AssertNoAllocation() {
-    Heap::allow_allocation(old_state_);
+    HEAP->allow_allocation(old_state_);
   }
 
  private:
@@ -1840,11 +1963,11 @@
 class DisableAssertNoAllocation {
  public:
   DisableAssertNoAllocation() {
-    old_state_ = Heap::allow_allocation(true);
+    old_state_ = HEAP->allow_allocation(true);
   }
 
   ~DisableAssertNoAllocation() {
-    Heap::allow_allocation(old_state_);
+    HEAP->allow_allocation(old_state_);
   }
 
  private:
@@ -1901,7 +2024,7 @@
     double start_time_;
   };
 
-  GCTracer();
+  explicit GCTracer(Heap* heap);
   ~GCTracer();
 
   // Sets the collector.
@@ -1927,22 +2050,13 @@
     promoted_objects_size_ += object_size;
   }
 
-  // Returns maximum GC pause.
-  static int get_max_gc_pause() { return max_gc_pause_; }
-
-  // Returns maximum size of objects alive after GC.
-  static intptr_t get_max_alive_after_gc() { return max_alive_after_gc_; }
-
-  // Returns minimal interval between two subsequent collections.
-  static int get_min_in_mutator() { return min_in_mutator_; }
-
  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;
+    return (static_cast<double>(HEAP->SizeOfObjects())) / MB;
   }
 
   double start_time_;  // Timestamp set in the constructor.
@@ -1991,19 +2105,7 @@
   // Size of objects promoted during the current collection.
   intptr_t promoted_objects_size_;
 
-  // Maximum GC pause.
-  static int max_gc_pause_;
-
-  // Maximum size of objects alive after GC.
-  static intptr_t max_alive_after_gc_;
-
-  // Minimal interval between two subsequent collections.
-  static int min_in_mutator_;
-
-  // Size of objects alive after last GC.
-  static intptr_t alive_after_last_gc_;
-
-  static double last_gc_end_timestamp_;
+  Heap* heap_;
 };
 
 
@@ -2013,131 +2115,71 @@
   static const int kTranscendentalTypeBits = 3;
   STATIC_ASSERT((1 << kTranscendentalTypeBits) >= kNumberOfCaches);
 
-  explicit TranscendentalCache(Type t);
-
   // Returns a heap number with f(input), where f is a math function specified
   // by the 'type' argument.
-  MUST_USE_RESULT static inline MaybeObject* Get(Type type, double input) {
-    TranscendentalCache* cache = caches_[type];
-    if (cache == NULL) {
-      caches_[type] = cache = new TranscendentalCache(type);
-    }
-    return cache->Get(input);
-  }
+  MUST_USE_RESULT inline MaybeObject* Get(Type type, double input);
 
   // The cache contains raw Object pointers.  This method disposes of
   // them before a garbage collection.
-  static void Clear();
+  void Clear();
 
  private:
-  MUST_USE_RESULT inline MaybeObject* Get(double input) {
-    Converter c;
-    c.dbl = input;
-    int hash = Hash(c);
-    Element e = elements_[hash];
-    if (e.in[0] == c.integers[0] &&
-        e.in[1] == c.integers[1]) {
-      ASSERT(e.output != NULL);
-      Counters::transcendental_cache_hit.Increment();
-      return e.output;
-    }
-    double answer = Calculate(input);
-    Counters::transcendental_cache_miss.Increment();
-    Object* heap_number;
-    { MaybeObject* maybe_heap_number = Heap::AllocateHeapNumber(answer);
-      if (!maybe_heap_number->ToObject(&heap_number)) return maybe_heap_number;
-    }
-    elements_[hash].in[0] = c.integers[0];
-    elements_[hash].in[1] = c.integers[1];
-    elements_[hash].output = heap_number;
-    return heap_number;
-  }
+  class SubCache {
+    static const int kCacheSize = 512;
 
-  inline double Calculate(double input) {
-    switch (type_) {
-      case ACOS:
-        return acos(input);
-      case ASIN:
-        return asin(input);
-      case ATAN:
-        return atan(input);
-      case COS:
-        return cos(input);
-      case EXP:
-        return exp(input);
-      case LOG:
-        return log(input);
-      case SIN:
-        return sin(input);
-      case TAN:
-        return tan(input);
-      default:
-        return 0.0;  // Never happens.
+    explicit SubCache(Type t);
+
+    MUST_USE_RESULT inline MaybeObject* Get(double input);
+
+    inline double Calculate(double input);
+
+    struct Element {
+      uint32_t in[2];
+      Object* output;
+    };
+
+    union Converter {
+      double dbl;
+      uint32_t integers[2];
+    };
+
+    inline static int Hash(const Converter& c) {
+      uint32_t hash = (c.integers[0] ^ c.integers[1]);
+      hash ^= static_cast<int32_t>(hash) >> 16;
+      hash ^= static_cast<int32_t>(hash) >> 8;
+      return (hash & (kCacheSize - 1));
     }
-  }
-  static const int kCacheSize = 512;
-  struct Element {
-    uint32_t in[2];
-    Object* output;
+
+    Element elements_[kCacheSize];
+    Type type_;
+    Isolate* isolate_;
+
+    // Allow access to the caches_ array as an ExternalReference.
+    friend class ExternalReference;
+    // Inline implementation of the cache.
+    friend class TranscendentalCacheStub;
+    // For evaluating value.
+    friend class TranscendentalCache;
+
+    DISALLOW_COPY_AND_ASSIGN(SubCache);
   };
-  union Converter {
-    double dbl;
-    uint32_t integers[2];
-  };
-  inline static int Hash(const Converter& c) {
-    uint32_t hash = (c.integers[0] ^ c.integers[1]);
-    hash ^= static_cast<int32_t>(hash) >> 16;
-    hash ^= static_cast<int32_t>(hash) >> 8;
-    return (hash & (kCacheSize - 1));
+
+  TranscendentalCache() {
+    for (int i = 0; i < kNumberOfCaches; ++i) caches_[i] = NULL;
   }
 
-  static Address cache_array_address() {
-    // Used to create an external reference.
-    return reinterpret_cast<Address>(caches_);
-  }
+  // Used to create an external reference.
+  inline Address cache_array_address();
 
+  // Instantiation
+  friend class Isolate;
+  // Inline implementation of the caching.
+  friend class TranscendentalCacheStub;
   // Allow access to the caches_ array as an ExternalReference.
   friend class ExternalReference;
-  // Inline implementation of the cache.
-  friend class TranscendentalCacheStub;
 
-  static TranscendentalCache* caches_[kNumberOfCaches];
-  Element elements_[kCacheSize];
-  Type type_;
-};
-
-
-// External strings table is a place where all external strings are
-// registered.  We need to keep track of such strings to properly
-// finalize them.
-class ExternalStringTable : public AllStatic {
- public:
-  // Registers an external string.
-  inline static void AddString(String* string);
-
-  inline static void Iterate(ObjectVisitor* v);
-
-  // Restores internal invariant and gets rid of collected strings.
-  // Must be called after each Iterate() that modified the strings.
-  static void CleanUp();
-
-  // Destroys all allocated memory.
-  static void TearDown();
-
- private:
-  friend class Heap;
-
-  inline static void Verify();
-
-  inline static void AddOldString(String* string);
-
-  // Notifies the table that only a prefix of the new list is valid.
-  inline static void ShrinkNewStrings(int position);
-
-  // To speed up scavenge collections new space string are kept
-  // separate from old space strings.
-  static List<Object*> new_space_strings_;
-  static List<Object*> old_space_strings_;
+  SubCache* caches_[kNumberOfCaches];
+  DISALLOW_COPY_AND_ASSIGN(TranscendentalCache);
 };
 
 
@@ -2214,4 +2256,6 @@
 
 } }  // namespace v8::internal
 
+#undef HEAP
+
 #endif  // V8_HEAP_H_
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index c2e5c8b..9bbe164 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -36,6 +36,8 @@
 #include "x64/lithium-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/lithium-arm.h"
+#elif V8_TARGET_ARCH_MIPS
+#include "mips/lithium-mips.h"
 #else
 #error Unsupported target architecture.
 #endif
@@ -414,10 +416,7 @@
 void HValue::RegisterUse(int index, HValue* new_value) {
   HValue* old_value = OperandAt(index);
   if (old_value == new_value) return;
-  if (old_value != NULL) {
-    ASSERT(old_value->uses_.Contains(this));
-    old_value->uses_.RemoveElement(this);
-  }
+  if (old_value != NULL) old_value->uses_.RemoveElement(this);
   if (new_value != NULL) {
     new_value->uses_.Add(this);
   }
@@ -933,6 +932,14 @@
 }
 
 
+bool HPhi::HasRealUses() {
+  for (int i = 0; i < uses()->length(); i++) {
+    if (!uses()->at(i)->IsPhi()) return true;
+  }
+  return false;
+}
+
+
 HValue* HPhi::GetRedundantReplacement() {
   HValue* candidate = NULL;
   int count = OperandCount();
@@ -1038,7 +1045,7 @@
 HConstant* HConstant::CopyToTruncatedInt32() const {
   if (!has_double_value_) return NULL;
   int32_t truncated = NumberToInt32(*handle_);
-  return new HConstant(Factory::NewNumberFromInt(truncated),
+  return new HConstant(FACTORY->NewNumberFromInt(truncated),
                        Representation::Integer32());
 }
 
@@ -1049,7 +1056,7 @@
 
 
 bool HArrayLiteral::IsCopyOnWrite() const {
-  return constant_elements()->map() == Heap::fixed_cow_array_map();
+  return constant_elements()->map() == HEAP->fixed_cow_array_map();
 }
 
 
@@ -1151,6 +1158,60 @@
 }
 
 
+HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* object,
+                                                       ZoneMapList* types,
+                                                       Handle<String> name)
+    : HUnaryOperation(object),
+      types_(Min(types->length(), kMaxLoadPolymorphism)),
+      name_(name),
+      need_generic_(false) {
+  set_representation(Representation::Tagged());
+  SetFlag(kDependsOnMaps);
+  for (int i = 0;
+       i < types->length() && types_.length() < kMaxLoadPolymorphism;
+       ++i) {
+    Handle<Map> map = types->at(i);
+    LookupResult lookup;
+    map->LookupInDescriptors(NULL, *name, &lookup);
+    if (lookup.IsProperty() && lookup.type() == FIELD) {
+      types_.Add(types->at(i));
+      int index = lookup.GetLocalFieldIndexFromMap(*map);
+      if (index < 0) {
+        SetFlag(kDependsOnInobjectFields);
+      } else {
+        SetFlag(kDependsOnBackingStoreFields);
+      }
+    }
+  }
+
+  if (types_.length() == types->length() && FLAG_deoptimize_uncommon_cases) {
+    SetFlag(kUseGVN);
+  } else {
+    SetAllSideEffects();
+    need_generic_ = true;
+  }
+}
+
+
+bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) {
+  HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value);
+  if (types_.length() != other->types()->length()) return false;
+  if (!name_.is_identical_to(other->name())) return false;
+  if (need_generic_ != other->need_generic_) return false;
+  for (int i = 0; i < types_.length(); i++) {
+    bool found = false;
+    for (int j = 0; j < types_.length(); j++) {
+      if (types_.at(j).is_identical_to(other->types()->at(i))) {
+        found = true;
+        break;
+      }
+    }
+    if (!found) return false;
+  }
+  return true;
+}
+
+
 void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
   object()->PrintNameTo(stream);
   stream->Add("[");
@@ -1167,8 +1228,36 @@
 }
 
 
-void HLoadPixelArrayElement::PrintDataTo(StringStream* stream) {
+void HLoadKeyedSpecializedArrayElement::PrintDataTo(
+    StringStream* stream) {
   external_pointer()->PrintNameTo(stream);
+  stream->Add(".");
+  switch (array_type()) {
+    case kExternalByteArray:
+      stream->Add("byte");
+      break;
+    case kExternalUnsignedByteArray:
+      stream->Add("u_byte");
+      break;
+    case kExternalShortArray:
+      stream->Add("short");
+      break;
+    case kExternalUnsignedShortArray:
+      stream->Add("u_short");
+      break;
+    case kExternalIntArray:
+      stream->Add("int");
+      break;
+    case kExternalUnsignedIntArray:
+      stream->Add("u_int");
+      break;
+    case kExternalFloatArray:
+      stream->Add("float");
+      break;
+    case kExternalPixelArray:
+      stream->Add("pixel");
+      break;
+  }
   stream->Add("[");
   key()->PrintNameTo(stream);
   stream->Add("]");
@@ -1216,8 +1305,36 @@
 }
 
 
-void HStorePixelArrayElement::PrintDataTo(StringStream* stream) {
+void HStoreKeyedSpecializedArrayElement::PrintDataTo(
+    StringStream* stream) {
   external_pointer()->PrintNameTo(stream);
+  stream->Add(".");
+  switch (array_type()) {
+    case kExternalByteArray:
+      stream->Add("byte");
+      break;
+    case kExternalUnsignedByteArray:
+      stream->Add("u_byte");
+      break;
+    case kExternalShortArray:
+      stream->Add("short");
+      break;
+    case kExternalUnsignedShortArray:
+      stream->Add("u_short");
+      break;
+    case kExternalIntArray:
+      stream->Add("int");
+      break;
+    case kExternalUnsignedIntArray:
+      stream->Add("u_int");
+      break;
+    case kExternalFloatArray:
+      stream->Add("float");
+      break;
+    case kExternalPixelArray:
+      stream->Add("pixel");
+      break;
+  }
   stream->Add("[");
   key()->PrintNameTo(stream);
   stream->Add("] = ");
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index cc75354..fed4b8b 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -29,7 +29,9 @@
 #define V8_HYDROGEN_INSTRUCTIONS_H_
 
 #include "v8.h"
+
 #include "code-stubs.h"
+#include "small-pointer-list.h"
 #include "string-stream.h"
 #include "zone.h"
 
@@ -91,6 +93,7 @@
   V(CheckNonSmi)                               \
   V(CheckPrototypeMaps)                        \
   V(CheckSmi)                                  \
+  V(ClassOfTest)                               \
   V(Compare)                                   \
   V(CompareJSObjectEq)                         \
   V(CompareMap)                                \
@@ -100,40 +103,40 @@
   V(Deoptimize)                                \
   V(Div)                                       \
   V(EnterInlined)                              \
+  V(ExternalArrayLength)                       \
   V(FixedArrayLength)                          \
   V(FunctionLiteral)                           \
   V(GetCachedArrayIndex)                       \
   V(GlobalObject)                              \
   V(GlobalReceiver)                            \
   V(Goto)                                      \
+  V(HasInstanceType)                           \
+  V(HasCachedArrayIndex)                       \
   V(InstanceOf)                                \
   V(InstanceOfKnownGlobal)                     \
   V(IsNull)                                    \
   V(IsObject)                                  \
   V(IsSmi)                                     \
   V(IsConstructCall)                           \
-  V(HasInstanceType)                           \
-  V(HasCachedArrayIndex)                       \
   V(JSArrayLength)                             \
-  V(ClassOfTest)                               \
   V(LeaveInlined)                              \
   V(LoadContextSlot)                           \
   V(LoadElements)                              \
+  V(LoadExternalArrayPointer)                  \
   V(LoadFunctionPrototype)                     \
   V(LoadGlobal)                                \
   V(LoadKeyedFastElement)                      \
   V(LoadKeyedGeneric)                          \
+  V(LoadKeyedSpecializedArrayElement)          \
   V(LoadNamedField)                            \
+  V(LoadNamedFieldPolymorphic)                 \
   V(LoadNamedGeneric)                          \
-  V(LoadPixelArrayElement)                     \
-  V(LoadPixelArrayExternalPointer)             \
   V(Mod)                                       \
   V(Mul)                                       \
   V(ObjectLiteral)                             \
   V(OsrEntry)                                  \
   V(OuterContext)                              \
   V(Parameter)                                 \
-  V(PixelArrayLength)                          \
   V(Power)                                     \
   V(PushArgument)                              \
   V(RegExpLiteral)                             \
@@ -146,15 +149,17 @@
   V(StoreContextSlot)                          \
   V(StoreGlobal)                               \
   V(StoreKeyedFastElement)                     \
-  V(StorePixelArrayElement)                    \
+  V(StoreKeyedSpecializedArrayElement)         \
   V(StoreKeyedGeneric)                         \
   V(StoreNamedField)                           \
   V(StoreNamedGeneric)                         \
   V(StringCharCodeAt)                          \
+  V(StringCharFromCode)                        \
   V(StringLength)                              \
   V(Sub)                                       \
   V(Test)                                      \
   V(Throw)                                     \
+  V(ToFastProperties)                          \
   V(Typeof)                                    \
   V(TypeofIs)                                  \
   V(UnaryMathOperation)                        \
@@ -166,7 +171,7 @@
   V(InobjectFields)                            \
   V(BackingStoreFields)                        \
   V(ArrayElements)                             \
-  V(PixelArrayElements)                        \
+  V(SpecializedArrayElements)                  \
   V(GlobalVars)                                \
   V(Maps)                                      \
   V(ArrayLengths)                              \
@@ -449,7 +454,6 @@
 
   HValue() : block_(NULL),
              id_(kNoNumber),
-             uses_(2),
              type_(HType::Tagged()),
              range_(NULL),
              flags_(0) {}
@@ -461,9 +465,9 @@
   int id() const { return id_; }
   void set_id(int id) { id_ = id; }
 
-  const ZoneList<HValue*>* uses() const { return &uses_; }
+  SmallPointerList<HValue>* uses() { return &uses_; }
 
-  virtual bool EmitAtUses() const { return false; }
+  virtual bool EmitAtUses() { return false; }
   Representation representation() const { return representation_; }
   void ChangeRepresentation(Representation r) {
     // Representation was already set and is allowed to be changed.
@@ -605,7 +609,7 @@
   int id_;
 
   Representation representation_;
-  ZoneList<HValue*> uses_;
+  SmallPointerList<HValue> uses_;
   HType type_;
   Range* range_;
   int flags_;
@@ -756,15 +760,33 @@
 };
 
 
-class HDeoptimize: public HTemplateControlInstruction<0> {
+class HDeoptimize: public HControlInstruction {
  public:
-  HDeoptimize() : HTemplateControlInstruction<0>(NULL, NULL) { }
+  explicit HDeoptimize(int environment_length)
+      : HControlInstruction(NULL, NULL),
+        values_(environment_length) { }
 
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::None();
   }
 
+  virtual int OperandCount() { return values_.length(); }
+  virtual HValue* OperandAt(int index) { return values_[index]; }
+
+  void AddEnvironmentValue(HValue* value) {
+    values_.Add(NULL);
+    SetOperandAt(values_.length() - 1, value);
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
+
+ protected:
+  virtual void InternalSetOperandAt(int index, HValue* value) {
+    values_[index] = value;
+  }
+
+ private:
+  ZoneList<HValue*> values_;
 };
 
 
@@ -1225,7 +1247,8 @@
   Handle<JSFunction> function() const { return function_; }
 
   bool IsApplyFunction() const {
-    return function_->code() == Builtins::builtin(Builtins::FunctionApply);
+    return function_->code() ==
+        Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply);
   }
 
   virtual void PrintDataTo(StringStream* stream);
@@ -1358,12 +1381,12 @@
 class HCallRuntime: public HCall<0> {
  public:
   HCallRuntime(Handle<String> name,
-               Runtime::Function* c_function,
+               const Runtime::Function* c_function,
                int argument_count)
       : HCall<0>(argument_count), c_function_(c_function), name_(name) { }
   virtual void PrintDataTo(StringStream* stream);
 
-  Runtime::Function* function() const { return c_function_; }
+  const Runtime::Function* function() const { return c_function_; }
   Handle<String> name() const { return name_; }
 
   virtual Representation RequiredInputRepresentation(int index) const {
@@ -1373,7 +1396,7 @@
   DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call_runtime")
 
  private:
-  Runtime::Function* c_function_;
+  const Runtime::Function* c_function_;
   Handle<String> name_;
 };
 
@@ -1385,8 +1408,9 @@
     // object. It is guaranteed to be 32 bit integer, but it can be
     // represented as either a smi or heap number.
     set_representation(Representation::Tagged());
-    SetFlag(kDependsOnArrayLengths);
     SetFlag(kUseGVN);
+    SetFlag(kDependsOnArrayLengths);
+    SetFlag(kDependsOnMaps);
   }
 
   virtual Representation RequiredInputRepresentation(int index) const {
@@ -1404,8 +1428,8 @@
  public:
   explicit HFixedArrayLength(HValue* value) : HUnaryOperation(value) {
     set_representation(Representation::Tagged());
-    SetFlag(kDependsOnArrayLengths);
     SetFlag(kUseGVN);
+    SetFlag(kDependsOnArrayLengths);
   }
 
   virtual Representation RequiredInputRepresentation(int index) const {
@@ -1419,9 +1443,9 @@
 };
 
 
-class HPixelArrayLength: public HUnaryOperation {
+class HExternalArrayLength: public HUnaryOperation {
  public:
-  explicit HPixelArrayLength(HValue* value) : HUnaryOperation(value) {
+  explicit HExternalArrayLength(HValue* value) : HUnaryOperation(value) {
     set_representation(Representation::Integer32());
     // The result of this instruction is idempotent as long as its inputs don't
     // change.  The length of a pixel array cannot change once set, so it's not
@@ -1433,7 +1457,7 @@
     return Representation::Tagged();
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel_array_length")
+  DECLARE_CONCRETE_INSTRUCTION(ExternalArrayLength, "external_array_length")
 
  protected:
   virtual bool DataEquals(HValue* other) { return true; }
@@ -1557,13 +1581,13 @@
 };
 
 
-class HLoadPixelArrayExternalPointer: public HUnaryOperation {
+class HLoadExternalArrayPointer: public HUnaryOperation {
  public:
-  explicit HLoadPixelArrayExternalPointer(HValue* value)
+  explicit HLoadExternalArrayPointer(HValue* value)
       : HUnaryOperation(value) {
     set_representation(Representation::External());
     // The result of this instruction is idempotent as long as its inputs don't
-    // change.  The external array of a pixel array elements object cannot
+    // change.  The external array of a specialized array elements object cannot
     // change once set, so it's no necessary to introduce any additional
     // dependencies on top of the inputs.
     SetFlag(kUseGVN);
@@ -1573,8 +1597,8 @@
     return Representation::Tagged();
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
-                               "load-pixel-array-external-pointer")
+  DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer,
+                               "load-external-array-pointer")
 
  protected:
   virtual bool DataEquals(HValue* other) { return true; }
@@ -1751,7 +1775,7 @@
   }
 
   virtual intptr_t Hashcode() {
-    ASSERT(!Heap::IsAllocationAllowed());
+    ASSERT(!HEAP->IsAllocationAllowed());
     intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
     hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
     return hash;
@@ -1800,7 +1824,8 @@
   explicit HPhi(int merged_index)
       : inputs_(2),
         merged_index_(merged_index),
-        phi_id_(-1) {
+        phi_id_(-1),
+        is_live_(false) {
     for (int i = 0; i < Representation::kNumRepresentations; i++) {
       non_phi_uses_[i] = 0;
       indirect_uses_[i] = 0;
@@ -1834,6 +1859,7 @@
   virtual HValue* OperandAt(int index) { return inputs_[index]; }
   HValue* GetRedundantReplacement();
   void AddInput(HValue* value);
+  bool HasRealUses();
 
   bool IsReceiver() { return merged_index_ == 0; }
 
@@ -1872,6 +1898,8 @@
     return indirect_uses_[Representation::kDouble];
   }
   int phi_id() { return phi_id_; }
+  bool is_live() { return is_live_; }
+  void set_is_live(bool b) { is_live_ = b; }
 
  protected:
   virtual void DeleteFromGraph();
@@ -1886,6 +1914,7 @@
   int non_phi_uses_[Representation::kNumRepresentations];
   int indirect_uses_[Representation::kNumRepresentations];
   int phi_id_;
+  bool is_live_;
 };
 
 
@@ -1910,13 +1939,13 @@
 
   Handle<Object> handle() const { return handle_; }
 
-  bool InOldSpace() const { return !Heap::InNewSpace(*handle_); }
+  bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); }
 
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::None();
   }
 
-  virtual bool EmitAtUses() const { return !representation().IsDouble(); }
+  virtual bool EmitAtUses() { return !representation().IsDouble(); }
   virtual void PrintDataTo(StringStream* stream);
   virtual HType CalculateInferredType();
   bool IsInteger() const { return handle_->IsSmi(); }
@@ -1935,7 +1964,7 @@
   bool HasStringValue() const { return handle_->IsString(); }
 
   virtual intptr_t Hashcode() {
-    ASSERT(!Heap::allow_allocation(false));
+    ASSERT(!HEAP->allow_allocation(false));
     return reinterpret_cast<intptr_t>(*handle());
   }
 
@@ -2191,7 +2220,7 @@
 
   void SetInputRepresentation(Representation r);
 
-  virtual bool EmitAtUses() const {
+  virtual bool EmitAtUses() {
     return !HasSideEffects() && (uses()->length() <= 1);
   }
 
@@ -2230,9 +2259,10 @@
       : HBinaryOperation(left, right) {
     set_representation(Representation::Tagged());
     SetFlag(kUseGVN);
+    SetFlag(kDependsOnMaps);
   }
 
-  virtual bool EmitAtUses() const {
+  virtual bool EmitAtUses() {
     return !HasSideEffects() && (uses()->length() <= 1);
   }
 
@@ -2255,7 +2285,7 @@
     SetFlag(kUseGVN);
   }
 
-  virtual bool EmitAtUses() const {
+  virtual bool EmitAtUses() {
     return !HasSideEffects() && (uses()->length() <= 1);
   }
 
@@ -2315,7 +2345,7 @@
     SetFlag(kUseGVN);
   }
 
-  virtual bool EmitAtUses() const {
+  virtual bool EmitAtUses() {
     return !HasSideEffects() && (uses()->length() <= 1);
   }
 
@@ -2437,7 +2467,7 @@
   HValue* left() { return OperandAt(1); }
   HValue* right() { return OperandAt(2); }
 
-  virtual bool EmitAtUses() const {
+  virtual bool EmitAtUses() {
     return !HasSideEffects() && (uses()->length() <= 1);
   }
 
@@ -2562,6 +2592,16 @@
     SetFlag(kCanBeDivByZero);
   }
 
+  bool HasPowerOf2Divisor() {
+    if (right()->IsConstant() &&
+        HConstant::cast(right())->HasInteger32Value()) {
+      int32_t value = HConstant::cast(right())->Integer32Value();
+      return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
+    }
+
+    return false;
+  }
+
   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
 
   DECLARE_CONCRETE_INSTRUCTION(Mod, "mod")
@@ -2784,7 +2824,7 @@
   virtual void PrintDataTo(StringStream* stream);
 
   virtual intptr_t Hashcode() {
-    ASSERT(!Heap::allow_allocation(false));
+    ASSERT(!HEAP->allow_allocation(false));
     return reinterpret_cast<intptr_t>(*cell_);
   }
 
@@ -2905,6 +2945,7 @@
         offset_(offset) {
     set_representation(Representation::Tagged());
     SetFlag(kUseGVN);
+    SetFlag(kDependsOnMaps);
     if (is_in_object) {
       SetFlag(kDependsOnInobjectFields);
     } else {
@@ -2935,6 +2976,37 @@
 };
 
 
+class HLoadNamedFieldPolymorphic: public HUnaryOperation {
+ public:
+  HLoadNamedFieldPolymorphic(HValue* object,
+                             ZoneMapList* types,
+                             Handle<String> name);
+
+  HValue* object() { return OperandAt(0); }
+  ZoneMapList* types() { return &types_; }
+  Handle<String> name() { return name_; }
+  bool need_generic() { return need_generic_; }
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic,
+                               "load_named_field_polymorphic")
+
+  static const int kMaxLoadPolymorphism = 4;
+
+ protected:
+  virtual bool DataEquals(HValue* value);
+
+ private:
+  ZoneMapList types_;
+  Handle<String> name_;
+  bool need_generic_;
+};
+
+
+
 class HLoadNamedGeneric: public HBinaryOperation {
  public:
   HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
@@ -3007,13 +3079,20 @@
 };
 
 
-class HLoadPixelArrayElement: public HBinaryOperation {
+class HLoadKeyedSpecializedArrayElement: public HBinaryOperation {
  public:
-  HLoadPixelArrayElement(HValue* external_elements, HValue* key)
-      : HBinaryOperation(external_elements, key) {
-    set_representation(Representation::Integer32());
-    SetFlag(kDependsOnPixelArrayElements);
-    // Native code could change the pixel array.
+  HLoadKeyedSpecializedArrayElement(HValue* external_elements,
+                                    HValue* key,
+                                    ExternalArrayType array_type)
+      : HBinaryOperation(external_elements, key),
+        array_type_(array_type) {
+    if (array_type == kExternalFloatArray) {
+      set_representation(Representation::Double());
+    } else {
+      set_representation(Representation::Integer32());
+    }
+    SetFlag(kDependsOnSpecializedArrayElements);
+    // Native code could change the specialized array.
     SetFlag(kDependsOnCalls);
     SetFlag(kUseGVN);
   }
@@ -3029,12 +3108,21 @@
 
   HValue* external_pointer() { return OperandAt(0); }
   HValue* key() { return OperandAt(1); }
+  ExternalArrayType array_type() const { return array_type_; }
 
-  DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayElement,
-                               "load_pixel_array_element")
+  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement,
+                               "load_keyed_specialized_array_element")
 
  protected:
-  virtual bool DataEquals(HValue* other) { return true; }
+  virtual bool DataEquals(HValue* other) {
+    if (!other->IsLoadKeyedSpecializedArrayElement()) return false;
+    HLoadKeyedSpecializedArrayElement* cast_other =
+        HLoadKeyedSpecializedArrayElement::cast(other);
+    return array_type_ == cast_other->array_type();
+  }
+
+ private:
+  ExternalArrayType array_type_;
 };
 
 
@@ -3169,10 +3257,14 @@
 };
 
 
-class HStorePixelArrayElement: public HTemplateInstruction<3> {
+class HStoreKeyedSpecializedArrayElement: public HTemplateInstruction<3> {
  public:
-  HStorePixelArrayElement(HValue* external_elements, HValue* key, HValue* val) {
-    SetFlag(kChangesPixelArrayElements);
+  HStoreKeyedSpecializedArrayElement(HValue* external_elements,
+                                     HValue* key,
+                                     HValue* val,
+                                     ExternalArrayType array_type)
+      : array_type_(array_type) {
+    SetFlag(kChangesSpecializedArrayElements);
     SetOperandAt(0, external_elements);
     SetOperandAt(1, key);
     SetOperandAt(2, val);
@@ -3184,16 +3276,23 @@
     if (index == 0) {
       return Representation::External();
     } else {
-      return Representation::Integer32();
+      if (index == 2 && array_type() == kExternalFloatArray) {
+        return Representation::Double();
+      } else {
+        return Representation::Integer32();
+      }
     }
   }
 
   HValue* external_pointer() { return OperandAt(0); }
   HValue* key() { return OperandAt(1); }
   HValue* value() { return OperandAt(2); }
+  ExternalArrayType array_type() const { return array_type_; }
 
-  DECLARE_CONCRETE_INSTRUCTION(StorePixelArrayElement,
-                               "store_pixel_array_element")
+  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement,
+                               "store_keyed_specialized_array_element")
+ private:
+  ExternalArrayType array_type_;
 };
 
 
@@ -3231,6 +3330,7 @@
       : HBinaryOperation(string, index) {
     set_representation(Representation::Integer32());
     SetFlag(kUseGVN);
+    SetFlag(kDependsOnMaps);
   }
 
   virtual Representation RequiredInputRepresentation(int index) const {
@@ -3253,11 +3353,29 @@
 };
 
 
+class HStringCharFromCode: public HUnaryOperation {
+ public:
+  explicit HStringCharFromCode(HValue* char_code) : HUnaryOperation(char_code) {
+    set_representation(Representation::Tagged());
+    SetFlag(kUseGVN);
+  }
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Integer32();
+  }
+
+  virtual bool DataEquals(HValue* other) { return true; }
+
+  DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string_char_from_code")
+};
+
+
 class HStringLength: public HUnaryOperation {
  public:
   explicit HStringLength(HValue* string) : HUnaryOperation(string) {
     set_representation(Representation::Tagged());
     SetFlag(kUseGVN);
+    SetFlag(kDependsOnMaps);
   }
 
   virtual Representation RequiredInputRepresentation(int index) const {
@@ -3330,10 +3448,12 @@
                  Handle<FixedArray> constant_properties,
                  bool fast_elements,
                  int literal_index,
-                 int depth)
+                 int depth,
+                 bool has_function)
       : HMaterializedLiteral<1>(literal_index, depth),
         constant_properties_(constant_properties),
-        fast_elements_(fast_elements) {
+        fast_elements_(fast_elements),
+        has_function_(has_function) {
     SetOperandAt(0, context);
   }
 
@@ -3342,6 +3462,7 @@
     return constant_properties_;
   }
   bool fast_elements() const { return fast_elements_; }
+  bool has_function() const { return has_function_; }
 
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
@@ -3352,6 +3473,7 @@
  private:
   Handle<FixedArray> constant_properties_;
   bool fast_elements_;
+  bool has_function_;
 };
 
 
@@ -3415,6 +3537,24 @@
 };
 
 
+class HToFastProperties: public HUnaryOperation {
+ public:
+  explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
+    // This instruction is not marked as having side effects, but
+    // changes the map of the input operand. Use it only when creating
+    // object literals.
+    ASSERT(value->IsObjectLiteral());
+    set_representation(Representation::Tagged());
+  }
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to_fast_properties")
+};
+
+
 class HValueOf: public HUnaryOperation {
  public:
   explicit HValueOf(HValue* value) : HUnaryOperation(value) {
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 158bfbe..2383192 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -25,6 +25,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include "v8.h"
 #include "hydrogen.h"
 
 #include "codegen.h"
@@ -42,6 +43,8 @@
 #include "x64/lithium-codegen-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/lithium-codegen-arm.h"
+#elif V8_TARGET_ARCH_MIPS
+#include "mips/lithium-codegen-mips.h"
 #else
 #error Unsupported target architecture.
 #endif
@@ -92,7 +95,7 @@
 void HBasicBlock::RemovePhi(HPhi* phi) {
   ASSERT(phi->block() == this);
   ASSERT(phis_.Contains(phi));
-  ASSERT(phi->HasNoUses());
+  ASSERT(phi->HasNoUses() || !phi->is_live());
   phi->ClearOperands();
   phis_.RemoveElement(phi);
   phi->SetBlock(NULL);
@@ -113,6 +116,21 @@
 }
 
 
+HDeoptimize* HBasicBlock::CreateDeoptimize() {
+  ASSERT(HasEnvironment());
+  HEnvironment* environment = last_environment();
+
+  HDeoptimize* instr = new HDeoptimize(environment->length());
+
+  for (int i = 0; i < environment->length(); i++) {
+    HValue* val = environment->values()->at(i);
+    instr->AddEnvironmentValue(val);
+  }
+
+  return instr;
+}
+
+
 HSimulate* HBasicBlock::CreateSimulate(int id) {
   ASSERT(HasEnvironment());
   HEnvironment* environment = last_environment();
@@ -150,6 +168,10 @@
 
 
 void HBasicBlock::Goto(HBasicBlock* block, bool include_stack_check) {
+  if (block->IsInlineReturnTarget()) {
+    AddInstruction(new HLeaveInlined);
+    last_environment_ = last_environment()->outer();
+  }
   AddSimulate(AstNode::kNoNumber);
   HGoto* instr = new HGoto(block);
   instr->set_include_stack_check(include_stack_check);
@@ -157,6 +179,18 @@
 }
 
 
+void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
+  ASSERT(target->IsInlineReturnTarget());
+  ASSERT(return_value != NULL);
+  AddInstruction(new HLeaveInlined);
+  last_environment_ = last_environment()->outer();
+  last_environment()->Push(return_value);
+  AddSimulate(AstNode::kNoNumber);
+  HGoto* instr = new HGoto(target);
+  Finish(instr);
+}
+
+
 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
   ASSERT(!HasEnvironment());
   ASSERT(first() == NULL);
@@ -286,6 +320,13 @@
   // Check that every block is finished.
   ASSERT(IsFinished());
   ASSERT(block_id() >= 0);
+
+  // Check that the incoming edges are in edge split form.
+  if (predecessors_.length() > 1) {
+    for (int i = 0; i < predecessors_.length(); ++i) {
+      ASSERT(predecessors_[i]->end()->SecondSuccessor() == NULL);
+    }
+  }
 }
 #endif
 
@@ -473,12 +514,12 @@
 
 
 HConstant* HGraph::GetConstantTrue() {
-  return GetConstant(&constant_true_, Heap::true_value());
+  return GetConstant(&constant_true_, isolate()->heap()->true_value());
 }
 
 
 HConstant* HGraph::GetConstantFalse() {
-  return GetConstant(&constant_false_, Heap::false_value());
+  return GetConstant(&constant_false_, isolate()->heap()->false_value());
 }
 
 
@@ -534,13 +575,16 @@
 
 
 HGraph::HGraph(CompilationInfo* info)
-    : HSubgraph(this),
+    : isolate_(info->isolate()),
       next_block_id_(0),
+      entry_block_(NULL),
       blocks_(8),
       values_(16),
       phi_list_(NULL) {
   start_environment_ = new HEnvironment(NULL, info->scope(), info->closure());
   start_environment_->set_ast_id(info->function()->id());
+  entry_block_ = CreateBasicBlock();
+  entry_block_->SetInitialEnvironment(start_environment_);
 }
 
 
@@ -615,7 +659,7 @@
   HBasicBlock* start = blocks_[0];
   Postorder(start, &visited, &reverse_result, NULL);
 
-  blocks_.Clear();
+  blocks_.Rewind(0);
   int index = 0;
   for (int i = reverse_result.length() - 1; i >= 0; --i) {
     HBasicBlock* b = reverse_result[i];
@@ -680,8 +724,7 @@
 
 
 void HGraph::EliminateRedundantPhis() {
-  HPhase phase("Phi elimination", this);
-  ZoneList<HValue*> uses_to_replace(2);
+  HPhase phase("Redundant phi elimination", this);
 
   // Worklist of phis that can potentially be eliminated. Initialized
   // with all phi nodes. When elimination of a phi node modifies
@@ -704,26 +747,57 @@
     if (value != NULL) {
       // Iterate through uses finding the ones that should be
       // replaced.
-      const ZoneList<HValue*>* uses = phi->uses();
-      for (int i = 0; i < uses->length(); ++i) {
-        HValue* use = uses->at(i);
-        if (!use->block()->IsStartBlock()) {
-          uses_to_replace.Add(use);
+      SmallPointerList<HValue>* uses = phi->uses();
+      while (!uses->is_empty()) {
+        HValue* use = uses->RemoveLast();
+        if (use != NULL) {
+          phi->ReplaceAtUse(use, value);
+          if (use->IsPhi()) worklist.Add(HPhi::cast(use));
         }
       }
-      // Replace the uses and add phis modified to the work list.
-      for (int i = 0; i < uses_to_replace.length(); ++i) {
-        HValue* use = uses_to_replace[i];
-        phi->ReplaceAtUse(use, value);
-        if (use->IsPhi()) worklist.Add(HPhi::cast(use));
-      }
-      uses_to_replace.Rewind(0);
       block->RemovePhi(phi);
-    } else if (FLAG_eliminate_dead_phis && phi->HasNoUses() &&
-               !phi->IsReceiver()) {
+    }
+  }
+}
+
+
+void HGraph::EliminateUnreachablePhis() {
+  HPhase phase("Unreachable phi elimination", this);
+
+  // Initialize worklist.
+  ZoneList<HPhi*> phi_list(blocks_.length());
+  ZoneList<HPhi*> worklist(blocks_.length());
+  for (int i = 0; i < blocks_.length(); ++i) {
+    for (int j = 0; j < blocks_[i]->phis()->length(); j++) {
+      HPhi* phi = blocks_[i]->phis()->at(j);
+      phi_list.Add(phi);
       // We can't eliminate phis in the receiver position in the environment
       // because in case of throwing an error we need this value to
       // construct a stack trace.
+      if (phi->HasRealUses() || phi->IsReceiver())  {
+        phi->set_is_live(true);
+        worklist.Add(phi);
+      }
+    }
+  }
+
+  // Iteratively mark live phis.
+  while (!worklist.is_empty()) {
+    HPhi* phi = worklist.RemoveLast();
+    for (int i = 0; i < phi->OperandCount(); i++) {
+      HValue* operand = phi->OperandAt(i);
+      if (operand->IsPhi() && !HPhi::cast(operand)->is_live()) {
+        HPhi::cast(operand)->set_is_live(true);
+        worklist.Add(HPhi::cast(operand));
+      }
+    }
+  }
+
+  // Remove unreachable phis.
+  for (int i = 0; i < phi_list.length(); i++) {
+    HPhi* phi = phi_list[i];
+    if (!phi->is_live()) {
+      HBasicBlock* block = phi->block();
       block->RemovePhi(phi);
       block->RecordDeletedPhi(phi->merged_index());
     }
@@ -732,11 +806,11 @@
 
 
 bool HGraph::CollectPhis() {
-  const ZoneList<HBasicBlock*>* blocks = graph_->blocks();
-  phi_list_ = new ZoneList<HPhi*>(blocks->length());
-  for (int i = 0; i < blocks->length(); ++i) {
-    for (int j = 0; j < blocks->at(i)->phis()->length(); j++) {
-      HPhi* phi = blocks->at(i)->phis()->at(j);
+  int block_count = blocks_.length();
+  phi_list_ = new ZoneList<HPhi*>(block_count);
+  for (int i = 0; i < block_count; ++i) {
+    for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
+      HPhi* phi = blocks_[i]->phis()->at(j);
       phi_list_->Add(phi);
       // We don't support phi uses of arguments for now.
       if (phi->CheckFlag(HValue::kIsArguments)) return false;
@@ -845,13 +919,15 @@
   ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
   if (test->value()->IsCompare()) {
     HCompare* compare = HCompare::cast(test->value());
-    Token::Value op = compare->token();
-    if (test->SecondSuccessor() == dest) {
-      op = Token::NegateCompareOp(op);
+    if (compare->GetInputRepresentation().IsInteger32()) {
+      Token::Value op = compare->token();
+      if (test->SecondSuccessor() == dest) {
+        op = Token::NegateCompareOp(op);
+      }
+      Token::Value inverted_op = Token::InvertCompareOp(op);
+      InferControlFlowRange(op, compare->left(), compare->right());
+      InferControlFlowRange(inverted_op, compare->right(), compare->left());
     }
-    Token::Value inverted_op = Token::InvertCompareOp(op);
-    InferControlFlowRange(op, compare->left(), compare->right());
-    InferControlFlowRange(inverted_op, compare->right(), compare->left());
   }
 }
 
@@ -954,8 +1030,8 @@
       lists_size_(other->lists_size_),
       count_(other->count_),
       present_flags_(other->present_flags_),
-      array_(Zone::NewArray<HValueMapListElement>(other->array_size_)),
-      lists_(Zone::NewArray<HValueMapListElement>(other->lists_size_)),
+      array_(ZONE->NewArray<HValueMapListElement>(other->array_size_)),
+      lists_(ZONE->NewArray<HValueMapListElement>(other->lists_size_)),
       free_list_head_(other->free_list_head_) {
   memcpy(array_, other->array_, array_size_ * sizeof(HValueMapListElement));
   memcpy(lists_, other->lists_, lists_size_ * sizeof(HValueMapListElement));
@@ -1034,7 +1110,7 @@
   }
 
   HValueMapListElement* new_array =
-      Zone::NewArray<HValueMapListElement>(new_size);
+      ZONE->NewArray<HValueMapListElement>(new_size);
   memset(new_array, 0, sizeof(HValueMapListElement) * new_size);
 
   HValueMapListElement* old_array = array_;
@@ -1072,7 +1148,7 @@
   ASSERT(new_size > lists_size_);
 
   HValueMapListElement* new_lists =
-      Zone::NewArray<HValueMapListElement>(new_size);
+      ZONE->NewArray<HValueMapListElement>(new_size);
   memset(new_lists, 0, sizeof(HValueMapListElement) * new_size);
 
   HValueMapListElement* old_lists = lists_;
@@ -1175,12 +1251,12 @@
         info_(info),
         block_side_effects_(graph_->blocks()->length()),
         loop_side_effects_(graph_->blocks()->length()) {
-    ASSERT(Heap::allow_allocation(false));
+    ASSERT(info->isolate()->heap()->allow_allocation(false));
     block_side_effects_.AddBlock(0, graph_->blocks()->length());
     loop_side_effects_.AddBlock(0, graph_->blocks()->length());
   }
   ~HGlobalValueNumberer() {
-    ASSERT(!Heap::allow_allocation(true));
+    ASSERT(!info_->isolate()->heap()->allow_allocation(true));
   }
 
   void Analyze();
@@ -1722,15 +1798,18 @@
 }
 
 
-void HGraph::InsertRepresentationChanges(HValue* current) {
+void HGraph::InsertRepresentationChangesForValue(
+    HValue* current,
+    ZoneList<HValue*>* to_convert,
+    ZoneList<Representation>* to_convert_reps) {
   Representation r = current->representation();
   if (r.IsNone()) return;
   if (current->uses()->length() == 0) return;
 
   // Collect the representation changes in a sorted list.  This allows
   // us to avoid duplicate changes without searching the list.
-  ZoneList<HValue*> to_convert(2);
-  ZoneList<Representation> to_convert_reps(2);
+  ASSERT(to_convert->is_empty());
+  ASSERT(to_convert_reps->is_empty());
   for (int i = 0; i < current->uses()->length(); ++i) {
     HValue* use = current->uses()->at(i);
     // The occurrences index means the index within the operand array of "use"
@@ -1750,10 +1829,10 @@
     Representation req = use->RequiredInputRepresentation(operand_index);
     if (req.IsNone() || req.Equals(r)) continue;
     int index = 0;
-    while (to_convert.length() > index &&
-           CompareConversionUses(to_convert[index],
+    while (index < to_convert->length() &&
+           CompareConversionUses(to_convert->at(index),
                                  use,
-                                 to_convert_reps[index],
+                                 to_convert_reps->at(index),
                                  req) < 0) {
       ++index;
     }
@@ -1763,13 +1842,13 @@
              current->id(),
              use->id());
     }
-    to_convert.InsertAt(index, use);
-    to_convert_reps.InsertAt(index, req);
+    to_convert->InsertAt(index, use);
+    to_convert_reps->InsertAt(index, req);
   }
 
-  for (int i = 0; i < to_convert.length(); ++i) {
-    HValue* use = to_convert[i];
-    Representation r_to = to_convert_reps[i];
+  for (int i = 0; i < to_convert->length(); ++i) {
+    HValue* use = to_convert->at(i);
+    Representation r_to = to_convert_reps->at(i);
     InsertRepresentationChangeForUse(current, use, r_to);
   }
 
@@ -1777,6 +1856,8 @@
     ASSERT(current->IsConstant());
     current->Delete();
   }
+  to_convert->Rewind(0);
+  to_convert_reps->Rewind(0);
 }
 
 
@@ -1812,17 +1893,19 @@
     }
   }
 
+  ZoneList<HValue*> value_list(4);
+  ZoneList<Representation> rep_list(4);
   for (int i = 0; i < blocks_.length(); ++i) {
     // Process phi instructions first.
     for (int j = 0; j < blocks_[i]->phis()->length(); j++) {
       HPhi* phi = blocks_[i]->phis()->at(j);
-      InsertRepresentationChanges(phi);
+      InsertRepresentationChangesForValue(phi, &value_list, &rep_list);
     }
 
     // Process normal instructions.
     HInstruction* current = blocks_[i]->first();
     while (current != NULL) {
-      InsertRepresentationChanges(current);
+      InsertRepresentationChangesForValue(current, &value_list, &rep_list);
       current = current->next();
     }
   }
@@ -1979,20 +2062,8 @@
   HTest* test = new HTest(value, empty_true, empty_false);
   builder->current_block()->Finish(test);
 
-  HValue* const no_return_value = NULL;
-  HBasicBlock* true_target = if_true();
-  if (true_target->IsInlineReturnTarget()) {
-    empty_true->AddLeaveInlined(no_return_value, true_target);
-  } else {
-    empty_true->Goto(true_target);
-  }
-
-  HBasicBlock* false_target = if_false();
-  if (false_target->IsInlineReturnTarget()) {
-    empty_false->AddLeaveInlined(no_return_value, false_target);
-  } else {
-    empty_false->Goto(false_target);
-  }
+  empty_true->Goto(if_true(), false);
+  empty_false->Goto(if_false(), false);
   builder->set_current_block(NULL);
 }
 
@@ -2032,36 +2103,6 @@
   } while (false)
 
 
-// 'thing' could be an expression, statement, or list of statements.
-#define ADD_TO_SUBGRAPH(graph, thing)       \
-  do {                                      \
-    AddToSubgraph(graph, thing);            \
-    if (HasStackOverflow()) return;         \
-  } while (false)
-
-
-class HGraphBuilder::SubgraphScope BASE_EMBEDDED {
- public:
-  SubgraphScope(HGraphBuilder* builder, HSubgraph* new_subgraph)
-      : builder_(builder) {
-    old_subgraph_ = builder_->current_subgraph_;
-    subgraph_ = new_subgraph;
-    builder_->current_subgraph_ = subgraph_;
-  }
-
-  ~SubgraphScope() {
-    builder_->current_subgraph_ = old_subgraph_;
-  }
-
-  HSubgraph* subgraph() const { return subgraph_; }
-
- private:
-  HGraphBuilder* builder_;
-  HSubgraph* old_subgraph_;
-  HSubgraph* subgraph_;
-};
-
-
 void HGraphBuilder::Bailout(const char* reason) {
   if (FLAG_trace_bailout) {
     SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
@@ -2113,13 +2154,12 @@
 
 
 HGraph* HGraphBuilder::CreateGraph() {
-  ASSERT(subgraph() == NULL);
   graph_ = new HGraph(info());
+  if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info());
 
   {
     HPhase phase("Block building");
-    graph()->Initialize(CreateBasicBlock(graph()->start_environment()));
-    current_subgraph_ = graph();
+    current_block_ = graph()->entry_block();
 
     Scope* scope = info()->scope();
     if (scope->HasIllegalRedeclaration()) {
@@ -2163,6 +2203,7 @@
   graph()->OrderBlocks();
   graph()->AssignDominators();
   graph()->EliminateRedundantPhis();
+  if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis();
   if (!graph()->CollectPhis()) {
     Bailout("Phi-use of arguments object");
     return NULL;
@@ -2196,25 +2237,6 @@
 }
 
 
-void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Statement* stmt) {
-  SubgraphScope scope(this, graph);
-  Visit(stmt);
-}
-
-
-void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Expression* expr) {
-  SubgraphScope scope(this, graph);
-  VisitForValue(expr);
-}
-
-
-void HGraphBuilder::AddToSubgraph(HSubgraph* graph,
-                                  ZoneList<Statement*>* stmts) {
-  SubgraphScope scope(this, graph);
-  VisitStatements(stmts);
-}
-
-
 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
   ASSERT(current_block() != NULL);
   current_block()->AddInstruction(instr);
@@ -2259,8 +2281,8 @@
   // We don't yet handle the function name for named function expressions.
   if (scope->function() != NULL) BAILOUT("named function expression");
 
-  HConstant* undefined_constant =
-      new HConstant(Factory::undefined_value(), Representation::Tagged());
+  HConstant* undefined_constant = new HConstant(
+      isolate()->factory()->undefined_value(), Representation::Tagged());
   AddInstruction(undefined_constant);
   graph_->set_undefined_constant(undefined_constant);
 
@@ -2281,14 +2303,17 @@
   // not have declarations).
   if (scope->arguments() != NULL) {
     if (!scope->arguments()->IsStackAllocated() ||
-        !scope->arguments_shadow()->IsStackAllocated()) {
+        (scope->arguments_shadow() != NULL &&
+        !scope->arguments_shadow()->IsStackAllocated())) {
       BAILOUT("context-allocated arguments");
     }
     HArgumentsObject* object = new HArgumentsObject;
     AddInstruction(object);
     graph()->SetArgumentsObject(object);
     environment()->Bind(scope->arguments(), object);
-    environment()->Bind(scope->arguments_shadow(), object);
+    if (scope->arguments_shadow() != NULL) {
+      environment()->Bind(scope->arguments_shadow(), object);
+    }
   }
 }
 
@@ -2308,33 +2333,6 @@
 }
 
 
-HSubgraph* HGraphBuilder::CreateInlinedSubgraph(HEnvironment* outer,
-                                                Handle<JSFunction> target,
-                                                FunctionLiteral* function) {
-  HConstant* undefined = graph()->GetConstantUndefined();
-  HEnvironment* inner =
-      outer->CopyForInlining(target, function, true, undefined);
-  HSubgraph* subgraph = new HSubgraph(graph());
-  subgraph->Initialize(CreateBasicBlock(inner));
-  return subgraph;
-}
-
-
-HSubgraph* HGraphBuilder::CreateEmptySubgraph() {
-  HSubgraph* subgraph = new HSubgraph(graph());
-  subgraph->Initialize(graph()->CreateBasicBlock());
-  return subgraph;
-}
-
-
-HSubgraph* HGraphBuilder::CreateBranchSubgraph(HEnvironment* env) {
-  HSubgraph* subgraph = new HSubgraph(graph());
-  HEnvironment* new_env = env->Copy();
-  subgraph->Initialize(CreateBasicBlock(new_env));
-  return subgraph;
-}
-
-
 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
   HBasicBlock* header = graph()->CreateBasicBlock();
   HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
@@ -2458,20 +2456,16 @@
       VisitForControl(stmt->expression(),
                       test->if_true(),
                       test->if_false());
+    } else if (context->IsEffect()) {
+      VISIT_FOR_EFFECT(stmt->expression());
+      current_block()->Goto(function_return(), false);
     } else {
-      HValue* return_value = NULL;
-      if (context->IsEffect()) {
-        VISIT_FOR_EFFECT(stmt->expression());
-        return_value = graph()->GetConstantUndefined();
-      } else {
-        ASSERT(context->IsValue());
-        VISIT_FOR_VALUE(stmt->expression());
-        return_value = environment()->Pop();
-      }
-      current_block()->AddLeaveInlined(return_value,
-                                       function_return());
-      set_current_block(NULL);
+      ASSERT(context->IsValue());
+      VISIT_FOR_VALUE(stmt->expression());
+      HValue* return_value = environment()->Pop();
+      current_block()->AddLeaveInlined(return_value, function_return());
     }
+    set_current_block(NULL);
   }
 }
 
@@ -2486,173 +2480,122 @@
 }
 
 
-HCompare* HGraphBuilder::BuildSwitchCompare(HSubgraph* subgraph,
-                                            HValue* switch_value,
-                                            CaseClause* clause) {
-  AddToSubgraph(subgraph, clause->label());
-  if (HasStackOverflow()) return NULL;
-  HValue* clause_value = subgraph->exit_block()->last_environment()->Pop();
-  HCompare* compare = new HCompare(switch_value,
-                                   clause_value,
-                                   Token::EQ_STRICT);
-  compare->SetInputRepresentation(Representation::Integer32());
-  subgraph->exit_block()->AddInstruction(compare);
-  return compare;
-}
-
-
 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
-  VISIT_FOR_VALUE(stmt->tag());
-  // TODO(3168478): simulate added for tag should be enough.
-  AddSimulate(stmt->EntryId());
-  HValue* switch_value = Pop();
-
+  // We only optimize switch statements with smi-literal smi comparisons,
+  // with a bounded number of clauses.
+  const int kCaseClauseLimit = 128;
   ZoneList<CaseClause*>* clauses = stmt->cases();
-  int num_clauses = clauses->length();
-  if (num_clauses == 0) return;
-  if (num_clauses > 128) BAILOUT("SwitchStatement: too many clauses");
+  int clause_count = clauses->length();
+  if (clause_count > kCaseClauseLimit) {
+    BAILOUT("SwitchStatement: too many clauses");
+  }
 
-  int num_smi_clauses = num_clauses;
-  for (int i = 0; i < num_clauses; i++) {
+  VISIT_FOR_VALUE(stmt->tag());
+  AddSimulate(stmt->EntryId());
+  HValue* tag_value = Pop();
+  HBasicBlock* first_test_block = current_block();
+
+  // 1. Build all the tests, with dangling true branches.  Unconditionally
+  // deoptimize if we encounter a non-smi comparison.
+  for (int i = 0; i < clause_count; ++i) {
     CaseClause* clause = clauses->at(i);
     if (clause->is_default()) continue;
-    clause->RecordTypeFeedback(oracle());
-    if (!clause->IsSmiCompare()) {
-      if (i == 0) BAILOUT("SwitchStatement: no smi compares");
-      // We will deoptimize if the first non-smi compare is reached.
-      num_smi_clauses = i;
-      break;
-    }
     if (!clause->label()->IsSmiLiteral()) {
       BAILOUT("SwitchStatement: non-literal switch label");
     }
-  }
 
-  // The single exit block of the whole switch statement.
-  HBasicBlock* single_exit_block = graph_->CreateBasicBlock();
-
-  // Build a series of empty subgraphs for the comparisons.
-  // The default clause does not have a comparison subgraph.
-  ZoneList<HSubgraph*> compare_graphs(num_smi_clauses);
-  for (int i = 0; i < num_smi_clauses; i++) {
-    if (clauses->at(i)->is_default()) {
-      compare_graphs.Add(NULL);
-    } else {
-      compare_graphs.Add(CreateEmptySubgraph());
-    }
-  }
-
-  HSubgraph* prev_graph = current_subgraph_;
-  HCompare* prev_compare_inst = NULL;
-  for (int i = 0; i < num_smi_clauses; i++) {
-    CaseClause* clause = clauses->at(i);
-    if (clause->is_default()) continue;
-
-    // Finish the previous graph by connecting it to the current.
-    HSubgraph* subgraph = compare_graphs.at(i);
-    if (prev_compare_inst == NULL) {
-      ASSERT(prev_graph == current_subgraph_);
-      prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block()));
-    } else {
-      HBasicBlock* empty = graph()->CreateBasicBlock();
-      prev_graph->exit_block()->Finish(new HTest(prev_compare_inst,
-                                                 empty,
-                                                 subgraph->entry_block()));
+    // Unconditionally deoptimize on the first non-smi compare.
+    clause->RecordTypeFeedback(oracle());
+    if (!clause->IsSmiCompare()) {
+      current_block()->FinishExitWithDeoptimization();
+      set_current_block(NULL);
+      break;
     }
 
-    // Build instructions for current subgraph.
-    ASSERT(clause->IsSmiCompare());
-    prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause);
-    if (HasStackOverflow()) return;
-
-    prev_graph = subgraph;
+    // Otherwise generate a compare and branch.
+    VISIT_FOR_VALUE(clause->label());
+    HValue* label_value = Pop();
+    HCompare* compare = new HCompare(tag_value, label_value, Token::EQ_STRICT);
+    compare->SetInputRepresentation(Representation::Integer32());
+    ASSERT(!compare->HasSideEffects());
+    AddInstruction(compare);
+    HBasicBlock* body_block = graph()->CreateBasicBlock();
+    HBasicBlock* next_test_block = graph()->CreateBasicBlock();
+    HTest* branch = new HTest(compare, body_block, next_test_block);
+    current_block()->Finish(branch);
+    set_current_block(next_test_block);
   }
 
-  // Finish last comparison if there was at least one comparison.
-  // last_false_block is the (empty) false-block of the last comparison. If
-  // there are no comparisons at all (a single default clause), it is just
-  // the last block of the current subgraph.
-  HBasicBlock* last_false_block = current_block();
-  if (prev_graph != current_subgraph_) {
-    last_false_block = graph()->CreateBasicBlock();
-    HBasicBlock* empty = graph()->CreateBasicBlock();
-    prev_graph->exit_block()->Finish(new HTest(prev_compare_inst,
-                                               empty,
-                                               last_false_block));
-  }
+  // Save the current block to use for the default or to join with the
+  // exit.  This block is NULL if we deoptimized.
+  HBasicBlock* last_block = current_block();
 
-  // If we have a non-smi compare clause, we deoptimize after trying
-  // all the previous compares.
-  if (num_smi_clauses < num_clauses) {
-    last_false_block->Finish(new HDeoptimize);
-  }
+  // 2. Loop over the clauses and the linked list of tests in lockstep,
+  // translating the clause bodies.
+  HBasicBlock* curr_test_block = first_test_block;
+  HBasicBlock* fall_through_block = NULL;
+  BreakAndContinueInfo break_info(stmt);
+  { BreakAndContinueScope push(&break_info, this);
+    for (int i = 0; i < clause_count; ++i) {
+      CaseClause* clause = clauses->at(i);
 
-  // Build statement blocks, connect them to their comparison block and
-  // to the previous statement block, if there is a fall-through.
-  HSubgraph* previous_subgraph = NULL;
-  for (int i = 0; i < num_clauses; i++) {
-    CaseClause* clause = clauses->at(i);
-    // Subgraph for the statements of the clause is only created when
-    // it's reachable either from the corresponding compare or as a
-    // fall-through from previous statements.
-    HSubgraph* subgraph = NULL;
+      // Identify the block where normal (non-fall-through) control flow
+      // goes to.
+      HBasicBlock* normal_block = NULL;
+      if (clause->is_default() && last_block != NULL) {
+        normal_block = last_block;
+        last_block = NULL;  // Cleared to indicate we've handled it.
+      } else if (!curr_test_block->end()->IsDeoptimize()) {
+        normal_block = curr_test_block->end()->FirstSuccessor();
+        curr_test_block = curr_test_block->end()->SecondSuccessor();
+      }
 
-    if (i < num_smi_clauses) {
-      if (clause->is_default()) {
-        if (!last_false_block->IsFinished()) {
-          // Default clause: Connect it to the last false block.
-          subgraph = CreateEmptySubgraph();
-          last_false_block->Finish(new HGoto(subgraph->entry_block()));
+      // Identify a block to emit the body into.
+      if (normal_block == NULL) {
+        if (fall_through_block == NULL) {
+          // (a) Unreachable.
+          if (clause->is_default()) {
+            continue;  // Might still be reachable clause bodies.
+          } else {
+            break;
+          }
+        } else {
+          // (b) Reachable only as fall through.
+          set_current_block(fall_through_block);
         }
+      } else if (fall_through_block == NULL) {
+        // (c) Reachable only normally.
+        set_current_block(normal_block);
       } else {
-        ASSERT(clause->IsSmiCompare());
-        // Connect with the corresponding comparison.
-        subgraph = CreateEmptySubgraph();
-        HBasicBlock* empty =
-            compare_graphs.at(i)->exit_block()->end()->FirstSuccessor();
-        empty->Finish(new HGoto(subgraph->entry_block()));
+        // (d) Reachable both ways.
+        HBasicBlock* join = CreateJoin(fall_through_block,
+                                       normal_block,
+                                       clause->EntryId());
+        set_current_block(join);
       }
-    }
 
-    // Check for fall-through from previous statement block.
-    if (previous_subgraph != NULL && previous_subgraph->exit_block() != NULL) {
-      if (subgraph == NULL) subgraph = CreateEmptySubgraph();
-      previous_subgraph->exit_block()->
-          Finish(new HGoto(subgraph->entry_block()));
+      VisitStatements(clause->statements());
+      CHECK_BAILOUT;
+      fall_through_block = current_block();
     }
-
-    if (subgraph != NULL) {
-      BreakAndContinueInfo break_info(stmt);
-      { BreakAndContinueScope push(&break_info, this);
-        ADD_TO_SUBGRAPH(subgraph, clause->statements());
-      }
-      if (break_info.break_block() != NULL) {
-        break_info.break_block()->SetJoinId(stmt->ExitId());
-        break_info.break_block()->Finish(new HGoto(single_exit_block));
-      }
-    }
-
-    previous_subgraph = subgraph;
   }
 
-  // If the last statement block has a fall-through, connect it to the
-  // single exit block.
-  if (previous_subgraph != NULL && previous_subgraph->exit_block() != NULL) {
-    previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block));
-  }
-
-  // If there is no default clause finish the last comparison's false target.
-  if (!last_false_block->IsFinished()) {
-    last_false_block->Finish(new HGoto(single_exit_block));
-  }
-
-  if (single_exit_block->HasPredecessor()) {
-    set_current_block(single_exit_block);
+  // Create an up-to-3-way join.  Use the break block if it exists since
+  // it's already a join block.
+  HBasicBlock* break_block = break_info.break_block();
+  if (break_block == NULL) {
+    set_current_block(CreateJoin(fall_through_block,
+                                 last_block,
+                                 stmt->ExitId()));
   } else {
-    set_current_block(NULL);
+    if (fall_through_block != NULL) fall_through_block->Goto(break_block);
+    if (last_block != NULL) last_block->Goto(break_block);
+    break_block->SetJoinId(stmt->ExitId());
+    set_current_block(break_block);
   }
 }
 
+
 bool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
   return statement->OsrEntryId() == info()->osr_ast_id();
 }
@@ -2847,18 +2790,22 @@
   cond_true->SetJoinId(expr->ThenId());
   cond_false->SetJoinId(expr->ElseId());
 
-  // TOOD(kmillikin): Visit the subexpressions in the same AST context as
-  // the whole expression.
+  // Visit the true and false subexpressions in the same AST context as the
+  // whole expression.
   set_current_block(cond_true);
-  VISIT_FOR_VALUE(expr->then_expression());
+  Visit(expr->then_expression());
+  CHECK_BAILOUT;
   HBasicBlock* other = current_block();
 
   set_current_block(cond_false);
-  VISIT_FOR_VALUE(expr->else_expression());
+  Visit(expr->else_expression());
+  CHECK_BAILOUT;
 
-  HBasicBlock* join = CreateJoin(other, current_block(), expr->id());
-  set_current_block(join);
-  ast_context()->ReturnValue(Pop());
+  if (!ast_context()->IsTest()) {
+    HBasicBlock* join = CreateJoin(other, current_block(), expr->id());
+    set_current_block(join);
+    if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
+  }
 }
 
 
@@ -2960,7 +2907,8 @@
                                                 expr->constant_properties(),
                                                 expr->fast_elements(),
                                                 expr->literal_index(),
-                                                expr->depth()));
+                                                expr->depth(),
+                                                expr->has_function()));
   // The object is expected in the bailout environment during computation
   // of the property values and is the value of the entire expression.
   PushAndAdd(literal);
@@ -3001,7 +2949,19 @@
       default: UNREACHABLE();
     }
   }
-  ast_context()->ReturnValue(Pop());
+
+  if (expr->has_function()) {
+    // Return the result of the transformation to fast properties
+    // instead of the original since this operation changes the map
+    // of the object. This makes sure that the original object won't
+    // be used by other optimized code before it is transformed
+    // (e.g. because of code motion).
+    HToFastProperties* result = new HToFastProperties(Pop());
+    AddInstruction(result);
+    ast_context()->ReturnValue(result);
+  } else {
+    ast_context()->ReturnValue(Pop());
+  }
 }
 
 
@@ -3049,55 +3009,6 @@
 }
 
 
-HBasicBlock* HGraphBuilder::BuildTypeSwitch(HValue* receiver,
-                                            ZoneMapList* maps,
-                                            ZoneList<HSubgraph*>* body_graphs,
-                                            HSubgraph* default_graph,
-                                            int join_id) {
-  ASSERT(maps->length() == body_graphs->length());
-  HBasicBlock* join_block = graph()->CreateBasicBlock();
-  AddInstruction(new HCheckNonSmi(receiver));
-
-  for (int i = 0; i < maps->length(); ++i) {
-    // Build the branches, connect all the target subgraphs to the join
-    // block.  Use the default as a target of the last branch.
-    HSubgraph* if_true = body_graphs->at(i);
-    HSubgraph* if_false = (i == maps->length() - 1)
-        ? default_graph
-        : CreateBranchSubgraph(environment());
-    HCompareMap* compare =
-        new HCompareMap(receiver,
-                        maps->at(i),
-                        if_true->entry_block(),
-                        if_false->entry_block());
-    current_block()->Finish(compare);
-
-    if (if_true->exit_block() != NULL) {
-      // In an effect context the value of the type switch is not needed.
-      // There is no need to merge it at the join block only to discard it.
-      if (ast_context()->IsEffect()) {
-        if_true->exit_block()->last_environment()->Drop(1);
-      }
-      if_true->exit_block()->Goto(join_block);
-    }
-
-    set_current_block(if_false->exit_block());
-  }
-
-  // Connect the default if necessary.
-  if (current_block() != NULL) {
-    if (ast_context()->IsEffect()) {
-      environment()->Drop(1);
-    }
-    current_block()->Goto(join_block);
-  }
-
-  if (join_block->predecessors()->is_empty()) return NULL;
-  join_block->SetJoinId(join_id);
-  return join_block;
-}
-
-
 // Sets the lookup result and returns true if the store can be inlined.
 static bool ComputeStoredField(Handle<Map> type,
                                Handle<String> name,
@@ -3229,7 +3140,7 @@
   // know about and do not want to handle ones we've never seen.  Otherwise
   // use a generic IC.
   if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
-    current_block()->FinishExit(new HDeoptimize);
+    current_block()->FinishExitWithDeoptimization();
   } else {
     HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
     instr->set_position(expr->position());
@@ -3306,11 +3217,14 @@
 
     if (expr->IsMonomorphic()) {
       Handle<Map> receiver_type(expr->GetMonomorphicReceiverType());
-      // An object has either fast elements or pixel array elements, but never
-      // both. Pixel array maps that are assigned to pixel array elements are
-      // always created with the fast elements flag cleared.
-      if (receiver_type->has_pixel_array_elements()) {
-        instr = BuildStoreKeyedPixelArrayElement(object, key, value, expr);
+      // An object has either fast elements or external array elements, but
+      // never both. Pixel array maps that are assigned to pixel array elements
+      // are always created with the fast elements flag cleared.
+      if (receiver_type->has_external_array_elements()) {
+        instr = BuildStoreKeyedSpecializedArrayElement(object,
+                                                       key,
+                                                       value,
+                                                       expr);
       } else if (receiver_type->has_fast_elements()) {
         instr = BuildStoreKeyedFastElement(object, key, value, expr);
       }
@@ -3534,69 +3448,6 @@
 }
 
 
-void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
-                                                    HValue* object,
-                                                    ZoneMapList* types,
-                                                    Handle<String> name) {
-  // TODO(ager): We should recognize when the prototype chains for different
-  // maps are identical. In that case we can avoid repeatedly generating the
-  // same prototype map checks.
-  int count = 0;
-  HBasicBlock* join = NULL;
-  for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
-    Handle<Map> map = types->at(i);
-    LookupResult lookup;
-    map->LookupInDescriptors(NULL, *name, &lookup);
-    if (lookup.IsProperty() && lookup.type() == FIELD) {
-      if (count == 0) {
-        AddInstruction(new HCheckNonSmi(object));  // Only needed once.
-        join = graph()->CreateBasicBlock();
-      }
-      ++count;
-      HBasicBlock* if_true = graph()->CreateBasicBlock();
-      HBasicBlock* if_false = graph()->CreateBasicBlock();
-      HCompareMap* compare = new HCompareMap(object, map, if_true, if_false);
-      current_block()->Finish(compare);
-
-      set_current_block(if_true);
-      HLoadNamedField* instr =
-          BuildLoadNamedField(object, expr, map, &lookup, false);
-      instr->set_position(expr->position());
-      instr->ClearFlag(HValue::kUseGVN);
-      AddInstruction(instr);
-      if (!ast_context()->IsEffect()) Push(instr);
-      current_block()->Goto(join);
-
-      set_current_block(if_false);
-    }
-  }
-
-  // Finish up.  Unconditionally deoptimize if we've handled all the maps we
-  // know about and do not want to handle ones we've never seen.  Otherwise
-  // use a generic IC.
-  if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
-    current_block()->FinishExit(new HDeoptimize);
-  } else {
-    HInstruction* instr = BuildLoadNamedGeneric(object, expr);
-    instr->set_position(expr->position());
-
-    if (join != NULL) {
-      AddInstruction(instr);
-      if (!ast_context()->IsEffect()) Push(instr);
-      current_block()->Goto(join);
-    } else {
-      ast_context()->ReturnInstruction(instr, expr->id());
-      return;
-    }
-  }
-
-  ASSERT(join != NULL);
-  join->SetJoinId(expr->id());
-  set_current_block(join);
-  if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
-}
-
-
 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
                                                     Property* expr,
                                                     Handle<Map> type,
@@ -3686,25 +3537,28 @@
 }
 
 
-HInstruction* HGraphBuilder::BuildLoadKeyedPixelArrayElement(HValue* object,
-                                                             HValue* key,
-                                                             Property* expr) {
+HInstruction* HGraphBuilder::BuildLoadKeyedSpecializedArrayElement(
+    HValue* object,
+    HValue* key,
+    Property* expr) {
   ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic());
   AddInstruction(new HCheckNonSmi(object));
   Handle<Map> map = expr->GetMonomorphicReceiverType();
   ASSERT(!map->has_fast_elements());
-  ASSERT(map->has_pixel_array_elements());
+  ASSERT(map->has_external_array_elements());
   AddInstruction(new HCheckMap(object, map));
   HLoadElements* elements = new HLoadElements(object);
   AddInstruction(elements);
-  HInstruction* length = new HPixelArrayLength(elements);
+  HInstruction* length = new HExternalArrayLength(elements);
   AddInstruction(length);
   AddInstruction(new HBoundsCheck(key, length));
-  HLoadPixelArrayExternalPointer* external_elements =
-      new HLoadPixelArrayExternalPointer(elements);
+  HLoadExternalArrayPointer* external_elements =
+      new HLoadExternalArrayPointer(elements);
   AddInstruction(external_elements);
-  HLoadPixelArrayElement* pixel_array_value =
-      new HLoadPixelArrayElement(external_elements, key);
+  HLoadKeyedSpecializedArrayElement* pixel_array_value =
+      new HLoadKeyedSpecializedArrayElement(external_elements,
+                                            key,
+                                            expr->GetExternalArrayType());
   return pixel_array_value;
 }
 
@@ -3728,7 +3582,8 @@
   ASSERT(map->has_fast_elements());
   AddInstruction(new HCheckMap(object, map));
   HInstruction* elements = AddInstruction(new HLoadElements(object));
-  AddInstruction(new HCheckMap(elements, Factory::fixed_array_map()));
+  AddInstruction(new HCheckMap(elements,
+                               isolate()->factory()->fixed_array_map()));
   bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
   HInstruction* length = NULL;
   if (is_array) {
@@ -3741,25 +3596,29 @@
 }
 
 
-HInstruction* HGraphBuilder::BuildStoreKeyedPixelArrayElement(
+HInstruction* HGraphBuilder::BuildStoreKeyedSpecializedArrayElement(
     HValue* object,
     HValue* key,
     HValue* val,
-    Expression* expr) {
+    Assignment* expr) {
   ASSERT(expr->IsMonomorphic());
   AddInstruction(new HCheckNonSmi(object));
   Handle<Map> map = expr->GetMonomorphicReceiverType();
   ASSERT(!map->has_fast_elements());
-  ASSERT(map->has_pixel_array_elements());
+  ASSERT(map->has_external_array_elements());
   AddInstruction(new HCheckMap(object, map));
   HLoadElements* elements = new HLoadElements(object);
   AddInstruction(elements);
-  HInstruction* length = AddInstruction(new HPixelArrayLength(elements));
+  HInstruction* length = AddInstruction(new HExternalArrayLength(elements));
   AddInstruction(new HBoundsCheck(key, length));
-  HLoadPixelArrayExternalPointer* external_elements =
-      new HLoadPixelArrayExternalPointer(elements);
+  HLoadExternalArrayPointer* external_elements =
+      new HLoadExternalArrayPointer(elements);
   AddInstruction(external_elements);
-  return new HStorePixelArrayElement(external_elements, key, val);
+  return new HStoreKeyedSpecializedArrayElement(
+      external_elements,
+      key,
+      val,
+      expr->GetExternalArrayType());
 }
 
 
@@ -3815,6 +3674,13 @@
                                           FIRST_STRING_TYPE,
                                           LAST_STRING_TYPE));
     instr = new HStringLength(string);
+  } else if (expr->IsStringAccess()) {
+    VISIT_FOR_VALUE(expr->key());
+    HValue* index = Pop();
+    HValue* string = Pop();
+    HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
+    AddInstruction(char_code);
+    instr = new HStringCharFromCode(char_code);
 
   } else if (expr->IsFunctionPrototype()) {
     HValue* function = Pop();
@@ -3829,9 +3695,8 @@
     if (expr->IsMonomorphic()) {
       instr = BuildLoadNamed(obj, expr, types->first(), name);
     } else if (types != NULL && types->length() > 1) {
-      HandlePolymorphicLoadNamedField(expr, obj, types, name);
-      return;
-
+      AddInstruction(new HCheckNonSmi(obj));
+      instr = new HLoadNamedFieldPolymorphic(obj, types, name);
     } else {
       instr = BuildLoadNamedGeneric(obj, expr);
     }
@@ -3847,8 +3712,8 @@
       // An object has either fast elements or pixel array elements, but never
       // both. Pixel array maps that are assigned to pixel array elements are
       // always created with the fast elements flag cleared.
-      if (receiver_type->has_pixel_array_elements()) {
-        instr = BuildLoadKeyedPixelArrayElement(obj, key, expr);
+      if (receiver_type->has_external_array_elements()) {
+        instr = BuildLoadKeyedSpecializedArrayElement(obj, key, expr);
       } else if (receiver_type->has_fast_elements()) {
         instr = BuildLoadKeyedFastElement(obj, key, expr);
       }
@@ -3885,22 +3750,26 @@
                                                HValue* receiver,
                                                ZoneMapList* types,
                                                Handle<String> name) {
-  int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
-  int number_of_types = Min(types->length(), kMaxCallPolymorphism);
-  ZoneMapList maps(number_of_types);
-  ZoneList<HSubgraph*> subgraphs(number_of_types);
-  bool needs_generic = (types->length() > kMaxCallPolymorphism);
-
-  // Build subgraphs for each of the specific maps.
-  //
   // TODO(ager): We should recognize when the prototype chains for different
   // maps are identical. In that case we can avoid repeatedly generating the
   // same prototype map checks.
-  for (int i = 0; i < number_of_types; ++i) {
+  int argument_count = expr->arguments()->length() + 1;  // Includes receiver.
+  int count = 0;
+  HBasicBlock* join = NULL;
+  for (int i = 0; i < types->length() && count < kMaxCallPolymorphism; ++i) {
     Handle<Map> map = types->at(i);
     if (expr->ComputeTarget(map, name)) {
-      HSubgraph* subgraph = CreateBranchSubgraph(environment());
-      SubgraphScope scope(this, subgraph);
+      if (count == 0) {
+        AddInstruction(new HCheckNonSmi(receiver));  // Only needed once.
+        join = graph()->CreateBasicBlock();
+      }
+      ++count;
+      HBasicBlock* if_true = graph()->CreateBasicBlock();
+      HBasicBlock* if_false = graph()->CreateBasicBlock();
+      HCompareMap* compare = new HCompareMap(receiver, map, if_true, if_false);
+      current_block()->Finish(compare);
+
+      set_current_block(if_true);
       AddCheckConstantFunction(expr, receiver, map, false);
       if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
         PrintF("Trying to inline the polymorphic call to %s\n",
@@ -3911,53 +3780,49 @@
         // during hydrogen processing.
         CHECK_BAILOUT;
         HCallConstantFunction* call =
-          new HCallConstantFunction(expr->target(), argument_count);
+            new HCallConstantFunction(expr->target(), argument_count);
         call->set_position(expr->position());
         PreProcessCall(call);
-        PushAndAdd(call);
+        AddInstruction(call);
+        if (!ast_context()->IsEffect()) Push(call);
       }
-      maps.Add(map);
-      subgraphs.Add(subgraph);
-    } else {
-      needs_generic = true;
+
+      if (current_block() != NULL) current_block()->Goto(join);
+      set_current_block(if_false);
     }
   }
 
-  // If we couldn't compute the target for any of the maps just perform an
-  // IC call.
-  if (maps.length() == 0) {
+  // Finish up.  Unconditionally deoptimize if we've handled all the maps we
+  // know about and do not want to handle ones we've never seen.  Otherwise
+  // use a generic IC.
+  if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
+    current_block()->FinishExitWithDeoptimization();
+  } else {
     HContext* context = new HContext;
     AddInstruction(context);
     HCallNamed* call = new HCallNamed(context, name, argument_count);
     call->set_position(expr->position());
     PreProcessCall(call);
-    ast_context()->ReturnInstruction(call, expr->id());
-  } else {
-    // Build subgraph for generic call through IC.
-    HSubgraph* default_graph = CreateBranchSubgraph(environment());
-    { SubgraphScope scope(this, default_graph);
-      if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
-        default_graph->exit_block()->FinishExit(new HDeoptimize());
-        default_graph->set_exit_block(NULL);
-      } else {
-        HContext* context = new HContext;
-        AddInstruction(context);
-        HCallNamed* call = new HCallNamed(context, name, argument_count);
-        call->set_position(expr->position());
-        PreProcessCall(call);
-        PushAndAdd(call);
-      }
-    }
 
-    HBasicBlock* new_exit_block =
-        BuildTypeSwitch(receiver, &maps, &subgraphs, default_graph, expr->id());
-    set_current_block(new_exit_block);
-    // In an effect context, we did not materialized the value in the
-    // predecessor environments so there's no need to handle it here.
-    if (new_exit_block != NULL && !ast_context()->IsEffect()) {
-      ast_context()->ReturnValue(Pop());
+    if (join != NULL) {
+      AddInstruction(call);
+      if (!ast_context()->IsEffect()) Push(call);
+      current_block()->Goto(join);
+    } else {
+      ast_context()->ReturnInstruction(call, expr->id());
+      return;
     }
   }
+
+  // We assume that control flow is always live after an expression.  So
+  // even without predecessors to the join block, we set it as the exit
+  // block and continue by adding instructions there.
+  ASSERT(join != NULL);
+  set_current_block(join);
+  if (join->HasPredecessor()) {
+    join->SetJoinId(expr->id());
+    if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
+  }
 }
 
 
@@ -4030,7 +3895,7 @@
   CompilationInfo target_info(target);
   if (!ParserApi::Parse(&target_info) ||
       !Scope::Analyze(&target_info)) {
-    if (Top::has_pending_exception()) {
+    if (target_info.isolate()->has_pending_exception()) {
       // Parse or scope error, never optimize this function.
       SetStackOverflow();
       target->shared()->set_optimization_disabled(true);
@@ -4103,9 +3968,16 @@
       Handle<Context>(target->context()->global_context()));
   FunctionState target_state(this, &target_info, &target_oracle);
 
-  HSubgraph* body = CreateInlinedSubgraph(env, target, function);
-  body->exit_block()->AddInstruction(new HEnterInlined(target, function));
-  AddToSubgraph(body, function->body());
+  HConstant* undefined = graph()->GetConstantUndefined();
+  HEnvironment* inner_env =
+      environment()->CopyForInlining(target, function, true, undefined);
+  HBasicBlock* body_entry = CreateBasicBlock(inner_env);
+  current_block()->Goto(body_entry);
+
+  body_entry->SetJoinId(expr->ReturnId());
+  set_current_block(body_entry);
+  AddInstruction(new HEnterInlined(target, function));
+  VisitStatements(function->body());
   if (HasStackOverflow()) {
     // Bail out if the inline function did, as we cannot residualize a call
     // instead.
@@ -4118,13 +3990,17 @@
 
   TraceInline(target, NULL);
 
-  if (body->exit_block() != NULL) {
+  if (current_block() != NULL) {
     // Add a return of undefined if control can fall off the body.  In a
     // test context, undefined is false.
-    HValue* return_value = graph()->GetConstantUndefined();
     if (inlined_test_context() == NULL) {
       ASSERT(function_return() != NULL);
-      body->exit_block()->AddLeaveInlined(return_value, function_return());
+      ASSERT(call_context()->IsEffect() || call_context()->IsValue());
+      if (call_context()->IsEffect()) {
+        current_block()->Goto(function_return(), false);
+      } else {
+        current_block()->AddLeaveInlined(undefined, function_return());
+      }
     } else {
       // The graph builder assumes control can reach both branches of a
       // test, so we materialize the undefined value and test it rather than
@@ -4133,24 +4009,14 @@
       // TODO(3168478): refactor to avoid this.
       HBasicBlock* empty_true = graph()->CreateBasicBlock();
       HBasicBlock* empty_false = graph()->CreateBasicBlock();
-      HTest* test = new HTest(return_value, empty_true, empty_false);
-      body->exit_block()->Finish(test);
+      HTest* test = new HTest(undefined, empty_true, empty_false);
+      current_block()->Finish(test);
 
-      HValue* const no_return_value = NULL;
-      empty_true->AddLeaveInlined(no_return_value,
-                                  inlined_test_context()->if_true());
-      empty_false->AddLeaveInlined(no_return_value,
-                                   inlined_test_context()->if_false());
+      empty_true->Goto(inlined_test_context()->if_true(), false);
+      empty_false->Goto(inlined_test_context()->if_false(), false);
     }
-    body->set_exit_block(NULL);
   }
 
-  // Record the environment at the inlined function call.
-  AddSimulate(expr->ReturnId());
-
-  // Jump to the function entry (without re-recording the environment).
-  current_block()->Finish(new HGoto(body->entry_block()));
-
   // Fix up the function exits.
   if (inlined_test_context() != NULL) {
     HBasicBlock* if_true = inlined_test_context()->if_true();
@@ -4162,20 +4028,10 @@
     ClearInlinedTestContext();
 
     // Forward to the real test context.
-    HValue* const no_return_value = NULL;
     HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
-    if (true_target->IsInlineReturnTarget()) {
-      if_true->AddLeaveInlined(no_return_value, true_target);
-    } else {
-      if_true->Goto(true_target);
-    }
-
     HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
-    if (false_target->IsInlineReturnTarget()) {
-      if_false->AddLeaveInlined(no_return_value, false_target);
-    } else {
-      if_false->Goto(false_target);
-    }
+    if_true->Goto(true_target, false);
+    if_false->Goto(false_target, false);
 
     // TODO(kmillikin): Come up with a better way to handle this. It is too
     // subtle. NULL here indicates that the enclosing context has no control
@@ -4191,16 +4047,6 @@
 }
 
 
-void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
-  ASSERT(target->IsInlineReturnTarget());
-  AddInstruction(new HLeaveInlined);
-  HEnvironment* outer = last_environment()->outer();
-  if (return_value != NULL) outer->Push(return_value);
-  UpdateEnvironment(outer);
-  Goto(target);
-}
-
-
 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
                                              HValue* receiver,
                                              Handle<Map> receiver_map,
@@ -4212,6 +4058,7 @@
   int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
   switch (id) {
     case kStringCharCodeAt:
+    case kStringCharAt:
       if (argument_count == 2 && check_type == STRING_CHECK) {
         HValue* index = Pop();
         HValue* string = Pop();
@@ -4219,7 +4066,13 @@
         AddInstruction(new HCheckPrototypeMaps(
             oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK),
             expr->holder()));
-        HStringCharCodeAt* result = BuildStringCharCodeAt(string, index);
+        HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
+        if (id == kStringCharCodeAt) {
+          ast_context()->ReturnInstruction(char_code, expr->id());
+          return true;
+        }
+        AddInstruction(char_code);
+        HStringCharFromCode* result = new HStringCharFromCode(char_code);
         ast_context()->ReturnInstruction(result, expr->id());
         return true;
       }
@@ -4331,13 +4184,6 @@
 }
 
 
-static bool HasCustomCallGenerator(Handle<JSFunction> function) {
-  SharedFunctionInfo* info = function->shared();
-  return info->HasBuiltinFunctionId() &&
-      CallStubCompiler::HasCustomCallGenerator(info->builtin_function_id());
-}
-
-
 void HGraphBuilder::VisitCall(Call* expr) {
   Expression* callee = expr->expression();
   int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
@@ -4395,11 +4241,11 @@
         return;
       }
 
-      if (HasCustomCallGenerator(expr->target()) ||
+      if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) ||
           expr->check_type() != RECEIVER_MAP_CHECK) {
         // When the target has a custom call IC generator, use the IC,
-        // because it is likely to generate better code. Also use the
-        // IC when a primitive receiver check is required.
+        // because it is likely to generate better code.  Also use the IC
+        // when a primitive receiver check is required.
         HContext* context = new HContext;
         AddInstruction(context);
         call = PreProcessCall(new HCallNamed(context, name, argument_count));
@@ -4407,16 +4253,6 @@
         AddCheckConstantFunction(expr, receiver, receiver_map, true);
 
         if (TryInline(expr)) {
-          if (current_block() != NULL) {
-            HValue* return_value = Pop();
-            // If we inlined a function in a test context then we need to emit
-            // a simulate here to shadow the ones at the end of the
-            // predecessor blocks.  Those environments contain the return
-            // value on top and do not correspond to any actual state of the
-            // unoptimized code.
-            if (ast_context()->IsEffect()) AddSimulate(expr->id());
-            ast_context()->ReturnValue(return_value);
-          }
           return;
         } else {
           // Check for bailout, as the TryInline call in the if condition above
@@ -4480,16 +4316,6 @@
         environment()->SetExpressionStackAt(receiver_index, global_receiver);
 
         if (TryInline(expr)) {
-          if (current_block() != NULL) {
-            HValue* return_value = Pop();
-            // If we inlined a function in a test context then we need to
-            // emit a simulate here to shadow the ones at the end of the
-            // predecessor blocks.  Those environments contain the return
-            // value on top and do not correspond to any actual state of the
-            // unoptimized code.
-            if (ast_context()->IsEffect()) AddSimulate(expr->id());
-            ast_context()->ReturnValue(return_value);
-          }
           return;
         }
         // Check for bailout, as trying to inline might fail due to bailout
@@ -4569,7 +4395,7 @@
     BAILOUT("call to a JavaScript runtime function");
   }
 
-  Runtime::Function* function = expr->function();
+  const Runtime::Function* function = expr->function();
   ASSERT(function != NULL);
   if (function->intrinsic_type == Runtime::INLINE) {
     ASSERT(expr->name()->length() > 0);
@@ -4666,7 +4492,12 @@
       VisitForEffect(expr->expression());
     }
 
-  } else if (op == Token::BIT_NOT || op == Token::SUB) {
+  } else if (op == Token::TYPEOF) {
+    VISIT_FOR_VALUE(expr->expression());
+    HValue* value = Pop();
+    ast_context()->ReturnInstruction(new HTypeof(value), expr->id());
+
+  } else {
     VISIT_FOR_VALUE(expr->expression());
     HValue* value = Pop();
     HInstruction* instr = NULL;
@@ -4675,19 +4506,16 @@
         instr = new HBitNot(value);
         break;
       case Token::SUB:
-        instr = new HMul(graph_->GetConstantMinus1(), value);
+        instr = new HMul(value, graph_->GetConstantMinus1());
+        break;
+      case Token::ADD:
+        instr = new HMul(value, graph_->GetConstant1());
         break;
       default:
-        UNREACHABLE();
+        BAILOUT("Value: unsupported unary operation");
         break;
     }
     ast_context()->ReturnInstruction(instr, expr->id());
-  } else if (op == Token::TYPEOF) {
-    VISIT_FOR_VALUE(expr->expression());
-    HValue* value = Pop();
-    ast_context()->ReturnInstruction(new HTypeof(value), expr->id());
-  } else {
-    BAILOUT("Value: unsupported unary operation");
   }
 }
 
@@ -5106,7 +4934,7 @@
         Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));
         // If the function is in new space we assume it's more likely to
         // change and thus prefer the general IC code.
-        if (!Heap::InNewSpace(*candidate)) {
+        if (!isolate()->heap()->InNewSpace(*candidate)) {
           target = candidate;
         }
       }
@@ -5325,19 +5153,24 @@
 
 // Fast support for string.charAt(n) and string[n].
 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
-  BAILOUT("inlined runtime function: StringCharFromCode");
+  ASSERT(call->arguments()->length() == 1);
+  VISIT_FOR_VALUE(call->arguments()->at(0));
+  HValue* char_code = Pop();
+  HStringCharFromCode* result = new HStringCharFromCode(char_code);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
 // Fast support for string.charAt(n) and string[n].
 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
-  ASSERT_EQ(2, call->arguments()->length());
-  VisitArgumentList(call->arguments());
-  CHECK_BAILOUT;
-  HContext* context = new HContext;
-  AddInstruction(context);
-  HCallStub* result = new HCallStub(context, CodeStub::StringCharAt, 2);
-  Drop(2);
+  ASSERT(call->arguments()->length() == 2);
+  VISIT_FOR_VALUE(call->arguments()->at(0));
+  VISIT_FOR_VALUE(call->arguments()->at(1));
+  HValue* index = Pop();
+  HValue* string = Pop();
+  HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
+  AddInstruction(char_code);
+  HStringCharFromCode* result = new HStringCharFromCode(char_code);
   ast_context()->ReturnInstruction(result, call->id());
 }
 
@@ -5887,12 +5720,12 @@
   Tag tag(this, "intervals");
   PrintStringProperty("name", name);
 
-  const ZoneList<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
+  const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
   for (int i = 0; i < fixed_d->length(); ++i) {
     TraceLiveRange(fixed_d->at(i), "fixed");
   }
 
-  const ZoneList<LiveRange*>* fixed = allocator->fixed_live_ranges();
+  const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
   for (int i = 0; i < fixed->length(); ++i) {
     TraceLiveRange(fixed->at(i), "fixed");
   }
@@ -5963,6 +5796,11 @@
 }
 
 
+void HStatistics::Initialize(CompilationInfo* info) {
+  source_size_ += info->shared_info()->SourceSize();
+}
+
+
 void HStatistics::Print() {
   PrintF("Timing results:\n");
   int64_t sum = 0;
@@ -5980,9 +5818,15 @@
     double size_percent = static_cast<double>(size) * 100 / total_size_;
     PrintF(" %8u bytes / %4.1f %%\n", size, size_percent);
   }
-  PrintF("%30s - %7.3f ms           %8u bytes\n", "Sum",
-         static_cast<double>(sum) / 1000,
-         total_size_);
+  double source_size_in_kb = static_cast<double>(source_size_) / 1024;
+  double normalized_time =  source_size_in_kb > 0
+      ? (static_cast<double>(sum) / 1000) / source_size_in_kb
+      : 0;
+  double normalized_bytes = source_size_in_kb > 0
+      ? total_size_ / source_size_in_kb
+      : 0;
+  PrintF("%30s - %7.3f ms           %7.3f bytes\n", "Sum",
+         normalized_time, normalized_bytes);
   PrintF("---------------------------------------------------------------\n");
   PrintF("%30s - %7.3f ms (%.1f times slower than full code gen)\n",
          "Total",
@@ -6027,13 +5871,13 @@
   if (allocator != NULL && chunk_ == NULL) {
     chunk_ = allocator->chunk();
   }
-  if (FLAG_time_hydrogen) start_ = OS::Ticks();
+  if (FLAG_hydrogen_stats) start_ = OS::Ticks();
   start_allocation_size_ = Zone::allocation_size_;
 }
 
 
 void HPhase::End() const {
-  if (FLAG_time_hydrogen) {
+  if (FLAG_hydrogen_stats) {
     int64_t end = OS::Ticks();
     unsigned size = Zone::allocation_size_ - start_allocation_size_;
     HStatistics::Instance()->SaveTiming(name_, end - start_, size);
diff --git a/src/hydrogen.h b/src/hydrogen.h
index d8b1cfb..e14799a 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -124,6 +124,10 @@
   void AddSimulate(int id) { AddInstruction(CreateSimulate(id)); }
   void AssignCommonDominator(HBasicBlock* other);
 
+  void FinishExitWithDeoptimization() {
+    FinishExit(CreateDeoptimize());
+  }
+
   // Add the inlined function exit sequence, adding an HLeaveInlined
   // instruction and updating the bailout environment.
   void AddLeaveInlined(HValue* return_value, HBasicBlock* target);
@@ -146,6 +150,7 @@
   void AddDominatedBlock(HBasicBlock* block);
 
   HSimulate* CreateSimulate(int id);
+  HDeoptimize* CreateDeoptimize();
 
   int block_id_;
   HGraph* graph_;
@@ -192,40 +197,13 @@
 };
 
 
-class HSubgraph: public ZoneObject {
- public:
-  explicit HSubgraph(HGraph* graph)
-      : graph_(graph),
-        entry_block_(NULL),
-        exit_block_(NULL) {
-  }
-
-  HGraph* graph() const { return graph_; }
-  HBasicBlock* entry_block() const { return entry_block_; }
-  HBasicBlock* exit_block() const { return exit_block_; }
-  void set_exit_block(HBasicBlock* block) {
-    exit_block_ = block;
-  }
-
-  void Initialize(HBasicBlock* block) {
-    ASSERT(entry_block_ == NULL);
-    entry_block_ = block;
-    exit_block_ = block;
-  }
-
- protected:
-  HGraph* graph_;  // The graph this is a subgraph of.
-  HBasicBlock* entry_block_;
-  HBasicBlock* exit_block_;
-};
-
-
-class HGraph: public HSubgraph {
+class HGraph: public ZoneObject {
  public:
   explicit HGraph(CompilationInfo* info);
 
   const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
   const ZoneList<HPhi*>* phi_list() const { return phi_list_; }
+  HBasicBlock* entry_block() const { return entry_block_; }
   HEnvironment* start_environment() const { return start_environment_; }
 
   void InitializeInferredTypes();
@@ -234,6 +212,7 @@
   void ComputeMinusZeroChecks();
   bool ProcessArgumentsObject();
   void EliminateRedundantPhis();
+  void EliminateUnreachablePhis();
   void Canonicalize();
   void OrderBlocks();
   void AssignDominators();
@@ -295,12 +274,18 @@
   void InsertRepresentationChangeForUse(HValue* value,
                                         HValue* use,
                                         Representation to);
-  void InsertRepresentationChanges(HValue* current);
+  void InsertRepresentationChangesForValue(HValue* current,
+                                           ZoneList<HValue*>* value_list,
+                                           ZoneList<Representation>* rep_list);
   void InferTypes(ZoneList<HValue*>* worklist);
   void InitializeInferredTypes(int from_inclusive, int to_inclusive);
   void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor);
 
+  Isolate* isolate() { return isolate_; }
+
+  Isolate* isolate_;
   int next_block_id_;
+  HBasicBlock* entry_block_;
   HEnvironment* start_environment_;
   ZoneList<HBasicBlock*> blocks_;
   ZoneList<HValue*> values_;
@@ -312,8 +297,6 @@
   SetOncePointer<HConstant> constant_false_;
   SetOncePointer<HArgumentsObject> arguments_object_;
 
-  friend class HSubgraph;
-
   DISALLOW_COPY_AND_ASSIGN(HGraph);
 };
 
@@ -404,7 +387,7 @@
   void ClearHistory() {
     pop_count_ = 0;
     push_count_ = 0;
-    assigned_variables_.Clear();
+    assigned_variables_.Rewind(0);
   }
 
   void SetValueAt(int index, HValue* value) {
@@ -640,7 +623,7 @@
         ast_context_(NULL),
         break_scope_(NULL),
         graph_(NULL),
-        current_subgraph_(NULL),
+        current_block_(NULL),
         inlined_count_(0) {
     // This is not initialized in the initializer list because the
     // constructor for the initial state relies on function_state_ == NULL
@@ -652,14 +635,11 @@
 
   // Simple accessors.
   HGraph* graph() const { return graph_; }
-  HSubgraph* subgraph() const { return current_subgraph_; }
   BreakAndContinueScope* break_scope() const { return break_scope_; }
   void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
 
-  HBasicBlock* current_block() const { return subgraph()->exit_block(); }
-  void set_current_block(HBasicBlock* block) {
-    subgraph()->set_exit_block(block);
-  }
+  HBasicBlock* current_block() const { return current_block_; }
+  void set_current_block(HBasicBlock* block) { current_block_ = block; }
   HEnvironment* environment() const {
     return current_block()->last_environment();
   }
@@ -750,10 +730,6 @@
                             HBasicBlock* exit_block,
                             HBasicBlock* continue_block);
 
-  void AddToSubgraph(HSubgraph* graph, ZoneList<Statement*>* stmts);
-  void AddToSubgraph(HSubgraph* graph, Statement* stmt);
-  void AddToSubgraph(HSubgraph* graph, Expression* expr);
-
   HValue* Top() const { return environment()->Top(); }
   void Drop(int n) { environment()->Drop(n); }
   void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
@@ -791,12 +767,7 @@
 #undef DECLARE_VISIT
 
   HBasicBlock* CreateBasicBlock(HEnvironment* env);
-  HSubgraph* CreateEmptySubgraph();
-  HSubgraph* CreateBranchSubgraph(HEnvironment* env);
   HBasicBlock* CreateLoopHeaderBlock();
-  HSubgraph* CreateInlinedSubgraph(HEnvironment* outer,
-                                   Handle<JSFunction> target,
-                                   FunctionLiteral* function);
 
   // Helpers for flow graph construction.
   void LookupGlobalPropertyCell(Variable* var,
@@ -823,10 +794,6 @@
 
   void HandlePropertyAssignment(Assignment* expr);
   void HandleCompoundAssignment(Assignment* expr);
-  void HandlePolymorphicLoadNamedField(Property* expr,
-                                       HValue* object,
-                                       ZoneMapList* types,
-                                       Handle<String> name);
   void HandlePolymorphicStoreNamedField(Assignment* expr,
                                         HValue* object,
                                         HValue* value,
@@ -852,9 +819,9 @@
   HInstruction* BuildLoadKeyedFastElement(HValue* object,
                                           HValue* key,
                                           Property* expr);
-  HInstruction* BuildLoadKeyedPixelArrayElement(HValue* object,
-                                                HValue* key,
-                                                Property* expr);
+  HInstruction* BuildLoadKeyedSpecializedArrayElement(HValue* object,
+                                                      HValue* key,
+                                                      Property* expr);
   HInstruction* BuildLoadKeyedGeneric(HValue* object,
                                       HValue* key);
 
@@ -883,14 +850,11 @@
                                            HValue* val,
                                            Expression* expr);
 
-  HInstruction* BuildStoreKeyedPixelArrayElement(HValue* object,
-                                                 HValue* key,
-                                                 HValue* val,
-                                                 Expression* expr);
-
-  HCompare* BuildSwitchCompare(HSubgraph* subgraph,
-                               HValue* switch_value,
-                               CaseClause* clause);
+  HInstruction* BuildStoreKeyedSpecializedArrayElement(
+      HValue* object,
+      HValue* key,
+      HValue* val,
+      Assignment* expr);
 
   HValue* BuildContextChainWalk(Variable* var);
 
@@ -900,12 +864,6 @@
                                 bool smi_and_map_check);
 
 
-  HBasicBlock* BuildTypeSwitch(HValue* receiver,
-                               ZoneMapList* maps,
-                               ZoneList<HSubgraph*>* body_graphs,
-                               HSubgraph* default_graph,
-                               int join_id);
-
   // The translation state of the currently-being-translated function.
   FunctionState* function_state_;
 
@@ -920,7 +878,7 @@
   BreakAndContinueScope* break_scope_;
 
   HGraph* graph_;
-  HSubgraph* current_subgraph_;
+  HBasicBlock* current_block_;
 
   int inlined_count_;
 
@@ -986,6 +944,7 @@
 
 class HStatistics: public Malloced {
  public:
+  void Initialize(CompilationInfo* info);
   void Print();
   void SaveTiming(const char* name, int64_t ticks, unsigned size);
   static HStatistics* Instance() {
@@ -1004,7 +963,8 @@
         sizes_(5),
         total_(0),
         total_size_(0),
-        full_code_gen_(0) { }
+        full_code_gen_(0),
+        source_size_(0) { }
 
   List<int64_t> timing_;
   List<const char*> names_;
@@ -1012,6 +972,7 @@
   int64_t total_;
   unsigned total_size_;
   int64_t full_code_gen_;
+  double source_size_;
 };
 
 
diff --git a/src/ia32/assembler-ia32-inl.h b/src/ia32/assembler-ia32-inl.h
index d5fd7b8..1da3f81 100644
--- a/src/ia32/assembler-ia32-inl.h
+++ b/src/ia32/assembler-ia32-inl.h
@@ -204,11 +204,12 @@
     visitor->VisitExternalReference(target_reference_address());
     CPU::FlushICache(pc_, sizeof(Address));
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  } else if (Debug::has_break_points() &&
-             ((RelocInfo::IsJSReturn(mode) &&
+  // TODO(isolates): Get a cached isolate below.
+  } else if (((RelocInfo::IsJSReturn(mode) &&
               IsPatchedReturnSequence()) ||
              (RelocInfo::IsDebugBreakSlot(mode) &&
-              IsPatchedDebugBreakSlotSequence()))) {
+              IsPatchedDebugBreakSlotSequence())) &&
+             Isolate::Current()->debug()->has_break_points()) {
     visitor->VisitDebugTarget(this);
 #endif
   } else if (mode == RelocInfo::RUNTIME_ENTRY) {
@@ -218,10 +219,10 @@
 
 
 template<typename StaticVisitor>
-void RelocInfo::Visit() {
+void RelocInfo::Visit(Heap* heap) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
-    StaticVisitor::VisitPointer(target_object_address());
+    StaticVisitor::VisitPointer(heap, target_object_address());
     CPU::FlushICache(pc_, sizeof(Address));
   } else if (RelocInfo::IsCodeTarget(mode)) {
     StaticVisitor::VisitCodeTarget(this);
@@ -231,7 +232,7 @@
     StaticVisitor::VisitExternalReference(target_reference_address());
     CPU::FlushICache(pc_, sizeof(Address));
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  } else if (Debug::has_break_points() &&
+  } else if (heap->isolate()->debug()->has_break_points() &&
              ((RelocInfo::IsJSReturn(mode) &&
               IsPatchedReturnSequence()) ||
              (RelocInfo::IsDebugBreakSlot(mode) &&
@@ -266,7 +267,7 @@
 Immediate::Immediate(Handle<Object> handle) {
   // Verify all Objects referred by code are NOT in new space.
   Object* obj = *handle;
-  ASSERT(!Heap::InNewSpace(obj));
+  ASSERT(!HEAP->InNewSpace(obj));
   if (obj->IsHeapObject()) {
     x_ = reinterpret_cast<intptr_t>(handle.location());
     rmode_ = RelocInfo::EMBEDDED_OBJECT;
@@ -299,7 +300,7 @@
 void Assembler::emit(Handle<Object> handle) {
   // Verify all Objects referred by code are NOT in new space.
   Object* obj = *handle;
-  ASSERT(!Heap::InNewSpace(obj));
+  ASSERT(!isolate()->heap()->InNewSpace(obj));
   if (obj->IsHeapObject()) {
     emit(reinterpret_cast<intptr_t>(handle.location()),
          RelocInfo::EMBEDDED_OBJECT);
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index 6652df2..e6d245e 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -48,16 +48,17 @@
 // -----------------------------------------------------------------------------
 // Implementation of CpuFeatures
 
-// Safe default is no features.
-uint64_t CpuFeatures::supported_ = 0;
-uint64_t CpuFeatures::enabled_ = 0;
-uint64_t CpuFeatures::found_by_runtime_probing_ = 0;
+CpuFeatures::CpuFeatures()
+    : supported_(0),
+      enabled_(0),
+      found_by_runtime_probing_(0) {
+}
 
 
 // The Probe method needs executable memory, so it uses Heap::CreateCode.
 // Allocation failure is silent and leads to safe default.
 void CpuFeatures::Probe(bool portable) {
-  ASSERT(Heap::HasBeenSetup());
+  ASSERT(HEAP->HasBeenSetup());
   ASSERT(supported_ == 0);
   if (portable && Serializer::enabled()) {
     supported_ |= OS::CpuFeaturesImpliedByPlatform();
@@ -120,16 +121,17 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-
   Object* code;
-  { MaybeObject* maybe_code = Heap::CreateCode(desc,
-                                               Code::ComputeFlags(Code::STUB),
-                                               Handle<Code>::null());
+  { MaybeObject* maybe_code =
+        assm.isolate()->heap()->CreateCode(desc,
+                                           Code::ComputeFlags(Code::STUB),
+                                           Handle<Code>::null());
     if (!maybe_code->ToObject(&code)) return;
   }
   if (!code->IsCode()) return;
 
-  PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG,
+  PROFILE(ISOLATE,
+          CodeCreateEvent(Logger::BUILTIN_TAG,
                           Code::cast(code), "CpuFeatures::Probe"));
   typedef uint64_t (*F0)();
   F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry());
@@ -295,19 +297,18 @@
 static void InitCoverageLog();
 #endif
 
-// Spare buffer.
-byte* Assembler::spare_buffer_ = NULL;
-
 Assembler::Assembler(void* buffer, int buffer_size)
-    : positions_recorder_(this) {
+    : AssemblerBase(Isolate::Current()),
+      positions_recorder_(this),
+      emit_debug_code_(FLAG_debug_code) {
   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 (isolate()->assembler_spare_buffer() != NULL) {
+        buffer = isolate()->assembler_spare_buffer();
+        isolate()->set_assembler_spare_buffer(NULL);
       }
     }
     if (buffer == NULL) {
@@ -348,8 +349,9 @@
 
 Assembler::~Assembler() {
   if (own_buffer_) {
-    if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
-      spare_buffer_ = buffer_;
+    if (isolate()->assembler_spare_buffer() == NULL &&
+        buffer_size_ == kMinimalBufferSize) {
+      isolate()->set_assembler_spare_buffer(buffer_);
     } else {
       DeleteArray(buffer_);
     }
@@ -367,8 +369,6 @@
   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);
 }
 
 
@@ -386,7 +386,7 @@
 
 
 void Assembler::cpuid() {
-  ASSERT(CpuFeatures::IsEnabled(CPUID));
+  ASSERT(isolate()->cpu_features()->IsEnabled(CPUID));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x0F);
@@ -747,7 +747,7 @@
 
 
 void Assembler::cmov(Condition cc, Register dst, int32_t imm32) {
-  ASSERT(CpuFeatures::IsEnabled(CMOV));
+  ASSERT(isolate()->cpu_features()->IsEnabled(CMOV));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   UNIMPLEMENTED();
@@ -758,7 +758,7 @@
 
 
 void Assembler::cmov(Condition cc, Register dst, Handle<Object> handle) {
-  ASSERT(CpuFeatures::IsEnabled(CMOV));
+  ASSERT(isolate()->cpu_features()->IsEnabled(CMOV));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   UNIMPLEMENTED();
@@ -769,7 +769,7 @@
 
 
 void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(CMOV));
+  ASSERT(isolate()->cpu_features()->IsEnabled(CMOV));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   // Opcode: 0f 40 + cc /r.
@@ -1450,7 +1450,7 @@
 
 
 void Assembler::rdtsc() {
-  ASSERT(CpuFeatures::IsEnabled(RDTSC));
+  ASSERT(isolate()->cpu_features()->IsEnabled(RDTSC));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x0F);
@@ -1856,7 +1856,7 @@
 
 
 void Assembler::fisttp_s(const Operand& adr) {
-  ASSERT(CpuFeatures::IsEnabled(SSE3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE3));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xDB);
@@ -1865,7 +1865,7 @@
 
 
 void Assembler::fisttp_d(const Operand& adr) {
-  ASSERT(CpuFeatures::IsEnabled(SSE3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE3));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xDD);
@@ -2134,7 +2134,7 @@
 
 
 void Assembler::cvttss2si(Register dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xF3);
@@ -2145,7 +2145,7 @@
 
 
 void Assembler::cvttsd2si(Register dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xF2);
@@ -2156,7 +2156,7 @@
 
 
 void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xF2);
@@ -2167,7 +2167,7 @@
 
 
 void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xF3);
@@ -2177,8 +2177,19 @@
 }
 
 
+void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF2);
+  EMIT(0x0F);
+  EMIT(0x5A);
+  emit_sse_operand(dst, src);
+}
+
+
 void Assembler::addsd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xF2);
@@ -2189,7 +2200,7 @@
 
 
 void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xF2);
@@ -2200,7 +2211,7 @@
 
 
 void Assembler::subsd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xF2);
@@ -2211,7 +2222,7 @@
 
 
 void Assembler::divsd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xF2);
@@ -2222,7 +2233,7 @@
 
 
 void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2253,7 +2264,7 @@
 
 
 void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2264,7 +2275,7 @@
 
 
 void Assembler::movmskpd(Register dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2275,7 +2286,7 @@
 
 
 void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xF2);
@@ -2287,7 +2298,7 @@
 
 
 void Assembler::movaps(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x0F);
@@ -2297,7 +2308,7 @@
 
 
 void Assembler::movdqa(const Operand& dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2308,7 +2319,7 @@
 
 
 void Assembler::movdqa(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2319,7 +2330,7 @@
 
 
 void Assembler::movdqu(const Operand& dst, XMMRegister src ) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xF3);
@@ -2330,7 +2341,7 @@
 
 
 void Assembler::movdqu(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xF3);
@@ -2341,7 +2352,7 @@
 
 
 void Assembler::movntdqa(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE4_1));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2353,7 +2364,7 @@
 
 
 void Assembler::movntdq(const Operand& dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2389,7 +2400,7 @@
 
 
 void Assembler::movsd(const Operand& dst, XMMRegister src ) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xF2);  // double
@@ -2400,7 +2411,7 @@
 
 
 void Assembler::movsd(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xF2);  // double
@@ -2411,7 +2422,7 @@
 
 
 void Assembler::movsd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0xF2);
@@ -2421,8 +2432,41 @@
 }
 
 
+void Assembler::movss(const Operand& dst, XMMRegister src ) {
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF3);  // float
+  EMIT(0x0F);
+  EMIT(0x11);  // store
+  emit_sse_operand(src, dst);
+}
+
+
+void Assembler::movss(XMMRegister dst, const Operand& src) {
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF3);  // float
+  EMIT(0x0F);
+  EMIT(0x10);  // load
+  emit_sse_operand(dst, src);
+}
+
+
+void Assembler::movss(XMMRegister dst, XMMRegister src) {
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0xF3);
+  EMIT(0x0F);
+  EMIT(0x10);
+  emit_sse_operand(dst, src);
+}
+
+
 void Assembler::movd(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2433,7 +2477,7 @@
 
 
 void Assembler::movd(const Operand& dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2444,7 +2488,7 @@
 
 
 void Assembler::pand(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2455,7 +2499,7 @@
 
 
 void Assembler::pxor(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2466,7 +2510,7 @@
 
 
 void Assembler::por(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2477,7 +2521,7 @@
 
 
 void Assembler::ptest(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE4_1));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2489,7 +2533,7 @@
 
 
 void Assembler::psllq(XMMRegister reg, int8_t shift) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2501,7 +2545,7 @@
 
 
 void Assembler::psllq(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2512,7 +2556,7 @@
 
 
 void Assembler::psrlq(XMMRegister reg, int8_t shift) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2524,7 +2568,7 @@
 
 
 void Assembler::psrlq(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2535,7 +2579,7 @@
 
 
 void Assembler::pshufd(XMMRegister dst, XMMRegister src, int8_t shuffle) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2547,7 +2591,7 @@
 
 
 void Assembler::pextrd(const Operand& dst, XMMRegister src, int8_t offset) {
-  ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE4_1));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2560,7 +2604,7 @@
 
 
 void Assembler::pinsrd(XMMRegister dst, const Operand& src, int8_t offset) {
-  ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE4_1));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   EMIT(0x66);
@@ -2629,7 +2673,7 @@
   // 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::MaxOldGenerationSize())) {
+      (desc.buffer_size > isolate()->heap()->MaxOldGenerationSize())) {
     V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
   }
 
@@ -2652,8 +2696,9 @@
           reloc_info_writer.pos(), desc.reloc_size);
 
   // Switch buffers.
-  if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
-    spare_buffer_ = buffer_;
+  if (isolate()->assembler_spare_buffer() == NULL &&
+      buffer_size_ == kMinimalBufferSize) {
+    isolate()->set_assembler_spare_buffer(buffer_);
   } else {
     DeleteArray(buffer_);
   }
@@ -2761,7 +2806,7 @@
       Serializer::TooLateToEnableNow();
     }
 #endif
-    if (!Serializer::enabled() && !FLAG_debug_code) {
+    if (!Serializer::enabled() && !emit_debug_code()) {
       return;
     }
   }
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index b60157c..8e0c762 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -37,6 +37,7 @@
 #ifndef V8_IA32_ASSEMBLER_IA32_H_
 #define V8_IA32_ASSEMBLER_IA32_H_
 
+#include "isolate.h"
 #include "serialize.h"
 
 namespace v8 {
@@ -445,16 +446,16 @@
 //   } else {
 //     // Generate standard x87 floating point code.
 //   }
-class CpuFeatures : public AllStatic {
+class CpuFeatures {
  public:
   // Detect features of the target CPU. If the portable flag is set,
   // the method sets safe defaults if the serializer is enabled
   // (snapshots must be portable).
-  static void Probe(bool portable);
-  static void Clear() { supported_ = 0; }
+  void Probe(bool portable);
+  void Clear() { supported_ = 0; }
 
   // Check whether a feature is supported by the target CPU.
-  static bool IsSupported(CpuFeature f) {
+  bool IsSupported(CpuFeature f) const {
     if (f == SSE2 && !FLAG_enable_sse2) return false;
     if (f == SSE3 && !FLAG_enable_sse3) return false;
     if (f == SSE4_1 && !FLAG_enable_sse4_1) return false;
@@ -463,36 +464,51 @@
     return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
   }
   // Check whether a feature is currently enabled.
-  static bool IsEnabled(CpuFeature f) {
+  bool IsEnabled(CpuFeature f) const {
     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(CpuFeature f) {
+    explicit Scope(CpuFeature f)
+        : cpu_features_(Isolate::Current()->cpu_features()),
+          isolate_(Isolate::Current()) {
       uint64_t mask = static_cast<uint64_t>(1) << f;
-      ASSERT(CpuFeatures::IsSupported(f));
-      ASSERT(!Serializer::enabled() || (found_by_runtime_probing_ & mask) == 0);
-      old_enabled_ = CpuFeatures::enabled_;
-      CpuFeatures::enabled_ |= mask;
+      ASSERT(cpu_features_->IsSupported(f));
+      ASSERT(!Serializer::enabled() ||
+          (cpu_features_->found_by_runtime_probing_ & mask) == 0);
+      old_enabled_ = cpu_features_->enabled_;
+      cpu_features_->enabled_ |= mask;
     }
-    ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
+    ~Scope() {
+      ASSERT_EQ(Isolate::Current(), isolate_);
+      cpu_features_->enabled_ = old_enabled_;
+    }
    private:
     uint64_t old_enabled_;
+    CpuFeatures* cpu_features_;
+    Isolate* isolate_;
 #else
    public:
     explicit Scope(CpuFeature f) {}
 #endif
   };
+
  private:
-  static uint64_t supported_;
-  static uint64_t enabled_;
-  static uint64_t found_by_runtime_probing_;
+  CpuFeatures();
+
+  uint64_t supported_;
+  uint64_t enabled_;
+  uint64_t found_by_runtime_probing_;
+
+  friend class Isolate;
+
+  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
 };
 
 
-class Assembler : public Malloced {
+class Assembler : public AssemblerBase {
  private:
   // We check before assembling an instruction that there is sufficient
   // space to write an instruction and its relocation information.
@@ -522,6 +538,9 @@
   Assembler(void* buffer, int buffer_size);
   ~Assembler();
 
+  // Overrides the default provided by FLAG_debug_code.
+  void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
+
   // 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.
@@ -885,6 +904,7 @@
 
   void cvtsi2sd(XMMRegister dst, const Operand& src);
   void cvtss2sd(XMMRegister dst, XMMRegister src);
+  void cvtsd2ss(XMMRegister dst, XMMRegister src);
 
   void addsd(XMMRegister dst, XMMRegister src);
   void subsd(XMMRegister dst, XMMRegister src);
@@ -915,6 +935,10 @@
   void movd(const Operand& src, XMMRegister dst);
   void movsd(XMMRegister dst, XMMRegister src);
 
+  void movss(XMMRegister dst, const Operand& src);
+  void movss(const Operand& src, XMMRegister dst);
+  void movss(XMMRegister dst, XMMRegister src);
+
   void pand(XMMRegister dst, XMMRegister src);
   void pxor(XMMRegister dst, XMMRegister src);
   void por(XMMRegister dst, XMMRegister src);
@@ -982,6 +1006,8 @@
   static const int kMinimalBufferSize = 4*KB;
 
  protected:
+  bool emit_debug_code() const { return emit_debug_code_; }
+
   void movsd(XMMRegister dst, const Operand& src);
   void movsd(const Operand& dst, XMMRegister src);
 
@@ -989,7 +1015,8 @@
   void emit_sse_operand(XMMRegister dst, XMMRegister src);
   void emit_sse_operand(Register dst, XMMRegister src);
 
-  byte* addr_at(int pos)  { return buffer_ + pos; }
+  byte* addr_at(int pos) { return buffer_ + pos; }
+
  private:
   byte byte_at(int pos)  { return buffer_[pos]; }
   void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
@@ -1045,8 +1072,6 @@
   int buffer_size_;
   // True if the assembler owns the buffer, false if buffer is external.
   bool own_buffer_;
-  // A previously allocated buffer of kMinimalBufferSize bytes, or NULL.
-  static byte* spare_buffer_;
 
   // code generation
   byte* pc_;  // the program counter; moves forward
@@ -1057,6 +1082,8 @@
 
   PositionsRecorder positions_recorder_;
 
+  bool emit_debug_code_;
+
   friend class PositionsRecorder;
 };
 
diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
index c7e5527..2970a0e 100644
--- a/src/ia32/builtins-ia32.cc
+++ b/src/ia32/builtins-ia32.cc
@@ -70,7 +70,7 @@
   // JumpToExternalReference expects eax to contain the number of arguments
   // including the receiver and the extra arguments.
   __ add(Operand(eax), Immediate(num_extra_args + 1));
-  __ JumpToExternalReference(ExternalReference(id));
+  __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
 }
 
 
@@ -100,8 +100,9 @@
   // Set expected number of arguments to zero (not changing eax).
   __ Set(ebx, Immediate(0));
   __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
-  __ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
-         RelocInfo::CODE_TARGET);
+  Handle<Code> arguments_adaptor =
+      masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
+  __ jmp(arguments_adaptor, RelocInfo::CODE_TARGET);
 }
 
 
@@ -128,7 +129,7 @@
     Label undo_allocation;
 #ifdef ENABLE_DEBUGGER_SUPPORT
     ExternalReference debug_step_in_fp =
-        ExternalReference::debug_step_in_fp_address();
+        ExternalReference::debug_step_in_fp_address(masm->isolate());
     __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0));
     __ j(not_equal, &rt_call);
 #endif
@@ -184,7 +185,8 @@
     // ebx: JSObject
     // edi: start of next object
     __ mov(Operand(ebx, JSObject::kMapOffset), eax);
-    __ mov(ecx, Factory::empty_fixed_array());
+    Factory* factory = masm->isolate()->factory();
+    __ 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.
@@ -194,9 +196,9 @@
     { Label loop, entry;
       // To allow for truncation.
       if (count_constructions) {
-        __ mov(edx, Factory::one_pointer_filler_map());
+        __ mov(edx, factory->one_pointer_filler_map());
       } else {
-        __ mov(edx, Factory::undefined_value());
+        __ mov(edx, factory->undefined_value());
       }
       __ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
       __ jmp(&entry);
@@ -252,7 +254,7 @@
     // edi: FixedArray
     // edx: number of elements
     // ecx: start of next object
-    __ mov(eax, Factory::fixed_array_map());
+    __ mov(eax, factory->fixed_array_map());
     __ mov(Operand(edi, FixedArray::kMapOffset), eax);  // setup the map
     __ SmiTag(edx);
     __ mov(Operand(edi, FixedArray::kLengthOffset), edx);  // and length
@@ -262,7 +264,7 @@
     // edi: FixedArray
     // ecx: start of next object
     { Label loop, entry;
-      __ mov(edx, Factory::undefined_value());
+      __ mov(edx, factory->undefined_value());
       __ lea(eax, Operand(edi, FixedArray::kHeaderSize));
       __ jmp(&entry);
       __ bind(&loop);
@@ -334,8 +336,8 @@
   // Call the function.
   if (is_api_function) {
     __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
-    Handle<Code> code = Handle<Code>(
-        Builtins::builtin(Builtins::HandleApiCallConstruct));
+    Handle<Code> code =
+        masm->isolate()->builtins()->HandleApiCallConstruct();
     ParameterCount expected(0);
     __ InvokeCode(code, expected, expected,
                   RelocInfo::CODE_TARGET, CALL_FUNCTION);
@@ -376,7 +378,7 @@
   __ pop(ecx);
   __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));  // 1 ~ receiver
   __ push(ecx);
-  __ IncrementCounter(&Counters::constructed_objects, 1);
+  __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
   __ ret(0);
 }
 
@@ -436,7 +438,7 @@
 
   // Invoke the code.
   if (is_construct) {
-    __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
+    __ call(masm->isolate()->builtins()->JSConstructCall(),
             RelocInfo::CODE_TARGET);
   } else {
     ParameterCount actual(eax);
@@ -561,12 +563,14 @@
 
 
 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
+  Factory* factory = masm->isolate()->factory();
+
   // 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(Immediate(factory->undefined_value()));
     __ push(ebx);
     __ inc(eax);
     __ bind(&done);
@@ -600,9 +604,9 @@
     __ test(ebx, Immediate(kSmiTagMask));
     __ j(zero, &convert_to_object);
 
-    __ cmp(ebx, Factory::null_value());
+    __ cmp(ebx, factory->null_value());
     __ j(equal, &use_global_receiver);
-    __ cmp(ebx, Factory::undefined_value());
+    __ cmp(ebx, factory->undefined_value());
     __ j(equal, &use_global_receiver);
 
     // We don't use IsObjectJSObjectType here because we jump on success.
@@ -674,7 +678,7 @@
     __ j(not_zero, &function, taken);
     __ Set(ebx, Immediate(0));
     __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
-    __ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
+    __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
            RelocInfo::CODE_TARGET);
     __ bind(&function);
   }
@@ -688,7 +692,8 @@
   __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
   __ SmiUntag(ebx);
   __ cmp(eax, Operand(ebx));
-  __ j(not_equal, Handle<Code>(builtin(ArgumentsAdaptorTrampoline)));
+  __ j(not_equal,
+       masm->isolate()->builtins()->ArgumentsAdaptorTrampoline());
 
   ParameterCount expected(0);
   __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION);
@@ -707,7 +712,7 @@
   // limit" is checked.
   Label okay;
   ExternalReference real_stack_limit =
-      ExternalReference::address_of_real_stack_limit();
+      ExternalReference::address_of_real_stack_limit(masm->isolate());
   __ mov(edi, Operand::StaticVariable(real_stack_limit));
   // Make ecx the space we have left. The stack might already be overflowed
   // here which will cause ecx to become negative.
@@ -753,9 +758,10 @@
   // Compute the receiver in non-strict mode.
   __ test(ebx, Immediate(kSmiTagMask));
   __ j(zero, &call_to_object);
-  __ cmp(ebx, Factory::null_value());
+  Factory* factory = masm->isolate()->factory();
+  __ cmp(ebx, factory->null_value());
   __ j(equal, &use_global_receiver);
-  __ cmp(ebx, Factory::undefined_value());
+  __ cmp(ebx, factory->undefined_value());
   __ j(equal, &use_global_receiver);
 
   // If given receiver is already a JavaScript object then there's no
@@ -795,7 +801,7 @@
   __ mov(edx, Operand(ebp, 2 * kPointerSize));  // load arguments
 
   // Use inline caching to speed up access to arguments.
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  Handle<Code> ic = masm->isolate()->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
@@ -866,8 +872,9 @@
   // scratch1: initial map
   // scratch2: start of next object
   __ mov(FieldOperand(result, JSObject::kMapOffset), scratch1);
+  Factory* factory = masm->isolate()->factory();
   __ mov(FieldOperand(result, JSArray::kPropertiesOffset),
-         Factory::empty_fixed_array());
+         factory->empty_fixed_array());
   // Field JSArray::kElementsOffset is initialized later.
   __ mov(FieldOperand(result, JSArray::kLengthOffset), Immediate(0));
 
@@ -875,7 +882,7 @@
   // fixed array.
   if (initial_capacity == 0) {
     __ mov(FieldOperand(result, JSArray::kElementsOffset),
-           Factory::empty_fixed_array());
+           factory->empty_fixed_array());
     return;
   }
 
@@ -892,7 +899,7 @@
   // scratch1: elements array
   // scratch2: start of next object
   __ mov(FieldOperand(scratch1, FixedArray::kMapOffset),
-         Factory::fixed_array_map());
+         factory->fixed_array_map());
   __ mov(FieldOperand(scratch1, FixedArray::kLengthOffset),
          Immediate(Smi::FromInt(initial_capacity)));
 
@@ -903,7 +910,7 @@
   if (initial_capacity <= kLoopUnfoldLimit) {
     // Use a scratch register here to have only one reloc info when unfolding
     // the loop.
-    __ mov(scratch3, Factory::the_hole_value());
+    __ mov(scratch3, factory->the_hole_value());
     for (int i = 0; i < initial_capacity; i++) {
       __ mov(FieldOperand(scratch1,
                           FixedArray::kHeaderSize + i * kPointerSize),
@@ -913,7 +920,7 @@
     Label loop, entry;
     __ jmp(&entry);
     __ bind(&loop);
-    __ mov(Operand(scratch1, 0), Factory::the_hole_value());
+    __ mov(Operand(scratch1, 0), factory->the_hole_value());
     __ add(Operand(scratch1), Immediate(kPointerSize));
     __ bind(&entry);
     __ cmp(scratch1, Operand(scratch2));
@@ -968,7 +975,8 @@
   // elements_array_end: start of next object
   // array_size: size of array (smi)
   __ mov(FieldOperand(result, JSObject::kMapOffset), elements_array);
-  __ mov(elements_array, Factory::empty_fixed_array());
+  Factory* factory = masm->isolate()->factory();
+  __ mov(elements_array, factory->empty_fixed_array());
   __ mov(FieldOperand(result, JSArray::kPropertiesOffset), elements_array);
   // Field JSArray::kElementsOffset is initialized later.
   __ mov(FieldOperand(result, JSArray::kLengthOffset), array_size);
@@ -987,7 +995,7 @@
   // elements_array_end: start of next object
   // array_size: size of array (smi)
   __ mov(FieldOperand(elements_array, FixedArray::kMapOffset),
-         Factory::fixed_array_map());
+         factory->fixed_array_map());
   // For non-empty JSArrays the length of the FixedArray and the JSArray is the
   // same.
   __ mov(FieldOperand(elements_array, FixedArray::kLengthOffset), array_size);
@@ -999,7 +1007,7 @@
     __ SmiUntag(array_size);
     __ lea(edi, Operand(elements_array,
                         FixedArray::kHeaderSize - kHeapObjectTag));
-    __ mov(eax, Factory::the_hole_value());
+    __ mov(eax, factory->the_hole_value());
     __ cld();
     // Do not use rep stos when filling less than kRepStosThreshold
     // words.
@@ -1063,7 +1071,7 @@
                        edi,
                        kPreallocatedArrayElements,
                        &prepare_generic_code_call);
-  __ IncrementCounter(&Counters::array_function_native, 1);
+  __ IncrementCounter(masm->isolate()->counters()->array_function_native(), 1);
   __ pop(ebx);
   if (construct_call) {
     __ pop(edi);
@@ -1119,7 +1127,8 @@
                   edi,
                   true,
                   &prepare_generic_code_call);
-  __ IncrementCounter(&Counters::array_function_native, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->array_function_native(), 1);
   __ mov(eax, ebx);
   __ pop(ebx);
   if (construct_call) {
@@ -1146,7 +1155,7 @@
                   edi,
                   false,
                   &prepare_generic_code_call);
-  __ IncrementCounter(&Counters::array_function_native, 1);
+  __ IncrementCounter(counters->array_function_native(), 1);
   __ mov(eax, ebx);
   __ pop(ebx);
   if (construct_call) {
@@ -1232,8 +1241,8 @@
   // Jump to the generic array code in case the specialized code cannot handle
   // the construction.
   __ bind(&generic_array_code);
-  Code* code = Builtins::builtin(Builtins::ArrayCodeGeneric);
-  Handle<Code> array_code(code);
+  Handle<Code> array_code =
+      masm->isolate()->builtins()->ArrayCodeGeneric();
   __ jmp(array_code, RelocInfo::CODE_TARGET);
 }
 
@@ -1266,8 +1275,8 @@
   // Jump to the generic construct code in case the specialized code cannot
   // handle the construction.
   __ bind(&generic_constructor);
-  Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
-  Handle<Code> generic_construct_stub(code);
+  Handle<Code> generic_construct_stub =
+      masm->isolate()->builtins()->JSConstructStubGeneric();
   __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
 }
 
@@ -1280,7 +1289,8 @@
   //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
   //  -- esp[(argc + 1) * 4] : receiver
   // -----------------------------------
-  __ IncrementCounter(&Counters::string_ctor_calls, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->string_ctor_calls(), 1);
 
   if (FLAG_debug_code) {
     __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, ecx);
@@ -1309,7 +1319,7 @@
       edx,  // Scratch 2.
       false,  // Input is known to be smi?
       &not_cached);
-  __ IncrementCounter(&Counters::string_ctor_cached_number, 1);
+  __ IncrementCounter(counters->string_ctor_cached_number(), 1);
   __ bind(&argument_is_string);
   // ----------- S t a t e -------------
   //  -- ebx    : argument converted to string
@@ -1338,7 +1348,8 @@
   __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx);
 
   // Set properties and elements.
-  __ Set(ecx, Immediate(Factory::empty_fixed_array()));
+  Factory* factory = masm->isolate()->factory();
+  __ Set(ecx, Immediate(factory->empty_fixed_array()));
   __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx);
   __ mov(FieldOperand(eax, JSObject::kElementsOffset), ecx);
 
@@ -1361,12 +1372,12 @@
   Condition is_string = masm->IsObjectStringType(eax, ebx, ecx);
   __ j(NegateCondition(is_string), &convert_argument);
   __ mov(ebx, eax);
-  __ IncrementCounter(&Counters::string_ctor_string_value, 1);
+  __ IncrementCounter(counters->string_ctor_string_value(), 1);
   __ jmp(&argument_is_string);
 
   // Invoke the conversion builtin and put the result into ebx.
   __ bind(&convert_argument);
-  __ IncrementCounter(&Counters::string_ctor_conversions, 1);
+  __ IncrementCounter(counters->string_ctor_conversions(), 1);
   __ EnterInternalFrame();
   __ push(edi);  // Preserve the function.
   __ push(eax);
@@ -1379,7 +1390,7 @@
   // Load the empty string into ebx, remove the receiver from the
   // stack, and jump back to the case where the argument is a string.
   __ bind(&no_arguments);
-  __ Set(ebx, Immediate(Factory::empty_string()));
+  __ Set(ebx, Immediate(factory->empty_string()));
   __ pop(ecx);
   __ lea(esp, Operand(esp, kPointerSize));
   __ push(ecx);
@@ -1388,7 +1399,7 @@
   // At this point the argument is already a string. Call runtime to
   // create a string wrapper.
   __ bind(&gc_required);
-  __ IncrementCounter(&Counters::string_ctor_gc_required, 1);
+  __ IncrementCounter(counters->string_ctor_gc_required(), 1);
   __ EnterInternalFrame();
   __ push(ebx);
   __ CallRuntime(Runtime::kNewStringWrapper, 1);
@@ -1439,7 +1450,7 @@
   // -----------------------------------
 
   Label invoke, dont_adapt_arguments;
-  __ IncrementCounter(&Counters::arguments_adaptors, 1);
+  __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1);
 
   Label enough, too_few;
   __ cmp(eax, Operand(ebx));
@@ -1487,7 +1498,7 @@
     Label fill;
     __ bind(&fill);
     __ inc(ecx);
-    __ push(Immediate(Factory::undefined_value()));
+    __ push(Immediate(masm->isolate()->factory()->undefined_value()));
     __ cmp(ecx, Operand(ebx));
     __ j(less, &fill);
 
@@ -1515,8 +1526,9 @@
   // We shouldn't be performing on-stack replacement in the first
   // place if the CPU features we need for the optimized Crankshaft
   // code aren't supported.
-  CpuFeatures::Probe(false);
-  if (!CpuFeatures::IsSupported(SSE2)) {
+  CpuFeatures* cpu_features = masm->isolate()->cpu_features();
+  cpu_features->Probe(false);
+  if (!cpu_features->IsSupported(SSE2)) {
     __ Abort("Unreachable code: Cannot optimize without SSE2 support.");
     return;
   }
@@ -1560,7 +1572,7 @@
   __ bind(&stack_check);
   NearLabel ok;
   ExternalReference stack_limit =
-      ExternalReference::address_of_stack_limit();
+      ExternalReference::address_of_stack_limit(masm->isolate());
   __ cmp(esp, Operand::StaticVariable(stack_limit));
   __ j(above_equal, &ok, taken);
   StackCheckStub stub;
@@ -1582,7 +1594,7 @@
 
 
 #undef __
-
-} }  // namespace v8::internal
+}
+}  // namespace v8::internal
 
 #endif  // V8_TARGET_ARCH_IA32
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 7efa934..96faae9 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -32,6 +32,7 @@
 #include "code-stubs.h"
 #include "bootstrapper.h"
 #include "jsregexp.h"
+#include "isolate.h"
 #include "regexp-macro-assembler.h"
 
 namespace v8 {
@@ -48,7 +49,8 @@
 
   __ bind(&check_heap_number);
   __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
-  __ cmp(Operand(ebx), Immediate(Factory::heap_number_map()));
+  Factory* factory = masm->isolate()->factory();
+  __ cmp(Operand(ebx), Immediate(factory->heap_number_map()));
   __ j(not_equal, &call_builtin);
   __ ret(0);
 
@@ -69,25 +71,30 @@
   // Get the function info from the stack.
   __ mov(edx, Operand(esp, 1 * kPointerSize));
 
+  int map_index = strict_mode_ == kStrictMode
+      ? Context::STRICT_MODE_FUNCTION_MAP_INDEX
+      : Context::FUNCTION_MAP_INDEX;
+
   // Compute the function map in the current global context and set that
   // as the map of the allocated object.
   __ mov(ecx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalContextOffset));
-  __ mov(ecx, Operand(ecx, Context::SlotOffset(Context::FUNCTION_MAP_INDEX)));
+  __ mov(ecx, Operand(ecx, Context::SlotOffset(map_index)));
   __ mov(FieldOperand(eax, JSObject::kMapOffset), ecx);
 
   // Initialize the rest of the function. We don't have to update the
   // write barrier because the allocated object is in new space.
-  __ mov(ebx, Immediate(Factory::empty_fixed_array()));
+  Factory* factory = masm->isolate()->factory();
+  __ mov(ebx, Immediate(factory->empty_fixed_array()));
   __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ebx);
   __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx);
   __ mov(FieldOperand(eax, JSFunction::kPrototypeOrInitialMapOffset),
-         Immediate(Factory::the_hole_value()));
+         Immediate(factory->the_hole_value()));
   __ mov(FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset), edx);
   __ mov(FieldOperand(eax, JSFunction::kContextOffset), esi);
   __ mov(FieldOperand(eax, JSFunction::kLiteralsOffset), ebx);
   __ mov(FieldOperand(eax, JSFunction::kNextFunctionLinkOffset),
-         Immediate(Factory::undefined_value()));
+         Immediate(factory->undefined_value()));
 
   // Initialize the code pointer in the function to be the one
   // found in the shared function info object.
@@ -104,7 +111,7 @@
   __ pop(edx);
   __ push(esi);
   __ push(edx);
-  __ push(Immediate(Factory::false_value()));
+  __ push(Immediate(factory->false_value()));
   __ push(ecx);  // Restore return address.
   __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
 }
@@ -121,7 +128,8 @@
   __ mov(ecx, Operand(esp, 1 * kPointerSize));
 
   // Setup the object header.
-  __ mov(FieldOperand(eax, HeapObject::kMapOffset), Factory::context_map());
+  Factory* factory = masm->isolate()->factory();
+  __ mov(FieldOperand(eax, HeapObject::kMapOffset), factory->context_map());
   __ mov(FieldOperand(eax, Context::kLengthOffset),
          Immediate(Smi::FromInt(length)));
 
@@ -140,7 +148,7 @@
   __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx);
 
   // Initialize the rest of the slots to undefined.
-  __ mov(ebx, Factory::undefined_value());
+  __ mov(ebx, factory->undefined_value());
   for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
     __ mov(Operand(eax, Context::SlotOffset(i)), ebx);
   }
@@ -176,7 +184,8 @@
   STATIC_ASSERT(kSmiTag == 0);
   __ mov(ecx, FieldOperand(ecx, eax, times_half_pointer_size,
                            FixedArray::kHeaderSize));
-  __ cmp(ecx, Factory::undefined_value());
+  Factory* factory = masm->isolate()->factory();
+  __ cmp(ecx, factory->undefined_value());
   __ j(equal, &slow_case);
 
   if (FLAG_debug_code) {
@@ -184,11 +193,11 @@
     Handle<Map> expected_map;
     if (mode_ == CLONE_ELEMENTS) {
       message = "Expected (writable) fixed array";
-      expected_map = Factory::fixed_array_map();
+      expected_map = factory->fixed_array_map();
     } else {
       ASSERT(mode_ == COPY_ON_WRITE_ELEMENTS);
       message = "Expected copy-on-write fixed array";
-      expected_map = Factory::fixed_cow_array_map();
+      expected_map = factory->fixed_cow_array_map();
     }
     __ push(ecx);
     __ mov(ecx, FieldOperand(ecx, JSArray::kElementsOffset));
@@ -237,7 +246,8 @@
   __ mov(eax, Operand(esp, 1 * kPointerSize));
 
   // 'null' => false.
-  __ cmp(eax, Factory::null_value());
+  Factory* factory = masm->isolate()->factory();
+  __ cmp(eax, factory->null_value());
   __ j(equal, &false_result);
 
   // Get the map and type of the heap object.
@@ -263,7 +273,7 @@
 
   __ bind(&not_string);
   // HeapNumber => false iff +0, -0, or NaN.
-  __ cmp(edx, Factory::heap_number_map());
+  __ cmp(edx, factory->heap_number_map());
   __ j(not_equal, &true_result);
   __ fldz();
   __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
@@ -284,7 +294,8 @@
 const char* GenericBinaryOpStub::GetName() {
   if (name_ != NULL) return name_;
   const int kMaxNameLength = 100;
-  name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
+  name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
+      kMaxNameLength);
   if (name_ == NULL) return "OOM";
   const char* op_name = Token::Name(op_);
   const char* overwrite_name;
@@ -358,7 +369,8 @@
 
     // Update flags to indicate that arguments are in registers.
     SetArgsInRegisters();
-    __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1);
+    __ IncrementCounter(
+        masm->isolate()->counters()->generic_binary_stub_calls_regs(), 1);
   }
 
   // Call the stub.
@@ -394,7 +406,8 @@
 
     // Update flags to indicate that arguments are in registers.
     SetArgsInRegisters();
-    __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1);
+    __ IncrementCounter(
+        masm->isolate()->counters()->generic_binary_stub_calls_regs(), 1);
   }
 
   // Call the stub.
@@ -429,7 +442,8 @@
     }
     // Update flags to indicate that arguments are in registers.
     SetArgsInRegisters();
-    __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1);
+    Counters* counters = masm->isolate()->counters();
+    __ IncrementCounter(counters->generic_binary_stub_calls_regs(), 1);
   }
 
   // Call the stub.
@@ -757,7 +771,7 @@
         // number in eax.
         __ AllocateHeapNumber(eax, ecx, ebx, slow);
         // Store the result in the HeapNumber and return.
-        if (CpuFeatures::IsSupported(SSE2)) {
+        if (masm->isolate()->cpu_features()->IsSupported(SSE2)) {
           CpuFeatures::Scope use_sse2(SSE2);
           __ cvtsi2sd(xmm0, Operand(left));
           __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
@@ -807,7 +821,7 @@
       }
       if (runtime_operands_type_ != BinaryOpIC::UNINIT_OR_SMI) {
         __ AllocateHeapNumber(ecx, ebx, no_reg, slow);
-        if (CpuFeatures::IsSupported(SSE2)) {
+        if (masm->isolate()->cpu_features()->IsSupported(SSE2)) {
           CpuFeatures::Scope use_sse2(SSE2);
           FloatingPointHelper::LoadSSE2Smis(masm, ebx);
           switch (op_) {
@@ -872,7 +886,8 @@
 void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
   Label call_runtime;
 
-  __ IncrementCounter(&Counters::generic_binary_stub_calls, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->generic_binary_stub_calls(), 1);
 
   if (runtime_operands_type_ == BinaryOpIC::UNINIT_OR_SMI) {
     Label slow;
@@ -911,7 +926,7 @@
         }
 
         Label not_floats;
-        if (CpuFeatures::IsSupported(SSE2)) {
+        if (masm->isolate()->cpu_features()->IsSupported(SSE2)) {
           CpuFeatures::Scope use_sse2(SSE2);
           if (static_operands_type_.IsNumber()) {
             if (FLAG_debug_code) {
@@ -1045,7 +1060,7 @@
             default: UNREACHABLE();
           }
           // Store the result in the HeapNumber and return.
-          if (CpuFeatures::IsSupported(SSE2)) {
+          if (masm->isolate()->cpu_features()->IsSupported(SSE2)) {
             CpuFeatures::Scope use_sse2(SSE2);
             __ cvtsi2sd(xmm0, Operand(ebx));
             __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
@@ -1263,7 +1278,7 @@
   // Patch the caller to an appropriate specialized stub and return the
   // operation result to the caller of the stub.
   __ TailCallExternalReference(
-      ExternalReference(IC_Utility(IC::kBinaryOp_Patch)),
+      ExternalReference(IC_Utility(IC::kBinaryOp_Patch), masm->isolate()),
       5,
       1);
 }
@@ -1299,7 +1314,8 @@
   // Patch the caller to an appropriate specialized stub and return the
   // operation result to the caller of the stub.
   __ TailCallExternalReference(
-      ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch)),
+      ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch),
+                        masm->isolate()),
       5,
       1);
 }
@@ -1322,7 +1338,8 @@
   // Patch the caller to an appropriate specialized stub and return the
   // operation result to the caller of the stub.
   __ TailCallExternalReference(
-      ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch)),
+      ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch),
+                        masm->isolate()),
       5,
       1);
 }
@@ -1342,6 +1359,9 @@
     case TRBinaryOpIC::HEAP_NUMBER:
       GenerateHeapNumberStub(masm);
       break;
+    case TRBinaryOpIC::ODDBALL:
+      GenerateOddballStub(masm);
+      break;
     case TRBinaryOpIC::STRING:
       GenerateStringStub(masm);
       break;
@@ -1357,7 +1377,8 @@
 const char* TypeRecordingBinaryOpStub::GetName() {
   if (name_ != NULL) return name_;
   const int kMaxNameLength = 100;
-  name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
+  name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
+      kMaxNameLength);
   if (name_ == NULL) return "OOM";
   const char* op_name = Token::Name(op_);
   const char* overwrite_name;
@@ -1639,7 +1660,7 @@
         // number in eax.
         __ AllocateHeapNumber(eax, ecx, ebx, slow);
         // Store the result in the HeapNumber and return.
-        if (CpuFeatures::IsSupported(SSE2)) {
+        if (masm->isolate()->cpu_features()->IsSupported(SSE2)) {
           CpuFeatures::Scope use_sse2(SSE2);
           __ cvtsi2sd(xmm0, Operand(left));
           __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
@@ -1684,7 +1705,7 @@
             break;
         }
         __ AllocateHeapNumber(ecx, ebx, no_reg, slow);
-        if (CpuFeatures::IsSupported(SSE2)) {
+        if (masm->isolate()->cpu_features()->IsSupported(SSE2)) {
           CpuFeatures::Scope use_sse2(SSE2);
           FloatingPointHelper::LoadSSE2Smis(masm, ebx);
           switch (op_) {
@@ -1816,7 +1837,7 @@
     case Token::DIV: {
       Label not_floats;
       Label not_int32;
-      if (CpuFeatures::IsSupported(SSE2)) {
+      if (masm->isolate()->cpu_features()->IsSupported(SSE2)) {
         CpuFeatures::Scope use_sse2(SSE2);
         FloatingPointHelper::LoadSSE2Operands(masm, &not_floats);
         FloatingPointHelper::CheckSSE2OperandsAreInt32(masm, &not_int32, ecx);
@@ -1937,7 +1958,7 @@
           default: UNREACHABLE();
         }
         // Store the result in the HeapNumber and return.
-        if (CpuFeatures::IsSupported(SSE2)) {
+        if (masm->isolate()->cpu_features()->IsSupported(SSE2)) {
           CpuFeatures::Scope use_sse2(SSE2);
           __ cvtsi2sd(xmm0, Operand(ebx));
           __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
@@ -2006,9 +2027,41 @@
 }
 
 
+void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
+  Label call_runtime;
+
+  if (op_ == Token::ADD) {
+    // Handle string addition here, because it is the only operation
+    // that does not do a ToNumber conversion on the operands.
+    GenerateAddStrings(masm);
+  }
+
+  // Convert odd ball arguments to numbers.
+  NearLabel check, done;
+  __ cmp(edx, FACTORY->undefined_value());
+  __ j(not_equal, &check);
+  if (Token::IsBitOp(op_)) {
+    __ xor_(edx, Operand(edx));
+  } else {
+    __ mov(edx, Immediate(FACTORY->nan_value()));
+  }
+  __ jmp(&done);
+  __ bind(&check);
+  __ cmp(eax, FACTORY->undefined_value());
+  __ j(not_equal, &done);
+  if (Token::IsBitOp(op_)) {
+    __ xor_(eax, Operand(eax));
+  } else {
+    __ mov(eax, Immediate(FACTORY->nan_value()));
+  }
+  __ bind(&done);
+
+  GenerateHeapNumberStub(masm);
+}
+
+
 void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
   Label call_runtime;
-  ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER);
 
   // Floating point case.
   switch (op_) {
@@ -2017,7 +2070,7 @@
     case Token::MUL:
     case Token::DIV: {
       Label not_floats;
-      if (CpuFeatures::IsSupported(SSE2)) {
+      if (masm->isolate()->cpu_features()->IsSupported(SSE2)) {
         CpuFeatures::Scope use_sse2(SSE2);
         FloatingPointHelper::LoadSSE2Operands(masm, &not_floats);
 
@@ -2120,7 +2173,7 @@
           default: UNREACHABLE();
         }
         // Store the result in the HeapNumber and return.
-        if (CpuFeatures::IsSupported(SSE2)) {
+        if (masm->isolate()->cpu_features()->IsSupported(SSE2)) {
           CpuFeatures::Scope use_sse2(SSE2);
           __ cvtsi2sd(xmm0, Operand(ebx));
           __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
@@ -2191,7 +2244,8 @@
 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
   Label call_runtime;
 
-  __ IncrementCounter(&Counters::generic_binary_stub_calls, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->generic_binary_stub_calls(), 1);
 
   switch (op_) {
     case Token::ADD:
@@ -2221,7 +2275,7 @@
     case Token::MUL:
     case Token::DIV: {
       Label not_floats;
-      if (CpuFeatures::IsSupported(SSE2)) {
+      if (masm->isolate()->cpu_features()->IsSupported(SSE2)) {
         CpuFeatures::Scope use_sse2(SSE2);
         FloatingPointHelper::LoadSSE2Operands(masm, &not_floats);
 
@@ -2319,7 +2373,7 @@
           default: UNREACHABLE();
         }
         // Store the result in the HeapNumber and return.
-        if (CpuFeatures::IsSupported(SSE2)) {
+        if (masm->isolate()->cpu_features()->IsSupported(SSE2)) {
           CpuFeatures::Scope use_sse2(SSE2);
           __ cvtsi2sd(xmm0, Operand(ebx));
           __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
@@ -2507,7 +2561,8 @@
     __ bind(&input_not_smi);
     // Check if input is a HeapNumber.
     __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
-    __ cmp(Operand(ebx), Immediate(Factory::heap_number_map()));
+    Factory* factory = masm->isolate()->factory();
+    __ cmp(Operand(ebx), Immediate(factory->heap_number_map()));
     __ j(not_equal, &runtime_call);
     // Input is a HeapNumber. Push it on the FPU stack and load its
     // low and high words into ebx, edx.
@@ -2517,7 +2572,7 @@
 
     __ bind(&loaded);
   } else {  // UNTAGGED.
-    if (CpuFeatures::IsSupported(SSE4_1)) {
+    if (masm->isolate()->cpu_features()->IsSupported(SSE4_1)) {
       CpuFeatures::Scope sse4_scope(SSE4_1);
       __ pextrd(Operand(edx), xmm1, 0x1);  // copy xmm1[63..32] to edx.
     } else {
@@ -2540,24 +2595,27 @@
   __ mov(eax, ecx);
   __ sar(eax, 8);
   __ xor_(ecx, Operand(eax));
-  ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
-  __ and_(Operand(ecx), Immediate(TranscendentalCache::kCacheSize - 1));
+  ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize));
+  __ and_(Operand(ecx),
+          Immediate(TranscendentalCache::SubCache::kCacheSize - 1));
 
   // ST[0] or xmm1 == double value.
   // ebx = low 32 bits of double value.
   // edx = high 32 bits of double value.
   // ecx = TranscendentalCache::hash(double value).
-  __ mov(eax,
-         Immediate(ExternalReference::transcendental_cache_array_address()));
-  // Eax points to cache array.
-  __ mov(eax, Operand(eax, type_ * sizeof(TranscendentalCache::caches_[0])));
+  ExternalReference cache_array =
+      ExternalReference::transcendental_cache_array_address(masm->isolate());
+  __ mov(eax, Immediate(cache_array));
+  int cache_array_index =
+      type_ * sizeof(masm->isolate()->transcendental_cache()->caches_[0]);
+  __ mov(eax, Operand(eax, cache_array_index));
   // Eax points to the cache for the type type_.
   // If NULL, the cache hasn't been initialized yet, so go through runtime.
   __ test(eax, Operand(eax));
   __ j(zero, &runtime_call_clear_stack);
 #ifdef DEBUG
   // Check that the layout of cache elements match expectations.
-  { TranscendentalCache::Element test_elem[2];
+  { TranscendentalCache::SubCache::Element test_elem[2];
     char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
     char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
     char* elem_in0  = reinterpret_cast<char*>(&(test_elem[0].in[0]));
@@ -2636,7 +2694,9 @@
     __ bind(&runtime_call_clear_stack);
     __ fstp(0);
     __ bind(&runtime_call);
-    __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
+    ExternalReference runtime =
+        ExternalReference(RuntimeFunction(), masm->isolate());
+    __ TailCallExternalReference(runtime, 1, 1);
   } else {  // UNTAGGED.
     __ bind(&runtime_call_clear_stack);
     __ bind(&runtime_call);
@@ -2766,7 +2826,8 @@
   Label done, right_exponent, normal_exponent;
   Register scratch = ebx;
   Register scratch2 = edi;
-  if (type_info.IsInteger32() && CpuFeatures::IsEnabled(SSE2)) {
+  if (type_info.IsInteger32() &&
+      masm->isolate()->cpu_features()->IsEnabled(SSE2)) {
     CpuFeatures::Scope scope(SSE2);
     __ cvttsd2si(ecx, FieldOperand(source, HeapNumber::kValueOffset));
     return;
@@ -2969,14 +3030,15 @@
 
   // If the argument is undefined it converts to zero (ECMA-262, section 9.5).
   __ bind(&check_undefined_arg1);
-  __ cmp(edx, Factory::undefined_value());
+  Factory* factory = masm->isolate()->factory();
+  __ cmp(edx, factory->undefined_value());
   __ j(not_equal, conversion_failure);
   __ mov(edx, Immediate(0));
   __ jmp(&load_arg2);
 
   __ bind(&arg1_is_object);
   __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
-  __ cmp(ebx, Factory::heap_number_map());
+  __ cmp(ebx, factory->heap_number_map());
   __ j(not_equal, &check_undefined_arg1);
 
   // Get the untagged integer version of the edx heap number in ecx.
@@ -3000,14 +3062,14 @@
 
   // If the argument is undefined it converts to zero (ECMA-262, section 9.5).
   __ bind(&check_undefined_arg2);
-  __ cmp(eax, Factory::undefined_value());
+  __ cmp(eax, factory->undefined_value());
   __ j(not_equal, conversion_failure);
   __ mov(ecx, Immediate(0));
   __ jmp(&done);
 
   __ bind(&arg2_is_object);
   __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
-  __ cmp(ebx, Factory::heap_number_map());
+  __ cmp(ebx, factory->heap_number_map());
   __ j(not_equal, &check_undefined_arg2);
 
   // Get the untagged integer version of the eax heap number in ecx.
@@ -3094,14 +3156,15 @@
   // Load operand in edx into xmm0, or branch to not_numbers.
   __ test(edx, Immediate(kSmiTagMask));
   __ j(zero, &load_smi_edx, not_taken);  // Argument in edx is a smi.
-  __ cmp(FieldOperand(edx, HeapObject::kMapOffset), Factory::heap_number_map());
+  Factory* factory = masm->isolate()->factory();
+  __ cmp(FieldOperand(edx, HeapObject::kMapOffset), factory->heap_number_map());
   __ j(not_equal, not_numbers);  // Argument in edx is not a number.
   __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
   __ bind(&load_eax);
   // Load operand in eax into xmm1, or branch to not_numbers.
   __ test(eax, Immediate(kSmiTagMask));
   __ j(zero, &load_smi_eax, not_taken);  // Argument in eax is a smi.
-  __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::heap_number_map());
+  __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map());
   __ j(equal, &load_float_eax);
   __ jmp(not_numbers);  // Argument in eax is not a number.
   __ bind(&load_smi_edx);
@@ -3219,14 +3282,15 @@
   __ 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());
+  Factory* factory = masm->isolate()->factory();
+  __ 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());
+  __ 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.
@@ -3272,7 +3336,7 @@
     }
 
     __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
-    __ cmp(edx, Factory::heap_number_map());
+    __ cmp(edx, masm->isolate()->factory()->heap_number_map());
     __ j(not_equal, &slow);
     if (overwrite_ == UNARY_OVERWRITE) {
       __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset));
@@ -3304,14 +3368,14 @@
 
     // Check if the operand is a heap number.
     __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
-    __ cmp(edx, Factory::heap_number_map());
+    __ cmp(edx, masm->isolate()->factory()->heap_number_map());
     __ j(not_equal, &slow, not_taken);
 
     // Convert the heap number in eax to an untagged integer in ecx.
     IntegerConvert(masm,
                    eax,
                    TypeInfo::Unknown(),
-                   CpuFeatures::IsSupported(SSE3),
+                   masm->isolate()->cpu_features()->IsSupported(SSE3),
                    &slow);
 
     // Do the bitwise operation and check if the result fits in a smi.
@@ -3334,7 +3398,7 @@
       __ AllocateHeapNumber(ebx, edx, edi, &slow);
       __ mov(eax, Operand(ebx));
     }
-    if (CpuFeatures::IsSupported(SSE2)) {
+    if (masm->isolate()->cpu_features()->IsSupported(SSE2)) {
       CpuFeatures::Scope use_sse2(SSE2);
       __ cvtsi2sd(xmm0, Operand(ecx));
       __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
@@ -3406,8 +3470,9 @@
   __ jmp(&powi);
   // exponent is smi and base is a heapnumber.
   __ bind(&base_nonsmi);
+  Factory* factory = masm->isolate()->factory();
   __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
-         Factory::heap_number_map());
+         factory->heap_number_map());
   __ j(not_equal, &call_runtime);
 
   __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
@@ -3459,7 +3524,7 @@
   // on doubles.
   __ bind(&exponent_nonsmi);
   __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
-         Factory::heap_number_map());
+         factory->heap_number_map());
   __ j(not_equal, &call_runtime);
   __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
   // Test if exponent is nan.
@@ -3476,7 +3541,7 @@
 
   __ bind(&base_not_smi);
   __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
-         Factory::heap_number_map());
+         factory->heap_number_map());
   __ j(not_equal, &call_runtime);
   __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset));
   __ and_(ecx, HeapNumber::kExponentMask);
@@ -3628,16 +3693,16 @@
   __ j(zero, &add_arguments_object);
   __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize));
   __ bind(&add_arguments_object);
-  __ add(Operand(ecx), Immediate(Heap::kArgumentsObjectSize));
+  __ add(Operand(ecx), Immediate(GetArgumentsObjectSize()));
 
   // Do the allocation of both objects in one go.
   __ AllocateInNewSpace(ecx, eax, edx, ebx, &runtime, TAG_OBJECT);
 
   // Get the arguments boilerplate from the current (global) context.
-  int offset = Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX);
   __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ mov(edi, FieldOperand(edi, GlobalObject::kGlobalContextOffset));
-  __ mov(edi, Operand(edi, offset));
+  __ mov(edi, Operand(edi,
+                      Context::SlotOffset(GetArgumentsBoilerplateIndex())));
 
   // Copy the JS object part.
   for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
@@ -3645,15 +3710,21 @@
     __ mov(FieldOperand(eax, i), ebx);
   }
 
-  // Setup the callee in-object property.
-  STATIC_ASSERT(Heap::arguments_callee_index == 0);
-  __ mov(ebx, Operand(esp, 3 * kPointerSize));
-  __ mov(FieldOperand(eax, JSObject::kHeaderSize), ebx);
+  if (type_ == NEW_NON_STRICT) {
+    // Setup the callee in-object property.
+    STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
+    __ mov(ebx, Operand(esp, 3 * kPointerSize));
+    __ mov(FieldOperand(eax, JSObject::kHeaderSize +
+                             Heap::kArgumentsCalleeIndex * kPointerSize),
+           ebx);
+  }
 
   // Get the length (smi tagged) and set that as an in-object property too.
-  STATIC_ASSERT(Heap::arguments_length_index == 1);
+  STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
   __ mov(ecx, Operand(esp, 1 * kPointerSize));
-  __ mov(FieldOperand(eax, JSObject::kHeaderSize + kPointerSize), ecx);
+  __ mov(FieldOperand(eax, JSObject::kHeaderSize +
+                           Heap::kArgumentsLengthIndex * kPointerSize),
+         ecx);
 
   // If there are no actual arguments, we're done.
   Label done;
@@ -3665,10 +3736,11 @@
 
   // Setup the elements pointer in the allocated arguments object and
   // initialize the header in the elements fixed array.
-  __ lea(edi, Operand(eax, Heap::kArgumentsObjectSize));
+  __ lea(edi, Operand(eax, GetArgumentsObjectSize()));
   __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
   __ mov(FieldOperand(edi, FixedArray::kMapOffset),
-         Immediate(Factory::fixed_array_map()));
+         Immediate(masm->isolate()->factory()->fixed_array_map()));
+
   __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx);
   // Untag the length for the loop below.
   __ SmiUntag(ecx);
@@ -3721,9 +3793,10 @@
 
   // Ensure that a RegExp stack is allocated.
   ExternalReference address_of_regexp_stack_memory_address =
-      ExternalReference::address_of_regexp_stack_memory_address();
+      ExternalReference::address_of_regexp_stack_memory_address(
+          masm->isolate());
   ExternalReference address_of_regexp_stack_memory_size =
-      ExternalReference::address_of_regexp_stack_memory_size();
+      ExternalReference::address_of_regexp_stack_memory_size(masm->isolate());
   __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size));
   __ test(ebx, Operand(ebx));
   __ j(zero, &runtime, not_taken);
@@ -3795,7 +3868,8 @@
   // Check that the JSArray is in fast case.
   __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset));
   __ mov(eax, FieldOperand(ebx, HeapObject::kMapOffset));
-  __ cmp(eax, Factory::fixed_array_map());
+  Factory* factory = masm->isolate()->factory();
+  __ cmp(eax, factory->fixed_array_map());
   __ j(not_equal, &runtime);
   // Check that the last match info has space for the capture registers and the
   // additional information.
@@ -3833,7 +3907,7 @@
   __ j(not_zero, &runtime);
   // String is a cons string.
   __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset));
-  __ cmp(Operand(edx), Factory::empty_string());
+  __ cmp(Operand(edx), factory->empty_string());
   __ j(not_equal, &runtime);
   __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
   __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
@@ -3883,11 +3957,17 @@
   // edx: code
   // edi: encoding of subject string (1 if ascii 0 if two_byte);
   // All checks done. Now push arguments for native regexp code.
-  __ IncrementCounter(&Counters::regexp_entry_native, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->regexp_entry_native(), 1);
 
-  static const int kRegExpExecuteArguments = 7;
+  // Isolates: note we add an additional parameter here (isolate pointer).
+  static const int kRegExpExecuteArguments = 8;
   __ EnterApiExitFrame(kRegExpExecuteArguments);
 
+  // Argument 8: Pass current isolate address.
+  __ mov(Operand(esp, 7 * kPointerSize),
+      Immediate(ExternalReference::isolate_address()));
+
   // Argument 7: Indicate that this is a direct call from JavaScript.
   __ mov(Operand(esp, 6 * kPointerSize), Immediate(1));
 
@@ -3898,7 +3978,8 @@
 
   // Argument 5: static offsets vector buffer.
   __ mov(Operand(esp, 4 * kPointerSize),
-         Immediate(ExternalReference::address_of_static_offsets_vector()));
+         Immediate(ExternalReference::address_of_static_offsets_vector(
+             masm->isolate())));
 
   // Argument 4: End of string data
   // Argument 3: Start of string data
@@ -3950,9 +4031,11 @@
   // stack overflow (on the backtrack stack) was detected in RegExp code but
   // haven't created the exception yet. Handle that in the runtime system.
   // TODO(592): Rerunning the RegExp to get the stack overflow exception.
-  ExternalReference pending_exception(Top::k_pending_exception_address);
+  ExternalReference pending_exception(Isolate::k_pending_exception_address,
+                                      masm->isolate());
   __ mov(edx,
-         Operand::StaticVariable(ExternalReference::the_hole_value_location()));
+         Operand::StaticVariable(ExternalReference::the_hole_value_location(
+             masm->isolate())));
   __ mov(eax, Operand::StaticVariable(pending_exception));
   __ cmp(edx, Operand(eax));
   __ j(equal, &runtime);
@@ -3963,7 +4046,7 @@
 
   // Special handling of termination exceptions which are uncatchable
   // by javascript code.
-  __ cmp(eax, Factory::termination_exception());
+  __ cmp(eax, factory->termination_exception());
   Label throw_termination_exception;
   __ j(equal, &throw_termination_exception);
 
@@ -3975,7 +4058,7 @@
 
   __ bind(&failure);
   // For failure to match, return null.
-  __ mov(Operand(eax), Factory::null_value());
+  __ mov(Operand(eax), factory->null_value());
   __ ret(4 * kPointerSize);
 
   // Load RegExp data.
@@ -4011,7 +4094,7 @@
 
   // Get the static offsets vector filled by the native regexp code.
   ExternalReference address_of_static_offsets_vector =
-      ExternalReference::address_of_static_offsets_vector();
+      ExternalReference::address_of_static_offsets_vector(masm->isolate());
   __ mov(ecx, Immediate(address_of_static_offsets_vector));
 
   // ebx: last_match_info backing store (FixedArray)
@@ -4076,7 +4159,8 @@
   // Set elements to point to FixedArray allocated right after the JSArray.
   // Interleave operations for better latency.
   __ mov(edx, ContextOperand(esi, Context::GLOBAL_INDEX));
-  __ mov(ecx, Immediate(Factory::empty_fixed_array()));
+  Factory* factory = masm->isolate()->factory();
+  __ mov(ecx, Immediate(factory->empty_fixed_array()));
   __ lea(ebx, Operand(eax, JSRegExpResult::kSize));
   __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalContextOffset));
   __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx);
@@ -4099,12 +4183,12 @@
 
   // Set map.
   __ mov(FieldOperand(ebx, HeapObject::kMapOffset),
-         Immediate(Factory::fixed_array_map()));
+         Immediate(factory->fixed_array_map()));
   // Set length.
   __ mov(FieldOperand(ebx, FixedArray::kLengthOffset), ecx);
   // Fill contents of fixed-array with the-hole.
   __ SmiUntag(ecx);
-  __ mov(edx, Immediate(Factory::the_hole_value()));
+  __ mov(edx, Immediate(factory->the_hole_value()));
   __ lea(ebx, FieldOperand(ebx, FixedArray::kHeaderSize));
   // Fill fixed array elements with hole.
   // eax: JSArray.
@@ -4140,7 +4224,8 @@
   Register scratch = scratch2;
 
   // Load the number string cache.
-  ExternalReference roots_address = ExternalReference::roots_address();
+  ExternalReference roots_address =
+      ExternalReference::roots_address(masm->isolate());
   __ mov(scratch, Immediate(Heap::kNumberStringCacheRootIndex));
   __ mov(number_string_cache,
          Operand::StaticArray(scratch, times_pointer_size, roots_address));
@@ -4169,7 +4254,7 @@
     __ jmp(&smi_hash_calculated);
     __ bind(&not_smi);
     __ cmp(FieldOperand(object, HeapObject::kMapOffset),
-           Factory::heap_number_map());
+           masm->isolate()->factory()->heap_number_map());
     __ j(not_equal, not_found);
     STATIC_ASSERT(8 == kDoubleSize);
     __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset));
@@ -4185,7 +4270,7 @@
                         FixedArray::kHeaderSize));
     __ test(probe, Immediate(kSmiTagMask));
     __ j(zero, not_found);
-    if (CpuFeatures::IsSupported(SSE2)) {
+    if (masm->isolate()->cpu_features()->IsSupported(SSE2)) {
       CpuFeatures::Scope fscope(SSE2);
       __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
       __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset));
@@ -4219,7 +4304,8 @@
                       index,
                       times_twice_pointer_size,
                       FixedArray::kHeaderSize + kPointerSize));
-  __ IncrementCounter(&Counters::number_to_string_native, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->number_to_string_native(), 1);
 }
 
 
@@ -4285,14 +4371,14 @@
       // Check for undefined.  undefined OP undefined is false even though
       // undefined == undefined.
       NearLabel check_for_nan;
-      __ cmp(edx, Factory::undefined_value());
+      __ cmp(edx, masm->isolate()->factory()->undefined_value());
       __ j(not_equal, &check_for_nan);
       __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_))));
       __ ret(0);
       __ bind(&check_for_nan);
     }
 
-    // Test for NaN. Sadly, we can't just compare to Factory::nan_value(),
+    // Test for NaN. Sadly, we can't just compare to factory->nan_value(),
     // so we do the second best thing - test it ourselves.
     // Note: if cc_ != equal, never_nan_nan_ is not used.
     if (never_nan_nan_ && (cc_ == equal)) {
@@ -4301,7 +4387,7 @@
     } else {
       NearLabel heap_number;
       __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
-             Immediate(Factory::heap_number_map()));
+             Immediate(masm->isolate()->factory()->heap_number_map()));
       __ j(equal, &heap_number);
       if (cc_ != equal) {
         // Call runtime on identical JSObjects.  Otherwise return equal.
@@ -4378,7 +4464,7 @@
 
     // Check if the non-smi operand is a heap number.
     __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
-           Immediate(Factory::heap_number_map()));
+           Immediate(masm->isolate()->factory()->heap_number_map()));
     // If heap number, handle it in the slow case.
     __ j(equal, &slow);
     // Return non-equal (ebx is not zero)
@@ -4423,7 +4509,7 @@
   if (include_number_compare_) {
     Label non_number_comparison;
     Label unordered;
-    if (CpuFeatures::IsSupported(SSE2)) {
+    if (masm->isolate()->cpu_features()->IsSupported(SSE2)) {
       CpuFeatures::Scope use_sse2(SSE2);
       CpuFeatures::Scope use_cmov(CMOV);
 
@@ -4642,11 +4728,17 @@
   __ Set(eax, Immediate(argc_));
   __ Set(ebx, Immediate(0));
   __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
-  Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
+  Handle<Code> adaptor =
+      masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
   __ jmp(adaptor, RelocInfo::CODE_TARGET);
 }
 
 
+bool CEntryStub::NeedsImmovableCode() {
+  return false;
+}
+
+
 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
   __ Throw(eax);
 }
@@ -4683,7 +4775,7 @@
   }
 
   ExternalReference scope_depth =
-      ExternalReference::heap_always_allocate_scope_depth();
+      ExternalReference::heap_always_allocate_scope_depth(masm->isolate());
   if (always_allocate_scope) {
     __ inc(Operand::StaticVariable(scope_depth));
   }
@@ -4691,6 +4783,8 @@
   // Call C function.
   __ mov(Operand(esp, 0 * kPointerSize), edi);  // argc.
   __ mov(Operand(esp, 1 * kPointerSize), esi);  // argv.
+  __ mov(Operand(esp, 2 * kPointerSize),
+         Immediate(ExternalReference::isolate_address()));
   __ call(Operand(ebx));
   // Result is in eax or edx:eax - do not destroy these registers!
 
@@ -4702,7 +4796,7 @@
   // call as this may lead to crashes in the IC code later.
   if (FLAG_debug_code) {
     NearLabel okay;
-    __ cmp(eax, Factory::the_hole_value());
+    __ cmp(eax, masm->isolate()->factory()->the_hole_value());
     __ j(not_equal, &okay);
     __ int3();
     __ bind(&okay);
@@ -4716,14 +4810,15 @@
   __ test(ecx, Immediate(kFailureTagMask));
   __ j(zero, &failure_returned, not_taken);
 
-  ExternalReference pending_exception_address(Top::k_pending_exception_address);
+  ExternalReference pending_exception_address(
+      Isolate::k_pending_exception_address, masm->isolate());
 
   // Check that there is no pending exception, otherwise we
   // should have returned some failure value.
   if (FLAG_debug_code) {
     __ push(edx);
     __ mov(edx, Operand::StaticVariable(
-           ExternalReference::the_hole_value_location()));
+        ExternalReference::the_hole_value_location(masm->isolate())));
     NearLabel okay;
     __ cmp(edx, Operand::StaticVariable(pending_exception_address));
     // Cannot use check here as it attempts to generate call into runtime.
@@ -4751,14 +4846,15 @@
   __ j(equal, throw_out_of_memory_exception);
 
   // Retrieve the pending exception and clear the variable.
+  ExternalReference the_hole_location =
+      ExternalReference::the_hole_value_location(masm->isolate());
   __ mov(eax, Operand::StaticVariable(pending_exception_address));
-  __ mov(edx,
-         Operand::StaticVariable(ExternalReference::the_hole_value_location()));
+  __ mov(edx, Operand::StaticVariable(the_hole_location));
   __ mov(Operand::StaticVariable(pending_exception_address), edx);
 
   // Special handling of termination exceptions which are uncatchable
   // by javascript code.
-  __ cmp(eax, Factory::termination_exception());
+  __ cmp(eax, masm->isolate()->factory()->termination_exception());
   __ j(equal, throw_termination_exception);
 
   // Handle normal exception.
@@ -4858,12 +4954,13 @@
   __ push(ebx);
 
   // Save copies of the top frame descriptor on the stack.
-  ExternalReference c_entry_fp(Top::k_c_entry_fp_address);
+  ExternalReference c_entry_fp(Isolate::k_c_entry_fp_address, masm->isolate());
   __ push(Operand::StaticVariable(c_entry_fp));
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
   // If this is the outermost JS call, set js_entry_sp value.
-  ExternalReference js_entry_sp(Top::k_js_entry_sp_address);
+  ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address,
+                                masm->isolate());
   __ cmp(Operand::StaticVariable(js_entry_sp), Immediate(0));
   __ j(not_equal, &not_outermost_js);
   __ mov(Operand::StaticVariable(js_entry_sp), ebp);
@@ -4875,7 +4972,8 @@
 
   // 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);
+  ExternalReference pending_exception(Isolate::k_pending_exception_address,
+                                      masm->isolate());
   __ mov(Operand::StaticVariable(pending_exception), eax);
   __ mov(eax, reinterpret_cast<int32_t>(Failure::Exception()));
   __ jmp(&exit);
@@ -4885,8 +4983,9 @@
   __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER);
 
   // Clear any pending exceptions.
-  __ mov(edx,
-         Operand::StaticVariable(ExternalReference::the_hole_value_location()));
+  ExternalReference the_hole_location =
+      ExternalReference::the_hole_value_location(masm->isolate());
+  __ mov(edx, Operand::StaticVariable(the_hole_location));
   __ mov(Operand::StaticVariable(pending_exception), edx);
 
   // Fake a receiver (NULL).
@@ -4897,10 +4996,13 @@
   // 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);
+    ExternalReference construct_entry(
+        Builtins::kJSConstructEntryTrampoline,
+        masm->isolate());
     __ mov(edx, Immediate(construct_entry));
   } else {
-    ExternalReference entry(Builtins::JSEntryTrampoline);
+    ExternalReference entry(Builtins::kJSEntryTrampoline,
+                            masm->isolate());
     __ mov(edx, Immediate(entry));
   }
   __ mov(edx, Operand(edx, 0));  // deref address
@@ -4908,7 +5010,9 @@
   __ call(Operand(edx));
 
   // Unlink this frame from the handler chain.
-  __ pop(Operand::StaticVariable(ExternalReference(Top::k_handler_address)));
+  __ pop(Operand::StaticVariable(ExternalReference(
+      Isolate::k_handler_address,
+      masm->isolate())));
   // Pop next_sp.
   __ add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize));
 
@@ -4923,7 +5027,9 @@
 
   // Restore the top frame descriptor from the stack.
   __ bind(&exit);
-  __ pop(Operand::StaticVariable(ExternalReference(Top::k_c_entry_fp_address)));
+  __ pop(Operand::StaticVariable(ExternalReference(
+      Isolate::k_c_entry_fp_address,
+      masm->isolate())));
 
   // Restore callee-saved registers (C calling conventions).
   __ pop(ebx);
@@ -4972,7 +5078,8 @@
   static const int8_t kCmpEdiImmediateByte2 = BitCast<int8_t, uint8_t>(0xff);
   static const int8_t kMovEaxImmediateByte = BitCast<int8_t, uint8_t>(0xb8);
 
-  ExternalReference roots_address = ExternalReference::roots_address();
+  ExternalReference roots_address =
+      ExternalReference::roots_address(masm->isolate());
 
   ASSERT_EQ(object.code(), InstanceofStub::left().code());
   ASSERT_EQ(function.code(), InstanceofStub::right().code());
@@ -5048,7 +5155,8 @@
   __ bind(&loop);
   __ cmp(scratch, Operand(prototype));
   __ j(equal, &is_instance);
-  __ cmp(Operand(scratch), Immediate(Factory::null_value()));
+  Factory* factory = masm->isolate()->factory();
+  __ cmp(Operand(scratch), Immediate(factory->null_value()));
   __ j(equal, &is_not_instance);
   __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
   __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset));
@@ -5062,7 +5170,7 @@
                                 times_pointer_size, roots_address), eax);
   } else {
     // Get return address and delta to inlined map check.
-    __ mov(eax, Factory::true_value());
+    __ mov(eax, factory->true_value());
     __ mov(scratch, Operand(esp, 0 * kPointerSize));
     __ sub(scratch, Operand(esp, 1 * kPointerSize));
     if (FLAG_debug_code) {
@@ -5084,7 +5192,7 @@
         scratch, times_pointer_size, roots_address), eax);
   } else {
     // Get return address and delta to inlined map check.
-    __ mov(eax, Factory::false_value());
+    __ mov(eax, factory->false_value());
     __ mov(scratch, Operand(esp, 0 * kPointerSize));
     __ sub(scratch, Operand(esp, 1 * kPointerSize));
     if (FLAG_debug_code) {
@@ -5108,7 +5216,7 @@
   __ j(not_equal, &slow, not_taken);
 
   // Null is not instance of anything.
-  __ cmp(object, Factory::null_value());
+  __ cmp(object, factory->null_value());
   __ j(not_equal, &object_not_null);
   __ Set(eax, Immediate(Smi::FromInt(1)));
   __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
@@ -5149,10 +5257,10 @@
     NearLabel true_value, done;
     __ test(eax, Operand(eax));
     __ j(zero, &true_value);
-    __ mov(eax, Factory::false_value());
+    __ mov(eax, factory->false_value());
     __ jmp(&done);
     __ bind(&true_value);
-    __ mov(eax, Factory::true_value());
+    __ mov(eax, factory->true_value());
     __ bind(&done);
     __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
   }
@@ -5187,7 +5295,8 @@
 
   if (name_ != NULL) return name_;
   const int kMaxNameLength = 100;
-  name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
+  name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
+      kMaxNameLength);
   if (name_ == NULL) return "OOM";
 
   const char* cc_name;
@@ -5280,7 +5389,7 @@
   // the case we would rather go to the runtime system now to flatten
   // the string.
   __ cmp(FieldOperand(object_, ConsString::kSecondOffset),
-         Immediate(Factory::empty_string()));
+         Immediate(masm->isolate()->factory()->empty_string()));
   __ j(not_equal, &call_runtime_);
   // Get the first of the two strings and load its instance type.
   __ mov(object_, FieldOperand(object_, ConsString::kFirstOffset));
@@ -5325,7 +5434,10 @@
   // Index is not a smi.
   __ bind(&index_not_smi_);
   // If index is a heap number, try converting it to an integer.
-  __ CheckMap(index_, Factory::heap_number_map(), index_not_number_, true);
+  __ CheckMap(index_,
+              masm->isolate()->factory()->heap_number_map(),
+              index_not_number_,
+              true);
   call_helper.BeforeCall(masm);
   __ push(object_);
   __ push(index_);
@@ -5386,7 +5498,8 @@
                     ((~String::kMaxAsciiCharCode) << kSmiTagSize)));
   __ j(not_zero, &slow_case_, not_taken);
 
-  __ Set(result_, Immediate(Factory::single_character_string_cache()));
+  Factory* factory = masm->isolate()->factory();
+  __ Set(result_, Immediate(factory->single_character_string_cache()));
   STATIC_ASSERT(kSmiTag == 0);
   STATIC_ASSERT(kSmiTagSize == 1);
   STATIC_ASSERT(kSmiShiftSize == 0);
@@ -5394,7 +5507,7 @@
   __ mov(result_, FieldOperand(result_,
                                code_, times_half_pointer_size,
                                FixedArray::kHeaderSize));
-  __ cmp(result_, Factory::undefined_value());
+  __ cmp(result_, factory->undefined_value());
   __ j(equal, &slow_case_, not_taken);
   __ bind(&exit_);
 }
@@ -5480,7 +5593,8 @@
   __ test(ecx, Operand(ecx));
   __ j(not_zero, &second_not_zero_length);
   // Second string is empty, result is first string which is already in eax.
-  __ IncrementCounter(&Counters::string_add_native, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->string_add_native(), 1);
   __ ret(2 * kPointerSize);
   __ bind(&second_not_zero_length);
   __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
@@ -5489,7 +5603,7 @@
   __ j(not_zero, &both_not_zero_length);
   // First string is empty, result is second string which is in edx.
   __ mov(eax, edx);
-  __ IncrementCounter(&Counters::string_add_native, 1);
+  __ IncrementCounter(counters->string_add_native(), 1);
   __ ret(2 * kPointerSize);
 
   // Both strings are non-empty.
@@ -5504,8 +5618,8 @@
   STATIC_ASSERT(Smi::kMaxValue == String::kMaxLength);
   // Handle exceptionally long strings in the runtime system.
   __ j(overflow, &string_add_runtime);
-  // Use the runtime system when adding two one character strings, as it
-  // contains optimizations for this specific case using the symbol table.
+  // Use the symbol table when adding two one character strings, as it
+  // helps later optimizations to return a symbol here.
   __ cmp(Operand(ebx), Immediate(Smi::FromInt(2)));
   __ j(not_equal, &longer_than_two);
 
@@ -5523,7 +5637,7 @@
   StringHelper::GenerateTwoCharacterSymbolTableProbe(
       masm, ebx, ecx, eax, edx, edi,
       &make_two_character_string_no_reload, &make_two_character_string);
-  __ IncrementCounter(&Counters::string_add_native, 1);
+  __ IncrementCounter(counters->string_add_native(), 1);
   __ ret(2 * kPointerSize);
 
   // Allocate a two character string.
@@ -5535,7 +5649,7 @@
   __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize));
   __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize));
   __ bind(&make_two_character_string_no_reload);
-  __ IncrementCounter(&Counters::string_add_make_two_char, 1);
+  __ IncrementCounter(counters->string_add_make_two_char(), 1);
   __ AllocateAsciiString(eax,  // Result.
                          2,    // Length.
                          edi,  // Scratch 1.
@@ -5546,7 +5660,7 @@
   __ or_(ebx, Operand(ecx));
   // Set the characters in the new string.
   __ mov_w(FieldOperand(eax, SeqAsciiString::kHeaderSize), ebx);
-  __ IncrementCounter(&Counters::string_add_native, 1);
+  __ IncrementCounter(counters->string_add_native(), 1);
   __ ret(2 * kPointerSize);
 
   __ bind(&longer_than_two);
@@ -5577,7 +5691,7 @@
   __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax);
   __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx);
   __ mov(eax, ecx);
-  __ IncrementCounter(&Counters::string_add_native, 1);
+  __ IncrementCounter(counters->string_add_native(), 1);
   __ ret(2 * kPointerSize);
   __ bind(&non_ascii);
   // At least one of the strings is two-byte. Check whether it happens
@@ -5654,7 +5768,7 @@
   // edx: first char of second argument
   // edi: length of second argument
   StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
-  __ IncrementCounter(&Counters::string_add_native, 1);
+  __ IncrementCounter(counters->string_add_native(), 1);
   __ ret(2 * kPointerSize);
 
   // Handle creating a flat two byte result.
@@ -5695,7 +5809,7 @@
   // edx: first char of second argument
   // edi: length of second argument
   StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
-  __ IncrementCounter(&Counters::string_add_native, 1);
+  __ IncrementCounter(counters->string_add_native(), 1);
   __ ret(2 * kPointerSize);
 
   // Just jump to runtime to add the two strings.
@@ -5880,7 +5994,8 @@
 
   // Load the symbol table.
   Register symbol_table = c2;
-  ExternalReference roots_address = ExternalReference::roots_address();
+  ExternalReference roots_address =
+      ExternalReference::roots_address(masm->isolate());
   __ mov(scratch, Immediate(Heap::kSymbolTableRootIndex));
   __ mov(symbol_table,
          Operand::StaticArray(scratch, times_pointer_size, roots_address));
@@ -5920,8 +6035,11 @@
                         SymbolTable::kElementsStartOffset));
 
     // If entry is undefined no string with this hash can be found.
-    __ cmp(candidate, Factory::undefined_value());
+    Factory* factory = masm->isolate()->factory();
+    __ cmp(candidate, factory->undefined_value());
     __ j(equal, not_found);
+    __ cmp(candidate, factory->null_value());
+    __ j(equal, &next_probe[i]);
 
     // If length is not 2 the string is not a candidate.
     __ cmp(FieldOperand(candidate, String::kLengthOffset),
@@ -6117,7 +6235,8 @@
   // esi: character of sub string start
   StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, true);
   __ mov(esi, edx);  // Restore esi.
-  __ IncrementCounter(&Counters::sub_string_native, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->sub_string_native(), 1);
   __ ret(3 * kPointerSize);
 
   __ bind(&non_ascii_flat);
@@ -6158,7 +6277,7 @@
   __ mov(esi, edx);  // Restore esi.
 
   __ bind(&return_eax);
-  __ IncrementCounter(&Counters::sub_string_native, 1);
+  __ IncrementCounter(counters->sub_string_native(), 1);
   __ ret(3 * kPointerSize);
 
   // Just jump to runtime to create the sub string.
@@ -6177,7 +6296,8 @@
   Label result_greater;
   Label compare_lengths;
 
-  __ IncrementCounter(&Counters::string_compare_native, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->string_compare_native(), 1);
 
   // Find minimum length.
   NearLabel left_shorter;
@@ -6268,7 +6388,7 @@
   STATIC_ASSERT(EQUAL == 0);
   STATIC_ASSERT(kSmiTag == 0);
   __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
-  __ IncrementCounter(&Counters::string_compare_native, 1);
+  __ IncrementCounter(masm->isolate()->counters()->string_compare_native(), 1);
   __ ret(2 * kPointerSize);
 
   __ bind(&not_same);
@@ -6290,59 +6410,6 @@
 }
 
 
-void StringCharAtStub::Generate(MacroAssembler* masm) {
-  // Expects two arguments (object, index) on the stack:
-
-  // Stack frame on entry.
-  //  esp[0]: return address
-  //  esp[4]: index
-  //  esp[8]: object
-
-  Register object = ebx;
-  Register index = eax;
-  Register scratch1 = ecx;
-  Register scratch2 = edx;
-  Register result = eax;
-
-  __ pop(scratch1);  // Return address.
-  __ pop(index);
-  __ pop(object);
-  __ push(scratch1);
-
-  Label need_conversion;
-  Label index_out_of_range;
-  Label done;
-  StringCharAtGenerator generator(object,
-                                  index,
-                                  scratch1,
-                                  scratch2,
-                                  result,
-                                  &need_conversion,
-                                  &need_conversion,
-                                  &index_out_of_range,
-                                  STRING_INDEX_IS_NUMBER);
-  generator.GenerateFast(masm);
-  __ jmp(&done);
-
-  __ bind(&index_out_of_range);
-  // When the index is out of range, the spec requires us to return
-  // the empty string.
-  __ Set(result, Immediate(Factory::empty_string()));
-  __ jmp(&done);
-
-  __ bind(&need_conversion);
-  // Move smi zero into the result register, which will trigger
-  // conversion.
-  __ Set(result, Immediate(Smi::FromInt(0)));
-  __ jmp(&done);
-
-  StubRuntimeCallHelper call_helper;
-  generator.GenerateSlow(masm, call_helper);
-
-  __ bind(&done);
-  __ ret(0);
-}
-
 void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
   ASSERT(state_ == CompareIC::SMIS);
   NearLabel miss;
@@ -6388,7 +6455,8 @@
 
   // Inlining the double comparison and falling back to the general compare
   // stub if NaN is involved or SS2 or CMOV is unsupported.
-  if (CpuFeatures::IsSupported(SSE2) && CpuFeatures::IsSupported(CMOV)) {
+  CpuFeatures* cpu_features = masm->isolate()->cpu_features();
+  if (cpu_features->IsSupported(SSE2) && cpu_features->IsSupported(CMOV)) {
     CpuFeatures::Scope scope1(SSE2);
     CpuFeatures::Scope scope2(CMOV);
 
@@ -6453,7 +6521,8 @@
   __ push(ecx);
 
   // Call the runtime system in a fresh internal frame.
-  ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss));
+  ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss),
+                                             masm->isolate());
   __ EnterInternalFrame();
   __ push(edx);
   __ push(eax);
@@ -6475,148 +6544,6 @@
 }
 
 
-// Loads a indexed element from a pixel array.
-void GenerateFastPixelArrayLoad(MacroAssembler* masm,
-                                Register receiver,
-                                Register key,
-                                Register elements,
-                                Register untagged_key,
-                                Register result,
-                                Label* not_pixel_array,
-                                Label* key_not_smi,
-                                Label* out_of_range) {
-  // Register use:
-  //   receiver - holds the receiver and is unchanged.
-  //   key - holds the key and is unchanged (must be a smi).
-  //   elements - is set to the the receiver's element if
-  //       the receiver doesn't have a pixel array or the
-  //       key is not a smi, otherwise it's the elements'
-  //       external pointer.
-  //   untagged_key - is set to the untagged key
-
-  // Some callers already have verified that the key is a smi.  key_not_smi is
-  // set to NULL as a sentinel for that case.  Otherwise, add an explicit check
-  // to ensure the key is a smi must be added.
-  if (key_not_smi != NULL) {
-    __ JumpIfNotSmi(key, key_not_smi);
-  } else {
-    if (FLAG_debug_code) {
-      __ AbortIfNotSmi(key);
-    }
-  }
-  __ mov(untagged_key, key);
-  __ SmiUntag(untagged_key);
-
-  __ mov(elements, FieldOperand(receiver, JSObject::kElementsOffset));
-  // By passing NULL as not_pixel_array, callers signal that they have already
-  // verified that the receiver has pixel array elements.
-  if (not_pixel_array != NULL) {
-    __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true);
-  } else {
-    if (FLAG_debug_code) {
-      // Map check should have already made sure that elements is a pixel array.
-      __ cmp(FieldOperand(elements, HeapObject::kMapOffset),
-             Immediate(Factory::pixel_array_map()));
-      __ Assert(equal, "Elements isn't a pixel array");
-    }
-  }
-
-  // Key must be in range.
-  __ cmp(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset));
-  __ j(above_equal, out_of_range);  // unsigned check handles negative keys.
-
-  // Perform the indexed load and tag the result as a smi.
-  __ mov(elements, FieldOperand(elements, PixelArray::kExternalPointerOffset));
-  __ movzx_b(result, Operand(elements, untagged_key, times_1, 0));
-  __ SmiTag(result);
-  __ ret(0);
-}
-
-
-// Stores an indexed element into a pixel array, clamping the stored value.
-void GenerateFastPixelArrayStore(MacroAssembler* masm,
-                                 Register receiver,
-                                 Register key,
-                                 Register value,
-                                 Register elements,
-                                 Register scratch1,
-                                 bool load_elements_from_receiver,
-                                 Label* key_not_smi,
-                                 Label* value_not_smi,
-                                 Label* not_pixel_array,
-                                 Label* out_of_range) {
-  // Register use:
-  //   receiver - holds the receiver and is unchanged unless the
-  //              store succeeds.
-  //   key - holds the key (must be a smi) and is unchanged.
-  //   value - holds the value (must be a smi) and is unchanged.
-  //   elements - holds the element object of the receiver on entry if
-  //              load_elements_from_receiver is false, otherwise used
-  //              internally to store the pixel arrays elements and
-  //              external array pointer.
-  //
-  // receiver, key and value remain unmodified until it's guaranteed that the
-  // store will succeed.
-  Register external_pointer = elements;
-  Register untagged_key = scratch1;
-  Register untagged_value = receiver;  // Only set once success guaranteed.
-
-  // Fetch the receiver's elements if the caller hasn't already done so.
-  if (load_elements_from_receiver) {
-    __ mov(elements, FieldOperand(receiver, JSObject::kElementsOffset));
-  }
-
-  // By passing NULL as not_pixel_array, callers signal that they have already
-  // verified that the receiver has pixel array elements.
-  if (not_pixel_array != NULL) {
-    __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true);
-  } else {
-    if (FLAG_debug_code) {
-      // Map check should have already made sure that elements is a pixel array.
-      __ cmp(FieldOperand(elements, HeapObject::kMapOffset),
-             Immediate(Factory::pixel_array_map()));
-      __ Assert(equal, "Elements isn't a pixel array");
-    }
-  }
-
-  // Some callers already have verified that the key is a smi.  key_not_smi is
-  // set to NULL as a sentinel for that case.  Otherwise, add an explicit check
-  // to ensure the key is a smi must be added.
-  if (key_not_smi != NULL) {
-    __ JumpIfNotSmi(key, key_not_smi);
-  } else {
-    if (FLAG_debug_code) {
-      __ AbortIfNotSmi(key);
-    }
-  }
-
-  // Key must be a smi and it must be in range.
-  __ mov(untagged_key, key);
-  __ SmiUntag(untagged_key);
-  __ cmp(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset));
-  __ j(above_equal, out_of_range);  // unsigned check handles negative keys.
-
-  // Value must be a smi.
-  __ JumpIfNotSmi(value, value_not_smi);
-  __ mov(untagged_value, value);
-  __ SmiUntag(untagged_value);
-
-  {  // Clamp the value to [0..255].
-    NearLabel done;
-    __ test(untagged_value, Immediate(0xFFFFFF00));
-    __ j(zero, &done);
-    __ setcc(negative, untagged_value);  // 1 if negative, 0 if positive.
-    __ dec_b(untagged_value);  // 0 if negative, 255 if positive.
-    __ bind(&done);
-  }
-
-  __ mov(external_pointer,
-         FieldOperand(elements, PixelArray::kExternalPointerOffset));
-  __ mov_b(Operand(external_pointer, untagged_key, times_1, 0), untagged_value);
-  __ ret(0);  // Return value in eax.
-}
-
-
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/ia32/code-stubs-ia32.h b/src/ia32/code-stubs-ia32.h
index 4a1119a..31fa645 100644
--- a/src/ia32/code-stubs-ia32.h
+++ b/src/ia32/code-stubs-ia32.h
@@ -96,7 +96,7 @@
     if (static_operands_type_.IsSmi()) {
       mode_ = NO_OVERWRITE;
     }
-    use_sse3_ = CpuFeatures::IsSupported(SSE3);
+    use_sse3_ = Isolate::Current()->cpu_features()->IsSupported(SSE3);
     ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
   }
 
@@ -235,7 +235,7 @@
         operands_type_(TRBinaryOpIC::UNINITIALIZED),
         result_type_(TRBinaryOpIC::UNINITIALIZED),
         name_(NULL) {
-    use_sse3_ = CpuFeatures::IsSupported(SSE3);
+    use_sse3_ = Isolate::Current()->cpu_features()->IsSupported(SSE3);
     ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
   }
 
@@ -306,6 +306,7 @@
   void GenerateSmiStub(MacroAssembler* masm);
   void GenerateInt32Stub(MacroAssembler* masm);
   void GenerateHeapNumberStub(MacroAssembler* masm);
+  void GenerateOddballStub(MacroAssembler* masm);
   void GenerateStringStub(MacroAssembler* masm);
   void GenerateGenericStub(MacroAssembler* masm);
   void GenerateAddStrings(MacroAssembler* masm);
@@ -489,48 +490,6 @@
 #endif
 };
 
-
-// Generate code to load an element from a pixel array. The receiver is assumed
-// to not be a smi and to have elements, the caller must guarantee this
-// precondition. If key is not a smi, then the generated code branches to
-// key_not_smi. Callers can specify NULL for key_not_smi to signal that a smi
-// check has already been performed on key so that the smi check is not
-// generated. If key is not a valid index within the bounds of the pixel array,
-// the generated code jumps to out_of_range. receiver, key and elements are
-// unchanged throughout the generated code sequence.
-void GenerateFastPixelArrayLoad(MacroAssembler* masm,
-                                Register receiver,
-                                Register key,
-                                Register elements,
-                                Register untagged_key,
-                                Register result,
-                                Label* not_pixel_array,
-                                Label* key_not_smi,
-                                Label* out_of_range);
-
-// Generate code to store an element into a pixel array, clamping values between
-// [0..255]. The receiver is assumed to not be a smi and to have elements, the
-// caller must guarantee this precondition. If key is not a smi, then the
-// generated code branches to key_not_smi. Callers can specify NULL for
-// key_not_smi to signal that a smi check has already been performed on key so
-// that the smi check is not generated. If the value is not a smi, the generated
-// code will branch to value_not_smi.  If the receiver doesn't have pixel array
-// elements, the generated code will branch to not_pixel_array, unless
-// not_pixel_array is NULL, in which case the caller must ensure that the
-// receiver has pixel array elements.  If key is not a valid index within the
-// bounds of the pixel array, the generated code jumps to out_of_range.
-void GenerateFastPixelArrayStore(MacroAssembler* masm,
-                                 Register receiver,
-                                 Register key,
-                                 Register value,
-                                 Register elements,
-                                 Register scratch1,
-                                 bool load_elements_from_receiver,
-                                 Label* key_not_smi,
-                                 Label* value_not_smi,
-                                 Label* not_pixel_array,
-                                 Label* out_of_range);
-
 } }  // namespace v8::internal
 
 #endif  // V8_IA32_CODE_STUBS_IA32_H_
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index 3a2753d..cf990a0 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -154,7 +154,8 @@
       safe_int32_mode_enabled_(true),
       function_return_is_shadowed_(false),
       in_spilled_code_(false),
-      jit_cookie_((FLAG_mask_constants_with_cookie) ? V8::RandomPrivate() : 0) {
+      jit_cookie_((FLAG_mask_constants_with_cookie) ?
+                  V8::RandomPrivate(Isolate::Current()) : 0) {
 }
 
 
@@ -182,7 +183,7 @@
   ASSERT_EQ(0, loop_nesting_);
   loop_nesting_ = info->is_in_loop() ? 1 : 0;
 
-  JumpTarget::set_compiling_deferred_code(false);
+  masm()->isolate()->set_jump_target_compiling_deferred_code(false);
 
   {
     CodeGenState state(this);
@@ -284,7 +285,7 @@
 
     // Initialize ThisFunction reference if present.
     if (scope()->is_function_scope() && scope()->function() != NULL) {
-      frame_->Push(Factory::the_hole_value());
+      frame_->Push(FACTORY->the_hole_value());
       StoreToSlot(scope()->function()->AsSlot(), NOT_CONST_INIT);
     }
 
@@ -320,7 +321,7 @@
     if (!scope()->HasIllegalRedeclaration()) {
       Comment cmnt(masm_, "[ function body");
 #ifdef DEBUG
-      bool is_builtin = Bootstrapper::IsActive();
+      bool is_builtin = info->isolate()->bootstrapper()->IsActive();
       bool should_trace =
           is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;
       if (should_trace) {
@@ -337,7 +338,7 @@
         ASSERT(!function_return_is_shadowed_);
         CodeForReturnPosition(info->function());
         frame_->PrepareForReturn();
-        Result undefined(Factory::undefined_value());
+        Result undefined(FACTORY->undefined_value());
         if (function_return_.is_bound()) {
           function_return_.Jump(&undefined);
         } else {
@@ -369,9 +370,9 @@
 
   // Process any deferred code using the register allocator.
   if (!HasStackOverflow()) {
-    JumpTarget::set_compiling_deferred_code(true);
+    info->isolate()->set_jump_target_compiling_deferred_code(true);
     ProcessDeferred();
-    JumpTarget::set_compiling_deferred_code(false);
+    info->isolate()->set_jump_target_compiling_deferred_code(false);
   }
 
   // There is no need to delete the register allocator, it is a
@@ -555,7 +556,7 @@
     __ sar(val, 1);
     // If there was an overflow, bits 30 and 31 of the original number disagree.
     __ xor_(val, 0x80000000u);
-    if (CpuFeatures::IsSupported(SSE2)) {
+    if (masm()->isolate()->cpu_features()->IsSupported(SSE2)) {
       CpuFeatures::Scope fscope(SSE2);
       __ cvtsi2sd(xmm0, Operand(val));
     } else {
@@ -573,7 +574,7 @@
                           no_reg, &allocation_failed);
     VirtualFrame* clone = new VirtualFrame(frame_);
     scratch.Unuse();
-    if (CpuFeatures::IsSupported(SSE2)) {
+    if (masm()->isolate()->cpu_features()->IsSupported(SSE2)) {
       CpuFeatures::Scope fscope(SSE2);
       __ movdbl(FieldOperand(val, HeapNumber::kValueOffset), xmm0);
     } else {
@@ -586,7 +587,7 @@
     RegisterFile empty_regs;
     SetFrame(clone, &empty_regs);
     __ bind(&allocation_failed);
-    if (!CpuFeatures::IsSupported(SSE2)) {
+    if (!masm()->isolate()->cpu_features()->IsSupported(SSE2)) {
       // Pop the value from the floating point stack.
       __ fstp(0);
     }
@@ -613,7 +614,7 @@
       safe_int32_mode_enabled() &&
       expr->side_effect_free() &&
       expr->num_bit_ops() > 2 &&
-      CpuFeatures::IsSupported(SSE2)) {
+      masm()->isolate()->cpu_features()->IsSupported(SSE2)) {
     BreakTarget unsafe_bailout;
     JumpTarget done;
     unsafe_bailout.set_expected_height(frame_->height());
@@ -634,12 +635,12 @@
     if (dest.false_was_fall_through()) {
       // The false target was just bound.
       JumpTarget loaded;
-      frame_->Push(Factory::false_value());
+      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());
+        frame_->Push(FACTORY->true_value());
         loaded.Bind();
       }
 
@@ -647,11 +648,11 @@
       // There is true, and possibly false, control flow (with true as
       // the fall through).
       JumpTarget loaded;
-      frame_->Push(Factory::true_value());
+      frame_->Push(FACTORY->true_value());
       if (false_target.is_linked()) {
         loaded.Jump();
         false_target.Bind();
-        frame_->Push(Factory::false_value());
+        frame_->Push(FACTORY->false_value());
         loaded.Bind();
       }
 
@@ -666,14 +667,14 @@
         loaded.Jump();  // Don't lose the current TOS.
         if (true_target.is_linked()) {
           true_target.Bind();
-          frame_->Push(Factory::true_value());
+          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());
+          frame_->Push(FACTORY->false_value());
         }
         loaded.Bind();
       }
@@ -729,11 +730,14 @@
 
 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() {
   if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION;
-  ASSERT(scope()->arguments_shadow() != NULL);
+
+  // In strict mode there is no need for shadow arguments.
+  ASSERT(scope()->arguments_shadow() != NULL || scope()->is_strict_mode());
+
   // We don't want to do lazy arguments allocation for functions that
   // have heap-allocated contexts, because it interfers with the
   // uninitialized const tracking in the context objects.
-  return (scope()->num_heap_slots() > 0)
+  return (scope()->num_heap_slots() > 0 || scope()->is_strict_mode())
       ? EAGER_ARGUMENTS_ALLOCATION
       : LAZY_ARGUMENTS_ALLOCATION;
 }
@@ -748,9 +752,11 @@
     // When using lazy arguments allocation, we store the arguments marker value
     // as a sentinel indicating that the arguments object hasn't been
     // allocated yet.
-    frame_->Push(Factory::arguments_marker());
+    frame_->Push(FACTORY->arguments_marker());
   } else {
-    ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
+    ArgumentsAccessStub stub(is_strict_mode()
+        ? ArgumentsAccessStub::NEW_STRICT
+        : ArgumentsAccessStub::NEW_NON_STRICT);
     frame_->PushFunction();
     frame_->PushReceiverSlotAddress();
     frame_->Push(Smi::FromInt(scope()->num_parameters()));
@@ -760,8 +766,11 @@
 
   Variable* arguments = scope()->arguments();
   Variable* shadow = scope()->arguments_shadow();
+
   ASSERT(arguments != NULL && arguments->AsSlot() != NULL);
-  ASSERT(shadow != NULL && shadow->AsSlot() != NULL);
+  ASSERT((shadow != NULL && shadow->AsSlot() != NULL) ||
+         scope()->is_strict_mode());
+
   JumpTarget done;
   bool skip_arguments = false;
   if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) {
@@ -775,7 +784,7 @@
       // been assigned a proper value.
       skip_arguments = !probe.handle()->IsArgumentsMarker();
     } else {
-      __ cmp(Operand(probe.reg()), Immediate(Factory::arguments_marker()));
+      __ cmp(Operand(probe.reg()), Immediate(FACTORY->arguments_marker()));
       probe.Unuse();
       done.Branch(not_equal);
     }
@@ -784,7 +793,9 @@
     StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT);
     if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind();
   }
-  StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
+  if (shadow != NULL) {
+    StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
+  }
   return frame_->Pop();
 }
 
@@ -904,15 +915,15 @@
   } else {
     // Fast case checks.
     // 'false' => false.
-    __ cmp(value.reg(), Factory::false_value());
+    __ cmp(value.reg(), FACTORY->false_value());
     dest->false_target()->Branch(equal);
 
     // 'true' => true.
-    __ cmp(value.reg(), Factory::true_value());
+    __ cmp(value.reg(), FACTORY->true_value());
     dest->true_target()->Branch(equal);
 
     // 'undefined' => false.
-    __ cmp(value.reg(), Factory::undefined_value());
+    __ cmp(value.reg(), FACTORY->undefined_value());
     dest->false_target()->Branch(equal);
 
     // Smi => false iff zero.
@@ -983,7 +994,8 @@
 
 
 Label* DeferredInlineBinaryOperation::NonSmiInputLabel() {
-  if (Token::IsBitOp(op_) && CpuFeatures::IsSupported(SSE2)) {
+  if (Token::IsBitOp(op_) &&
+      masm()->isolate()->cpu_features()->IsSupported(SSE2)) {
     return &non_smi_input_;
   } else {
     return entry_label();
@@ -1006,7 +1018,7 @@
 void DeferredInlineBinaryOperation::Generate() {
   // Registers are not saved implicitly for this stub, so we should not
   // tread on the registers that were not passed to us.
-  if (CpuFeatures::IsSupported(SSE2) &&
+  if (masm()->isolate()->cpu_features()->IsSupported(SSE2) &&
       ((op_ == Token::ADD) ||
        (op_ == Token::SUB) ||
        (op_ == Token::MUL) ||
@@ -1019,7 +1031,7 @@
       __ j(zero, &left_smi);
       if (!left_info_.IsNumber()) {
         __ cmp(FieldOperand(left_, HeapObject::kMapOffset),
-               Factory::heap_number_map());
+               FACTORY->heap_number_map());
         __ j(not_equal, &call_runtime);
       }
       __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset));
@@ -1048,7 +1060,7 @@
       __ j(zero, &right_smi);
       if (!right_info_.IsNumber()) {
         __ cmp(FieldOperand(right_, HeapObject::kMapOffset),
-               Factory::heap_number_map());
+               FACTORY->heap_number_map());
         __ j(not_equal, &call_runtime);
       }
       __ movdbl(xmm1, FieldOperand(right_, HeapNumber::kValueOffset));
@@ -1142,7 +1154,7 @@
     // The left_ and right_ registers have not been initialized yet.
     __ mov(right_, Immediate(smi_value_));
     __ mov(left_, Operand(dst_));
-    if (!CpuFeatures::IsSupported(SSE2)) {
+    if (!masm()->isolate()->cpu_features()->IsSupported(SSE2)) {
       __ jmp(entry_label());
       return;
     } else {
@@ -1255,7 +1267,8 @@
   // This trashes right_.
   __ AllocateHeapNumber(left_, right_, no_reg, &after_alloc_failure2);
   __ bind(&allocation_ok);
-  if (CpuFeatures::IsSupported(SSE2) && op_ != Token::SHR) {
+  if (masm()->isolate()->cpu_features()->IsSupported(SSE2) &&
+      op_ != Token::SHR) {
     CpuFeatures::Scope use_sse2(SSE2);
     ASSERT(Token::IsBitOp(op_));
     // Signed conversion.
@@ -1497,7 +1510,7 @@
 
 
 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) {
-  Object* answer_object = Heap::undefined_value();
+  Object* answer_object = HEAP->undefined_value();
   switch (op) {
     case Token::ADD:
       if (Smi::IsValid(left + right)) {
@@ -1569,7 +1582,7 @@
       UNREACHABLE();
       break;
   }
-  if (answer_object == Heap::undefined_value()) {
+  if (answer_object->IsUndefined()) {
     return false;
   }
   frame_->Push(Handle<Object>(answer_object));
@@ -3018,13 +3031,14 @@
       // Jump or fall through to here if we are comparing a non-smi to a
       // constant smi.  If the non-smi is a heap number and this is not
       // a loop condition, inline the floating point code.
-      if (!is_loop_condition && CpuFeatures::IsSupported(SSE2)) {
+      if (!is_loop_condition &&
+          masm()->isolate()->cpu_features()->IsSupported(SSE2)) {
         // Right side is a constant smi and left side has been checked
         // not to be a smi.
         CpuFeatures::Scope use_sse2(SSE2);
         JumpTarget not_number;
         __ cmp(FieldOperand(left_reg, HeapObject::kMapOffset),
-               Immediate(Factory::heap_number_map()));
+               Immediate(FACTORY->heap_number_map()));
         not_number.Branch(not_equal, left_side);
         __ movdbl(xmm1,
                   FieldOperand(left_reg, HeapNumber::kValueOffset));
@@ -3090,7 +3104,7 @@
     __ test(operand->reg(), Immediate(kSmiTagMask));
     __ j(zero, &done);
     __ cmp(FieldOperand(operand->reg(), HeapObject::kMapOffset),
-           Immediate(Factory::heap_number_map()));
+           Immediate(FACTORY->heap_number_map()));
     not_numbers->Branch(not_equal, left_side, right_side, not_taken);
     __ bind(&done);
   }
@@ -3157,7 +3171,7 @@
     __ j(zero, &smi);
     if (!operand->type_info().IsNumber()) {
       __ cmp(FieldOperand(operand->reg(), HeapObject::kMapOffset),
-             Immediate(Factory::heap_number_map()));
+             Immediate(FACTORY->heap_number_map()));
       not_numbers->Branch(not_equal, left_side, right_side, taken);
     }
     __ movdbl(xmm_reg, FieldOperand(operand->reg(), HeapNumber::kValueOffset));
@@ -3182,7 +3196,7 @@
   ASSERT(right_side->is_register());
 
   JumpTarget not_numbers;
-  if (CpuFeatures::IsSupported(SSE2)) {
+  if (masm()->isolate()->cpu_features()->IsSupported(SSE2)) {
     CpuFeatures::Scope use_sse2(SSE2);
 
     // Load left and right operand into registers xmm0 and xmm1 and compare.
@@ -3264,7 +3278,7 @@
   // give us a megamorphic load site. Not super, but it works.
   Load(applicand);
   frame()->Dup();
-  Handle<String> name = Factory::LookupAsciiSymbol("apply");
+  Handle<String> name = FACTORY->LookupAsciiSymbol("apply");
   frame()->Push(name);
   Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET);
   __ nop();
@@ -3296,7 +3310,7 @@
     if (probe.is_constant()) {
       try_lazy = probe.handle()->IsArgumentsMarker();
     } else {
-      __ cmp(Operand(probe.reg()), Immediate(Factory::arguments_marker()));
+      __ cmp(Operand(probe.reg()), Immediate(FACTORY->arguments_marker()));
       probe.Unuse();
       __ j(not_equal, &slow);
     }
@@ -3332,7 +3346,8 @@
       __ j(not_equal, &build_args);
       __ mov(ecx, FieldOperand(eax, JSFunction::kCodeEntryOffset));
       __ sub(Operand(ecx), Immediate(Code::kHeaderSize - kHeapObjectTag));
-      Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
+      Handle<Code> apply_code(masm()->isolate()->builtins()->builtin(
+          Builtins::kFunctionApply));
       __ cmp(Operand(ecx), Immediate(apply_code));
       __ j(not_equal, &build_args);
 
@@ -3458,7 +3473,7 @@
 void CodeGenerator::CheckStack() {
   DeferredStackCheck* deferred = new DeferredStackCheck;
   ExternalReference stack_limit =
-      ExternalReference::address_of_stack_limit();
+      ExternalReference::address_of_stack_limit(masm()->isolate());
   __ cmp(esp, Operand::StaticVariable(stack_limit));
   deferred->Branch(below);
   deferred->BindExit();
@@ -3559,7 +3574,7 @@
     // 'undefined') because we may have a (legal) redeclaration and we
     // must not destroy the current value.
     if (node->mode() == Variable::CONST) {
-      frame_->EmitPush(Immediate(Factory::the_hole_value()));
+      frame_->EmitPush(Immediate(FACTORY->the_hole_value()));
     } else if (node->fun() != NULL) {
       Load(node->fun());
     } else {
@@ -3575,7 +3590,7 @@
   // 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());
+    val = new Literal(FACTORY->the_hole_value());
   } else {
     val = node->fun();  // NULL if we don't have a function
   }
@@ -4356,9 +4371,9 @@
   frame_->EmitPop(eax);
 
   // eax: value to be iterated over
-  __ cmp(eax, Factory::undefined_value());
+  __ cmp(eax, FACTORY->undefined_value());
   exit.Branch(equal);
-  __ cmp(eax, Factory::null_value());
+  __ cmp(eax, FACTORY->null_value());
   exit.Branch(equal);
 
   // Stack layout in body:
@@ -4397,14 +4412,14 @@
   loop.Bind();
   // Check that there are no elements.
   __ mov(edx, FieldOperand(ecx, JSObject::kElementsOffset));
-  __ cmp(Operand(edx), Immediate(Factory::empty_fixed_array()));
+  __ cmp(Operand(edx), Immediate(FACTORY->empty_fixed_array()));
   call_runtime.Branch(not_equal);
   // Check that instance descriptors are not empty so that we can
   // check for an enum cache.  Leave the map in ebx for the subsequent
   // prototype load.
   __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
   __ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOffset));
-  __ cmp(Operand(edx), Immediate(Factory::empty_descriptor_array()));
+  __ cmp(Operand(edx), Immediate(FACTORY->empty_descriptor_array()));
   call_runtime.Branch(equal);
   // Check that there in an enum cache in the non-empty instance
   // descriptors.  This is the case if the next enumeration index
@@ -4416,12 +4431,12 @@
   __ cmp(ecx, Operand(eax));
   check_prototype.Branch(equal);
   __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset));
-  __ cmp(Operand(edx), Immediate(Factory::empty_fixed_array()));
+  __ cmp(Operand(edx), Immediate(FACTORY->empty_fixed_array()));
   call_runtime.Branch(not_equal);
   check_prototype.Bind();
   // Load the prototype from the map and loop if non-null.
   __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
-  __ cmp(Operand(ecx), Immediate(Factory::null_value()));
+  __ cmp(Operand(ecx), Immediate(FACTORY->null_value()));
   loop.Branch(not_equal);
   // The enum cache is valid.  Load the map of the object being
   // iterated over and use the cache for the iteration.
@@ -4440,7 +4455,7 @@
   // Runtime::kGetPropertyNamesFast)
   __ mov(edx, Operand(eax));
   __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
-  __ cmp(ecx, Factory::meta_map());
+  __ cmp(ecx, FACTORY->meta_map());
   fixed_array.Branch(not_equal);
 
   use_cache.Bind();
@@ -4632,7 +4647,8 @@
   function_return_is_shadowed_ = function_return_was_shadowed;
 
   // Get an external reference to the handler address.
-  ExternalReference handler_address(Top::k_handler_address);
+  ExternalReference handler_address(Isolate::k_handler_address,
+                                    masm()->isolate());
 
   // Make sure that there's nothing left on the stack above the
   // handler structure.
@@ -4758,7 +4774,8 @@
   function_return_is_shadowed_ = function_return_was_shadowed;
 
   // Get an external reference to the handler address.
-  ExternalReference handler_address(Top::k_handler_address);
+  ExternalReference handler_address(Isolate::k_handler_address,
+                                    masm()->isolate());
 
   // 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.
@@ -4770,7 +4787,7 @@
 
     // 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()));
+    frame_->EmitPush(Immediate(FACTORY->undefined_value()));
     __ Set(ecx, Immediate(Smi::FromInt(FALLING)));
     if (nof_unlinks > 0) {
       finally_block.Jump();
@@ -4813,7 +4830,7 @@
         frame_->EmitPush(eax);
       } else {
         // Fake TOS for targets that shadowed breaks and continues.
-        frame_->EmitPush(Immediate(Factory::undefined_value()));
+        frame_->EmitPush(Immediate(FACTORY->undefined_value()));
       }
       __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i)));
       if (--nof_unlinks > 0) {
@@ -4908,10 +4925,11 @@
 
   // Use the fast case closure allocation code that allocates in new
   // space for nested functions that don't need literals cloning.
-  if (scope()->is_function_scope() &&
-      function_info->num_literals() == 0 &&
-      !pretenure) {
-    FastNewClosureStub stub;
+  if (!pretenure &&
+      scope()->is_function_scope() &&
+      function_info->num_literals() == 0) {
+    FastNewClosureStub stub(
+        function_info->strict_mode() ? kStrictMode : kNonStrictMode);
     frame()->EmitPush(Immediate(function_info));
     return frame()->CallStub(&stub, 1);
   } else {
@@ -4920,8 +4938,8 @@
     frame()->EmitPush(esi);
     frame()->EmitPush(Immediate(function_info));
     frame()->EmitPush(Immediate(pretenure
-                                ? Factory::true_value()
-                                : Factory::false_value()));
+                                ? FACTORY->true_value()
+                                : FACTORY->false_value()));
     return frame()->CallRuntime(Runtime::kNewClosure, 3);
   }
 }
@@ -5029,9 +5047,9 @@
     Comment cmnt(masm_, "[ Load const");
     Label exit;
     __ mov(ecx, SlotOperand(slot, ecx));
-    __ cmp(ecx, Factory::the_hole_value());
+    __ cmp(ecx, FACTORY->the_hole_value());
     __ j(not_equal, &exit);
-    __ mov(ecx, Factory::undefined_value());
+    __ mov(ecx, FACTORY->undefined_value());
     __ bind(&exit);
     frame()->EmitPush(ecx);
 
@@ -5081,7 +5099,7 @@
   // indicates that we haven't loaded the arguments object yet, we
   // need to do it now.
   JumpTarget exit;
-  __ cmp(Operand(result.reg()), Immediate(Factory::arguments_marker()));
+  __ cmp(Operand(result.reg()), Immediate(FACTORY->arguments_marker()));
   frame()->Push(&result);
   exit.Branch(not_equal);
 
@@ -5135,7 +5153,7 @@
     __ bind(&next);
     // Terminate at global context.
     __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
-           Immediate(Factory::global_context_map()));
+           Immediate(FACTORY->global_context_map()));
     __ j(equal, &fast);
     // Check that extension is NULL.
     __ cmp(ContextOperand(tmp.reg(), Context::EXTENSION_INDEX), Immediate(0));
@@ -5195,9 +5213,9 @@
       __ mov(result->reg(),
              ContextSlotOperandCheckExtensions(potential_slot, *result, slow));
       if (potential_slot->var()->mode() == Variable::CONST) {
-        __ cmp(result->reg(), Factory::the_hole_value());
+        __ cmp(result->reg(), FACTORY->the_hole_value());
         done->Branch(not_equal, result);
-        __ mov(result->reg(), Factory::undefined_value());
+        __ mov(result->reg(), FACTORY->undefined_value());
       }
       done->Jump(result);
     } else if (rewrite != NULL) {
@@ -5284,7 +5302,7 @@
       VirtualFrame::SpilledScope spilled_scope;
       Comment cmnt(masm_, "[ Init const");
       __ mov(ecx, SlotOperand(slot, ecx));
-      __ cmp(ecx, Factory::the_hole_value());
+      __ cmp(ecx, FACTORY->the_hole_value());
       exit.Branch(not_equal);
     }
 
@@ -5455,7 +5473,7 @@
                              Register target,
                              int registers_to_save = 0)
     : size_(size), target_(target), registers_to_save_(registers_to_save) {
-    ASSERT(size >= kPointerSize && size <= Heap::MaxObjectSizeInNewSpace());
+    ASSERT(size >= kPointerSize && size <= HEAP->MaxObjectSizeInNewSpace());
     ASSERT_EQ(0, registers_to_save & target.bit());
     set_comment("[ DeferredAllocateInNewSpace");
   }
@@ -5516,7 +5534,7 @@
   // jump to the deferred code passing the literals array.
   DeferredRegExpLiteral* deferred =
       new DeferredRegExpLiteral(boilerplate.reg(), literals.reg(), node);
-  __ cmp(boilerplate.reg(), Factory::undefined_value());
+  __ cmp(boilerplate.reg(), FACTORY->undefined_value());
   deferred->Branch(equal);
   deferred->BindExit();
 
@@ -5674,11 +5692,12 @@
   frame_->Push(node->constant_elements());
   int length = node->values()->length();
   Result clone;
-  if (node->constant_elements()->map() == Heap::fixed_cow_array_map()) {
+  if (node->constant_elements()->map() == HEAP->fixed_cow_array_map()) {
     FastCloneShallowArrayStub stub(
         FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
     clone = frame_->CallStub(&stub, 3);
-    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1);
+    Counters* counters = masm()->isolate()->counters();
+    __ IncrementCounter(counters->cow_arrays_created_stub(), 1);
   } else if (node->depth() > 1) {
     clone = frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3);
   } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
@@ -6081,7 +6100,7 @@
     Load(function);
 
     // Allocate a frame slot for the receiver.
-    frame_->Push(Factory::undefined_value());
+    frame_->Push(FACTORY->undefined_value());
 
     // Load the arguments.
     int arg_count = args->length();
@@ -6113,7 +6132,7 @@
       if (arg_count > 0) {
         frame_->PushElementAt(arg_count);
       } else {
-        frame_->Push(Factory::undefined_value());
+        frame_->Push(FACTORY->undefined_value());
       }
       frame_->PushParameterAt(-1);
 
@@ -6135,7 +6154,7 @@
     if (arg_count > 0) {
       frame_->PushElementAt(arg_count);
     } else {
-      frame_->Push(Factory::undefined_value());
+      frame_->Push(FACTORY->undefined_value());
     }
     frame_->PushParameterAt(-1);
 
@@ -6429,7 +6448,7 @@
   }
 #endif
   // Finally, we're expected to leave a value on the top of the stack.
-  frame_->Push(Factory::undefined_value());
+  frame_->Push(FACTORY->undefined_value());
 }
 
 
@@ -6472,13 +6491,13 @@
     __ bind(&need_conversion_);
     // Move the undefined value into the result register, which will
     // trigger conversion.
-    __ Set(result_, Immediate(Factory::undefined_value()));
+    __ Set(result_, Immediate(FACTORY->undefined_value()));
     __ jmp(exit_label());
 
     __ bind(&index_out_of_range_);
     // When the index is out of range, the spec requires us to return
     // NaN.
-    __ Set(result_, Immediate(Factory::nan_value()));
+    __ Set(result_, Immediate(FACTORY->nan_value()));
     __ jmp(exit_label());
   }
 
@@ -6601,7 +6620,7 @@
     __ bind(&index_out_of_range_);
     // When the index is out of range, the spec requires us to return
     // the empty string.
-    __ Set(result_, Immediate(Factory::empty_string()));
+    __ Set(result_, Immediate(FACTORY->empty_string()));
     __ jmp(exit_label());
   }
 
@@ -6719,7 +6738,7 @@
   __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset));
   __ sar(array_length, 1);
   __ j(not_zero, &non_trivial_array);
-  __ mov(result_operand, Factory::empty_string());
+  __ mov(result_operand, FACTORY->empty_string());
   __ jmp(&done);
 
   // Save the array length.
@@ -6930,7 +6949,7 @@
 
 
   __ bind(&bailout);
-  __ mov(result_operand, Factory::undefined_value());
+  __ mov(result_operand, FACTORY->undefined_value());
   __ bind(&done);
   __ mov(eax, result_operand);
   // Drop temp values from the stack, and restore context register.
@@ -6971,7 +6990,7 @@
 
   __ test(obj.reg(), Immediate(kSmiTagMask));
   destination()->false_target()->Branch(zero);
-  __ cmp(obj.reg(), Factory::null_value());
+  __ cmp(obj.reg(), FACTORY->null_value());
   destination()->true_target()->Branch(equal);
 
   Result map = allocator()->Allocate();
@@ -7042,7 +7061,7 @@
     // Check for fast case object. Generate false result for slow case object.
     __ mov(scratch1_, FieldOperand(object_, JSObject::kPropertiesOffset));
     __ mov(scratch1_, FieldOperand(scratch1_, HeapObject::kMapOffset));
-    __ cmp(scratch1_, Factory::hash_table_map());
+    __ cmp(scratch1_, FACTORY->hash_table_map());
     __ j(equal, &false_result);
 
     // Look for valueOf symbol in the descriptor array, and indicate false if
@@ -7069,7 +7088,7 @@
     __ jmp(&entry);
     __ bind(&loop);
     __ mov(scratch2_, FieldOperand(map_result_, 0));
-    __ cmp(scratch2_, Factory::value_of_symbol());
+    __ cmp(scratch2_, FACTORY->value_of_symbol());
     __ j(equal, &false_result);
     __ add(Operand(map_result_), Immediate(kPointerSize));
     __ bind(&entry);
@@ -7284,17 +7303,17 @@
 
   // Functions have class 'Function'.
   function.Bind();
-  frame_->Push(Factory::function_class_symbol());
+  frame_->Push(FACTORY->function_class_symbol());
   leave.Jump();
 
   // Objects with a non-function constructor have class 'Object'.
   non_function_constructor.Bind();
-  frame_->Push(Factory::Object_symbol());
+  frame_->Push(FACTORY->Object_symbol());
   leave.Jump();
 
   // Non-JS objects have class null.
   null.Bind();
-  frame_->Push(Factory::null_value());
+  frame_->Push(FACTORY->null_value());
 
   // All done.
   leave.Bind();
@@ -7430,13 +7449,14 @@
   __ bind(&heapnumber_allocated);
 
   __ PrepareCallCFunction(0, ebx);
-  __ CallCFunction(ExternalReference::random_uint32_function(), 0);
+  __ CallCFunction(ExternalReference::random_uint32_function(masm()->isolate()),
+                   0);
 
   // Convert 32 random bits in eax to 0.(32 random bits) in a double
   // by computing:
   // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
   // This is implemented on both SSE2 and FPU.
-  if (CpuFeatures::IsSupported(SSE2)) {
+  if (masm()->isolate()->cpu_features()->IsSupported(SSE2)) {
     CpuFeatures::Scope fscope(SSE2);
     __ mov(ebx, Immediate(0x49800000));  // 1.0 x 2^20 as single.
     __ movd(xmm1, Operand(ebx));
@@ -7653,10 +7673,10 @@
   int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
 
   Handle<FixedArray> jsfunction_result_caches(
-      Top::global_context()->jsfunction_result_caches());
+      masm()->isolate()->global_context()->jsfunction_result_caches());
   if (jsfunction_result_caches->length() <= cache_id) {
     __ Abort("Attempt to use undefined cache.");
-    frame_->Push(Factory::undefined_value());
+    frame_->Push(FACTORY->undefined_value());
     return;
   }
 
@@ -7773,7 +7793,7 @@
   // Check the object's elements are in fast case and writable.
   __ mov(tmp1.reg(), FieldOperand(object.reg(), JSObject::kElementsOffset));
   __ cmp(FieldOperand(tmp1.reg(), HeapObject::kMapOffset),
-         Immediate(Factory::fixed_array_map()));
+         Immediate(FACTORY->fixed_array_map()));
   deferred->Branch(not_equal);
 
   // Smi-tagging is equivalent to multiplying by 2.
@@ -7814,7 +7834,7 @@
   __ bind(&done);
 
   deferred->BindExit();
-  frame_->Push(Factory::undefined_value());
+  frame_->Push(FACTORY->undefined_value());
 }
 
 
@@ -7842,7 +7862,7 @@
   ASSERT(args->length() == 2);
   Load(args->at(0));
   Load(args->at(1));
-  if (!CpuFeatures::IsSupported(SSE2)) {
+  if (!masm()->isolate()->cpu_features()->IsSupported(SSE2)) {
     Result res = frame_->CallRuntime(Runtime::kMath_pow, 2);
     frame_->Push(&res);
   } else {
@@ -7883,7 +7903,7 @@
     // exponent is smi and base is a heapnumber.
     __ bind(&base_nonsmi);
     __ cmp(FieldOperand(base.reg(), HeapObject::kMapOffset),
-           Factory::heap_number_map());
+           FACTORY->heap_number_map());
     call_runtime.Branch(not_equal);
 
     __ movdbl(xmm0, FieldOperand(base.reg(), HeapNumber::kValueOffset));
@@ -7934,7 +7954,7 @@
     // on doubles.
     __ bind(&exponent_nonsmi);
     __ cmp(FieldOperand(exponent.reg(), HeapObject::kMapOffset),
-           Factory::heap_number_map());
+           FACTORY->heap_number_map());
     call_runtime.Branch(not_equal);
     __ movdbl(xmm1, FieldOperand(exponent.reg(), HeapNumber::kValueOffset));
     // Test if exponent is nan.
@@ -7950,7 +7970,7 @@
     __ jmp(&handle_special_cases);
     __ bind(&base_not_smi);
     __ cmp(FieldOperand(base.reg(), HeapObject::kMapOffset),
-           Factory::heap_number_map());
+           FACTORY->heap_number_map());
     call_runtime.Branch(not_equal);
     __ mov(answer.reg(), FieldOperand(base.reg(), HeapNumber::kExponentOffset));
     __ and_(answer.reg(), HeapNumber::kExponentMask);
@@ -8059,7 +8079,7 @@
   ASSERT_EQ(args->length(), 1);
   Load(args->at(0));
 
-  if (!CpuFeatures::IsSupported(SSE2)) {
+  if (!masm()->isolate()->cpu_features()->IsSupported(SSE2)) {
     Result result = frame()->CallRuntime(Runtime::kMath_sqrt, 1);
     frame()->Push(&result);
   } else {
@@ -8081,7 +8101,7 @@
     __ jmp(&load_done);
     __ bind(&non_smi);
     __ cmp(FieldOperand(result.reg(), HeapObject::kMapOffset),
-           Factory::heap_number_map());
+           FACTORY->heap_number_map());
     __ j(not_equal, &runtime);
     __ movdbl(xmm0, FieldOperand(result.reg(), HeapNumber::kValueOffset));
 
@@ -8187,7 +8207,7 @@
 
   ZoneList<Expression*>* args = node->arguments();
   Comment cmnt(masm_, "[ CallRuntime");
-  Runtime::Function* function = node->function();
+  const Runtime::Function* function = node->function();
 
   if (function == NULL) {
     // Push the builtins object found in the current global object.
@@ -8270,12 +8290,12 @@
       } else {
         // Default: Result of deleting non-global, not dynamically
         // introduced variables is false.
-        frame_->Push(Factory::false_value());
+        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());
+      frame_->SetElementAt(0, FACTORY->true_value());
     }
 
   } else if (op == Token::TYPEOF) {
@@ -8296,10 +8316,10 @@
         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());
+      frame_->Push(FACTORY->undefined_value());
     } else {
       Load(node->expression());
-      frame_->SetElementAt(0, Factory::undefined_value());
+      frame_->SetElementAt(0, FACTORY->undefined_value());
     }
 
   } else {
@@ -9101,16 +9121,16 @@
     Result answer = frame_->Pop();
     answer.ToRegister();
 
-    if (check->Equals(Heap::number_symbol())) {
+    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());
+      __ cmp(answer.reg(), FACTORY->heap_number_map());
       answer.Unuse();
       destination()->Split(equal);
 
-    } else if (check->Equals(Heap::string_symbol())) {
+    } else if (check->Equals(HEAP->string_symbol())) {
       __ test(answer.reg(), Immediate(kSmiTagMask));
       destination()->false_target()->Branch(zero);
 
@@ -9126,15 +9146,15 @@
       answer.Unuse();
       destination()->Split(below);
 
-    } else if (check->Equals(Heap::boolean_symbol())) {
-      __ cmp(answer.reg(), Factory::true_value());
+    } else if (check->Equals(HEAP->boolean_symbol())) {
+      __ cmp(answer.reg(), FACTORY->true_value());
       destination()->true_target()->Branch(equal);
-      __ cmp(answer.reg(), Factory::false_value());
+      __ cmp(answer.reg(), FACTORY->false_value());
       answer.Unuse();
       destination()->Split(equal);
 
-    } else if (check->Equals(Heap::undefined_symbol())) {
-      __ cmp(answer.reg(), Factory::undefined_value());
+    } else if (check->Equals(HEAP->undefined_symbol())) {
+      __ cmp(answer.reg(), FACTORY->undefined_value());
       destination()->true_target()->Branch(equal);
 
       __ test(answer.reg(), Immediate(kSmiTagMask));
@@ -9148,7 +9168,7 @@
       answer.Unuse();
       destination()->Split(not_zero);
 
-    } else if (check->Equals(Heap::function_symbol())) {
+    } else if (check->Equals(HEAP->function_symbol())) {
       __ test(answer.reg(), Immediate(kSmiTagMask));
       destination()->false_target()->Branch(zero);
       frame_->Spill(answer.reg());
@@ -9158,10 +9178,10 @@
       __ CmpInstanceType(answer.reg(), JS_REGEXP_TYPE);
       answer.Unuse();
       destination()->Split(equal);
-    } else if (check->Equals(Heap::object_symbol())) {
+    } else if (check->Equals(HEAP->object_symbol())) {
       __ test(answer.reg(), Immediate(kSmiTagMask));
       destination()->false_target()->Branch(zero);
-      __ cmp(answer.reg(), Factory::null_value());
+      __ cmp(answer.reg(), FACTORY->null_value());
       destination()->true_target()->Branch(equal);
 
       Result map = allocator()->Allocate();
@@ -9204,7 +9224,7 @@
       Result scratch = allocator()->Allocate();
       ASSERT(scratch.is_valid());
       __ mov(scratch.reg(), FieldOperand(lhs.reg(), HeapObject::kMapOffset));
-      __ cmp(scratch.reg(), Factory::heap_number_map());
+      __ cmp(scratch.reg(), FACTORY->heap_number_map());
       JumpTarget not_a_number;
       not_a_number.Branch(not_equal, &lhs);
       __ mov(scratch.reg(),
@@ -9291,7 +9311,7 @@
   Load(node->expression());
   Result operand = frame_->Pop();
   operand.ToRegister();
-  __ cmp(operand.reg(), Factory::null_value());
+  __ cmp(operand.reg(), FACTORY->null_value());
   if (node->is_strict()) {
     operand.Unuse();
     destination()->Split(equal);
@@ -9299,7 +9319,7 @@
     // The 'null' value is only equal to 'undefined' if using non-strict
     // comparisons.
     destination()->true_target()->Branch(equal);
-    __ cmp(operand.reg(), Factory::undefined_value());
+    __ cmp(operand.reg(), FACTORY->undefined_value());
     destination()->true_target()->Branch(equal);
     __ test(operand.reg(), Immediate(kSmiTagMask));
     destination()->false_target()->Branch(equal);
@@ -9372,7 +9392,8 @@
     __ mov(eax, receiver_);
   }
   __ Set(ecx, Immediate(name_));
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Handle<Code> ic(masm()->isolate()->builtins()->builtin(
+      Builtins::kLoadIC_Initialize));
   RelocInfo::Mode mode = is_contextual_
       ? RelocInfo::CODE_TARGET_CONTEXT
       : RelocInfo::CODE_TARGET;
@@ -9389,15 +9410,16 @@
   int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
   // Here we use masm_-> instead of the __ macro because this is the
   // instruction that gets patched and coverage code gets in the way.
+  Counters* counters = masm()->isolate()->counters();
   if (is_contextual_) {
     masm_->mov(is_dont_delete_ ? edx : ecx, -delta_to_patch_site);
-    __ IncrementCounter(&Counters::named_load_global_inline_miss, 1);
+    __ IncrementCounter(counters->named_load_global_inline_miss(), 1);
     if (is_dont_delete_) {
-      __ IncrementCounter(&Counters::dont_delete_hint_miss, 1);
+      __ IncrementCounter(counters->dont_delete_hint_miss(), 1);
     }
   } else {
     masm_->test(eax, Immediate(-delta_to_patch_site));
-    __ IncrementCounter(&Counters::named_load_inline_miss, 1);
+    __ IncrementCounter(counters->named_load_inline_miss(), 1);
   }
 
   if (!dst_.is(eax)) __ mov(dst_, eax);
@@ -9451,7 +9473,8 @@
   // 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.
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  Handle<Code> ic(masm()->isolate()->builtins()->builtin(
+      Builtins::kKeyedLoadIC_Initialize));
   __ call(ic, RelocInfo::CODE_TARGET);
   // The delta from the start of the map-compare instruction to the
   // test instruction.  We use masm_-> directly here instead of the __
@@ -9462,7 +9485,8 @@
   // Here we use masm_-> instead of the __ macro because this is the
   // instruction that gets patched and coverage code gets in the way.
   masm_->test(eax, Immediate(-delta_to_patch_site));
-  __ IncrementCounter(&Counters::keyed_load_inline_miss, 1);
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_inline_miss(), 1);
 
   if (!dst_.is(eax)) __ mov(dst_, eax);
 }
@@ -9498,7 +9522,8 @@
 
 
 void DeferredReferenceSetKeyedValue::Generate() {
-  __ IncrementCounter(&Counters::keyed_store_inline_miss, 1);
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->keyed_store_inline_miss(), 1);
   // Move value_ to eax, key_ to ecx, and receiver_ to edx.
   Register old_value = value_;
 
@@ -9552,9 +9577,9 @@
   }
 
   // Call the IC stub.
-  Handle<Code> ic(Builtins::builtin(
-      (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
-                                    : Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(masm()->isolate()->builtins()->builtin(
+      (strict_mode_ == kStrictMode) ? Builtins::kKeyedStoreIC_Initialize_Strict
+                                    : Builtins::kKeyedStoreIC_Initialize));
   __ call(ic, RelocInfo::CODE_TARGET);
   // The delta from the start of the map-compare instruction to the
   // test instruction.  We use masm_-> directly here instead of the
@@ -9575,9 +9600,13 @@
   int original_height = frame()->height();
 #endif
 
+  Isolate* isolate = masm()->isolate();
+  Factory* factory = isolate->factory();
+  Counters* counters = isolate->counters();
+
   bool contextual_load_in_builtin =
       is_contextual &&
-      (Bootstrapper::IsActive() ||
+      (isolate->bootstrapper()->IsActive() ||
        (!info_->closure().is_null() && info_->closure()->IsBuiltin()));
 
   Result result;
@@ -9623,7 +9652,7 @@
     // use the double underscore macro that may insert instructions).
     // Initially use an invalid map to force a failure.
     masm()->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
-                Immediate(Factory::null_value()));
+                Immediate(factory->null_value()));
     // This branch is always a forwards branch so it's always a fixed size
     // which allows the assert below to succeed and patching to work.
     deferred->Branch(not_equal);
@@ -9635,14 +9664,16 @@
 
     if (is_contextual) {
       // Load the (initialy invalid) cell and get its value.
-      masm()->mov(result.reg(), Factory::null_value());
+      masm()->mov(result.reg(), factory->null_value());
       if (FLAG_debug_code) {
         __ cmp(FieldOperand(result.reg(), HeapObject::kMapOffset),
-               Factory::global_property_cell_map());
+               factory->global_property_cell_map());
         __ Assert(equal, "Uninitialized inlined contextual load");
       }
       __ mov(result.reg(),
              FieldOperand(result.reg(), JSGlobalPropertyCell::kValueOffset));
+      __ cmp(result.reg(), factory->the_hole_value());
+      deferred->Branch(equal);
       bool is_dont_delete = false;
       if (!info_->closure().is_null()) {
         // When doing lazy compilation we can check if the global cell
@@ -9661,15 +9692,15 @@
       }
       deferred->set_is_dont_delete(is_dont_delete);
       if (!is_dont_delete) {
-        __ cmp(result.reg(), Factory::the_hole_value());
+        __ cmp(result.reg(), factory->the_hole_value());
         deferred->Branch(equal);
       } else if (FLAG_debug_code) {
-        __ cmp(result.reg(), Factory::the_hole_value());
+        __ cmp(result.reg(), factory->the_hole_value());
         __ Check(not_equal, "DontDelete cells can't contain the hole");
       }
-      __ IncrementCounter(&Counters::named_load_global_inline, 1);
+      __ IncrementCounter(counters->named_load_global_inline(), 1);
       if (is_dont_delete) {
-        __ IncrementCounter(&Counters::dont_delete_hint_hit, 1);
+        __ IncrementCounter(counters->dont_delete_hint_hit(), 1);
       }
     } else {
       // The initial (invalid) offset has to be large enough to force a 32-bit
@@ -9677,7 +9708,7 @@
       // kMaxInt (minus kHeapObjectTag).
       int offset = kMaxInt;
       masm()->mov(result.reg(), FieldOperand(receiver.reg(), offset));
-      __ IncrementCounter(&Counters::named_load_inline, 1);
+      __ IncrementCounter(counters->named_load_inline(), 1);
     }
 
     deferred->BindExit();
@@ -9723,7 +9754,7 @@
     // Initially use an invalid map to force a failure.
     __ bind(&patch_site);
     masm()->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
-                Immediate(Factory::null_value()));
+                Immediate(FACTORY->null_value()));
     // This branch is always a forwards branch so it's always a fixed size
     // which allows the assert below to succeed and patching to work.
     slow.Branch(not_equal, &value, &receiver);
@@ -9833,7 +9864,7 @@
     // Use masm-> here instead of the double underscore macro since extra
     // coverage code can interfere with the patching.
     masm_->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
-               Immediate(Factory::null_value()));
+               Immediate(FACTORY->null_value()));
     deferred->Branch(not_equal);
 
     // Check that the key is a smi.
@@ -9863,9 +9894,9 @@
                         times_2,
                         FixedArray::kHeaderSize));
     result = elements;
-    __ cmp(Operand(result.reg()), Immediate(Factory::the_hole_value()));
+    __ cmp(Operand(result.reg()), Immediate(FACTORY->the_hole_value()));
     deferred->Branch(equal);
-    __ IncrementCounter(&Counters::keyed_load_inline, 1);
+    __ IncrementCounter(masm_->isolate()->counters()->keyed_load_inline(), 1);
 
     deferred->BindExit();
   } else {
@@ -9935,12 +9966,6 @@
     __ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, tmp.reg());
     deferred->Branch(not_equal);
 
-    // Check that the key is within bounds.  Both the key and the length of
-    // the JSArray are smis. Use unsigned comparison to handle negative keys.
-    __ cmp(key.reg(),
-           FieldOperand(receiver.reg(), JSArray::kLengthOffset));
-    deferred->Branch(above_equal);
-
     // Get the elements array from the receiver and check that it is not a
     // dictionary.
     __ mov(tmp.reg(),
@@ -9963,12 +9988,20 @@
     // which will allow the debugger to break for fast case stores.
     __ bind(deferred->patch_site());
     __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
-           Immediate(Factory::fixed_array_map()));
+           Immediate(FACTORY->fixed_array_map()));
     deferred->Branch(not_equal);
 
+    // Check that the key is within bounds.  Both the key and the length of
+    // the JSArray are smis (because the fixed array check above ensures the
+    // elements are in fast case). Use unsigned comparison to handle negative
+    // keys.
+    __ cmp(key.reg(),
+           FieldOperand(receiver.reg(), JSArray::kLengthOffset));
+    deferred->Branch(above_equal);
+
     // Store the value.
     __ mov(FixedArrayElementOperand(tmp.reg(), key.reg()), result.reg());
-    __ IncrementCounter(&Counters::keyed_store_inline, 1);
+    __ IncrementCounter(masm_->isolate()->counters()->keyed_store_inline(), 1);
 
     deferred->BindExit();
   } else {
@@ -10171,7 +10204,7 @@
     __ int3();
     __ bind(&ok);
   }
-  if (CpuFeatures::IsSupported(SSE2)) {
+  if (masm.isolate()->cpu_features()->IsSupported(SSE2)) {
     CpuFeatures::Scope enable(SSE2);
     __ push(edi);
     __ push(esi);
@@ -10199,7 +10232,7 @@
     __ test(Operand(src), Immediate(0x0F));
     __ j(not_zero, &unaligned_source);
     {
-      __ IncrementCounter(&Counters::memcopy_aligned, 1);
+      __ IncrementCounter(masm.isolate()->counters()->memcopy_aligned(), 1);
       // Copy loop for aligned source and destination.
       __ mov(edx, count);
       Register loop_count = ecx;
@@ -10247,7 +10280,7 @@
       // Copy loop for unaligned source and aligned destination.
       // If source is not aligned, we can't read it as efficiently.
       __ bind(&unaligned_source);
-      __ IncrementCounter(&Counters::memcopy_unaligned, 1);
+      __ IncrementCounter(masm.isolate()->counters()->memcopy_unaligned(), 1);
       __ mov(edx, ecx);
       Register loop_count = ecx;
       Register count = edx;
@@ -10291,7 +10324,7 @@
     }
 
   } else {
-    __ IncrementCounter(&Counters::memcopy_noxmm, 1);
+    __ IncrementCounter(masm.isolate()->counters()->memcopy_noxmm(), 1);
     // SSE2 not supported. Unlikely to happen in practice.
     __ push(edi);
     __ push(esi);
diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h
index 27e3396..acd651b 100644
--- a/src/ia32/codegen-ia32.h
+++ b/src/ia32/codegen-ia32.h
@@ -365,6 +365,7 @@
   // Accessors
   inline bool is_eval();
   inline Scope* scope();
+  inline bool is_strict_mode();
   inline StrictModeFlag strict_mode_flag();
 
   // Generating deferred code.
@@ -779,6 +780,7 @@
   int jit_cookie_;
 
   friend class VirtualFrame;
+  friend class Isolate;
   friend class JumpTarget;
   friend class Reference;
   friend class Result;
@@ -788,6 +790,7 @@
   friend class LCodeGen;
 
   friend class CodeGeneratorPatcher;  // Used in test-log-stack-tracer.cc
+  friend class InlineRuntimeFunctionsTable;
 
   DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
 };
diff --git a/src/ia32/cpu-ia32.cc b/src/ia32/cpu-ia32.cc
index d64257f..286ed7b 100644
--- a/src/ia32/cpu-ia32.cc
+++ b/src/ia32/cpu-ia32.cc
@@ -42,9 +42,10 @@
 namespace internal {
 
 void CPU::Setup() {
-  CpuFeatures::Clear();
-  CpuFeatures::Probe(true);
-  if (!CpuFeatures::IsSupported(SSE2) || Serializer::enabled()) {
+  CpuFeatures* cpu_features = Isolate::Current()->cpu_features();
+  cpu_features->Clear();
+  cpu_features->Probe(true);
+  if (!cpu_features->IsSupported(SSE2) || Serializer::enabled()) {
     V8::DisableCrankshaft();
   }
 }
diff --git a/src/ia32/debug-ia32.cc b/src/ia32/debug-ia32.cc
index 678cc93..33c5251 100644
--- a/src/ia32/debug-ia32.cc
+++ b/src/ia32/debug-ia32.cc
@@ -49,7 +49,8 @@
 void BreakLocationIterator::SetDebugBreakAtReturn() {
   ASSERT(Assembler::kJSReturnSequenceLength >=
          Assembler::kCallInstructionLength);
-  rinfo()->PatchCodeWithCall(Debug::debug_break_return()->entry(),
+  Isolate* isolate = Isolate::Current();
+  rinfo()->PatchCodeWithCall(isolate->debug()->debug_break_return()->entry(),
       Assembler::kJSReturnSequenceLength - Assembler::kCallInstructionLength);
 }
 
@@ -78,8 +79,9 @@
 
 void BreakLocationIterator::SetDebugBreakAtSlot() {
   ASSERT(IsDebugBreakSlot());
+  Isolate* isolate = Isolate::Current();
   rinfo()->PatchCodeWithCall(
-      Debug::debug_break_slot()->entry(),
+      isolate->debug()->debug_break_slot()->entry(),
       Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength);
 }
 
@@ -126,7 +128,7 @@
   __ RecordComment("// Calling from debug break to runtime - come in - over");
 #endif
   __ Set(eax, Immediate(0));  // No arguments.
-  __ mov(ebx, Immediate(ExternalReference::debug_break()));
+  __ mov(ebx, Immediate(ExternalReference::debug_break(masm->isolate())));
 
   CEntryStub ceb(1);
   __ CallStub(&ceb);
@@ -161,7 +163,7 @@
   // 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());
+      ExternalReference(Debug_Address::AfterBreakTarget(), masm->isolate());
   __ jmp(Operand::StaticVariable(after_break_target));
 }
 
@@ -277,7 +279,8 @@
 
 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
   ExternalReference restarter_frame_function_slot =
-      ExternalReference(Debug_Address::RestarterFrameFunctionPointer());
+      ExternalReference(Debug_Address::RestarterFrameFunctionPointer(),
+                        masm->isolate());
   __ mov(Operand::StaticVariable(restarter_frame_function_slot), Immediate(0));
 
   // We do not know our frame height, but set esp based on ebp.
diff --git a/src/ia32/deoptimizer-ia32.cc b/src/ia32/deoptimizer-ia32.cc
index 5f4d944..c6342d7 100644
--- a/src/ia32/deoptimizer-ia32.cc
+++ b/src/ia32/deoptimizer-ia32.cc
@@ -55,11 +55,89 @@
 }
 
 
-void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
-  AssertNoAllocation no_allocation;
+void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
+  Isolate* isolate = code->GetIsolate();
+  HandleScope scope(isolate);
 
+  // Compute the size of relocation information needed for the code
+  // patching in Deoptimizer::DeoptimizeFunction.
+  int min_reloc_size = 0;
+  Address prev_reloc_address = code->instruction_start();
+  Address code_start_address = code->instruction_start();
+  SafepointTable table(*code);
+  for (unsigned i = 0; i < table.length(); ++i) {
+    Address curr_reloc_address = code_start_address + table.GetPcOffset(i);
+    ASSERT_GE(curr_reloc_address, prev_reloc_address);
+    SafepointEntry safepoint_entry = table.GetEntry(i);
+    int deoptimization_index = safepoint_entry.deoptimization_index();
+    if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
+      // The gap code is needed to get to the state expected at the
+      // bailout and we need to skip the call opcode to get to the
+      // address that needs reloc.
+      curr_reloc_address += safepoint_entry.gap_code_size() + 1;
+      int pc_delta = curr_reloc_address - prev_reloc_address;
+      // We use RUNTIME_ENTRY reloc info which has a size of 2 bytes
+      // if encodable with small pc delta encoding and up to 6 bytes
+      // otherwise.
+      if (pc_delta <= RelocInfo::kMaxSmallPCDelta) {
+        min_reloc_size += 2;
+      } else {
+        min_reloc_size += 6;
+      }
+      prev_reloc_address = curr_reloc_address;
+    }
+  }
+
+  // If the relocation information is not big enough we create a new
+  // relocation info object that is padded with comments to make it
+  // big enough for lazy doptimization.
+  int reloc_length = code->relocation_info()->length();
+  if (min_reloc_size > reloc_length) {
+    int comment_reloc_size = RelocInfo::kMinRelocCommentSize;
+    // Padding needed.
+    int min_padding = min_reloc_size - reloc_length;
+    // Number of comments needed to take up at least that much space.
+    int additional_comments =
+        (min_padding + comment_reloc_size - 1) / comment_reloc_size;
+    // Actual padding size.
+    int padding = additional_comments * comment_reloc_size;
+    // Allocate new relocation info and copy old relocation to the end
+    // of the new relocation info array because relocation info is
+    // written and read backwards.
+    Factory* factory = isolate->factory();
+    Handle<ByteArray> new_reloc =
+        factory->NewByteArray(reloc_length + padding, TENURED);
+    memcpy(new_reloc->GetDataStartAddress() + padding,
+           code->relocation_info()->GetDataStartAddress(),
+           reloc_length);
+    // Create a relocation writer to write the comments in the padding
+    // space. Use position 0 for everything to ensure short encoding.
+    RelocInfoWriter reloc_info_writer(
+        new_reloc->GetDataStartAddress() + padding, 0);
+    intptr_t comment_string
+        = reinterpret_cast<intptr_t>(RelocInfo::kFillerCommentString);
+    RelocInfo rinfo(0, RelocInfo::COMMENT, comment_string);
+    for (int i = 0; i < additional_comments; ++i) {
+#ifdef DEBUG
+      byte* pos_before = reloc_info_writer.pos();
+#endif
+      reloc_info_writer.Write(&rinfo);
+      ASSERT(RelocInfo::kMinRelocCommentSize ==
+             pos_before - reloc_info_writer.pos());
+    }
+    // Replace relocation information on the code object.
+    code->set_relocation_info(*new_reloc);
+  }
+}
+
+
+void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
   if (!function->IsOptimized()) return;
 
+  Isolate* isolate = function->GetIsolate();
+  HandleScope scope(isolate);
+  AssertNoAllocation no_allocation;
+
   // Get the optimized code.
   Code* code = function->code();
   Address code_start_address = code->instruction_start();
@@ -118,12 +196,14 @@
   // a non-live object in the extra space at the end of the former reloc info.
   Address junk_address = reloc_info->address() + reloc_info->Size();
   ASSERT(junk_address <= reloc_end_address);
-  Heap::CreateFillerObjectAt(junk_address, reloc_end_address - junk_address);
+  isolate->heap()->CreateFillerObjectAt(junk_address,
+                                        reloc_end_address - junk_address);
 
   // Add the deoptimizing code to the list.
   DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code);
-  node->set_next(deoptimizing_code_list_);
-  deoptimizing_code_list_ = node;
+  DeoptimizerData* data = isolate->deoptimizer_data();
+  node->set_next(data->deoptimizing_code_list_);
+  data->deoptimizing_code_list_ = node;
 
   // Set the code for the function to non-optimized version.
   function->ReplaceCode(function->shared()->code());
@@ -132,6 +212,11 @@
     PrintF("[forced deoptimization: ");
     function->PrintName();
     PrintF(" / %x]\n", reinterpret_cast<uint32_t>(function));
+#ifdef DEBUG
+    if (FLAG_print_code) {
+      code->PrintLn();
+    }
+#endif
   }
 }
 
@@ -284,13 +369,31 @@
 
   // There are no translation commands for the caller's pc and fp, the
   // context, and the function.  Set them up explicitly.
-  for (int i = 0; ok && i < 4; i++) {
+  for (int i =  StandardFrameConstants::kCallerPCOffset;
+       ok && i >=  StandardFrameConstants::kMarkerOffset;
+       i -= kPointerSize) {
     uint32_t input_value = input_->GetFrameSlot(input_offset);
     if (FLAG_trace_osr) {
-      PrintF("    [esp + %d] <- 0x%08x ; [esp + %d] (fixed part)\n",
+      const char* name = "UNKNOWN";
+      switch (i) {
+        case StandardFrameConstants::kCallerPCOffset:
+          name = "caller's pc";
+          break;
+        case StandardFrameConstants::kCallerFPOffset:
+          name = "fp";
+          break;
+        case StandardFrameConstants::kContextOffset:
+          name = "context";
+          break;
+        case StandardFrameConstants::kMarkerOffset:
+          name = "function";
+          break;
+      }
+      PrintF("    [esp + %d] <- 0x%08x ; [esp + %d] (fixed part - %s)\n",
              output_offset,
              input_value,
-             input_offset);
+             input_offset,
+             name);
     }
     output_[0]->SetFrameSlot(output_offset, input_->GetFrameSlot(input_offset));
     input_offset -= kPointerSize;
@@ -317,7 +420,8 @@
         optimized_code_->entry() + pc_offset);
     output_[0]->SetPc(pc);
   }
-  Code* continuation = Builtins::builtin(Builtins::NotifyOSR);
+  Code* continuation =
+      function->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR);
   output_[0]->SetContinuation(
       reinterpret_cast<uint32_t>(continuation->entry()));
 
@@ -484,9 +588,10 @@
 
   // Set the continuation for the topmost frame.
   if (is_topmost) {
+    Builtins* builtins = isolate_->builtins();
     Code* continuation = (bailout_type_ == EAGER)
-        ? Builtins::builtin(Builtins::NotifyDeoptimized)
-        : Builtins::builtin(Builtins::NotifyLazyDeoptimized);
+        ? builtins->builtin(Builtins::kNotifyDeoptimized)
+        : builtins->builtin(Builtins::kNotifyLazyDeoptimized);
     output_frame->SetContinuation(
         reinterpret_cast<uint32_t>(continuation->entry()));
   }
@@ -501,6 +606,8 @@
   GeneratePrologue();
   CpuFeatures::Scope scope(SSE2);
 
+  Isolate* isolate = masm()->isolate();
+
   // Save all general purpose registers before messing with them.
   const int kNumberOfRegisters = Register::kNumRegisters;
 
@@ -541,7 +648,7 @@
   __ mov(Operand(esp, 2 * kPointerSize), ebx);  // Bailout id.
   __ mov(Operand(esp, 3 * kPointerSize), ecx);  // Code address or 0.
   __ mov(Operand(esp, 4 * kPointerSize), edx);  // Fp-to-sp delta.
-  __ CallCFunction(ExternalReference::new_deoptimizer_function(), 5);
+  __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate), 5);
 
   // Preserve deoptimizer object in register eax and get the input
   // frame descriptor pointer.
@@ -589,7 +696,8 @@
   __ push(eax);
   __ PrepareCallCFunction(1, ebx);
   __ mov(Operand(esp, 0 * kPointerSize), eax);
-  __ CallCFunction(ExternalReference::compute_output_frames_function(), 1);
+  __ CallCFunction(
+      ExternalReference::compute_output_frames_function(isolate), 1);
   __ pop(eax);
 
   // Replace the current frame with the output frames.
diff --git a/src/ia32/disasm-ia32.cc b/src/ia32/disasm-ia32.cc
index e0cbe35..d1c869a 100644
--- a/src/ia32/disasm-ia32.cc
+++ b/src/ia32/disasm-ia32.cc
@@ -331,6 +331,7 @@
   int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name);
   int PrintRightOperand(byte* modrmp);
   int PrintRightByteOperand(byte* modrmp);
+  int PrintRightXMMOperand(byte* modrmp);
   int PrintOperands(const char* mnem, OperandOrder op_order, byte* data);
   int PrintImmediateOp(byte* data);
   int F7Instruction(byte* data);
@@ -367,9 +368,11 @@
 
 int DisassemblerIA32::PrintRightOperandHelper(
     byte* modrmp,
-    RegisterNameMapping register_name) {
+    RegisterNameMapping direct_register_name) {
   int mod, regop, rm;
   get_modrm(*modrmp, &mod, &regop, &rm);
+  RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
+      &DisassemblerIA32::NameOfCPURegister;
   switch (mod) {
     case 0:
       if (rm == ebp) {
@@ -454,6 +457,12 @@
 }
 
 
+int DisassemblerIA32::PrintRightXMMOperand(byte* modrmp) {
+  return PrintRightOperandHelper(modrmp,
+                                 &DisassemblerIA32::NameOfXMMRegister);
+}
+
+
 // 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,
@@ -937,7 +946,7 @@
           get_modrm(*data, &mod, &regop, &rm);
           if (regop == eax) {
             AppendToBuffer("test_b ");
-            data += PrintRightOperand(data);
+            data += PrintRightByteOperand(data);
             int32_t imm = *data;
             AppendToBuffer(",0x%x", imm);
             data++;
@@ -1035,11 +1044,19 @@
       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;
+          if (is_byte) {
+            AppendToBuffer("%s ", "mov_b");
+            data += PrintRightByteOperand(data);
+            int32_t imm = *data;
+            AppendToBuffer(",0x%x", imm);
+            data++;
+          } else {
+            AppendToBuffer("%s ", "mov");
+            data += PrintRightOperand(data);
+            int32_t imm = *reinterpret_cast<int32_t*>(data);
+            AppendToBuffer(",0x%x", imm);
+            data += 4;
+          }
         }
         break;
 
@@ -1054,7 +1071,7 @@
             default: UnimplementedInstruction();
           }
           AppendToBuffer("%s ", mnem);
-          data += PrintRightOperand(data);
+          data += PrintRightByteOperand(data);
           int32_t imm = *data;
           AppendToBuffer(",0x%x", imm);
           data++;
@@ -1067,9 +1084,15 @@
           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));
+          if (is_byte) {
+            AppendToBuffer("%s ", "mov_b");
+            data += PrintRightByteOperand(data);
+            AppendToBuffer(",%s", NameOfByteCPURegister(regop));
+          } else {
+            AppendToBuffer("%s ", "mov");
+            data += PrintRightOperand(data);
+            AppendToBuffer(",%s", NameOfCPURegister(regop));
+          }
         }
         break;
 
@@ -1181,7 +1204,7 @@
             int mod, regop, rm;
             get_modrm(*data, &mod, &regop, &rm);
             AppendToBuffer("movdqa %s,", NameOfXMMRegister(regop));
-            data += PrintRightOperand(data);
+            data += PrintRightXMMOperand(data);
           } else if (*data == 0x70) {
             data++;
             int mod, regop, rm;
@@ -1224,7 +1247,7 @@
             data++;
             int mod, regop, rm;
             get_modrm(*data, &mod, &regop, &rm);
-            data += PrintRightOperand(data);
+            data += PrintRightXMMOperand(data);
             AppendToBuffer(",%s", NameOfXMMRegister(regop));
           } else if (*data == 0x7E) {
             data++;
@@ -1242,12 +1265,16 @@
                            NameOfXMMRegister(rm));
             data++;
           } else if (*data == 0xE7) {
-            AppendToBuffer("movntdq ");
             data++;
             int mod, regop, rm;
             get_modrm(*data, &mod, &regop, &rm);
-            data += PrintRightOperand(data);
-            AppendToBuffer(",%s", NameOfXMMRegister(regop));
+            if (mod == 3) {
+              AppendToBuffer("movntdq ");
+              data += PrintRightOperand(data);
+              AppendToBuffer(",%s", NameOfXMMRegister(regop));
+            } else {
+              UnimplementedInstruction();
+            }
           } else if (*data == 0xEF) {
             data++;
             int mod, regop, rm;
@@ -1338,14 +1365,20 @@
             data += 3;
             int mod, regop, rm;
             get_modrm(*data, &mod, &regop, &rm);
-            data += PrintRightOperand(data);
+            data += PrintRightXMMOperand(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);
+            data += PrintRightXMMOperand(data);
+          } else  if (b2 == 0x5A) {
+            data += 3;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("cvtsd2ss %s,", NameOfXMMRegister(regop));
+            data += PrintRightXMMOperand(data);
           } else {
             const char* mnem = "?";
             switch (b2) {
@@ -1361,27 +1394,11 @@
             int mod, regop, rm;
             get_modrm(*data, &mod, &regop, &rm);
             if (b2 == 0x2A) {
-              if (mod != 0x3) {
-                AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
-                data += PrintRightOperand(data);
-              } else {
-                AppendToBuffer("%s %s,%s",
-                               mnem,
-                               NameOfXMMRegister(regop),
-                               NameOfCPURegister(rm));
-                data++;
-              }
+              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
+              data += PrintRightOperand(data);
             } else if (b2 == 0x2C) {
-              if (mod != 0x3) {
-                AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
-                data += PrintRightOperand(data);
-              } else {
-                AppendToBuffer("%s %s,%s",
-                               mnem,
-                               NameOfCPURegister(regop),
-                               NameOfXMMRegister(rm));
-                data++;
-              }
+              AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
+              data += PrintRightXMMOperand(data);
             } else if (b2 == 0xC2) {
               // Intel manual 2A, Table 3-18.
               const char* const pseudo_op[] = {
@@ -1400,16 +1417,8 @@
                              NameOfXMMRegister(rm));
               data += 2;
             } else {
-              if (mod != 0x3) {
-                AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
-                data += PrintRightOperand(data);
-              } else {
-                AppendToBuffer("%s %s,%s",
-                               mnem,
-                               NameOfXMMRegister(regop),
-                               NameOfXMMRegister(rm));
-                data++;
-              }
+              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
+              data += PrintRightXMMOperand(data);
             }
           }
         } else {
@@ -1419,29 +1428,44 @@
 
       case 0xF3:
         if (*(data+1) == 0x0F) {
-          if (*(data+2) == 0x2C) {
-            data += 3;
-            data += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, data);
-          } else  if (*(data+2) == 0x5A) {
+          byte b2 = *(data+2);
+          if (b2 == 0x11) {
+            AppendToBuffer("movss ");
             data += 3;
             int mod, regop, rm;
             get_modrm(*data, &mod, &regop, &rm);
-            AppendToBuffer("cvtss2sd %s,%s",
-                           NameOfXMMRegister(regop),
-                           NameOfXMMRegister(rm));
-            data++;
-          } else  if (*(data+2) == 0x6F) {
+            data += PrintRightXMMOperand(data);
+            AppendToBuffer(",%s", NameOfXMMRegister(regop));
+          } else if (b2 == 0x10) {
+            data += 3;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("movss %s,", NameOfXMMRegister(regop));
+            data += PrintRightXMMOperand(data);
+          } else if (b2 == 0x2C) {
+            data += 3;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("cvttss2si %s,", NameOfCPURegister(regop));
+            data += PrintRightXMMOperand(data);
+          } else if (b2 == 0x5A) {
+            data += 3;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
+            data += PrintRightXMMOperand(data);
+          } else  if (b2 == 0x6F) {
             data += 3;
             int mod, regop, rm;
             get_modrm(*data, &mod, &regop, &rm);
             AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop));
-            data += PrintRightOperand(data);
-          } else  if (*(data+2) == 0x7F) {
+            data += PrintRightXMMOperand(data);
+          } else  if (b2 == 0x7F) {
             AppendToBuffer("movdqu ");
             data += 3;
             int mod, regop, rm;
             get_modrm(*data, &mod, &regop, &rm);
-            data += PrintRightOperand(data);
+            data += PrintRightXMMOperand(data);
             AppendToBuffer(",%s", NameOfXMMRegister(regop));
           } else {
             UnimplementedInstruction();
@@ -1514,9 +1538,8 @@
 
 
 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();
+  v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
+  return tmp_buffer_.start();
 }
 
 
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 9a7d41a..16c39c5 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -129,9 +129,9 @@
   { Comment cmnt(masm_, "[ Allocate locals");
     int locals_count = scope()->num_stack_slots();
     if (locals_count == 1) {
-      __ push(Immediate(Factory::undefined_value()));
+      __ push(Immediate(isolate()->factory()->undefined_value()));
     } else if (locals_count > 1) {
-      __ mov(eax, Immediate(Factory::undefined_value()));
+      __ mov(eax, Immediate(isolate()->factory()->undefined_value()));
       for (int i = 0; i < locals_count; i++) {
         __ push(eax);
       }
@@ -197,12 +197,17 @@
     //   function, receiver address, parameter count.
     // The stub will rewrite receiver and parameter count if the previous
     // stack frame was an arguments adapter frame.
-    ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
+    ArgumentsAccessStub stub(
+        is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT
+                         : ArgumentsAccessStub::NEW_NON_STRICT);
     __ CallStub(&stub);
-    __ mov(ecx, eax);  // Duplicate result.
+
+    Variable* arguments_shadow = scope()->arguments_shadow();
+    if (arguments_shadow != NULL) {
+      __ mov(ecx, eax);  // Duplicate result.
+      Move(arguments_shadow->AsSlot(), ecx, ebx, edx);
+    }
     Move(arguments->AsSlot(), eax, ebx, edx);
-    Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot();
-    Move(dot_arguments_slot, ecx, ebx, edx);
   }
 
   if (FLAG_trace) {
@@ -229,7 +234,7 @@
       PrepareForBailout(info->function(), NO_REGISTERS);
       NearLabel ok;
       ExternalReference stack_limit =
-          ExternalReference::address_of_stack_limit();
+          ExternalReference::address_of_stack_limit(isolate());
       __ cmp(esp, Operand::StaticVariable(stack_limit));
       __ j(above_equal, &ok, taken);
       StackCheckStub stub;
@@ -247,7 +252,7 @@
   // Always emit a 'return undefined' in case control fell off the end of
   // the body.
   { Comment cmnt(masm_, "[ return <undefined>;");
-    __ mov(eax, Factory::undefined_value());
+    __ mov(eax, isolate()->factory()->undefined_value());
     EmitReturnSequence();
   }
 }
@@ -261,7 +266,8 @@
 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) {
   Comment cmnt(masm_, "[ Stack check");
   NearLabel ok;
-  ExternalReference stack_limit = ExternalReference::address_of_stack_limit();
+  ExternalReference stack_limit =
+      ExternalReference::address_of_stack_limit(isolate());
   __ cmp(esp, Operand::StaticVariable(stack_limit));
   __ j(above_equal, &ok, taken);
   StackCheckStub stub;
@@ -462,10 +468,10 @@
     Label* materialize_false) const {
   NearLabel done;
   __ bind(materialize_true);
-  __ mov(result_register(), Factory::true_value());
+  __ mov(result_register(), isolate()->factory()->true_value());
   __ jmp(&done);
   __ bind(materialize_false);
-  __ mov(result_register(), Factory::false_value());
+  __ mov(result_register(), isolate()->factory()->false_value());
   __ bind(&done);
 }
 
@@ -475,10 +481,10 @@
     Label* materialize_false) const {
   NearLabel done;
   __ bind(materialize_true);
-  __ push(Immediate(Factory::true_value()));
+  __ push(Immediate(isolate()->factory()->true_value()));
   __ jmp(&done);
   __ bind(materialize_false);
-  __ push(Immediate(Factory::false_value()));
+  __ push(Immediate(isolate()->factory()->false_value()));
   __ bind(&done);
 }
 
@@ -495,15 +501,17 @@
 
 
 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
-  Handle<Object> value =
-      flag ? Factory::true_value() : Factory::false_value();
+  Handle<Object> value = flag
+      ? isolate()->factory()->true_value()
+      : isolate()->factory()->false_value();
   __ mov(result_register(), value);
 }
 
 
 void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
-  Handle<Object> value =
-      flag ? Factory::true_value() : Factory::false_value();
+  Handle<Object> value = flag
+      ? isolate()->factory()->true_value()
+      : isolate()->factory()->false_value();
   __ push(Immediate(value));
 }
 
@@ -525,11 +533,11 @@
                                Label* if_false,
                                Label* fall_through) {
   // Emit the inlined tests assumed by the stub.
-  __ cmp(result_register(), Factory::undefined_value());
+  __ cmp(result_register(), isolate()->factory()->undefined_value());
   __ j(equal, if_false);
-  __ cmp(result_register(), Factory::true_value());
+  __ cmp(result_register(), isolate()->factory()->true_value());
   __ j(equal, if_true);
-  __ cmp(result_register(), Factory::false_value());
+  __ cmp(result_register(), isolate()->factory()->false_value());
   __ j(equal, if_false);
   STATIC_ASSERT(kSmiTag == 0);
   __ test(result_register(), Operand(result_register()));
@@ -624,7 +632,7 @@
   }
 
   if (should_normalize) {
-    __ cmp(eax, Factory::true_value());
+    __ cmp(eax, isolate()->factory()->true_value());
     Split(equal, if_true, if_false, NULL);
     __ bind(&skip);
   }
@@ -645,7 +653,7 @@
       case Slot::LOCAL:
         if (mode == Variable::CONST) {
           __ mov(Operand(ebp, SlotOffset(slot)),
-                 Immediate(Factory::the_hole_value()));
+                 Immediate(isolate()->factory()->the_hole_value()));
         } else if (function != NULL) {
           VisitForAccumulatorValue(function);
           __ mov(Operand(ebp, SlotOffset(slot)), result_register());
@@ -667,7 +675,7 @@
         }
         if (mode == Variable::CONST) {
           __ mov(ContextOperand(esi, slot->index()),
-                 Immediate(Factory::the_hole_value()));
+                 Immediate(isolate()->factory()->the_hole_value()));
           // No write barrier since the hole value is in old space.
         } else if (function != NULL) {
           VisitForAccumulatorValue(function);
@@ -690,7 +698,7 @@
         // 'undefined') because we may have a (legal) redeclaration and we
         // must not destroy the current value.
         if (mode == Variable::CONST) {
-          __ push(Immediate(Factory::the_hole_value()));
+          __ push(Immediate(isolate()->factory()->the_hole_value()));
         } else if (function != NULL) {
           VisitForStackValue(function);
         } else {
@@ -718,15 +726,15 @@
         __ pop(edx);
       } else {
         __ mov(edx, eax);
-        __ mov(eax, Factory::the_hole_value());
+        __ mov(eax, isolate()->factory()->the_hole_value());
       }
       ASSERT(prop->key()->AsLiteral() != NULL &&
              prop->key()->AsLiteral()->handle()->IsSmi());
       __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle()));
 
-      Handle<Code> ic(Builtins::builtin(is_strict()
-          ? Builtins::KeyedStoreIC_Initialize_Strict
-          : Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic = is_strict_mode()
+          ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+          : isolate()->builtins()->KeyedStoreIC_Initialize();
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
     }
   }
@@ -822,6 +830,7 @@
     Comment cmnt(masm_, "[ Case body");
     CaseClause* clause = clauses->at(i);
     __ bind(clause->body_target()->entry_label());
+    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
     VisitStatements(clause->statements());
   }
 
@@ -842,9 +851,9 @@
   // ignore null and undefined in contrast to the specification; see
   // ECMA-262 section 12.6.4.
   VisitForAccumulatorValue(stmt->enumerable());
-  __ cmp(eax, Factory::undefined_value());
+  __ cmp(eax, isolate()->factory()->undefined_value());
   __ j(equal, &exit);
-  __ cmp(eax, Factory::null_value());
+  __ cmp(eax, isolate()->factory()->null_value());
   __ j(equal, &exit);
 
   // Convert the object to a JS object.
@@ -870,7 +879,7 @@
   // Check that there are no elements.  Register ecx contains the
   // current JS object we've reached through the prototype chain.
   __ cmp(FieldOperand(ecx, JSObject::kElementsOffset),
-         Factory::empty_fixed_array());
+         isolate()->factory()->empty_fixed_array());
   __ j(not_equal, &call_runtime);
 
   // Check that instance descriptors are not empty so that we can
@@ -878,7 +887,7 @@
   // prototype load.
   __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
   __ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOffset));
-  __ cmp(edx, Factory::empty_descriptor_array());
+  __ cmp(edx, isolate()->factory()->empty_descriptor_array());
   __ j(equal, &call_runtime);
 
   // Check that there is an enum cache in the non-empty instance
@@ -893,13 +902,13 @@
   __ cmp(ecx, Operand(eax));
   __ j(equal, &check_prototype);
   __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset));
-  __ cmp(edx, Factory::empty_fixed_array());
+  __ cmp(edx, isolate()->factory()->empty_fixed_array());
   __ j(not_equal, &call_runtime);
 
   // Load the prototype from the map and loop if non-null.
   __ bind(&check_prototype);
   __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
-  __ cmp(ecx, Factory::null_value());
+  __ cmp(ecx, isolate()->factory()->null_value());
   __ j(not_equal, &next);
 
   // The enum cache is valid.  Load the map of the object being
@@ -917,7 +926,8 @@
   // modification check. Otherwise, we got a fixed array, and we have
   // to do a slow check.
   NearLabel fixed_array;
-  __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::meta_map());
+  __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
+         isolate()->factory()->meta_map());
   __ j(not_equal, &fixed_array);
 
   // We got a map in register eax. Get the enumeration cache from it.
@@ -1013,18 +1023,18 @@
   // doesn't just get a copy of the existing unoptimized code.
   if (!FLAG_always_opt &&
       !FLAG_prepare_always_opt &&
+      !pretenure &&
       scope()->is_function_scope() &&
-      info->num_literals() == 0 &&
-      !pretenure) {
-    FastNewClosureStub stub;
+      info->num_literals() == 0) {
+    FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode);
     __ push(Immediate(info));
     __ CallStub(&stub);
   } else {
     __ push(esi);
     __ push(Immediate(info));
     __ push(Immediate(pretenure
-                      ? Factory::true_value()
-                      : Factory::false_value()));
+                      ? isolate()->factory()->true_value()
+                      : isolate()->factory()->false_value()));
     __ CallRuntime(Runtime::kNewClosure, 3);
   }
   context()->Plug(eax);
@@ -1076,7 +1086,7 @@
     __ bind(&next);
     // Terminate at global context.
     __ cmp(FieldOperand(temp, HeapObject::kMapOffset),
-           Immediate(Factory::global_context_map()));
+           Immediate(isolate()->factory()->global_context_map()));
     __ j(equal, &fast);
     // Check that extension is NULL.
     __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
@@ -1092,7 +1102,7 @@
   // load IC call.
   __ mov(eax, GlobalObjectOperand());
   __ mov(ecx, slot->var()->name());
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
       ? RelocInfo::CODE_TARGET
       : RelocInfo::CODE_TARGET_CONTEXT;
@@ -1153,9 +1163,9 @@
       __ mov(eax,
              ContextSlotOperandCheckExtensions(potential_slot, slow));
       if (potential_slot->var()->mode() == Variable::CONST) {
-        __ cmp(eax, Factory::the_hole_value());
+        __ cmp(eax, isolate()->factory()->the_hole_value());
         __ j(not_equal, done);
-        __ mov(eax, Factory::undefined_value());
+        __ mov(eax, isolate()->factory()->undefined_value());
       }
       __ jmp(done);
     } else if (rewrite != NULL) {
@@ -1175,7 +1185,8 @@
                  ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
                                                    slow));
           __ mov(eax, Immediate(key_literal->handle()));
-          Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+          Handle<Code> ic =
+              isolate()->builtins()->KeyedLoadIC_Initialize();
           EmitCallIC(ic, RelocInfo::CODE_TARGET);
           __ jmp(done);
         }
@@ -1198,7 +1209,7 @@
     // object on the stack.
     __ mov(eax, GlobalObjectOperand());
     __ mov(ecx, var->name());
-    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
     EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
     context()->Plug(eax);
 
@@ -1228,9 +1239,9 @@
       NearLabel done;
       MemOperand slot_operand = EmitSlotSearch(slot, eax);
       __ mov(eax, slot_operand);
-      __ cmp(eax, Factory::the_hole_value());
+      __ cmp(eax, isolate()->factory()->the_hole_value());
       __ j(not_equal, &done);
-      __ mov(eax, Factory::undefined_value());
+      __ mov(eax, isolate()->factory()->undefined_value());
       __ bind(&done);
       context()->Plug(eax);
     } else {
@@ -1261,7 +1272,7 @@
     __ mov(eax, Immediate(key_literal->handle()));
 
     // Do a keyed property load.
-    Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+    Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
     EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
     // Drop key and object left on the stack by IC.
@@ -1283,7 +1294,7 @@
   int literal_offset =
       FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
   __ mov(ebx, FieldOperand(ecx, literal_offset));
-  __ cmp(ebx, Factory::undefined_value());
+  __ cmp(ebx, isolate()->factory()->undefined_value());
   __ j(not_equal, &materialized);
 
   // Create regexp literal using runtime function
@@ -1330,7 +1341,13 @@
   __ push(FieldOperand(edi, JSFunction::kLiteralsOffset));
   __ push(Immediate(Smi::FromInt(expr->literal_index())));
   __ push(Immediate(expr->constant_properties()));
-  __ push(Immediate(Smi::FromInt(expr->fast_elements() ? 1 : 0)));
+  int flags = expr->fast_elements()
+      ? ObjectLiteral::kFastElements
+      : ObjectLiteral::kNoFlags;
+  flags |= expr->has_function()
+      ? ObjectLiteral::kHasFunction
+      : ObjectLiteral::kNoFlags;
+  __ push(Immediate(Smi::FromInt(flags)));
   if (expr->depth() > 1) {
     __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
   } else {
@@ -1366,9 +1383,9 @@
             VisitForAccumulatorValue(value);
             __ mov(ecx, Immediate(key->handle()));
             __ mov(edx, Operand(esp, 0));
-            Handle<Code> ic(Builtins::builtin(
-                is_strict() ? Builtins::StoreIC_Initialize_Strict
-                            : Builtins::StoreIC_Initialize));
+            Handle<Code> ic = is_strict_mode()
+                ? isolate()->builtins()->StoreIC_Initialize_Strict()
+                : isolate()->builtins()->StoreIC_Initialize();
             EmitCallIC(ic, RelocInfo::CODE_TARGET);
             PrepareForBailoutForId(key->id(), NO_REGISTERS);
           } else {
@@ -1402,6 +1419,12 @@
     }
   }
 
+  if (expr->has_function()) {
+    ASSERT(result_saved);
+    __ push(Operand(esp, 0));
+    __ CallRuntime(Runtime::kToFastProperties, 1);
+  }
+
   if (result_saved) {
     context()->PlugTOS();
   } else {
@@ -1420,12 +1443,13 @@
   __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
   __ push(Immediate(Smi::FromInt(expr->literal_index())));
   __ push(Immediate(expr->constant_elements()));
-  if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) {
+  if (expr->constant_elements()->map() ==
+      isolate()->heap()->fixed_cow_array_map()) {
     ASSERT(expr->depth() == 1);
     FastCloneShallowArrayStub stub(
         FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
     __ CallStub(&stub);
-    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1);
+    __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), 1);
   } else if (expr->depth() > 1) {
     __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
   } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
@@ -1610,14 +1634,14 @@
   SetSourcePosition(prop->position());
   Literal* key = prop->key()->AsLiteral();
   __ mov(ecx, Immediate(key->handle()));
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 }
 
 
 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
   SetSourcePosition(prop->position());
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 }
 
@@ -1758,9 +1782,9 @@
       __ mov(edx, eax);
       __ pop(eax);  // Restore value.
       __ mov(ecx, prop->key()->AsLiteral()->handle());
-      Handle<Code> ic(Builtins::builtin(
-          is_strict() ? Builtins::StoreIC_Initialize_Strict
-                      : Builtins::StoreIC_Initialize));
+      Handle<Code> ic = is_strict_mode()
+          ? isolate()->builtins()->StoreIC_Initialize_Strict()
+          : isolate()->builtins()->StoreIC_Initialize();
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
@@ -1781,9 +1805,9 @@
         __ pop(edx);
       }
       __ pop(eax);  // Restore value.
-      Handle<Code> ic(Builtins::builtin(
-          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
-                      : Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic = is_strict_mode()
+          ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+          : isolate()->builtins()->KeyedStoreIC_Initialize();
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
@@ -1807,9 +1831,9 @@
     // ecx, and the global object on the stack.
     __ mov(ecx, var->name());
     __ mov(edx, GlobalObjectOperand());
-    Handle<Code> ic(Builtins::builtin(
-        is_strict() ? Builtins::StoreIC_Initialize_Strict
-                    : Builtins::StoreIC_Initialize));
+    Handle<Code> ic = is_strict_mode()
+        ? isolate()->builtins()->StoreIC_Initialize_Strict()
+        : isolate()->builtins()->StoreIC_Initialize();
     EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
 
   } else if (op == Token::INIT_CONST) {
@@ -1826,14 +1850,14 @@
         break;
       case Slot::LOCAL:
         __ mov(edx, Operand(ebp, SlotOffset(slot)));
-        __ cmp(edx, Factory::the_hole_value());
+        __ cmp(edx, isolate()->factory()->the_hole_value());
         __ j(not_equal, &skip);
         __ mov(Operand(ebp, SlotOffset(slot)), eax);
         break;
       case Slot::CONTEXT: {
         __ mov(ecx, ContextOperand(esi, Context::FCONTEXT_INDEX));
         __ mov(edx, ContextOperand(ecx, slot->index()));
-        __ cmp(edx, Factory::the_hole_value());
+        __ cmp(edx, isolate()->factory()->the_hole_value());
         __ j(not_equal, &skip);
         __ mov(ContextOperand(ecx, slot->index()), eax);
         int offset = Context::SlotOffset(slot->index());
@@ -1910,9 +1934,9 @@
   } else {
     __ pop(edx);
   }
-  Handle<Code> ic(Builtins::builtin(
-      is_strict() ? Builtins::StoreIC_Initialize_Strict
-                  : Builtins::StoreIC_Initialize));
+  Handle<Code> ic = is_strict_mode()
+      ? isolate()->builtins()->StoreIC_Initialize_Strict()
+      : isolate()->builtins()->StoreIC_Initialize();
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -1950,9 +1974,9 @@
   }
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
-  Handle<Code> ic(Builtins::builtin(
-      is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
-                  : Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic = is_strict_mode()
+      ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+      : isolate()->builtins()->KeyedStoreIC_Initialize();
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -2002,7 +2026,8 @@
   // Record source position of the IC call.
   SetSourcePosition(expr->position());
   InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
+  Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(
+      arg_count, in_loop);
   EmitCallIC(ic, mode);
   RecordJSReturnSite(expr);
   // Restore context register.
@@ -2034,7 +2059,8 @@
   // Record source position of the IC call.
   SetSourcePosition(expr->position());
   InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
+  Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(
+      arg_count, in_loop);
   __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize));  // Key.
   EmitCallIC(ic, mode);
   RecordJSReturnSite(expr);
@@ -2071,7 +2097,7 @@
   if (arg_count > 0) {
     __ push(Operand(esp, arg_count * kPointerSize));
   } else {
-    __ push(Immediate(Factory::undefined_value()));
+    __ push(Immediate(isolate()->factory()->undefined_value()));
   }
 
   // Push the receiver of the enclosing function.
@@ -2107,7 +2133,7 @@
     { PreservePositionScope pos_scope(masm()->positions_recorder());
       VisitForStackValue(fun);
       // Reserved receiver slot.
-      __ push(Immediate(Factory::undefined_value()));
+      __ push(Immediate(isolate()->factory()->undefined_value()));
 
       // Push the arguments.
       for (int i = 0; i < arg_count; i++) {
@@ -2226,7 +2252,7 @@
         // Record source code position for IC call.
         SetSourcePosition(prop->position());
 
-        Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+        Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
         EmitCallIC(ic, RelocInfo::CODE_TARGET);
         // Push result (function).
         __ push(eax);
@@ -2247,7 +2273,7 @@
     // also use the full code generator.
     FunctionLiteral* lit = fun->AsFunctionLiteral();
     if (lit != NULL &&
-        lit->name()->Equals(Heap::empty_string()) &&
+        lit->name()->Equals(isolate()->heap()->empty_string()) &&
         loop_depth() == 0) {
       lit->set_try_full_codegen(true);
     }
@@ -2294,7 +2320,8 @@
   __ Set(eax, Immediate(arg_count));
   __ mov(edi, Operand(esp, arg_count * kPointerSize));
 
-  Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
+  Handle<Code> construct_builtin =
+      isolate()->builtins()->JSConstructCall();
   __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
   context()->Plug(eax);
 }
@@ -2354,7 +2381,7 @@
 
   __ test(eax, Immediate(kSmiTagMask));
   __ j(zero, if_false);
-  __ cmp(eax, Factory::null_value());
+  __ cmp(eax, isolate()->factory()->null_value());
   __ j(equal, if_true);
   __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
   // Undetectable objects behave like undefined when tested with typeof.
@@ -2633,17 +2660,17 @@
 
   // Functions have class 'Function'.
   __ bind(&function);
-  __ mov(eax, Factory::function_class_symbol());
+  __ mov(eax, isolate()->factory()->function_class_symbol());
   __ jmp(&done);
 
   // Objects with a non-function constructor have class 'Object'.
   __ bind(&non_function_constructor);
-  __ mov(eax, Factory::Object_symbol());
+  __ mov(eax, isolate()->factory()->Object_symbol());
   __ jmp(&done);
 
   // Non-JS objects have class null.
   __ bind(&null);
-  __ mov(eax, Factory::null_value());
+  __ mov(eax, isolate()->factory()->null_value());
 
   // All done.
   __ bind(&done);
@@ -2669,7 +2696,7 @@
   }
 #endif
   // Finally, we're expected to leave a value on the top of the stack.
-  __ mov(eax, Factory::undefined_value());
+  __ mov(eax, isolate()->factory()->undefined_value());
   context()->Plug(eax);
 }
 
@@ -2691,13 +2718,14 @@
   __ bind(&heapnumber_allocated);
 
   __ PrepareCallCFunction(0, ebx);
-  __ CallCFunction(ExternalReference::random_uint32_function(), 0);
+  __ CallCFunction(ExternalReference::random_uint32_function(isolate()),
+                   0);
 
   // Convert 32 random bits in eax to 0.(32 random bits) in a double
   // by computing:
   // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
   // This is implemented on both SSE2 and FPU.
-  if (CpuFeatures::IsSupported(SSE2)) {
+  if (isolate()->cpu_features()->IsSupported(SSE2)) {
     CpuFeatures::Scope fscope(SSE2);
     __ mov(ebx, Immediate(0x49800000));  // 1.0 x 2^20 as single.
     __ movd(xmm1, Operand(ebx));
@@ -2772,8 +2800,12 @@
   VisitForStackValue(args->at(0));
   VisitForStackValue(args->at(1));
 
-  MathPowStub stub;
-  __ CallStub(&stub);
+  if (isolate()->cpu_features()->IsSupported(SSE2)) {
+    MathPowStub stub;
+    __ CallStub(&stub);
+  } else {
+    __ CallRuntime(Runtime::kMath_pow, 2);
+  }
   context()->Plug(eax);
 }
 
@@ -2866,13 +2898,13 @@
   __ bind(&index_out_of_range);
   // When the index is out of range, the spec requires us to return
   // NaN.
-  __ Set(result, Immediate(Factory::nan_value()));
+  __ Set(result, Immediate(isolate()->factory()->nan_value()));
   __ jmp(&done);
 
   __ bind(&need_conversion);
   // Move the undefined value into the result register, which will
   // trigger conversion.
-  __ Set(result, Immediate(Factory::undefined_value()));
+  __ Set(result, Immediate(isolate()->factory()->undefined_value()));
   __ jmp(&done);
 
   NopRuntimeCallHelper call_helper;
@@ -2915,7 +2947,7 @@
   __ bind(&index_out_of_range);
   // When the index is out of range, the spec requires us to return
   // the empty string.
-  __ Set(result, Immediate(Factory::empty_string()));
+  __ Set(result, Immediate(isolate()->factory()->empty_string()));
   __ jmp(&done);
 
   __ bind(&need_conversion);
@@ -3045,8 +3077,8 @@
   // Fetch the map and check if array is in fast case.
   // Check that object doesn't require security checks and
   // has no indexed interceptor.
-  __ CmpObjectType(object, FIRST_JS_OBJECT_TYPE, temp);
-  __ j(below, &slow_case);
+  __ CmpObjectType(object, JS_ARRAY_TYPE, temp);
+  __ j(not_equal, &slow_case);
   __ test_b(FieldOperand(temp, Map::kBitFieldOffset),
             KeyedLoadIC::kSlowCaseBitFieldMask);
   __ j(not_zero, &slow_case);
@@ -3054,7 +3086,7 @@
   // Check the object's elements are in fast case and writable.
   __ mov(elements, FieldOperand(object, JSObject::kElementsOffset));
   __ cmp(FieldOperand(elements, HeapObject::kMapOffset),
-         Immediate(Factory::fixed_array_map()));
+         Immediate(isolate()->factory()->fixed_array_map()));
   __ j(not_equal, &slow_case);
 
   // Check that both indices are smis.
@@ -3092,7 +3124,7 @@
   __ bind(&new_space);
   // We are done. Drop elements from the stack, and return undefined.
   __ add(Operand(esp), Immediate(3 * kPointerSize));
-  __ mov(eax, Factory::undefined_value());
+  __ mov(eax, isolate()->factory()->undefined_value());
   __ jmp(&done);
 
   __ bind(&slow_case);
@@ -3110,10 +3142,10 @@
   int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
 
   Handle<FixedArray> jsfunction_result_caches(
-      Top::global_context()->jsfunction_result_caches());
+      isolate()->global_context()->jsfunction_result_caches());
   if (jsfunction_result_caches->length() <= cache_id) {
     __ Abort("Attempt to use undefined cache.");
-    __ mov(eax, Factory::undefined_value());
+    __ mov(eax, isolate()->factory()->undefined_value());
     context()->Plug(eax);
     return;
   }
@@ -3170,7 +3202,8 @@
   __ and_(Operand(tmp), right);
   __ test(Operand(tmp), Immediate(kSmiTagMask));
   __ j(zero, &fail);
-  __ CmpObjectType(left, JS_REGEXP_TYPE, tmp);
+  __ mov(tmp, FieldOperand(left, HeapObject::kMapOffset));
+  __ CmpInstanceType(tmp, JS_REGEXP_TYPE);
   __ j(not_equal, &fail);
   __ cmp(tmp, FieldOperand(right, HeapObject::kMapOffset));
   __ j(not_equal, &fail);
@@ -3178,10 +3211,10 @@
   __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset));
   __ j(equal, &ok);
   __ bind(&fail);
-  __ mov(eax, Immediate(Factory::false_value()));
+  __ mov(eax, Immediate(isolate()->factory()->false_value()));
   __ jmp(&done);
   __ bind(&ok);
-  __ mov(eax, Immediate(Factory::true_value()));
+  __ mov(eax, Immediate(isolate()->factory()->true_value()));
   __ bind(&done);
 
   context()->Plug(eax);
@@ -3274,7 +3307,7 @@
   __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset));
   __ SmiUntag(array_length);
   __ j(not_zero, &non_trivial_array);
-  __ mov(result_operand, Factory::empty_string());
+  __ mov(result_operand, isolate()->factory()->empty_string());
   __ jmp(&done);
 
   // Save the array length.
@@ -3485,7 +3518,7 @@
 
 
   __ bind(&bailout);
-  __ mov(result_operand, Factory::undefined_value());
+  __ mov(result_operand, isolate()->factory()->undefined_value());
   __ bind(&done);
   __ mov(eax, result_operand);
   // Drop temp values from the stack, and restore context register.
@@ -3523,7 +3556,8 @@
     // Call the JS runtime function via a call IC.
     __ Set(ecx, Immediate(expr->name()));
     InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-    Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
+    Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(
+        arg_count, in_loop);
     EmitCallIC(ic, RelocInfo::CODE_TARGET);
     // Restore context register.
     __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
@@ -3589,7 +3623,7 @@
     case Token::VOID: {
       Comment cmnt(masm_, "[ UnaryOperation (VOID)");
       VisitForEffect(expr->expression());
-      context()->Plug(Factory::undefined_value());
+      context()->Plug(isolate()->factory()->undefined_value());
       break;
     }
 
@@ -3837,9 +3871,9 @@
     case NAMED_PROPERTY: {
       __ mov(ecx, prop->key()->AsLiteral()->handle());
       __ pop(edx);
-      Handle<Code> ic(Builtins::builtin(
-          is_strict() ? Builtins::StoreIC_Initialize_Strict
-                      : Builtins::StoreIC_Initialize));
+      Handle<Code> ic = is_strict_mode()
+          ? isolate()->builtins()->StoreIC_Initialize_Strict()
+          : isolate()->builtins()->StoreIC_Initialize();
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -3854,9 +3888,9 @@
     case KEYED_PROPERTY: {
       __ pop(ecx);
       __ pop(edx);
-      Handle<Code> ic(Builtins::builtin(
-          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
-                      : Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic = is_strict_mode()
+          ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+          : isolate()->builtins()->KeyedStoreIC_Initialize();
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -3882,7 +3916,7 @@
     Comment cmnt(masm_, "Global variable");
     __ mov(eax, GlobalObjectOperand());
     __ mov(ecx, Immediate(proxy->name()));
-    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
     // Use a regular load, not a contextual load, to avoid a reference
     // error.
     EmitCallIC(ic, RelocInfo::CODE_TARGET);
@@ -3935,12 +3969,12 @@
   }
   PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
 
-  if (check->Equals(Heap::number_symbol())) {
+  if (check->Equals(isolate()->heap()->number_symbol())) {
     __ JumpIfSmi(eax, if_true);
     __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
-           Factory::heap_number_map());
+           isolate()->factory()->heap_number_map());
     Split(equal, if_true, if_false, fall_through);
-  } else if (check->Equals(Heap::string_symbol())) {
+  } else if (check->Equals(isolate()->heap()->string_symbol())) {
     __ JumpIfSmi(eax, if_false);
     __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
     __ j(above_equal, if_false);
@@ -3948,13 +3982,13 @@
     __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
               1 << Map::kIsUndetectable);
     Split(zero, if_true, if_false, fall_through);
-  } else if (check->Equals(Heap::boolean_symbol())) {
-    __ cmp(eax, Factory::true_value());
+  } else if (check->Equals(isolate()->heap()->boolean_symbol())) {
+    __ cmp(eax, isolate()->factory()->true_value());
     __ j(equal, if_true);
-    __ cmp(eax, Factory::false_value());
+    __ cmp(eax, isolate()->factory()->false_value());
     Split(equal, if_true, if_false, fall_through);
-  } else if (check->Equals(Heap::undefined_symbol())) {
-    __ cmp(eax, Factory::undefined_value());
+  } else if (check->Equals(isolate()->heap()->undefined_symbol())) {
+    __ cmp(eax, isolate()->factory()->undefined_value());
     __ j(equal, if_true);
     __ JumpIfSmi(eax, if_false);
     // Check for undetectable objects => true.
@@ -3962,13 +3996,13 @@
     __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
     __ test(ecx, Immediate(1 << Map::kIsUndetectable));
     Split(not_zero, if_true, if_false, fall_through);
-  } else if (check->Equals(Heap::function_symbol())) {
+  } else if (check->Equals(isolate()->heap()->function_symbol())) {
     __ JumpIfSmi(eax, if_false);
     __ CmpObjectType(eax, FIRST_FUNCTION_CLASS_TYPE, edx);
     Split(above_equal, if_true, if_false, fall_through);
-  } else if (check->Equals(Heap::object_symbol())) {
+  } else if (check->Equals(isolate()->heap()->object_symbol())) {
     __ JumpIfSmi(eax, if_false);
-    __ cmp(eax, Factory::null_value());
+    __ cmp(eax, isolate()->factory()->null_value());
     __ j(equal, if_true);
     __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, edx);
     __ j(below, if_false);
@@ -4016,7 +4050,7 @@
       VisitForStackValue(expr->right());
       __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
       PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
-      __ cmp(eax, Factory::true_value());
+      __ cmp(eax, isolate()->factory()->true_value());
       Split(equal, if_true, if_false, fall_through);
       break;
 
@@ -4109,12 +4143,12 @@
   VisitForAccumulatorValue(expr->expression());
   PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
 
-  __ cmp(eax, Factory::null_value());
+  __ cmp(eax, isolate()->factory()->null_value());
   if (expr->is_strict()) {
     Split(equal, if_true, if_false, fall_through);
   } else {
     __ j(equal, if_true);
-    __ cmp(eax, Factory::undefined_value());
+    __ cmp(eax, isolate()->factory()->undefined_value());
     __ j(equal, if_true);
     __ test(eax, Immediate(kSmiTagMask));
     __ j(zero, if_false);
@@ -4149,16 +4183,16 @@
          mode == RelocInfo::CODE_TARGET_CONTEXT);
   switch (ic->kind()) {
     case Code::LOAD_IC:
-      __ IncrementCounter(&Counters::named_load_full, 1);
+      __ IncrementCounter(isolate()->counters()->named_load_full(), 1);
       break;
     case Code::KEYED_LOAD_IC:
-      __ IncrementCounter(&Counters::keyed_load_full, 1);
+      __ IncrementCounter(isolate()->counters()->keyed_load_full(), 1);
       break;
     case Code::STORE_IC:
-      __ IncrementCounter(&Counters::named_store_full, 1);
+      __ IncrementCounter(isolate()->counters()->named_store_full(), 1);
       break;
     case Code::KEYED_STORE_IC:
-      __ IncrementCounter(&Counters::keyed_store_full, 1);
+      __ IncrementCounter(isolate()->counters()->keyed_store_full(), 1);
     default:
       break;
   }
@@ -4190,18 +4224,19 @@
 
 
 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) {
+  Counters* counters = isolate()->counters();
   switch (ic->kind()) {
     case Code::LOAD_IC:
-      __ IncrementCounter(&Counters::named_load_full, 1);
+      __ IncrementCounter(counters->named_load_full(), 1);
       break;
     case Code::KEYED_LOAD_IC:
-      __ IncrementCounter(&Counters::keyed_load_full, 1);
+      __ IncrementCounter(counters->keyed_load_full(), 1);
       break;
     case Code::STORE_IC:
-      __ IncrementCounter(&Counters::named_store_full, 1);
+      __ IncrementCounter(counters->named_store_full(), 1);
       break;
     case Code::KEYED_STORE_IC:
-      __ IncrementCounter(&Counters::keyed_store_full, 1);
+      __ IncrementCounter(counters->keyed_store_full(), 1);
     default:
       break;
   }
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index 6b9e749..48ffc73 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -93,7 +93,7 @@
   __ j(not_zero, miss, not_taken);
 
   __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset));
-  __ CheckMap(r0, Factory::hash_table_map(), miss, true);
+  __ CheckMap(r0, FACTORY->hash_table_map(), miss, true);
 }
 
 
@@ -475,7 +475,7 @@
   __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset));
   if (not_fast_array != NULL) {
     // Check that the object is in fast mode and writable.
-    __ CheckMap(scratch, Factory::fixed_array_map(), not_fast_array, true);
+    __ CheckMap(scratch, FACTORY->fixed_array_map(), not_fast_array, true);
   } else {
     __ AssertFastElements(scratch);
   }
@@ -485,7 +485,7 @@
   // Fast case: Do the load.
   ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0));
   __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize));
-  __ cmp(Operand(scratch), Immediate(Factory::the_hole_value()));
+  __ cmp(Operand(scratch), 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, out_of_range);
@@ -530,7 +530,7 @@
   //  -- esp[0] : return address
   // -----------------------------------
   Label slow, check_string, index_smi, index_string, property_array_property;
-  Label check_pixel_array, probe_dictionary, check_number_dictionary;
+  Label probe_dictionary, check_number_dictionary;
 
   // Check that the key is a smi.
   __ test(eax, Immediate(kSmiTagMask));
@@ -546,7 +546,7 @@
   // now in ecx.
   __ test_b(FieldOperand(ecx, Map::kBitField2Offset),
             1 << Map::kHasFastElements);
-  __ j(zero, &check_pixel_array, not_taken);
+  __ j(zero, &check_number_dictionary, not_taken);
 
   GenerateFastArrayLoad(masm,
                         edx,
@@ -555,27 +555,22 @@
                         eax,
                         NULL,
                         &slow);
-  __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
+  Isolate* isolate = masm->isolate();
+  Counters* counters = isolate->counters();
+  __ IncrementCounter(counters->keyed_load_generic_smi(), 1);
   __ ret(0);
 
-  __ bind(&check_pixel_array);
-  GenerateFastPixelArrayLoad(masm,
-                             edx,
-                             eax,
-                             ecx,
-                             ebx,
-                             eax,
-                             &check_number_dictionary,
-                             NULL,
-                             &slow);
-
   __ bind(&check_number_dictionary);
+  __ mov(ebx, eax);
+  __ SmiUntag(ebx);
+  __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
+
   // Check whether the elements is a number dictionary.
   // edx: receiver
   // ebx: untagged index
   // eax: key
   // ecx: elements
-  __ CheckMap(ecx, Factory::hash_table_map(), &slow, true);
+  __ CheckMap(ecx, isolate->factory()->hash_table_map(), &slow, true);
   Label slow_pop_receiver;
   // Push receiver on the stack to free up a register for the dictionary
   // probing.
@@ -600,7 +595,7 @@
   // Slow case: jump to runtime.
   // edx: receiver
   // eax: key
-  __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
+  __ IncrementCounter(counters->keyed_load_generic_slow(), 1);
   GenerateRuntimeGetProperty(masm);
 
   __ bind(&check_string);
@@ -613,7 +608,7 @@
   // cache. Otherwise probe the dictionary.
   __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
   __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
-         Immediate(Factory::hash_table_map()));
+         Immediate(isolate->factory()->hash_table_map()));
   __ j(equal, &probe_dictionary);
 
   // Load the map of the receiver, compute the keyed lookup cache hash
@@ -628,8 +623,8 @@
 
   // Load the key (consisting of map and symbol) from the cache and
   // check for match.
-  ExternalReference cache_keys
-      = ExternalReference::keyed_lookup_cache_keys();
+  ExternalReference cache_keys =
+      ExternalReference::keyed_lookup_cache_keys(masm->isolate());
   __ mov(edi, ecx);
   __ shl(edi, kPointerSizeLog2 + 1);
   __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
@@ -643,8 +638,8 @@
   // ebx     : receiver's map
   // eax     : key
   // ecx     : lookup cache index
-  ExternalReference cache_field_offsets
-      = ExternalReference::keyed_lookup_cache_field_offsets();
+  ExternalReference cache_field_offsets =
+      ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
   __ mov(edi,
          Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets));
   __ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
@@ -655,7 +650,7 @@
   __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
   __ add(ecx, Operand(edi));
   __ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0));
-  __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1);
+  __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
   __ ret(0);
 
   // Load property array property.
@@ -663,7 +658,7 @@
   __ mov(eax, FieldOperand(edx, JSObject::kPropertiesOffset));
   __ mov(eax, FieldOperand(eax, edi, times_pointer_size,
                            FixedArray::kHeaderSize));
-  __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1);
+  __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
   __ ret(0);
 
   // Do a quick inline probe of the receiver's dictionary, if it
@@ -675,7 +670,7 @@
   GenerateGlobalInstanceTypeCheck(masm, ecx, &slow);
 
   GenerateDictionaryLoad(masm, &slow, ebx, eax, ecx, edi, eax);
-  __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
+  __ IncrementCounter(counters->keyed_load_generic_symbol(), 1);
   __ ret(0);
 
   __ bind(&index_string);
@@ -752,8 +747,9 @@
   __ push(ecx);  // return address
 
   // Perform tail call to the entry.
-  ExternalReference ref = ExternalReference(
-      IC_Utility(kKeyedLoadPropertyWithInterceptor));
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor),
+                        masm->isolate());
   __ TailCallExternalReference(ref, 2, 1);
 
   __ bind(&slow);
@@ -769,7 +765,7 @@
   //  -- edx    : receiver
   //  -- esp[0] : return address
   // -----------------------------------
-  Label slow, fast, array, extra, check_pixel_array;
+  Label slow, fast, array, extra;
 
   // Check that the object isn't a smi.
   __ test(edx, Immediate(kSmiTagMask));
@@ -796,7 +792,7 @@
   // ecx: key (a smi)
   __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
   // Check that the object is in fast mode and writable.
-  __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true);
+  __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true);
   __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
   __ j(below, &fast, taken);
 
@@ -804,24 +800,6 @@
   __ bind(&slow);
   GenerateRuntimeSetProperty(masm, strict_mode);
 
-  // Check whether the elements is a pixel array.
-  __ bind(&check_pixel_array);
-  // eax: value
-  // ecx: key (a smi)
-  // edx: receiver
-  // edi: elements array
-  GenerateFastPixelArrayStore(masm,
-                              edx,
-                              ecx,
-                              eax,
-                              edi,
-                              ebx,
-                              false,
-                              NULL,
-                              &slow,
-                              &slow,
-                              &slow);
-
   // 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].
@@ -847,7 +825,7 @@
   // edx: receiver, a JSArray
   // ecx: key, a smi.
   __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
-  __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true);
+  __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, true);
 
   // Check the key against the length in the array, compute the
   // address to store into and fall through to fast case.
@@ -886,7 +864,8 @@
                                          Code::kNoExtraICState,
                                          NORMAL,
                                          argc);
-  StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax);
+  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
+                                                  eax);
 
   // If the stub cache probing failed, the receiver might be a value.
   // For value objects, we use the map of the prototype objects for
@@ -913,9 +892,9 @@
 
   // Check for boolean.
   __ bind(&non_string);
-  __ cmp(edx, Factory::true_value());
+  __ cmp(edx, FACTORY->true_value());
   __ j(equal, &boolean, not_taken);
-  __ cmp(edx, Factory::false_value());
+  __ cmp(edx, FACTORY->false_value());
   __ j(not_equal, &miss, taken);
   __ bind(&boolean);
   StubCompiler::GenerateLoadGlobalFunctionPrototype(
@@ -923,7 +902,8 @@
 
   // Probe the stub cache for the value object.
   __ bind(&probe);
-  StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
+  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
+                                                  no_reg);
   __ bind(&miss);
 }
 
@@ -989,10 +969,11 @@
   //  -- esp[(argc + 1) * 4] : receiver
   // -----------------------------------
 
+  Counters* counters = masm->isolate()->counters();
   if (id == IC::kCallIC_Miss) {
-    __ IncrementCounter(&Counters::call_miss, 1);
+    __ IncrementCounter(counters->call_miss(), 1);
   } else {
-    __ IncrementCounter(&Counters::keyed_call_miss, 1);
+    __ IncrementCounter(counters->keyed_call_miss(), 1);
   }
 
   // Get the receiver of the function from the stack; 1 ~ return address.
@@ -1008,7 +989,7 @@
   // Call the entry.
   CEntryStub stub(1);
   __ mov(eax, Immediate(2));
-  __ mov(ebx, Immediate(ExternalReference(IC_Utility(id))));
+  __ mov(ebx, Immediate(ExternalReference(IC_Utility(id), masm->isolate())));
   __ CallStub(&stub);
 
   // Move result to edi and exit the internal frame.
@@ -1114,7 +1095,9 @@
 
   GenerateFastArrayLoad(
       masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load);
-  __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1);
+  Isolate* isolate = masm->isolate();
+  Counters* counters = isolate->counters();
+  __ IncrementCounter(counters->keyed_call_generic_smi_fast(), 1);
 
   __ bind(&do_call);
   // receiver in edx is not used after this point.
@@ -1126,14 +1109,14 @@
   // eax: elements
   // ecx: smi key
   // Check whether the elements is a number dictionary.
-  __ CheckMap(eax, Factory::hash_table_map(), &slow_load, true);
+  __ CheckMap(eax, isolate->factory()->hash_table_map(), &slow_load, true);
   __ mov(ebx, ecx);
   __ SmiUntag(ebx);
   // ebx: untagged index
   // Receiver in edx will be clobbered, need to reload it on miss.
   GenerateNumberDictionaryLoad(
       masm, &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi);
-  __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1);
+  __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1);
   __ jmp(&do_call);
 
   __ bind(&slow_reload_receiver);
@@ -1142,7 +1125,7 @@
   __ bind(&slow_load);
   // This branch is taken when calling KeyedCallIC_Miss is neither required
   // nor beneficial.
-  __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1);
+  __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1);
   __ EnterInternalFrame();
   __ push(ecx);  // save the key
   __ push(edx);  // pass the receiver
@@ -1164,14 +1147,17 @@
       masm, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache);
 
   __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
-  __ CheckMap(ebx, Factory::hash_table_map(), &lookup_monomorphic_cache, true);
+  __ CheckMap(ebx,
+              isolate->factory()->hash_table_map(),
+              &lookup_monomorphic_cache,
+              true);
 
   GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi);
-  __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1);
+  __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1);
   __ jmp(&do_call);
 
   __ bind(&lookup_monomorphic_cache);
-  __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1);
+  __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1);
   GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC);
   // Fall through on miss.
 
@@ -1182,7 +1168,7 @@
   // - the value loaded is not a function,
   // - there is hope that the runtime will create a monomorphic call stub
   //   that will get fetched next time.
-  __ IncrementCounter(&Counters::keyed_call_generic_slow, 1);
+  __ IncrementCounter(counters->keyed_call_generic_slow(), 1);
   GenerateMiss(masm, argc);
 
   __ bind(&index_string);
@@ -1237,7 +1223,8 @@
   Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
                                          NOT_IN_LOOP,
                                          MONOMORPHIC);
-  StubCache::GenerateProbe(masm, flags, eax, ecx, ebx, edx);
+  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, eax, ecx, ebx,
+                                                  edx);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
@@ -1272,7 +1259,7 @@
   //  -- esp[0] : return address
   // -----------------------------------
 
-  __ IncrementCounter(&Counters::load_miss, 1);
+  __ IncrementCounter(masm->isolate()->counters()->load_miss(), 1);
 
   __ pop(ebx);
   __ push(eax);  // receiver
@@ -1280,7 +1267,8 @@
   __ push(ebx);  // return address
 
   // Perform tail call to the entry.
-  ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss));
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate());
   __ TailCallExternalReference(ref, 2, 1);
 }
 
@@ -1400,7 +1388,7 @@
   // (-1) or we should be clearing the inlined version.
   ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt - 1 ||
          *reinterpret_cast<int*>(offset_address) == -1 ||
-         (offset == 0 && map == Heap::null_value()));
+         (offset == 0 && map == HEAP->null_value()));
   *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag;
 
   // Patch the offset in the write-barrier code. The offset is the
@@ -1410,7 +1398,7 @@
   // (-1) or we should be clearing the inlined version.
   ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt ||
          *reinterpret_cast<int*>(offset_address) == -1 ||
-         (offset == 0 && map == Heap::null_value()));
+         (offset == 0 && map == HEAP->null_value()));
   *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag;
 
   return true;
@@ -1458,7 +1446,7 @@
   //  -- esp[0] : return address
   // -----------------------------------
 
-  __ IncrementCounter(&Counters::keyed_load_miss, 1);
+  __ IncrementCounter(masm->isolate()->counters()->keyed_load_miss(), 1);
 
   __ pop(ebx);
   __ push(edx);  // receiver
@@ -1466,7 +1454,8 @@
   __ push(ebx);  // return address
 
   // Perform tail call to the entry.
-  ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss));
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate());
   __ TailCallExternalReference(ref, 2, 1);
 }
 
@@ -1501,7 +1490,8 @@
                                          NOT_IN_LOOP,
                                          MONOMORPHIC,
                                          strict_mode);
-  StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
+  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
+                                                  no_reg);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
@@ -1523,7 +1513,8 @@
   __ push(ebx);
 
   // Perform tail call to the entry.
-  ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss));
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate());
   __ TailCallExternalReference(ref, 3, 1);
 }
 
@@ -1543,9 +1534,8 @@
   // -----------------------------------
   //
   // This accepts as a receiver anything JSObject::SetElementsLength accepts
-  // (currently anything except for external and pixel arrays which means
-  // anything with elements of FixedArray type.), but currently is restricted
-  // to JSArray.
+  // (currently anything except for external arrays which means anything with
+  // elements of FixedArray type.), but currently is restricted to JSArray.
   // Value must be a number, but only smis are accepted as the most common case.
 
   Label miss;
@@ -1579,7 +1569,8 @@
   __ push(value);
   __ push(scratch);  // return address
 
-  ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength));
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate());
   __ TailCallExternalReference(ref, 2, 1);
 
   __ bind(&miss);
@@ -1606,14 +1597,15 @@
   __ push(edx);
   GenerateDictionaryStore(masm, &restore_miss, ebx, ecx, eax, edx, edi);
   __ Drop(1);
-  __ IncrementCounter(&Counters::store_normal_hit, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->store_normal_hit(), 1);
   __ ret(0);
 
   __ bind(&restore_miss);
   __ pop(edx);
 
   __ bind(&miss);
-  __ IncrementCounter(&Counters::store_normal_miss, 1);
+  __ IncrementCounter(counters->store_normal_miss(), 1);
   GenerateMiss(masm);
 }
 
@@ -1676,7 +1668,8 @@
   __ push(ebx);
 
   // Do tail-call to runtime routine.
-  ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss));
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate());
   __ TailCallExternalReference(ref, 3, 1);
 }
 
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 9dcca9e..1691098 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -31,6 +31,7 @@
 
 #include "ia32/lithium-codegen-ia32.h"
 #include "code-stubs.h"
+#include "deoptimizer.h"
 #include "stub-cache.h"
 
 namespace v8 {
@@ -43,20 +44,13 @@
  public:
   SafepointGenerator(LCodeGen* codegen,
                      LPointerMap* pointers,
-                     int deoptimization_index,
-                     bool ensure_reloc_space = false)
+                     int deoptimization_index)
       : codegen_(codegen),
         pointers_(pointers),
-        deoptimization_index_(deoptimization_index),
-        ensure_reloc_space_(ensure_reloc_space) { }
+        deoptimization_index_(deoptimization_index) {}
   virtual ~SafepointGenerator() { }
 
   virtual void Generate() {
-    // Ensure that we have enough space in the reloc info to patch
-    // this with calls when doing deoptimization.
-    if (ensure_reloc_space_) {
-      codegen_->EnsureRelocSpaceForDeoptimization();
-    }
     codegen_->RecordSafepoint(pointers_, deoptimization_index_);
   }
 
@@ -64,7 +58,6 @@
   LCodeGen* codegen_;
   LPointerMap* pointers_;
   int deoptimization_index_;
-  bool ensure_reloc_space_;
 };
 
 
@@ -78,7 +71,6 @@
   return GeneratePrologue() &&
       GenerateBody() &&
       GenerateDeferredCode() &&
-      GenerateRelocPadding() &&
       GenerateSafepointTable();
 }
 
@@ -88,6 +80,7 @@
   code->set_stack_slots(StackSlotCount());
   code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
   PopulateDeoptimizationData(code);
+  Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
 }
 
 
@@ -123,16 +116,6 @@
 }
 
 
-bool LCodeGen::GenerateRelocPadding() {
-  int reloc_size = masm()->relocation_writer_size();
-  while (reloc_size < deoptimization_reloc_size.min_size) {
-    __ RecordComment(RelocInfo::kFillerCommentString, true);
-    reloc_size += RelocInfo::kMinRelocCommentSize;
-  }
-  return !is_aborted();
-}
-
-
 bool LCodeGen::GeneratePrologue() {
   ASSERT(is_generating());
 
@@ -385,22 +368,6 @@
 }
 
 
-void LCodeGen::EnsureRelocSpaceForDeoptimization() {
-  // Since we patch the reloc info with RUNTIME_ENTRY calls every patch
-  // site will take up 2 bytes + any pc-jumps.
-  // We are conservative and always reserver 6 bytes in case where a
-  // simple pc-jump is not enough.
-  uint32_t pc_delta =
-      masm()->pc_offset() - deoptimization_reloc_size.last_pc_offset;
-  if (is_uintn(pc_delta, 6)) {
-    deoptimization_reloc_size.min_size += 2;
-  } else {
-    deoptimization_reloc_size.min_size += 6;
-  }
-  deoptimization_reloc_size.last_pc_offset = masm()->pc_offset();
-}
-
-
 void LCodeGen::AddToTranslation(Translation* translation,
                                 LOperand* op,
                                 bool is_tagged) {
@@ -454,7 +421,6 @@
   }
   __ call(code, mode);
 
-  EnsureRelocSpaceForDeoptimization();
   RegisterLazyDeoptimization(instr);
 
   // Signal that we don't inline smi code before these stubs in the
@@ -466,7 +432,7 @@
 }
 
 
-void LCodeGen::CallRuntime(Runtime::Function* fun,
+void LCodeGen::CallRuntime(const Runtime::Function* fun,
                            int argc,
                            LInstruction* instr,
                            bool adjusted) {
@@ -479,6 +445,7 @@
     __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
   }
   __ CallRuntime(fun, argc);
+
   RegisterLazyDeoptimization(instr);
 }
 
@@ -586,14 +553,14 @@
   if (length == 0) return;
   ASSERT(FLAG_deopt);
   Handle<DeoptimizationInputData> data =
-      Factory::NewDeoptimizationInputData(length, TENURED);
+      factory()->NewDeoptimizationInputData(length, TENURED);
 
   Handle<ByteArray> translations = translations_.CreateByteArray();
   data->SetTranslationByteArray(*translations);
   data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
 
   Handle<FixedArray> literals =
-      Factory::NewFixedArray(deoptimization_literals_.length(), TENURED);
+      factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
   for (int i = 0; i < deoptimization_literals_.length(); i++) {
     literals->set(i, *deoptimization_literals_[i]);
   }
@@ -743,16 +710,6 @@
       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
       break;
     }
-    case CodeStub::StringCharAt: {
-      StringCharAtStub stub;
-      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
-      break;
-    }
-    case CodeStub::MathPow: {
-      MathPowStub stub;
-      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
-      break;
-    }
     case CodeStub::NumberToString: {
       NumberToStringStub stub;
       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
@@ -786,41 +743,64 @@
 
 
 void LCodeGen::DoModI(LModI* instr) {
-  LOperand* right = instr->InputAt(1);
-  ASSERT(ToRegister(instr->result()).is(edx));
-  ASSERT(ToRegister(instr->InputAt(0)).is(eax));
-  ASSERT(!ToRegister(instr->InputAt(1)).is(eax));
-  ASSERT(!ToRegister(instr->InputAt(1)).is(edx));
+  if (instr->hydrogen()->HasPowerOf2Divisor()) {
+    Register dividend = ToRegister(instr->InputAt(0));
 
-  Register right_reg = ToRegister(right);
+    int32_t divisor =
+        HConstant::cast(instr->hydrogen()->right())->Integer32Value();
 
-  // Check for x % 0.
-  if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
-    __ test(right_reg, ToOperand(right));
-    DeoptimizeIf(zero, instr->environment());
-  }
+    if (divisor < 0) divisor = -divisor;
 
-  // Sign extend to edx.
-  __ cdq();
-
-  // Check for (0 % -x) that will produce negative zero.
-  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
-    NearLabel positive_left;
-    NearLabel done;
-    __ test(eax, Operand(eax));
-    __ j(not_sign, &positive_left);
-    __ idiv(right_reg);
-
-    // Test the remainder for 0, because then the result would be -0.
-    __ test(edx, Operand(edx));
-    __ j(not_zero, &done);
-
-    DeoptimizeIf(no_condition, instr->environment());
-    __ bind(&positive_left);
-    __ idiv(right_reg);
+    NearLabel positive_dividend, done;
+    __ test(dividend, Operand(dividend));
+    __ j(not_sign, &positive_dividend);
+    __ neg(dividend);
+    __ and_(dividend, divisor - 1);
+    __ neg(dividend);
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      __ j(not_zero, &done);
+      DeoptimizeIf(no_condition, instr->environment());
+    }
+    __ bind(&positive_dividend);
+    __ and_(dividend, divisor - 1);
     __ bind(&done);
   } else {
-    __ idiv(right_reg);
+    LOperand* right = instr->InputAt(1);
+    ASSERT(ToRegister(instr->InputAt(0)).is(eax));
+    ASSERT(ToRegister(instr->result()).is(edx));
+
+    Register right_reg = ToRegister(right);
+    ASSERT(!right_reg.is(eax));
+    ASSERT(!right_reg.is(edx));
+
+    // Check for x % 0.
+    if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
+      __ test(right_reg, ToOperand(right));
+      DeoptimizeIf(zero, instr->environment());
+    }
+
+    // Sign extend to edx.
+    __ cdq();
+
+    // Check for (0 % -x) that will produce negative zero.
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      NearLabel positive_left;
+      NearLabel done;
+      __ test(eax, Operand(eax));
+      __ j(not_sign, &positive_left);
+      __ idiv(right_reg);
+
+      // Test the remainder for 0, because then the result would be -0.
+      __ test(edx, Operand(edx));
+      __ j(not_zero, &done);
+
+      DeoptimizeIf(no_condition, instr->environment());
+      __ bind(&positive_left);
+      __ idiv(right_reg);
+      __ bind(&done);
+    } else {
+      __ idiv(right_reg);
+    }
   }
 }
 
@@ -880,7 +860,49 @@
   }
 
   if (right->IsConstantOperand()) {
-    __ imul(left, left, ToInteger32(LConstantOperand::cast(right)));
+    // Try strength reductions on the multiplication.
+    // All replacement instructions are at most as long as the imul
+    // and have better latency.
+    int constant = ToInteger32(LConstantOperand::cast(right));
+    if (constant == -1) {
+      __ neg(left);
+    } else if (constant == 0) {
+      __ xor_(left, Operand(left));
+    } else if (constant == 2) {
+      __ add(left, Operand(left));
+    } else if (!instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+      // If we know that the multiplication can't overflow, it's safe to
+      // use instructions that don't set the overflow flag for the
+      // multiplication.
+      switch (constant) {
+        case 1:
+          // Do nothing.
+          break;
+        case 3:
+          __ lea(left, Operand(left, left, times_2, 0));
+          break;
+        case 4:
+          __ shl(left, 2);
+          break;
+        case 5:
+          __ lea(left, Operand(left, left, times_4, 0));
+          break;
+        case 8:
+          __ shl(left, 3);
+          break;
+        case 9:
+          __ lea(left, Operand(left, left, times_8, 0));
+          break;
+       case 16:
+         __ shl(left, 4);
+         break;
+        default:
+          __ imul(left, left, constant);
+          break;
+      }
+    } else {
+      __ imul(left, left, constant);
+    }
   } else {
     __ imul(left, ToOperand(right));
   }
@@ -1040,7 +1062,7 @@
     uint64_t int_val = BitCast<uint64_t, double>(v);
     int32_t lower = static_cast<int32_t>(int_val);
     int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
-    if (CpuFeatures::IsSupported(SSE4_1)) {
+    if (isolate()->cpu_features()->IsSupported(SSE4_1)) {
       CpuFeatures::Scope scope(SSE4_1);
       if (lower != 0) {
         __ Set(temp, Immediate(lower));
@@ -1086,10 +1108,10 @@
 }
 
 
-void LCodeGen::DoPixelArrayLength(LPixelArrayLength* instr) {
+void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) {
   Register result = ToRegister(instr->result());
   Register array = ToRegister(instr->InputAt(0));
-  __ mov(result, FieldOperand(array, PixelArray::kLengthOffset));
+  __ mov(result, FieldOperand(array, ExternalArray::kLengthOffset));
 }
 
 
@@ -1171,7 +1193,9 @@
       __ PrepareCallCFunction(4, eax);
       __ movdbl(Operand(esp, 0 * kDoubleSize), left);
       __ movdbl(Operand(esp, 1 * kDoubleSize), right);
-      __ CallCFunction(ExternalReference::double_fp_operation(Token::MOD), 4);
+      __ CallCFunction(
+          ExternalReference::double_fp_operation(Token::MOD, isolate()),
+          4);
 
       // Return value is in st(0) on ia32.
       // Store it into the (fixed) result register.
@@ -1243,17 +1267,17 @@
     ASSERT(r.IsTagged());
     Register reg = ToRegister(instr->InputAt(0));
     if (instr->hydrogen()->type().IsBoolean()) {
-      __ cmp(reg, Factory::true_value());
+      __ cmp(reg, factory()->true_value());
       EmitBranch(true_block, false_block, equal);
     } else {
       Label* true_label = chunk_->GetAssemblyLabel(true_block);
       Label* false_label = chunk_->GetAssemblyLabel(false_block);
 
-      __ cmp(reg, Factory::undefined_value());
+      __ cmp(reg, factory()->undefined_value());
       __ j(equal, false_label);
-      __ cmp(reg, Factory::true_value());
+      __ cmp(reg, factory()->true_value());
       __ j(equal, true_label);
-      __ cmp(reg, Factory::false_value());
+      __ cmp(reg, factory()->false_value());
       __ j(equal, false_label);
       __ test(reg, Operand(reg));
       __ j(equal, false_label);
@@ -1263,7 +1287,7 @@
       // Test for double values. Zero is false.
       NearLabel call_stub;
       __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
-             Factory::heap_number_map());
+             factory()->heap_number_map());
       __ j(not_equal, &call_stub);
       __ fldz();
       __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
@@ -1293,7 +1317,7 @@
     // Perform stack overflow check if this goto needs it before jumping.
     if (deferred_stack_check != NULL) {
       ExternalReference stack_limit =
-          ExternalReference::address_of_stack_limit();
+          ExternalReference::address_of_stack_limit(isolate());
       __ cmp(esp, Operand::StaticVariable(stack_limit));
       __ j(above_equal, chunk_->GetAssemblyLabel(block));
       __ jmp(deferred_stack_check->entry());
@@ -1386,11 +1410,11 @@
 
   NearLabel done;
   Condition cc = TokenToCondition(instr->op(), instr->is_double());
-  __ mov(ToRegister(result), Factory::true_value());
+  __ mov(ToRegister(result), factory()->true_value());
   __ j(cc, &done);
 
   __ bind(&unordered);
-  __ mov(ToRegister(result), Factory::false_value());
+  __ mov(ToRegister(result), factory()->false_value());
   __ bind(&done);
 }
 
@@ -1421,10 +1445,10 @@
   Register result = ToRegister(instr->result());
 
   __ cmp(left, Operand(right));
-  __ mov(result, Factory::true_value());
+  __ mov(result, factory()->true_value());
   NearLabel done;
   __ j(equal, &done);
-  __ mov(result, Factory::false_value());
+  __ mov(result, factory()->false_value());
   __ bind(&done);
 }
 
@@ -1447,17 +1471,17 @@
   // TODO(fsc): If the expression is known to be a smi, then it's
   // definitely not null. Materialize false.
 
-  __ cmp(reg, Factory::null_value());
+  __ cmp(reg, factory()->null_value());
   if (instr->is_strict()) {
-    __ mov(result, Factory::true_value());
+    __ mov(result, factory()->true_value());
     NearLabel done;
     __ j(equal, &done);
-    __ mov(result, Factory::false_value());
+    __ mov(result, factory()->false_value());
     __ bind(&done);
   } else {
     NearLabel true_value, false_value, done;
     __ j(equal, &true_value);
-    __ cmp(reg, Factory::undefined_value());
+    __ cmp(reg, factory()->undefined_value());
     __ j(equal, &true_value);
     __ test(reg, Immediate(kSmiTagMask));
     __ j(zero, &false_value);
@@ -1469,10 +1493,10 @@
     __ test(scratch, Immediate(1 << Map::kIsUndetectable));
     __ j(not_zero, &true_value);
     __ bind(&false_value);
-    __ mov(result, Factory::false_value());
+    __ mov(result, factory()->false_value());
     __ jmp(&done);
     __ bind(&true_value);
-    __ mov(result, Factory::true_value());
+    __ mov(result, factory()->true_value());
     __ bind(&done);
   }
 }
@@ -1487,14 +1511,14 @@
   int true_block = chunk_->LookupDestination(instr->true_block_id());
   int false_block = chunk_->LookupDestination(instr->false_block_id());
 
-  __ cmp(reg, Factory::null_value());
+  __ cmp(reg, factory()->null_value());
   if (instr->is_strict()) {
     EmitBranch(true_block, false_block, equal);
   } else {
     Label* true_label = chunk_->GetAssemblyLabel(true_block);
     Label* false_label = chunk_->GetAssemblyLabel(false_block);
     __ j(equal, true_label);
-    __ cmp(reg, Factory::undefined_value());
+    __ cmp(reg, factory()->undefined_value());
     __ j(equal, true_label);
     __ test(reg, Immediate(kSmiTagMask));
     __ j(zero, false_label);
@@ -1521,7 +1545,7 @@
   __ test(input, Immediate(kSmiTagMask));
   __ j(equal, is_not_object);
 
-  __ cmp(input, Factory::null_value());
+  __ cmp(input, isolate()->factory()->null_value());
   __ j(equal, is_object);
 
   __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset));
@@ -1548,11 +1572,11 @@
   __ j(true_cond, &is_true);
 
   __ bind(&is_false);
-  __ mov(result, Factory::false_value());
+  __ mov(result, factory()->false_value());
   __ jmp(&done);
 
   __ bind(&is_true);
-  __ mov(result, Factory::true_value());
+  __ mov(result, factory()->true_value());
 
   __ bind(&done);
 }
@@ -1580,10 +1604,10 @@
 
   ASSERT(instr->hydrogen()->value()->representation().IsTagged());
   __ test(input, Immediate(kSmiTagMask));
-  __ mov(result, Factory::true_value());
+  __ mov(result, factory()->true_value());
   NearLabel done;
   __ j(zero, &done);
-  __ mov(result, Factory::false_value());
+  __ mov(result, factory()->false_value());
   __ bind(&done);
 }
 
@@ -1629,10 +1653,10 @@
   __ j(zero, &is_false);
   __ CmpObjectType(input, TestType(instr->hydrogen()), result);
   __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false);
-  __ mov(result, Factory::true_value());
+  __ mov(result, factory()->true_value());
   __ jmp(&done);
   __ bind(&is_false);
-  __ mov(result, Factory::false_value());
+  __ mov(result, factory()->false_value());
   __ bind(&done);
 }
 
@@ -1672,12 +1696,12 @@
   Register result = ToRegister(instr->result());
 
   ASSERT(instr->hydrogen()->value()->representation().IsTagged());
-  __ mov(result, Factory::true_value());
+  __ mov(result, factory()->true_value());
   __ test(FieldOperand(input, String::kHashFieldOffset),
           Immediate(String::kContainsCachedArrayIndexMask));
   NearLabel done;
   __ j(zero, &done);
-  __ mov(result, Factory::false_value());
+  __ mov(result, factory()->false_value());
   __ bind(&done);
 }
 
@@ -1766,11 +1790,11 @@
   __ j(not_equal, &is_false);
 
   __ bind(&is_true);
-  __ mov(result, Factory::true_value());
+  __ mov(result, factory()->true_value());
   __ jmp(&done);
 
   __ bind(&is_false);
-  __ mov(result, Factory::false_value());
+  __ mov(result, factory()->false_value());
   __ bind(&done);
 }
 
@@ -1818,10 +1842,10 @@
   NearLabel true_value, done;
   __ test(eax, Operand(eax));
   __ j(zero, &true_value);
-  __ mov(ToRegister(instr->result()), Factory::false_value());
+  __ mov(ToRegister(instr->result()), factory()->false_value());
   __ jmp(&done);
   __ bind(&true_value);
-  __ mov(ToRegister(instr->result()), Factory::true_value());
+  __ mov(ToRegister(instr->result()), factory()->true_value());
   __ bind(&done);
 }
 
@@ -1873,16 +1897,16 @@
   Register map = ToRegister(instr->TempAt(0));
   __ mov(map, FieldOperand(object, HeapObject::kMapOffset));
   __ bind(deferred->map_check());  // Label for calculating code patching.
-  __ cmp(map, Factory::the_hole_value());  // Patched to cached map.
+  __ cmp(map, factory()->the_hole_value());  // Patched to cached map.
   __ j(not_equal, &cache_miss, not_taken);
-  __ mov(eax, Factory::the_hole_value());  // Patched to either true or false.
+  __ mov(eax, factory()->the_hole_value());  // Patched to either true or false.
   __ jmp(&done);
 
   // The inlined call site cache did not match. Check for null and string
   // before calling the deferred code.
   __ bind(&cache_miss);
   // Null is not an instance of anything.
-  __ cmp(object, Factory::null_value());
+  __ cmp(object, factory()->null_value());
   __ j(equal, &false_result);
 
   // String values are not instances of anything.
@@ -1893,7 +1917,7 @@
   __ jmp(deferred->entry());
 
   __ bind(&false_result);
-  __ mov(ToRegister(instr->result()), Factory::false_value());
+  __ mov(ToRegister(instr->result()), factory()->false_value());
 
   // Here result has either true or false. Deferred code also produces true or
   // false object.
@@ -1965,10 +1989,10 @@
   NearLabel true_value, done;
   __ test(eax, Operand(eax));
   __ j(condition, &true_value);
-  __ mov(ToRegister(instr->result()), Factory::false_value());
+  __ mov(ToRegister(instr->result()), factory()->false_value());
   __ jmp(&done);
   __ bind(&true_value);
-  __ mov(ToRegister(instr->result()), Factory::true_value());
+  __ mov(ToRegister(instr->result()), factory()->true_value());
   __ bind(&done);
 }
 
@@ -2012,7 +2036,7 @@
   Register result = ToRegister(instr->result());
   __ mov(result, Operand::Cell(instr->hydrogen()->cell()));
   if (instr->hydrogen()->check_hole_value()) {
-    __ cmp(result, Factory::the_hole_value());
+    __ cmp(result, factory()->the_hole_value());
     DeoptimizeIf(equal, instr->environment());
   }
 }
@@ -2027,7 +2051,7 @@
   // to update the property details in the property dictionary to mark
   // it as no longer deleted. We deoptimize in that case.
   if (instr->hydrogen()->check_hole_value()) {
-    __ cmp(cell_operand, Factory::the_hole_value());
+    __ cmp(cell_operand, factory()->the_hole_value());
     DeoptimizeIf(equal, instr->environment());
   }
 
@@ -2056,7 +2080,7 @@
 
 
 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
-  Register object = ToRegister(instr->InputAt(0));
+  Register object = ToRegister(instr->object());
   Register result = ToRegister(instr->result());
   if (instr->hydrogen()->is_in_object()) {
     __ mov(result, FieldOperand(object, instr->hydrogen()->offset()));
@@ -2067,13 +2091,76 @@
 }
 
 
+void LCodeGen::EmitLoadField(Register result,
+                             Register object,
+                             Handle<Map> type,
+                             Handle<String> name) {
+  LookupResult lookup;
+  type->LookupInDescriptors(NULL, *name, &lookup);
+  ASSERT(lookup.IsProperty() && lookup.type() == FIELD);
+  int index = lookup.GetLocalFieldIndexFromMap(*type);
+  int offset = index * kPointerSize;
+  if (index < 0) {
+    // Negative property indices are in-object properties, indexed
+    // from the end of the fixed part of the object.
+    __ mov(result, FieldOperand(object, offset + type->instance_size()));
+  } else {
+    // Non-negative property indices are in the properties array.
+    __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
+    __ mov(result, FieldOperand(result, offset + FixedArray::kHeaderSize));
+  }
+}
+
+
+void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
+  Register object = ToRegister(instr->object());
+  Register result = ToRegister(instr->result());
+
+  int map_count = instr->hydrogen()->types()->length();
+  Handle<String> name = instr->hydrogen()->name();
+  if (map_count == 0) {
+    ASSERT(instr->hydrogen()->need_generic());
+    __ mov(ecx, name);
+    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+    CallCode(ic, RelocInfo::CODE_TARGET, instr, false);
+  } else {
+    NearLabel done;
+    for (int i = 0; i < map_count - 1; ++i) {
+      Handle<Map> map = instr->hydrogen()->types()->at(i);
+      NearLabel next;
+      __ cmp(FieldOperand(object, HeapObject::kMapOffset), map);
+      __ j(not_equal, &next);
+      EmitLoadField(result, object, map, name);
+      __ jmp(&done);
+      __ bind(&next);
+    }
+    Handle<Map> map = instr->hydrogen()->types()->last();
+    __ cmp(FieldOperand(object, HeapObject::kMapOffset), map);
+    if (instr->hydrogen()->need_generic()) {
+      NearLabel generic;
+      __ j(not_equal, &generic);
+      EmitLoadField(result, object, map, name);
+      __ jmp(&done);
+      __ bind(&generic);
+      __ mov(ecx, name);
+      Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+      CallCode(ic, RelocInfo::CODE_TARGET, instr, false);
+    } else {
+      DeoptimizeIf(not_equal, instr->environment());
+      EmitLoadField(result, object, map, name);
+    }
+    __ bind(&done);
+  }
+}
+
+
 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
   ASSERT(ToRegister(instr->context()).is(esi));
   ASSERT(ToRegister(instr->object()).is(eax));
   ASSERT(ToRegister(instr->result()).is(eax));
 
   __ mov(ecx, instr->name());
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2098,7 +2185,7 @@
          FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
 
   // Check that the function has a prototype or an initial map.
-  __ cmp(Operand(result), Immediate(Factory::the_hole_value()));
+  __ cmp(Operand(result), Immediate(factory()->the_hole_value()));
   DeoptimizeIf(equal, instr->environment());
 
   // If the function does not have an initial map, we're done.
@@ -2127,24 +2214,30 @@
   if (FLAG_debug_code) {
     NearLabel done;
     __ cmp(FieldOperand(result, HeapObject::kMapOffset),
-           Immediate(Factory::fixed_array_map()));
+           Immediate(factory()->fixed_array_map()));
     __ j(equal, &done);
     __ cmp(FieldOperand(result, HeapObject::kMapOffset),
-           Immediate(Factory::pixel_array_map()));
+           Immediate(factory()->fixed_cow_array_map()));
     __ j(equal, &done);
-    __ cmp(FieldOperand(result, HeapObject::kMapOffset),
-           Immediate(Factory::fixed_cow_array_map()));
-    __ Check(equal, "Check for fast elements or pixel array failed.");
+    Register temp((result.is(eax)) ? ebx : eax);
+    __ push(temp);
+    __ mov(temp, FieldOperand(result, HeapObject::kMapOffset));
+    __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
+    __ sub(Operand(temp), Immediate(FIRST_EXTERNAL_ARRAY_TYPE));
+    __ cmp(Operand(temp), Immediate(kExternalArrayTypeCount));
+    __ pop(temp);
+    __ Check(below, "Check for fast elements or pixel array failed.");
     __ bind(&done);
   }
 }
 
 
-void LCodeGen::DoLoadPixelArrayExternalPointer(
-    LLoadPixelArrayExternalPointer* instr) {
+void LCodeGen::DoLoadExternalArrayPointer(
+    LLoadExternalArrayPointer* instr) {
   Register result = ToRegister(instr->result());
   Register input = ToRegister(instr->InputAt(0));
-  __ mov(result, FieldOperand(input, PixelArray::kExternalPointerOffset));
+  __ mov(result, FieldOperand(input,
+                              ExternalArray::kExternalPointerOffset));
 }
 
 
@@ -2176,19 +2269,52 @@
                               FixedArray::kHeaderSize));
 
   // Check for the hole value.
-  __ cmp(result, Factory::the_hole_value());
+  __ cmp(result, factory()->the_hole_value());
   DeoptimizeIf(equal, instr->environment());
 }
 
 
-void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) {
+void LCodeGen::DoLoadKeyedSpecializedArrayElement(
+    LLoadKeyedSpecializedArrayElement* instr) {
   Register external_pointer = ToRegister(instr->external_pointer());
   Register key = ToRegister(instr->key());
-  Register result = ToRegister(instr->result());
-  ASSERT(result.is(external_pointer));
-
-  // Load the result.
-  __ movzx_b(result, Operand(external_pointer, key, times_1, 0));
+  ExternalArrayType array_type = instr->array_type();
+  if (array_type == kExternalFloatArray) {
+    XMMRegister result(ToDoubleRegister(instr->result()));
+    __ movss(result, Operand(external_pointer, key, times_4, 0));
+    __ cvtss2sd(result, result);
+  } else {
+    Register result(ToRegister(instr->result()));
+    switch (array_type) {
+      case kExternalByteArray:
+        __ movsx_b(result, Operand(external_pointer, key, times_1, 0));
+        break;
+      case kExternalUnsignedByteArray:
+      case kExternalPixelArray:
+        __ movzx_b(result, Operand(external_pointer, key, times_1, 0));
+        break;
+      case kExternalShortArray:
+        __ movsx_w(result, Operand(external_pointer, key, times_2, 0));
+        break;
+      case kExternalUnsignedShortArray:
+        __ movzx_w(result, Operand(external_pointer, key, times_2, 0));
+        break;
+      case kExternalIntArray:
+        __ mov(result, Operand(external_pointer, key, times_4, 0));
+        break;
+      case kExternalUnsignedIntArray:
+        __ mov(result, Operand(external_pointer, key, times_4, 0));
+        __ test(Operand(result), Immediate(0x80000000));
+        // TODO(danno): we could be more clever here, perhaps having a special
+        // version of the stub that detects if the overflow case actually
+        // happens, and generate code that returns a double rather than int.
+        DeoptimizeIf(not_zero, instr->environment());
+        break;
+      case kExternalFloatArray:
+        UNREACHABLE();
+        break;
+    }
+  }
 }
 
 
@@ -2197,7 +2323,7 @@
   ASSERT(ToRegister(instr->object()).is(edx));
   ASSERT(ToRegister(instr->key()).is(eax));
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2262,9 +2388,9 @@
   // If the receiver is null or undefined, we have to pass the global object
   // as a receiver.
   NearLabel global_object, receiver_ok;
-  __ cmp(receiver, Factory::null_value());
+  __ cmp(receiver, factory()->null_value());
   __ j(equal, &global_object);
-  __ cmp(receiver, Factory::undefined_value());
+  __ cmp(receiver, factory()->undefined_value());
   __ j(equal, &global_object);
 
   // The receiver should be a JS object.
@@ -2311,8 +2437,7 @@
   RegisterEnvironmentForDeoptimization(env);
   SafepointGenerator safepoint_generator(this,
                                          pointers,
-                                         env->deoptimization_index(),
-                                         true);
+                                         env->deoptimization_index());
   v8::internal::ParameterCount actual(eax);
   __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
 }
@@ -2384,7 +2509,6 @@
     __ CallSelf();
   } else {
     __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
-    EnsureRelocSpaceForDeoptimization();
   }
 
   // Setup deoptimization.
@@ -2402,7 +2526,7 @@
 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
   Register input_reg = ToRegister(instr->InputAt(0));
   __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
-         Factory::heap_number_map());
+         factory()->heap_number_map());
   DeoptimizeIf(not_equal, instr->environment());
 
   Label done;
@@ -2583,13 +2707,15 @@
   LOperand* right = instr->InputAt(1);
   DoubleRegister result_reg = ToDoubleRegister(instr->result());
   Representation exponent_type = instr->hydrogen()->right()->representation();
+
   if (exponent_type.IsDouble()) {
     // It is safe to use ebx directly since the instruction is marked
     // as a call.
     __ PrepareCallCFunction(4, ebx);
     __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left));
     __ movdbl(Operand(esp, 1 * kDoubleSize), ToDoubleRegister(right));
-    __ CallCFunction(ExternalReference::power_double_double_function(), 4);
+    __ CallCFunction(ExternalReference::power_double_double_function(isolate()),
+                     4);
   } else if (exponent_type.IsInteger32()) {
     // It is safe to use ebx directly since the instruction is marked
     // as a call.
@@ -2597,7 +2723,8 @@
     __ PrepareCallCFunction(4, ebx);
     __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left));
     __ mov(Operand(esp, 1 * kDoubleSize), ToRegister(right));
-    __ CallCFunction(ExternalReference::power_double_int_function(), 4);
+    __ CallCFunction(ExternalReference::power_double_int_function(isolate()),
+                     4);
   } else {
     ASSERT(exponent_type.IsTagged());
     CpuFeatures::Scope scope(SSE2);
@@ -2622,7 +2749,8 @@
     __ PrepareCallCFunction(4, ebx);
     __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left));
     __ movdbl(Operand(esp, 1 * kDoubleSize), result_reg);
-    __ CallCFunction(ExternalReference::power_double_double_function(), 4);
+    __ CallCFunction(ExternalReference::power_double_double_function(isolate()),
+                     4);
   }
 
   // Return value is in st(0) on ia32.
@@ -2697,7 +2825,8 @@
   ASSERT(ToRegister(instr->result()).is(eax));
 
   int arity = instr->arity();
-  Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arity, NOT_IN_LOOP);
+  Handle<Code> ic = isolate()->stub_cache()->
+      ComputeKeyedCallInitialize(arity, NOT_IN_LOOP);
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2707,7 +2836,8 @@
   ASSERT(ToRegister(instr->result()).is(eax));
 
   int arity = instr->arity();
-  Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP);
+  Handle<Code> ic = isolate()->stub_cache()->
+      ComputeCallInitialize(arity, NOT_IN_LOOP);
   __ mov(ecx, instr->name());
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
@@ -2729,7 +2859,8 @@
   ASSERT(ToRegister(instr->result()).is(eax));
 
   int arity = instr->arity();
-  Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP);
+  Handle<Code> ic = isolate()->stub_cache()->
+      ComputeCallInitialize(arity, NOT_IN_LOOP);
   __ mov(ecx, instr->name());
   CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
 }
@@ -2747,7 +2878,7 @@
   ASSERT(ToRegister(instr->constructor()).is(edi));
   ASSERT(ToRegister(instr->result()).is(eax));
 
-  Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall));
+  Handle<Code> builtin = isolate()->builtins()->JSConstructCall();
   __ Set(eax, Immediate(instr->arity()));
   CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr);
 }
@@ -2794,9 +2925,9 @@
   ASSERT(ToRegister(instr->value()).is(eax));
 
   __ mov(ecx, instr->name());
-  Handle<Code> ic(Builtins::builtin(
-      info_->is_strict() ? Builtins::StoreIC_Initialize_Strict
-                         : Builtins::StoreIC_Initialize));
+  Handle<Code> ic = info_->is_strict()
+      ? isolate()->builtins()->StoreIC_Initialize_Strict()
+      : isolate()->builtins()->StoreIC_Initialize();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2807,22 +2938,52 @@
 }
 
 
-void LCodeGen::DoStorePixelArrayElement(LStorePixelArrayElement* instr) {
+void LCodeGen::DoStoreKeyedSpecializedArrayElement(
+    LStoreKeyedSpecializedArrayElement* instr) {
   Register external_pointer = ToRegister(instr->external_pointer());
   Register key = ToRegister(instr->key());
-  Register value = ToRegister(instr->value());
-  ASSERT(ToRegister(instr->TempAt(0)).is(eax));
-
-  __ mov(eax, value);
-  {  // Clamp the value to [0..255].
-    NearLabel done;
-    __ test(eax, Immediate(0xFFFFFF00));
-    __ j(zero, &done);
-    __ setcc(negative, eax);  // 1 if negative, 0 if positive.
-    __ dec_b(eax);  // 0 if negative, 255 if positive.
-    __ bind(&done);
+  ExternalArrayType array_type = instr->array_type();
+  if (array_type == kExternalFloatArray) {
+    __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value()));
+    __ movss(Operand(external_pointer, key, times_4, 0), xmm0);
+  } else {
+    Register value = ToRegister(instr->value());
+    switch (array_type) {
+      case kExternalPixelArray: {
+        // Clamp the value to [0..255].
+        Register temp = ToRegister(instr->TempAt(0));
+        // The dec_b below requires that the clamped value is in a byte
+        // register. eax is an arbitrary choice to satisfy this requirement, we
+        // hinted the register allocator to give us eax when building the
+        // instruction.
+        ASSERT(temp.is(eax));
+        __ mov(temp, ToRegister(instr->value()));
+        NearLabel done;
+        __ test(temp, Immediate(0xFFFFFF00));
+        __ j(zero, &done);
+        __ setcc(negative, temp);  // 1 if negative, 0 if positive.
+        __ dec_b(temp);  // 0 if negative, 255 if positive.
+        __ bind(&done);
+        __ mov_b(Operand(external_pointer, key, times_1, 0), temp);
+        break;
+      }
+      case kExternalByteArray:
+      case kExternalUnsignedByteArray:
+        __ mov_b(Operand(external_pointer, key, times_1, 0), value);
+        break;
+      case kExternalShortArray:
+      case kExternalUnsignedShortArray:
+        __ mov_w(Operand(external_pointer, key, times_2, 0), value);
+        break;
+      case kExternalIntArray:
+      case kExternalUnsignedIntArray:
+        __ mov(Operand(external_pointer, key, times_4, 0), value);
+        break;
+      case kExternalFloatArray:
+        UNREACHABLE();
+        break;
+    }
   }
-  __ mov_b(Operand(external_pointer, key, times_1, 0), eax);
 }
 
 
@@ -2864,9 +3025,9 @@
   ASSERT(ToRegister(instr->key()).is(ecx));
   ASSERT(ToRegister(instr->value()).is(eax));
 
-  Handle<Code> ic(Builtins::builtin(
-      info_->is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
-                         : Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic = info_->is_strict()
+      ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+      : isolate()->builtins()->KeyedStoreIC_Initialize();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2926,7 +3087,7 @@
   // the case we would rather go to the runtime system now to flatten
   // the string.
   __ cmp(FieldOperand(string, ConsString::kSecondOffset),
-         Immediate(Factory::empty_string()));
+         Immediate(factory()->empty_string()));
   __ j(not_equal, deferred->entry());
   // Get the first of the two strings and load its instance type.
   __ mov(string, FieldOperand(string, ConsString::kFirstOffset));
@@ -3011,6 +3172,56 @@
 }
 
 
+void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
+  class DeferredStringCharFromCode: public LDeferredCode {
+   public:
+    DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); }
+   private:
+    LStringCharFromCode* instr_;
+  };
+
+  DeferredStringCharFromCode* deferred =
+      new DeferredStringCharFromCode(this, instr);
+
+  ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
+  Register char_code = ToRegister(instr->char_code());
+  Register result = ToRegister(instr->result());
+  ASSERT(!char_code.is(result));
+
+  __ cmp(char_code, String::kMaxAsciiCharCode);
+  __ j(above, deferred->entry());
+  __ Set(result, Immediate(factory()->single_character_string_cache()));
+  __ mov(result, FieldOperand(result,
+                              char_code, times_pointer_size,
+                              FixedArray::kHeaderSize));
+  __ cmp(result, factory()->undefined_value());
+  __ j(equal, deferred->entry());
+  __ bind(deferred->exit());
+}
+
+
+void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
+  Register char_code = ToRegister(instr->char_code());
+  Register result = ToRegister(instr->result());
+
+  // TODO(3095996): Get rid of this. For now, we need to make the
+  // result register contain a valid pointer because it is already
+  // contained in the register pointer map.
+  __ Set(result, Immediate(0));
+
+  __ PushSafepointRegisters();
+  __ SmiTag(char_code);
+  __ push(char_code);
+  __ CallRuntimeSaveDoubles(Runtime::kCharFromCode);
+  RecordSafepointWithRegisters(
+      instr->pointer_map(), 1, Safepoint::kNoDeoptimizationIndex);
+  __ StoreToSafepointRegisterSlot(result, eax);
+  __ PopSafepointRegisters();
+}
+
+
 void LCodeGen::DoStringLength(LStringLength* instr) {
   Register string = ToRegister(instr->string());
   Register result = ToRegister(instr->result());
@@ -3163,17 +3374,15 @@
 
   // Heap number map check.
   __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
-         Factory::heap_number_map());
+         factory()->heap_number_map());
   __ j(equal, &heap_number);
 
-  __ cmp(input_reg, Factory::undefined_value());
+  __ cmp(input_reg, factory()->undefined_value());
   DeoptimizeIf(not_equal, env);
 
   // Convert undefined to NaN.
-  __ push(input_reg);
-  __ mov(input_reg, Factory::nan_value());
-  __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
-  __ pop(input_reg);
+  ExternalReference nan = ExternalReference::address_of_nan();
+  __ movdbl(result_reg, Operand::StaticVariable(nan));
   __ jmp(&done);
 
   // Heap number to XMM conversion.
@@ -3206,19 +3415,19 @@
 
   // Heap number map check.
   __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
-         Factory::heap_number_map());
+         factory()->heap_number_map());
 
   if (instr->truncating()) {
     __ j(equal, &heap_number);
     // Check for undefined. Undefined is converted to zero for truncating
     // conversions.
-    __ cmp(input_reg, Factory::undefined_value());
+    __ cmp(input_reg, factory()->undefined_value());
     DeoptimizeIf(not_equal, instr->environment());
     __ mov(input_reg, 0);
     __ jmp(&done);
 
     __ bind(&heap_number);
-    if (CpuFeatures::IsSupported(SSE3)) {
+    if (isolate()->cpu_features()->IsSupported(SSE3)) {
       CpuFeatures::Scope scope(SSE3);
       NearLabel convert;
       // Use more powerful conversion when sse3 is available.
@@ -3328,7 +3537,7 @@
     // the JS bitwise operations.
     __ cvttsd2si(result_reg, Operand(input_reg));
     __ cmp(result_reg, 0x80000000u);
-    if (CpuFeatures::IsSupported(SSE3)) {
+    if (isolate()->cpu_features()->IsSupported(SSE3)) {
       // This will deoptimize if the exponent of the input in out of range.
       CpuFeatures::Scope scope(SSE3);
       NearLabel convert, done;
@@ -3433,9 +3642,15 @@
 
 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
   LOperand* input = instr->InputAt(0);
-  ASSERT(input->IsRegister());
   __ test(ToRegister(input), Immediate(kSmiTagMask));
-  DeoptimizeIf(instr->condition(), instr->environment());
+  DeoptimizeIf(not_zero, instr->environment());
+}
+
+
+void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
+  LOperand* input = instr->InputAt(0);
+  __ test(ToRegister(input), Immediate(kSmiTagMask));
+  DeoptimizeIf(zero, instr->environment());
 }
 
 
@@ -3489,9 +3704,9 @@
 
 
 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) {
-  if (Heap::InNewSpace(*object)) {
+  if (isolate()->heap()->InNewSpace(*object)) {
     Handle<JSGlobalPropertyCell> cell =
-        Factory::NewJSGlobalPropertyCell(object);
+        isolate()->factory()->NewJSGlobalPropertyCell(object);
     __ mov(result, Operand::Cell(cell));
   } else {
     __ mov(result, object);
@@ -3561,7 +3776,13 @@
   __ push(FieldOperand(eax, JSFunction::kLiteralsOffset));
   __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
   __ push(Immediate(instr->hydrogen()->constant_properties()));
-  __ push(Immediate(Smi::FromInt(instr->hydrogen()->fast_elements() ? 1 : 0)));
+  int flags = instr->hydrogen()->fast_elements()
+      ? ObjectLiteral::kFastElements
+      : ObjectLiteral::kNoFlags;
+  flags |= instr->hydrogen()->has_function()
+      ? ObjectLiteral::kHasFunction
+      : ObjectLiteral::kNoFlags;
+  __ push(Immediate(Smi::FromInt(flags)));
 
   // Pick the right runtime function to call.
   if (instr->hydrogen()->depth() > 1) {
@@ -3572,6 +3793,13 @@
 }
 
 
+void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
+  ASSERT(ToRegister(instr->InputAt(0)).is(eax));
+  __ push(eax);
+  CallRuntime(Runtime::kToFastProperties, 1, instr);
+}
+
+
 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
   NearLabel materialized;
   // Registers will be used as follows:
@@ -3584,7 +3812,7 @@
   int literal_offset = FixedArray::kHeaderSize +
       instr->hydrogen()->literal_index() * kPointerSize;
   __ mov(ebx, FieldOperand(ecx, literal_offset));
-  __ cmp(ebx, Factory::undefined_value());
+  __ cmp(ebx, factory()->undefined_value());
   __ j(not_equal, &materialized);
 
   // Create regexp literal using runtime function
@@ -3629,16 +3857,17 @@
   // space for nested functions that don't need literals cloning.
   Handle<SharedFunctionInfo> shared_info = instr->shared_info();
   bool pretenure = instr->hydrogen()->pretenure();
-  if (shared_info->num_literals() == 0 && !pretenure) {
-    FastNewClosureStub stub;
+  if (!pretenure && shared_info->num_literals() == 0) {
+    FastNewClosureStub stub(
+        shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
     __ push(Immediate(shared_info));
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false);
   } else {
     __ push(Operand(ebp, StandardFrameConstants::kContextOffset));
     __ push(Immediate(shared_info));
     __ push(Immediate(pretenure
-                      ? Factory::true_value()
-                      : Factory::false_value()));
+                      ? factory()->true_value()
+                      : factory()->false_value()));
     CallRuntime(Runtime::kNewClosure, 3, instr, false);
   }
 }
@@ -3668,11 +3897,11 @@
                                                   instr->type_literal());
   __ j(final_branch_condition, &true_label);
   __ bind(&false_label);
-  __ mov(result, Factory::false_value());
+  __ mov(result, factory()->false_value());
   __ jmp(&done);
 
   __ bind(&true_label);
-  __ mov(result, Factory::true_value());
+  __ mov(result, factory()->true_value());
 
   __ bind(&done);
 }
@@ -3699,13 +3928,13 @@
                                  Register input,
                                  Handle<String> type_name) {
   Condition final_branch_condition = no_condition;
-  if (type_name->Equals(Heap::number_symbol())) {
+  if (type_name->Equals(heap()->number_symbol())) {
     __ JumpIfSmi(input, true_label);
     __ cmp(FieldOperand(input, HeapObject::kMapOffset),
-           Factory::heap_number_map());
+           factory()->heap_number_map());
     final_branch_condition = equal;
 
-  } else if (type_name->Equals(Heap::string_symbol())) {
+  } else if (type_name->Equals(heap()->string_symbol())) {
     __ JumpIfSmi(input, false_label);
     __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
     __ j(above_equal, false_label);
@@ -3713,14 +3942,14 @@
               1 << Map::kIsUndetectable);
     final_branch_condition = zero;
 
-  } else if (type_name->Equals(Heap::boolean_symbol())) {
-    __ cmp(input, Factory::true_value());
+  } else if (type_name->Equals(heap()->boolean_symbol())) {
+    __ cmp(input, factory()->true_value());
     __ j(equal, true_label);
-    __ cmp(input, Factory::false_value());
+    __ cmp(input, factory()->false_value());
     final_branch_condition = equal;
 
-  } else if (type_name->Equals(Heap::undefined_symbol())) {
-    __ cmp(input, Factory::undefined_value());
+  } else if (type_name->Equals(heap()->undefined_symbol())) {
+    __ cmp(input, factory()->undefined_value());
     __ j(equal, true_label);
     __ JumpIfSmi(input, false_label);
     // Check for undetectable objects => true.
@@ -3729,7 +3958,7 @@
               1 << Map::kIsUndetectable);
     final_branch_condition = not_zero;
 
-  } else if (type_name->Equals(Heap::function_symbol())) {
+  } else if (type_name->Equals(heap()->function_symbol())) {
     __ JumpIfSmi(input, false_label);
     __ CmpObjectType(input, JS_FUNCTION_TYPE, input);
     __ j(equal, true_label);
@@ -3737,9 +3966,9 @@
     __ CmpInstanceType(input, JS_REGEXP_TYPE);
     final_branch_condition = equal;
 
-  } else if (type_name->Equals(Heap::object_symbol())) {
+  } else if (type_name->Equals(heap()->object_symbol())) {
     __ JumpIfSmi(input, false_label);
-    __ cmp(input, Factory::null_value());
+    __ cmp(input, factory()->null_value());
     __ j(equal, true_label);
     // Regular expressions => 'function', not 'object'.
     __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, input);
@@ -3770,11 +3999,11 @@
   EmitIsConstructCall(result);
   __ j(equal, &true_label);
 
-  __ mov(result, Factory::false_value());
+  __ mov(result, factory()->false_value());
   __ jmp(&done);
 
   __ bind(&true_label);
-  __ mov(result, Factory::true_value());
+  __ mov(result, factory()->true_value());
 
   __ bind(&done);
 }
@@ -3838,8 +4067,7 @@
   // builtin)
   SafepointGenerator safepoint_generator(this,
                                          pointers,
-                                         env->deoptimization_index(),
-                                         true);
+                                         env->deoptimization_index());
   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
   __ push(Immediate(Smi::FromInt(strict_mode_flag())));
   __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, &safepoint_generator);
@@ -3849,7 +4077,8 @@
 void LCodeGen::DoStackCheck(LStackCheck* instr) {
   // Perform stack overflow check.
   NearLabel done;
-  ExternalReference stack_limit = ExternalReference::address_of_stack_limit();
+  ExternalReference stack_limit =
+      ExternalReference::address_of_stack_limit(isolate());
   __ cmp(esp, Operand::StaticVariable(stack_limit));
   __ j(above_equal, &done);
 
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index ecd6caa..4414e6a 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -68,6 +68,9 @@
   // Simple accessors.
   MacroAssembler* masm() const { return masm_; }
   CompilationInfo* info() const { return info_; }
+  Isolate* isolate() const { return info_->isolate(); }
+  Factory* factory() const { return isolate()->factory(); }
+  Heap* heap() const { return isolate()->heap(); }
 
   // Support for converting LOperands to assembler types.
   Operand ToOperand(LOperand* op) const;
@@ -95,6 +98,7 @@
   void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
   void DoDeferredStackCheck(LGoto* instr);
   void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
+  void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
   void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
                                         Label* map_check);
 
@@ -162,11 +166,11 @@
 
   void CallCode(Handle<Code> code, RelocInfo::Mode mode, LInstruction* instr,
                 bool adjusted = true);
-  void CallRuntime(Runtime::Function* fun, int argc, LInstruction* instr,
+  void CallRuntime(const Runtime::Function* fun, int argc, LInstruction* instr,
                    bool adjusted = true);
   void CallRuntime(Runtime::FunctionId id, int argc, LInstruction* instr,
                    bool adjusted = true) {
-    Runtime::Function* function = Runtime::FunctionForId(id);
+    const Runtime::Function* function = Runtime::FunctionForId(id);
     CallRuntime(function, argc, instr, adjusted);
   }
 
@@ -242,6 +246,10 @@
   // Caller should branch on equal condition.
   void EmitIsConstructCall(Register temp);
 
+  void EmitLoadField(Register result,
+                     Register object,
+                     Handle<Map> type,
+                     Handle<String> name);
 
   LChunk* const chunk_;
   MacroAssembler* const masm_;
diff --git a/src/ia32/lithium-gap-resolver-ia32.cc b/src/ia32/lithium-gap-resolver-ia32.cc
index 45c790f..eabfecc 100644
--- a/src/ia32/lithium-gap-resolver-ia32.cc
+++ b/src/ia32/lithium-gap-resolver-ia32.cc
@@ -25,6 +25,8 @@
 // (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 "ia32/lithium-gap-resolver-ia32.h"
 #include "ia32/lithium-codegen-ia32.h"
 
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 4440cdf..199a80a 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -1366,13 +1366,23 @@
   if (instr->representation().IsInteger32()) {
     ASSERT(instr->left()->representation().IsInteger32());
     ASSERT(instr->right()->representation().IsInteger32());
-    // The temporary operand is necessary to ensure that right is not allocated
-    // into edx.
-    LOperand* temp = FixedTemp(edx);
-    LOperand* value = UseFixed(instr->left(), eax);
-    LOperand* divisor = UseRegister(instr->right());
-    LModI* mod = new LModI(value, divisor, temp);
-    LInstruction* result = DefineFixed(mod, edx);
+
+    LInstruction* result;
+    if (instr->HasPowerOf2Divisor()) {
+      ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
+      LOperand* value = UseRegisterAtStart(instr->left());
+      LModI* mod = new LModI(value, UseOrConstant(instr->right()), NULL);
+      result = DefineSameAsFirst(mod);
+    } else {
+      // The temporary operand is necessary to ensure that right is
+      // not allocated into edx.
+      LOperand* temp = FixedTemp(edx);
+      LOperand* value = UseFixed(instr->left(), eax);
+      LOperand* divisor = UseRegister(instr->right());
+      LModI* mod = new LModI(value, divisor, temp);
+      result = DefineFixed(mod, edx);
+    }
+
     return (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
             instr->CheckFlag(HValue::kCanBeDivByZero))
         ? AssignEnvironment(result)
@@ -1577,9 +1587,10 @@
 }
 
 
-LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) {
+LInstruction* LChunkBuilder::DoExternalArrayLength(
+    HExternalArrayLength* instr) {
   LOperand* array = UseRegisterAtStart(instr->value());
-  return DefineAsRegister(new LPixelArrayLength(array));
+  return DefineAsRegister(new LExternalArrayLength(array));
 }
 
 
@@ -1622,8 +1633,9 @@
       LOperand* value = UseRegister(instr->value());
       bool needs_check = !instr->value()->type().IsSmi();
       if (needs_check) {
+        CpuFeatures* cpu_features = Isolate::Current()->cpu_features();
         LOperand* xmm_temp =
-            (instr->CanTruncateToInt32() && CpuFeatures::IsSupported(SSE3))
+            (instr->CanTruncateToInt32() && cpu_features->IsSupported(SSE3))
             ? NULL
             : FixedTemp(xmm1);
         LTaggedToI* res = new LTaggedToI(value, xmm_temp);
@@ -1644,7 +1656,7 @@
     } else {
       ASSERT(to.IsInteger32());
       bool needs_temp = instr->CanTruncateToInt32() &&
-          !CpuFeatures::IsSupported(SSE3);
+          !Isolate::Current()->cpu_features()->IsSupported(SSE3);
       LOperand* value = needs_temp ?
           UseTempRegister(instr->value()) : UseRegister(instr->value());
       LOperand* temp = needs_temp ? TempRegister() : NULL;
@@ -1672,7 +1684,7 @@
 
 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
-  return AssignEnvironment(new LCheckSmi(value, zero));
+  return AssignEnvironment(new LCheckNonSmi(value));
 }
 
 
@@ -1693,7 +1705,7 @@
 
 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
-  return AssignEnvironment(new LCheckSmi(value, not_zero));
+  return AssignEnvironment(new LCheckSmi(value));
 }
 
 
@@ -1778,6 +1790,21 @@
 }
 
 
+LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
+    HLoadNamedFieldPolymorphic* instr) {
+  ASSERT(instr->representation().IsTagged());
+  if (instr->need_generic()) {
+    LOperand* obj = UseFixed(instr->object(), eax);
+    LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
+    return MarkAsCall(DefineFixed(result, eax), instr);
+  } else {
+    LOperand* obj = UseRegisterAtStart(instr->object());
+    LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
+    return AssignEnvironment(DefineAsRegister(result));
+  }
+}
+
+
 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), esi);
   LOperand* object = UseFixed(instr->object(), eax);
@@ -1800,10 +1827,10 @@
 }
 
 
-LInstruction* LChunkBuilder::DoLoadPixelArrayExternalPointer(
-    HLoadPixelArrayExternalPointer* instr) {
+LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
+    HLoadExternalArrayPointer* instr) {
   LOperand* input = UseRegisterAtStart(instr->value());
-  return DefineAsRegister(new LLoadPixelArrayExternalPointer(input));
+  return DefineAsRegister(new LLoadExternalArrayPointer(input));
 }
 
 
@@ -1818,16 +1845,24 @@
 }
 
 
-LInstruction* LChunkBuilder::DoLoadPixelArrayElement(
-    HLoadPixelArrayElement* instr) {
-  ASSERT(instr->representation().IsInteger32());
+LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
+    HLoadKeyedSpecializedArrayElement* instr) {
+  ExternalArrayType array_type = instr->array_type();
+  Representation representation(instr->representation());
+  ASSERT((representation.IsInteger32() && array_type != kExternalFloatArray) ||
+         (representation.IsDouble() && array_type == kExternalFloatArray));
   ASSERT(instr->key()->representation().IsInteger32());
-  LOperand* external_pointer =
-      UseRegisterAtStart(instr->external_pointer());
-  LOperand* key = UseRegisterAtStart(instr->key());
-  LLoadPixelArrayElement* result =
-      new LLoadPixelArrayElement(external_pointer, key);
-  return DefineSameAsFirst(result);
+  LOperand* external_pointer = UseRegister(instr->external_pointer());
+  LOperand* key = UseRegister(instr->key());
+  LLoadKeyedSpecializedArrayElement* result =
+      new LLoadKeyedSpecializedArrayElement(external_pointer,
+                                            key);
+  LInstruction* load_instr = DefineAsRegister(result);
+  // An unsigned int array load might overflow and cause a deopt, make sure it
+  // has an environment.
+  return (array_type == kExternalUnsignedIntArray)
+      ? AssignEnvironment(load_instr)
+      : load_instr;
 }
 
 
@@ -1860,20 +1895,39 @@
 }
 
 
-LInstruction* LChunkBuilder::DoStorePixelArrayElement(
-    HStorePixelArrayElement* instr) {
-  ASSERT(instr->value()->representation().IsInteger32());
+LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
+    HStoreKeyedSpecializedArrayElement* instr) {
+  Representation representation(instr->value()->representation());
+  ExternalArrayType array_type = instr->array_type();
+  ASSERT((representation.IsInteger32() && array_type != kExternalFloatArray) ||
+         (representation.IsDouble() && array_type == kExternalFloatArray));
   ASSERT(instr->external_pointer()->representation().IsExternal());
   ASSERT(instr->key()->representation().IsInteger32());
 
   LOperand* external_pointer = UseRegister(instr->external_pointer());
-  LOperand* val = UseRegister(instr->value());
   LOperand* key = UseRegister(instr->key());
-  // The generated code requires that the clamped value is in a byte
-  // register. eax is an arbitrary choice to satisfy this requirement.
-  LOperand* clamped = FixedTemp(eax);
+  LOperand* temp = NULL;
 
-  return new LStorePixelArrayElement(external_pointer, key, val, clamped);
+  if (array_type == kExternalPixelArray) {
+    // The generated code for pixel array stores requires that the clamped value
+    // is in a byte register. eax is an arbitrary choice to satisfy this
+    // requirement.
+    temp = FixedTemp(eax);
+  }
+
+  LOperand* val = NULL;
+  if (array_type == kExternalByteArray ||
+      array_type == kExternalUnsignedByteArray) {
+    // We need a byte register in this case for the value.
+    val = UseFixed(instr->value(), eax);
+  } else {
+    val = UseRegister(instr->value());
+  }
+
+  return new LStoreKeyedSpecializedArrayElement(external_pointer,
+                                                key,
+                                                val,
+                                                temp);
 }
 
 
@@ -1932,6 +1986,13 @@
 }
 
 
+LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
+  LOperand* char_code = UseRegister(instr->value());
+  LStringCharFromCode* result = new LStringCharFromCode(char_code);
+  return AssignPointerMap(DefineAsRegister(result));
+}
+
+
 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
   LOperand* string = UseRegisterAtStart(instr->value());
   return DefineAsRegister(new LStringLength(string));
@@ -2011,6 +2072,13 @@
 }
 
 
+LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
+  LOperand* object = UseFixed(instr->value(), eax);
+  LToFastProperties* result = new LToFastProperties(object);
+  return MarkAsCall(DefineFixed(result, eax), instr);
+}
+
+
 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
   LTypeof* result = new LTypeof(UseAtStart(instr->value()));
   return MarkAsCall(DefineFixed(result, eax), instr);
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index f8cb871..a9d769b 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -70,6 +70,7 @@
   V(CheckFunction)                              \
   V(CheckInstanceType)                          \
   V(CheckMap)                                   \
+  V(CheckNonSmi)                                \
   V(CheckPrototypeMaps)                         \
   V(CheckSmi)                                   \
   V(ClassOfTest)                                \
@@ -89,6 +90,7 @@
   V(Deoptimize)                                 \
   V(DivI)                                       \
   V(DoubleToI)                                  \
+  V(ExternalArrayLength)                        \
   V(FixedArrayLength)                           \
   V(FunctionLiteral)                            \
   V(Gap)                                        \
@@ -117,14 +119,15 @@
   V(LazyBailout)                                \
   V(LoadContextSlot)                            \
   V(LoadElements)                               \
+  V(LoadExternalArrayPointer)                   \
   V(LoadFunctionPrototype)                      \
   V(LoadGlobal)                                 \
   V(LoadKeyedFastElement)                       \
   V(LoadKeyedGeneric)                           \
+  V(LoadKeyedSpecializedArrayElement)           \
   V(LoadNamedField)                             \
+  V(LoadNamedFieldPolymorphic)                  \
   V(LoadNamedGeneric)                           \
-  V(LoadPixelArrayElement)                      \
-  V(LoadPixelArrayExternalPointer)              \
   V(ModI)                                       \
   V(MulI)                                       \
   V(NumberTagD)                                 \
@@ -134,7 +137,6 @@
   V(OsrEntry)                                   \
   V(OuterContext)                               \
   V(Parameter)                                  \
-  V(PixelArrayLength)                           \
   V(Power)                                      \
   V(PushArgument)                               \
   V(RegExpLiteral)                              \
@@ -147,14 +149,16 @@
   V(StoreGlobal)                                \
   V(StoreKeyedFastElement)                      \
   V(StoreKeyedGeneric)                          \
+  V(StoreKeyedSpecializedArrayElement)          \
   V(StoreNamedField)                            \
   V(StoreNamedGeneric)                          \
-  V(StorePixelArrayElement)                     \
   V(StringCharCodeAt)                           \
+  V(StringCharFromCode)                         \
   V(StringLength)                               \
   V(SubI)                                       \
   V(TaggedToI)                                  \
   V(Throw)                                      \
+  V(ToFastProperties)                           \
   V(Typeof)                                     \
   V(TypeofIs)                                   \
   V(TypeofIsAndBranch)                          \
@@ -1036,14 +1040,14 @@
 };
 
 
-class LPixelArrayLength: public LTemplateInstruction<1, 1, 0> {
+class LExternalArrayLength: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LPixelArrayLength(LOperand* value) {
+  explicit LExternalArrayLength(LOperand* value) {
     inputs_[0] = value;
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel-array-length")
-  DECLARE_HYDROGEN_ACCESSOR(PixelArrayLength)
+  DECLARE_CONCRETE_INSTRUCTION(ExternalArrayLength, "external-array-length")
+  DECLARE_HYDROGEN_ACCESSOR(ExternalArrayLength)
 };
 
 
@@ -1168,6 +1172,21 @@
 
   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
   DECLARE_HYDROGEN_ACCESSOR(LoadNamedField)
+
+  LOperand* object() { return inputs_[0]; }
+};
+
+
+class LLoadNamedFieldPolymorphic: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LLoadNamedFieldPolymorphic(LOperand* object) {
+    inputs_[0] = object;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field-polymorphic")
+  DECLARE_HYDROGEN_ACCESSOR(LoadNamedFieldPolymorphic)
+
+  LOperand* object() { return inputs_[0]; }
 };
 
 
@@ -1211,14 +1230,14 @@
 };
 
 
-class LLoadPixelArrayExternalPointer: public LTemplateInstruction<1, 1, 0> {
+class LLoadExternalArrayPointer: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LLoadPixelArrayExternalPointer(LOperand* object) {
+  explicit LLoadExternalArrayPointer(LOperand* object) {
     inputs_[0] = object;
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
-                               "load-pixel-array-external-pointer")
+  DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer,
+                               "load-external-array-pointer")
 };
 
 
@@ -1237,19 +1256,23 @@
 };
 
 
-class LLoadPixelArrayElement: public LTemplateInstruction<1, 2, 0> {
+class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
  public:
-  LLoadPixelArrayElement(LOperand* external_pointer, LOperand* key) {
+  LLoadKeyedSpecializedArrayElement(LOperand* external_pointer,
+                                    LOperand* key) {
     inputs_[0] = external_pointer;
     inputs_[1] = key;
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayElement,
-                               "load-pixel-array-element")
-  DECLARE_HYDROGEN_ACCESSOR(LoadPixelArrayElement)
+  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement,
+                               "load-keyed-specialized-array-element")
+  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedSpecializedArrayElement)
 
   LOperand* external_pointer() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
+  ExternalArrayType array_type() const {
+    return hydrogen()->array_type();
+  }
 };
 
 
@@ -1489,7 +1512,7 @@
   DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
   DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
 
-  Runtime::Function* function() const { return hydrogen()->function(); }
+  const Runtime::Function* function() const { return hydrogen()->function(); }
   int arity() const { return hydrogen()->argument_count(); }
 };
 
@@ -1655,25 +1678,28 @@
 };
 
 
-class LStorePixelArrayElement: public LTemplateInstruction<0, 3, 1> {
+class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 1> {
  public:
-  LStorePixelArrayElement(LOperand* external_pointer,
-                          LOperand* key,
-                          LOperand* val,
-                          LOperand* clamped) {
+  LStoreKeyedSpecializedArrayElement(LOperand* external_pointer,
+                                     LOperand* key,
+                                     LOperand* val,
+                                     LOperand* temp) {
     inputs_[0] = external_pointer;
     inputs_[1] = key;
     inputs_[2] = val;
-    temps_[0] = clamped;
+    temps_[0] = temp;
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(StorePixelArrayElement,
-                               "store-pixel-array-element")
-  DECLARE_HYDROGEN_ACCESSOR(StorePixelArrayElement)
+  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement,
+                               "store-keyed-specialized-array-element")
+  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedSpecializedArrayElement)
 
   LOperand* external_pointer() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
+  ExternalArrayType array_type() const {
+    return hydrogen()->array_type();
+  }
 };
 
 
@@ -1715,6 +1741,19 @@
 };
 
 
+class LStringCharFromCode: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LStringCharFromCode(LOperand* char_code) {
+    inputs_[0] = char_code;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
+  DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
+
+  LOperand* char_code() { return inputs_[0]; }
+};
+
+
 class LStringLength: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LStringLength(LOperand* string) {
@@ -1778,20 +1817,21 @@
 
 class LCheckSmi: public LTemplateInstruction<0, 1, 0> {
  public:
-  LCheckSmi(LOperand* value, Condition condition)
-      : condition_(condition) {
+  explicit LCheckSmi(LOperand* value) {
     inputs_[0] = value;
   }
 
-  Condition condition() const { return condition_; }
+  DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi")
+};
 
-  virtual void CompileToNative(LCodeGen* generator);
-  virtual const char* Mnemonic() const {
-    return (condition_ == zero) ? "check-non-smi" : "check-smi";
+
+class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LCheckNonSmi(LOperand* value) {
+    inputs_[0] = value;
   }
 
- private:
-  Condition condition_;
+  DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi")
 };
 
 
@@ -1831,6 +1871,17 @@
 };
 
 
+class LToFastProperties: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LToFastProperties(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to-fast-properties")
+  DECLARE_HYDROGEN_ACCESSOR(ToFastProperties)
+};
+
+
 class LTypeof: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LTypeof(LOperand* value) {
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 91b6651..ba30c49 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -45,14 +45,14 @@
     : Assembler(buffer, size),
       generating_stub_(false),
       allow_stub_calls_(true),
-      code_object_(Heap::undefined_value()) {
+      code_object_(isolate()->heap()->undefined_value()) {
 }
 
 
 void MacroAssembler::RecordWriteHelper(Register object,
                                        Register addr,
                                        Register scratch) {
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     // Check that the object is not in new space.
     Label not_in_new_space;
     InNewSpace(object, scratch, not_equal, &not_in_new_space);
@@ -113,7 +113,7 @@
 
   // Clobber all input registers when running with the debug-code flag
   // turned on to provoke errors.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     mov(object, Immediate(BitCast<int32_t>(kZapValue)));
     mov(value, Immediate(BitCast<int32_t>(kZapValue)));
     mov(scratch, Immediate(BitCast<int32_t>(kZapValue)));
@@ -141,7 +141,7 @@
 
   // Clobber all input registers when running with the debug-code flag
   // turned on to provoke errors.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     mov(object, Immediate(BitCast<int32_t>(kZapValue)));
     mov(address, Immediate(BitCast<int32_t>(kZapValue)));
     mov(value, Immediate(BitCast<int32_t>(kZapValue)));
@@ -152,7 +152,7 @@
 #ifdef ENABLE_DEBUGGER_SUPPORT
 void MacroAssembler::DebugBreak() {
   Set(eax, Immediate(0));
-  mov(ebx, Immediate(ExternalReference(Runtime::kDebugBreak)));
+  mov(ebx, Immediate(ExternalReference(Runtime::kDebugBreak, isolate())));
   CEntryStub ces(1);
   call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
 }
@@ -231,7 +231,7 @@
 
 
 void MacroAssembler::FCmp() {
-  if (CpuFeatures::IsSupported(CMOV)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(CMOV)) {
     fucomip();
     ffree(0);
     fincstp();
@@ -250,7 +250,7 @@
   test(object, Immediate(kSmiTagMask));
   j(zero, &ok);
   cmp(FieldOperand(object, HeapObject::kMapOffset),
-      Factory::heap_number_map());
+      isolate()->factory()->heap_number_map());
   Assert(equal, "Operand not a number");
   bind(&ok);
 }
@@ -285,15 +285,15 @@
   push(esi);
   push(Immediate(Smi::FromInt(type)));
   push(Immediate(CodeObject()));
-  if (FLAG_debug_code) {
-    cmp(Operand(esp, 0), Immediate(Factory::undefined_value()));
+  if (emit_debug_code()) {
+    cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value()));
     Check(not_equal, "code object not properly patched");
   }
 }
 
 
 void MacroAssembler::LeaveFrame(StackFrame::Type type) {
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset),
         Immediate(Smi::FromInt(type)));
     Check(equal, "stack frame types must match");
@@ -316,8 +316,10 @@
   push(Immediate(CodeObject()));  // Accessed from ExitFrame::code_slot.
 
   // 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);
+  ExternalReference c_entry_fp_address(Isolate::k_c_entry_fp_address,
+                                       isolate());
+  ExternalReference context_address(Isolate::k_context_address,
+                                    isolate());
   mov(Operand::StaticVariable(c_entry_fp_address), ebp);
   mov(Operand::StaticVariable(context_address), esi);
 }
@@ -339,7 +341,7 @@
   }
 
   // Get the required frame alignment for the OS.
-  static const int kFrameAlignment = OS::ActivationFrameAlignment();
+  const int kFrameAlignment = OS::ActivationFrameAlignment();
   if (kFrameAlignment > 0) {
     ASSERT(IsPowerOf2(kFrameAlignment));
     and_(esp, -kFrameAlignment);
@@ -358,7 +360,8 @@
   mov(edi, Operand(eax));
   lea(esi, Operand(ebp, eax, times_4, offset));
 
-  EnterExitFrameEpilogue(2, save_doubles);
+  // Reserve space for argc, argv and isolate.
+  EnterExitFrameEpilogue(3, save_doubles);
 }
 
 
@@ -394,14 +397,15 @@
 
 void MacroAssembler::LeaveExitFrameEpilogue() {
   // Restore current context from top and clear it in debug mode.
-  ExternalReference context_address(Top::k_context_address);
+  ExternalReference context_address(Isolate::k_context_address, isolate());
   mov(esi, Operand::StaticVariable(context_address));
 #ifdef DEBUG
   mov(Operand::StaticVariable(context_address), Immediate(0));
 #endif
 
   // Clear the top frame.
-  ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
+  ExternalReference c_entry_fp_address(Isolate::k_c_entry_fp_address,
+                                       isolate());
   mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0));
 }
 
@@ -435,15 +439,19 @@
     push(Immediate(0));  // NULL frame pointer.
   }
   // Save the current handler as the next handler.
-  push(Operand::StaticVariable(ExternalReference(Top::k_handler_address)));
+  push(Operand::StaticVariable(ExternalReference(Isolate::k_handler_address,
+                                                 isolate())));
   // Link this handler as the new current one.
-  mov(Operand::StaticVariable(ExternalReference(Top::k_handler_address)), esp);
+  mov(Operand::StaticVariable(ExternalReference(Isolate::k_handler_address,
+                                                isolate())),
+      esp);
 }
 
 
 void MacroAssembler::PopTryHandler() {
   ASSERT_EQ(0, StackHandlerConstants::kNextOffset);
-  pop(Operand::StaticVariable(ExternalReference(Top::k_handler_address)));
+  pop(Operand::StaticVariable(ExternalReference(Isolate::k_handler_address,
+                                                isolate())));
   add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize));
 }
 
@@ -458,7 +466,8 @@
   }
 
   // Drop the sp to the top of the handler.
-  ExternalReference handler_address(Top::k_handler_address);
+  ExternalReference handler_address(Isolate::k_handler_address,
+                                    isolate());
   mov(esp, Operand::StaticVariable(handler_address));
 
   // Restore next handler and frame pointer, discard handler state.
@@ -494,7 +503,8 @@
   }
 
   // Drop sp to the top stack handler.
-  ExternalReference handler_address(Top::k_handler_address);
+  ExternalReference handler_address(Isolate::k_handler_address,
+                                    isolate());
   mov(esp, Operand::StaticVariable(handler_address));
 
   // Unwind the handlers until the ENTRY handler is found.
@@ -516,12 +526,15 @@
 
   if (type == OUT_OF_MEMORY) {
     // Set external caught exception to false.
-    ExternalReference external_caught(Top::k_external_caught_exception_address);
+    ExternalReference external_caught(
+        Isolate::k_external_caught_exception_address,
+        isolate());
     mov(eax, false);
     mov(Operand::StaticVariable(external_caught), eax);
 
     // Set pending exception and eax to out of memory exception.
-    ExternalReference pending_exception(Top::k_pending_exception_address);
+    ExternalReference pending_exception(Isolate::k_pending_exception_address,
+                                        isolate());
     mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
     mov(Operand::StaticVariable(pending_exception), eax);
   }
@@ -550,7 +563,7 @@
   mov(scratch, Operand(ebp, StandardFrameConstants::kContextOffset));
 
   // When generating debug code, make sure the lexical context is set.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     cmp(Operand(scratch), Immediate(0));
     Check(not_equal, "we should not have an empty lexical context");
   }
@@ -560,11 +573,11 @@
   mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset));
 
   // Check the context is a global context.
-  if (FLAG_debug_code) {
+  if (emit_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());
+    cmp(scratch, isolate()->factory()->global_context_map());
     Check(equal, "JSGlobalObject::global_context should be a global context.");
     pop(scratch);
   }
@@ -584,14 +597,14 @@
   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());
+  if (emit_debug_code()) {
+    cmp(holder_reg, isolate()->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());
+    cmp(holder_reg, isolate()->factory()->global_context_map());
     Check(equal, "JSGlobalObject::global_context should be a global context.");
     pop(holder_reg);
   }
@@ -611,7 +624,7 @@
                                              Register scratch,
                                              AllocationFlags flags) {
   ExternalReference new_space_allocation_top =
-      ExternalReference::new_space_allocation_top_address();
+      ExternalReference::new_space_allocation_top_address(isolate());
 
   // Just return if allocation top is already known.
   if ((flags & RESULT_CONTAINS_TOP) != 0) {
@@ -637,13 +650,13 @@
 
 void MacroAssembler::UpdateAllocationTopHelper(Register result_end,
                                                Register scratch) {
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     test(result_end, Immediate(kObjectAlignmentMask));
     Check(zero, "Unaligned allocation in new space");
   }
 
   ExternalReference new_space_allocation_top =
-      ExternalReference::new_space_allocation_top_address();
+      ExternalReference::new_space_allocation_top_address(isolate());
 
   // Update new top. Use scratch if available.
   if (scratch.is(no_reg)) {
@@ -661,7 +674,7 @@
                                         Label* gc_required,
                                         AllocationFlags flags) {
   if (!FLAG_inline_new) {
-    if (FLAG_debug_code) {
+    if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
       mov(result, Immediate(0x7091));
       if (result_end.is_valid()) {
@@ -683,7 +696,7 @@
 
   // Calculate new top and bail out if new space is exhausted.
   ExternalReference new_space_allocation_limit =
-      ExternalReference::new_space_allocation_limit_address();
+      ExternalReference::new_space_allocation_limit_address(isolate());
 
   if (!top_reg.is(result)) {
     mov(top_reg, result);
@@ -718,7 +731,7 @@
                                         Label* gc_required,
                                         AllocationFlags flags) {
   if (!FLAG_inline_new) {
-    if (FLAG_debug_code) {
+    if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
       mov(result, Immediate(0x7091));
       mov(result_end, Immediate(0x7191));
@@ -737,7 +750,7 @@
 
   // Calculate new top and bail out if new space is exhausted.
   ExternalReference new_space_allocation_limit =
-      ExternalReference::new_space_allocation_limit_address();
+      ExternalReference::new_space_allocation_limit_address(isolate());
 
   // We assume that element_count*element_size + header_size does not
   // overflow.
@@ -764,7 +777,7 @@
                                         Label* gc_required,
                                         AllocationFlags flags) {
   if (!FLAG_inline_new) {
-    if (FLAG_debug_code) {
+    if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
       mov(result, Immediate(0x7091));
       mov(result_end, Immediate(0x7191));
@@ -783,7 +796,7 @@
 
   // Calculate new top and bail out if new space is exhausted.
   ExternalReference new_space_allocation_limit =
-      ExternalReference::new_space_allocation_limit_address();
+      ExternalReference::new_space_allocation_limit_address(isolate());
   if (!object_size.is(result_end)) {
     mov(result_end, object_size);
   }
@@ -804,7 +817,7 @@
 
 void MacroAssembler::UndoAllocationInNewSpace(Register object) {
   ExternalReference new_space_allocation_top =
-      ExternalReference::new_space_allocation_top_address();
+      ExternalReference::new_space_allocation_top_address(isolate());
 
   // Make sure the object has no tag before resetting top.
   and_(Operand(object), Immediate(~kHeapObjectTagMask));
@@ -830,7 +843,7 @@
 
   // Set the map.
   mov(FieldOperand(result, HeapObject::kMapOffset),
-      Immediate(Factory::heap_number_map()));
+      Immediate(isolate()->factory()->heap_number_map()));
 }
 
 
@@ -860,7 +873,7 @@
 
   // Set the map, length and hash field.
   mov(FieldOperand(result, HeapObject::kMapOffset),
-      Immediate(Factory::string_map()));
+      Immediate(isolate()->factory()->string_map()));
   mov(scratch1, length);
   SmiTag(scratch1);
   mov(FieldOperand(result, String::kLengthOffset), scratch1);
@@ -895,7 +908,7 @@
 
   // Set the map, length and hash field.
   mov(FieldOperand(result, HeapObject::kMapOffset),
-      Immediate(Factory::ascii_string_map()));
+      Immediate(isolate()->factory()->ascii_string_map()));
   mov(scratch1, length);
   SmiTag(scratch1);
   mov(FieldOperand(result, String::kLengthOffset), scratch1);
@@ -921,7 +934,7 @@
 
   // Set the map, length and hash field.
   mov(FieldOperand(result, HeapObject::kMapOffset),
-      Immediate(Factory::ascii_string_map()));
+      Immediate(isolate()->factory()->ascii_string_map()));
   mov(FieldOperand(result, String::kLengthOffset),
       Immediate(Smi::FromInt(length)));
   mov(FieldOperand(result, String::kHashFieldOffset),
@@ -943,7 +956,7 @@
 
   // Set the map. The other fields are left uninitialized.
   mov(FieldOperand(result, HeapObject::kMapOffset),
-      Immediate(Factory::cons_string_map()));
+      Immediate(isolate()->factory()->cons_string_map()));
 }
 
 
@@ -961,7 +974,7 @@
 
   // Set the map. The other fields are left uninitialized.
   mov(FieldOperand(result, HeapObject::kMapOffset),
-      Immediate(Factory::cons_ascii_string_map()));
+      Immediate(isolate()->factory()->cons_ascii_string_map()));
 }
 
 
@@ -1079,7 +1092,7 @@
   // 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()));
+  cmp(Operand(result), Immediate(isolate()->factory()->the_hole_value()));
   j(equal, miss, not_taken);
 
   // If the function does not have an initial map, we're done.
@@ -1145,7 +1158,7 @@
   if (num_arguments > 0) {
     add(Operand(esp), Immediate(num_arguments * kPointerSize));
   }
-  mov(eax, Immediate(Factory::undefined_value()));
+  mov(eax, Immediate(isolate()->factory()->undefined_value()));
 }
 
 
@@ -1174,9 +1187,9 @@
 
 
 void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
-  Runtime::Function* function = Runtime::FunctionForId(id);
+  const Runtime::Function* function = Runtime::FunctionForId(id);
   Set(eax, Immediate(function->nargs));
-  mov(ebx, Immediate(ExternalReference(function)));
+  mov(ebx, Immediate(ExternalReference(function, isolate())));
   CEntryStub ces(1);
   ces.SaveDoubles();
   CallStub(&ces);
@@ -1189,7 +1202,8 @@
 }
 
 
-void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
+void MacroAssembler::CallRuntime(const 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.
@@ -1203,19 +1217,19 @@
   // should remove this need and make the runtime routine entry code
   // smarter.
   Set(eax, Immediate(num_arguments));
-  mov(ebx, Immediate(ExternalReference(f)));
+  mov(ebx, Immediate(ExternalReference(f, isolate())));
   CEntryStub ces(1);
   CallStub(&ces);
 }
 
 
-MaybeObject* MacroAssembler::TryCallRuntime(Runtime::Function* f,
+MaybeObject* MacroAssembler::TryCallRuntime(const Runtime::Function* f,
                                             int num_arguments) {
   if (f->nargs >= 0 && f->nargs != num_arguments) {
     IllegalOperation(num_arguments);
     // Since we did not call the stub, there was no allocation failure.
     // Return some non-failure object.
-    return Heap::undefined_value();
+    return isolate()->heap()->undefined_value();
   }
 
   // TODO(1236192): Most runtime routines don't need the number of
@@ -1223,7 +1237,7 @@
   // should remove this need and make the runtime routine entry code
   // smarter.
   Set(eax, Immediate(num_arguments));
-  mov(ebx, Immediate(ExternalReference(f)));
+  mov(ebx, Immediate(ExternalReference(f, isolate())));
   CEntryStub ces(1);
   return TryCallStub(&ces);
 }
@@ -1265,7 +1279,9 @@
 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
                                      int num_arguments,
                                      int result_size) {
-  TailCallExternalReference(ExternalReference(fid), num_arguments, result_size);
+  TailCallExternalReference(ExternalReference(fid, isolate()),
+                            num_arguments,
+                            result_size);
 }
 
 
@@ -1273,7 +1289,7 @@
                                                 int num_arguments,
                                                 int result_size) {
   return TryTailCallExternalReference(
-      ExternalReference(fid), num_arguments, result_size);
+      ExternalReference(fid, isolate()), num_arguments, result_size);
 }
 
 
@@ -1320,7 +1336,7 @@
     // pointer to out cell.
     lea(scratch, Operand(esp, (argc + 1) * kPointerSize));
     mov(Operand(esp, 0 * kPointerSize), scratch);  // output.
-    if (FLAG_debug_code) {
+    if (emit_debug_code()) {
       mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0));  // out cell.
     }
   }
@@ -1373,9 +1389,9 @@
 
   // Check if the function scheduled an exception.
   ExternalReference scheduled_exception_address =
-      ExternalReference::scheduled_exception_address();
+      ExternalReference::scheduled_exception_address(isolate());
   cmp(Operand::StaticVariable(scheduled_exception_address),
-      Immediate(Factory::the_hole_value()));
+      Immediate(isolate()->factory()->the_hole_value()));
   j(not_equal, &promote_scheduled_exception, not_taken);
   LeaveApiExitFrame();
   ret(stack_space * kPointerSize);
@@ -1387,14 +1403,17 @@
   }
   bind(&empty_handle);
   // It was zero; the result is undefined.
-  mov(eax, Factory::undefined_value());
+  mov(eax, isolate()->factory()->undefined_value());
   jmp(&prologue);
 
   // HandleScope limit has changed. Delete allocated extensions.
+  ExternalReference delete_extensions =
+      ExternalReference::delete_handle_scope_extensions(isolate());
   bind(&delete_allocated_handles);
   mov(Operand::StaticVariable(limit_address), edi);
   mov(edi, eax);
-  mov(eax, Immediate(ExternalReference::delete_handle_scope_extensions()));
+  mov(Operand(esp, 0), Immediate(ExternalReference::isolate_address()));
+  mov(eax, Immediate(delete_extensions));
   call(Operand(eax));
   mov(eax, edi);
   jmp(&leave_exit_frame);
@@ -1424,7 +1443,7 @@
                                     const ParameterCount& actual,
                                     Handle<Code> code_constant,
                                     const Operand& code_operand,
-                                    Label* done,
+                                    NearLabel* done,
                                     InvokeFlag flag,
                                     PostCallGenerator* post_call_generator) {
   bool definitely_matches = false;
@@ -1467,7 +1486,7 @@
 
   if (!definitely_matches) {
     Handle<Code> adaptor =
-        Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
+        isolate()->builtins()->ArgumentsAdaptorTrampoline();
     if (!code_constant.is_null()) {
       mov(edx, Immediate(code_constant));
       add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag));
@@ -1492,7 +1511,7 @@
                                 const ParameterCount& actual,
                                 InvokeFlag flag,
                                 PostCallGenerator* post_call_generator) {
-  Label done;
+  NearLabel done;
   InvokePrologue(expected, actual, Handle<Code>::null(), code,
                  &done, flag, post_call_generator);
   if (flag == CALL_FUNCTION) {
@@ -1512,7 +1531,7 @@
                                 RelocInfo::Mode rmode,
                                 InvokeFlag flag,
                                 PostCallGenerator* post_call_generator) {
-  Label done;
+  NearLabel done;
   Operand dummy(eax);
   InvokePrologue(expected, actual, code, dummy, &done,
                  flag, post_call_generator);
@@ -1621,7 +1640,7 @@
   // (i.e., the static scope chain and runtime context chain do not agree).
   // A variable occurring in such a scope should have slot type LOOKUP and
   // not CONTEXT.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     cmp(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
     Check(equal, "Yo dawg, I heard you liked function contexts "
                  "so I put function contexts in all your contexts");
@@ -1643,9 +1662,9 @@
                                                   Register map) {
   // Load the initial map.  The global functions all have initial maps.
   mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     Label ok, fail;
-    CheckMap(map, Factory::meta_map(), &fail, false);
+    CheckMap(map, isolate()->factory()->meta_map(), &fail, false);
     jmp(&ok);
     bind(&fail);
     Abort("Global functions must have initial map");
@@ -1787,18 +1806,19 @@
 
 
 void MacroAssembler::Assert(Condition cc, const char* msg) {
-  if (FLAG_debug_code) Check(cc, msg);
+  if (emit_debug_code()) Check(cc, msg);
 }
 
 
 void MacroAssembler::AssertFastElements(Register elements) {
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
+    Factory* factory = isolate()->factory();
     Label ok;
     cmp(FieldOperand(elements, HeapObject::kMapOffset),
-        Immediate(Factory::fixed_array_map()));
+        Immediate(factory->fixed_array_map()));
     j(equal, &ok);
     cmp(FieldOperand(elements, HeapObject::kMapOffset),
-        Immediate(Factory::fixed_cow_array_map()));
+        Immediate(factory->fixed_cow_array_map()));
     j(equal, &ok);
     Abort("JSObject with fast elements map has slow elements");
     bind(&ok);
@@ -1860,10 +1880,10 @@
 void MacroAssembler::JumpIfNotNumber(Register reg,
                                      TypeInfo info,
                                      Label* on_not_number) {
-  if (FLAG_debug_code) AbortIfSmi(reg);
+  if (emit_debug_code()) AbortIfSmi(reg);
   if (!info.IsNumber()) {
     cmp(FieldOperand(reg, HeapObject::kMapOffset),
-        Factory::heap_number_map());
+        isolate()->factory()->heap_number_map());
     j(not_equal, on_not_number);
   }
 }
@@ -1874,7 +1894,7 @@
                                     Register scratch,
                                     TypeInfo info,
                                     Label* on_not_int32) {
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     AbortIfSmi(source);
     AbortIfNotNumber(source);
   }
@@ -1968,6 +1988,9 @@
 
 
 void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
+  // Reserve space for Isolate address which is always passed as last parameter
+  num_arguments += 1;
+
   int frameAlignment = OS::ActivationFrameAlignment();
   if (frameAlignment != 0) {
     // Make stack end at alignment and make room for num_arguments words
@@ -1993,8 +2016,13 @@
 
 void MacroAssembler::CallCFunction(Register function,
                                    int num_arguments) {
+  // Pass current isolate address as additional parameter.
+  mov(Operand(esp, num_arguments * kPointerSize),
+      Immediate(ExternalReference::isolate_address()));
+  num_arguments += 1;
+
   // Check stack alignment.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     CheckStackAlignment();
   }
 
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index 62bb0f3..bafb175 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -474,13 +474,13 @@
   void StubReturn(int argc);
 
   // Call a runtime routine.
-  void CallRuntime(Runtime::Function* f, int num_arguments);
+  void CallRuntime(const Runtime::Function* f, int num_arguments);
   void CallRuntimeSaveDoubles(Runtime::FunctionId id);
 
   // Call a runtime function, returning the CodeStub object called.
   // Try to generate the stub code if necessary.  Do not perform a GC
   // but instead return a retry after GC failure.
-  MUST_USE_RESULT MaybeObject* TryCallRuntime(Runtime::Function* f,
+  MUST_USE_RESULT MaybeObject* TryCallRuntime(const Runtime::Function* f,
                                               int num_arguments);
 
   // Convenience function: Same as above, but takes the fid instead.
@@ -646,7 +646,7 @@
                       const ParameterCount& actual,
                       Handle<Code> code_constant,
                       const Operand& code_operand,
-                      Label* done,
+                      NearLabel* done,
                       InvokeFlag flag,
                       PostCallGenerator* post_call_generator = NULL);
 
@@ -695,14 +695,16 @@
     // The mask isn't really an address.  We load it as an external reference in
     // case the size of the new space is different between the snapshot maker
     // and the running system.
-    and_(Operand(scratch), Immediate(ExternalReference::new_space_mask()));
-    cmp(Operand(scratch), Immediate(ExternalReference::new_space_start()));
+    and_(Operand(scratch),
+         Immediate(ExternalReference::new_space_mask(isolate())));
+    cmp(Operand(scratch),
+        Immediate(ExternalReference::new_space_start(isolate())));
     j(cc, branch);
   } else {
     int32_t new_space_start = reinterpret_cast<int32_t>(
-        ExternalReference::new_space_start().address());
+        ExternalReference::new_space_start(isolate()).address());
     lea(scratch, Operand(object, -new_space_start));
-    and_(scratch, Heap::NewSpaceMask());
+    and_(scratch, isolate()->heap()->NewSpaceMask());
     j(cc, branch);
   }
 }
diff --git a/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc
index 1213448..f1c773b 100644
--- a/src/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/ia32/regexp-macro-assembler-ia32.cc
@@ -56,6 +56,7 @@
  *
  * Each call to a public method should retain this convention.
  * The stack will have the following structure:
+ *       - Isolate* isolate     (Address of the current isolate)
  *       - direct_call          (if 1, direct call from JavaScript code, if 0
  *                               call through the runtime system)
  *       - stack_area_base      (High end of the memory area to use as
@@ -392,7 +393,7 @@
     __ mov(Operand(esp, 0 * kPointerSize), edx);
 
     ExternalReference compare =
-        ExternalReference::re_case_insensitive_compare_uc16();
+        ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate());
     __ CallCFunction(compare, argument_count);
     // Pop original values before reacting on result value.
     __ pop(ebx);
@@ -678,7 +679,7 @@
   Label stack_ok;
 
   ExternalReference stack_limit =
-      ExternalReference::address_of_stack_limit();
+      ExternalReference::address_of_stack_limit(masm_->isolate());
   __ mov(ecx, esp);
   __ sub(ecx, Operand::StaticVariable(stack_limit));
   // Handle it if the stack pointer is already below the stack limit.
@@ -842,7 +843,8 @@
     __ lea(eax, Operand(ebp, kStackHighEnd));
     __ mov(Operand(esp, 1 * kPointerSize), eax);
     __ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer());
-    ExternalReference grow_stack = ExternalReference::re_grow_stack();
+    ExternalReference grow_stack =
+        ExternalReference::re_grow_stack(masm_->isolate());
     __ CallCFunction(grow_stack, num_arguments);
     // If return NULL, we have failed to grow the stack, and
     // must exit with a stack-overflow exception.
@@ -866,10 +868,11 @@
 
   CodeDesc code_desc;
   masm_->GetCode(&code_desc);
-  Handle<Code> code = Factory::NewCode(code_desc,
-                                       Code::ComputeFlags(Code::REGEXP),
-                                       masm_->CodeObject());
-  PROFILE(RegExpCodeCreateEvent(*code, *source));
+  Handle<Code> code =
+      masm_->isolate()->factory()->NewCode(code_desc,
+                                           Code::ComputeFlags(Code::REGEXP),
+                                           masm_->CodeObject());
+  PROFILE(masm_->isolate(), RegExpCodeCreateEvent(*code, *source));
   return Handle<Object>::cast(code);
 }
 
@@ -1024,7 +1027,7 @@
   __ lea(eax, Operand(esp, -kPointerSize));
   __ mov(Operand(esp, 0 * kPointerSize), eax);
   ExternalReference check_stack_guard =
-      ExternalReference::re_check_stack_guard_state();
+      ExternalReference::re_check_stack_guard_state(masm_->isolate());
   __ CallCFunction(check_stack_guard, num_arguments);
 }
 
@@ -1039,8 +1042,10 @@
 int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
                                                    Code* re_code,
                                                    Address re_frame) {
-  if (StackGuard::IsStackOverflow()) {
-    Top::StackOverflow();
+  Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
+  ASSERT(isolate == Isolate::Current());
+  if (isolate->stack_guard()->IsStackOverflow()) {
+    isolate->StackOverflow();
     return EXCEPTION;
   }
 
@@ -1196,7 +1201,7 @@
   // Check for preemption.
   Label no_preempt;
   ExternalReference stack_limit =
-      ExternalReference::address_of_stack_limit();
+      ExternalReference::address_of_stack_limit(masm_->isolate());
   __ cmp(esp, Operand::StaticVariable(stack_limit));
   __ j(above, &no_preempt, taken);
 
@@ -1209,7 +1214,7 @@
 void RegExpMacroAssemblerIA32::CheckStackLimit() {
   Label no_stack_overflow;
   ExternalReference stack_limit =
-      ExternalReference::address_of_regexp_stack_limit();
+      ExternalReference::address_of_regexp_stack_limit(masm_->isolate());
   __ cmp(backtrack_stackpointer(), Operand::StaticVariable(stack_limit));
   __ j(above, &no_stack_overflow);
 
diff --git a/src/ia32/regexp-macro-assembler-ia32.h b/src/ia32/regexp-macro-assembler-ia32.h
index 51e2cb0..0af61f2 100644
--- a/src/ia32/regexp-macro-assembler-ia32.h
+++ b/src/ia32/regexp-macro-assembler-ia32.h
@@ -126,6 +126,7 @@
   static const int kRegisterOutput = kInputEnd + kPointerSize;
   static const int kStackHighEnd = kRegisterOutput + kPointerSize;
   static const int kDirectCall = kStackHighEnd + kPointerSize;
+  static const int kIsolate = kDirectCall + kPointerSize;
   // Below the frame pointer - local stack variables.
   // When adding local variables remember to push space for them in
   // the frame in GetCode.
diff --git a/src/ia32/register-allocator-ia32.cc b/src/ia32/register-allocator-ia32.cc
index d840c0c..6db13d4 100644
--- a/src/ia32/register-allocator-ia32.cc
+++ b/src/ia32/register-allocator-ia32.cc
@@ -42,12 +42,14 @@
 void Result::ToRegister() {
   ASSERT(is_valid());
   if (is_constant()) {
-    Result fresh = CodeGeneratorScope::Current()->allocator()->Allocate();
+    CodeGenerator* code_generator =
+        CodeGeneratorScope::Current(Isolate::Current());
+    Result fresh = code_generator->allocator()->Allocate();
     ASSERT(fresh.is_valid());
     if (is_untagged_int32()) {
       fresh.set_untagged_int32(true);
       if (handle()->IsSmi()) {
-      CodeGeneratorScope::Current()->masm()->Set(
+      code_generator->masm()->Set(
           fresh.reg(),
           Immediate(Smi::cast(*handle())->value()));
       } else if (handle()->IsHeapNumber()) {
@@ -56,25 +58,23 @@
         if (double_value == 0 && signbit(double_value)) {
           // Negative zero must not be converted to an int32 unless
           // the context allows it.
-          CodeGeneratorScope::Current()->unsafe_bailout_->Branch(equal);
-          CodeGeneratorScope::Current()->unsafe_bailout_->Branch(not_equal);
+          code_generator->unsafe_bailout_->Branch(equal);
+          code_generator->unsafe_bailout_->Branch(not_equal);
         } else if (double_value == value) {
-          CodeGeneratorScope::Current()->masm()->Set(
-              fresh.reg(), Immediate(value));
+          code_generator->masm()->Set(fresh.reg(), Immediate(value));
         } else {
-          CodeGeneratorScope::Current()->unsafe_bailout_->Branch(equal);
-          CodeGeneratorScope::Current()->unsafe_bailout_->Branch(not_equal);
+          code_generator->unsafe_bailout_->Branch(equal);
+          code_generator->unsafe_bailout_->Branch(not_equal);
         }
       } else {
         // Constant is not a number.  This was not predicted by AST analysis.
-        CodeGeneratorScope::Current()->unsafe_bailout_->Branch(equal);
-        CodeGeneratorScope::Current()->unsafe_bailout_->Branch(not_equal);
+        code_generator->unsafe_bailout_->Branch(equal);
+        code_generator->unsafe_bailout_->Branch(not_equal);
       }
-    } else if (CodeGeneratorScope::Current()->IsUnsafeSmi(handle())) {
-      CodeGeneratorScope::Current()->MoveUnsafeSmi(fresh.reg(), handle());
+    } else if (code_generator->IsUnsafeSmi(handle())) {
+      code_generator->MoveUnsafeSmi(fresh.reg(), handle());
     } else {
-      CodeGeneratorScope::Current()->masm()->Set(fresh.reg(),
-                                                 Immediate(handle()));
+      code_generator->masm()->Set(fresh.reg(), Immediate(handle()));
     }
     // This result becomes a copy of the fresh one.
     fresh.set_type_info(type_info());
@@ -85,17 +85,19 @@
 
 
 void Result::ToRegister(Register target) {
+  CodeGenerator* code_generator =
+      CodeGeneratorScope::Current(Isolate::Current());
   ASSERT(is_valid());
   if (!is_register() || !reg().is(target)) {
-    Result fresh = CodeGeneratorScope::Current()->allocator()->Allocate(target);
+    Result fresh = code_generator->allocator()->Allocate(target);
     ASSERT(fresh.is_valid());
     if (is_register()) {
-      CodeGeneratorScope::Current()->masm()->mov(fresh.reg(), reg());
+      code_generator->masm()->mov(fresh.reg(), reg());
     } else {
       ASSERT(is_constant());
       if (is_untagged_int32()) {
         if (handle()->IsSmi()) {
-          CodeGeneratorScope::Current()->masm()->Set(
+          code_generator->masm()->Set(
               fresh.reg(),
               Immediate(Smi::cast(*handle())->value()));
         } else {
@@ -105,22 +107,20 @@
           if (double_value == 0 && signbit(double_value)) {
             // Negative zero must not be converted to an int32 unless
             // the context allows it.
-            CodeGeneratorScope::Current()->unsafe_bailout_->Branch(equal);
-            CodeGeneratorScope::Current()->unsafe_bailout_->Branch(not_equal);
+            code_generator->unsafe_bailout_->Branch(equal);
+            code_generator->unsafe_bailout_->Branch(not_equal);
           } else if (double_value == value) {
-            CodeGeneratorScope::Current()->masm()->Set(
-                fresh.reg(), Immediate(value));
+            code_generator->masm()->Set(fresh.reg(), Immediate(value));
           } else {
-            CodeGeneratorScope::Current()->unsafe_bailout_->Branch(equal);
-            CodeGeneratorScope::Current()->unsafe_bailout_->Branch(not_equal);
+            code_generator->unsafe_bailout_->Branch(equal);
+            code_generator->unsafe_bailout_->Branch(not_equal);
           }
         }
       } else {
-        if (CodeGeneratorScope::Current()->IsUnsafeSmi(handle())) {
-          CodeGeneratorScope::Current()->MoveUnsafeSmi(fresh.reg(), handle());
+        if (code_generator->IsUnsafeSmi(handle())) {
+          code_generator->MoveUnsafeSmi(fresh.reg(), handle());
         } else {
-          CodeGeneratorScope::Current()->masm()->Set(fresh.reg(),
-                                                     Immediate(handle()));
+          code_generator->masm()->Set(fresh.reg(), Immediate(handle()));
         }
       }
     }
@@ -128,9 +128,9 @@
     fresh.set_untagged_int32(is_untagged_int32());
     *this = fresh;
   } else if (is_register() && reg().is(target)) {
-    ASSERT(CodeGeneratorScope::Current()->has_valid_frame());
-    CodeGeneratorScope::Current()->frame()->Spill(target);
-    ASSERT(CodeGeneratorScope::Current()->allocator()->count(target) == 1);
+    ASSERT(code_generator->has_valid_frame());
+    code_generator->frame()->Spill(target);
+    ASSERT(code_generator->allocator()->count(target) == 1);
   }
   ASSERT(is_register());
   ASSERT(reg().is(target));
diff --git a/src/ia32/simulator-ia32.h b/src/ia32/simulator-ia32.h
index 43b7ea3..cb660cd 100644
--- a/src/ia32/simulator-ia32.h
+++ b/src/ia32/simulator-ia32.h
@@ -40,12 +40,12 @@
 
 
 typedef int (*regexp_matcher)(String*, int, const byte*,
-                              const byte*, int*, Address, int);
+                              const byte*, int*, Address, int, Isolate*);
 
 // Call the generated regexp code directly. The code at the entry address should
-// expect seven int/pointer sized arguments and return an int.
-#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
-  (FUNCTION_CAST<regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6))
+// expect eight int/pointer sized arguments and return an int.
+#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
+  (FUNCTION_CAST<regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7))
 
 
 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 633097a..7730ee3 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -39,14 +39,15 @@
 #define __ ACCESS_MASM(masm)
 
 
-static void ProbeTable(MacroAssembler* masm,
+static void ProbeTable(Isolate* isolate,
+                       MacroAssembler* masm,
                        Code::Flags flags,
                        StubCache::Table table,
                        Register name,
                        Register offset,
                        Register extra) {
-  ExternalReference key_offset(SCTableReference::keyReference(table));
-  ExternalReference value_offset(SCTableReference::valueReference(table));
+  ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
+  ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
 
   Label miss;
 
@@ -113,8 +114,9 @@
                                              Register r0,
                                              Register r1) {
   ASSERT(name->IsSymbol());
-  __ IncrementCounter(&Counters::negative_lookups, 1);
-  __ IncrementCounter(&Counters::negative_lookups_miss, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->negative_lookups(), 1);
+  __ IncrementCounter(counters->negative_lookups_miss(), 1);
 
   Label done;
   __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset));
@@ -137,7 +139,7 @@
 
   // Check that the properties array is a dictionary.
   __ cmp(FieldOperand(properties, HeapObject::kMapOffset),
-         Immediate(Factory::hash_table_map()));
+         Immediate(masm->isolate()->factory()->hash_table_map()));
   __ j(not_equal, miss_label);
 
   // Compute the capacity mask.
@@ -177,7 +179,7 @@
     ASSERT_EQ(kSmiTagSize, 1);
     __ mov(entity_name, Operand(properties, index, times_half_pointer_size,
                                 kElementsStartOffset - kHeapObjectTag));
-    __ cmp(entity_name, Factory::undefined_value());
+    __ cmp(entity_name, masm->isolate()->factory()->undefined_value());
     if (i != kProbes - 1) {
       __ j(equal, &done, taken);
 
@@ -197,7 +199,7 @@
   }
 
   __ bind(&done);
-  __ DecrementCounter(&Counters::negative_lookups_miss, 1);
+  __ DecrementCounter(counters->negative_lookups_miss(), 1);
 }
 
 
@@ -208,6 +210,7 @@
                               Register scratch,
                               Register extra,
                               Register extra2) {
+  Isolate* isolate = Isolate::Current();
   Label miss;
   USE(extra2);  // The register extra2 is not used on the ia32 platform.
 
@@ -240,7 +243,7 @@
   __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
 
   // Probe the primary table.
-  ProbeTable(masm, flags, kPrimary, name, scratch, extra);
+  ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra);
 
   // Primary miss: Compute hash for secondary probe.
   __ mov(scratch, FieldOperand(name, String::kHashFieldOffset));
@@ -252,7 +255,7 @@
   __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize);
 
   // Probe the secondary table.
-  ProbeTable(masm, flags, kSecondary, name, scratch, extra);
+  ProbeTable(isolate, masm, flags, kSecondary, name, scratch, extra);
 
   // Cache miss: Fall-through and let caller handle the miss by
   // entering the runtime system.
@@ -274,10 +277,11 @@
     MacroAssembler* masm, int index, Register prototype, Label* miss) {
   // Check we're still in the same context.
   __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)),
-         Top::global());
+         masm->isolate()->global());
   __ j(not_equal, miss);
   // Get the global function with the given index.
-  JSFunction* function = JSFunction::cast(Top::global_context()->get(index));
+  JSFunction* function =
+      JSFunction::cast(masm->isolate()->global_context()->get(index));
   // Load its initial map. The global functions all have initial maps.
   __ Set(prototype, Immediate(Handle<Map>(function->initial_map())));
   // Load the prototype from the initial map.
@@ -395,7 +399,7 @@
                                      JSObject* holder_obj) {
   __ push(name);
   InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
-  ASSERT(!Heap::InNewSpace(interceptor));
+  ASSERT(!masm->isolate()->heap()->InNewSpace(interceptor));
   Register scratch = name;
   __ mov(scratch, Immediate(Handle<Object>(interceptor)));
   __ push(scratch);
@@ -412,8 +416,9 @@
                                                    JSObject* holder_obj) {
   PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
   __ CallExternalReference(
-        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)),
-        5);
+      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
+                        masm->isolate()),
+      5);
 }
 
 
@@ -480,7 +485,7 @@
   __ mov(Operand(esp, 2 * kPointerSize), edi);
   Object* call_data = optimization.api_call_info()->data();
   Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info());
-  if (Heap::InNewSpace(call_data)) {
+  if (masm->isolate()->heap()->InNewSpace(call_data)) {
     __ mov(ecx, api_call_info_handle);
     __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset));
     __ mov(Operand(esp, 3 * kPointerSize), ebx);
@@ -574,7 +579,7 @@
                      name,
                      holder,
                      miss);
-      return Heap::undefined_value();  // Success.
+      return masm->isolate()->heap()->undefined_value();  // Success.
     }
   }
 
@@ -610,10 +615,11 @@
                              (depth2 != kInvalidProtoDepth);
     }
 
-    __ IncrementCounter(&Counters::call_const_interceptor, 1);
+    Counters* counters = masm->isolate()->counters();
+    __ IncrementCounter(counters->call_const_interceptor(), 1);
 
     if (can_do_fast_api_call) {
-      __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1);
+      __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1);
       ReserveSpaceForFastApiCall(masm, scratch1);
     }
 
@@ -672,7 +678,7 @@
       FreeSpaceForFastApiCall(masm, scratch1);
     }
 
-    return Heap::undefined_value();  // Success.
+    return masm->isolate()->heap()->undefined_value();  // Success.
   }
 
   void CompileRegular(MacroAssembler* masm,
@@ -700,9 +706,9 @@
                              interceptor_holder);
 
     __ CallExternalReference(
-          ExternalReference(
-              IC_Utility(IC::kLoadPropertyWithInterceptorForCall)),
-          5);
+        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
+                          masm->isolate()),
+        5);
 
     // Restore the name_ register.
     __ pop(name_);
@@ -728,7 +734,7 @@
     __ pop(receiver);  // Restore the holder.
     __ LeaveInternalFrame();
 
-    __ cmp(eax, Factory::no_interceptor_result_sentinel());
+    __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel());
     __ j(not_equal, interceptor_succeeded);
   }
 
@@ -742,9 +748,9 @@
   ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
   Code* code = NULL;
   if (kind == Code::LOAD_IC) {
-    code = Builtins::builtin(Builtins::LoadIC_Miss);
+    code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss);
   } else {
-    code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
+    code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss);
   }
 
   Handle<Code> ic(code);
@@ -790,7 +796,10 @@
     __ push(eax);
     __ push(scratch);
     __ TailCallExternalReference(
-        ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage)), 3, 1);
+        ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
+                          masm->isolate()),
+        3,
+        1);
     return;
   }
 
@@ -851,10 +860,10 @@
   if (Serializer::enabled()) {
     __ mov(scratch, Immediate(Handle<Object>(cell)));
     __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
-           Immediate(Factory::the_hole_value()));
+           Immediate(masm->isolate()->factory()->the_hole_value()));
   } else {
     __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)),
-           Immediate(Factory::the_hole_value()));
+           Immediate(masm->isolate()->factory()->the_hole_value()));
   }
   __ j(not_equal, miss, not_taken);
   return cell;
@@ -906,6 +915,7 @@
   ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
   ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
          && !scratch2.is(scratch1));
+
   // Keep track of the current object in register reg.
   Register reg = object_reg;
   JSObject* current = object;
@@ -930,7 +940,7 @@
         !current->IsJSGlobalObject() &&
         !current->IsJSGlobalProxy()) {
       if (!name->IsSymbol()) {
-        MaybeObject* maybe_lookup_result = Heap::LookupSymbol(name);
+        MaybeObject* maybe_lookup_result = heap()->LookupSymbol(name);
         Object* lookup_result = NULL;  // Initialization to please compiler.
         if (!maybe_lookup_result->ToObject(&lookup_result)) {
           set_failure(Failure::cast(maybe_lookup_result));
@@ -950,7 +960,7 @@
       __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
       reg = holder_reg;  // from now the object is in holder_reg
       __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
-    } else if (Heap::InNewSpace(prototype)) {
+    } else if (heap()->InNewSpace(prototype)) {
       // Get the map of the current object.
       __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
       __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map())));
@@ -997,7 +1007,7 @@
   ASSERT(current == holder);
 
   // Log the check depth.
-  LOG(IntEvent("check-maps-depth", depth + 1));
+  LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
 
   // Check the holder map.
   __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
@@ -1080,7 +1090,7 @@
   ASSERT(!scratch2.is(reg));
   __ push(reg);  // holder
   // Push data from AccessorInfo.
-  if (Heap::InNewSpace(callback_handle->data())) {
+  if (isolate()->heap()->InNewSpace(callback_handle->data())) {
     __ mov(scratch1, Immediate(callback_handle));
     __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset));
   } else {
@@ -1204,7 +1214,7 @@
     // Check if interceptor provided a value for property.  If it's
     // the case, return immediately.
     Label interceptor_failed;
-    __ cmp(eax, Factory::no_interceptor_result_sentinel());
+    __ cmp(eax, factory()->no_interceptor_result_sentinel());
     __ j(equal, &interceptor_failed);
     __ LeaveInternalFrame();
     __ ret(0);
@@ -1259,7 +1269,8 @@
       __ push(scratch2);  // restore return address
 
       ExternalReference ref =
-          ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
+          ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
+                            masm()->isolate());
       __ TailCallExternalReference(ref, 5, 1);
     }
   } else {  // !compile_followup_inline
@@ -1273,8 +1284,9 @@
                              name_reg, interceptor_holder);
     __ push(scratch2);  // restore old return address
 
-    ExternalReference ref = ExternalReference(
-        IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
+    ExternalReference ref =
+        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
+                          isolate());
     __ TailCallExternalReference(ref, 5, 1);
   }
 }
@@ -1325,7 +1337,7 @@
   }
 
   // Check that the cell contains the same function.
-  if (Heap::InNewSpace(function)) {
+  if (isolate()->heap()->InNewSpace(function)) {
     // We can't embed a pointer to a function in new space so we have
     // to verify that the shared function info is unchanged. This has
     // the nice side effect that multiple closures based on the same
@@ -1348,8 +1360,9 @@
 
 
 MaybeObject* CallStubCompiler::GenerateMissBranch() {
-  MaybeObject* maybe_obj = StubCache::ComputeCallMiss(arguments().immediate(),
-                                                      kind_);
+  MaybeObject* maybe_obj =
+      isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
+                                                       kind_);
   Object* obj;
   if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
@@ -1405,10 +1418,8 @@
 
   // Handle call cache miss.
   __ bind(&miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(FIELD, name);
@@ -1429,7 +1440,9 @@
   // -----------------------------------
 
   // If object is not an array, bail out to regular call.
-  if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value();
+  if (!object->IsJSArray() || cell != NULL) {
+    return isolate()->heap()->undefined_value();
+  }
 
   Label miss;
 
@@ -1459,7 +1472,7 @@
 
     // Check that the elements are in fast mode and writable.
     __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
-           Immediate(Factory::fixed_array_map()));
+           Immediate(factory()->fixed_array_map()));
     __ j(not_equal, &call_builtin);
 
     if (argc == 1) {  // Otherwise fall through to call builtin.
@@ -1508,9 +1521,9 @@
       }
 
       ExternalReference new_space_allocation_top =
-          ExternalReference::new_space_allocation_top_address();
+          ExternalReference::new_space_allocation_top_address(isolate());
       ExternalReference new_space_allocation_limit =
-          ExternalReference::new_space_allocation_limit_address();
+          ExternalReference::new_space_allocation_limit_address(isolate());
 
       const int kAllocationDelta = 4;
       // Load top.
@@ -1535,7 +1548,7 @@
       // ... and fill the rest with holes.
       for (int i = 1; i < kAllocationDelta; i++) {
         __ mov(Operand(edx, i * kPointerSize),
-               Immediate(Factory::the_hole_value()));
+               Immediate(factory()->the_hole_value()));
       }
 
       // Restore receiver to edx as finish sequence assumes it's here.
@@ -1551,16 +1564,15 @@
     }
 
     __ bind(&call_builtin);
-    __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
-                                 argc + 1,
-                                 1);
+    __ TailCallExternalReference(
+        ExternalReference(Builtins::c_ArrayPush, isolate()),
+        argc + 1,
+        1);
   }
 
   __ bind(&miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(function);
@@ -1581,7 +1593,9 @@
   // -----------------------------------
 
   // If object is not an array, bail out to regular call.
-  if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value();
+  if (!object->IsJSArray() || cell != NULL) {
+    return heap()->undefined_value();
+  }
 
   Label miss, return_undefined, call_builtin;
 
@@ -1603,7 +1617,7 @@
 
   // Check that the elements are in fast mode and writable.
   __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
-         Immediate(Factory::fixed_array_map()));
+         Immediate(factory()->fixed_array_map()));
   __ j(not_equal, &call_builtin);
 
   // Get the array's length into ecx and calculate new length.
@@ -1617,7 +1631,7 @@
   __ mov(eax, FieldOperand(ebx,
                            ecx, times_half_pointer_size,
                            FixedArray::kHeaderSize));
-  __ cmp(Operand(eax), Immediate(Factory::the_hole_value()));
+  __ cmp(Operand(eax), Immediate(factory()->the_hole_value()));
   __ j(equal, &call_builtin);
 
   // Set the array's length.
@@ -1627,23 +1641,22 @@
   __ mov(FieldOperand(ebx,
                       ecx, times_half_pointer_size,
                       FixedArray::kHeaderSize),
-         Immediate(Factory::the_hole_value()));
+         Immediate(factory()->the_hole_value()));
   __ ret((argc + 1) * kPointerSize);
 
   __ bind(&return_undefined);
-  __ mov(eax, Immediate(Factory::undefined_value()));
+  __ mov(eax, Immediate(factory()->undefined_value()));
   __ ret((argc + 1) * kPointerSize);
 
   __ bind(&call_builtin);
-  __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop),
-                               argc + 1,
-                               1);
+  __ TailCallExternalReference(
+      ExternalReference(Builtins::c_ArrayPop, isolate()),
+      argc + 1,
+      1);
 
   __ bind(&miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(function);
@@ -1665,7 +1678,9 @@
   // -----------------------------------
 
   // If object is not a string, bail out to regular call.
-  if (!object->IsString() || cell != NULL) return Heap::undefined_value();
+  if (!object->IsString() || cell != NULL) {
+    return isolate()->heap()->undefined_value();
+  }
 
   const int argc = arguments().immediate();
 
@@ -1697,7 +1712,7 @@
   if (argc > 0) {
     __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
   } else {
-    __ Set(index, Immediate(Factory::undefined_value()));
+    __ Set(index, Immediate(factory()->undefined_value()));
   }
 
   StringCharCodeAtGenerator char_code_at_generator(receiver,
@@ -1716,7 +1731,7 @@
 
   if (index_out_of_range.is_linked()) {
     __ bind(&index_out_of_range);
-    __ Set(eax, Immediate(Factory::nan_value()));
+    __ Set(eax, Immediate(factory()->nan_value()));
     __ ret((argc + 1) * kPointerSize);
   }
 
@@ -1724,10 +1739,8 @@
   // Restore function name in ecx.
   __ Set(ecx, Immediate(Handle<String>(name)));
   __ bind(&name_miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(function);
@@ -1749,7 +1762,9 @@
   // -----------------------------------
 
   // If object is not a string, bail out to regular call.
-  if (!object->IsString() || cell != NULL) return Heap::undefined_value();
+  if (!object->IsString() || cell != NULL) {
+    return heap()->undefined_value();
+  }
 
   const int argc = arguments().immediate();
 
@@ -1782,7 +1797,7 @@
   if (argc > 0) {
     __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
   } else {
-    __ Set(index, Immediate(Factory::undefined_value()));
+    __ Set(index, Immediate(factory()->undefined_value()));
   }
 
   StringCharAtGenerator char_at_generator(receiver,
@@ -1802,7 +1817,7 @@
 
   if (index_out_of_range.is_linked()) {
     __ bind(&index_out_of_range);
-    __ Set(eax, Immediate(Factory::empty_string()));
+    __ Set(eax, Immediate(factory()->empty_string()));
     __ ret((argc + 1) * kPointerSize);
   }
 
@@ -1810,10 +1825,8 @@
   // Restore function name in ecx.
   __ Set(ecx, Immediate(Handle<String>(name)));
   __ bind(&name_miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(function);
@@ -1838,7 +1851,9 @@
 
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
-  if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
+  if (!object->IsJSObject() || argc != 1) {
+    return isolate()->heap()->undefined_value();
+  }
 
   Label miss;
   GenerateNameCheck(name, &miss);
@@ -1885,10 +1900,8 @@
 
   __ bind(&miss);
   // ecx: function name.
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
@@ -1908,14 +1921,19 @@
   //  -- esp[(argc + 1) * 4] : receiver
   // -----------------------------------
 
-  if (!CpuFeatures::IsSupported(SSE2)) return Heap::undefined_value();
+  if (!isolate()->cpu_features()->IsSupported(SSE2)) {
+    return isolate()->heap()->undefined_value();
+  }
+
   CpuFeatures::Scope use_sse2(SSE2);
 
   const int argc = arguments().immediate();
 
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
-  if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
+  if (!object->IsJSObject() || argc != 1) {
+    return isolate()->heap()->undefined_value();
+  }
 
   Label miss;
   GenerateNameCheck(name, &miss);
@@ -1946,7 +1964,7 @@
 
   // Check if the argument is a heap number and load its value into xmm0.
   Label slow;
-  __ CheckMap(eax, Factory::heap_number_map(), &slow, true);
+  __ CheckMap(eax, factory()->heap_number_map(), &slow, true);
   __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
 
   // Check if the argument is strictly positive. Note this also
@@ -2012,10 +2030,8 @@
 
   __ bind(&miss);
   // ecx: function name.
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
@@ -2039,7 +2055,9 @@
 
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
-  if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
+  if (!object->IsJSObject() || argc != 1) {
+    return isolate()->heap()->undefined_value();
+  }
 
   Label miss;
   GenerateNameCheck(name, &miss);
@@ -2090,7 +2108,7 @@
   // Check if the argument is a heap number and load its exponent and
   // sign into ebx.
   __ bind(&not_smi);
-  __ CheckMap(eax, Factory::heap_number_map(), &slow, true);
+  __ CheckMap(eax, factory()->heap_number_map(), &slow, true);
   __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset));
 
   // Check the sign of the argument. If the argument is positive,
@@ -2117,16 +2135,75 @@
 
   __ bind(&miss);
   // ecx: function name.
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
 }
 
 
+MaybeObject* CallStubCompiler::CompileFastApiCall(
+    const CallOptimization& optimization,
+    Object* object,
+    JSObject* holder,
+    JSGlobalPropertyCell* cell,
+    JSFunction* function,
+    String* name) {
+  ASSERT(optimization.is_simple_api_call());
+  // Bail out if object is a global object as we don't want to
+  // repatch it to global receiver.
+  if (object->IsGlobalObject()) return heap()->undefined_value();
+  if (cell != NULL) return heap()->undefined_value();
+  int depth = optimization.GetPrototypeDepthOfExpectedType(
+            JSObject::cast(object), holder);
+  if (depth == kInvalidProtoDepth) return heap()->undefined_value();
+
+  Label miss, miss_before_stack_reserved;
+
+  GenerateNameCheck(name, &miss_before_stack_reserved);
+
+  // 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_before_stack_reserved, not_taken);
+
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->call_const(), 1);
+  __ IncrementCounter(counters->call_const_fast_api(), 1);
+
+  // Allocate space for v8::Arguments implicit values. Must be initialized
+  // before calling any runtime function.
+  __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
+
+  // Check that the maps haven't changed and find a Holder as a side effect.
+  CheckPrototypes(JSObject::cast(object), edx, holder,
+                  ebx, eax, edi, name, depth, &miss);
+
+  // Move the return address on top of the stack.
+  __ mov(eax, Operand(esp, 3 * kPointerSize));
+  __ mov(Operand(esp, 0 * kPointerSize), eax);
+
+  // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains
+  // duplicate of return address and will be overwritten.
+  MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc);
+  if (result->IsFailure()) return result;
+
+  __ bind(&miss);
+  __ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
+
+  __ bind(&miss_before_stack_reserved);
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
+
+  // Return the generated code.
+  return GetCode(function);
+}
+
+
 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
                                                    JSObject* holder,
                                                    JSFunction* function,
@@ -2140,20 +2217,18 @@
   //  -- esp[(argc + 1) * 4] : receiver
   // -----------------------------------
 
-  SharedFunctionInfo* function_info = function->shared();
-  if (function_info->HasBuiltinFunctionId()) {
-    BuiltinFunctionId id = function_info->builtin_function_id();
+  if (HasCustomCallGenerator(function)) {
     MaybeObject* maybe_result = CompileCustomCall(
-        id, object, holder, NULL, function, name);
+        object, holder, NULL, function, name);
     Object* result;
     if (!maybe_result->ToObject(&result)) return maybe_result;
     // undefined means bail out to regular compiler.
     if (!result->IsUndefined()) return result;
   }
 
-  Label miss_in_smi_check;
+  Label miss;
 
-  GenerateNameCheck(name, &miss_in_smi_check);
+  GenerateNameCheck(name, &miss);
 
   // Get the receiver from the stack.
   const int argc = arguments().immediate();
@@ -2162,42 +2237,25 @@
   // Check that the receiver isn't a smi.
   if (check != NUMBER_CHECK) {
     __ test(edx, Immediate(kSmiTagMask));
-    __ j(zero, &miss_in_smi_check, not_taken);
+    __ 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);
 
-  CallOptimization optimization(function);
-  int depth = kInvalidProtoDepth;
-  Label miss;
-
+  SharedFunctionInfo* function_info = function->shared();
   switch (check) {
     case RECEIVER_MAP_CHECK:
-      __ IncrementCounter(&Counters::call_const, 1);
-
-      if (optimization.is_simple_api_call() && !object->IsGlobalObject()) {
-        depth = optimization.GetPrototypeDepthOfExpectedType(
-            JSObject::cast(object), holder);
-      }
-
-      if (depth != kInvalidProtoDepth) {
-        __ IncrementCounter(&Counters::call_const_fast_api, 1);
-
-        // Allocate space for v8::Arguments implicit values. Must be initialized
-        // before to call any runtime function.
-        __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
-      }
+      __ IncrementCounter(isolate()->counters()->call_const(), 1);
 
       // Check that the maps haven't changed.
       CheckPrototypes(JSObject::cast(object), edx, holder,
-                      ebx, eax, edi, name, depth, &miss);
+                      ebx, eax, edi, name, &miss);
 
       // Patch the receiver on the stack with the global proxy if
       // necessary.
       if (object->IsGlobalObject()) {
-        ASSERT(depth == kInvalidProtoDepth);
         __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
         __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
       }
@@ -2250,9 +2308,9 @@
       } else {
         Label fast;
         // Check that the object is a boolean.
-        __ cmp(edx, Factory::true_value());
+        __ cmp(edx, factory()->true_value());
         __ j(equal, &fast, taken);
-        __ cmp(edx, Factory::false_value());
+        __ cmp(edx, factory()->false_value());
         __ j(not_equal, &miss, not_taken);
         __ bind(&fast);
         // Check that the maps starting from the prototype haven't changed.
@@ -2268,29 +2326,12 @@
       UNREACHABLE();
   }
 
-  if (depth != kInvalidProtoDepth) {
-    // Move the return address on top of the stack.
-    __ mov(eax, Operand(esp, 3 * kPointerSize));
-    __ mov(Operand(esp, 0 * kPointerSize), eax);
-
-    // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains
-    // duplicate of return address and will be overwritten.
-    MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc);
-    if (result->IsFailure()) return result;
-  } else {
-    __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
-  }
+  __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
 
   // Handle call cache miss.
   __ bind(&miss);
-  if (depth != kInvalidProtoDepth) {
-    __ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
-  }
-  __ bind(&miss_in_smi_check);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(function);
@@ -2355,10 +2396,8 @@
 
   // Handle load cache miss.
   __ bind(&miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(INTERCEPTOR, name);
@@ -2378,11 +2417,9 @@
   //  -- esp[(argc + 1) * 4] : receiver
   // -----------------------------------
 
-  SharedFunctionInfo* function_info = function->shared();
-  if (function_info->HasBuiltinFunctionId()) {
-    BuiltinFunctionId id = function_info->builtin_function_id();
+  if (HasCustomCallGenerator(function)) {
     MaybeObject* maybe_result = CompileCustomCall(
-        id, object, holder, cell, function, name);
+        object, holder, cell, function, name);
     Object* result;
     if (!maybe_result->ToObject(&result)) return maybe_result;
     // undefined means bail out to regular compiler.
@@ -2410,7 +2447,8 @@
   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
 
   // Jump to the cached code (tail call).
-  __ IncrementCounter(&Counters::call_global_inline, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->call_global_inline(), 1);
   ASSERT(function->is_compiled());
   ParameterCount expected(function->shared()->formal_parameter_count());
   if (V8::UseCrankshaft()) {
@@ -2427,11 +2465,9 @@
 
   // Handle call cache miss.
   __ bind(&miss);
-  __ IncrementCounter(&Counters::call_global_inline_miss, 1);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  __ IncrementCounter(counters->call_global_inline_miss(), 1);
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(NORMAL, name);
@@ -2461,7 +2497,7 @@
   // Handle store cache miss.
   __ bind(&miss);
   __ mov(ecx, Immediate(Handle<String>(name)));  // restore name
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2507,12 +2543,12 @@
 
   // Do tail-call to the runtime system.
   ExternalReference store_callback_property =
-      ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
+      ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
   __ TailCallExternalReference(store_callback_property, 4, 1);
 
   // Handle store cache miss.
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2557,12 +2593,12 @@
 
   // Do tail-call to the runtime system.
   ExternalReference store_ic_property =
-      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
+      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
   __ TailCallExternalReference(store_ic_property, 4, 1);
 
   // Handle store cache miss.
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2598,20 +2634,21 @@
   // cell could have been deleted and reintroducing the global needs
   // to update the property details in the property dictionary of the
   // global object. We bail out to the runtime system to do that.
-  __ cmp(cell_operand, Factory::the_hole_value());
+  __ cmp(cell_operand, factory()->the_hole_value());
   __ j(equal, &miss);
 
   // Store the value in the cell.
   __ mov(cell_operand, eax);
 
   // Return the value (register eax).
-  __ IncrementCounter(&Counters::named_store_global_inline, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->named_store_global_inline(), 1);
   __ ret(0);
 
   // Handle store cache miss.
   __ bind(&miss);
-  __ IncrementCounter(&Counters::named_store_global_inline_miss, 1);
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  __ IncrementCounter(counters->named_store_global_inline_miss(), 1);
+  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2631,7 +2668,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_store_field, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_store_field(), 1);
 
   // Check that the name has not changed.
   __ cmp(Operand(ecx), Immediate(Handle<String>(name)));
@@ -2647,8 +2685,8 @@
 
   // Handle store cache miss.
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_store_field, 1);
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
+  __ DecrementCounter(counters->keyed_store_field(), 1);
+  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2682,7 +2720,7 @@
   // Get the elements array and make sure it is a fast element array, not 'cow'.
   __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
   __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
-         Immediate(Factory::fixed_array_map()));
+         Immediate(factory()->fixed_array_map()));
   __ j(not_equal, &miss, not_taken);
 
   // Check that the key is within bounds.
@@ -2705,43 +2743,7 @@
 
   // Handle store cache miss.
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
-  __ jmp(ic, RelocInfo::CODE_TARGET);
-
-  // Return the generated code.
-  return GetCode(NORMAL, NULL);
-}
-
-
-MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray(
-    JSObject* receiver) {
-  // ----------- S t a t e -------------
-  //  -- eax    : value
-  //  -- ecx    : key
-  //  -- edx    : receiver
-  //  -- esp[0] : return address
-  // -----------------------------------
-  Label miss;
-
-  // Check that the map matches.
-  __ CheckMap(edx, Handle<Map>(receiver->map()), &miss, false);
-
-  // Do the load.
-  GenerateFastPixelArrayStore(masm(),
-                              edx,
-                              ecx,
-                              eax,
-                              edi,
-                              ebx,
-                              true,
-                              &miss,
-                              &miss,
-                              NULL,
-                              &miss);
-
-  // Handle store cache miss.
-  __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
+  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2786,14 +2788,14 @@
 
   // Return undefined if maps of the full prototype chain are still the
   // same and no global property with this name contains a value.
-  __ mov(eax, Factory::undefined_value());
+  __ mov(eax, isolate()->factory()->undefined_value());
   __ ret(0);
 
   __ bind(&miss);
   GenerateLoadMiss(masm(), Code::LOAD_IC);
 
   // Return the generated code.
-  return GetCode(NONEXISTENT, Heap::empty_string());
+  return GetCode(NONEXISTENT, isolate()->heap()->empty_string());
 }
 
 
@@ -2930,19 +2932,20 @@
 
   // Check for deleted property if property can actually be deleted.
   if (!is_dont_delete) {
-    __ cmp(ebx, Factory::the_hole_value());
+    __ cmp(ebx, factory()->the_hole_value());
     __ j(equal, &miss, not_taken);
   } else if (FLAG_debug_code) {
-    __ cmp(ebx, Factory::the_hole_value());
+    __ cmp(ebx, factory()->the_hole_value());
     __ Check(not_equal, "DontDelete cells can't contain the hole");
   }
 
-  __ IncrementCounter(&Counters::named_load_global_stub, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->named_load_global_stub(), 1);
   __ mov(eax, ebx);
   __ ret(0);
 
   __ bind(&miss);
-  __ IncrementCounter(&Counters::named_load_global_stub_miss, 1);
+  __ IncrementCounter(counters->named_load_global_stub_miss(), 1);
   GenerateLoadMiss(masm(), Code::LOAD_IC);
 
   // Return the generated code.
@@ -2961,7 +2964,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_load_field, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_field(), 1);
 
   // Check that the name has not changed.
   __ cmp(Operand(eax), Immediate(Handle<String>(name)));
@@ -2970,7 +2974,7 @@
   GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss);
 
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_field, 1);
+  __ DecrementCounter(counters->keyed_load_field(), 1);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
@@ -2990,7 +2994,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_load_callback, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_callback(), 1);
 
   // Check that the name has not changed.
   __ cmp(Operand(eax), Immediate(Handle<String>(name)));
@@ -3005,7 +3010,7 @@
 
   __ bind(&miss);
 
-  __ DecrementCounter(&Counters::keyed_load_callback, 1);
+  __ DecrementCounter(counters->keyed_load_callback(), 1);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
@@ -3024,7 +3029,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_load_constant_function, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_constant_function(), 1);
 
   // Check that the name has not changed.
   __ cmp(Operand(eax), Immediate(Handle<String>(name)));
@@ -3033,7 +3039,7 @@
   GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi,
                        value, name, &miss);
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_constant_function, 1);
+  __ DecrementCounter(counters->keyed_load_constant_function(), 1);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
@@ -3051,7 +3057,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_load_interceptor, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_interceptor(), 1);
 
   // Check that the name has not changed.
   __ cmp(Operand(eax), Immediate(Handle<String>(name)));
@@ -3070,7 +3077,7 @@
                           name,
                           &miss);
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_interceptor, 1);
+  __ DecrementCounter(counters->keyed_load_interceptor(), 1);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
@@ -3086,7 +3093,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_load_array_length, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_array_length(), 1);
 
   // Check that the name has not changed.
   __ cmp(Operand(eax), Immediate(Handle<String>(name)));
@@ -3094,7 +3102,7 @@
 
   GenerateLoadArrayLength(masm(), edx, ecx, &miss);
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_array_length, 1);
+  __ DecrementCounter(counters->keyed_load_array_length(), 1);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
@@ -3110,7 +3118,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_load_string_length, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_string_length(), 1);
 
   // Check that the name has not changed.
   __ cmp(Operand(eax), Immediate(Handle<String>(name)));
@@ -3118,7 +3127,7 @@
 
   GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true);
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_string_length, 1);
+  __ DecrementCounter(counters->keyed_load_string_length(), 1);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
@@ -3134,7 +3143,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_load_function_prototype, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_function_prototype(), 1);
 
   // Check that the name has not changed.
   __ cmp(Operand(eax), Immediate(Handle<String>(name)));
@@ -3142,7 +3152,7 @@
 
   GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss);
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_function_prototype, 1);
+  __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
@@ -3182,7 +3192,7 @@
   // Load the result and make sure it's not the hole.
   __ mov(ebx, Operand(ecx, eax, times_2,
                       FixedArray::kHeaderSize - kHeapObjectTag));
-  __ cmp(ebx, Factory::the_hole_value());
+  __ cmp(ebx, factory()->the_hole_value());
   __ j(equal, &miss, not_taken);
   __ mov(eax, ebx);
   __ ret(0);
@@ -3195,37 +3205,6 @@
 }
 
 
-MaybeObject* KeyedLoadStubCompiler::CompileLoadPixelArray(JSObject* receiver) {
-  // ----------- S t a t e -------------
-  //  -- eax    : key
-  //  -- edx    : receiver
-  //  -- esp[0] : return address
-  // -----------------------------------
-  Label miss;
-
-  // Check that the map matches.
-  __ CheckMap(edx, Handle<Map>(receiver->map()), &miss, false);
-
-  GenerateFastPixelArrayLoad(masm(),
-                             edx,
-                             eax,
-                             ecx,
-                             ebx,
-                             eax,
-                             &miss,
-                             &miss,
-                             &miss);
-
-  // Handle load cache miss.
-  __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Miss));
-  __ jmp(ic, RelocInfo::CODE_TARGET);
-
-  // Return the generated code.
-  return GetCode(NORMAL, NULL);
-}
-
-
 // Specialized stub for constructing objects from functions which only have only
 // simple assignments of the form this.x = ...; in their body.
 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
@@ -3242,7 +3221,7 @@
   // code for the function thereby hitting the break points.
   __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
   __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset));
-  __ cmp(ebx, Factory::undefined_value());
+  __ cmp(ebx, factory()->undefined_value());
   __ j(not_equal, &generic_stub_call, not_taken);
 #endif
 
@@ -3279,7 +3258,7 @@
   // ebx: initial map
   // edx: JSObject (untagged)
   __ mov(Operand(edx, JSObject::kMapOffset), ebx);
-  __ mov(ebx, Factory::empty_fixed_array());
+  __ mov(ebx, factory()->empty_fixed_array());
   __ mov(Operand(edx, JSObject::kPropertiesOffset), ebx);
   __ mov(Operand(edx, JSObject::kElementsOffset), ebx);
 
@@ -3296,7 +3275,7 @@
   __ lea(ecx, Operand(esp, eax, times_4, 1 * kPointerSize));
 
   // Use edi for holding undefined which is used in several places below.
-  __ mov(edi, Factory::undefined_value());
+  __ mov(edi, factory()->undefined_value());
 
   // eax: argc
   // ecx: first argument
@@ -3313,7 +3292,7 @@
       int arg_number = shared->GetThisPropertyAssignmentArgument(i);
       __ mov(ebx, edi);
       __ cmp(eax, arg_number);
-      if (CpuFeatures::IsSupported(CMOV)) {
+      if (isolate()->cpu_features()->IsSupported(CMOV)) {
         CpuFeatures::Scope use_cmov(CMOV);
         __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize));
       } else {
@@ -3348,15 +3327,16 @@
   __ pop(ecx);
   __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize));
   __ push(ecx);
-  __ IncrementCounter(&Counters::constructed_objects, 1);
-  __ IncrementCounter(&Counters::constructed_objects_stub, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->constructed_objects(), 1);
+  __ IncrementCounter(counters->constructed_objects_stub(), 1);
   __ ret(0);
 
   // Jump to the generic stub in case the specialized code cannot handle the
   // construction.
   __ bind(&generic_stub_call);
-  Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
-  Handle<Code> generic_construct_stub(code);
+  Handle<Code> generic_construct_stub =
+      isolate()->builtins()->JSConstructStubGeneric();
   __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -3365,7 +3345,7 @@
 
 
 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
-    ExternalArrayType array_type, Code::Flags flags) {
+    JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) {
   // ----------- S t a t e -------------
   //  -- eax    : key
   //  -- edx    : receiver
@@ -3381,25 +3361,9 @@
   __ test(eax, Immediate(kSmiTagMask));
   __ j(not_zero, &slow, not_taken);
 
-  // Get the map of the receiver.
-  __ mov(ecx, FieldOperand(edx, 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.
-  __ test_b(FieldOperand(ecx, Map::kBitFieldOffset),
-            1 << Map::kIsAccessCheckNeeded);
-  __ j(not_zero, &slow, not_taken);
-
-  __ CmpInstanceType(ecx, JS_OBJECT_TYPE);
-  __ j(not_equal, &slow, not_taken);
-
-  // Check that the elements array is the appropriate type of
-  // ExternalArray.
+  // Check that the map matches.
+  __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false);
   __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
-  Handle<Map> map(Heap::MapForExternalArrayType(array_type));
-  __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
-         Immediate(map));
-  __ j(not_equal, &slow, not_taken);
 
   // eax: key, known to be a smi.
   // edx: receiver, known to be a JSObject.
@@ -3410,21 +3374,21 @@
   __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset));
   // Unsigned comparison catches both negative and too-large values.
   __ j(above_equal, &slow);
-
   __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
   // ebx: base pointer of external storage
   switch (array_type) {
     case kExternalByteArray:
-      __ movsx_b(ecx, Operand(ebx, ecx, times_1, 0));
+      __ movsx_b(eax, Operand(ebx, ecx, times_1, 0));
       break;
     case kExternalUnsignedByteArray:
-      __ movzx_b(ecx, Operand(ebx, ecx, times_1, 0));
+    case kExternalPixelArray:
+      __ movzx_b(eax, Operand(ebx, ecx, times_1, 0));
       break;
     case kExternalShortArray:
-      __ movsx_w(ecx, Operand(ebx, ecx, times_2, 0));
+      __ movsx_w(eax, Operand(ebx, ecx, times_2, 0));
       break;
     case kExternalUnsignedShortArray:
-      __ movzx_w(ecx, Operand(ebx, ecx, times_2, 0));
+      __ movzx_w(eax, Operand(ebx, ecx, times_2, 0));
       break;
     case kExternalIntArray:
     case kExternalUnsignedIntArray:
@@ -3499,7 +3463,6 @@
     __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
     __ ret(0);
   } else {
-    __ mov(eax, ecx);
     __ SmiTag(eax);
     __ ret(0);
   }
@@ -3513,7 +3476,8 @@
 
   // Slow case: Jump to runtime.
   __ bind(&slow);
-  __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
   // ----------- S t a t e -------------
   //  -- eax    : key
   //  -- edx    : receiver
@@ -3534,7 +3498,7 @@
 
 
 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
-    ExternalArrayType array_type, Code::Flags flags) {
+    JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : key
@@ -3546,30 +3510,16 @@
   // Check that the object isn't a smi.
   __ test(edx, Immediate(kSmiTagMask));
   __ j(zero, &slow);
-  // Get the map from the receiver.
-  __ mov(edi, 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.
-  __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
-            1 << Map::kIsAccessCheckNeeded);
-  __ j(not_zero, &slow);
+
+  // Check that the map matches.
+  __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false);
+
   // Check that the key is a smi.
   __ test(ecx, Immediate(kSmiTagMask));
   __ j(not_zero, &slow);
-  // Get the instance type from the map of the receiver.
-  __ CmpInstanceType(edi, JS_OBJECT_TYPE);
-  __ j(not_equal, &slow);
-
-  // Check that the elements array is the appropriate type of
-  // ExternalArray.
-  // eax: value
-  // edx: receiver, a JSObject
-  // ecx: key, a smi
-  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
-  __ CheckMap(edi, Handle<Map>(Heap::MapForExternalArrayType(array_type)),
-              &slow, true);
 
   // Check that the index is in range.
+  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
   __ mov(ebx, ecx);
   __ SmiUntag(ebx);
   __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset));
@@ -3584,13 +3534,28 @@
   // edi: elements array
   // ebx: untagged index
   __ test(eax, Immediate(kSmiTagMask));
-  __ j(not_equal, &check_heap_number);
+  if (array_type == kExternalPixelArray)
+    __ j(not_equal, &slow);
+  else
+    __ j(not_equal, &check_heap_number);
+
   // smi case
   __ mov(ecx, eax);  // Preserve the value in eax.  Key is no longer needed.
   __ SmiUntag(ecx);
   __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
   // ecx: base pointer of external storage
   switch (array_type) {
+    case kExternalPixelArray:
+      {  // Clamp the value to [0..255].
+        NearLabel done;
+        __ test(ecx, Immediate(0xFFFFFF00));
+        __ j(zero, &done);
+        __ setcc(negative, ecx);  // 1 if negative, 0 if positive.
+        __ dec_b(ecx);  // 0 if negative, 255 if positive.
+        __ bind(&done);
+      }
+      __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
+      break;
     case kExternalByteArray:
     case kExternalUnsignedByteArray:
       __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
@@ -3616,87 +3581,100 @@
   }
   __ ret(0);  // Return the original value.
 
-  __ bind(&check_heap_number);
-  // eax: value
-  // edx: receiver
-  // ecx: key
-  // edi: elements array
-  // ebx: untagged index
-  __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
-         Immediate(Factory::heap_number_map()));
-  __ j(not_equal, &slow);
+  // TODO(danno): handle heap number -> pixel array conversion
+  if (array_type != kExternalPixelArray) {
+    __ bind(&check_heap_number);
+    // eax: value
+    // edx: receiver
+    // ecx: key
+    // edi: elements array
+    // ebx: untagged index
+    __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
+           Immediate(factory()->heap_number_map()));
+    __ j(not_equal, &slow);
 
-  // The WebGL specification leaves the behavior of storing NaN and
-  // +/-Infinity into integer arrays basically undefined. For more
-  // reproducible behavior, convert these to zero.
-  __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
-  // ebx: untagged index
-  // edi: base pointer of external storage
-  if (array_type == kExternalFloatArray) {
-    __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
-    __ fstp_s(Operand(edi, ebx, times_4, 0));
-    __ ret(0);
-  } else {
-    // Perform float-to-int conversion with truncation (round-to-zero)
-    // behavior.
+    // The WebGL specification leaves the behavior of storing NaN and
+    // +/-Infinity into integer arrays basically undefined. For more
+    // reproducible behavior, convert these to zero.
+    __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
+    // ebx: untagged index
+    // edi: base pointer of external storage
+    if (array_type == kExternalFloatArray) {
+      __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
+      __ fstp_s(Operand(edi, ebx, times_4, 0));
+      __ ret(0);
+    } else {
+      // Perform float-to-int conversion with truncation (round-to-zero)
+      // behavior.
 
-    // For the moment we make the slow call to the runtime on
-    // processors that don't support SSE2. The code in IntegerConvert
-    // (code-stubs-ia32.cc) is roughly what is needed here though the
-    // conversion failure case does not need to be handled.
-    if (CpuFeatures::IsSupported(SSE2)) {
-      if (array_type != kExternalIntArray &&
-          array_type != kExternalUnsignedIntArray) {
-        ASSERT(CpuFeatures::IsSupported(SSE2));
-        CpuFeatures::Scope scope(SSE2);
-        __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset));
-        // ecx: untagged integer value
-        switch (array_type) {
-          case kExternalByteArray:
-          case kExternalUnsignedByteArray:
-            __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
-            break;
-          case kExternalShortArray:
-          case kExternalUnsignedShortArray:
-            __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
-            break;
-          default:
-            UNREACHABLE();
-            break;
-        }
-      } else {
-        if (CpuFeatures::IsSupported(SSE3)) {
-          CpuFeatures::Scope scope(SSE3);
-          // fisttp stores values as signed integers. To represent the
-          // entire range of int and unsigned int arrays, store as a
-          // 64-bit int and discard the high 32 bits.
-          // If the value is NaN or +/-infinity, the result is 0x80000000,
-          // which is automatically zero when taken mod 2^n, n < 32.
-          __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
-          __ sub(Operand(esp), Immediate(2 * kPointerSize));
-          __ fisttp_d(Operand(esp, 0));
-          __ pop(ecx);
-          __ add(Operand(esp), Immediate(kPointerSize));
-        } else {
-          ASSERT(CpuFeatures::IsSupported(SSE2));
+      // For the moment we make the slow call to the runtime on
+      // processors that don't support SSE2. The code in IntegerConvert
+      // (code-stubs-ia32.cc) is roughly what is needed here though the
+      // conversion failure case does not need to be handled.
+      if (isolate()->cpu_features()->IsSupported(SSE2)) {
+        if (array_type != kExternalIntArray &&
+            array_type != kExternalUnsignedIntArray) {
+          ASSERT(isolate()->cpu_features()->IsSupported(SSE2));
           CpuFeatures::Scope scope(SSE2);
-          // We can easily implement the correct rounding behavior for the
-          // range [0, 2^31-1]. For the time being, to keep this code simple,
-          // make the slow runtime call for values outside this range.
-          // Note: we could do better for signed int arrays.
-          __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
-          // We will need the key if we have to make the slow runtime call.
-          __ push(ecx);
-          __ LoadPowerOf2(xmm1, ecx, 31);
-          __ pop(ecx);
-          __ ucomisd(xmm1, xmm0);
-          __ j(above_equal, &slow);
-          __ cvttsd2si(ecx, Operand(xmm0));
+          __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset));
+          // ecx: untagged integer value
+          switch (array_type) {
+            case kExternalPixelArray:
+              {  // Clamp the value to [0..255].
+                NearLabel done;
+                __ test(ecx, Immediate(0xFFFFFF00));
+                __ j(zero, &done);
+                __ setcc(negative, ecx);  // 1 if negative, 0 if positive.
+                __ dec_b(ecx);  // 0 if negative, 255 if positive.
+                __ bind(&done);
+              }
+              __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
+            case kExternalByteArray:
+            case kExternalUnsignedByteArray:
+              __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
+              break;
+            case kExternalShortArray:
+            case kExternalUnsignedShortArray:
+              __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
+              break;
+            default:
+              UNREACHABLE();
+              break;
+          }
+        } else {
+          if (isolate()->cpu_features()->IsSupported(SSE3)) {
+            CpuFeatures::Scope scope(SSE3);
+            // fisttp stores values as signed integers. To represent the
+            // entire range of int and unsigned int arrays, store as a
+            // 64-bit int and discard the high 32 bits.
+            // If the value is NaN or +/-infinity, the result is 0x80000000,
+            // which is automatically zero when taken mod 2^n, n < 32.
+            __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
+            __ sub(Operand(esp), Immediate(2 * kPointerSize));
+            __ fisttp_d(Operand(esp, 0));
+            __ pop(ecx);
+            __ add(Operand(esp), Immediate(kPointerSize));
+          } else {
+            ASSERT(isolate()->cpu_features()->IsSupported(SSE2));
+            CpuFeatures::Scope scope(SSE2);
+            // We can easily implement the correct rounding behavior for the
+            // range [0, 2^31-1]. For the time being, to keep this code simple,
+            // make the slow runtime call for values outside this range.
+            // Note: we could do better for signed int arrays.
+            __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
+            // We will need the key if we have to make the slow runtime call.
+            __ push(ecx);
+            __ LoadPowerOf2(xmm1, ecx, 31);
+            __ pop(ecx);
+            __ ucomisd(xmm1, xmm0);
+            __ j(above_equal, &slow);
+            __ cvttsd2si(ecx, Operand(xmm0));
+          }
+          // ecx: untagged integer value
+          __ mov(Operand(edi, ebx, times_4, 0), ecx);
         }
-        // ecx: untagged integer value
-        __ mov(Operand(edi, ebx, times_4, 0), ecx);
+        __ ret(0);  // Return original value.
       }
-      __ ret(0);  // Return original value.
     }
   }
 
diff --git a/src/ia32/virtual-frame-ia32.cc b/src/ia32/virtual-frame-ia32.cc
index 93d711e..2613caf 100644
--- a/src/ia32/virtual-frame-ia32.cc
+++ b/src/ia32/virtual-frame-ia32.cc
@@ -501,7 +501,7 @@
     // them later.  First sync everything above the stack pointer so we can
     // use pushes to allocate and initialize the locals.
     SyncRange(stack_pointer_ + 1, element_count() - 1);
-    Handle<Object> undefined = Factory::undefined_value();
+    Handle<Object> undefined = FACTORY->undefined_value();
     FrameElement initial_value =
         FrameElement::ConstantElement(undefined, FrameElement::SYNCED);
     if (count == 1) {
@@ -824,11 +824,11 @@
         __ bind(&not_smi);
         if (!original.type_info().IsNumber()) {
           __ cmp(FieldOperand(fresh_reg, HeapObject::kMapOffset),
-                 Factory::heap_number_map());
+                 FACTORY->heap_number_map());
           cgen()->unsafe_bailout_->Branch(not_equal);
         }
 
-        if (!CpuFeatures::IsSupported(SSE2)) {
+        if (!Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
           UNREACHABLE();
         } else {
           CpuFeatures::Scope use_sse2(SSE2);
@@ -931,7 +931,7 @@
 }
 
 
-Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
+Result VirtualFrame::CallRuntime(const Runtime::Function* f, int arg_count) {
   PrepareForCall(arg_count, arg_count);
   ASSERT(cgen()->HasValidEntryRegisters());
   __ CallRuntime(f, arg_count);
@@ -1016,7 +1016,8 @@
   PrepareForCall(0, 0);  // No stack arguments.
   MoveResultsToRegisters(&name, &receiver, ecx, eax);
 
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      Builtins::kLoadIC_Initialize));
   return RawCallCodeObject(ic, mode);
 }
 
@@ -1028,7 +1029,8 @@
   PrepareForCall(0, 0);
   MoveResultsToRegisters(&key, &receiver, eax, edx);
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      Builtins::kKeyedLoadIC_Initialize));
   return RawCallCodeObject(ic, mode);
 }
 
@@ -1038,9 +1040,9 @@
                                  StrictModeFlag strict_mode) {
   // Value and (if not contextual) receiver are on top of the frame.
   // The IC expects name in ecx, value in eax, and receiver in edx.
-  Handle<Code> ic(Builtins::builtin(
-      (strict_mode == kStrictMode) ? Builtins::StoreIC_Initialize_Strict
-                                   : Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      (strict_mode == kStrictMode) ? Builtins::kStoreIC_Initialize_Strict
+                                   : Builtins::kStoreIC_Initialize));
 
   Result value = Pop();
   RelocInfo::Mode mode;
@@ -1105,9 +1107,9 @@
     receiver.Unuse();
   }
 
-  Handle<Code> ic(Builtins::builtin(
-      (strict_mode == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
-                                   : Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      (strict_mode == kStrictMode) ? Builtins::kKeyedStoreIC_Initialize_Strict
+                                   : Builtins::kKeyedStoreIC_Initialize));
   return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
 }
 
@@ -1119,7 +1121,8 @@
   // The IC expects the name in ecx and the rest on the stack and
   // drops them all.
   InLoopFlag in_loop = loop_nesting > 0 ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
+  Handle<Code> ic = Isolate::Current()->stub_cache()->ComputeCallInitialize(
+      arg_count, in_loop);
   // Spill args, receiver, and function.  The call will drop args and
   // receiver.
   Result name = Pop();
@@ -1137,7 +1140,9 @@
   // The IC expects the name in ecx and the rest on the stack and
   // drops them all.
   InLoopFlag in_loop = loop_nesting > 0 ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
+  Handle<Code> ic =
+      Isolate::Current()->stub_cache()->ComputeKeyedCallInitialize(arg_count,
+                                                                   in_loop);
   // Spill args, receiver, and function.  The call will drop args and
   // receiver.
   Result name = Pop();
@@ -1152,7 +1157,8 @@
   // 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));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      Builtins::kJSConstructCall));
   // Duplicate the function before preparing the frame.
   PushElementAt(arg_count);
   Result function = Pop();
diff --git a/src/ia32/virtual-frame-ia32.h b/src/ia32/virtual-frame-ia32.h
index 5187430..504a8fc 100644
--- a/src/ia32/virtual-frame-ia32.h
+++ b/src/ia32/virtual-frame-ia32.h
@@ -67,7 +67,9 @@
    private:
     bool previous_state_;
 
-    CodeGenerator* cgen() {return CodeGeneratorScope::Current();}
+    CodeGenerator* cgen() {
+      return CodeGeneratorScope::Current(Isolate::Current());
+    }
   };
 
   // An illegal index into the virtual frame.
@@ -79,7 +81,9 @@
   // Construct a virtual frame as a clone of an existing one.
   explicit inline VirtualFrame(VirtualFrame* original);
 
-  CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
+  CodeGenerator* cgen() {
+    return CodeGeneratorScope::Current(Isolate::Current());
+  }
 
   MacroAssembler* masm() { return cgen()->masm(); }
 
@@ -344,7 +348,7 @@
 
   // Call runtime given the number of arguments expected on (and
   // removed from) the stack.
-  Result CallRuntime(Runtime::Function* f, int arg_count);
+  Result CallRuntime(const Runtime::Function* f, int arg_count);
   Result CallRuntime(Runtime::FunctionId id, int arg_count);
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
diff --git a/src/ic-inl.h b/src/ic-inl.h
index 9d358ed..b4f789c 100644
--- a/src/ic-inl.h
+++ b/src/ic-inl.h
@@ -41,13 +41,14 @@
   Address result = pc() - Assembler::kCallTargetAddressOffset;
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
+  Debug* debug = Isolate::Current()->debug();
   // First check if any break points are active if not just return the address
   // of the call.
-  if (!Debug::has_break_points()) return result;
+  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 (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
diff --git a/src/ic.cc b/src/ic.cc
index 087a959..382b438 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -65,8 +65,8 @@
                  const char* extra_info) {
   if (FLAG_trace_ic) {
     State new_state = StateFrom(new_target,
-                                Heap::undefined_value(),
-                                Heap::undefined_value());
+                                HEAP->undefined_value(),
+                                HEAP->undefined_value());
     PrintF("[%s (%c->%c)%s", type,
            TransitionMarkFromState(old_state),
            TransitionMarkFromState(new_state),
@@ -78,11 +78,13 @@
 #endif
 
 
-IC::IC(FrameDepth depth) {
+IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) {
+  ASSERT(isolate == Isolate::Current());
   // 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());
+  const Address entry =
+      Isolate::c_entry_fp(isolate->thread_local_top());
   Address* pc_address =
       reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
@@ -136,9 +138,11 @@
 #endif
 
 
-static bool HasNormalObjectsInPrototypeChain(LookupResult* lookup,
+static bool HasNormalObjectsInPrototypeChain(Isolate* isolate,
+                                             LookupResult* lookup,
                                              Object* receiver) {
-  Object* end = lookup->IsProperty() ? lookup->holder() : Heap::null_value();
+  Object* end = lookup->IsProperty()
+      ? lookup->holder() : isolate->heap()->null_value();
   for (Object* current = receiver;
        current != end;
        current = current->GetPrototype()) {
@@ -231,7 +235,7 @@
 
 RelocInfo::Mode IC::ComputeMode() {
   Address addr = address();
-  Code* code = Code::cast(Heap::FindCodeObject(addr));
+  Code* code = Code::cast(isolate()->heap()->FindCodeObject(addr));
   for (RelocIterator it(code, RelocInfo::kCodeTargetMask);
        !it.done(); it.next()) {
     RelocInfo* info = it.rinfo();
@@ -245,18 +249,19 @@
 Failure* IC::TypeError(const char* type,
                        Handle<Object> object,
                        Handle<Object> key) {
-  HandleScope scope;
+  HandleScope scope(isolate());
   Handle<Object> args[2] = { key, object };
-  Handle<Object> error = Factory::NewTypeError(type, HandleVector(args, 2));
-  return Top::Throw(*error);
+  Handle<Object> error = isolate()->factory()->NewTypeError(
+      type, HandleVector(args, 2));
+  return isolate()->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);
+  HandleScope scope(isolate());
+  Handle<Object> error = isolate()->factory()->NewReferenceError(
+      type, HandleVector(&name, 1));
+  return isolate()->Throw(*error);
 }
 
 
@@ -268,9 +273,13 @@
 
   switch (target->kind()) {
     case Code::LOAD_IC: return LoadIC::Clear(address, target);
-    case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target);
+    case Code::KEYED_LOAD_IC:
+    case Code::KEYED_EXTERNAL_ARRAY_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::KEYED_STORE_IC:
+    case Code::KEYED_EXTERNAL_ARRAY_STORE_IC:
+      return KeyedStoreIC::Clear(address, target);
     case Code::CALL_IC: return CallIC::Clear(address, target);
     case Code::KEYED_CALL_IC:  return KeyedCallIC::Clear(address, target);
     case Code::BINARY_OP_IC:
@@ -288,9 +297,10 @@
   State state = target->ic_state();
   if (state == UNINITIALIZED) return;
   Code* code =
-      StubCache::FindCallInitialize(target->arguments_count(),
-                                    target->ic_in_loop(),
-                                    target->kind());
+      Isolate::Current()->stub_cache()->FindCallInitialize(
+          target->arguments_count(),
+          target->ic_in_loop(),
+          target->kind());
   SetTargetAtAddress(address, code);
 }
 
@@ -298,7 +308,7 @@
 void KeyedLoadIC::ClearInlinedVersion(Address address) {
   // Insert null as the map to check for to make sure the map check fails
   // sending control flow to the IC instead of the inlined version.
-  PatchInlinedLoad(address, Heap::null_value());
+  PatchInlinedLoad(address, HEAP->null_value());
 }
 
 
@@ -316,10 +326,11 @@
   // Reset the map check of the inlined inobject property load (if
   // present) to guarantee failure by holding an invalid map (the null
   // value).  The offset can be patched to anything.
-  PatchInlinedLoad(address, Heap::null_value(), 0);
+  Heap* heap = HEAP;
+  PatchInlinedLoad(address, heap->null_value(), 0);
   PatchInlinedContextualLoad(address,
-                             Heap::null_value(),
-                             Heap::null_value(),
+                             heap->null_value(),
+                             heap->null_value(),
                              true);
 }
 
@@ -335,7 +346,7 @@
   // Reset the map check of the inlined inobject property store (if
   // present) to guarantee failure by holding an invalid map (the null
   // value).  The offset can be patched to anything.
-  PatchInlinedStore(address, Heap::null_value(), 0);
+  PatchInlinedStore(address, HEAP->null_value(), 0);
 }
 
 
@@ -353,14 +364,14 @@
   // Insert null as the elements map to check for.  This will make
   // sure that the elements fast-case map check fails so that control
   // flows to the IC instead of the inlined version.
-  PatchInlinedStore(address, Heap::null_value());
+  PatchInlinedStore(address, HEAP->null_value());
 }
 
 
 void KeyedStoreIC::RestoreInlinedVersion(Address address) {
   // Restore the fast-case elements map check so that the inlined
   // version can be used again.
-  PatchInlinedStore(address, Heap::fixed_array_map());
+  PatchInlinedStore(address, HEAP->fixed_array_map());
 }
 
 
@@ -419,8 +430,8 @@
 
 
 Object* CallICBase::TryCallAsFunction(Object* object) {
-  HandleScope scope;
-  Handle<Object> target(object);
+  HandleScope scope(isolate());
+  Handle<Object> target(object, isolate());
   Handle<Object> delegate = Execution::GetFunctionDelegate(target);
 
   if (delegate->IsJSFunction()) {
@@ -455,7 +466,7 @@
     StackFrameLocator locator;
     JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
     int index = frame->ComputeExpressionsCount() - (argc + 1);
-    frame->SetExpression(index, *Factory::ToObject(object));
+    frame->SetExpression(index, *isolate()->factory()->ToObject(object));
   }
 }
 
@@ -527,7 +538,7 @@
 
   ASSERT(!result->IsTheHole());
 
-  HandleScope scope;
+  HandleScope scope(isolate());
   // Wrap result in a handle because ReceiverToObjectIfRequired may allocate
   // new object and cause GC.
   Handle<Object> result_handle(result);
@@ -539,11 +550,12 @@
   if (result_handle->IsJSFunction()) {
 #ifdef ENABLE_DEBUGGER_SUPPORT
     // Handle stepping into a function if step into is active.
-    if (Debug::StepInActive()) {
+    Debug* debug = isolate()->debug();
+    if (debug->StepInActive()) {
       // Protect the result in a handle as the debugger can allocate and might
       // cause GC.
-      Handle<JSFunction> function(JSFunction::cast(*result_handle));
-      Debug::HandleStepIn(function, object, fp(), false);
+      Handle<JSFunction> function(JSFunction::cast(*result_handle), isolate());
+      debug->HandleStepIn(function, object, fp(), false);
       return *function;
     }
 #endif
@@ -569,7 +581,7 @@
 
   // Fetch the arguments passed to the called function.
   const int argc = target()->arguments_count();
-  Address entry = Top::c_entry_fp(Top::GetCurrentThread());
+  Address entry = isolate()->c_entry_fp(isolate()->thread_local_top());
   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
   Arguments args(argc + 1,
                  &Memory::Object_at(fp +
@@ -619,13 +631,13 @@
   switch (lookup->type()) {
     case FIELD: {
       int index = lookup->GetFieldIndex();
-      maybe_code = StubCache::ComputeCallField(argc,
-                                               in_loop,
-                                               kind_,
-                                               *name,
-                                               *object,
-                                               lookup->holder(),
-                                               index);
+      maybe_code = isolate()->stub_cache()->ComputeCallField(argc,
+                                                             in_loop,
+                                                             kind_,
+                                                             *name,
+                                                             *object,
+                                                             lookup->holder(),
+                                                             index);
       break;
     }
     case CONSTANT_FUNCTION: {
@@ -633,14 +645,15 @@
       // call; used for rewriting to monomorphic state and making sure
       // that the code stub is in the stub cache.
       JSFunction* function = lookup->GetConstantFunction();
-      maybe_code = StubCache::ComputeCallConstant(argc,
-                                                  in_loop,
-                                                  kind_,
-                                                  extra_ic_state,
-                                                  *name,
-                                                  *object,
-                                                  lookup->holder(),
-                                                  function);
+      maybe_code =
+          isolate()->stub_cache()->ComputeCallConstant(argc,
+                                                       in_loop,
+                                                       kind_,
+                                                       extra_ic_state,
+                                                       *name,
+                                                       *object,
+                                                       lookup->holder(),
+                                                       function);
       break;
     }
     case NORMAL: {
@@ -653,35 +666,36 @@
             JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
         if (!cell->value()->IsJSFunction()) return NULL;
         JSFunction* function = JSFunction::cast(cell->value());
-        maybe_code = StubCache::ComputeCallGlobal(argc,
-                                                  in_loop,
-                                                  kind_,
-                                                  *name,
-                                                  *receiver,
-                                                  global,
-                                                  cell,
-                                                  function);
+        maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc,
+                                                                in_loop,
+                                                                kind_,
+                                                                *name,
+                                                                *receiver,
+                                                                global,
+                                                                cell,
+                                                                function);
       } else {
         // 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 (lookup->holder() != *receiver) return NULL;
-        maybe_code = StubCache::ComputeCallNormal(argc,
-                                                  in_loop,
-                                                  kind_,
-                                                  *name,
-                                                  *receiver);
+        maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc,
+                                                                in_loop,
+                                                                kind_,
+                                                                *name,
+                                                                *receiver);
       }
       break;
     }
     case INTERCEPTOR: {
       ASSERT(HasInterceptorGetter(lookup->holder()));
-      maybe_code = StubCache::ComputeCallInterceptor(argc,
-                                                     kind_,
-                                                     *name,
-                                                     *object,
-                                                     lookup->holder());
+      maybe_code = isolate()->stub_cache()->ComputeCallInterceptor(
+          argc,
+          kind_,
+          *name,
+          *object,
+          lookup->holder());
       break;
     }
     default:
@@ -701,7 +715,8 @@
   if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
 
   if (lookup->holder() != *object &&
-      HasNormalObjectsInPrototypeChain(lookup, object->GetPrototype())) {
+      HasNormalObjectsInPrototypeChain(
+          isolate(), lookup, object->GetPrototype())) {
     // Suppress optimization for prototype chains with slow properties objects
     // in the middle.
     return;
@@ -716,7 +731,9 @@
     // This is the first time we execute this inline cache.
     // Set the target to the pre monomorphic stub to delay
     // setting the monomorphic state.
-    maybe_code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_);
+    maybe_code = isolate()->stub_cache()->ComputeCallPreMonomorphic(argc,
+                                                                    in_loop,
+                                                                    kind_);
   } else if (state == MONOMORPHIC) {
     if (kind_ == Code::CALL_IC &&
         TryUpdateExtraICState(lookup, object, &extra_ic_state)) {
@@ -736,7 +753,9 @@
                                           object,
                                           name);
     } else {
-      maybe_code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_);
+      maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic(argc,
+                                                                   in_loop,
+                                                                   kind_);
     }
   } else {
     maybe_code = ComputeMonomorphicStub(lookup,
@@ -764,7 +783,7 @@
                               object->GetPrototype())->map();
 
     // Update the stub cache.
-    StubCache::Set(*name, map, Code::cast(code));
+    isolate()->stub_cache()->Set(*name, map, Code::cast(code));
   }
 
   USE(had_proto_failure);
@@ -793,7 +812,7 @@
   if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) {
     int argc = target()->arguments_count();
     InLoopFlag in_loop = target()->ic_in_loop();
-    MaybeObject* maybe_code = StubCache::ComputeCallMegamorphic(
+    MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic(
         argc, in_loop, Code::KEYED_CALL_IC);
     Object* code;
     if (maybe_code->ToObject(&code)) {
@@ -805,9 +824,9 @@
     }
   }
 
-  HandleScope scope;
+  HandleScope scope(isolate());
   Handle<Object> result = GetProperty(object, key);
-  RETURN_IF_EMPTY_HANDLE(result);
+  RETURN_IF_EMPTY_HANDLE(isolate(), result);
 
   // Make receiver an object if the callee requires it. Strict mode or builtin
   // functions do not wrap the receiver, non-strict functions and objects
@@ -848,8 +867,8 @@
     // 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;
+        name->Equals(isolate()->heap()->length_symbol())) {
+      HandleScope scope(isolate());
 #ifdef DEBUG
       if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
 #endif
@@ -858,24 +877,29 @@
           Map* map = HeapObject::cast(*object)->map();
           const int offset = String::kLengthOffset;
           PatchInlinedLoad(address(), map, offset);
-          set_target(Builtins::builtin(Builtins::LoadIC_StringLength));
+          set_target(isolate()->builtins()->builtin(
+              Builtins::kLoadIC_StringLength));
         } else {
-          set_target(Builtins::builtin(Builtins::LoadIC_StringWrapperLength));
+          set_target(isolate()->builtins()->builtin(
+              Builtins::kLoadIC_StringWrapperLength));
         }
       } else if (state == MONOMORPHIC && object->IsStringWrapper()) {
-        set_target(Builtins::builtin(Builtins::LoadIC_StringWrapperLength));
+        set_target(isolate()->builtins()->builtin(
+            Builtins::kLoadIC_StringWrapperLength));
       } else {
         set_target(non_monomorphic_stub);
       }
       // Get the string if we have a string wrapper object.
       if (object->IsJSValue()) {
-        object = Handle<Object>(Handle<JSValue>::cast(object)->value());
+        object = Handle<Object>(Handle<JSValue>::cast(object)->value(),
+                                isolate());
       }
       return Smi::FromInt(String::cast(*object)->length());
     }
 
     // Use specialized code for getting the length of arrays.
-    if (object->IsJSArray() && name->Equals(Heap::length_symbol())) {
+    if (object->IsJSArray() &&
+        name->Equals(isolate()->heap()->length_symbol())) {
 #ifdef DEBUG
       if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
 #endif
@@ -883,7 +907,8 @@
         Map* map = HeapObject::cast(*object)->map();
         const int offset = JSArray::kLengthOffset;
         PatchInlinedLoad(address(), map, offset);
-        set_target(Builtins::builtin(Builtins::LoadIC_ArrayLength));
+        set_target(isolate()->builtins()->builtin(
+            Builtins::kLoadIC_ArrayLength));
       } else {
         set_target(non_monomorphic_stub);
       }
@@ -891,13 +916,15 @@
     }
 
     // Use specialized code for getting prototype of functions.
-    if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) &&
+    if (object->IsJSFunction() &&
+        name->Equals(isolate()->heap()->prototype_symbol()) &&
         JSFunction::cast(*object)->should_have_prototype()) {
 #ifdef DEBUG
       if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
 #endif
       if (state == PREMONOMORPHIC) {
-        set_target(Builtins::builtin(Builtins::LoadIC_FunctionPrototype));
+        set_target(isolate()->builtins()->builtin(
+            Builtins::kLoadIC_FunctionPrototype));
       } else {
         set_target(non_monomorphic_stub);
       }
@@ -919,7 +946,7 @@
     if (FLAG_strict || IsContextual(object)) {
       return ReferenceError("not_defined", name);
     }
-    LOG(SuspectReadEvent(*name, *object));
+    LOG(isolate(), SuspectReadEvent(*name, *object));
   }
 
   bool can_be_inlined_precheck =
@@ -970,7 +997,7 @@
                                    lookup.IsDontDelete())) {
       set_target(megamorphic_stub());
       TRACE_IC_NAMED("[LoadIC : inline contextual patch %s]\n", name);
-      ASSERT(cell->value() != Heap::the_hole_value());
+      ASSERT(cell->value() != isolate()->heap()->the_hole_value());
       return cell->value();
     }
   } else {
@@ -1017,7 +1044,7 @@
   if (!object->IsJSObject()) return;
   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
 
-  if (HasNormalObjectsInPrototypeChain(lookup, *object)) return;
+  if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
 
   // Compute the code stub for this load.
   MaybeObject* maybe_code = NULL;
@@ -1029,20 +1056,23 @@
     maybe_code = pre_monomorphic_stub();
   } else if (!lookup->IsProperty()) {
     // Nonexistent property. The result is undefined.
-    maybe_code = StubCache::ComputeLoadNonexistent(*name, *receiver);
+    maybe_code = isolate()->stub_cache()->ComputeLoadNonexistent(*name,
+                                                                 *receiver);
   } else {
     // Compute monomorphic stub.
     switch (lookup->type()) {
       case FIELD: {
-        maybe_code = StubCache::ComputeLoadField(*name, *receiver,
-                                                 lookup->holder(),
-                                                 lookup->GetFieldIndex());
+        maybe_code = isolate()->stub_cache()->ComputeLoadField(
+            *name,
+            *receiver,
+            lookup->holder(),
+            lookup->GetFieldIndex());
         break;
       }
       case CONSTANT_FUNCTION: {
         Object* constant = lookup->GetConstantFunction();
-        maybe_code = StubCache::ComputeLoadConstant(*name, *receiver,
-                                                    lookup->holder(), constant);
+        maybe_code = isolate()->stub_cache()->ComputeLoadConstant(
+            *name, *receiver, lookup->holder(), constant);
         break;
       }
       case NORMAL: {
@@ -1050,7 +1080,7 @@
           GlobalObject* global = GlobalObject::cast(lookup->holder());
           JSGlobalPropertyCell* cell =
               JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
-          maybe_code = StubCache::ComputeLoadGlobal(*name,
+          maybe_code = isolate()->stub_cache()->ComputeLoadGlobal(*name,
                                                     *receiver,
                                                     global,
                                                     cell,
@@ -1061,7 +1091,7 @@
           // property must be found in the receiver for the stub to be
           // applicable.
           if (lookup->holder() != *receiver) return;
-          maybe_code = StubCache::ComputeLoadNormal();
+          maybe_code = isolate()->stub_cache()->ComputeLoadNormal();
         }
         break;
       }
@@ -1070,14 +1100,14 @@
         AccessorInfo* callback =
             AccessorInfo::cast(lookup->GetCallbackObject());
         if (v8::ToCData<Address>(callback->getter()) == 0) return;
-        maybe_code = StubCache::ComputeLoadCallback(*name, *receiver,
-                                                    lookup->holder(), callback);
+        maybe_code = isolate()->stub_cache()->ComputeLoadCallback(
+            *name, *receiver, lookup->holder(), callback);
         break;
       }
       case INTERCEPTOR: {
         ASSERT(HasInterceptorGetter(lookup->holder()));
-        maybe_code = StubCache::ComputeLoadInterceptor(*name, *receiver,
-                                                       lookup->holder());
+        maybe_code = isolate()->stub_cache()->ComputeLoadInterceptor(
+            *name, *receiver, lookup->holder());
         break;
       }
       default:
@@ -1101,7 +1131,7 @@
     Map* map = JSObject::cast(object->IsJSObject() ? *object :
                               object->GetPrototype())->map();
 
-    StubCache::Set(*name, map, Code::cast(code));
+    isolate()->stub_cache()->Set(*name, map, Code::cast(code));
   }
 
 #ifdef DEBUG
@@ -1126,11 +1156,13 @@
       // TODO(1073): don't ignore the current stub state.
 
       // Use specialized code for getting the length of strings.
-      if (object->IsString() && name->Equals(Heap::length_symbol())) {
+      if (object->IsString() &&
+          name->Equals(isolate()->heap()->length_symbol())) {
         Handle<String> string = Handle<String>::cast(object);
         Object* code = NULL;
         { MaybeObject* maybe_code =
-              StubCache::ComputeKeyedLoadStringLength(*name, *string);
+              isolate()->stub_cache()->ComputeKeyedLoadStringLength(*name,
+                                                                    *string);
           if (!maybe_code->ToObject(&code)) return maybe_code;
         }
         set_target(Code::cast(code));
@@ -1141,11 +1173,13 @@
       }
 
       // Use specialized code for getting the length of arrays.
-      if (object->IsJSArray() && name->Equals(Heap::length_symbol())) {
+      if (object->IsJSArray() &&
+          name->Equals(isolate()->heap()->length_symbol())) {
         Handle<JSArray> array = Handle<JSArray>::cast(object);
         Object* code;
         { MaybeObject* maybe_code =
-              StubCache::ComputeKeyedLoadArrayLength(*name, *array);
+              isolate()->stub_cache()->ComputeKeyedLoadArrayLength(*name,
+                                                                   *array);
           if (!maybe_code->ToObject(&code)) return maybe_code;
         }
         set_target(Code::cast(code));
@@ -1156,12 +1190,14 @@
       }
 
       // Use specialized code for getting prototype of functions.
-      if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) &&
+      if (object->IsJSFunction() &&
+          name->Equals(isolate()->heap()->prototype_symbol()) &&
         JSFunction::cast(*object)->should_have_prototype()) {
         Handle<JSFunction> function = Handle<JSFunction>::cast(object);
         Object* code;
         { MaybeObject* maybe_code =
-              StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function);
+              isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype(
+                  *name, *function);
           if (!maybe_code->ToObject(&code)) return maybe_code;
         }
         set_target(Code::cast(code));
@@ -1176,10 +1212,10 @@
     // the element or char if so.
     uint32_t index = 0;
     if (name->AsArrayIndex(&index)) {
-      HandleScope scope;
+      HandleScope scope(isolate());
       // Rewrite to the generic keyed load stub.
       if (FLAG_use_ic) set_target(generic_stub());
-      return Runtime::GetElementOrCharAt(object, index);
+      return Runtime::GetElementOrCharAt(isolate(), object, index);
     }
 
     // Named lookup.
@@ -1229,22 +1265,16 @@
         Handle<JSObject> receiver = Handle<JSObject>::cast(object);
         if (receiver->HasExternalArrayElements()) {
           MaybeObject* probe =
-              StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver,
-                                                              false,
-                                                              kNonStrictMode);
+              isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
+                  *receiver, false, kNonStrictMode);
           stub = probe->IsFailure() ?
               NULL : Code::cast(probe->ToObjectUnchecked());
         } else if (receiver->HasIndexedInterceptor()) {
           stub = indexed_interceptor_stub();
-        } else if (receiver->HasPixelElements()) {
-          MaybeObject* probe =
-              StubCache::ComputeKeyedLoadPixelArray(*receiver);
-          stub = probe->IsFailure() ?
-              NULL : Code::cast(probe->ToObjectUnchecked());
         } else if (key->IsSmi() &&
                    receiver->map()->has_fast_elements()) {
           MaybeObject* probe =
-              StubCache::ComputeKeyedLoadSpecialized(*receiver);
+              isolate()->stub_cache()->ComputeKeyedLoadSpecialized(*receiver);
           stub = probe->IsFailure() ?
               NULL : Code::cast(probe->ToObjectUnchecked());
         }
@@ -1270,7 +1300,7 @@
   }
 
   // Get the property.
-  return Runtime::GetObjectProperty(object, key);
+  return Runtime::GetObjectProperty(isolate(), object, key);
 }
 
 
@@ -1282,7 +1312,7 @@
   if (!object->IsJSObject()) return;
   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
 
-  if (HasNormalObjectsInPrototypeChain(lookup, *object)) return;
+  if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
 
   // Compute the code stub for this load.
   MaybeObject* maybe_code = NULL;
@@ -1297,17 +1327,14 @@
     // Compute a monomorphic stub.
     switch (lookup->type()) {
       case FIELD: {
-        maybe_code = StubCache::ComputeKeyedLoadField(*name, *receiver,
-                                                      lookup->holder(),
-                                                      lookup->GetFieldIndex());
+        maybe_code = isolate()->stub_cache()->ComputeKeyedLoadField(
+            *name, *receiver, lookup->holder(), lookup->GetFieldIndex());
         break;
       }
       case CONSTANT_FUNCTION: {
         Object* constant = lookup->GetConstantFunction();
-        maybe_code = StubCache::ComputeKeyedLoadConstant(*name,
-                                                         *receiver,
-                                                         lookup->holder(),
-                                                         constant);
+        maybe_code = isolate()->stub_cache()->ComputeKeyedLoadConstant(
+            *name, *receiver, lookup->holder(), constant);
         break;
       }
       case CALLBACKS: {
@@ -1315,16 +1342,14 @@
         AccessorInfo* callback =
             AccessorInfo::cast(lookup->GetCallbackObject());
         if (v8::ToCData<Address>(callback->getter()) == 0) return;
-        maybe_code = StubCache::ComputeKeyedLoadCallback(*name,
-                                                         *receiver,
-                                                         lookup->holder(),
-                                                         callback);
+        maybe_code = isolate()->stub_cache()->ComputeKeyedLoadCallback(
+            *name, *receiver, lookup->holder(), callback);
         break;
       }
       case INTERCEPTOR: {
         ASSERT(HasInterceptorGetter(lookup->holder()));
-        maybe_code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver,
-                                                            lookup->holder());
+        maybe_code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
+            *name, *receiver, lookup->holder());
         break;
       }
       default: {
@@ -1400,7 +1425,7 @@
   if (!object->IsJSObject()) {
     // The length property of string values is read-only. Throw in strict mode.
     if (strict_mode == kStrictMode && object->IsString() &&
-        name->Equals(Heap::length_symbol())) {
+        name->Equals(isolate()->heap()->length_symbol())) {
       return TypeError("strict_read_only_property", object, name);
     }
     // Ignore stores where the receiver is not a JSObject.
@@ -1412,7 +1437,7 @@
   // Check if the given name is an array index.
   uint32_t index;
   if (name->AsArrayIndex(&index)) {
-    HandleScope scope;
+    HandleScope scope(isolate());
     Handle<Object> result = SetElement(receiver, index, value, strict_mode);
     if (result.is_null()) return Failure::Exception();
     return *value;
@@ -1420,15 +1445,15 @@
 
   // Use specialized code for setting the length of arrays.
   if (receiver->IsJSArray()
-      && name->Equals(Heap::length_symbol())
+      && name->Equals(isolate()->heap()->length_symbol())
       && receiver->AllowsSetElementsLength()) {
 #ifdef DEBUG
     if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
 #endif
     Builtins::Name target = (strict_mode == kStrictMode)
-        ? Builtins::StoreIC_ArrayLength_Strict
-        : Builtins::StoreIC_ArrayLength;
-    set_target(Builtins::builtin(target));
+        ? Builtins::kStoreIC_ArrayLength_Strict
+        : Builtins::kStoreIC_ArrayLength;
+    set_target(isolate()->builtins()->builtin(target));
     return receiver->SetProperty(*name, *value, NONE, strict_mode);
   }
 
@@ -1544,17 +1569,17 @@
   Object* code = NULL;
   switch (type) {
     case FIELD: {
-      maybe_code = StubCache::ComputeStoreField(
+      maybe_code = isolate()->stub_cache()->ComputeStoreField(
           *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
       break;
     }
     case MAP_TRANSITION: {
       if (lookup->GetAttributes() != NONE) return;
-      HandleScope scope;
+      HandleScope scope(isolate());
       ASSERT(type == MAP_TRANSITION);
       Handle<Map> transition(lookup->GetTransitionMap());
       int index = transition->PropertyIndexFor(*name);
-      maybe_code = StubCache::ComputeStoreField(
+      maybe_code = isolate()->stub_cache()->ComputeStoreField(
           *name, *receiver, index, *transition, strict_mode);
       break;
     }
@@ -1566,11 +1591,11 @@
         Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
         JSGlobalPropertyCell* cell =
             JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
-        maybe_code = StubCache::ComputeStoreGlobal(
+        maybe_code = isolate()->stub_cache()->ComputeStoreGlobal(
             *name, *global, cell, strict_mode);
       } else {
         if (lookup->holder() != *receiver) return;
-        maybe_code = StubCache::ComputeStoreNormal(strict_mode);
+        maybe_code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode);
       }
       break;
     }
@@ -1578,13 +1603,13 @@
       if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
       AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
       if (v8::ToCData<Address>(callback->setter()) == 0) return;
-      maybe_code = StubCache::ComputeStoreCallback(
+      maybe_code = isolate()->stub_cache()->ComputeStoreCallback(
           *name, *receiver, callback, strict_mode);
       break;
     }
     case INTERCEPTOR: {
       ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
-      maybe_code = StubCache::ComputeStoreInterceptor(
+      maybe_code = isolate()->stub_cache()->ComputeStoreInterceptor(
           *name, *receiver, strict_mode);
       break;
     }
@@ -1608,7 +1633,9 @@
     }
   } else if (state == MEGAMORPHIC) {
     // Update the stub cache.
-    StubCache::Set(*name, receiver->map(), Code::cast(code));
+    isolate()->stub_cache()->Set(*name,
+                                 receiver->map(),
+                                 Code::cast(code));
   }
 
 #ifdef DEBUG
@@ -1638,7 +1665,7 @@
     // Check if the given name is an array index.
     uint32_t index;
     if (name->AsArrayIndex(&index)) {
-      HandleScope scope;
+      HandleScope scope(isolate());
       Handle<Object> result = SetElement(receiver, index, value, strict_mode);
       if (result.is_null()) return Failure::Exception();
       return *value;
@@ -1670,18 +1697,14 @@
         Handle<JSObject> receiver = Handle<JSObject>::cast(object);
         if (receiver->HasExternalArrayElements()) {
           MaybeObject* probe =
-              StubCache::ComputeKeyedLoadOrStoreExternalArray(
+              isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
                   *receiver, true, strict_mode);
           stub = probe->IsFailure() ?
               NULL : Code::cast(probe->ToObjectUnchecked());
-        } else if (receiver->HasPixelElements()) {
-          MaybeObject* probe =
-              StubCache::ComputeKeyedStorePixelArray(*receiver, strict_mode);
-          stub = probe->IsFailure() ?
-              NULL : Code::cast(probe->ToObjectUnchecked());
         } else if (key->IsSmi() && receiver->map()->has_fast_elements()) {
           MaybeObject* probe =
-              StubCache::ComputeKeyedStoreSpecialized(*receiver, strict_mode);
+              isolate()->stub_cache()->ComputeKeyedStoreSpecialized(
+                  *receiver, strict_mode);
           stub = probe->IsFailure() ?
               NULL : Code::cast(probe->ToObjectUnchecked());
         }
@@ -1691,7 +1714,8 @@
   }
 
   // Set the property.
-  return Runtime::SetObjectProperty(object, key, value, NONE, strict_mode);
+  return Runtime::SetObjectProperty(
+      isolate(), object , key, value, NONE, strict_mode);
 }
 
 
@@ -1724,17 +1748,17 @@
 
   switch (type) {
     case FIELD: {
-      maybe_code = StubCache::ComputeKeyedStoreField(
+      maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField(
           *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
       break;
     }
     case MAP_TRANSITION: {
       if (lookup->GetAttributes() == NONE) {
-        HandleScope scope;
+        HandleScope scope(isolate());
         ASSERT(type == MAP_TRANSITION);
         Handle<Map> transition(lookup->GetTransitionMap());
         int index = transition->PropertyIndexFor(*name);
-        maybe_code = StubCache::ComputeKeyedStoreField(
+        maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField(
             *name, *receiver, index, *transition, strict_mode);
         break;
       }
@@ -1775,11 +1799,12 @@
 // Static IC stub generators.
 //
 
-static JSFunction* CompileFunction(JSFunction* function,
+static JSFunction* CompileFunction(Isolate* isolate,
+                                   JSFunction* function,
                                    InLoopFlag in_loop) {
   // Compile now with optimization.
-  HandleScope scope;
-  Handle<JSFunction> function_handle(function);
+  HandleScope scope(isolate);
+  Handle<JSFunction> function_handle(function, isolate);
   if (in_loop == IN_LOOP) {
     CompileLazyInLoop(function_handle, CLEAR_EXCEPTION);
   } else {
@@ -1790,10 +1815,11 @@
 
 
 // Used from ic-<arch>.cc.
-MUST_USE_RESULT MaybeObject* CallIC_Miss(Arguments args) {
+MUST_USE_RESULT MaybeObject* CallIC_Miss(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation na;
   ASSERT(args.length() == 2);
-  CallIC ic;
+  CallIC ic(isolate);
   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
   MaybeObject* maybe_result = ic.LoadFunction(state,
@@ -1813,15 +1839,18 @@
   if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
     return result;
   }
-  return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop());
+  return CompileFunction(isolate,
+                         JSFunction::cast(result),
+                         ic.target()->ic_in_loop());
 }
 
 
 // Used from ic-<arch>.cc.
-MUST_USE_RESULT MaybeObject* KeyedCallIC_Miss(Arguments args) {
+MUST_USE_RESULT MaybeObject* KeyedCallIC_Miss(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation na;
   ASSERT(args.length() == 2);
-  KeyedCallIC ic;
+  KeyedCallIC ic(isolate);
   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   Object* result;
   { MaybeObject* maybe_result =
@@ -1832,35 +1861,40 @@
   if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
     return result;
   }
-  return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop());
+  return CompileFunction(isolate,
+                         JSFunction::cast(result),
+                         ic.target()->ic_in_loop());
 }
 
 
 // Used from ic-<arch>.cc.
-MUST_USE_RESULT MaybeObject* LoadIC_Miss(Arguments args) {
+MUST_USE_RESULT MaybeObject* LoadIC_Miss(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation na;
   ASSERT(args.length() == 2);
-  LoadIC ic;
+  LoadIC ic(isolate);
   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   return ic.Load(state, args.at<Object>(0), args.at<String>(1));
 }
 
 
 // Used from ic-<arch>.cc
-MUST_USE_RESULT MaybeObject* KeyedLoadIC_Miss(Arguments args) {
+MUST_USE_RESULT MaybeObject* KeyedLoadIC_Miss(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation na;
   ASSERT(args.length() == 2);
-  KeyedLoadIC ic;
+  KeyedLoadIC ic(isolate);
   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   return ic.Load(state, args.at<Object>(0), args.at<Object>(1));
 }
 
 
 // Used from ic-<arch>.cc.
-MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) {
+MUST_USE_RESULT MaybeObject* StoreIC_Miss(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation na;
   ASSERT(args.length() == 3);
-  StoreIC ic;
+  StoreIC ic(isolate);
   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
   return ic.Store(state,
@@ -1871,7 +1905,8 @@
 }
 
 
-MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(Arguments args) {
+MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation nha;
 
   ASSERT(args.length() == 2);
@@ -1892,7 +1927,9 @@
 // Extend storage is called in a store inline cache when
 // it is necessary to extend the properties array of a
 // JSObject.
-MUST_USE_RESULT MaybeObject* SharedStoreIC_ExtendStorage(Arguments args) {
+MUST_USE_RESULT MaybeObject* SharedStoreIC_ExtendStorage(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation na;
   ASSERT(args.length() == 3);
 
@@ -1926,10 +1963,11 @@
 
 
 // Used from ic-<arch>.cc.
-MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(Arguments args) {
+MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation na;
   ASSERT(args.length() == 3);
-  KeyedStoreIC ic;
+  KeyedStoreIC ic(isolate);
   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
   return ic.Store(state,
@@ -1999,10 +2037,11 @@
 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info);
 
 
-MUST_USE_RESULT MaybeObject* BinaryOp_Patch(Arguments args) {
+MUST_USE_RESULT MaybeObject* BinaryOp_Patch(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 5);
 
-  HandleScope scope;
+  HandleScope scope(isolate);
   Handle<Object> left = args.at<Object>(0);
   Handle<Object> right = args.at<Object>(1);
   int key = Smi::cast(args[2])->value();
@@ -2013,7 +2052,7 @@
   BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(*left, *right);
   Handle<Code> code = GetBinaryOpStub(key, type);
   if (!code.is_null()) {
-    BinaryOpIC ic;
+    BinaryOpIC ic(isolate);
     ic.patch(*code);
     if (FLAG_trace_ic) {
       PrintF("[BinaryOpIC (%s->%s)#%s]\n",
@@ -2023,7 +2062,8 @@
     }
   }
 
-  Handle<JSBuiltinsObject> builtins = Top::builtins();
+  Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>(
+      isolate->thread_local_top()->context_->builtins(), isolate);
   Object* builtin = NULL;  // Initialization calms down the compiler.
   switch (op) {
     case Token::ADD:
@@ -2063,7 +2103,8 @@
       UNREACHABLE();
   }
 
-  Handle<JSFunction> builtin_function(JSFunction::cast(builtin));
+  Handle<JSFunction> builtin_function(JSFunction::cast(builtin),
+                                      isolate);
 
   bool caught_exception;
   Object** builtin_args[] = { right.location() };
@@ -2090,6 +2131,7 @@
     case SMI: return "SMI";
     case INT32: return "Int32s";
     case HEAP_NUMBER: return "HeapNumbers";
+    case ODDBALL: return "Oddball";
     case STRING: return "Strings";
     case GENERIC: return "Generic";
     default: return "Invalid";
@@ -2104,6 +2146,7 @@
     case SMI:
     case INT32:
     case HEAP_NUMBER:
+    case ODDBALL:
     case STRING:
       return MONOMORPHIC;
     case GENERIC:
@@ -2151,6 +2194,10 @@
     return STRING;
   }
 
+  // Check for oddball objects.
+  if (left->IsUndefined() && right->IsNumber()) return ODDBALL;
+  if (left->IsNumber() && right->IsUndefined()) return ODDBALL;
+
   return GENERIC;
 }
 
@@ -2162,10 +2209,11 @@
                                           TRBinaryOpIC::TypeInfo result_type);
 
 
-MaybeObject* TypeRecordingBinaryOp_Patch(Arguments args) {
+MaybeObject* TypeRecordingBinaryOp_Patch(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 5);
 
-  HandleScope scope;
+  HandleScope scope(isolate);
   Handle<Object> left = args.at<Object>(0);
   Handle<Object> right = args.at<Object>(1);
   int key = Smi::cast(args[2])->value();
@@ -2207,7 +2255,7 @@
              TRBinaryOpIC::GetName(result_type),
              Token::Name(op));
     }
-    TRBinaryOpIC ic;
+    TRBinaryOpIC ic(isolate);
     ic.patch(*code);
 
     // Activate inlined smi code.
@@ -2216,7 +2264,8 @@
     }
   }
 
-  Handle<JSBuiltinsObject> builtins = Top::builtins();
+  Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>(
+      isolate->thread_local_top()->context_->builtins(), isolate);
   Object* builtin = NULL;  // Initialization calms down the compiler.
   switch (op) {
     case Token::ADD:
@@ -2256,7 +2305,7 @@
       UNREACHABLE();
   }
 
-  Handle<JSFunction> builtin_function(JSFunction::cast(builtin));
+  Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);
 
   bool caught_exception;
   Object** builtin_args[] = { right.location() };
@@ -2316,16 +2365,17 @@
 
 
 // Used from ic_<arch>.cc.
-Code* CompareIC_Miss(Arguments args) {
+Code* CompareIC_Miss(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation na;
   ASSERT(args.length() == 3);
-  CompareIC ic(static_cast<Token::Value>(Smi::cast(args[2])->value()));
+  CompareIC ic(isolate, static_cast<Token::Value>(Smi::cast(args[2])->value()));
   ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
   return ic.target();
 }
 
 
-static Address IC_utilities[] = {
+static const Address IC_utilities[] = {
 #define ADDR(name) FUNCTION_ADDR(name),
     IC_UTIL_LIST(ADDR)
     NULL
diff --git a/src/ic.h b/src/ic.h
index e12cbaf..bb8a981 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -86,7 +86,7 @@
 
   // Construct the IC structure with the given number of extra
   // JavaScript frames on the stack.
-  explicit IC(FrameDepth depth);
+  IC(FrameDepth depth, Isolate* isolate);
 
   // Get the call-site target; used for determining the state.
   Code* target() { return GetTargetAtAddress(address()); }
@@ -130,6 +130,7 @@
  protected:
   Address fp() const { return fp_; }
   Address pc() const { return *pc_address_; }
+  Isolate* isolate() const { return isolate_; }
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Computes the address in the original code when the code running is
@@ -148,10 +149,10 @@
                       const char* extra_info = "");
 #endif
 
-  static Failure* TypeError(const char* type,
-                            Handle<Object> object,
-                            Handle<Object> key);
-  static Failure* ReferenceError(const char* type, Handle<String> name);
+  Failure* TypeError(const char* type,
+                     Handle<Object> object,
+                     Handle<Object> key);
+  Failure* ReferenceError(const char* type, Handle<String> name);
 
   // Access the target code for the given IC address.
   static inline Code* GetTargetAtAddress(Address address);
@@ -167,6 +168,8 @@
   // invoke the garbage collector.
   Address* pc_address_;
 
+  Isolate* isolate_;
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
 };
 
@@ -189,7 +192,8 @@
 
 class CallICBase: public IC {
  protected:
-  explicit CallICBase(Code::Kind kind) : IC(EXTRA_CALL_FRAME), kind_(kind) {}
+  CallICBase(Code::Kind kind, Isolate* isolate)
+      : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
 
  public:
   MUST_USE_RESULT MaybeObject* LoadFunction(State state,
@@ -233,7 +237,9 @@
 
 class CallIC: public CallICBase {
  public:
-  CallIC() : CallICBase(Code::CALL_IC) { ASSERT(target()->is_call_stub()); }
+  explicit CallIC(Isolate* isolate) : CallICBase(Code::CALL_IC, isolate) {
+    ASSERT(target()->is_call_stub());
+  }
 
   // Code generator routines.
   static void GenerateInitialize(MacroAssembler* masm, int argc) {
@@ -247,7 +253,8 @@
 
 class KeyedCallIC: public CallICBase {
  public:
-  KeyedCallIC() : CallICBase(Code::KEYED_CALL_IC) {
+  explicit KeyedCallIC(Isolate* isolate)
+      : CallICBase(Code::KEYED_CALL_IC, isolate) {
     ASSERT(target()->is_keyed_call_stub());
   }
 
@@ -267,7 +274,9 @@
 
 class LoadIC: public IC {
  public:
-  LoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_load_stub()); }
+  explicit LoadIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
+    ASSERT(target()->is_load_stub());
+  }
 
   MUST_USE_RESULT MaybeObject* Load(State state,
                                     Handle<Object> object,
@@ -305,14 +314,17 @@
                     Handle<String> name);
 
   // Stub accessors.
-  static Code* megamorphic_stub() {
-    return Builtins::builtin(Builtins::LoadIC_Megamorphic);
+  Code* megamorphic_stub() {
+    return isolate()->builtins()->builtin(
+        Builtins::kLoadIC_Megamorphic);
   }
   static Code* initialize_stub() {
-    return Builtins::builtin(Builtins::LoadIC_Initialize);
+    return Isolate::Current()->builtins()->builtin(
+        Builtins::kLoadIC_Initialize);
   }
-  static Code* pre_monomorphic_stub() {
-    return Builtins::builtin(Builtins::LoadIC_PreMonomorphic);
+  Code* pre_monomorphic_stub() {
+    return isolate()->builtins()->builtin(
+        Builtins::kLoadIC_PreMonomorphic);
   }
 
   static void Clear(Address address, Code* target);
@@ -330,7 +342,9 @@
 
 class KeyedLoadIC: public IC {
  public:
-  KeyedLoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_keyed_load_stub()); }
+  explicit KeyedLoadIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
+    ASSERT(target()->is_keyed_load_stub());
+  }
 
   MUST_USE_RESULT MaybeObject* Load(State state,
                                     Handle<Object> object,
@@ -367,23 +381,29 @@
 
   // Stub accessors.
   static Code* initialize_stub() {
-    return Builtins::builtin(Builtins::KeyedLoadIC_Initialize);
+    return Isolate::Current()->builtins()->builtin(
+        Builtins::kKeyedLoadIC_Initialize);
   }
-  static Code* megamorphic_stub() {
-    return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
+  Code* megamorphic_stub() {
+    return isolate()->builtins()->builtin(
+        Builtins::kKeyedLoadIC_Generic);
   }
-  static Code* generic_stub() {
-    return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
+  Code* generic_stub() {
+    return isolate()->builtins()->builtin(
+        Builtins::kKeyedLoadIC_Generic);
   }
-  static Code* pre_monomorphic_stub() {
-    return Builtins::builtin(Builtins::KeyedLoadIC_PreMonomorphic);
+  Code* pre_monomorphic_stub() {
+    return isolate()->builtins()->builtin(
+        Builtins::kKeyedLoadIC_PreMonomorphic);
   }
-  static Code* string_stub() {
-    return Builtins::builtin(Builtins::KeyedLoadIC_String);
+  Code* string_stub() {
+    return isolate()->builtins()->builtin(
+        Builtins::kKeyedLoadIC_String);
   }
 
-  static Code* indexed_interceptor_stub() {
-    return Builtins::builtin(Builtins::KeyedLoadIC_IndexedInterceptor);
+  Code* indexed_interceptor_stub() {
+    return isolate()->builtins()->builtin(
+        Builtins::kKeyedLoadIC_IndexedInterceptor);
   }
 
   static void Clear(Address address, Code* target);
@@ -398,7 +418,9 @@
 
 class StoreIC: public IC {
  public:
-  StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); }
+  explicit StoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
+    ASSERT(target()->is_store_stub());
+  }
 
   MUST_USE_RESULT MaybeObject* Store(State state,
                                      StrictModeFlag strict_mode,
@@ -441,23 +463,29 @@
   }
 
   // Stub accessors.
-  static Code* megamorphic_stub() {
-    return Builtins::builtin(Builtins::StoreIC_Megamorphic);
+  Code* megamorphic_stub() {
+    return isolate()->builtins()->builtin(
+        Builtins::kStoreIC_Megamorphic);
   }
-  static Code* megamorphic_stub_strict() {
-    return Builtins::builtin(Builtins::StoreIC_Megamorphic_Strict);
+  Code* megamorphic_stub_strict() {
+    return isolate()->builtins()->builtin(
+        Builtins::kStoreIC_Megamorphic_Strict);
   }
   static Code* initialize_stub() {
-    return Builtins::builtin(Builtins::StoreIC_Initialize);
+    return Isolate::Current()->builtins()->builtin(
+        Builtins::kStoreIC_Initialize);
   }
   static Code* initialize_stub_strict() {
-    return Builtins::builtin(Builtins::StoreIC_Initialize_Strict);
+    return Isolate::Current()->builtins()->builtin(
+        Builtins::kStoreIC_Initialize_Strict);
   }
-  static Code* global_proxy_stub() {
-    return Builtins::builtin(Builtins::StoreIC_GlobalProxy);
+  Code* global_proxy_stub() {
+    return isolate()->builtins()->builtin(
+        Builtins::kStoreIC_GlobalProxy);
   }
-  static Code* global_proxy_stub_strict() {
-    return Builtins::builtin(Builtins::StoreIC_GlobalProxy_Strict);
+  Code* global_proxy_stub_strict() {
+    return isolate()->builtins()->builtin(
+        Builtins::kStoreIC_GlobalProxy_Strict);
   }
 
   static void Clear(Address address, Code* target);
@@ -472,7 +500,7 @@
 
 class KeyedStoreIC: public IC {
  public:
-  KeyedStoreIC() : IC(NO_EXTRA_FRAME) { }
+  explicit KeyedStoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
 
   MUST_USE_RESULT MaybeObject* Store(State state,
                                      StrictModeFlag strict_mode,
@@ -511,22 +539,28 @@
 
   // Stub accessors.
   static Code* initialize_stub() {
-    return Builtins::builtin(Builtins::KeyedStoreIC_Initialize);
+    return Isolate::Current()->builtins()->builtin(
+        Builtins::kKeyedStoreIC_Initialize);
+  }
+  Code* megamorphic_stub() {
+    return isolate()->builtins()->builtin(
+        Builtins::kKeyedStoreIC_Generic);
   }
   static Code* initialize_stub_strict() {
-    return Builtins::builtin(Builtins::KeyedStoreIC_Initialize_Strict);
+    return Isolate::Current()->builtins()->builtin(
+        Builtins::kKeyedStoreIC_Initialize_Strict);
   }
-  static Code* megamorphic_stub() {
-    return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
+  Code* megamorphic_stub_strict() {
+    return isolate()->builtins()->builtin(
+        Builtins::kKeyedStoreIC_Generic_Strict);
   }
-  static Code* megamorphic_stub_strict() {
-    return Builtins::builtin(Builtins::KeyedStoreIC_Generic_Strict);
+  Code* generic_stub() {
+    return isolate()->builtins()->builtin(
+        Builtins::kKeyedStoreIC_Generic);
   }
-  static Code* generic_stub() {
-    return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
-  }
-  static Code* generic_stub_strict() {
-    return Builtins::builtin(Builtins::KeyedStoreIC_Generic_Strict);
+  Code* generic_stub_strict() {
+    return isolate()->builtins()->builtin(
+        Builtins::kKeyedStoreIC_Generic_Strict);
   }
 
   static void Clear(Address address, Code* target);
@@ -555,7 +589,7 @@
     GENERIC   // Non-specialized case (processes any type combination).
   };
 
-  BinaryOpIC() : IC(NO_EXTRA_FRAME) { }
+  explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
 
   void patch(Code* code);
 
@@ -576,11 +610,12 @@
     SMI,
     INT32,
     HEAP_NUMBER,
+    ODDBALL,
     STRING,  // Only used for addition operation.  At least one string operand.
     GENERIC
   };
 
-  TRBinaryOpIC() : IC(NO_EXTRA_FRAME) { }
+  explicit TRBinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
 
   void patch(Code* code);
 
@@ -604,7 +639,8 @@
     GENERIC
   };
 
-  explicit CompareIC(Token::Value op) : IC(EXTRA_CALL_FRAME), op_(op) { }
+  CompareIC(Isolate* isolate, Token::Value op)
+      : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
 
   // Update the inline cache for the given operands.
   void UpdateCaches(Handle<Object> x, Handle<Object> y);
diff --git a/src/interpreter-irregexp.cc b/src/interpreter-irregexp.cc
index c9c3cc4..1c6c52c 100644
--- a/src/interpreter-irregexp.cc
+++ b/src/interpreter-irregexp.cc
@@ -40,10 +40,10 @@
 namespace internal {
 
 
-static unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize;
+typedef unibrow::Mapping<unibrow::Ecma262Canonicalize> Canonicalize;
 
-
-static bool BackRefMatchesNoCase(int from,
+static bool BackRefMatchesNoCase(Canonicalize* interp_canonicalize,
+                                 int from,
                                  int current,
                                  int len,
                                  Vector<const uc16> subject) {
@@ -53,8 +53,8 @@
     if (old_char == new_char) continue;
     unibrow::uchar old_string[1] = { old_char };
     unibrow::uchar new_string[1] = { new_char };
-    interp_canonicalize.get(old_char, '\0', old_string);
-    interp_canonicalize.get(new_char, '\0', new_string);
+    interp_canonicalize->get(old_char, '\0', old_string);
+    interp_canonicalize->get(new_char, '\0', new_string);
     if (old_string[0] != new_string[0]) {
       return false;
     }
@@ -63,7 +63,8 @@
 }
 
 
-static bool BackRefMatchesNoCase(int from,
+static bool BackRefMatchesNoCase(Canonicalize* interp_canonicalize,
+                                 int from,
                                  int current,
                                  int len,
                                  Vector<const char> subject) {
@@ -150,11 +151,11 @@
 // matching terminates.
 class BacktrackStack {
  public:
-  explicit BacktrackStack() {
-    if (cache_ != NULL) {
+  explicit BacktrackStack(Isolate* isolate) : isolate_(isolate) {
+    if (isolate->irregexp_interpreter_backtrack_stack_cache() != NULL) {
       // If the cache is not empty reuse the previously allocated stack.
-      data_ = cache_;
-      cache_ = NULL;
+      data_ = isolate->irregexp_interpreter_backtrack_stack_cache();
+      isolate->set_irregexp_interpreter_backtrack_stack_cache(NULL);
     } else {
       // Cache was empty. Allocate a new backtrack stack.
       data_ = NewArray<int>(kBacktrackStackSize);
@@ -162,9 +163,9 @@
   }
 
   ~BacktrackStack() {
-    if (cache_ == NULL) {
+    if (isolate_->irregexp_interpreter_backtrack_stack_cache() == NULL) {
       // The cache is empty. Keep this backtrack stack around.
-      cache_ = data_;
+      isolate_->set_irregexp_interpreter_backtrack_stack_cache(data_);
     } else {
       // A backtrack stack was already cached, just release this one.
       DeleteArray(data_);
@@ -179,16 +180,15 @@
   static const int kBacktrackStackSize = 10000;
 
   int* data_;
-  static int* cache_;
+  Isolate* isolate_;
 
   DISALLOW_COPY_AND_ASSIGN(BacktrackStack);
 };
 
-int* BacktrackStack::cache_ = NULL;
-
 
 template <typename Char>
-static bool RawMatch(const byte* code_base,
+static bool RawMatch(Isolate* isolate,
+                     const byte* code_base,
                      Vector<const Char> subject,
                      int* registers,
                      int current,
@@ -197,7 +197,7 @@
   // BacktrackStack ensures that the memory allocated for the backtracking stack
   // is returned to the system or cached if there is no stack being cached at
   // the moment.
-  BacktrackStack backtrack_stack;
+  BacktrackStack backtrack_stack(isolate);
   int* backtrack_stack_base = backtrack_stack.data();
   int* backtrack_sp = backtrack_stack_base;
   int backtrack_stack_space = backtrack_stack.max_size();
@@ -584,7 +584,8 @@
           pc = code_base + Load32Aligned(pc + 4);
           break;
         } else {
-          if (BackRefMatchesNoCase(from, current, len, subject)) {
+          if (BackRefMatchesNoCase(isolate->interp_canonicalize_mapping(),
+                                   from, current, len, subject)) {
             current += len;
             pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
           } else {
@@ -624,7 +625,8 @@
 }
 
 
-bool IrregexpInterpreter::Match(Handle<ByteArray> code_array,
+bool IrregexpInterpreter::Match(Isolate* isolate,
+                                Handle<ByteArray> code_array,
                                 Handle<String> subject,
                                 int* registers,
                                 int start_position) {
@@ -636,7 +638,8 @@
   if (subject->IsAsciiRepresentation()) {
     Vector<const char> subject_vector = subject->ToAsciiVector();
     if (start_position != 0) previous_char = subject_vector[start_position - 1];
-    return RawMatch(code_base,
+    return RawMatch(isolate,
+                    code_base,
                     subject_vector,
                     registers,
                     start_position,
@@ -644,7 +647,8 @@
   } else {
     Vector<const uc16> subject_vector = subject->ToUC16Vector();
     if (start_position != 0) previous_char = subject_vector[start_position - 1];
-    return RawMatch(code_base,
+    return RawMatch(isolate,
+                    code_base,
                     subject_vector,
                     registers,
                     start_position,
diff --git a/src/interpreter-irregexp.h b/src/interpreter-irregexp.h
index 0ad8846..076f0c5 100644
--- a/src/interpreter-irregexp.h
+++ b/src/interpreter-irregexp.h
@@ -36,7 +36,8 @@
 
 class IrregexpInterpreter {
  public:
-  static bool Match(Handle<ByteArray> code,
+  static bool Match(Isolate* isolate,
+                    Handle<ByteArray> code,
                     Handle<String> subject,
                     int* captures,
                     int start_position);
diff --git a/src/isolate.cc b/src/isolate.cc
new file mode 100644
index 0000000..a163532
--- /dev/null
+++ b/src/isolate.cc
@@ -0,0 +1,895 @@
+// Copyright 2006-2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "ast.h"
+#include "bootstrapper.h"
+#include "codegen.h"
+#include "compilation-cache.h"
+#include "debug.h"
+#include "deoptimizer.h"
+#include "heap-profiler.h"
+#include "hydrogen.h"
+#include "isolate.h"
+#include "lithium-allocator.h"
+#include "log.h"
+#include "regexp-stack.h"
+#include "runtime-profiler.h"
+#include "scanner.h"
+#include "scopeinfo.h"
+#include "serialize.h"
+#include "simulator.h"
+#include "spaces.h"
+#include "stub-cache.h"
+#include "version.h"
+
+
+namespace v8 {
+namespace internal {
+
+
+// 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:
+  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_;
+  }
+
+  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_;
+  }
+
+  // Stop the PreallocatedMemoryThread and release its resources.
+  void StopThread() {
+    keep_running_ = false;
+    wait_for_ever_semaphore_->Signal();
+
+    // Wait for the thread to terminate.
+    Join();
+
+    if (data_ready_semaphore_ != NULL) {
+      delete data_ready_semaphore_;
+      data_ready_semaphore_ = NULL;
+    }
+
+    delete wait_for_ever_semaphore_;
+    wait_for_ever_semaphore_ = NULL;
+  }
+
+ protected:
+  // 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, 15 * 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.start();
+    length_ = local_buffer.length();
+    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());
+  }
+
+
+ private:
+  explicit PreallocatedMemoryThread(Isolate* isolate)
+      : Thread(isolate, "v8:PreallocMem"),
+        keep_running_(true),
+        wait_for_ever_semaphore_(OS::CreateSemaphore(0)),
+        data_ready_semaphore_(OS::CreateSemaphore(0)),
+        data_(NULL),
+        length_(0) {
+  }
+
+  // Used to make sure that the thread keeps looping even for spurious wakeups.
+  bool keep_running_;
+
+  // This semaphore is used by the PreallocatedMemoryThread to wait for ever.
+  Semaphore* wait_for_ever_semaphore_;
+  // Semaphore to signal that the data has been initialized.
+  Semaphore* data_ready_semaphore_;
+
+  // Location and size of the preallocated memory block.
+  char* data_;
+  unsigned length_;
+
+  friend class Isolate;
+
+  DISALLOW_COPY_AND_ASSIGN(PreallocatedMemoryThread);
+};
+
+
+void Isolate::PreallocatedMemoryThreadStart() {
+  if (preallocated_memory_thread_ != NULL) return;
+  preallocated_memory_thread_ = new PreallocatedMemoryThread(this);
+  preallocated_memory_thread_->Start();
+}
+
+
+void Isolate::PreallocatedMemoryThreadStop() {
+  if (preallocated_memory_thread_ == NULL) return;
+  preallocated_memory_thread_->StopThread();
+  // Done with the thread entirely.
+  delete preallocated_memory_thread_;
+  preallocated_memory_thread_ = NULL;
+}
+
+
+void Isolate::PreallocatedStorageInit(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_storage_preallocated_ = true;
+}
+
+
+void* Isolate::PreallocatedStorageNew(size_t size) {
+  if (!preallocated_storage_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 Isolate::PreallocatedStorageDelete(void* p) {
+  if (p == NULL) {
+    return;
+  }
+  if (!preallocated_storage_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_);
+}
+
+
+Isolate* Isolate::default_isolate_ = NULL;
+Thread::LocalStorageKey Isolate::isolate_key_;
+Thread::LocalStorageKey Isolate::thread_id_key_;
+Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
+Mutex* Isolate::process_wide_mutex_ = OS::CreateMutex();
+Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
+Isolate::ThreadId Isolate::highest_thread_id_ = 0;
+
+
+class IsolateInitializer {
+ public:
+  IsolateInitializer() {
+    Isolate::EnsureDefaultIsolate();
+  }
+};
+
+static IsolateInitializer* EnsureDefaultIsolateAllocated() {
+  // TODO(isolates): Use the system threading API to do this once?
+  static IsolateInitializer static_initializer;
+  return &static_initializer;
+}
+
+// This variable only needed to trigger static intialization.
+static IsolateInitializer* static_initializer = EnsureDefaultIsolateAllocated();
+
+
+Isolate::ThreadId Isolate::AllocateThreadId() {
+  ThreadId new_id;
+  {
+    ScopedLock lock(process_wide_mutex_);
+    new_id = ++highest_thread_id_;
+  }
+  return new_id;
+}
+
+
+Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData(
+    ThreadId thread_id) {
+  ASSERT(thread_id != 0);
+  ASSERT(Thread::GetThreadLocalInt(thread_id_key_) == thread_id);
+  PerIsolateThreadData* per_thread = new PerIsolateThreadData(this, thread_id);
+  {
+    ScopedLock lock(process_wide_mutex_);
+    ASSERT(thread_data_table_->Lookup(this, thread_id) == NULL);
+    thread_data_table_->Insert(per_thread);
+    ASSERT(thread_data_table_->Lookup(this, thread_id) == per_thread);
+  }
+  return per_thread;
+}
+
+
+Isolate::PerIsolateThreadData*
+    Isolate::FindOrAllocatePerThreadDataForThisThread() {
+  ThreadId thread_id = Thread::GetThreadLocalInt(thread_id_key_);
+  if (thread_id == 0) {
+    thread_id = AllocateThreadId();
+    Thread::SetThreadLocalInt(thread_id_key_, thread_id);
+  }
+  PerIsolateThreadData* per_thread = NULL;
+  {
+    ScopedLock lock(process_wide_mutex_);
+    per_thread = thread_data_table_->Lookup(this, thread_id);
+    if (per_thread == NULL) {
+      per_thread = AllocatePerIsolateThreadData(thread_id);
+    }
+  }
+  return per_thread;
+}
+
+
+void Isolate::EnsureDefaultIsolate() {
+  ScopedLock lock(process_wide_mutex_);
+  if (default_isolate_ == NULL) {
+    isolate_key_ = Thread::CreateThreadLocalKey();
+    thread_id_key_ = Thread::CreateThreadLocalKey();
+    per_isolate_thread_data_key_ = Thread::CreateThreadLocalKey();
+    thread_data_table_ = new Isolate::ThreadDataTable();
+    default_isolate_ = new Isolate();
+  }
+  // Can't use SetIsolateThreadLocals(default_isolate_, NULL) here
+  // becase a non-null thread data may be already set.
+  Thread::SetThreadLocal(isolate_key_, default_isolate_);
+  CHECK(default_isolate_->PreInit());
+}
+
+
+Debugger* Isolate::GetDefaultIsolateDebugger() {
+  EnsureDefaultIsolate();
+  return default_isolate_->debugger();
+}
+
+
+StackGuard* Isolate::GetDefaultIsolateStackGuard() {
+  EnsureDefaultIsolate();
+  return default_isolate_->stack_guard();
+}
+
+
+void Isolate::EnterDefaultIsolate() {
+  EnsureDefaultIsolate();
+  ASSERT(default_isolate_ != NULL);
+
+  PerIsolateThreadData* data = CurrentPerIsolateThreadData();
+  // If not yet in default isolate - enter it.
+  if (data == NULL || data->isolate() != default_isolate_) {
+    default_isolate_->Enter();
+  }
+}
+
+
+Isolate* Isolate::GetDefaultIsolateForLocking() {
+  EnsureDefaultIsolate();
+  return default_isolate_;
+}
+
+
+Isolate::ThreadDataTable::ThreadDataTable()
+    : list_(NULL) {
+}
+
+
+Isolate::PerIsolateThreadData*
+    Isolate::ThreadDataTable::Lookup(Isolate* isolate, ThreadId thread_id) {
+  for (PerIsolateThreadData* data = list_; data != NULL; data = data->next_) {
+    if (data->Matches(isolate, thread_id)) return data;
+  }
+  return NULL;
+}
+
+
+void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) {
+  if (list_ != NULL) list_->prev_ = data;
+  data->next_ = list_;
+  list_ = data;
+}
+
+
+void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) {
+  if (list_ == data) list_ = data->next_;
+  if (data->next_ != NULL) data->next_->prev_ = data->prev_;
+  if (data->prev_ != NULL) data->prev_->next_ = data->next_;
+}
+
+
+void Isolate::ThreadDataTable::Remove(Isolate* isolate, ThreadId thread_id) {
+  PerIsolateThreadData* data = Lookup(isolate, thread_id);
+  if (data != NULL) {
+    Remove(data);
+  }
+}
+
+
+#ifdef DEBUG
+#define TRACE_ISOLATE(tag)                                              \
+  do {                                                                  \
+    if (FLAG_trace_isolates) {                                          \
+      PrintF("Isolate %p " #tag "\n", reinterpret_cast<void*>(this));   \
+    }                                                                   \
+  } while (false)
+#else
+#define TRACE_ISOLATE(tag)
+#endif
+
+
+Isolate::Isolate()
+    : state_(UNINITIALIZED),
+      entry_stack_(NULL),
+      stack_trace_nesting_level_(0),
+      incomplete_message_(NULL),
+      preallocated_memory_thread_(NULL),
+      preallocated_message_space_(NULL),
+      bootstrapper_(NULL),
+      runtime_profiler_(NULL),
+      compilation_cache_(NULL),
+      counters_(new Counters()),
+      cpu_features_(NULL),
+      code_range_(NULL),
+      break_access_(OS::CreateMutex()),
+      logger_(new Logger()),
+      stats_table_(new StatsTable()),
+      stub_cache_(NULL),
+      deoptimizer_data_(NULL),
+      capture_stack_trace_for_uncaught_exceptions_(false),
+      stack_trace_for_uncaught_exceptions_frame_limit_(0),
+      stack_trace_for_uncaught_exceptions_options_(StackTrace::kOverview),
+      transcendental_cache_(NULL),
+      memory_allocator_(NULL),
+      keyed_lookup_cache_(NULL),
+      context_slot_cache_(NULL),
+      descriptor_lookup_cache_(NULL),
+      handle_scope_implementer_(NULL),
+      scanner_constants_(NULL),
+      in_use_list_(0),
+      free_list_(0),
+      preallocated_storage_preallocated_(false),
+      pc_to_code_cache_(NULL),
+      write_input_buffer_(NULL),
+      global_handles_(NULL),
+      context_switcher_(NULL),
+      thread_manager_(NULL),
+      ast_sentinels_(NULL),
+      string_tracker_(NULL),
+      regexp_stack_(NULL),
+      frame_element_constant_list_(0),
+      result_constant_list_(0) {
+  TRACE_ISOLATE(constructor);
+
+  memset(isolate_addresses_, 0,
+      sizeof(isolate_addresses_[0]) * (k_isolate_address_count + 1));
+
+  heap_.isolate_ = this;
+  zone_.isolate_ = this;
+  stack_guard_.isolate_ = this;
+
+#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
+    defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
+  simulator_initialized_ = false;
+  simulator_i_cache_ = NULL;
+  simulator_redirection_ = NULL;
+#endif
+
+#ifdef DEBUG
+  // heap_histograms_ initializes itself.
+  memset(&js_spill_information_, 0, sizeof(js_spill_information_));
+  memset(code_kind_statistics_, 0,
+         sizeof(code_kind_statistics_[0]) * Code::NUMBER_OF_KINDS);
+#endif
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  debug_ = NULL;
+  debugger_ = NULL;
+#endif
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  producer_heap_profile_ = NULL;
+#endif
+
+  handle_scope_data_.Initialize();
+
+#define ISOLATE_INIT_EXECUTE(type, name, initial_value)                        \
+  name##_ = (initial_value);
+  ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE)
+#undef ISOLATE_INIT_EXECUTE
+
+#define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length)                         \
+  memset(name##_, 0, sizeof(type) * length);
+  ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE)
+#undef ISOLATE_INIT_ARRAY_EXECUTE
+}
+
+void Isolate::TearDown() {
+  TRACE_ISOLATE(tear_down);
+
+  // Temporarily set this isolate as current so that various parts of
+  // the isolate can access it in their destructors without having a
+  // direct pointer. We don't use Enter/Exit here to avoid
+  // initializing the thread data.
+  PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData();
+  Isolate* saved_isolate = UncheckedCurrent();
+  SetIsolateThreadLocals(this, NULL);
+
+  Deinit();
+
+  if (!IsDefaultIsolate()) {
+    delete this;
+  }
+
+  // Restore the previous current isolate.
+  SetIsolateThreadLocals(saved_isolate, saved_data);
+}
+
+
+void Isolate::Deinit() {
+  if (state_ == INITIALIZED) {
+    TRACE_ISOLATE(deinit);
+
+    if (FLAG_hydrogen_stats) HStatistics::Instance()->Print();
+
+    // We must stop the logger before we tear down other components.
+    logger_->EnsureTickerStopped();
+
+    delete deoptimizer_data_;
+    deoptimizer_data_ = NULL;
+    if (FLAG_preemption) {
+      v8::Locker locker;
+      v8::Locker::StopPreemption();
+    }
+    builtins_.TearDown();
+    bootstrapper_->TearDown();
+
+    // Remove the external reference to the preallocated stack memory.
+    delete preallocated_message_space_;
+    preallocated_message_space_ = NULL;
+    PreallocatedMemoryThreadStop();
+
+    HeapProfiler::TearDown();
+    CpuProfiler::TearDown();
+    if (runtime_profiler_ != NULL) {
+      runtime_profiler_->TearDown();
+      delete runtime_profiler_;
+      runtime_profiler_ = NULL;
+    }
+    heap_.TearDown();
+    logger_->TearDown();
+
+    // The default isolate is re-initializable due to legacy API.
+    state_ = PREINITIALIZED;
+  }
+}
+
+
+void Isolate::SetIsolateThreadLocals(Isolate* isolate,
+                                     PerIsolateThreadData* data) {
+  Thread::SetThreadLocal(isolate_key_, isolate);
+  Thread::SetThreadLocal(per_isolate_thread_data_key_, data);
+}
+
+
+Isolate::~Isolate() {
+  TRACE_ISOLATE(destructor);
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  delete producer_heap_profile_;
+  producer_heap_profile_ = NULL;
+#endif
+
+  delete scanner_constants_;
+  scanner_constants_ = NULL;
+
+  delete regexp_stack_;
+  regexp_stack_ = NULL;
+
+  delete ast_sentinels_;
+  ast_sentinels_ = NULL;
+
+  delete descriptor_lookup_cache_;
+  descriptor_lookup_cache_ = NULL;
+  delete context_slot_cache_;
+  context_slot_cache_ = NULL;
+  delete keyed_lookup_cache_;
+  keyed_lookup_cache_ = NULL;
+
+  delete transcendental_cache_;
+  transcendental_cache_ = NULL;
+  delete stub_cache_;
+  stub_cache_ = NULL;
+  delete stats_table_;
+  stats_table_ = NULL;
+
+  delete logger_;
+  logger_ = NULL;
+
+  delete counters_;
+  counters_ = NULL;
+  delete cpu_features_;
+  cpu_features_ = NULL;
+
+  delete handle_scope_implementer_;
+  handle_scope_implementer_ = NULL;
+  delete break_access_;
+  break_access_ = NULL;
+
+  delete compilation_cache_;
+  compilation_cache_ = NULL;
+  delete bootstrapper_;
+  bootstrapper_ = NULL;
+  delete pc_to_code_cache_;
+  pc_to_code_cache_ = NULL;
+  delete write_input_buffer_;
+  write_input_buffer_ = NULL;
+
+  delete context_switcher_;
+  context_switcher_ = NULL;
+  delete thread_manager_;
+  thread_manager_ = NULL;
+
+  delete string_tracker_;
+  string_tracker_ = NULL;
+
+  delete memory_allocator_;
+  memory_allocator_ = NULL;
+  delete code_range_;
+  code_range_ = NULL;
+  delete global_handles_;
+  global_handles_ = NULL;
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  delete debugger_;
+  debugger_ = NULL;
+  delete debug_;
+  debug_ = NULL;
+#endif
+}
+
+
+bool Isolate::PreInit() {
+  if (state_ != UNINITIALIZED) return true;
+
+  TRACE_ISOLATE(preinit);
+
+  ASSERT(Isolate::Current() == this);
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  debug_ = new Debug(this);
+  debugger_ = new Debugger();
+  debugger_->isolate_ = this;
+#endif
+
+  memory_allocator_ = new MemoryAllocator();
+  memory_allocator_->isolate_ = this;
+  code_range_ = new CodeRange();
+  code_range_->isolate_ = this;
+
+  // Safe after setting Heap::isolate_, initializing StackGuard and
+  // ensuring that Isolate::Current() == this.
+  heap_.SetStackLimits();
+
+#ifdef DEBUG
+  DisallowAllocationFailure disallow_allocation_failure;
+#endif
+
+#define C(name) isolate_addresses_[Isolate::k_##name] =                        \
+    reinterpret_cast<Address>(name());
+  ISOLATE_ADDRESS_LIST(C)
+  ISOLATE_ADDRESS_LIST_PROF(C)
+#undef C
+
+  string_tracker_ = new StringTracker();
+  string_tracker_->isolate_ = this;
+  thread_manager_ = new ThreadManager();
+  thread_manager_->isolate_ = this;
+  compilation_cache_ = new CompilationCache(this);
+  transcendental_cache_ = new TranscendentalCache();
+  keyed_lookup_cache_ = new KeyedLookupCache();
+  context_slot_cache_ = new ContextSlotCache();
+  descriptor_lookup_cache_ = new DescriptorLookupCache();
+  scanner_constants_ = new ScannerConstants();
+  pc_to_code_cache_ = new PcToCodeCache(this);
+  write_input_buffer_ = new StringInputBuffer();
+  global_handles_ = new GlobalHandles(this);
+  bootstrapper_ = new Bootstrapper();
+  cpu_features_ = new CpuFeatures();
+  handle_scope_implementer_ = new HandleScopeImplementer();
+  stub_cache_ = new StubCache(this);
+  ast_sentinels_ = new AstSentinels();
+  regexp_stack_ = new RegExpStack();
+  regexp_stack_->isolate_ = this;
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  producer_heap_profile_ = new ProducerHeapProfile();
+  producer_heap_profile_->isolate_ = this;
+#endif
+
+  state_ = PREINITIALIZED;
+  return true;
+}
+
+
+void Isolate::InitializeThreadLocal() {
+  thread_local_top_.Initialize();
+  clear_pending_exception();
+  clear_pending_message();
+  clear_scheduled_exception();
+}
+
+
+bool Isolate::Init(Deserializer* des) {
+  ASSERT(state_ != INITIALIZED);
+
+  TRACE_ISOLATE(init);
+
+  bool create_heap_objects = des == NULL;
+
+#ifdef DEBUG
+  // The initialization process does not handle memory exhaustion.
+  DisallowAllocationFailure disallow_allocation_failure;
+#endif
+
+  if (state_ == UNINITIALIZED && !PreInit()) return false;
+
+  // Enable logging before setting up the heap
+  logger_->Setup();
+
+  CpuProfiler::Setup();
+  HeapProfiler::Setup();
+
+  // Setup the platform OS support.
+  OS::Setup();
+
+  // Initialize other runtime facilities
+#if defined(USE_SIMULATOR)
+#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+  Simulator::Initialize();
+#endif
+#endif
+
+  { // NOLINT
+    // Ensure that the thread has a valid stack guard.  The v8::Locker object
+    // will ensure this too, but we don't have to use lockers if we are only
+    // using one thread.
+    ExecutionAccess lock(this);
+    stack_guard_.InitThread(lock);
+  }
+
+  // Setup the object heap
+  ASSERT(!heap_.HasBeenSetup());
+  if (!heap_.Setup(create_heap_objects)) {
+    V8::SetFatalError();
+    return false;
+  }
+
+  bootstrapper_->Initialize(create_heap_objects);
+  builtins_.Setup(create_heap_objects);
+
+  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.
+    PreallocatedMemoryThreadStart();
+    preallocated_message_space_ =
+        new NoAllocationStringAllocator(
+            preallocated_memory_thread_->data(),
+            preallocated_memory_thread_->length());
+    PreallocatedStorageInit(preallocated_memory_thread_->length() / 4);
+  }
+
+  if (FLAG_preemption) {
+    v8::Locker locker;
+    v8::Locker::StartPreemption(100);
+  }
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  debug_->Setup(create_heap_objects);
+#endif
+  stub_cache_->Initialize(create_heap_objects);
+
+  // If we are deserializing, read the state into the now-empty heap.
+  if (des != NULL) {
+    des->Deserialize();
+    stub_cache_->Clear();
+  }
+
+  // Deserializing may put strange things in the root array's copy of the
+  // stack guard.
+  heap_.SetStackLimits();
+
+  // 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();
+
+  deoptimizer_data_ = new DeoptimizerData;
+  runtime_profiler_ = new RuntimeProfiler(this);
+  runtime_profiler_->Setup();
+
+  // If we are deserializing, log non-function code objects and compiled
+  // functions found in the snapshot.
+  if (des != NULL && FLAG_log_code) {
+    HandleScope scope;
+    LOG(this, LogCodeObjects());
+    LOG(this, LogCompiledFunctions());
+  }
+
+  state_ = INITIALIZED;
+  return true;
+}
+
+
+void Isolate::Enter() {
+  Isolate* current_isolate = NULL;
+  PerIsolateThreadData* current_data = CurrentPerIsolateThreadData();
+  if (current_data != NULL) {
+    current_isolate = current_data->isolate_;
+    ASSERT(current_isolate != NULL);
+    if (current_isolate == this) {
+      ASSERT(Current() == this);
+      ASSERT(entry_stack_ != NULL);
+      ASSERT(entry_stack_->previous_thread_data == NULL ||
+             entry_stack_->previous_thread_data->thread_id() ==
+                 Thread::GetThreadLocalInt(thread_id_key_));
+      // Same thread re-enters the isolate, no need to re-init anything.
+      entry_stack_->entry_count++;
+      return;
+    }
+  }
+
+  // Threads can have default isolate set into TLS as Current but not yet have
+  // PerIsolateThreadData for it, as it requires more advanced phase of the
+  // initialization. For example, a thread might be the one that system used for
+  // static initializers - in this case the default isolate is set in TLS but
+  // the thread did not yet Enter the isolate. If PerisolateThreadData is not
+  // there, use the isolate set in TLS.
+  if (current_isolate == NULL) {
+    current_isolate = Isolate::UncheckedCurrent();
+  }
+
+  PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread();
+  ASSERT(data != NULL);
+  ASSERT(data->isolate_ == this);
+
+  EntryStackItem* item = new EntryStackItem(current_data,
+                                            current_isolate,
+                                            entry_stack_);
+  entry_stack_ = item;
+
+  SetIsolateThreadLocals(this, data);
+
+  CHECK(PreInit());
+
+  // In case it's the first time some thread enters the isolate.
+  set_thread_id(data->thread_id());
+}
+
+
+void Isolate::Exit() {
+  ASSERT(entry_stack_ != NULL);
+  ASSERT(entry_stack_->previous_thread_data == NULL ||
+         entry_stack_->previous_thread_data->thread_id() ==
+             Thread::GetThreadLocalInt(thread_id_key_));
+
+  if (--entry_stack_->entry_count > 0) return;
+
+  ASSERT(CurrentPerIsolateThreadData() != NULL);
+  ASSERT(CurrentPerIsolateThreadData()->isolate_ == this);
+
+  // Pop the stack.
+  EntryStackItem* item = entry_stack_;
+  entry_stack_ = item->previous_item;
+
+  PerIsolateThreadData* previous_thread_data = item->previous_thread_data;
+  Isolate* previous_isolate = item->previous_isolate;
+
+  delete item;
+
+  // Reinit the current thread for the isolate it was running before this one.
+  SetIsolateThreadLocals(previous_isolate, previous_thread_data);
+}
+
+
+void Isolate::ResetEagerOptimizingData() {
+  compilation_cache_->ResetEagerOptimizingData();
+}
+
+
+#ifdef DEBUG
+#define ISOLATE_FIELD_OFFSET(type, name, ignored)                       \
+const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_);
+ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
+ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
+#undef ISOLATE_FIELD_OFFSET
+#endif
+
+} }  // namespace v8::internal
diff --git a/src/isolate.h b/src/isolate.h
new file mode 100644
index 0000000..03a4866
--- /dev/null
+++ b/src/isolate.h
@@ -0,0 +1,1308 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_ISOLATE_H_
+#define V8_ISOLATE_H_
+
+#include "../include/v8-debug.h"
+#include "allocation.h"
+#include "apiutils.h"
+#include "atomicops.h"
+#include "builtins.h"
+#include "contexts.h"
+#include "execution.h"
+#include "frames.h"
+#include "global-handles.h"
+#include "handles.h"
+#include "heap.h"
+#include "regexp-stack.h"
+#include "runtime-profiler.h"
+#include "runtime.h"
+#include "zone.h"
+
+namespace v8 {
+namespace internal {
+
+class AstSentinels;
+class Bootstrapper;
+class CodeGenerator;
+class CodeRange;
+class CompilationCache;
+class ContextSlotCache;
+class ContextSwitcher;
+class Counters;
+class CpuFeatures;
+class CpuProfiler;
+class DeoptimizerData;
+class Deserializer;
+class EmptyStatement;
+class ExternalReferenceTable;
+class Factory;
+class FunctionInfoListener;
+class HandleScopeImplementer;
+class HeapProfiler;
+class InlineRuntimeFunctionsTable;
+class NoAllocationStringAllocator;
+class PcToCodeCache;
+class PreallocatedMemoryThread;
+class ProducerHeapProfile;
+class RegExpStack;
+class SaveContext;
+class ScannerConstants;
+class StringInputBuffer;
+class StringTracker;
+class StubCache;
+class ThreadManager;
+class ThreadState;
+class ThreadVisitor;  // Defined in v8threads.h
+class VMState;
+
+// 'void function pointer', used to roundtrip the
+// ExternalReference::ExternalReferenceRedirector since we can not include
+// assembler.h, where it is defined, here.
+typedef void* ExternalReferenceRedirectorPointer();
+
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+class Debug;
+class Debugger;
+class DebuggerAgent;
+#endif
+
+#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
+    !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
+class Redirection;
+class Simulator;
+#endif
+
+
+// Static indirection table for handles to constants.  If a frame
+// element represents a constant, the data contains an index into
+// this table of handles to the actual constants.
+// Static indirection table for handles to constants.  If a Result
+// represents a constant, the data contains an index into this table
+// of handles to the actual constants.
+typedef ZoneList<Handle<Object> > ZoneObjectList;
+
+#define RETURN_IF_SCHEDULED_EXCEPTION(isolate)    \
+  if (isolate->has_scheduled_exception())         \
+      return isolate->PromoteScheduledException()
+
+#define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value) \
+  if (call.is_null()) {                                    \
+    ASSERT(isolate->has_pending_exception());              \
+    return value;                                          \
+  }
+
+#define RETURN_IF_EMPTY_HANDLE(isolate, call)                       \
+  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, Failure::Exception())
+
+#define ISOLATE_ADDRESS_LIST(C)            \
+  C(handler_address)                       \
+  C(c_entry_fp_address)                    \
+  C(context_address)                       \
+  C(pending_exception_address)             \
+  C(external_caught_exception_address)
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+#define ISOLATE_ADDRESS_LIST_PROF(C)       \
+  C(js_entry_sp_address)
+#else
+#define ISOLATE_ADDRESS_LIST_PROF(C)
+#endif
+
+
+class ThreadLocalTop BASE_EMBEDDED {
+ public:
+  // Initialize the thread data.
+  void Initialize();
+
+  // Get the top C++ try catch handler or NULL if none are registered.
+  //
+  // This method is not guarenteed to return an address that can be
+  // used for comparison with addresses into the JS stack.  If such an
+  // address is needed, use try_catch_handler_address.
+  v8::TryCatch* TryCatchHandler();
+
+  // Get the address of the top C++ try catch handler or NULL if
+  // none are registered.
+  //
+  // This method always returns an address that can be compared to
+  // pointers into the JavaScript stack.  When running on actual
+  // hardware, try_catch_handler_address and TryCatchHandler return
+  // the same pointer.  When running on a simulator with a separate JS
+  // stack, try_catch_handler_address returns a JS stack address that
+  // corresponds to the place on the JS stack where the C++ handler
+  // would have been if the stack were not separate.
+  inline Address try_catch_handler_address() {
+    return try_catch_handler_address_;
+  }
+
+  // Set the address of the top C++ try catch handler.
+  inline void set_try_catch_handler_address(Address address) {
+    try_catch_handler_address_ = address;
+  }
+
+  void Free() {
+    ASSERT(!has_pending_message_);
+    ASSERT(!external_caught_exception_);
+    ASSERT(try_catch_handler_address_ == NULL);
+  }
+
+  // The context where the current execution method is created and for variable
+  // lookups.
+  Context* context_;
+  int thread_id_;
+  MaybeObject* 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.
+  MaybeObject* scheduled_exception_;
+  bool external_caught_exception_;
+  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
+
+#ifdef USE_SIMULATOR
+#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+  Simulator* simulator_;
+#endif
+#endif  // USE_SIMULATOR
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  Address js_entry_sp_;  // the stack pointer of the bottom js entry frame
+  Address external_callback_;  // the external callback we're currently in
+#endif
+
+#ifdef ENABLE_VMSTATE_TRACKING
+  StateTag current_vm_state_;
+#endif
+
+  // Generated code scratch locations.
+  int32_t formal_count_;
+
+  // Call back function to report unsafe JS accesses.
+  v8::FailedAccessCheckCallback failed_access_check_callback_;
+
+ private:
+  Address try_catch_handler_address_;
+};
+
+#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+
+#define ISOLATE_PLATFORM_INIT_LIST(V)                                          \
+  /* VirtualFrame::SpilledScope state */                                       \
+  V(bool, is_virtual_frame_in_spilled_scope, false)                            \
+  /* CodeGenerator::EmitNamedStore state */                                    \
+  V(int, inlined_write_barrier_size, -1)
+
+#if !defined(__arm__) && !defined(__mips__)
+class HashMap;
+#endif
+
+#else
+
+#define ISOLATE_PLATFORM_INIT_LIST(V)
+
+#endif
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+
+#define ISOLATE_DEBUGGER_INIT_LIST(V)                                          \
+  V(v8::Debug::EventCallback, debug_event_callback, NULL)                      \
+  V(DebuggerAgent*, debugger_agent_instance, NULL)
+#else
+
+#define ISOLATE_DEBUGGER_INIT_LIST(V)
+
+#endif
+
+#ifdef DEBUG
+
+#define ISOLATE_INIT_DEBUG_ARRAY_LIST(V)                                       \
+  V(CommentStatistic, paged_space_comments_statistics,                         \
+      CommentStatistic::kMaxComments + 1)
+#else
+
+#define ISOLATE_INIT_DEBUG_ARRAY_LIST(V)
+
+#endif
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+#define ISOLATE_LOGGING_INIT_LIST(V)                                           \
+  V(CpuProfiler*, cpu_profiler, NULL)                                          \
+  V(HeapProfiler*, heap_profiler, NULL)
+
+#else
+
+#define ISOLATE_LOGGING_INIT_LIST(V)
+
+#endif
+
+#define ISOLATE_INIT_ARRAY_LIST(V)                                             \
+  /* SerializerDeserializer state. */                                          \
+  V(Object*, serialize_partial_snapshot_cache, kPartialSnapshotCacheCapacity)  \
+  V(int, jsregexp_static_offsets_vector, kJSRegexpStaticOffsetsVectorSize)     \
+  V(int, bad_char_shift_table, kUC16AlphabetSize)                              \
+  V(int, good_suffix_shift_table, (kBMMaxShift + 1))                           \
+  V(int, suffix_table, (kBMMaxShift + 1))                                      \
+  ISOLATE_INIT_DEBUG_ARRAY_LIST(V)
+
+typedef List<HeapObject*, PreallocatedStorage> DebugObjectCache;
+
+#define ISOLATE_INIT_LIST(V)                                                   \
+  /* AssertNoZoneAllocation state. */                                          \
+  V(bool, zone_allow_allocation, true)                                         \
+  /* SerializerDeserializer state. */                                          \
+  V(int, serialize_partial_snapshot_cache_length, 0)                           \
+  /* Assembler state. */                                                       \
+  /* A previously allocated buffer of kMinimalBufferSize bytes, or NULL. */    \
+  V(byte*, assembler_spare_buffer, NULL)                                       \
+  V(FatalErrorCallback, exception_behavior, NULL)                              \
+  V(v8::Debug::MessageHandler, message_handler, NULL)                          \
+  /* To distinguish the function templates, so that we can find them in the */ \
+  /* function cache of the global context. */                                  \
+  V(int, next_serial_number, 0)                                                \
+  V(ExternalReferenceRedirectorPointer*, external_reference_redirector, NULL)  \
+  V(bool, always_allow_natives_syntax, false)                                  \
+  /* Part of the state of liveedit. */                                         \
+  V(FunctionInfoListener*, active_function_info_listener, NULL)                \
+  /* State for Relocatable. */                                                 \
+  V(Relocatable*, relocatable_top, NULL)                                       \
+  /* State for CodeEntry in profile-generator. */                              \
+  V(CodeGenerator*, current_code_generator, NULL)                              \
+  V(bool, jump_target_compiling_deferred_code, false)                          \
+  V(DebugObjectCache*, string_stream_debug_object_cache, NULL)                 \
+  V(Object*, string_stream_current_security_token, NULL)                       \
+  /* TODO(isolates): Release this on destruction? */                           \
+  V(int*, irregexp_interpreter_backtrack_stack_cache, NULL)                    \
+  /* Serializer state. */                                                      \
+  V(ExternalReferenceTable*, external_reference_table, NULL)                   \
+  /* AstNode state. */                                                         \
+  V(unsigned, ast_node_id, 0)                                                  \
+  V(unsigned, ast_node_count, 0)                                               \
+  ISOLATE_PLATFORM_INIT_LIST(V)                                                \
+  ISOLATE_LOGGING_INIT_LIST(V)                                                 \
+  ISOLATE_DEBUGGER_INIT_LIST(V)
+
+class Isolate {
+  // These forward declarations are required to make the friend declarations in
+  // PerIsolateThreadData work on some older versions of gcc.
+  class ThreadDataTable;
+  class EntryStackItem;
+ public:
+  ~Isolate();
+
+  typedef int ThreadId;
+
+  // A thread has a PerIsolateThreadData instance for each isolate that it has
+  // entered. That instance is allocated when the isolate is initially entered
+  // and reused on subsequent entries.
+  class PerIsolateThreadData {
+   public:
+    PerIsolateThreadData(Isolate* isolate, ThreadId thread_id)
+        : isolate_(isolate),
+          thread_id_(thread_id),
+          stack_limit_(0),
+          thread_state_(NULL),
+#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
+    !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
+          simulator_(NULL),
+#endif
+          next_(NULL),
+          prev_(NULL) { }
+    Isolate* isolate() const { return isolate_; }
+    ThreadId thread_id() const { return thread_id_; }
+    void set_stack_limit(uintptr_t value) { stack_limit_ = value; }
+    uintptr_t stack_limit() const { return stack_limit_; }
+    ThreadState* thread_state() const { return thread_state_; }
+    void set_thread_state(ThreadState* value) { thread_state_ = value; }
+
+#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
+    !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
+    Simulator* simulator() const { return simulator_; }
+    void set_simulator(Simulator* simulator) {
+      simulator_ = simulator;
+    }
+#endif
+
+    bool Matches(Isolate* isolate, ThreadId thread_id) const {
+      return isolate_ == isolate && thread_id_ == thread_id;
+    }
+
+   private:
+    Isolate* isolate_;
+    ThreadId thread_id_;
+    uintptr_t stack_limit_;
+    ThreadState* thread_state_;
+
+#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
+    !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
+    Simulator* simulator_;
+#endif
+
+    PerIsolateThreadData* next_;
+    PerIsolateThreadData* prev_;
+
+    friend class Isolate;
+    friend class ThreadDataTable;
+    friend class EntryStackItem;
+
+    DISALLOW_COPY_AND_ASSIGN(PerIsolateThreadData);
+  };
+
+
+  enum AddressId {
+#define C(name) k_##name,
+    ISOLATE_ADDRESS_LIST(C)
+    ISOLATE_ADDRESS_LIST_PROF(C)
+#undef C
+    k_isolate_address_count
+  };
+
+  // Returns the PerIsolateThreadData for the current thread (or NULL if one is
+  // not currently set).
+  static PerIsolateThreadData* CurrentPerIsolateThreadData() {
+    return reinterpret_cast<PerIsolateThreadData*>(
+        Thread::GetThreadLocal(per_isolate_thread_data_key_));
+  }
+
+  // Returns the isolate inside which the current thread is running.
+  INLINE(static Isolate* Current()) {
+    Isolate* isolate = reinterpret_cast<Isolate*>(
+        Thread::GetExistingThreadLocal(isolate_key_));
+    ASSERT(isolate != NULL);
+    return isolate;
+  }
+
+  INLINE(static Isolate* UncheckedCurrent()) {
+    return reinterpret_cast<Isolate*>(Thread::GetThreadLocal(isolate_key_));
+  }
+
+  bool Init(Deserializer* des);
+
+  bool IsInitialized() { return state_ == INITIALIZED; }
+
+  // True if at least one thread Enter'ed this isolate.
+  bool IsInUse() { return entry_stack_ != NULL; }
+
+  // Destroys the non-default isolates.
+  // Sets default isolate into "has_been_disposed" state rather then destroying,
+  // for legacy API reasons.
+  void TearDown();
+
+  bool IsDefaultIsolate() const { return this == default_isolate_; }
+
+  // Ensures that process-wide resources and the default isolate have been
+  // allocated. It is only necessary to call this method in rare casses, for
+  // example if you are using V8 from within the body of a static initializer.
+  // Safe to call multiple times.
+  static void EnsureDefaultIsolate();
+
+  // Get the debugger from the default isolate. Preinitializes the
+  // default isolate if needed.
+  static Debugger* GetDefaultIsolateDebugger();
+
+  // Get the stack guard from the default isolate. Preinitializes the
+  // default isolate if needed.
+  static StackGuard* GetDefaultIsolateStackGuard();
+
+  // Returns the key used to store the pointer to the current isolate.
+  // Used internally for V8 threads that do not execute JavaScript but still
+  // are part of the domain of an isolate (like the context switcher).
+  static Thread::LocalStorageKey isolate_key() {
+    return isolate_key_;
+  }
+
+  // Returns the key used to store process-wide thread IDs.
+  static Thread::LocalStorageKey thread_id_key() {
+    return thread_id_key_;
+  }
+
+  // Atomically allocates a new thread ID.
+  static ThreadId AllocateThreadId();
+
+  // If a client attempts to create a Locker without specifying an isolate,
+  // we assume that the client is using legacy behavior. Set up the current
+  // thread to be inside the implicit isolate (or fail a check if we have
+  // switched to non-legacy behavior).
+  static void EnterDefaultIsolate();
+
+  // Debug.
+  // Mutex for serializing access to break control structures.
+  Mutex* break_access() { return break_access_; }
+
+  Address get_address_from_id(AddressId id);
+
+  // Access to top context (where the current function object was created).
+  Context* context() { return thread_local_top_.context_; }
+  void set_context(Context* context) {
+    thread_local_top_.context_ = context;
+  }
+  Context** context_address() { return &thread_local_top_.context_; }
+
+  SaveContext* save_context() {return thread_local_top_.save_context_; }
+  void set_save_context(SaveContext* save) {
+    thread_local_top_.save_context_ = save;
+  }
+
+  // Access to current thread id.
+  int thread_id() { return thread_local_top_.thread_id_; }
+  void set_thread_id(int id) { thread_local_top_.thread_id_ = id; }
+
+  // Interface to pending exception.
+  MaybeObject* pending_exception() {
+    ASSERT(has_pending_exception());
+    return thread_local_top_.pending_exception_;
+  }
+  bool external_caught_exception() {
+    return thread_local_top_.external_caught_exception_;
+  }
+  void set_pending_exception(MaybeObject* exception) {
+    thread_local_top_.pending_exception_ = exception;
+  }
+  void clear_pending_exception() {
+    thread_local_top_.pending_exception_ = heap_.the_hole_value();
+  }
+  MaybeObject** pending_exception_address() {
+    return &thread_local_top_.pending_exception_;
+  }
+  bool has_pending_exception() {
+    return !thread_local_top_.pending_exception_->IsTheHole();
+  }
+  void clear_pending_message() {
+    thread_local_top_.has_pending_message_ = false;
+    thread_local_top_.pending_message_ = NULL;
+    thread_local_top_.pending_message_obj_ = heap_.the_hole_value();
+    thread_local_top_.pending_message_script_ = NULL;
+  }
+  v8::TryCatch* try_catch_handler() {
+    return thread_local_top_.TryCatchHandler();
+  }
+  Address try_catch_handler_address() {
+    return thread_local_top_.try_catch_handler_address();
+  }
+  bool* external_caught_exception_address() {
+    return &thread_local_top_.external_caught_exception_;
+  }
+
+  MaybeObject** scheduled_exception_address() {
+    return &thread_local_top_.scheduled_exception_;
+  }
+  MaybeObject* scheduled_exception() {
+    ASSERT(has_scheduled_exception());
+    return thread_local_top_.scheduled_exception_;
+  }
+  bool has_scheduled_exception() {
+    return !thread_local_top_.scheduled_exception_->IsTheHole();
+  }
+  void clear_scheduled_exception() {
+    thread_local_top_.scheduled_exception_ = heap_.the_hole_value();
+  }
+
+  bool IsExternallyCaught();
+
+  bool is_catchable_by_javascript(MaybeObject* exception) {
+    return (exception != Failure::OutOfMemoryException()) &&
+        (exception != heap()->termination_exception());
+  }
+
+  // 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_; }
+
+  inline Address* c_entry_fp_address() {
+    return &thread_local_top_.c_entry_fp_;
+  }
+  inline Address* handler_address() { return &thread_local_top_.handler_; }
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  // Bottom JS entry (see StackTracer::Trace in log.cc).
+  static Address js_entry_sp(ThreadLocalTop* thread) {
+    return thread->js_entry_sp_;
+  }
+  inline Address* js_entry_sp_address() {
+    return &thread_local_top_.js_entry_sp_;
+  }
+#endif
+
+  // Generated code scratch locations.
+  void* formal_count_address() { return &thread_local_top_.formal_count_; }
+
+  // Returns the global object of the current context. It could be
+  // a builtin object, or a js global object.
+  Handle<GlobalObject> global() {
+    return Handle<GlobalObject>(context()->global());
+  }
+
+  // Returns the global proxy object of the current context.
+  Object* global_proxy() {
+    return context()->global_proxy();
+  }
+
+  Handle<JSBuiltinsObject> js_builtins_object() {
+    return Handle<JSBuiltinsObject>(thread_local_top_.context_->builtins());
+  }
+
+  static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); }
+  void FreeThreadResources() { thread_local_top_.Free(); }
+
+  // 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.
+  bool OptionalRescheduleException(bool is_bottom_call);
+
+  void SetCaptureStackTraceForUncaughtExceptions(
+      bool capture,
+      int frame_limit,
+      StackTrace::StackTraceOptions options);
+
+  // Tells whether the current context has experienced an out of memory
+  // exception.
+  bool is_out_of_memory();
+
+  void PrintCurrentStackTrace(FILE* out);
+  void PrintStackTrace(FILE* out, char* thread_data);
+  void PrintStack(StringStream* accumulator);
+  void PrintStack();
+  Handle<String> StackTraceString();
+  Handle<JSArray> CaptureCurrentStackTrace(
+      int frame_limit,
+      StackTrace::StackTraceOptions options);
+
+  // Returns if the top context may access the given global object. If
+  // the result is false, the pending exception is guaranteed to be
+  // set.
+  bool MayNamedAccess(JSObject* receiver,
+                      Object* key,
+                      v8::AccessType type);
+  bool MayIndexedAccess(JSObject* receiver,
+                        uint32_t index,
+                        v8::AccessType type);
+
+  void SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback);
+  void ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type);
+
+  // Exception throwing support. The caller should use the result
+  // of Throw() as its return value.
+  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.
+  Failure* ReThrow(MaybeObject* exception, MessageLocation* location = NULL);
+  void ScheduleThrow(Object* exception);
+  void ReportPendingMessages();
+  Failure* ThrowIllegalOperation();
+
+  // Promote a scheduled exception to pending. Asserts has_scheduled_exception.
+  Failure* PromoteScheduledException();
+  void DoThrow(MaybeObject* exception,
+               MessageLocation* location,
+               const char* message);
+  // Checks if exception should be reported and finds out if it's
+  // caught externally.
+  bool ShouldReportException(bool* can_be_caught_externally,
+                             bool catchable_by_javascript);
+
+  // Attempts to compute the current source location, storing the
+  // result in the target out parameter.
+  void ComputeLocation(MessageLocation* target);
+
+  // Override command line flag.
+  void TraceException(bool flag);
+
+  // Out of resource exception helpers.
+  Failure* StackOverflow();
+  Failure* TerminateExecution();
+
+  // Administration
+  void Iterate(ObjectVisitor* v);
+  void Iterate(ObjectVisitor* v, ThreadLocalTop* t);
+  char* Iterate(ObjectVisitor* v, char* t);
+  void IterateThread(ThreadVisitor* v);
+  void IterateThread(ThreadVisitor* v, char* t);
+
+
+  // Returns the current global context.
+  Handle<Context> global_context();
+
+  // Returns the global context of the calling JavaScript code.  That
+  // is, the global context of the top-most JavaScript frame.
+  Handle<Context> GetCallingGlobalContext();
+
+  void RegisterTryCatchHandler(v8::TryCatch* that);
+  void UnregisterTryCatchHandler(v8::TryCatch* that);
+
+  char* ArchiveThread(char* to);
+  char* RestoreThread(char* from);
+
+  static const char* const kStackOverflowMessage;
+
+  static const int kUC16AlphabetSize = 256;  // See StringSearchBase.
+  static const int kBMMaxShift = 250;        // See StringSearchBase.
+
+  // Accessors.
+#define GLOBAL_ACCESSOR(type, name, initialvalue)                       \
+  inline type name() const {                                            \
+    ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_);        \
+    return name##_;                                                     \
+  }                                                                     \
+  inline void set_##name(type value) {                                  \
+    ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_);        \
+    name##_ = value;                                                    \
+  }
+  ISOLATE_INIT_LIST(GLOBAL_ACCESSOR)
+#undef GLOBAL_ACCESSOR
+
+#define GLOBAL_ARRAY_ACCESSOR(type, name, length)                       \
+  inline type* name() {                                                 \
+    ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_);        \
+    return &(name##_)[0];                                               \
+  }
+  ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_ACCESSOR)
+#undef GLOBAL_ARRAY_ACCESSOR
+
+#define GLOBAL_CONTEXT_FIELD_ACCESSOR(index, type, name)      \
+  Handle<type> name() {                                       \
+    return Handle<type>(context()->global_context()->name()); \
+  }
+  GLOBAL_CONTEXT_FIELDS(GLOBAL_CONTEXT_FIELD_ACCESSOR)
+#undef GLOBAL_CONTEXT_FIELD_ACCESSOR
+
+  Bootstrapper* bootstrapper() { return bootstrapper_; }
+  Counters* counters() { return counters_; }
+  // TODO(isolates): Having CPU features per isolate is probably too
+  // flexible. We only really need to have the set of currently
+  // enabled features for asserts in DEBUG builds.
+  CpuFeatures* cpu_features() { return cpu_features_; }
+  CodeRange* code_range() { return code_range_; }
+  RuntimeProfiler* runtime_profiler() { return runtime_profiler_; }
+  CompilationCache* compilation_cache() { return compilation_cache_; }
+  Logger* logger() { return logger_; }
+  StackGuard* stack_guard() { return &stack_guard_; }
+  Heap* heap() { return &heap_; }
+  StatsTable* stats_table() { return stats_table_; }
+  StubCache* stub_cache() { return stub_cache_; }
+  DeoptimizerData* deoptimizer_data() { return deoptimizer_data_; }
+  ThreadLocalTop* thread_local_top() { return &thread_local_top_; }
+
+  TranscendentalCache* transcendental_cache() const {
+    return transcendental_cache_;
+  }
+
+  MemoryAllocator* memory_allocator() {
+    return memory_allocator_;
+  }
+
+  KeyedLookupCache* keyed_lookup_cache() {
+    return keyed_lookup_cache_;
+  }
+
+  ContextSlotCache* context_slot_cache() {
+    return context_slot_cache_;
+  }
+
+  DescriptorLookupCache* descriptor_lookup_cache() {
+    return descriptor_lookup_cache_;
+  }
+
+  v8::ImplementationUtilities::HandleScopeData* handle_scope_data() {
+    return &handle_scope_data_;
+  }
+  HandleScopeImplementer* handle_scope_implementer() {
+    ASSERT(handle_scope_implementer_);
+    return handle_scope_implementer_;
+  }
+  Zone* zone() { return &zone_; }
+
+  ScannerConstants* scanner_constants() {
+    return scanner_constants_;
+  }
+
+  PcToCodeCache* pc_to_code_cache() { return pc_to_code_cache_; }
+
+  StringInputBuffer* write_input_buffer() { return write_input_buffer_; }
+
+  GlobalHandles* global_handles() { return global_handles_; }
+
+  ThreadManager* thread_manager() { return thread_manager_; }
+
+  ContextSwitcher* context_switcher() { return context_switcher_; }
+
+  void set_context_switcher(ContextSwitcher* switcher) {
+    context_switcher_ = switcher;
+  }
+
+  StringTracker* string_tracker() { return string_tracker_; }
+
+  unibrow::Mapping<unibrow::Ecma262UnCanonicalize>* jsregexp_uncanonicalize() {
+    return &jsregexp_uncanonicalize_;
+  }
+
+  unibrow::Mapping<unibrow::CanonicalizationRange>* jsregexp_canonrange() {
+    return &jsregexp_canonrange_;
+  }
+
+  StringInputBuffer* objects_string_compare_buffer_a() {
+    return &objects_string_compare_buffer_a_;
+  }
+
+  StringInputBuffer* objects_string_compare_buffer_b() {
+    return &objects_string_compare_buffer_b_;
+  }
+
+  StaticResource<StringInputBuffer>* objects_string_input_buffer() {
+    return &objects_string_input_buffer_;
+  }
+
+  AstSentinels* ast_sentinels() { return ast_sentinels_; }
+
+  RuntimeState* runtime_state() { return &runtime_state_; }
+
+  StringInputBuffer* liveedit_compare_substrings_buf1() {
+    return &liveedit_compare_substrings_buf1_;
+  }
+
+  StringInputBuffer* liveedit_compare_substrings_buf2() {
+    return &liveedit_compare_substrings_buf2_;
+  }
+
+  StaticResource<SafeStringInputBuffer>* compiler_safe_string_input_buffer() {
+    return &compiler_safe_string_input_buffer_;
+  }
+
+  Builtins* builtins() { return &builtins_; }
+
+  unibrow::Mapping<unibrow::Ecma262Canonicalize>*
+      regexp_macro_assembler_canonicalize() {
+    return &regexp_macro_assembler_canonicalize_;
+  }
+
+  RegExpStack* regexp_stack() { return regexp_stack_; }
+
+  unibrow::Mapping<unibrow::Ecma262Canonicalize>*
+      interp_canonicalize_mapping() {
+    return &interp_canonicalize_mapping_;
+  }
+
+  ZoneObjectList* frame_element_constant_list() {
+    return &frame_element_constant_list_;
+  }
+
+  ZoneObjectList* result_constant_list() {
+    return &result_constant_list_;
+  }
+
+  void* PreallocatedStorageNew(size_t size);
+  void PreallocatedStorageDelete(void* p);
+  void PreallocatedStorageInit(size_t size);
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  Debugger* debugger() { return debugger_; }
+  Debug* debug() { return debug_; }
+#endif
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  ProducerHeapProfile* producer_heap_profile() {
+    return producer_heap_profile_;
+  }
+#endif
+
+#ifdef DEBUG
+  HistogramInfo* heap_histograms() { return heap_histograms_; }
+
+  JSObject::SpillInformation* js_spill_information() {
+    return &js_spill_information_;
+  }
+
+  int* code_kind_statistics() { return code_kind_statistics_; }
+#endif
+
+#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
+    defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
+  bool simulator_initialized() { return simulator_initialized_; }
+  void set_simulator_initialized(bool initialized) {
+    simulator_initialized_ = initialized;
+  }
+
+  HashMap* simulator_i_cache() { return simulator_i_cache_; }
+  void set_simulator_i_cache(HashMap* hash_map) {
+    simulator_i_cache_ = hash_map;
+  }
+
+  Redirection* simulator_redirection() {
+    return simulator_redirection_;
+  }
+  void set_simulator_redirection(Redirection* redirection) {
+    simulator_redirection_ = redirection;
+  }
+#endif
+
+  Factory* factory() { return reinterpret_cast<Factory*>(this); }
+
+  // SerializerDeserializer state.
+  static const int kPartialSnapshotCacheCapacity = 1400;
+
+  static const int kJSRegexpStaticOffsetsVectorSize = 50;
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  Address external_callback() {
+    return thread_local_top_.external_callback_;
+  }
+  void set_external_callback(Address callback) {
+    thread_local_top_.external_callback_ = callback;
+  }
+#endif
+
+#ifdef ENABLE_VMSTATE_TRACKING
+  StateTag current_vm_state() {
+    return thread_local_top_.current_vm_state_;
+  }
+
+  void SetCurrentVMState(StateTag state) {
+    if (RuntimeProfiler::IsEnabled()) {
+      if (state == JS) {
+        // JS or non-JS -> JS transition.
+        RuntimeProfiler::IsolateEnteredJS(this);
+      } else if (thread_local_top_.current_vm_state_ == JS) {
+        // JS -> non-JS transition.
+        ASSERT(RuntimeProfiler::IsSomeIsolateInJS());
+        RuntimeProfiler::IsolateExitedJS(this);
+      }
+    }
+    thread_local_top_.current_vm_state_ = state;
+  }
+#endif
+
+  void ResetEagerOptimizingData();
+
+ private:
+  Isolate();
+
+  // The per-process lock should be acquired before the ThreadDataTable is
+  // modified.
+  class ThreadDataTable {
+   public:
+    ThreadDataTable();
+    ~ThreadDataTable();
+
+    PerIsolateThreadData* Lookup(Isolate* isolate, ThreadId thread_id);
+    void Insert(PerIsolateThreadData* data);
+    void Remove(Isolate* isolate, ThreadId thread_id);
+    void Remove(PerIsolateThreadData* data);
+
+   private:
+    PerIsolateThreadData* list_;
+  };
+
+  // These items form a stack synchronously with threads Enter'ing and Exit'ing
+  // the Isolate. The top of the stack points to a thread which is currently
+  // running the Isolate. When the stack is empty, the Isolate is considered
+  // not entered by any thread and can be Disposed.
+  // If the same thread enters the Isolate more then once, the entry_count_
+  // is incremented rather then a new item pushed to the stack.
+  class EntryStackItem {
+   public:
+    EntryStackItem(PerIsolateThreadData* previous_thread_data,
+                   Isolate* previous_isolate,
+                   EntryStackItem* previous_item)
+        : entry_count(1),
+          previous_thread_data(previous_thread_data),
+          previous_isolate(previous_isolate),
+          previous_item(previous_item) { }
+
+    int entry_count;
+    PerIsolateThreadData* previous_thread_data;
+    Isolate* previous_isolate;
+    EntryStackItem* previous_item;
+
+    DISALLOW_COPY_AND_ASSIGN(EntryStackItem);
+  };
+
+  // This mutex protects highest_thread_id_, thread_data_table_ and
+  // default_isolate_.
+  static Mutex* process_wide_mutex_;
+
+  static Thread::LocalStorageKey per_isolate_thread_data_key_;
+  static Thread::LocalStorageKey isolate_key_;
+  static Thread::LocalStorageKey thread_id_key_;
+  static Isolate* default_isolate_;
+  static ThreadDataTable* thread_data_table_;
+  static ThreadId highest_thread_id_;
+
+  bool PreInit();
+
+  void Deinit();
+
+  static void SetIsolateThreadLocals(Isolate* isolate,
+                                     PerIsolateThreadData* data);
+
+  enum State {
+    UNINITIALIZED,    // Some components may not have been allocated.
+    PREINITIALIZED,   // Components have been allocated but not initialized.
+    INITIALIZED       // All components are fully initialized.
+  };
+
+  State state_;
+  EntryStackItem* entry_stack_;
+
+  // Allocate and insert PerIsolateThreadData into the ThreadDataTable
+  // (regardless of whether such data already exists).
+  PerIsolateThreadData* AllocatePerIsolateThreadData(ThreadId thread_id);
+
+  // Find the PerThread for this particular (isolate, thread) combination.
+  // If one does not yet exist, allocate a new one.
+  PerIsolateThreadData* FindOrAllocatePerThreadDataForThisThread();
+
+  // PreInits and returns a default isolate. Needed when a new thread tries
+  // to create a Locker for the first time (the lock itself is in the isolate).
+  static Isolate* GetDefaultIsolateForLocking();
+
+  // Initializes the current thread to run this Isolate.
+  // Not thread-safe. Multiple threads should not Enter/Exit the same isolate
+  // at the same time, this should be prevented using external locking.
+  void Enter();
+
+  // Exits the current thread. The previosuly entered Isolate is restored
+  // for the thread.
+  // Not thread-safe. Multiple threads should not Enter/Exit the same isolate
+  // at the same time, this should be prevented using external locking.
+  void Exit();
+
+  void PreallocatedMemoryThreadStart();
+  void PreallocatedMemoryThreadStop();
+  void InitializeThreadLocal();
+
+  void PrintStackTrace(FILE* out, ThreadLocalTop* thread);
+  void MarkCompactPrologue(bool is_compacting,
+                           ThreadLocalTop* archived_thread_data);
+  void MarkCompactEpilogue(bool is_compacting,
+                           ThreadLocalTop* archived_thread_data);
+
+  void FillCache();
+
+  int stack_trace_nesting_level_;
+  StringStream* incomplete_message_;
+  // The preallocated memory thread singleton.
+  PreallocatedMemoryThread* preallocated_memory_thread_;
+  Address isolate_addresses_[k_isolate_address_count + 1];  // NOLINT
+  NoAllocationStringAllocator* preallocated_message_space_;
+
+  Bootstrapper* bootstrapper_;
+  RuntimeProfiler* runtime_profiler_;
+  CompilationCache* compilation_cache_;
+  Counters* counters_;
+  CpuFeatures* cpu_features_;
+  CodeRange* code_range_;
+  Mutex* break_access_;
+  Heap heap_;
+  Logger* logger_;
+  StackGuard stack_guard_;
+  StatsTable* stats_table_;
+  StubCache* stub_cache_;
+  DeoptimizerData* deoptimizer_data_;
+  ThreadLocalTop thread_local_top_;
+  bool capture_stack_trace_for_uncaught_exceptions_;
+  int stack_trace_for_uncaught_exceptions_frame_limit_;
+  StackTrace::StackTraceOptions stack_trace_for_uncaught_exceptions_options_;
+  TranscendentalCache* transcendental_cache_;
+  MemoryAllocator* memory_allocator_;
+  KeyedLookupCache* keyed_lookup_cache_;
+  ContextSlotCache* context_slot_cache_;
+  DescriptorLookupCache* descriptor_lookup_cache_;
+  v8::ImplementationUtilities::HandleScopeData handle_scope_data_;
+  HandleScopeImplementer* handle_scope_implementer_;
+  ScannerConstants* scanner_constants_;
+  Zone zone_;
+  PreallocatedStorage in_use_list_;
+  PreallocatedStorage free_list_;
+  bool preallocated_storage_preallocated_;
+  PcToCodeCache* pc_to_code_cache_;
+  StringInputBuffer* write_input_buffer_;
+  GlobalHandles* global_handles_;
+  ContextSwitcher* context_switcher_;
+  ThreadManager* thread_manager_;
+  AstSentinels* ast_sentinels_;
+  RuntimeState runtime_state_;
+  StringInputBuffer liveedit_compare_substrings_buf1_;
+  StringInputBuffer liveedit_compare_substrings_buf2_;
+  StaticResource<SafeStringInputBuffer> compiler_safe_string_input_buffer_;
+  Builtins builtins_;
+  StringTracker* string_tracker_;
+  unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize_;
+  unibrow::Mapping<unibrow::CanonicalizationRange> jsregexp_canonrange_;
+  StringInputBuffer objects_string_compare_buffer_a_;
+  StringInputBuffer objects_string_compare_buffer_b_;
+  StaticResource<StringInputBuffer> objects_string_input_buffer_;
+  unibrow::Mapping<unibrow::Ecma262Canonicalize>
+      regexp_macro_assembler_canonicalize_;
+  RegExpStack* regexp_stack_;
+  unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize_mapping_;
+  ZoneObjectList frame_element_constant_list_;
+  ZoneObjectList result_constant_list_;
+
+#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
+    defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
+  bool simulator_initialized_;
+  HashMap* simulator_i_cache_;
+  Redirection* simulator_redirection_;
+#endif
+
+#ifdef DEBUG
+  // A static array of histogram info for each type.
+  HistogramInfo heap_histograms_[LAST_TYPE + 1];
+  JSObject::SpillInformation js_spill_information_;
+  int code_kind_statistics_[Code::NUMBER_OF_KINDS];
+#endif
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  Debugger* debugger_;
+  Debug* debug_;
+#endif
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  ProducerHeapProfile* producer_heap_profile_;
+#endif
+
+#define GLOBAL_BACKING_STORE(type, name, initialvalue)                         \
+  type name##_;
+  ISOLATE_INIT_LIST(GLOBAL_BACKING_STORE)
+#undef GLOBAL_BACKING_STORE
+
+#define GLOBAL_ARRAY_BACKING_STORE(type, name, length)                         \
+  type name##_[length];
+  ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_BACKING_STORE)
+#undef GLOBAL_ARRAY_BACKING_STORE
+
+#ifdef DEBUG
+  // This class is huge and has a number of fields controlled by
+  // preprocessor defines. Make sure the offsets of these fields agree
+  // between compilation units.
+#define ISOLATE_FIELD_OFFSET(type, name, ignored)                              \
+  static const intptr_t name##_debug_offset_;
+  ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
+  ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
+#undef ISOLATE_FIELD_OFFSET
+#endif
+
+  friend class ExecutionAccess;
+  friend class IsolateInitializer;
+  friend class v8::Isolate;
+  friend class v8::Locker;
+
+  DISALLOW_COPY_AND_ASSIGN(Isolate);
+};
+
+
+// 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:
+  explicit SaveContext(Isolate* isolate) : prev_(isolate->save_context()) {
+    if (isolate->context() != NULL) {
+      context_ = Handle<Context>(isolate->context());
+#if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
+      dummy_ = Handle<Context>(isolate->context());
+#endif
+    }
+    isolate->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() {
+    if (context_.is_null()) {
+      Isolate* isolate = Isolate::Current();
+      isolate->set_context(NULL);
+      isolate->set_save_context(prev_);
+    } else {
+      Isolate* isolate = context_->GetIsolate();
+      isolate->set_context(*context_);
+      isolate->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() :
+      scope_(Isolate::Current()),
+      context_(Isolate::Current()->context(), Isolate::Current()) {
+  }
+
+  ~AssertNoContextChange() {
+    ASSERT(Isolate::Current()->context() == *context_);
+  }
+
+ private:
+  HandleScope scope_;
+  Handle<Context> context_;
+#else
+ public:
+  AssertNoContextChange() { }
+#endif
+};
+
+
+class ExecutionAccess BASE_EMBEDDED {
+ public:
+  explicit ExecutionAccess(Isolate* isolate) : isolate_(isolate) {
+    Lock(isolate);
+  }
+  ~ExecutionAccess() { Unlock(isolate_); }
+
+  static void Lock(Isolate* isolate) { isolate->break_access_->Lock(); }
+  static void Unlock(Isolate* isolate) { isolate->break_access_->Unlock(); }
+
+  static bool TryLock(Isolate* isolate) {
+    return isolate->break_access_->TryLock();
+  }
+
+ private:
+  Isolate* isolate_;
+};
+
+
+// Support for checking for stack-overflows in C++ code.
+class StackLimitCheck BASE_EMBEDDED {
+ public:
+  explicit StackLimitCheck(Isolate* isolate) : isolate_(isolate) { }
+
+  bool HasOverflowed() const {
+    StackGuard* stack_guard = isolate_->stack_guard();
+    // 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) < stack_guard->climit()) &&
+           stack_guard->IsStackOverflow();
+  }
+ private:
+  Isolate* isolate_;
+};
+
+
+// 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:
+  explicit PostponeInterruptsScope(Isolate* isolate)
+      : stack_guard_(isolate->stack_guard()) {
+    stack_guard_->thread_local_.postpone_interrupts_nesting_++;
+    stack_guard_->DisableInterrupts();
+  }
+
+  ~PostponeInterruptsScope() {
+    if (--stack_guard_->thread_local_.postpone_interrupts_nesting_ == 0) {
+      stack_guard_->EnableInterrupts();
+    }
+  }
+ private:
+  StackGuard* stack_guard_;
+};
+
+
+// Temporary macros for accessing current isolate and its subobjects.
+// They provide better readability, especially when used a lot in the code.
+#define HEAP (v8::internal::Isolate::Current()->heap())
+#define FACTORY (v8::internal::Isolate::Current()->factory())
+#define ISOLATE (v8::internal::Isolate::Current())
+#define ZONE (v8::internal::Isolate::Current()->zone())
+#define LOGGER (v8::internal::Isolate::Current()->logger())
+
+
+// Tells whether the global context is marked with out of memory.
+inline bool Context::has_out_of_memory() {
+  return global_context()->out_of_memory()->IsTrue();
+}
+
+
+// Mark the global context with out of memory.
+inline void Context::mark_out_of_memory() {
+  global_context()->set_out_of_memory(HEAP->true_value());
+}
+
+
+// Temporary macro to be used to flag definitions that are indeed static
+// and not per-isolate. (It would be great to be able to grep for [static]!)
+#define RLYSTC static
+
+
+// Temporary macro to be used to flag classes that should be static.
+#define STATIC_CLASS class
+
+
+// Temporary macro to be used to flag classes that are completely converted
+// to be isolate-friendly. Their mix of static/nonstatic methods/fields is
+// correct.
+#define ISOLATED_CLASS class
+
+} }  // namespace v8::internal
+
+// TODO(isolates): Get rid of these -inl.h includes and place them only where
+//                 they're needed.
+#include "allocation-inl.h"
+#include "zone-inl.h"
+#include "frames-inl.h"
+
+#endif  // V8_ISOLATE_H_
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index b271b02..06aae35 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -35,7 +35,6 @@
 #include "platform.h"
 #include "string-search.h"
 #include "runtime.h"
-#include "top.h"
 #include "compilation-cache.h"
 #include "string-stream.h"
 #include "parser.h"
@@ -51,6 +50,8 @@
 #include "x64/regexp-macro-assembler-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/regexp-macro-assembler-arm.h"
+#elif V8_TARGET_ARCH_MIPS
+#include "mips/regexp-macro-assembler-mips.h"
 #else
 #error Unsupported target architecture.
 #endif
@@ -62,7 +63,6 @@
 namespace v8 {
 namespace internal {
 
-
 Handle<Object> RegExpImpl::CreateRegExpLiteral(Handle<JSFunction> constructor,
                                                Handle<String> pattern,
                                                Handle<String> flags,
@@ -97,12 +97,14 @@
                                         Handle<String> pattern,
                                         Handle<String> error_text,
                                         const char* message) {
-  Handle<FixedArray> elements = Factory::NewFixedArray(2);
+  Isolate* isolate = re->GetIsolate();
+  Factory* factory = isolate->factory();
+  Handle<FixedArray> elements = factory->NewFixedArray(2);
   elements->set(0, *pattern);
   elements->set(1, *error_text);
-  Handle<JSArray> array = Factory::NewJSArrayWithElements(elements);
-  Handle<Object> regexp_err = Factory::NewSyntaxError(message, array);
-  Top::Throw(*regexp_err);
+  Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
+  Handle<Object> regexp_err = factory->NewSyntaxError(message, array);
+  isolate->Throw(*regexp_err);
 }
 
 
@@ -112,10 +114,12 @@
 Handle<Object> RegExpImpl::Compile(Handle<JSRegExp> re,
                                    Handle<String> pattern,
                                    Handle<String> flag_str) {
+  Isolate* isolate = re->GetIsolate();
   JSRegExp::Flags flags = RegExpFlagsFromString(flag_str);
-  Handle<FixedArray> cached = CompilationCache::LookupRegExp(pattern, flags);
+  CompilationCache* compilation_cache = isolate->compilation_cache();
+  Handle<FixedArray> cached = compilation_cache->LookupRegExp(pattern, flags);
   bool in_cache = !cached.is_null();
-  LOG(RegExpCompileEvent(re, in_cache));
+  LOG(isolate, RegExpCompileEvent(re, in_cache));
 
   Handle<Object> result;
   if (in_cache) {
@@ -124,9 +128,9 @@
   }
   pattern = FlattenGetString(pattern);
   CompilationZoneScope zone_scope(DELETE_ON_EXIT);
-  PostponeInterruptsScope postpone;
+  PostponeInterruptsScope postpone(isolate);
   RegExpCompileData parse_result;
-  FlatStringReader reader(pattern);
+  FlatStringReader reader(isolate, pattern);
   if (!RegExpParser::ParseRegExp(&reader, flags.is_multiline(),
                                  &parse_result)) {
     // Throw an exception if we fail to parse the pattern.
@@ -145,7 +149,8 @@
       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);
+    Handle<String> atom_string =
+        isolate->factory()->NewStringFromTwoByte(atom_pattern);
     AtomCompile(re, pattern, flags, atom_string);
   } else {
     IrregexpInitialize(re, pattern, flags, parse_result.capture_count);
@@ -154,7 +159,7 @@
   // 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);
+  compilation_cache->PutRegExp(pattern, flags, data);
 
   return re;
 }
@@ -170,7 +175,7 @@
     case JSRegExp::IRREGEXP: {
       Handle<Object> result =
           IrregexpExec(regexp, subject, index, last_match_info);
-      ASSERT(!result.is_null() || Top::has_pending_exception());
+      ASSERT(!result.is_null() || Isolate::Current()->has_pending_exception());
       return result;
     }
     default:
@@ -187,11 +192,11 @@
                              Handle<String> pattern,
                              JSRegExp::Flags flags,
                              Handle<String> match_pattern) {
-  Factory::SetRegExpAtomData(re,
-                             JSRegExp::ATOM,
-                             pattern,
-                             flags,
-                             match_pattern);
+  re->GetIsolate()->factory()->SetRegExpAtomData(re,
+                                                 JSRegExp::ATOM,
+                                                 pattern,
+                                                 flags,
+                                                 match_pattern);
 }
 
 
@@ -224,6 +229,8 @@
                                     Handle<String> subject,
                                     int index,
                                     Handle<JSArray> last_match_info) {
+  Isolate* isolate = re->GetIsolate();
+
   ASSERT(0 <= index);
   ASSERT(index <= subject->length());
 
@@ -237,24 +244,30 @@
   int needle_len = needle->length();
 
   if (needle_len != 0) {
-    if (index + needle_len > subject->length()) return Factory::null_value();
+    if (index + needle_len > subject->length())
+        return isolate->factory()->null_value();
+
     // dispatch on type of strings
     index = (needle->IsAsciiRepresentation()
              ? (seq_sub->IsAsciiRepresentation()
-                ? SearchString(seq_sub->ToAsciiVector(),
+                ? SearchString(isolate,
+                               seq_sub->ToAsciiVector(),
                                needle->ToAsciiVector(),
                                index)
-                : SearchString(seq_sub->ToUC16Vector(),
+                : SearchString(isolate,
+                               seq_sub->ToUC16Vector(),
                                needle->ToAsciiVector(),
                                index))
              : (seq_sub->IsAsciiRepresentation()
-                ? SearchString(seq_sub->ToAsciiVector(),
+                ? SearchString(isolate,
+                               seq_sub->ToAsciiVector(),
                                needle->ToUC16Vector(),
                                index)
-                : SearchString(seq_sub->ToUC16Vector(),
+                : SearchString(isolate,
+                               seq_sub->ToUC16Vector(),
                                needle->ToUC16Vector(),
                                index)));
-    if (index == -1) return Factory::null_value();
+    if (index == -1) return FACTORY->null_value();
   }
   ASSERT(last_match_info->HasFastElements());
 
@@ -288,13 +301,14 @@
 
 bool RegExpImpl::CompileIrregexp(Handle<JSRegExp> re, bool is_ascii) {
   // Compile the RegExp.
+  Isolate* isolate = re->GetIsolate();
   CompilationZoneScope zone_scope(DELETE_ON_EXIT);
-  PostponeInterruptsScope postpone;
+  PostponeInterruptsScope postpone(isolate);
   Object* entry = re->DataAt(JSRegExp::code_index(is_ascii));
   if (entry->IsJSObject()) {
     // If it's a JSObject, a previous compilation failed and threw this object.
     // Re-throw the object without trying again.
-    Top::Throw(entry);
+    isolate->Throw(entry);
     return false;
   }
   ASSERT(entry->IsTheHole());
@@ -307,7 +321,7 @@
   }
 
   RegExpCompileData compile_data;
-  FlatStringReader reader(pattern);
+  FlatStringReader reader(isolate, pattern);
   if (!RegExpParser::ParseRegExp(&reader, flags.is_multiline(),
                                  &compile_data)) {
     // Throw an exception if we fail to parse the pattern.
@@ -326,15 +340,16 @@
                             is_ascii);
   if (result.error_message != NULL) {
     // Unable to compile regexp.
-    Handle<FixedArray> elements = Factory::NewFixedArray(2);
+    Factory* factory = isolate->factory();
+    Handle<FixedArray> elements = factory->NewFixedArray(2);
     elements->set(0, *pattern);
     Handle<String> error_message =
-        Factory::NewStringFromUtf8(CStrVector(result.error_message));
+        factory->NewStringFromUtf8(CStrVector(result.error_message));
     elements->set(1, *error_message);
-    Handle<JSArray> array = Factory::NewJSArrayWithElements(elements);
+    Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
     Handle<Object> regexp_err =
-        Factory::NewSyntaxError("malformed_regexp", array);
-    Top::Throw(*regexp_err);
+        factory->NewSyntaxError("malformed_regexp", array);
+    isolate->Throw(*regexp_err);
     re->SetDataAt(JSRegExp::code_index(is_ascii), *regexp_err);
     return false;
   }
@@ -386,11 +401,11 @@
                                     JSRegExp::Flags flags,
                                     int capture_count) {
   // Initialize compiled code entries to null.
-  Factory::SetRegExpIrregexpData(re,
-                                 JSRegExp::IRREGEXP,
-                                 pattern,
-                                 flags,
-                                 capture_count);
+  re->GetIsolate()->factory()->SetRegExpIrregexpData(re,
+                                                     JSRegExp::IRREGEXP,
+                                                     pattern,
+                                                     flags,
+                                                     capture_count);
 }
 
 
@@ -428,7 +443,9 @@
     Handle<String> subject,
     int index,
     Vector<int> output) {
-  Handle<FixedArray> irregexp(FixedArray::cast(regexp->data()));
+  Isolate* isolate = regexp->GetIsolate();
+
+  Handle<FixedArray> irregexp(FixedArray::cast(regexp->data()), isolate);
 
   ASSERT(index >= 0);
   ASSERT(index <= subject->length());
@@ -436,24 +453,24 @@
 
   // A flat ASCII string might have a two-byte first part.
   if (subject->IsConsString()) {
-    subject = Handle<String>(ConsString::cast(*subject)->first());
+    subject = Handle<String>(ConsString::cast(*subject)->first(), isolate);
   }
 
 #ifndef V8_INTERPRETED_REGEXP
-  ASSERT(output.length() >=
-      (IrregexpNumberOfCaptures(*irregexp) + 1) * 2);
+  ASSERT(output.length() >= (IrregexpNumberOfCaptures(*irregexp) + 1) * 2);
   do {
     bool is_ascii = subject->IsAsciiRepresentation();
-    Handle<Code> code(IrregexpNativeCode(*irregexp, is_ascii));
+    Handle<Code> code(IrregexpNativeCode(*irregexp, is_ascii), isolate);
     NativeRegExpMacroAssembler::Result res =
         NativeRegExpMacroAssembler::Match(code,
                                           subject,
                                           output.start(),
                                           output.length(),
-                                          index);
+                                          index,
+                                          isolate);
     if (res != NativeRegExpMacroAssembler::RETRY) {
       ASSERT(res != NativeRegExpMacroAssembler::EXCEPTION ||
-             Top::has_pending_exception());
+             isolate->has_pending_exception());
       STATIC_ASSERT(
           static_cast<int>(NativeRegExpMacroAssembler::SUCCESS) == RE_SUCCESS);
       STATIC_ASSERT(
@@ -484,9 +501,10 @@
   for (int i = number_of_capture_registers - 1; i >= 0; i--) {
     register_vector[i] = -1;
   }
-  Handle<ByteArray> byte_codes(IrregexpByteCode(*irregexp, is_ascii));
+  Handle<ByteArray> byte_codes(IrregexpByteCode(*irregexp, is_ascii), isolate);
 
-  if (IrregexpInterpreter::Match(byte_codes,
+  if (IrregexpInterpreter::Match(isolate,
+                                 byte_codes,
                                  subject,
                                  register_vector,
                                  index)) {
@@ -516,7 +534,7 @@
   int required_registers = RegExpImpl::IrregexpPrepare(jsregexp, subject);
   if (required_registers < 0) {
     // Compiling failed with an exception.
-    ASSERT(Top::has_pending_exception());
+    ASSERT(Isolate::Current()->has_pending_exception());
     return Handle<Object>::null();
   }
 
@@ -542,11 +560,11 @@
     return last_match_info;
   }
   if (res == RE_EXCEPTION) {
-    ASSERT(Top::has_pending_exception());
+    ASSERT(Isolate::Current()->has_pending_exception());
     return Handle<Object>::null();
   }
   ASSERT(res == RE_FAILURE);
-  return Factory::null_value();
+  return Isolate::Current()->factory()->null_value();
 }
 
 
@@ -860,9 +878,11 @@
   if (reg_exp_too_big_) return IrregexpRegExpTooBig();
 
   Handle<Object> code = macro_assembler_->GetCode(pattern);
-
   work_list_ = NULL;
 #ifdef DEBUG
+  if (FLAG_print_code) {
+    Handle<Code>::cast(code)->Disassemble(*pattern->ToCString());
+  }
   if (FLAG_trace_regexp_assembler) {
     delete macro_assembler_;
   }
@@ -1304,16 +1324,14 @@
 }
 
 
-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,
+static int GetCaseIndependentLetters(Isolate* isolate,
+                                     uc16 character,
                                      bool ascii_subject,
                                      unibrow::uchar* letters) {
-  int length = uncanonicalize.get(character, '\0', letters);
+  int length =
+      isolate->jsregexp_uncanonicalize()->get(character, '\0', letters);
   // Unibrow returns 0 or 1 for characters where case independence is
   // trivial.
   if (length == 0) {
@@ -1329,7 +1347,8 @@
 }
 
 
-static inline bool EmitSimpleCharacter(RegExpCompiler* compiler,
+static inline bool EmitSimpleCharacter(Isolate* isolate,
+                                       RegExpCompiler* compiler,
                                        uc16 c,
                                        Label* on_failure,
                                        int cp_offset,
@@ -1351,7 +1370,8 @@
 
 // Only emits non-letters (things that don't have case).  Only used for case
 // independent matches.
-static inline bool EmitAtomNonLetter(RegExpCompiler* compiler,
+static inline bool EmitAtomNonLetter(Isolate* isolate,
+                                     RegExpCompiler* compiler,
                                      uc16 c,
                                      Label* on_failure,
                                      int cp_offset,
@@ -1360,7 +1380,7 @@
   RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
   bool ascii = compiler->ascii();
   unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
-  int length = GetCaseIndependentLetters(c, ascii, chars);
+  int length = GetCaseIndependentLetters(isolate, 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.
@@ -1422,7 +1442,8 @@
 }
 
 
-typedef bool EmitCharacterFunction(RegExpCompiler* compiler,
+typedef bool EmitCharacterFunction(Isolate* isolate,
+                                   RegExpCompiler* compiler,
                                    uc16 c,
                                    Label* on_failure,
                                    int cp_offset,
@@ -1431,7 +1452,8 @@
 
 // Only emits letters (things that have case).  Only used for case independent
 // matches.
-static inline bool EmitAtomLetter(RegExpCompiler* compiler,
+static inline bool EmitAtomLetter(Isolate* isolate,
+                                  RegExpCompiler* compiler,
                                   uc16 c,
                                   Label* on_failure,
                                   int cp_offset,
@@ -1440,7 +1462,7 @@
   RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
   bool ascii = compiler->ascii();
   unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
-  int length = GetCaseIndependentLetters(c, ascii, chars);
+  int length = GetCaseIndependentLetters(isolate, 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.
@@ -1878,6 +1900,7 @@
                                     RegExpCompiler* compiler,
                                     int characters_filled_in,
                                     bool not_at_start) {
+  Isolate* isolate = Isolate::Current();
   ASSERT(characters_filled_in < details->characters());
   int characters = details->characters();
   int char_mask;
@@ -1908,7 +1931,8 @@
         }
         if (compiler->ignore_case()) {
           unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
-          int length = GetCaseIndependentLetters(c, compiler->ascii(), chars);
+          int length = GetCaseIndependentLetters(isolate, 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
@@ -2408,6 +2432,7 @@
                             Trace* trace,
                             bool first_element_checked,
                             int* checked_up_to) {
+  Isolate* isolate = Isolate::Current();
   RegExpMacroAssembler* assembler = compiler->macro_assembler();
   bool ascii = compiler->ascii();
   Label* backtrack = trace->backtrack();
@@ -2443,7 +2468,8 @@
             break;
         }
         if (emit_function != NULL) {
-          bool bound_checked = emit_function(compiler,
+          bool bound_checked = emit_function(isolate,
+                                             compiler,
                                              quarks[j],
                                              backtrack,
                                              cp_offset + j,
@@ -4083,13 +4109,15 @@
 }
 
 
-static void AddUncanonicals(ZoneList<CharacterRange>* ranges,
+static void AddUncanonicals(Isolate* isolate,
+                            ZoneList<CharacterRange>* ranges,
                             int bottom,
                             int top);
 
 
 void CharacterRange::AddCaseEquivalents(ZoneList<CharacterRange>* ranges,
                                         bool is_ascii) {
+  Isolate* isolate = Isolate::Current();
   uc16 bottom = from();
   uc16 top = to();
   if (is_ascii) {
@@ -4099,7 +4127,7 @@
   unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
   if (top == bottom) {
     // If this is a singleton we just expand the one character.
-    int length = uncanonicalize.get(bottom, '\0', chars);
+    int length = isolate->jsregexp_uncanonicalize()->get(bottom, '\0', chars);
     for (int i = 0; i < length; i++) {
       uc32 chr = chars[i];
       if (chr != bottom) {
@@ -4128,7 +4156,7 @@
     unibrow::uchar range[unibrow::Ecma262UnCanonicalize::kMaxWidth];
     int pos = bottom;
     while (pos < top) {
-      int length = canonrange.get(pos, '\0', range);
+      int length = isolate->jsregexp_canonrange()->get(pos, '\0', range);
       uc16 block_end;
       if (length == 0) {
         block_end = pos;
@@ -4137,7 +4165,7 @@
         block_end = range[0];
       }
       int end = (block_end > top) ? top : block_end;
-      length = uncanonicalize.get(block_end, '\0', range);
+      length = isolate->jsregexp_uncanonicalize()->get(block_end, '\0', range);
       for (int i = 0; i < length; i++) {
         uc32 c = range[i];
         uc16 range_from = c - (block_end - pos);
@@ -4247,7 +4275,8 @@
 }
 
 
-static void AddUncanonicals(ZoneList<CharacterRange>* ranges,
+static void AddUncanonicals(Isolate* isolate,
+                            ZoneList<CharacterRange>* ranges,
                             int bottom,
                             int top) {
   unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
@@ -4279,8 +4308,8 @@
   // case mappings.
   for (int i = 0; i < boundary_count; i++) {
     if (bottom < boundaries[i] && top >= boundaries[i]) {
-      AddUncanonicals(ranges, bottom, boundaries[i] - 1);
-      AddUncanonicals(ranges, boundaries[i], top);
+      AddUncanonicals(isolate, ranges, bottom, boundaries[i] - 1);
+      AddUncanonicals(isolate, ranges, boundaries[i], top);
       return;
     }
   }
@@ -4291,7 +4320,8 @@
 #ifdef DEBUG
       for (int j = bottom; j <= top; j++) {
         unsigned current_char = j;
-        int length = uncanonicalize.get(current_char, '\0', chars);
+        int length = isolate->jsregexp_uncanonicalize()->get(current_char,
+                                                             '\0', chars);
         for (int k = 0; k < length; k++) {
           ASSERT(chars[k] == current_char);
         }
@@ -4304,7 +4334,7 @@
   // Step through the range finding equivalent characters.
   ZoneList<unibrow::uchar> *characters = new ZoneList<unibrow::uchar>(100);
   for (int i = bottom; i <= top; i++) {
-    int length = uncanonicalize.get(i, '\0', chars);
+    int length = isolate->jsregexp_uncanonicalize()->get(i, '\0', chars);
     for (int j = 0; j < length; j++) {
       uc32 chr = chars[j];
       if (chr != i && (chr < bottom || chr > top)) {
@@ -4826,7 +4856,7 @@
 
 
 void Analysis::EnsureAnalyzed(RegExpNode* that) {
-  StackLimitCheck check;
+  StackLimitCheck check(Isolate::Current());
   if (check.HasOverflowed()) {
     fail("Stack overflow");
     return;
@@ -5312,6 +5342,8 @@
   RegExpMacroAssemblerX64 macro_assembler(mode, (data->capture_count + 1) * 2);
 #elif V8_TARGET_ARCH_ARM
   RegExpMacroAssemblerARM macro_assembler(mode, (data->capture_count + 1) * 2);
+#elif V8_TARGET_ARCH_MIPS
+  RegExpMacroAssemblerMIPS macro_assembler(mode, (data->capture_count + 1) * 2);
 #endif
 
 #else  // V8_INTERPRETED_REGEXP
@@ -5336,7 +5368,4 @@
 }
 
 
-int OffsetsVector::static_offsets_vector_[
-    OffsetsVector::kStaticOffsetsVectorSize];
-
 }}  // namespace v8::internal
diff --git a/src/jsregexp.h b/src/jsregexp.h
index af28a87..3ed5a7e 100644
--- a/src/jsregexp.h
+++ b/src/jsregexp.h
@@ -1424,7 +1424,7 @@
   struct CompilationResult {
     explicit CompilationResult(const char* error_message)
         : error_message(error_message),
-          code(Heap::the_hole_value()),
+          code(HEAP->the_hole_value()),
           num_registers(0) {}
     CompilationResult(Object* code, int registers)
       : error_message(NULL),
@@ -1449,14 +1449,14 @@
  public:
   inline OffsetsVector(int num_registers)
       : offsets_vector_length_(num_registers) {
-    if (offsets_vector_length_ > kStaticOffsetsVectorSize) {
+    if (offsets_vector_length_ > Isolate::kJSRegexpStaticOffsetsVectorSize) {
       vector_ = NewArray<int>(offsets_vector_length_);
     } else {
-      vector_ = static_offsets_vector_;
+      vector_ = Isolate::Current()->jsregexp_static_offsets_vector();
     }
   }
   inline ~OffsetsVector() {
-    if (offsets_vector_length_ > kStaticOffsetsVectorSize) {
+    if (offsets_vector_length_ > Isolate::kJSRegexpStaticOffsetsVectorSize) {
       DeleteArray(vector_);
       vector_ = NULL;
     }
@@ -1467,13 +1467,12 @@
   static const int kStaticOffsetsVectorSize = 50;
 
  private:
-  static Address static_offsets_vector_address() {
-    return reinterpret_cast<Address>(&static_offsets_vector_);
+  static Address static_offsets_vector_address(Isolate* isolate) {
+    return reinterpret_cast<Address>(isolate->jsregexp_static_offsets_vector());
   }
 
   int* vector_;
   int offsets_vector_length_;
-  static int static_offsets_vector_[kStaticOffsetsVectorSize];
 
   friend class ExternalReference;
 };
diff --git a/src/jump-target-heavy.cc b/src/jump-target-heavy.cc
index c3c22f1..f73e027 100644
--- a/src/jump-target-heavy.cc
+++ b/src/jump-target-heavy.cc
@@ -35,9 +35,6 @@
 namespace internal {
 
 
-bool JumpTarget::compiling_deferred_code_ = false;
-
-
 void JumpTarget::Jump(Result* arg) {
   ASSERT(cgen()->has_valid_frame());
 
@@ -143,9 +140,9 @@
   // the directionality of the block.  Compute: an entry frame for the
   // block.
 
-  Counters::compute_entry_frame.Increment();
+  Isolate::Current()->counters()->compute_entry_frame()->Increment();
 #ifdef DEBUG
-  if (compiling_deferred_code_) {
+  if (Isolate::Current()->jump_target_compiling_deferred_code()) {
     ASSERT(reaching_frames_.length() > 1);
     VirtualFrame* frame = reaching_frames_[0];
     bool all_identical = true;
@@ -413,15 +410,15 @@
 
 
 DeferredCode::DeferredCode()
-    : masm_(CodeGeneratorScope::Current()->masm()),
+    : masm_(CodeGeneratorScope::Current(Isolate::Current())->masm()),
       statement_position_(masm_->positions_recorder()->
                           current_statement_position()),
       position_(masm_->positions_recorder()->current_position()),
-      frame_state_(CodeGeneratorScope::Current()->frame()) {
+      frame_state_(CodeGeneratorScope::Current(Isolate::Current())->frame()) {
   ASSERT(statement_position_ != RelocInfo::kNoPosition);
   ASSERT(position_ != RelocInfo::kNoPosition);
 
-  CodeGeneratorScope::Current()->AddDeferred(this);
+  CodeGeneratorScope::Current(Isolate::Current())->AddDeferred(this);
 #ifdef DEBUG
   comment_ = "";
 #endif
diff --git a/src/jump-target-heavy.h b/src/jump-target-heavy.h
index 8cec869..bf97756 100644
--- a/src/jump-target-heavy.h
+++ b/src/jump-target-heavy.h
@@ -135,10 +135,6 @@
   // after the call is the same as the frame before the call.
   void Call();
 
-  static void set_compiling_deferred_code(bool flag) {
-    compiling_deferred_code_ = flag;
-  }
-
  protected:
   // Directionality flag set at initialization time.
   Directionality direction_;
@@ -164,8 +160,6 @@
   void DoBind();
 
  private:
-  static bool compiling_deferred_code_;
-
   // Add a virtual frame reaching this labeled block via a forward jump,
   // and a corresponding merge code label.
   void AddReachingFrame(VirtualFrame* frame);
diff --git a/src/jump-target-inl.h b/src/jump-target-inl.h
index 4c9ee5b..545328c 100644
--- a/src/jump-target-inl.h
+++ b/src/jump-target-inl.h
@@ -40,7 +40,7 @@
 namespace internal {
 
 CodeGenerator* JumpTarget::cgen() {
-  return CodeGeneratorScope::Current();
+  return CodeGeneratorScope::Current(Isolate::Current());
 }
 
 } }  // namespace v8::internal
diff --git a/src/jump-target-light.cc b/src/jump-target-light.cc
index 36dc176..1d89474 100644
--- a/src/jump-target-light.cc
+++ b/src/jump-target-light.cc
@@ -35,15 +35,15 @@
 
 
 DeferredCode::DeferredCode()
-    : masm_(CodeGeneratorScope::Current()->masm()),
+    : masm_(CodeGeneratorScope::Current(Isolate::Current())->masm()),
       statement_position_(masm_->positions_recorder()->
                           current_statement_position()),
       position_(masm_->positions_recorder()->current_position()),
-      frame_state_(*CodeGeneratorScope::Current()->frame()) {
+      frame_state_(*CodeGeneratorScope::Current(Isolate::Current())->frame()) {
   ASSERT(statement_position_ != RelocInfo::kNoPosition);
   ASSERT(position_ != RelocInfo::kNoPosition);
 
-  CodeGeneratorScope::Current()->AddDeferred(this);
+  CodeGeneratorScope::Current(Isolate::Current())->AddDeferred(this);
 
 #ifdef DEBUG
   comment_ = "";
diff --git a/src/lithium-allocator-inl.h b/src/lithium-allocator-inl.h
index 84c5bbd..c0beaaf 100644
--- a/src/lithium-allocator-inl.h
+++ b/src/lithium-allocator-inl.h
@@ -36,6 +36,8 @@
 #include "x64/lithium-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/lithium-arm.h"
+#elif V8_TARGET_ARCH_MIPS
+#include "mips/lithium-mips.h"
 #else
 #error "Unknown architecture."
 #endif
diff --git a/src/lithium-allocator.cc b/src/lithium-allocator.cc
index 5755bb2..f62a7db 100644
--- a/src/lithium-allocator.cc
+++ b/src/lithium-allocator.cc
@@ -25,6 +25,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include "v8.h"
 #include "lithium-allocator-inl.h"
 
 #include "hydrogen.h"
@@ -36,6 +37,8 @@
 #include "x64/lithium-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/lithium-arm.h"
+#elif V8_TARGET_ARCH_MIPS
+#include "mips/lithium-mips.h"
 #else
 #error "Unknown architecture."
 #endif
@@ -44,13 +47,18 @@
 namespace internal {
 
 
-#define DEFINE_OPERAND_CACHE(name, type)            \
-  name name::cache[name::kNumCachedOperands];       \
-  void name::SetupCache() {                         \
-    for (int i = 0; i < kNumCachedOperands; i++) {  \
-      cache[i].ConvertTo(type, i);                  \
-    }                                               \
-  }
+#define DEFINE_OPERAND_CACHE(name, type)                      \
+  name name::cache[name::kNumCachedOperands];                 \
+  void name::SetupCache() {                                   \
+    for (int i = 0; i < kNumCachedOperands; i++) {            \
+      cache[i].ConvertTo(type, i);                            \
+    }                                                         \
+  }                                                           \
+  static bool name##_initialize() {                           \
+    name::SetupCache();                                       \
+    return true;                                              \
+  }                                                           \
+  static bool name##_cache_initialized = name##_initialize();
 
 DEFINE_OPERAND_CACHE(LConstantOperand, CONSTANT_OPERAND)
 DEFINE_OPERAND_CACHE(LStackSlot,       STACK_SLOT)
@@ -525,6 +533,24 @@
 }
 
 
+LAllocator::LAllocator(int num_values, HGraph* graph)
+    : chunk_(NULL),
+      live_in_sets_(graph->blocks()->length()),
+      live_ranges_(num_values * 2),
+      fixed_live_ranges_(NULL),
+      fixed_double_live_ranges_(NULL),
+      unhandled_live_ranges_(num_values * 2),
+      active_live_ranges_(8),
+      inactive_live_ranges_(8),
+      reusable_slots_(8),
+      next_virtual_register_(num_values),
+      first_artificial_register_(num_values),
+      mode_(NONE),
+      num_registers_(-1),
+      graph_(graph),
+      has_osr_entry_(false) {}
+
+
 void LAllocator::InitializeLivenessAnalysis() {
   // Initialize the live_in sets for each block to NULL.
   int block_count = graph_->blocks()->length();
@@ -618,11 +644,7 @@
 
 
 LiveRange* LAllocator::FixedLiveRangeFor(int index) {
-  if (index >= fixed_live_ranges_.length()) {
-    fixed_live_ranges_.AddBlock(NULL,
-                                index - fixed_live_ranges_.length() + 1);
-  }
-
+  ASSERT(index < Register::kNumAllocatableRegisters);
   LiveRange* result = fixed_live_ranges_[index];
   if (result == NULL) {
     result = new LiveRange(FixedLiveRangeID(index));
@@ -635,11 +657,7 @@
 
 
 LiveRange* LAllocator::FixedDoubleLiveRangeFor(int index) {
-  if (index >= fixed_double_live_ranges_.length()) {
-    fixed_double_live_ranges_.AddBlock(NULL,
-                                index - fixed_double_live_ranges_.length() + 1);
-  }
-
+  ASSERT(index < DoubleRegister::kNumAllocatableRegisters);
   LiveRange* result = fixed_double_live_ranges_[index];
   if (result == NULL) {
     result = new LiveRange(FixedDoubleLiveRangeID(index));
@@ -650,6 +668,7 @@
   return result;
 }
 
+
 LiveRange* LAllocator::LiveRangeFor(int index) {
   if (index >= live_ranges_.length()) {
     live_ranges_.AddBlock(NULL, index - live_ranges_.length() + 1);
@@ -1436,7 +1455,7 @@
 
 void LAllocator::AllocateRegisters() {
   ASSERT(mode_ != NONE);
-  reusable_slots_.Clear();
+  ASSERT(unhandled_live_ranges_.is_empty());
 
   for (int i = 0; i < live_ranges_.length(); ++i) {
     if (live_ranges_[i] != NULL) {
@@ -1448,6 +1467,7 @@
   SortUnhandled();
   ASSERT(UnhandledIsSorted());
 
+  ASSERT(reusable_slots_.is_empty());
   ASSERT(active_live_ranges_.is_empty());
   ASSERT(inactive_live_ranges_.is_empty());
 
@@ -1532,17 +1552,9 @@
     }
   }
 
-  active_live_ranges_.Clear();
-  inactive_live_ranges_.Clear();
-}
-
-
-void LAllocator::Setup() {
-  LConstantOperand::SetupCache();
-  LStackSlot::SetupCache();
-  LDoubleStackSlot::SetupCache();
-  LRegister::SetupCache();
-  LDoubleRegister::SetupCache();
+  reusable_slots_.Rewind(0);
+  active_live_ranges_.Rewind(0);
+  inactive_live_ranges_.Rewind(0);
 }
 
 
diff --git a/src/lithium-allocator.h b/src/lithium-allocator.h
index d53ea78..f109c45 100644
--- a/src/lithium-allocator.h
+++ b/src/lithium-allocator.h
@@ -428,24 +428,8 @@
 
 class LAllocator BASE_EMBEDDED {
  public:
-  explicit LAllocator(int first_virtual_register, HGraph* graph)
-      : chunk_(NULL),
-        live_in_sets_(0),
-        live_ranges_(16),
-        fixed_live_ranges_(8),
-        fixed_double_live_ranges_(8),
-        unhandled_live_ranges_(8),
-        active_live_ranges_(8),
-        inactive_live_ranges_(8),
-        reusable_slots_(8),
-        next_virtual_register_(first_virtual_register),
-        first_artificial_register_(first_virtual_register),
-        mode_(NONE),
-        num_registers_(-1),
-        graph_(graph),
-        has_osr_entry_(false) {}
+  LAllocator(int first_virtual_register, HGraph* graph);
 
-  static void Setup();
   static void TraceAlloc(const char* msg, ...);
 
   // Lithium translation support.
@@ -468,10 +452,10 @@
   void Allocate(LChunk* chunk);
 
   const ZoneList<LiveRange*>* live_ranges() const { return &live_ranges_; }
-  const ZoneList<LiveRange*>* fixed_live_ranges() const {
+  const Vector<LiveRange*>* fixed_live_ranges() const {
     return &fixed_live_ranges_;
   }
-  const ZoneList<LiveRange*>* fixed_double_live_ranges() const {
+  const Vector<LiveRange*>* fixed_double_live_ranges() const {
     return &fixed_double_live_ranges_;
   }
 
@@ -616,8 +600,10 @@
   ZoneList<LiveRange*> live_ranges_;
 
   // Lists of live ranges
-  ZoneList<LiveRange*> fixed_live_ranges_;
-  ZoneList<LiveRange*> fixed_double_live_ranges_;
+  EmbeddedVector<LiveRange*, Register::kNumAllocatableRegisters>
+      fixed_live_ranges_;
+  EmbeddedVector<LiveRange*, DoubleRegister::kNumAllocatableRegisters>
+      fixed_double_live_ranges_;
   ZoneList<LiveRange*> unhandled_live_ranges_;
   ZoneList<LiveRange*> active_live_ranges_;
   ZoneList<LiveRange*> inactive_live_ranges_;
diff --git a/src/lithium.cc b/src/lithium.cc
index e829f2f..aeac2db 100644
--- a/src/lithium.cc
+++ b/src/lithium.cc
@@ -25,6 +25,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include "v8.h"
 #include "lithium.h"
 
 namespace v8 {
diff --git a/src/liveedit.cc b/src/liveedit.cc
index 744ed49..dbcf5ef 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -35,10 +35,10 @@
 #include "debug.h"
 #include "deoptimizer.h"
 #include "global-handles.h"
-#include "memory.h"
 #include "parser.h"
 #include "scopeinfo.h"
 #include "scopes.h"
+#include "v8memory.h"
 
 namespace v8 {
 namespace internal {
@@ -47,6 +47,18 @@
 #ifdef ENABLE_DEBUGGER_SUPPORT
 
 
+void SetElementNonStrict(Handle<JSObject> object,
+                         uint32_t index,
+                         Handle<Object> value) {
+  // Ignore return value from SetElement. It can only be a failure if there
+  // are element setters causing exceptions and the debugger context has none
+  // of these.
+  Handle<Object> no_failure;
+  no_failure = SetElement(object, index, value, kNonStrictMode);
+  ASSERT(!no_failure.is_null());
+  USE(no_failure);
+}
+
 // A simple implementation of dynamic programming algorithm. It solves
 // the problem of finding the difference of 2 arrays. It uses a table of results
 // of subproblems. Each cell contains a number together with 2-bit flag
@@ -256,10 +268,10 @@
 }
 
 
-static bool CompareSubstrings(Handle<String> s1, int pos1,
+static bool CompareSubstrings(Isolate* isolate, Handle<String> s1, int pos1,
                               Handle<String> s2, int pos2, int len) {
-  static StringInputBuffer buf1;
-  static StringInputBuffer buf2;
+  StringInputBuffer& buf1 = *isolate->liveedit_compare_substrings_buf1();
+  StringInputBuffer& buf2 = *isolate->liveedit_compare_substrings_buf2();
   buf1.Reset(*s1);
   buf1.Seek(pos1);
   buf2.Reset(*s2);
@@ -279,25 +291,22 @@
 class CompareOutputArrayWriter {
  public:
   CompareOutputArrayWriter()
-      : array_(Factory::NewJSArray(10)), current_size_(0) {}
+      : array_(FACTORY->NewJSArray(10)), current_size_(0) {}
 
   Handle<JSArray> GetResult() {
     return array_;
   }
 
   void WriteChunk(int char_pos1, int char_pos2, int char_len1, int char_len2) {
-    SetElement(array_,
-               current_size_,
-               Handle<Object>(Smi::FromInt(char_pos1)),
-               kNonStrictMode);
-    SetElement(array_,
-               current_size_ + 1,
-               Handle<Object>(Smi::FromInt(char_pos1 + char_len1)),
-               kNonStrictMode);
-    SetElement(array_,
-               current_size_ + 2,
-               Handle<Object>(Smi::FromInt(char_pos2 + char_len2)),
-               kNonStrictMode);
+    SetElementNonStrict(array_,
+                       current_size_,
+                       Handle<Object>(Smi::FromInt(char_pos1)));
+    SetElementNonStrict(array_,
+                        current_size_ + 1,
+                        Handle<Object>(Smi::FromInt(char_pos1 + char_len1)));
+    SetElementNonStrict(array_,
+                        current_size_ + 2,
+                        Handle<Object>(Smi::FromInt(char_pos2 + char_len2)));
     current_size_ += 3;
   }
 
@@ -401,9 +410,10 @@
 // Represents 2 strings as 2 arrays of lines.
 class LineArrayCompareInput : public Comparator::Input {
  public:
-  LineArrayCompareInput(Handle<String> s1, Handle<String> s2,
+  LineArrayCompareInput(Isolate* isolate, Handle<String> s1, Handle<String> s2,
                         LineEndsWrapper line_ends1, LineEndsWrapper line_ends2)
-      : s1_(s1), s2_(s2), line_ends1_(line_ends1), line_ends2_(line_ends2) {
+      : isolate_(isolate), s1_(s1), s2_(s2), line_ends1_(line_ends1),
+        line_ends2_(line_ends2) {
   }
   int getLength1() {
     return line_ends1_.length();
@@ -421,10 +431,12 @@
     if (len1 != len2) {
       return false;
     }
-    return CompareSubstrings(s1_, line_start1, s2_, line_start2, len1);
+    return CompareSubstrings(isolate_, s1_, line_start1, s2_, line_start2,
+                             len1);
   }
 
  private:
+  Isolate* isolate_;
   Handle<String> s1_;
   Handle<String> s2_;
   LineEndsWrapper line_ends1_;
@@ -483,7 +495,8 @@
   LineEndsWrapper line_ends1(s1);
   LineEndsWrapper line_ends2(s2);
 
-  LineArrayCompareInput input(s1, s2, line_ends1, line_ends2);
+  LineArrayCompareInput
+      input(Isolate::Current(), s1, s2, line_ends1, line_ends2);
   TokenizingLineArrayCompareOutput output(line_ends1, line_ends2, s1, s2);
 
   Comparator::CalculateDifference(&input, &output);
@@ -492,21 +505,21 @@
 }
 
 
-static void CompileScriptForTracker(Handle<Script> script) {
+static void CompileScriptForTracker(Isolate* isolate, Handle<Script> script) {
   // TODO(635): support extensions.
-  PostponeInterruptsScope postpone;
+  PostponeInterruptsScope postpone(isolate);
 
   // Build AST.
   CompilationInfo info(script);
   info.MarkAsGlobal();
   if (ParserApi::Parse(&info)) {
     // Compile the code.
-    LiveEditFunctionTracker tracker(info.function());
+    LiveEditFunctionTracker tracker(info.isolate(), info.function());
     if (Compiler::MakeCodeForLiveEdit(&info)) {
       ASSERT(!info.code().is_null());
       tracker.RecordRootFunctionInfo(info.code());
     } else {
-      Top::StackOverflow();
+      info.isolate()->StackOverflow();
     }
   }
 }
@@ -521,9 +534,10 @@
 // Wraps any object into a OpaqueReference, that will hide the object
 // from JavaScript.
 static Handle<JSValue> WrapInJSValue(Object* object) {
-  Handle<JSFunction> constructor = Top::opaque_reference_function();
+  Handle<JSFunction> constructor =
+      Isolate::Current()->opaque_reference_function();
   Handle<JSValue> result =
-      Handle<JSValue>::cast(Factory::NewJSObject(constructor));
+      Handle<JSValue>::cast(FACTORY->NewJSObject(constructor));
   result->set_value(object);
   return result;
 }
@@ -536,7 +550,7 @@
 class JSArrayBasedStruct {
  public:
   static S Create() {
-    Handle<JSArray> array = Factory::NewJSArray(S::kSize_);
+    Handle<JSArray> array = FACTORY->NewJSArray(S::kSize_);
     return S(array);
   }
   static S cast(Object* object) {
@@ -552,13 +566,12 @@
 
  protected:
   void SetField(int field_position, Handle<Object> value) {
-    SetElement(array_, field_position, value, kNonStrictMode);
+    SetElementNonStrict(array_, field_position, value);
   }
   void SetSmiValueField(int field_position, int value) {
-    SetElement(array_,
-               field_position,
-               Handle<Smi>(Smi::FromInt(value)),
-               kNonStrictMode);
+    SetElementNonStrict(array_,
+                        field_position,
+                        Handle<Smi>(Smi::FromInt(value)));
   }
   Object* GetField(int field_position) {
     return array_->GetElementNoExceptionThrown(field_position);
@@ -687,7 +700,7 @@
   FunctionInfoListener() {
     current_parent_index_ = -1;
     len_ = 0;
-    result_ = Factory::NewJSArray(10);
+    result_ = FACTORY->NewJSArray(10);
   }
 
   void FunctionStarted(FunctionLiteral* fun) {
@@ -697,7 +710,7 @@
                               fun->end_position(), fun->num_parameters(),
                               current_parent_index_);
     current_parent_index_ = len_;
-    SetElement(result_, len_, info.GetJSArray(), kNonStrictMode);
+    SetElementNonStrict(result_, len_, info.GetJSArray());
     len_++;
   }
 
@@ -715,7 +728,7 @@
     FunctionInfoWrapper info =
         FunctionInfoWrapper::cast(
             result_->GetElementNoExceptionThrown(current_parent_index_));
-    info.SetFunctionCode(function_code, Handle<Object>(Heap::null_value()));
+    info.SetFunctionCode(function_code, Handle<Object>(HEAP->null_value()));
   }
 
   // Saves full information about a function: its code, its scope info
@@ -741,7 +754,7 @@
   Object* SerializeFunctionScope(Scope* scope) {
     HandleScope handle_scope;
 
-    Handle<JSArray> scope_info_list = Factory::NewJSArray(10);
+    Handle<JSArray> scope_info_list = FACTORY->NewJSArray(10);
     int scope_info_length = 0;
 
     // Saves some description of scope. It stores name and indexes of
@@ -749,7 +762,7 @@
     // scopes of this chain.
     Scope* outer_scope = scope->outer_scope();
     if (outer_scope == NULL) {
-      return Heap::undefined_value();
+      return HEAP->undefined_value();
     }
     do {
       ZoneList<Variable*> list(10);
@@ -777,16 +790,19 @@
         list[k] = list[l];
       }
       for (int i = 0; i < j; i++) {
-        SetElement(scope_info_list, scope_info_length,
-                   list[i]->name(), kNonStrictMode);
+        SetElementNonStrict(scope_info_list,
+                            scope_info_length,
+                            list[i]->name());
         scope_info_length++;
-        SetElement(scope_info_list, scope_info_length,
-                   Handle<Smi>(Smi::FromInt(list[i]->AsSlot()->index())),
-                   kNonStrictMode);
+        SetElementNonStrict(
+            scope_info_list,
+            scope_info_length,
+            Handle<Smi>(Smi::FromInt(list[i]->AsSlot()->index())));
         scope_info_length++;
       }
-      SetElement(scope_info_list, scope_info_length,
-                 Handle<Object>(Heap::null_value()), kNonStrictMode);
+      SetElementNonStrict(scope_info_list,
+                          scope_info_length,
+                          Handle<Object>(HEAP->null_value()));
       scope_info_length++;
 
       outer_scope = outer_scope->outer_scope();
@@ -801,18 +817,17 @@
 };
 
 
-static FunctionInfoListener* active_function_info_listener = NULL;
-
 JSArray* LiveEdit::GatherCompileInfo(Handle<Script> script,
                                      Handle<String> source) {
+  Isolate* isolate = Isolate::Current();
   CompilationZoneScope zone_scope(DELETE_ON_EXIT);
 
   FunctionInfoListener listener;
   Handle<Object> original_source = Handle<Object>(script->source());
   script->set_source(*source);
-  active_function_info_listener = &listener;
-  CompileScriptForTracker(script);
-  active_function_info_listener = NULL;
+  isolate->set_active_function_info_listener(&listener);
+  CompileScriptForTracker(isolate, script);
+  isolate->set_active_function_info_listener(NULL);
   script->set_source(*original_source);
 
   return *(listener.GetResult());
@@ -829,7 +844,7 @@
     Handle<String> name_handle(String::cast(info->name()));
     info_wrapper.SetProperties(name_handle, info->start_position(),
                                info->end_position(), info);
-    SetElement(array, i, info_wrapper.GetJSArray(), kNonStrictMode);
+    SetElementNonStrict(array, i, info_wrapper.GetJSArray());
   }
 }
 
@@ -894,7 +909,7 @@
 
 // Finds all references to original and replaces them with substitution.
 static void ReplaceCodeObject(Code* original, Code* substitution) {
-  ASSERT(!Heap::InNewSpace(substitution));
+  ASSERT(!HEAP->InNewSpace(substitution));
 
   AssertNoAllocation no_allocations_please;
 
@@ -907,7 +922,7 @@
   // so temporary replace the pointers with offset numbers
   // in prologue/epilogue.
   {
-    Heap::IterateStrongRoots(&visitor, VISIT_ALL);
+    HEAP->IterateStrongRoots(&visitor, VISIT_ALL);
   }
 
   // Now iterate over all pointers of all objects, including code_target
@@ -937,7 +952,7 @@
   DeoptimizationInputData* data =
       DeoptimizationInputData::cast(function->code()->deoptimization_data());
 
-  if (data == Heap::empty_fixed_array()) return false;
+  if (data == HEAP->empty_fixed_array()) return false;
 
   FixedArray* literals = data->LiteralArray();
 
@@ -989,7 +1004,7 @@
   HandleScope scope;
 
   if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
-    return Top::ThrowIllegalOperation();
+    return Isolate::Current()->ThrowIllegalOperation();
   }
 
   FunctionInfoWrapper compile_info_wrapper(new_compile_info_array);
@@ -1009,7 +1024,7 @@
   if (shared_info->debug_info()->IsDebugInfo()) {
     Handle<DebugInfo> debug_info(DebugInfo::cast(shared_info->debug_info()));
     Handle<Code> new_original_code =
-        Factory::CopyCode(compile_info_wrapper.GetFunctionCode());
+        FACTORY->CopyCode(compile_info_wrapper.GetFunctionCode());
     debug_info->set_original_code(*new_original_code);
   }
 
@@ -1017,12 +1032,13 @@
   shared_info->set_end_position(compile_info_wrapper.GetEndPosition());
 
   shared_info->set_construct_stub(
-      Builtins::builtin(Builtins::JSConstructStubGeneric));
+      Isolate::Current()->builtins()->builtin(
+          Builtins::kJSConstructStubGeneric));
 
   DeoptimizeDependentFunctions(*shared_info);
-  CompilationCache::Remove(shared_info);
+  Isolate::Current()->compilation_cache()->Remove(shared_info);
 
-  return Heap::undefined_value();
+  return HEAP->undefined_value();
 }
 
 
@@ -1031,16 +1047,16 @@
   HandleScope scope;
 
   if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
-    return Top::ThrowIllegalOperation();
+    return Isolate::Current()->ThrowIllegalOperation();
   }
 
   SharedInfoWrapper shared_info_wrapper(shared_info_array);
   Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
 
   DeoptimizeDependentFunctions(*shared_info);
-  CompilationCache::Remove(shared_info);
+  Isolate::Current()->compilation_cache()->Remove(shared_info);
 
-  return Heap::undefined_value();
+  return HEAP->undefined_value();
 }
 
 
@@ -1050,7 +1066,7 @@
       Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper));
   shared_info->set_script(*script_handle);
 
-  CompilationCache::Remove(shared_info);
+  Isolate::Current()->compilation_cache()->Remove(shared_info);
 }
 
 
@@ -1198,7 +1214,7 @@
     // Relocation info section now has different size. We cannot simply
     // rewrite it inside code object. Instead we have to create a new
     // code object.
-    Handle<Code> result(Factory::CopyCode(code, buffer));
+    Handle<Code> result(FACTORY->CopyCode(code, buffer));
     return result;
   }
 }
@@ -1208,7 +1224,7 @@
     Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) {
 
   if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
-    return Top::ThrowIllegalOperation();
+    return Isolate::Current()->ThrowIllegalOperation();
   }
 
   SharedInfoWrapper shared_info_wrapper(shared_info_array);
@@ -1239,14 +1255,14 @@
     }
   }
 
-  return Heap::undefined_value();
+  return HEAP->undefined_value();
 }
 
 
 static Handle<Script> CreateScriptCopy(Handle<Script> original) {
   Handle<String> original_source(String::cast(original->source()));
 
-  Handle<Script> copy = Factory::NewScript(original_source);
+  Handle<Script> copy = FACTORY->NewScript(original_source);
 
   copy->set_name(original->name());
   copy->set_line_offset(original->line_offset());
@@ -1271,15 +1287,16 @@
     Handle<Script> old_script = CreateScriptCopy(original_script);
     old_script->set_name(String::cast(*old_script_name));
     old_script_object = old_script;
-    Debugger::OnAfterCompile(old_script, Debugger::SEND_WHEN_DEBUGGING);
+    Isolate::Current()->debugger()->OnAfterCompile(
+        old_script, Debugger::SEND_WHEN_DEBUGGING);
   } else {
-    old_script_object = Handle<Object>(Heap::null_value());
+    old_script_object = Handle<Object>(HEAP->null_value());
   }
 
   original_script->set_source(*new_source);
 
   // Drop line ends so that they will be recalculated.
-  original_script->set_line_ends(Heap::undefined_value());
+  original_script->set_line_ends(HEAP->undefined_value());
 
   return *old_script_object;
 }
@@ -1327,7 +1344,7 @@
         SharedFunctionInfo::cast(wrapper->value()));
 
     if (function->shared() == *shared || IsInlined(*function, *shared)) {
-      SetElement(result, i, Handle<Smi>(Smi::FromInt(status)), kNonStrictMode);
+      SetElementNonStrict(result, i, Handle<Smi>(Smi::FromInt(status)));
       return true;
     }
   }
@@ -1340,7 +1357,8 @@
 static bool FixTryCatchHandler(StackFrame* top_frame,
                                StackFrame* bottom_frame) {
   Address* pointer_address =
-      &Memory::Address_at(Top::get_address_from_id(Top::k_handler_address));
+      &Memory::Address_at(Isolate::Current()->get_address_from_id(
+          Isolate::k_handler_address));
 
   while (*pointer_address < top_frame->sp()) {
     pointer_address = &Memory::Address_at(*pointer_address);
@@ -1375,19 +1393,22 @@
   ASSERT(bottom_js_frame->is_java_script());
 
   // Check the nature of the top frame.
-  if (pre_top_frame->code()->is_inline_cache_stub() &&
-      pre_top_frame->code()->ic_state() == DEBUG_BREAK) {
+  Code* pre_top_frame_code = pre_top_frame->LookupCode(Isolate::Current());
+  if (pre_top_frame_code->is_inline_cache_stub() &&
+      pre_top_frame_code->ic_state() == DEBUG_BREAK) {
     // OK, we can drop inline cache calls.
     *mode = Debug::FRAME_DROPPED_IN_IC_CALL;
-  } else if (pre_top_frame->code() == Debug::debug_break_slot()) {
+  } else if (pre_top_frame_code ==
+             Isolate::Current()->debug()->debug_break_slot()) {
     // OK, we can drop debug break slot.
     *mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL;
-  } else if (pre_top_frame->code() ==
-      Builtins::builtin(Builtins::FrameDropper_LiveEdit)) {
+  } else if (pre_top_frame_code ==
+      Isolate::Current()->builtins()->builtin(
+          Builtins::kFrameDropper_LiveEdit)) {
     // OK, we can drop our own code.
     *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
-  } else if (pre_top_frame->code()->kind() == Code::STUB &&
-      pre_top_frame->code()->major_key()) {
+  } else if (pre_top_frame_code->kind() == Code::STUB &&
+      pre_top_frame_code->major_key()) {
     // Entry from our unit tests, it's fine, we support this case.
     *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
   } else {
@@ -1409,7 +1430,7 @@
   // Make sure FixTryCatchHandler is idempotent.
   ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame));
 
-  Handle<Code> code(Builtins::builtin(Builtins::FrameDropper_LiveEdit));
+  Handle<Code> code = Isolate::Current()->builtins()->FrameDropper_LiveEdit();
   top_frame->set_pc(code->entry());
   pre_top_frame->SetCallerFp(bottom_js_frame->fp());
 
@@ -1436,7 +1457,7 @@
 // removing all listed function if possible and if do_drop is true.
 static const char* DropActivationsInActiveThread(
     Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop) {
-
+  Debug* debug = Isolate::Current()->debug();
   ZoneScope scope(DELETE_ON_EXIT);
   Vector<StackFrame*> frames = CreateStackMap();
 
@@ -1446,7 +1467,7 @@
   int frame_index = 0;
   for (; frame_index < frames.length(); frame_index++) {
     StackFrame* frame = frames[frame_index];
-    if (frame->id() == Debug::break_frame_id()) {
+    if (frame->id() == debug->break_frame_id()) {
       top_frame_index = frame_index;
       break;
     }
@@ -1523,7 +1544,7 @@
       break;
     }
   }
-  Debug::FramesHaveBeenDropped(new_id, drop_mode,
+  debug->FramesHaveBeenDropped(new_id, drop_mode,
                                restarter_frame_function_pointer);
 
   // Replace "blocked on active" with "replaced on active" status.
@@ -1532,7 +1553,7 @@
         Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
       Handle<Object> replaced(
           Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK));
-      SetElement(result, i, replaced, kNonStrictMode);
+      SetElementNonStrict(result, i, replaced);
     }
   }
   return NULL;
@@ -1568,20 +1589,22 @@
     Handle<JSArray> shared_info_array, bool do_drop) {
   int len = Smi::cast(shared_info_array->length())->value();
 
-  Handle<JSArray> result = Factory::NewJSArray(len);
+  Handle<JSArray> result = FACTORY->NewJSArray(len);
 
   // Fill the default values.
   for (int i = 0; i < len; i++) {
-    SetElement(result, i,
-               Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH)),
-               kNonStrictMode);
+    SetElementNonStrict(
+        result,
+        i,
+        Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH)));
   }
 
 
   // First check inactive threads. Fail if some functions are blocked there.
   InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array,
                                                             result);
-  ThreadManager::IterateArchivedThreads(&inactive_threads_checker);
+  Isolate::Current()->thread_manager()->IterateArchivedThreads(
+      &inactive_threads_checker);
   if (inactive_threads_checker.HasBlockedFunctions()) {
     return result;
   }
@@ -1592,42 +1615,44 @@
   if (error_message != NULL) {
     // Add error message as an array extra element.
     Vector<const char> vector_message(error_message, StrLength(error_message));
-    Handle<String> str = Factory::NewStringFromAscii(vector_message);
-    SetElement(result, len, str, kNonStrictMode);
+    Handle<String> str = FACTORY->NewStringFromAscii(vector_message);
+    SetElementNonStrict(result, len, str);
   }
   return result;
 }
 
 
-LiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) {
-  if (active_function_info_listener != NULL) {
-    active_function_info_listener->FunctionStarted(fun);
+LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate,
+                                                 FunctionLiteral* fun)
+    : isolate_(isolate) {
+  if (isolate_->active_function_info_listener() != NULL) {
+    isolate_->active_function_info_listener()->FunctionStarted(fun);
   }
 }
 
 
 LiveEditFunctionTracker::~LiveEditFunctionTracker() {
-  if (active_function_info_listener != NULL) {
-    active_function_info_listener->FunctionDone();
+  if (isolate_->active_function_info_listener() != NULL) {
+    isolate_->active_function_info_listener()->FunctionDone();
   }
 }
 
 
 void LiveEditFunctionTracker::RecordFunctionInfo(
     Handle<SharedFunctionInfo> info, FunctionLiteral* lit) {
-  if (active_function_info_listener != NULL) {
-    active_function_info_listener->FunctionInfo(info, lit->scope());
+  if (isolate_->active_function_info_listener() != NULL) {
+    isolate_->active_function_info_listener()->FunctionInfo(info, lit->scope());
   }
 }
 
 
 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) {
-  active_function_info_listener->FunctionCode(code);
+  isolate_->active_function_info_listener()->FunctionCode(code);
 }
 
 
-bool LiveEditFunctionTracker::IsActive() {
-  return active_function_info_listener != NULL;
+bool LiveEditFunctionTracker::IsActive(Isolate* isolate) {
+  return isolate->active_function_info_listener() != NULL;
 }
 
 
@@ -1635,7 +1660,8 @@
 
 // This ifdef-else-endif section provides working or stub implementation of
 // LiveEditFunctionTracker.
-LiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) {
+LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate,
+                                                 FunctionLiteral* fun) {
 }
 
 
diff --git a/src/liveedit.h b/src/liveedit.h
index 5f2c99c..36c2c76 100644
--- a/src/liveedit.h
+++ b/src/liveedit.h
@@ -65,13 +65,18 @@
 // also collects compiled function codes.
 class LiveEditFunctionTracker {
  public:
-  explicit LiveEditFunctionTracker(FunctionLiteral* fun);
+  explicit LiveEditFunctionTracker(Isolate* isolate, FunctionLiteral* fun);
   ~LiveEditFunctionTracker();
   void RecordFunctionInfo(Handle<SharedFunctionInfo> info,
                           FunctionLiteral* lit);
   void RecordRootFunctionInfo(Handle<Code> code);
 
-  static bool IsActive();
+  static bool IsActive(Isolate* isolate);
+
+ private:
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  Isolate* isolate_;
+#endif
 };
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
diff --git a/src/liveobjectlist.h b/src/liveobjectlist.h
index 423f8f0..23e418d 100644
--- a/src/liveobjectlist.h
+++ b/src/liveobjectlist.h
@@ -273,28 +273,28 @@
   inline static void ProcessNonLive(HeapObject* obj) {}
   inline static void UpdateReferencesForScavengeGC() {}
 
-  inline static MaybeObject* Capture() { return Heap::undefined_value(); }
+  inline static MaybeObject* Capture() { return HEAP->undefined_value(); }
   inline static bool Delete(int id) { return false; }
   inline static MaybeObject* Dump(int id1,
                                   int id2,
                                   int start_idx,
                                   int dump_limit,
                                   Handle<JSObject> filter_obj) {
-    return Heap::undefined_value();
+    return HEAP->undefined_value();
   }
   inline static MaybeObject* Info(int start_idx, int dump_limit) {
-    return Heap::undefined_value();
+    return HEAP->undefined_value();
   }
   inline static MaybeObject* Summarize(int id1,
                                        int id2,
                                        Handle<JSObject> filter_obj) {
-    return Heap::undefined_value();
+    return HEAP->undefined_value();
   }
 
   inline static void Reset() {}
-  inline static Object* GetObj(int obj_id) { return Heap::undefined_value(); }
+  inline static Object* GetObj(int obj_id) { return HEAP->undefined_value(); }
   inline static Object* GetObjId(Handle<String> address) {
-    return Heap::undefined_value();
+    return HEAP->undefined_value();
   }
   inline static MaybeObject* GetObjRetainers(int obj_id,
                                              Handle<JSObject> instance_filter,
@@ -302,15 +302,15 @@
                                              int start,
                                              int count,
                                              Handle<JSObject> filter_obj) {
-    return Heap::undefined_value();
+    return HEAP->undefined_value();
   }
 
   inline static Object* GetPath(int obj_id1,
                                 int obj_id2,
                                 Handle<JSObject> instance_filter) {
-    return Heap::undefined_value();
+    return HEAP->undefined_value();
   }
-  inline static Object* PrintObj(int obj_id) { return Heap::undefined_value(); }
+  inline static Object* PrintObj(int obj_id) { return HEAP->undefined_value(); }
 };
 
 
diff --git a/src/log-utils.cc b/src/log-utils.cc
index 9a498ec..a854ade 100644
--- a/src/log-utils.cc
+++ b/src/log-utils.cc
@@ -28,6 +28,7 @@
 #include "v8.h"
 
 #include "log-utils.h"
+#include "string-stream.h"
 
 namespace v8 {
 namespace internal {
@@ -118,29 +119,117 @@
   return data_size;
 }
 
-
-bool Log::is_stopped_ = false;
-Log::WritePtr Log::Write = NULL;
-FILE* Log::output_handle_ = NULL;
-FILE* Log::output_code_handle_ = NULL;
-LogDynamicBuffer* Log::output_buffer_ = NULL;
 // Must be the same message as in Logger::PauseProfiler.
-const char* Log::kDynamicBufferSeal = "profiler,\"pause\"\n";
-Mutex* Log::mutex_ = NULL;
-char* Log::message_buffer_ = NULL;
+const char* const Log::kDynamicBufferSeal = "profiler,\"pause\"\n";
+
+Log::Log(Logger* logger)
+  : write_to_file_(false),
+    is_stopped_(false),
+    output_handle_(NULL),
+    output_code_handle_(NULL),
+    output_buffer_(NULL),
+    mutex_(NULL),
+    message_buffer_(NULL),
+    logger_(logger) {
+}
 
 
-void Log::Init() {
+static void AddIsolateIdIfNeeded(StringStream* stream) {
+  Isolate* isolate = Isolate::Current();
+  if (isolate->IsDefaultIsolate()) return;
+  stream->Add("isolate-%p-", isolate);
+}
+
+
+void Log::Initialize() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
   mutex_ = OS::CreateMutex();
   message_buffer_ = NewArray<char>(kMessageBufferSize);
+
+  // --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;
+
+  // --prof_lazy controls --log-code, implies --noprof_auto.
+  if (FLAG_prof_lazy) {
+    FLAG_log_code = false;
+    FLAG_prof_auto = false;
+  }
+
+  bool start_logging = 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;
+
+  bool open_log_file = start_logging || FLAG_prof_lazy;
+
+  // If we're logging anything, we need to open the log file.
+  if (open_log_file) {
+    if (strcmp(FLAG_logfile, "-") == 0) {
+      OpenStdout();
+    } else if (strcmp(FLAG_logfile, "*") == 0) {
+      OpenMemoryBuffer();
+    } else  {
+      if (strchr(FLAG_logfile, '%') != NULL ||
+          !Isolate::Current()->IsDefaultIsolate()) {
+        // If there's a '%' in the log file name we have to expand
+        // placeholders.
+        HeapStringAllocator allocator;
+        StringStream stream(&allocator);
+        AddIsolateIdIfNeeded(&stream);
+        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.
+                double time = OS::TimeCurrentMillis();
+                stream.Add("%.0f", FmtElm(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();
+        OpenFile(*expanded);
+      } else {
+        OpenFile(FLAG_logfile);
+      }
+    }
+  }
+#endif
 }
 
 
 void Log::OpenStdout() {
   ASSERT(!IsEnabled());
   output_handle_ = stdout;
-  Write = WriteToFile;
-  Init();
+  write_to_file_ = true;
 }
 
 
@@ -150,6 +239,7 @@
 void Log::OpenFile(const char* name) {
   ASSERT(!IsEnabled());
   output_handle_ = OS::FOpen(name, OS::LogFileOpenMode);
+  write_to_file_ = true;
   if (FLAG_ll_prof) {
     // Open a file for logging the contents of code objects so that
     // they can be disassembled later.
@@ -160,8 +250,6 @@
     memcpy(code_name.start() + name_len, kCodeLogExt, sizeof(kCodeLogExt));
     output_code_handle_ = OS::FOpen(code_name.start(), OS::LogFileOpenMode);
   }
-  Write = WriteToFile;
-  Init();
 }
 
 
@@ -170,24 +258,20 @@
   output_buffer_ = new LogDynamicBuffer(
       kDynamicBufferBlockSize, kMaxDynamicBufferSize,
       kDynamicBufferSeal, StrLength(kDynamicBufferSeal));
-  Write = WriteToMemory;
-  Init();
+  write_to_file_ = false;
 }
 
 
 void Log::Close() {
-  if (Write == WriteToFile) {
+  if (write_to_file_) {
     if (output_handle_ != NULL) fclose(output_handle_);
     output_handle_ = NULL;
     if (output_code_handle_ != NULL) fclose(output_code_handle_);
     output_code_handle_ = NULL;
-  } else if (Write == WriteToMemory) {
+  } else {
     delete output_buffer_;
     output_buffer_ = NULL;
-  } else {
-    ASSERT(Write == NULL);
   }
-  Write = NULL;
 
   DeleteArray(message_buffer_);
   message_buffer_ = NULL;
@@ -200,7 +284,7 @@
 
 
 int Log::GetLogLines(int from_pos, char* dest_buf, int max_size) {
-  if (Write != WriteToMemory) return 0;
+  if (write_to_file_) return 0;
   ASSERT(output_buffer_ != NULL);
   ASSERT(from_pos >= 0);
   ASSERT(max_size >= 0);
@@ -220,17 +304,16 @@
 }
 
 
-LogMessageBuilder::WriteFailureHandler
-    LogMessageBuilder::write_failure_handler = NULL;
-
-
-LogMessageBuilder::LogMessageBuilder(): sl(Log::mutex_), pos_(0) {
-  ASSERT(Log::message_buffer_ != NULL);
+LogMessageBuilder::LogMessageBuilder(Logger* logger)
+  : log_(logger->log_),
+    sl(log_->mutex_),
+    pos_(0) {
+  ASSERT(log_->message_buffer_ != NULL);
 }
 
 
 void LogMessageBuilder::Append(const char* format, ...) {
-  Vector<char> buf(Log::message_buffer_ + pos_,
+  Vector<char> buf(log_->message_buffer_ + pos_,
                    Log::kMessageBufferSize - pos_);
   va_list args;
   va_start(args, format);
@@ -241,7 +324,7 @@
 
 
 void LogMessageBuilder::AppendVA(const char* format, va_list args) {
-  Vector<char> buf(Log::message_buffer_ + pos_,
+  Vector<char> buf(log_->message_buffer_ + pos_,
                    Log::kMessageBufferSize - pos_);
   int result = v8::internal::OS::VSNPrintF(buf, format, args);
 
@@ -257,7 +340,7 @@
 
 void LogMessageBuilder::Append(const char c) {
   if (pos_ < Log::kMessageBufferSize) {
-    Log::message_buffer_[pos_++] = c;
+    log_->message_buffer_[pos_++] = c;
   }
   ASSERT(pos_ <= Log::kMessageBufferSize);
 }
@@ -315,7 +398,7 @@
     ASSERT(len >= 0);
     if (len == 0) return;
   }
-  Vector<char> buf(Log::message_buffer_ + pos_,
+  Vector<char> buf(log_->message_buffer_ + pos_,
                    Log::kMessageBufferSize - pos_);
   OS::StrNCpy(buf, str, len);
   pos_ += len;
@@ -325,12 +408,16 @@
 
 void LogMessageBuilder::WriteToLogFile() {
   ASSERT(pos_ <= Log::kMessageBufferSize);
-  const int written = Log::Write(Log::message_buffer_, pos_);
-  if (written != pos_ && write_failure_handler != NULL) {
-    write_failure_handler();
+  const int written = log_->write_to_file_ ?
+      log_->WriteToFile(log_->message_buffer_, pos_) :
+      log_->WriteToMemory(log_->message_buffer_, pos_);
+  if (written != pos_) {
+    log_->stop();
+    log_->logger_->LogFailure();
   }
 }
 
+
 #endif  // ENABLE_LOGGING_AND_PROFILING
 
 } }  // namespace v8::internal
diff --git a/src/log-utils.h b/src/log-utils.h
index 719d370..255c73c 100644
--- a/src/log-utils.h
+++ b/src/log-utils.h
@@ -33,6 +33,8 @@
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
 
+class Logger;
+
 // A memory buffer that increments its size as you write in it.  Size
 // is incremented with 'block_size' steps, never exceeding 'max_size'.
 // During growth, memory contents are never copied.  At the end of the
@@ -89,28 +91,23 @@
 
 
 // Functions and data for performing output of log messages.
-class Log : public AllStatic {
+class Log {
  public:
-  // Opens stdout for logging.
-  static void OpenStdout();
 
-  // Opens file for logging.
-  static void OpenFile(const char* name);
-
-  // Opens memory buffer for logging.
-  static void OpenMemoryBuffer();
+  // Performs process-wide initialization.
+  void Initialize();
 
   // Disables logging, but preserves acquired resources.
-  static void stop() { is_stopped_ = true; }
+  void stop() { is_stopped_ = true; }
 
-  // Frees all resources acquired in Open... functions.
-  static void Close();
+  // Frees all resources acquired in Initialize and Open... functions.
+  void Close();
 
   // See description in include/v8.h.
-  static int GetLogLines(int from_pos, char* dest_buf, int max_size);
+  int GetLogLines(int from_pos, char* dest_buf, int max_size);
 
   // Returns whether logging is enabled.
-  static bool IsEnabled() {
+  bool IsEnabled() {
     return !is_stopped_ && (output_handle_ != NULL || output_buffer_ != NULL);
   }
 
@@ -118,16 +115,19 @@
   static const int kMessageBufferSize = v8::V8::kMinimumSizeForLogLinesBuffer;
 
  private:
-  typedef int (*WritePtr)(const char* msg, int length);
+  explicit Log(Logger* logger);
 
-  // Initialization function called from Open... functions.
-  static void Init();
+  // Opens stdout for logging.
+  void OpenStdout();
 
-  // Write functions assume that mutex_ is acquired by the caller.
-  static WritePtr Write;
+  // Opens file for logging.
+  void OpenFile(const char* name);
+
+  // Opens memory buffer for logging.
+  void OpenMemoryBuffer();
 
   // Implementation of writing to a log file.
-  static int WriteToFile(const char* msg, int length) {
+  int WriteToFile(const char* msg, int length) {
     ASSERT(output_handle_ != NULL);
     size_t rv = fwrite(msg, 1, length, output_handle_);
     ASSERT(static_cast<size_t>(length) == rv);
@@ -137,25 +137,27 @@
   }
 
   // Implementation of writing to a memory buffer.
-  static int WriteToMemory(const char* msg, int length) {
+  int WriteToMemory(const char* msg, int length) {
     ASSERT(output_buffer_ != NULL);
     return output_buffer_->Write(msg, length);
   }
 
+  bool write_to_file_;
+
   // Whether logging is stopped (e.g. due to insufficient resources).
-  static bool is_stopped_;
+  bool is_stopped_;
 
   // When logging is active, either output_handle_ or output_buffer_ is used
   // to store a pointer to log destination. If logging was opened via OpenStdout
   // or OpenFile, then output_handle_ is used. If logging was opened
   // via OpenMemoryBuffer, then output_buffer_ is used.
   // mutex_ should be acquired before using output_handle_ or output_buffer_.
-  static FILE* output_handle_;
+  FILE* output_handle_;
 
   // Used when low-level profiling is active to save code object contents.
-  static FILE* output_code_handle_;
+  FILE* output_code_handle_;
 
-  static LogDynamicBuffer* output_buffer_;
+  LogDynamicBuffer* output_buffer_;
 
   // Size of dynamic buffer block (and dynamic buffer initial size).
   static const int kDynamicBufferBlockSize = 65536;
@@ -164,15 +166,17 @@
   static const int kMaxDynamicBufferSize = 50 * 1024 * 1024;
 
   // Message to "seal" dynamic buffer with.
-  static const char* kDynamicBufferSeal;
+  static const char* const kDynamicBufferSeal;
 
   // mutex_ is a Mutex used for enforcing exclusive
   // access to the formatting buffer and the log file or log memory buffer.
-  static Mutex* mutex_;
+  Mutex* mutex_;
 
   // Buffer used for formatting log messages. This is a singleton buffer and
   // mutex_ should be acquired before using it.
-  static char* message_buffer_;
+  char* message_buffer_;
+
+  Logger* logger_;
 
   friend class Logger;
   friend class LogMessageBuilder;
@@ -185,7 +189,7 @@
  public:
   // Create a message builder starting from position 0. This acquires the mutex
   // in the log as well.
-  explicit LogMessageBuilder();
+  explicit LogMessageBuilder(Logger* logger);
   ~LogMessageBuilder() { }
 
   // Append string data to the log message.
@@ -211,16 +215,9 @@
   // Write the log message to the log file currently opened.
   void WriteToLogFile();
 
-  // A handler that is called when Log::Write fails.
-  typedef void (*WriteFailureHandler)();
-
-  static void set_write_failure_handler(WriteFailureHandler handler) {
-    write_failure_handler = handler;
-  }
-
  private:
-  static WriteFailureHandler write_failure_handler;
 
+  Log* log_;
   ScopedLock sl;
   int pos_;
 };
diff --git a/src/log.cc b/src/log.cc
index 16aeadb..6991f3d 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -52,24 +52,25 @@
 //
 class SlidingStateWindow {
  public:
-  SlidingStateWindow();
+  explicit SlidingStateWindow(Isolate* isolate);
   ~SlidingStateWindow();
   void AddState(StateTag state);
 
  private:
   static const int kBufferSize = 256;
+  Counters* counters_;
   int current_index_;
   bool is_full_;
   byte buffer_[kBufferSize];
 
 
   void IncrementStateCounter(StateTag state) {
-    Counters::state_counters[state].Increment();
+    counters_->state_counters(state)->Increment();
   }
 
 
   void DecrementStateCounter(StateTag state) {
-    Counters::state_counters[state].Decrement();
+    counters_->state_counters(state)->Decrement();
   }
 };
 
@@ -82,7 +83,7 @@
 //
 class Profiler: public Thread {
  public:
-  Profiler();
+  explicit Profiler(Isolate* isolate);
   void Engage();
   void Disengage();
 
@@ -113,9 +114,9 @@
   void Run();
 
   // Pause and Resume TickSample data collection.
-  static bool paused() { return paused_; }
-  static void pause() { paused_ = true; }
-  static void resume() { paused_ = false; }
+  bool paused() const { return paused_; }
+  void pause() { paused_ = true; }
+  void resume() { paused_ = false; }
 
  private:
   // Returns the next index in the cyclic buffer.
@@ -137,43 +138,44 @@
   bool running_;
 
   // Tells whether we are currently recording tick samples.
-  static bool paused_;
+  bool paused_;
 };
 
-bool Profiler::paused_ = false;
-
 
 //
 // StackTracer implementation
 //
-void StackTracer::Trace(TickSample* sample) {
+void StackTracer::Trace(Isolate* isolate, TickSample* sample) {
+  ASSERT(isolate->IsInitialized());
+
   sample->tos = NULL;
   sample->frames_count = 0;
 
   // Avoid collecting traces while doing GC.
   if (sample->state == GC) return;
 
-  const Address js_entry_sp = Top::js_entry_sp(Top::GetCurrentThread());
+  const Address js_entry_sp =
+      Isolate::js_entry_sp(isolate->thread_local_top());
   if (js_entry_sp == 0) {
     // Not executing JS now.
     return;
   }
 
-  // Sample potential return address value for frameless invocation of
-  // stubs (we'll figure out later, if this value makes sense).
-  sample->tos = Memory::Address_at(sample->sp);
-
-  int i = 0;
-  const Address callback = Top::external_callback();
-  // Surprisingly, PC can point _exactly_ to callback start, with good
-  // probability, and this will result in reporting fake nested
-  // callback call.
-  if (callback != NULL && callback != sample->pc) {
-    sample->stack[i++] = callback;
+  const Address callback = isolate->external_callback();
+  if (callback != NULL) {
+    sample->external_callback = callback;
+    sample->has_external_callback = true;
+  } else {
+    // Sample potential return address value for frameless invocation of
+    // stubs (we'll figure out later, if this value makes sense).
+    sample->tos = Memory::Address_at(sample->sp);
+    sample->has_external_callback = false;
   }
 
-  SafeStackTraceFrameIterator it(sample->fp, sample->sp,
+  SafeStackTraceFrameIterator it(isolate,
+                                 sample->fp, sample->sp,
                                  sample->sp, js_entry_sp);
+  int i = 0;
   while (!it.done() && i < TickSample::kMaxFramesCount) {
     sample->stack[i++] = it.frame()->pc();
     it.Advance();
@@ -188,8 +190,8 @@
 //
 class Ticker: public Sampler {
  public:
-  explicit Ticker(int interval) :
-      Sampler(interval),
+  explicit Ticker(Isolate* isolate, int interval):
+      Sampler(isolate, interval),
       window_(NULL),
       profiler_(NULL) {}
 
@@ -225,7 +227,7 @@
 
  protected:
   virtual void DoSampleStack(TickSample* sample) {
-    StackTracer::Trace(sample);
+    StackTracer::Trace(isolate(), sample);
   }
 
  private:
@@ -237,16 +239,17 @@
 //
 // SlidingStateWindow implementation.
 //
-SlidingStateWindow::SlidingStateWindow(): current_index_(0), is_full_(false) {
+SlidingStateWindow::SlidingStateWindow(Isolate* isolate)
+    : counters_(isolate->counters()), current_index_(0), is_full_(false) {
   for (int i = 0; i < kBufferSize; i++) {
     buffer_[i] = static_cast<byte>(OTHER);
   }
-  Logger::ticker_->SetWindow(this);
+  isolate->logger()->ticker_->SetWindow(this);
 }
 
 
 SlidingStateWindow::~SlidingStateWindow() {
-  Logger::ticker_->ClearWindow();
+  LOGGER->ticker_->ClearWindow();
 }
 
 
@@ -266,14 +269,15 @@
 //
 // Profiler implementation.
 //
-Profiler::Profiler()
-    : Thread("v8:Profiler"),
+Profiler::Profiler(Isolate* isolate)
+    : Thread(isolate, "v8:Profiler"),
       head_(0),
       tail_(0),
       overflow_(false),
       buffer_semaphore_(OS::CreateSemaphore(0)),
       engaged_(false),
-      running_(false) {
+      running_(false),
+      paused_(false) {
 }
 
 
@@ -292,9 +296,9 @@
   Start();
 
   // Register to get ticks.
-  Logger::ticker_->SetProfiler(this);
+  LOGGER->ticker_->SetProfiler(this);
 
-  Logger::ProfilerBeginEvent();
+  LOGGER->ProfilerBeginEvent();
 }
 
 
@@ -302,7 +306,7 @@
   if (!engaged_) return;
 
   // Stop receiving ticks.
-  Logger::ticker_->ClearProfiler();
+  LOGGER->ticker_->ClearProfiler();
 
   // Terminate the worker thread by setting running_ to false,
   // inserting a fake element in the queue and then wait for
@@ -314,15 +318,16 @@
   Insert(&sample);
   Join();
 
-  LOG(UncheckedStringEvent("profiler", "end"));
+  LOG(ISOLATE, UncheckedStringEvent("profiler", "end"));
 }
 
 
 void Profiler::Run() {
   TickSample sample;
   bool overflow = Remove(&sample);
+  i::Isolate* isolate = ISOLATE;
   while (running_) {
-    LOG(TickEvent(&sample, overflow));
+    LOG(isolate, TickEvent(&sample, overflow));
     overflow = Remove(&sample);
   }
 }
@@ -331,23 +336,38 @@
 //
 // Logger class implementation.
 //
-Ticker* Logger::ticker_ = NULL;
-Profiler* Logger::profiler_ = NULL;
-SlidingStateWindow* Logger::sliding_state_window_ = NULL;
-int Logger::logging_nesting_ = 0;
-int Logger::cpu_profiler_nesting_ = 0;
-int Logger::heap_profiler_nesting_ = 0;
+
+Logger::Logger()
+  : ticker_(NULL),
+    profiler_(NULL),
+    sliding_state_window_(NULL),
+    log_events_(NULL),
+    logging_nesting_(0),
+    cpu_profiler_nesting_(0),
+    heap_profiler_nesting_(0),
+    log_(new Log(this)),
+    is_initialized_(false),
+    last_address_(NULL),
+    prev_sp_(NULL),
+    prev_function_(NULL),
+    prev_to_(NULL),
+    prev_code_(NULL) {
+}
+
+Logger::~Logger() {
+  delete log_;
+}
 
 #define DECLARE_EVENT(ignore1, name) name,
-const char* kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = {
+static const char* const kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = {
   LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT)
 };
 #undef DECLARE_EVENT
 
 
 void Logger::ProfilerBeginEvent() {
-  if (!Log::IsEnabled()) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled()) return;
+  LogMessageBuilder msg(this);
   msg.Append("profiler,\"begin\",%d\n", kSamplingIntervalMs);
   msg.WriteToLogFile();
 }
@@ -364,8 +384,8 @@
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
 void Logger::UncheckedStringEvent(const char* name, const char* value) {
-  if (!Log::IsEnabled()) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled()) return;
+  LogMessageBuilder msg(this);
   msg.Append("%s,\"%s\"\n", name, value);
   msg.WriteToLogFile();
 }
@@ -388,8 +408,8 @@
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
 void Logger::UncheckedIntEvent(const char* name, int value) {
-  if (!Log::IsEnabled()) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled()) return;
+  LogMessageBuilder msg(this);
   msg.Append("%s,%d\n", name, value);
   msg.WriteToLogFile();
 }
@@ -398,8 +418,8 @@
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
 void Logger::UncheckedIntPtrTEvent(const char* name, intptr_t value) {
-  if (!Log::IsEnabled()) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled()) return;
+  LogMessageBuilder msg(this);
   msg.Append("%s,%" V8_PTR_PREFIX "d\n", name, value);
   msg.WriteToLogFile();
 }
@@ -408,8 +428,8 @@
 
 void Logger::HandleEvent(const char* name, Object** location) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_handles) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_handles) return;
+  LogMessageBuilder msg(this);
   msg.Append("%s,0x%" V8PRIxPTR "\n", name, location);
   msg.WriteToLogFile();
 #endif
@@ -421,8 +441,8 @@
 // caller's responsibility to ensure that log is enabled and that
 // FLAG_log_api is true.
 void Logger::ApiEvent(const char* format, ...) {
-  ASSERT(Log::IsEnabled() && FLAG_log_api);
-  LogMessageBuilder msg;
+  ASSERT(log_->IsEnabled() && FLAG_log_api);
+  LogMessageBuilder msg(this);
   va_list ap;
   va_start(ap, format);
   msg.AppendVA(format, ap);
@@ -434,7 +454,7 @@
 
 void Logger::ApiNamedSecurityCheck(Object* key) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_api) return;
+  if (!log_->IsEnabled() || !FLAG_log_api) return;
   if (key->IsString()) {
     SmartPointer<char> str =
         String::cast(key)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
@@ -452,8 +472,8 @@
                                 uintptr_t start,
                                 uintptr_t end) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_prof) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_prof) return;
+  LogMessageBuilder msg(this);
   msg.Append("shared-library,\"%s\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR "\n",
              library_path,
              start,
@@ -467,8 +487,8 @@
                                 uintptr_t start,
                                 uintptr_t end) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_prof) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_prof) return;
+  LogMessageBuilder msg(this);
   msg.Append("shared-library,\"%ls\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR "\n",
              library_path,
              start,
@@ -482,7 +502,7 @@
 void Logger::LogRegExpSource(Handle<JSRegExp> regexp) {
   // Prints "/" + re.source + "/" +
   //      (re.global?"g":"") + (re.ignorecase?"i":"") + (re.multiline?"m":"")
-  LogMessageBuilder msg;
+  LogMessageBuilder msg(this);
 
   Handle<Object> source = GetProperty(regexp, "source");
   if (!source->IsString()) {
@@ -524,8 +544,8 @@
 
 void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_regexp) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_regexp) return;
+  LogMessageBuilder msg(this);
   msg.Append("regexp-compile,");
   LogRegExpSource(regexp);
   msg.Append(in_cache ? ",hit\n" : ",miss\n");
@@ -536,9 +556,9 @@
 
 void Logger::LogRuntime(Vector<const char> format, JSArray* args) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_runtime) return;
+  if (!log_->IsEnabled() || !FLAG_log_runtime) return;
   HandleScope scope;
-  LogMessageBuilder msg;
+  LogMessageBuilder msg(this);
   for (int i = 0; i < format.length(); i++) {
     char c = format[i];
     if (c == '%' && i <= format.length() - 2) {
@@ -582,7 +602,7 @@
 
 void Logger::ApiIndexedSecurityCheck(uint32_t index) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_api) return;
+  if (!log_->IsEnabled() || !FLAG_log_api) return;
   ApiEvent("api,check-security,%u\n", index);
 #endif
 }
@@ -593,13 +613,13 @@
                                     Object* name) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
   ASSERT(name->IsString());
-  if (!Log::IsEnabled() || !FLAG_log_api) return;
+  if (!log_->IsEnabled() || !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);
+  ApiEvent("api,%s,\"%s\",\"%s\"\n", tag, *class_name, *property_name);
 #endif
 }
 
@@ -607,37 +627,37 @@
                                       JSObject* holder,
                                       uint32_t index) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_api) return;
+  if (!log_->IsEnabled() || !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);
+  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 (!Log::IsEnabled() || !FLAG_log_api) return;
+  if (!log_->IsEnabled() || !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);
+  ApiEvent("api,%s,\"%s\"\n", tag, *class_name);
 #endif
 }
 
 
 void Logger::ApiEntryCall(const char* name) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_api) return;
-  Logger::ApiEvent("api,%s\n", name);
+  if (!log_->IsEnabled() || !FLAG_log_api) return;
+  ApiEvent("api,%s\n", name);
 #endif
 }
 
 
 void Logger::NewEvent(const char* name, void* object, size_t size) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log) return;
+  LogMessageBuilder msg(this);
   msg.Append("new,%s,0x%" V8PRIxPTR ",%u\n", name, object,
              static_cast<unsigned int>(size));
   msg.WriteToLogFile();
@@ -647,19 +667,28 @@
 
 void Logger::DeleteEvent(const char* name, void* object) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log) return;
+  LogMessageBuilder msg(this);
   msg.Append("delete,%s,0x%" V8PRIxPTR "\n", name, object);
   msg.WriteToLogFile();
 #endif
 }
 
 
+void Logger::NewEventStatic(const char* name, void* object, size_t size) {
+  LOGGER->NewEvent(name, object, size);
+}
+
+
+void Logger::DeleteEventStatic(const char* name, void* object) {
+  LOGGER->DeleteEvent(name, object);
+}
+
 #ifdef ENABLE_LOGGING_AND_PROFILING
 void Logger::CallbackEventInternal(const char* prefix, const char* name,
                                    Address entry_point) {
-  if (!Log::IsEnabled() || !FLAG_log_code) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_code) return;
+  LogMessageBuilder msg(this);
   msg.Append("%s,%s,",
              kLogEventsNames[CODE_CREATION_EVENT],
              kLogEventsNames[CALLBACK_TAG]);
@@ -673,7 +702,7 @@
 
 void Logger::CallbackEvent(String* name, Address entry_point) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_code) return;
+  if (!log_->IsEnabled() || !FLAG_log_code) return;
   SmartPointer<char> str =
       name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
   CallbackEventInternal("", *str, entry_point);
@@ -683,7 +712,7 @@
 
 void Logger::GetterCallbackEvent(String* name, Address entry_point) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_code) return;
+  if (!log_->IsEnabled() || !FLAG_log_code) return;
   SmartPointer<char> str =
       name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
   CallbackEventInternal("get ", *str, entry_point);
@@ -693,7 +722,7 @@
 
 void Logger::SetterCallbackEvent(String* name, Address entry_point) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_code) return;
+  if (!log_->IsEnabled() || !FLAG_log_code) return;
   SmartPointer<char> str =
       name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
   CallbackEventInternal("set ", *str, entry_point);
@@ -705,8 +734,8 @@
                              Code* code,
                              const char* comment) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_code) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_code) return;
+  LogMessageBuilder msg(this);
   msg.Append("%s,%s,",
              kLogEventsNames[CODE_CREATION_EVENT],
              kLogEventsNames[tag]);
@@ -758,9 +787,12 @@
                              SharedFunctionInfo* shared,
                              String* name) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_code) return;
-  if (code == Builtins::builtin(Builtins::LazyCompile)) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_code) return;
+  if (code == Isolate::Current()->builtins()->builtin(
+      Builtins::kLazyCompile))
+    return;
+
+  LogMessageBuilder msg(this);
   SmartPointer<char> str =
       name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
   msg.Append("%s,%s,",
@@ -785,8 +817,8 @@
                              SharedFunctionInfo* shared,
                              String* source, int line) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_code) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_code) return;
+  LogMessageBuilder msg(this);
   SmartPointer<char> name =
       shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
   SmartPointer<char> sourcestr =
@@ -811,8 +843,8 @@
 
 void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_code) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_code) return;
+  LogMessageBuilder msg(this);
   msg.Append("%s,%s,",
              kLogEventsNames[CODE_CREATION_EVENT],
              kLogEventsNames[tag]);
@@ -827,8 +859,8 @@
 
 void Logger::CodeMovingGCEvent() {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_code || !FLAG_ll_prof) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_code || !FLAG_ll_prof) return;
+  LogMessageBuilder msg(this);
   msg.Append("%s\n", kLogEventsNames[CODE_MOVING_GC]);
   msg.WriteToLogFile();
   OS::SignalCodeMovingGC();
@@ -838,8 +870,8 @@
 
 void Logger::RegExpCodeCreateEvent(Code* code, String* source) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_code) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_code) return;
+  LogMessageBuilder msg(this);
   msg.Append("%s,%s,",
              kLogEventsNames[CODE_CREATION_EVENT],
              kLogEventsNames[REG_EXP_TAG]);
@@ -870,8 +902,8 @@
 
 void Logger::SnapshotPositionEvent(Address addr, int pos) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_snapshot_positions) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_snapshot_positions) return;
+  LogMessageBuilder msg(this);
   msg.Append("%s,", kLogEventsNames[SNAPSHOT_POSITION_EVENT]);
   msg.AppendAddress(addr);
   msg.Append(",%d", pos);
@@ -881,9 +913,9 @@
 }
 
 
-void Logger::SFIMoveEvent(Address from, Address to) {
+void Logger::SharedFunctionInfoMoveEvent(Address from, Address to) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  MoveEventInternal(SFI_MOVE_EVENT, from, to);
+  MoveEventInternal(SHARED_FUNC_MOVE_EVENT, from, to);
 #endif
 }
 
@@ -892,8 +924,8 @@
 void Logger::MoveEventInternal(LogEventsAndTags event,
                                Address from,
                                Address to) {
-  if (!Log::IsEnabled() || !FLAG_log_code) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_code) return;
+  LogMessageBuilder msg(this);
   msg.Append("%s,", kLogEventsNames[event]);
   msg.AppendAddress(from);
   msg.Append(',');
@@ -906,8 +938,8 @@
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
 void Logger::DeleteEventInternal(LogEventsAndTags event, Address from) {
-  if (!Log::IsEnabled() || !FLAG_log_code) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_code) return;
+  LogMessageBuilder msg(this);
   msg.Append("%s,", kLogEventsNames[event]);
   msg.AppendAddress(from);
   msg.Append('\n');
@@ -918,8 +950,8 @@
 
 void Logger::ResourceEvent(const char* name, const char* tag) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log) return;
+  LogMessageBuilder msg(this);
   msg.Append("%s,%s,", name, tag);
 
   uint32_t sec, usec;
@@ -936,11 +968,11 @@
 
 void Logger::SuspectReadEvent(String* name, Object* obj) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_suspect) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_suspect) return;
+  LogMessageBuilder msg(this);
   String* class_name = obj->IsJSObject()
                        ? JSObject::cast(obj)->class_name()
-                       : Heap::empty_string();
+                       : HEAP->empty_string();
   msg.Append("suspect-read,");
   msg.Append(class_name);
   msg.Append(',');
@@ -955,8 +987,8 @@
 
 void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_gc) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_gc) return;
+  LogMessageBuilder msg(this);
   // Using non-relative system time in order to be able to synchronize with
   // external memory profiling events (e.g. DOM memory size).
   msg.Append("heap-sample-begin,\"%s\",\"%s\",%.0f\n",
@@ -969,8 +1001,8 @@
 void Logger::HeapSampleStats(const char* space, const char* kind,
                              intptr_t capacity, intptr_t used) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_gc) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_gc) return;
+  LogMessageBuilder msg(this);
   msg.Append("heap-sample-stats,\"%s\",\"%s\","
                  "%" V8_PTR_PREFIX "d,%" V8_PTR_PREFIX "d\n",
              space, kind, capacity, used);
@@ -981,8 +1013,8 @@
 
 void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_gc) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_gc) return;
+  LogMessageBuilder msg(this);
   msg.Append("heap-sample-end,\"%s\",\"%s\"\n", space, kind);
   msg.WriteToLogFile();
 #endif
@@ -991,8 +1023,8 @@
 
 void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_gc) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_gc) return;
+  LogMessageBuilder msg(this);
   msg.Append("heap-sample-item,%s,%d,%d\n", type, number, bytes);
   msg.WriteToLogFile();
 #endif
@@ -1002,32 +1034,32 @@
 void Logger::HeapSampleJSConstructorEvent(const char* constructor,
                                           int number, int bytes) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_gc) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_gc) return;
+  LogMessageBuilder msg(this);
   msg.Append("heap-js-cons-item,%s,%d,%d\n", constructor, number, bytes);
   msg.WriteToLogFile();
 #endif
 }
 
+// Event starts with comma, so we don't have it in the format string.
+static const char kEventText[] = "heap-js-ret-item,%s";
+// We take placeholder strings into account, but it's OK to be conservative.
+static const int kEventTextLen = sizeof(kEventText)/sizeof(kEventText[0]);
 
 void Logger::HeapSampleJSRetainersEvent(
     const char* constructor, const char* event) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_gc) return;
-  // Event starts with comma, so we don't have it in the format string.
-  static const char* event_text = "heap-js-ret-item,%s";
-  // We take placeholder strings into account, but it's OK to be conservative.
-  static const int event_text_len = StrLength(event_text);
+  if (!log_->IsEnabled() || !FLAG_log_gc) return;
   const int cons_len = StrLength(constructor);
   const int event_len = StrLength(event);
   int pos = 0;
   // Retainer lists can be long. We may need to split them into multiple events.
   do {
-    LogMessageBuilder msg;
-    msg.Append(event_text, constructor);
+    LogMessageBuilder msg(this);
+    msg.Append(kEventText, constructor);
     int to_write = event_len - pos;
-    if (to_write > Log::kMessageBufferSize - (cons_len + event_text_len)) {
-      int cut_pos = pos + Log::kMessageBufferSize - (cons_len + event_text_len);
+    if (to_write > Log::kMessageBufferSize - (cons_len + kEventTextLen)) {
+      int cut_pos = pos + Log::kMessageBufferSize - (cons_len + kEventTextLen);
       ASSERT(cut_pos < event_len);
       while (cut_pos > pos && event[cut_pos] != ',') --cut_pos;
       if (event[cut_pos] != ',') {
@@ -1053,8 +1085,8 @@
 void Logger::HeapSampleJSProducerEvent(const char* constructor,
                                        Address* stack) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_gc) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log_gc) return;
+  LogMessageBuilder msg(this);
   msg.Append("heap-js-prod-item,%s", constructor);
   while (*stack != NULL) {
     msg.Append(",0x%" V8PRIxPTR, *stack++);
@@ -1067,8 +1099,8 @@
 
 void Logger::DebugTag(const char* call_site_tag) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_log) return;
+  LogMessageBuilder msg(this);
   msg.Append("debug-tag,%s\n", call_site_tag);
   msg.WriteToLogFile();
 #endif
@@ -1077,13 +1109,13 @@
 
 void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log) return;
+  if (!log_->IsEnabled() || !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;
+  LogMessageBuilder msg(this);
   msg.Append("debug-queue-event,%s,%15.3f,%s\n",
              event_type,
              OS::TimeCurrentMillis(),
@@ -1096,14 +1128,19 @@
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
 void Logger::TickEvent(TickSample* sample, bool overflow) {
-  if (!Log::IsEnabled() || !FLAG_prof) return;
-  LogMessageBuilder msg;
+  if (!log_->IsEnabled() || !FLAG_prof) return;
+  LogMessageBuilder msg(this);
   msg.Append("%s,", kLogEventsNames[TICK_EVENT]);
   msg.AppendAddress(sample->pc);
   msg.Append(',');
   msg.AppendAddress(sample->sp);
-  msg.Append(',');
-  msg.AppendAddress(sample->tos);
+  if (sample->has_external_callback) {
+    msg.Append(",1,");
+    msg.AppendAddress(sample->external_callback);
+  } else {
+    msg.Append(",0,");
+    msg.AppendAddress(sample->tos);
+  }
   msg.Append(",%d", static_cast<int>(sample->state));
   if (overflow) {
     msg.Append(",overflow");
@@ -1130,7 +1167,7 @@
 
 
 void Logger::PauseProfiler(int flags, int tag) {
-  if (!Log::IsEnabled()) return;
+  if (!log_->IsEnabled()) return;
   if (profiler_ != NULL && (flags & PROFILER_MODULE_CPU)) {
     // It is OK to have negative nesting.
     if (--cpu_profiler_nesting_ == 0) {
@@ -1141,7 +1178,7 @@
         }
         FLAG_log_code = false;
         // Must be the same message as Log::kDynamicBufferSeal.
-        LOG(UncheckedStringEvent("profiler", "pause"));
+        LOG(ISOLATE, UncheckedStringEvent("profiler", "pause"));
       }
       --logging_nesting_;
     }
@@ -1160,7 +1197,7 @@
 
 
 void Logger::ResumeProfiler(int flags, int tag) {
-  if (!Log::IsEnabled()) return;
+  if (!log_->IsEnabled()) return;
   if (tag != 0) {
     UncheckedIntEvent("open-tag", tag);
   }
@@ -1169,7 +1206,7 @@
       ++logging_nesting_;
       if (FLAG_prof_lazy) {
         profiler_->Engage();
-        LOG(UncheckedStringEvent("profiler", "resume"));
+        LOG(ISOLATE, UncheckedStringEvent("profiler", "resume"));
         FLAG_log_code = true;
         LogCompiledFunctions();
         LogAccessorCallbacks();
@@ -1192,8 +1229,7 @@
 
 // This function can be called when Log's mutex is acquired,
 // either from main or Profiler's thread.
-void Logger::StopLoggingAndProfiling() {
-  Log::stop();
+void Logger::LogFailure() {
   PauseProfiler(PROFILER_MODULE_CPU, 0);
 }
 
@@ -1204,7 +1240,7 @@
 
 
 int Logger::GetLogLines(int from_pos, char* dest_buf, int max_size) {
-  return Log::GetLogLines(from_pos, dest_buf, max_size);
+  return log_->GetLogLines(from_pos, dest_buf, max_size);
 }
 
 
@@ -1297,6 +1333,10 @@
         description = "A keyed load IC from the snapshot";
         tag = Logger::KEYED_LOAD_IC_TAG;
         break;
+      case Code::KEYED_EXTERNAL_ARRAY_LOAD_IC:
+        description = "A keyed external array load IC from the snapshot";
+        tag = Logger::KEYED_EXTERNAL_ARRAY_LOAD_IC_TAG;
+        break;
       case Code::LOAD_IC:
         description = "A load IC from the snapshot";
         tag = Logger::LOAD_IC_TAG;
@@ -1309,6 +1349,10 @@
         description = "A keyed store IC from the snapshot";
         tag = Logger::KEYED_STORE_IC_TAG;
         break;
+      case Code::KEYED_EXTERNAL_ARRAY_STORE_IC:
+        description = "A keyed external array store IC from the snapshot";
+        tag = Logger::KEYED_EXTERNAL_ARRAY_STORE_IC_TAG;
+        break;
       case Code::CALL_IC:
         description = "A call IC from the snapshot";
         tag = Logger::CALL_IC_TAG;
@@ -1318,14 +1362,14 @@
         tag = Logger::KEYED_CALL_IC_TAG;
         break;
     }
-    PROFILE(CodeCreateEvent(tag, code_object, description));
+    PROFILE(ISOLATE, CodeCreateEvent(tag, code_object, description));
   }
 }
 
 
 void Logger::LogCodeInfo() {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  if (!Log::IsEnabled() || !FLAG_log_code || !FLAG_ll_prof) return;
+  if (!log_->IsEnabled() || !FLAG_log_code || !FLAG_ll_prof) return;
 #if V8_TARGET_ARCH_IA32
   const char arch[] = "ia32";
 #elif V8_TARGET_ARCH_X64
@@ -1335,7 +1379,7 @@
 #else
   const char arch[] = "unknown";
 #endif
-  LogMessageBuilder msg;
+  LogMessageBuilder msg(this);
   msg.Append("code-info,%s,%d\n", arch, Code::kHeaderSize);
   msg.WriteToLogFile();
 #endif  // ENABLE_LOGGING_AND_PROFILING
@@ -1343,10 +1387,10 @@
 
 
 void Logger::LowLevelCodeCreateEvent(Code* code, LogMessageBuilder* msg) {
-  if (!FLAG_ll_prof || Log::output_code_handle_ == NULL) return;
-  int pos = static_cast<int>(ftell(Log::output_code_handle_));
+  if (!FLAG_ll_prof || log_->output_code_handle_ == NULL) return;
+  int pos = static_cast<int>(ftell(log_->output_code_handle_));
   size_t rv = fwrite(code->instruction_start(), 1, code->instruction_size(),
-                     Log::output_code_handle_);
+                     log_->output_code_handle_);
   ASSERT(static_cast<size_t>(code->instruction_size()) == rv);
   USE(rv);
   msg->Append(",%d", pos);
@@ -1372,7 +1416,9 @@
   // During iteration, there can be heap allocation due to
   // GetScriptLineNumber call.
   for (int i = 0; i < compiled_funcs_count; ++i) {
-    if (*code_objects[i] == Builtins::builtin(Builtins::LazyCompile)) continue;
+    if (*code_objects[i] == Isolate::Current()->builtins()->builtin(
+        Builtins::kLazyCompile))
+      continue;
     Handle<SharedFunctionInfo> shared = sfis[i];
     Handle<String> func_name(shared->DebugName());
     if (shared->script()->IsScript()) {
@@ -1381,20 +1427,23 @@
         Handle<String> script_name(String::cast(script->name()));
         int line_num = GetScriptLineNumber(script, shared->start_position());
         if (line_num > 0) {
-          PROFILE(CodeCreateEvent(
-              Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
-              *code_objects[i], *shared,
-              *script_name, line_num + 1));
+          PROFILE(ISOLATE,
+                  CodeCreateEvent(
+                    Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
+                    *code_objects[i], *shared,
+                    *script_name, line_num + 1));
         } else {
           // Can't distinguish eval and script here, so always use Script.
-          PROFILE(CodeCreateEvent(
-              Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
-              *code_objects[i], *shared, *script_name));
+          PROFILE(ISOLATE,
+                  CodeCreateEvent(
+                      Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
+                      *code_objects[i], *shared, *script_name));
         }
       } else {
-        PROFILE(CodeCreateEvent(
-            Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
-            *code_objects[i], *shared, *func_name));
+        PROFILE(ISOLATE,
+                CodeCreateEvent(
+                    Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
+                    *code_objects[i], *shared, *func_name));
       }
     } else if (shared->IsApiFunction()) {
       // API function.
@@ -1404,11 +1453,13 @@
         CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
         Object* callback_obj = call_data->callback();
         Address entry_point = v8::ToCData<Address>(callback_obj);
-        PROFILE(CallbackEvent(*func_name, entry_point));
+        PROFILE(ISOLATE, CallbackEvent(*func_name, entry_point));
       }
     } else {
-      PROFILE(CodeCreateEvent(
-          Logger::LAZY_COMPILE_TAG, *code_objects[i], *shared, *func_name));
+      PROFILE(ISOLATE,
+              CodeCreateEvent(
+                  Logger::LAZY_COMPILE_TAG, *code_objects[i],
+                  *shared, *func_name));
     }
   }
 }
@@ -1417,6 +1468,7 @@
 void Logger::LogAccessorCallbacks() {
   AssertNoAllocation no_alloc;
   HeapIterator iterator;
+  i::Isolate* isolate = ISOLATE;
   for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
     if (!obj->IsAccessorInfo()) continue;
     AccessorInfo* ai = AccessorInfo::cast(obj);
@@ -1424,11 +1476,11 @@
     String* name = String::cast(ai->name());
     Address getter_entry = v8::ToCData<Address>(ai->getter());
     if (getter_entry != 0) {
-      PROFILE(GetterCallbackEvent(name, getter_entry));
+      PROFILE(isolate, GetterCallbackEvent(name, getter_entry));
     }
     Address setter_entry = v8::ToCData<Address>(ai->setter());
     if (setter_entry != 0) {
-      PROFILE(SetterCallbackEvent(name, setter_entry));
+      PROFILE(isolate, SetterCallbackEvent(name, setter_entry));
     }
   }
 }
@@ -1438,19 +1490,9 @@
 
 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;
+  // Tests and EnsureInitialize() can call this twice in a row. It's harmless.
+  if (is_initialized_) return true;
+  is_initialized_ = true;
 
   // --ll-prof implies --log-code and --log-snapshot-positions.
   if (FLAG_ll_prof) {
@@ -1464,73 +1506,31 @@
     FLAG_prof_auto = false;
   }
 
-  bool start_logging = 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;
+  // TODO(isolates): this assert introduces cyclic dependency (logger
+  // -> thread local top -> heap -> logger).
+  // ASSERT(VMState::is_outermost_external());
 
-  bool open_log_file = start_logging || FLAG_prof_lazy;
-
-  // If we're logging anything, we need to open the log file.
-  if (open_log_file) {
-    if (strcmp(FLAG_logfile, "-") == 0) {
-      Log::OpenStdout();
-    } else if (strcmp(FLAG_logfile, "*") == 0) {
-      Log::OpenMemoryBuffer();
-    } 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.
-              double time = OS::TimeCurrentMillis();
-              stream.Add("%.0f", FmtElm(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();
-      Log::OpenFile(*expanded);
-    } else {
-      Log::OpenFile(FLAG_logfile);
-    }
-  }
+  log_->Initialize();
 
   if (FLAG_ll_prof) LogCodeInfo();
 
-  ticker_ = new Ticker(kSamplingIntervalMs);
+  ticker_ = new Ticker(Isolate::Current(), kSamplingIntervalMs);
 
+  Isolate* isolate = Isolate::Current();
   if (FLAG_sliding_state_window && sliding_state_window_ == NULL) {
-    sliding_state_window_ = new SlidingStateWindow();
+    sliding_state_window_ = new SlidingStateWindow(isolate);
   }
 
+  bool start_logging = 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 (start_logging) {
     logging_nesting_ = 1;
   }
 
   if (FLAG_prof) {
-    profiler_ = new Profiler();
+    profiler_ = new Profiler(isolate);
     if (!FLAG_prof_auto) {
       profiler_->pause();
     } else {
@@ -1541,7 +1541,6 @@
     }
   }
 
-  LogMessageBuilder::set_write_failure_handler(StopLoggingAndProfiling);
   return true;
 
 #else
@@ -1550,6 +1549,11 @@
 }
 
 
+Sampler* Logger::sampler() {
+  return ticker_;
+}
+
+
 void Logger::EnsureTickerStarted() {
 #ifdef ENABLE_LOGGING_AND_PROFILING
   ASSERT(ticker_ != NULL);
@@ -1567,7 +1571,8 @@
 
 void Logger::TearDown() {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  LogMessageBuilder::set_write_failure_handler(NULL);
+  if (!is_initialized_) return;
+  is_initialized_ = false;
 
   // Stop the profiler before closing the file.
   if (profiler_ != NULL) {
@@ -1582,7 +1587,7 @@
   delete ticker_;
   ticker_ = NULL;
 
-  Log::Close();
+  log_->Close();
 #endif
 }
 
@@ -1600,9 +1605,61 @@
   // 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();
+    sliding_state_window_ = new SlidingStateWindow(Isolate::Current());
   }
 #endif
 }
 
+
+Mutex* SamplerRegistry::mutex_ = OS::CreateMutex();
+List<Sampler*>* SamplerRegistry::active_samplers_ = NULL;
+
+
+bool SamplerRegistry::IterateActiveSamplers(VisitSampler func, void* param) {
+  ScopedLock lock(mutex_);
+  for (int i = 0;
+       ActiveSamplersExist() && i < active_samplers_->length();
+       ++i) {
+    func(active_samplers_->at(i), param);
+  }
+  return ActiveSamplersExist();
+}
+
+
+static void ComputeCpuProfiling(Sampler* sampler, void* flag_ptr) {
+  bool* flag = reinterpret_cast<bool*>(flag_ptr);
+  *flag |= sampler->IsProfiling();
+}
+
+
+SamplerRegistry::State SamplerRegistry::GetState() {
+  bool flag = false;
+  if (!IterateActiveSamplers(&ComputeCpuProfiling, &flag)) {
+    return HAS_NO_SAMPLERS;
+  }
+  return flag ? HAS_CPU_PROFILING_SAMPLERS : HAS_SAMPLERS;
+}
+
+
+void SamplerRegistry::AddActiveSampler(Sampler* sampler) {
+  ASSERT(sampler->IsActive());
+  ScopedLock lock(mutex_);
+  if (active_samplers_ == NULL) {
+    active_samplers_ = new List<Sampler*>;
+  } else {
+    ASSERT(!active_samplers_->Contains(sampler));
+  }
+  active_samplers_->Add(sampler);
+}
+
+
+void SamplerRegistry::RemoveActiveSampler(Sampler* sampler) {
+  ASSERT(sampler->IsActive());
+  ScopedLock lock(mutex_);
+  ASSERT(active_samplers_ != NULL);
+  bool removed = active_samplers_->RemoveElement(sampler);
+  ASSERT(removed);
+  USE(removed);
+}
+
 } }  // namespace v8::internal
diff --git a/src/log.h b/src/log.h
index a808cd1..4fb0e23 100644
--- a/src/log.h
+++ b/src/log.h
@@ -77,13 +77,15 @@
 
 #undef LOG
 #ifdef ENABLE_LOGGING_AND_PROFILING
-#define LOG(Call)                           \
-  do {                                      \
-    if (v8::internal::Logger::is_logging()) \
-      v8::internal::Logger::Call;           \
+#define LOG(isolate, Call)                          \
+  do {                                              \
+    v8::internal::Logger* logger =                  \
+        (isolate)->logger();                        \
+    if (logger->is_logging())                       \
+      logger->Call;                                 \
   } while (false)
 #else
-#define LOG(Call) ((void) 0)
+#define LOG(isolate, Call) ((void) 0)
 #endif
 
 #define LOG_EVENTS_AND_TAGS_LIST(V) \
@@ -91,7 +93,7 @@
   V(CODE_MOVE_EVENT,                "code-move")                \
   V(CODE_DELETE_EVENT,              "code-delete")              \
   V(CODE_MOVING_GC,                 "code-moving-gc")           \
-  V(SFI_MOVE_EVENT,                 "sfi-move")                 \
+  V(SHARED_FUNC_MOVE_EVENT,         "sfi-move")                 \
   V(SNAPSHOT_POSITION_EVENT,        "snapshot-pos")             \
   V(TICK_EVENT,                     "tick")                     \
   V(REPEAT_META_EVENT,              "repeat")                   \
@@ -117,7 +119,9 @@
   V(EVAL_TAG,                       "Eval")                     \
   V(FUNCTION_TAG,                   "Function")                 \
   V(KEYED_LOAD_IC_TAG,              "KeyedLoadIC")              \
+  V(KEYED_EXTERNAL_ARRAY_LOAD_IC_TAG, "KeyedExternalArrayLoadIC") \
   V(KEYED_STORE_IC_TAG,             "KeyedStoreIC")             \
+  V(KEYED_EXTERNAL_ARRAY_STORE_IC_TAG, "KeyedExternalArrayStoreIC")\
   V(LAZY_COMPILE_TAG,               "LazyCompile")              \
   V(LOAD_IC_TAG,                    "LoadIC")                   \
   V(REG_EXP_TAG,                    "RegExp")                   \
@@ -131,6 +135,9 @@
 // original tags when writing to the log.
 
 
+class Sampler;
+
+
 class Logger {
  public:
 #define DECLARE_ENUM(enum_item, ignore) enum_item,
@@ -141,142 +148,147 @@
 #undef DECLARE_ENUM
 
   // Acquires resources for logging if the right flags are set.
-  static bool Setup();
+  bool Setup();
 
-  static void EnsureTickerStarted();
-  static void EnsureTickerStopped();
+  void EnsureTickerStarted();
+  void EnsureTickerStopped();
+
+  Sampler* sampler();
 
   // Frees resources acquired in Setup.
-  static void TearDown();
+  void TearDown();
 
   // Enable the computation of a sliding window of states.
-  static void EnableSlidingStateWindow();
+  void EnableSlidingStateWindow();
 
   // Emits an event with a string value -> (name, value).
-  static void StringEvent(const char* name, const char* value);
+  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);
-  static void IntPtrTEvent(const char* name, intptr_t value);
+  void IntEvent(const char* name, int value);
+  void IntPtrTEvent(const char* name, intptr_t value);
 
   // Emits an event with an handle value -> (name, location).
-  static void HandleEvent(const char* name, Object** location);
+  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);
+  void NewEvent(const char* name, void* object, size_t size);
+  void DeleteEvent(const char* name, void* object);
+
+  // Static versions of the above, operate on current isolate's logger.
+  // Used in TRACK_MEMORY(TypeName) defined in globals.h
+  static void NewEventStatic(const char* name, void* object, size_t size);
+  static void DeleteEventStatic(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);
+  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);
+  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);
+  void DebugTag(const char* call_site_tag);
+  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);
+  void ApiNamedSecurityCheck(Object* key);
+  void ApiIndexedSecurityCheck(uint32_t index);
+  void ApiNamedPropertyAccess(const char* tag, JSObject* holder, Object* name);
+  void ApiIndexedPropertyAccess(const char* tag,
+                                JSObject* holder,
+                                uint32_t index);
+  void ApiObjectAccess(const char* tag, JSObject* obj);
+  void ApiEntryCall(const char* name);
 
 
   // ==== Events logged by --log-code. ====
   // Emits a code event for a callback function.
-  static void CallbackEvent(String* name, Address entry_point);
-  static void GetterCallbackEvent(String* name, Address entry_point);
-  static void SetterCallbackEvent(String* name, Address entry_point);
+  void CallbackEvent(String* name, Address entry_point);
+  void GetterCallbackEvent(String* name, Address entry_point);
+  void SetterCallbackEvent(String* name, Address entry_point);
   // Emits a code create event.
-  static void CodeCreateEvent(LogEventsAndTags tag,
-                              Code* code, const char* source);
-  static void CodeCreateEvent(LogEventsAndTags tag,
-                              Code* code, String* name);
-  static void CodeCreateEvent(LogEventsAndTags tag,
-                              Code* code,
-                              SharedFunctionInfo* shared,
-                              String* name);
-  static void CodeCreateEvent(LogEventsAndTags tag,
-                              Code* code,
-                              SharedFunctionInfo* shared,
-                              String* source, int line);
-  static void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count);
-  static void CodeMovingGCEvent();
+  void CodeCreateEvent(LogEventsAndTags tag,
+                       Code* code, const char* source);
+  void CodeCreateEvent(LogEventsAndTags tag,
+                       Code* code, String* name);
+  void CodeCreateEvent(LogEventsAndTags tag,
+                       Code* code,
+                       SharedFunctionInfo* shared,
+                       String* name);
+  void CodeCreateEvent(LogEventsAndTags tag,
+                       Code* code,
+                       SharedFunctionInfo* shared,
+                       String* source, int line);
+  void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count);
+  void CodeMovingGCEvent();
   // Emits a code create event for a RegExp.
-  static void RegExpCodeCreateEvent(Code* code, String* source);
+  void RegExpCodeCreateEvent(Code* code, String* source);
   // Emits a code move event.
-  static void CodeMoveEvent(Address from, Address to);
+  void CodeMoveEvent(Address from, Address to);
   // Emits a code delete event.
-  static void CodeDeleteEvent(Address from);
+  void CodeDeleteEvent(Address from);
 
-  static void SFIMoveEvent(Address from, Address to);
+  void SharedFunctionInfoMoveEvent(Address from, Address to);
 
-  static void SnapshotPositionEvent(Address addr, int pos);
+  void SnapshotPositionEvent(Address addr, int pos);
 
   // ==== 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 HeapSampleJSConstructorEvent(const char* constructor,
-                                           int number, int bytes);
-  static void HeapSampleJSRetainersEvent(const char* constructor,
+  void HeapSampleBeginEvent(const char* space, const char* kind);
+  void HeapSampleEndEvent(const char* space, const char* kind);
+  void HeapSampleItemEvent(const char* type, int number, int bytes);
+  void HeapSampleJSConstructorEvent(const char* constructor,
+                                    int number, int bytes);
+  void HeapSampleJSRetainersEvent(const char* constructor,
                                          const char* event);
-  static void HeapSampleJSProducerEvent(const char* constructor,
-                                        Address* stack);
-  static void HeapSampleStats(const char* space, const char* kind,
-                              intptr_t capacity, intptr_t used);
+  void HeapSampleJSProducerEvent(const char* constructor,
+                                 Address* stack);
+  void HeapSampleStats(const char* space, const char* kind,
+                       intptr_t capacity, intptr_t used);
 
-  static void SharedLibraryEvent(const char* library_path,
-                                 uintptr_t start,
-                                 uintptr_t end);
-  static void SharedLibraryEvent(const wchar_t* library_path,
-                                 uintptr_t start,
-                                 uintptr_t end);
+  void SharedLibraryEvent(const char* library_path,
+                          uintptr_t start,
+                          uintptr_t end);
+  void SharedLibraryEvent(const wchar_t* library_path,
+                          uintptr_t start,
+                          uintptr_t end);
 
   // ==== Events logged by --log-regexp ====
   // Regexp compilation and execution events.
 
-  static void RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache);
+  void RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache);
 
   // Log an event reported from generated code
-  static void LogRuntime(Vector<const char> format, JSArray* args);
+  void LogRuntime(Vector<const char> format, JSArray* args);
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  static bool is_logging() {
+  bool is_logging() {
     return logging_nesting_ > 0;
   }
 
   // Pause/Resume collection of profiling data.
   // When data collection is paused, CPU Tick events are discarded until
   // data collection is Resumed.
-  static void PauseProfiler(int flags, int tag);
-  static void ResumeProfiler(int flags, int tag);
-  static int GetActiveProfilerModules();
+  void PauseProfiler(int flags, int tag);
+  void ResumeProfiler(int flags, int tag);
+  int GetActiveProfilerModules();
 
   // If logging is performed into a memory buffer, allows to
   // retrieve previously written messages. See v8.h.
-  static int GetLogLines(int from_pos, char* dest_buf, int max_size);
+  int GetLogLines(int from_pos, char* dest_buf, int max_size);
 
   // Logs all compiled functions found in the heap.
-  static void LogCompiledFunctions();
+  void LogCompiledFunctions();
   // Logs all accessor callbacks found in the heap.
-  static void LogAccessorCallbacks();
+  void LogAccessorCallbacks();
   // Used for logging stubs found in the snapshot.
-  static void LogCodeObjects();
+  void LogCodeObjects();
 
   // Converts tag to a corresponding NATIVE_... if the script is native.
   INLINE(static LogEventsAndTags ToNativeByScript(LogEventsAndTags, Script*));
@@ -284,70 +296,74 @@
   // Profiler's sampling interval (in milliseconds).
   static const int kSamplingIntervalMs = 1;
 
+  // Callback from Log, stops profiling in case of insufficient resources.
+  void LogFailure();
+
  private:
+  Logger();
+  ~Logger();
 
   // Emits the profiler's first message.
-  static void ProfilerBeginEvent();
+  void ProfilerBeginEvent();
 
   // Emits callback event messages.
-  static void CallbackEventInternal(const char* prefix,
-                                    const char* name,
-                                    Address entry_point);
+  void CallbackEventInternal(const char* prefix,
+                             const char* name,
+                             Address entry_point);
 
   // Internal configurable move event.
-  static void MoveEventInternal(LogEventsAndTags event,
-                                Address from,
-                                Address to);
+  void MoveEventInternal(LogEventsAndTags event, Address from, Address to);
 
   // Internal configurable move event.
-  static void DeleteEventInternal(LogEventsAndTags event,
-                                  Address from);
+  void DeleteEventInternal(LogEventsAndTags event, Address from);
 
   // Emits the source code of a regexp. Used by regexp events.
-  static void LogRegExpSource(Handle<JSRegExp> regexp);
+  void LogRegExpSource(Handle<JSRegExp> regexp);
 
   // Used for logging stubs found in the snapshot.
-  static void LogCodeObject(Object* code_object);
+  void LogCodeObject(Object* code_object);
 
   // Emits general information about generated code.
-  static void LogCodeInfo();
+  void LogCodeInfo();
 
   // Handles code creation when low-level profiling is active.
-  static void LowLevelCodeCreateEvent(Code* code, LogMessageBuilder* msg);
+  void LowLevelCodeCreateEvent(Code* code, LogMessageBuilder* msg);
 
   // Emits a profiler tick event. Used by the profiler thread.
-  static void TickEvent(TickSample* sample, bool overflow);
+  void TickEvent(TickSample* sample, bool overflow);
 
-  static void ApiEvent(const char* name, ...);
+  void ApiEvent(const char* name, ...);
 
   // Logs a StringEvent regardless of whether FLAG_log is true.
-  static void UncheckedStringEvent(const char* name, const char* value);
+  void UncheckedStringEvent(const char* name, const char* value);
 
   // Logs an IntEvent regardless of whether FLAG_log is true.
-  static void UncheckedIntEvent(const char* name, int value);
-  static void UncheckedIntPtrTEvent(const char* name, intptr_t value);
-
-  // Stops logging and profiling in case of insufficient resources.
-  static void StopLoggingAndProfiling();
+  void UncheckedIntEvent(const char* name, int value);
+  void UncheckedIntPtrTEvent(const char* name, intptr_t value);
 
   // Returns whether profiler's sampler is active.
-  static bool IsProfilerSamplerActive();
+  bool IsProfilerSamplerActive();
 
   // The sampler used by the profiler and the sliding state window.
-  static Ticker* ticker_;
+  Ticker* ticker_;
 
   // When the statistical profile is active, profiler_
   // points to a Profiler, that handles collection
   // of samples.
-  static Profiler* profiler_;
+  Profiler* profiler_;
 
   // SlidingStateWindow instance keeping a sliding window of the most
   // recent VM states.
-  static SlidingStateWindow* sliding_state_window_;
+  SlidingStateWindow* sliding_state_window_;
+
+  // An array of log events names.
+  const char* const* log_events_;
 
   // Internal implementation classes with access to
   // private members.
   friend class EventLog;
+  friend class Isolate;
+  friend class LogMessageBuilder;
   friend class TimeLog;
   friend class Profiler;
   friend class SlidingStateWindow;
@@ -356,21 +372,72 @@
 
   friend class LoggerTestHelper;
 
-  static int logging_nesting_;
-  static int cpu_profiler_nesting_;
-  static int heap_profiler_nesting_;
+
+  int logging_nesting_;
+  int cpu_profiler_nesting_;
+  int heap_profiler_nesting_;
+
+  Log* log_;
+
+  // Guards against multiple calls to TearDown() that can happen in some tests.
+  // 'true' between Setup() and TearDown().
+  bool is_initialized_;
+
+  // Support for 'incremental addresses' in compressed logs:
+  //  LogMessageBuilder::AppendAddress(Address addr)
+  Address last_address_;
+  //  Logger::TickEvent(...)
+  Address prev_sp_;
+  Address prev_function_;
+  //  Logger::MoveEventInternal(...)
+  Address prev_to_;
+  //  Logger::FunctionCreateEvent(...)
+  Address prev_code_;
 
   friend class CpuProfiler;
 #else
-  static bool is_logging() { return false; }
+  bool is_logging() { return false; }
 #endif
 };
 
 
+// Process wide registry of samplers.
+class SamplerRegistry : public AllStatic {
+ public:
+  enum State {
+    HAS_NO_SAMPLERS,
+    HAS_SAMPLERS,
+    HAS_CPU_PROFILING_SAMPLERS
+  };
+
+  typedef void (*VisitSampler)(Sampler*, void*);
+
+  static State GetState();
+
+  // Iterates over all active samplers keeping the internal lock held.
+  // Returns whether there are any active samplers.
+  static bool IterateActiveSamplers(VisitSampler func, void* param);
+
+  // Adds/Removes an active sampler.
+  static void AddActiveSampler(Sampler* sampler);
+  static void RemoveActiveSampler(Sampler* sampler);
+
+ private:
+  static bool ActiveSamplersExist() {
+    return active_samplers_ != NULL && !active_samplers_->is_empty();
+  }
+
+  static Mutex* mutex_;  // Protects the state below.
+  static List<Sampler*>* active_samplers_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(SamplerRegistry);
+};
+
+
 // Class that extracts stack trace, used for profiling.
 class StackTracer : public AllStatic {
  public:
-  static void Trace(TickSample* sample);
+  static void Trace(Isolate* isolate, TickSample* sample);
 };
 
 } }  // namespace v8::internal
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index a4c782c..1f73388 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -44,28 +44,27 @@
 // -------------------------------------------------------------------------
 // MarkCompactCollector
 
-bool MarkCompactCollector::force_compaction_ = false;
-bool MarkCompactCollector::compacting_collection_ = false;
-bool MarkCompactCollector::compact_on_next_gc_ = false;
-
-int MarkCompactCollector::previous_marked_count_ = 0;
-GCTracer* MarkCompactCollector::tracer_ = NULL;
-
-
+MarkCompactCollector::MarkCompactCollector() :  // NOLINT
 #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_size_ = 0;
-int MarkCompactCollector::live_old_data_objects_size_ = 0;
-int MarkCompactCollector::live_old_pointer_objects_size_ = 0;
-int MarkCompactCollector::live_code_objects_size_ = 0;
-int MarkCompactCollector::live_map_objects_size_ = 0;
-int MarkCompactCollector::live_cell_objects_size_ = 0;
-int MarkCompactCollector::live_lo_objects_size_ = 0;
+      state_(IDLE),
 #endif
+      force_compaction_(false),
+      compacting_collection_(false),
+      compact_on_next_gc_(false),
+      previous_marked_count_(0),
+      tracer_(NULL),
+#ifdef DEBUG
+      live_young_objects_size_(0),
+      live_old_pointer_objects_size_(0),
+      live_old_data_objects_size_(0),
+      live_code_objects_size_(0),
+      live_map_objects_size_(0),
+      live_cell_objects_size_(0),
+      live_lo_objects_size_(0),
+      live_bytes_(0),
+#endif
+      heap_(NULL),
+      code_flusher_(NULL) { }
 
 
 void MarkCompactCollector::CollectGarbage() {
@@ -87,15 +86,15 @@
     GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_COMPACT);
     EncodeForwardingAddresses();
 
-    Heap::MarkMapPointersAsEncoded(true);
+    heap_->MarkMapPointersAsEncoded(true);
     UpdatePointers();
-    Heap::MarkMapPointersAsEncoded(false);
-    PcToCodeCache::FlushPcToCodeCache();
+    heap_->MarkMapPointersAsEncoded(false);
+    heap_->isolate()->pc_to_code_cache()->Flush();
 
     RelocateObjects();
   } else {
     SweepSpaces();
-    PcToCodeCache::FlushPcToCodeCache();
+    heap_->isolate()->pc_to_code_cache()->Flush();
   }
 
   Finish();
@@ -124,7 +123,7 @@
   compact_on_next_gc_ = false;
 
   if (FLAG_never_compact) compacting_collection_ = false;
-  if (!Heap::map_space()->MapPointersEncodable())
+  if (!HEAP->map_space()->MapPointersEncodable())
       compacting_collection_ = false;
   if (FLAG_collect_maps) CreateBackPointers();
 #ifdef ENABLE_GDB_JIT_INTERFACE
@@ -162,9 +161,9 @@
   // 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();
+  Isolate::Current()->stub_cache()->Clear();
 
-  ExternalStringTable::CleanUp();
+  heap_->external_string_table_.CleanUp();
 
   // If we've just compacted old space there's no reason to check the
   // fragmentation limit. Just return.
@@ -221,17 +220,19 @@
 // and continue with marking.  This process repeats until all reachable
 // objects have been marked.
 
-static MarkingStack marking_stack;
-
-class FlushCode : public AllStatic {
+class CodeFlusher {
  public:
-  static void AddCandidate(SharedFunctionInfo* shared_info) {
+  explicit CodeFlusher(Isolate* isolate)
+      : isolate_(isolate),
+        jsfunction_candidates_head_(NULL),
+        shared_function_info_candidates_head_(NULL) {}
+
+  void AddCandidate(SharedFunctionInfo* shared_info) {
     SetNextCandidate(shared_info, shared_function_info_candidates_head_);
     shared_function_info_candidates_head_ = shared_info;
   }
 
-
-  static void AddCandidate(JSFunction* function) {
+  void AddCandidate(JSFunction* function) {
     ASSERT(function->unchecked_code() ==
            function->unchecked_shared()->unchecked_code());
 
@@ -239,15 +240,14 @@
     jsfunction_candidates_head_ = function;
   }
 
-
-  static void ProcessCandidates() {
+  void ProcessCandidates() {
     ProcessSharedFunctionInfoCandidates();
     ProcessJSFunctionCandidates();
   }
 
  private:
-  static void ProcessJSFunctionCandidates() {
-    Code* lazy_compile = Builtins::builtin(Builtins::LazyCompile);
+  void ProcessJSFunctionCandidates() {
+    Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kLazyCompile);
 
     JSFunction* candidate = jsfunction_candidates_head_;
     JSFunction* next_candidate;
@@ -271,8 +271,8 @@
   }
 
 
-  static void ProcessSharedFunctionInfoCandidates() {
-    Code* lazy_compile = Builtins::builtin(Builtins::LazyCompile);
+  void ProcessSharedFunctionInfoCandidates() {
+    Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kLazyCompile);
 
     SharedFunctionInfo* candidate = shared_function_info_candidates_head_;
     SharedFunctionInfo* next_candidate;
@@ -291,27 +291,22 @@
     shared_function_info_candidates_head_ = NULL;
   }
 
-
   static JSFunction** GetNextCandidateField(JSFunction* candidate) {
     return reinterpret_cast<JSFunction**>(
         candidate->address() + JSFunction::kCodeEntryOffset);
   }
 
-
   static JSFunction* GetNextCandidate(JSFunction* candidate) {
     return *GetNextCandidateField(candidate);
   }
 
-
   static void SetNextCandidate(JSFunction* candidate,
                                JSFunction* next_candidate) {
     *GetNextCandidateField(candidate) = next_candidate;
   }
 
-
   STATIC_ASSERT(kPointerSize <= Code::kHeaderSize - Code::kHeaderPaddingStart);
 
-
   static SharedFunctionInfo** GetNextCandidateField(
       SharedFunctionInfo* candidate) {
     Code* code = candidate->unchecked_code();
@@ -319,29 +314,34 @@
         code->address() + Code::kHeaderPaddingStart);
   }
 
-
   static SharedFunctionInfo* GetNextCandidate(SharedFunctionInfo* candidate) {
     return *GetNextCandidateField(candidate);
   }
 
-
   static void SetNextCandidate(SharedFunctionInfo* candidate,
                                SharedFunctionInfo* next_candidate) {
     *GetNextCandidateField(candidate) = next_candidate;
   }
 
-  static JSFunction* jsfunction_candidates_head_;
+  Isolate* isolate_;
+  JSFunction* jsfunction_candidates_head_;
+  SharedFunctionInfo* shared_function_info_candidates_head_;
 
-  static SharedFunctionInfo* shared_function_info_candidates_head_;
+  DISALLOW_COPY_AND_ASSIGN(CodeFlusher);
 };
 
-JSFunction* FlushCode::jsfunction_candidates_head_ = NULL;
 
-SharedFunctionInfo* FlushCode::shared_function_info_candidates_head_ = NULL;
+MarkCompactCollector::~MarkCompactCollector() {
+  if (code_flusher_ != NULL) {
+    delete code_flusher_;
+    code_flusher_ = NULL;
+  }
+}
+
 
 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
+  // 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
@@ -349,7 +349,7 @@
   //
   // The check performed is:
   //   object->IsConsString() && !object->IsSymbol() &&
-  //   (ConsString::cast(object)->second() == Heap::empty_string())
+  //   (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);
@@ -359,7 +359,8 @@
   if ((type & kShortcutTypeMask) != kShortcutTypeTag) return object;
 
   Object* second = reinterpret_cast<ConsString*>(object)->unchecked_second();
-  if (second != Heap::raw_unchecked_empty_string()) {
+  Heap* heap = map_word.ToMap()->heap();
+  if (second != heap->raw_unchecked_empty_string()) {
     return object;
   }
 
@@ -367,7 +368,7 @@
   // page dirty marks. Therefore, we only replace the string with its left
   // substring when page dirty marks do not change.
   Object* first = reinterpret_cast<ConsString*>(object)->unchecked_first();
-  if (!Heap::InNewSpace(object) && Heap::InNewSpace(first)) return object;
+  if (!heap->InNewSpace(object) && heap->InNewSpace(first)) return object;
 
   *p = first;
   return HeapObject::cast(first);
@@ -380,19 +381,6 @@
     table_.GetVisitor(map)(map, obj);
   }
 
-  static void EnableCodeFlushing(bool enabled) {
-    if (enabled) {
-      table_.Register(kVisitJSFunction, &VisitJSFunctionAndFlushCode);
-      table_.Register(kVisitSharedFunctionInfo,
-                      &VisitSharedFunctionInfoAndFlushCode);
-
-    } else {
-      table_.Register(kVisitJSFunction, &VisitJSFunction);
-      table_.Register(kVisitSharedFunctionInfo,
-                      &VisitSharedFunctionInfoGeneric);
-    }
-  }
-
   static void Initialize() {
     table_.Register(kVisitShortcutCandidate,
                     &FixedBodyVisitor<StaticMarkingVisitor,
@@ -454,18 +442,18 @@
                                    kVisitStructGeneric>();
   }
 
-  INLINE(static void VisitPointer(Object** p)) {
-    MarkObjectByPointer(p);
+  INLINE(static void VisitPointer(Heap* heap, Object** p)) {
+    MarkObjectByPointer(heap, p);
   }
 
-  INLINE(static void VisitPointers(Object** start, Object** end)) {
+  INLINE(static void VisitPointers(Heap* heap, 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;
+      if (VisitUnmarkedObjects(heap, start, end)) return;
       // We are close to a stack overflow, so just mark the objects.
     }
-    for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
+    for (Object** p = start; p < end; p++) MarkObjectByPointer(heap, p);
   }
 
   static inline void VisitCodeTarget(RelocInfo* rinfo) {
@@ -474,9 +462,9 @@
     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().
+      // marked since they are contained in HEAP->non_monomorphic_cache().
     } else {
-      MarkCompactCollector::MarkObject(code);
+      HEAP->mark_compact_collector()->MarkObject(code);
     }
   }
 
@@ -484,7 +472,7 @@
     ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
     Object* cell = rinfo->target_cell();
     Object* old_cell = cell;
-    VisitPointer(&cell);
+    VisitPointer(HEAP, &cell);
     if (cell != old_cell) {
       rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell));
     }
@@ -496,34 +484,38 @@
            (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
             rinfo->IsPatchedDebugBreakSlotSequence()));
     HeapObject* code = Code::GetCodeFromTargetAddress(rinfo->call_address());
-    MarkCompactCollector::MarkObject(code);
+    HEAP->mark_compact_collector()->MarkObject(code);
   }
 
   // Mark object pointed to by p.
-  INLINE(static void MarkObjectByPointer(Object** p)) {
+  INLINE(static void MarkObjectByPointer(Heap* heap, Object** p)) {
     if (!(*p)->IsHeapObject()) return;
     HeapObject* object = ShortCircuitConsString(p);
-    MarkCompactCollector::MarkObject(object);
+    heap->mark_compact_collector()->MarkObject(object);
   }
 
+
   // Visit an unmarked object.
   static inline void VisitUnmarkedObject(HeapObject* obj) {
 #ifdef DEBUG
-    ASSERT(Heap::Contains(obj));
+    ASSERT(HEAP->Contains(obj));
     ASSERT(!obj->IsMarked());
 #endif
     Map* map = obj->map();
-    MarkCompactCollector::SetMark(obj);
+    MarkCompactCollector* collector = map->heap()->mark_compact_collector();
+    collector->SetMark(obj);
     // Mark the map pointer and the body.
-    MarkCompactCollector::MarkObject(map);
+    collector->MarkObject(map);
     IterateBody(map, obj);
   }
 
   // Visit all unmarked objects pointed to by [start, end).
   // Returns false if the operation fails (lack of stack space).
-  static inline bool VisitUnmarkedObjects(Object** start, Object** end) {
+  static inline bool VisitUnmarkedObjects(Heap* heap,
+                                          Object** start,
+                                          Object** end) {
     // Return false is we are close to the stack limit.
-    StackLimitCheck check;
+    StackLimitCheck check(heap->isolate());
     if (check.HasOverflowed()) return false;
 
     // Visit the unmarked objects.
@@ -559,7 +551,8 @@
                               void> StructObjectVisitor;
 
   static void VisitCode(Map* map, HeapObject* object) {
-    reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>();
+    reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>(
+        map->heap());
   }
 
   // Code flushing support.
@@ -569,21 +562,20 @@
   static const int kCodeAgeThreshold = 5;
 
   inline static bool HasSourceCode(SharedFunctionInfo* info) {
-    Object* undefined = Heap::raw_unchecked_undefined_value();
+    Object* undefined = HEAP->raw_unchecked_undefined_value();
     return (info->script() != undefined) &&
         (reinterpret_cast<Script*>(info->script())->source() != undefined);
   }
 
 
   inline static bool IsCompiled(JSFunction* function) {
-    return
-        function->unchecked_code() != Builtins::builtin(Builtins::LazyCompile);
+    return function->unchecked_code() !=
+        Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
   }
 
-
   inline static bool IsCompiled(SharedFunctionInfo* function) {
-    return
-        function->unchecked_code() != Builtins::builtin(Builtins::LazyCompile);
+    return function->unchecked_code() !=
+        Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
   }
 
   inline static bool IsFlushable(JSFunction* function) {
@@ -645,7 +637,7 @@
   }
 
 
-  static bool FlushCodeForFunction(JSFunction* function) {
+  static bool FlushCodeForFunction(Heap* heap, JSFunction* function) {
     if (!IsFlushable(function)) return false;
 
     // This function's code looks flushable. But we have to postpone the
@@ -653,7 +645,7 @@
     // SharedFunctionInfo because some of them might be optimized.
     // That would make the nonoptimized version of the code nonflushable,
     // because it is required for bailing out from optimized code.
-    FlushCode::AddCandidate(function);
+    heap->mark_compact_collector()->code_flusher()->AddCandidate(function);
     return true;
   }
 
@@ -676,9 +668,10 @@
     if (!ctx->IsHeapObject()) return false;
 
     Map* map = SafeMap(ctx);
-    if (!(map == Heap::raw_unchecked_context_map() ||
-          map == Heap::raw_unchecked_catch_context_map() ||
-          map == Heap::raw_unchecked_global_context_map())) {
+    Heap* heap = map->heap();
+    if (!(map == heap->raw_unchecked_context_map() ||
+          map == heap->raw_unchecked_catch_context_map() ||
+          map == heap->raw_unchecked_global_context_map())) {
       return false;
     }
 
@@ -705,29 +698,37 @@
 
   static void VisitSharedFunctionInfoAndFlushCode(Map* map,
                                                   HeapObject* object) {
+    MarkCompactCollector* collector = map->heap()->mark_compact_collector();
+    if (!collector->is_code_flushing_enabled()) {
+      VisitSharedFunctionInfoGeneric(map, object);
+      return;
+    }
     VisitSharedFunctionInfoAndFlushCodeGeneric(map, object, false);
   }
 
 
   static void VisitSharedFunctionInfoAndFlushCodeGeneric(
       Map* map, HeapObject* object, bool known_flush_code_candidate) {
+    Heap* heap = map->heap();
     SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(object);
 
     if (shared->IsInobjectSlackTrackingInProgress()) shared->DetachInitialMap();
 
     if (!known_flush_code_candidate) {
       known_flush_code_candidate = IsFlushable(shared);
-      if (known_flush_code_candidate) FlushCode::AddCandidate(shared);
+      if (known_flush_code_candidate) {
+        heap->mark_compact_collector()->code_flusher()->AddCandidate(shared);
+      }
     }
 
-    VisitSharedFunctionInfoFields(object, known_flush_code_candidate);
+    VisitSharedFunctionInfoFields(heap, object, known_flush_code_candidate);
   }
 
 
-  static void VisitCodeEntry(Address entry_address) {
+  static void VisitCodeEntry(Heap* heap, Address entry_address) {
     Object* code = Code::GetObjectFromEntryAddress(entry_address);
     Object* old_code = code;
-    VisitPointer(&code);
+    VisitPointer(heap, &code);
     if (code != old_code) {
       Memory::Address_at(entry_address) =
           reinterpret_cast<Code*>(code)->entry();
@@ -736,16 +737,22 @@
 
 
   static void VisitJSFunctionAndFlushCode(Map* map, HeapObject* object) {
+    Heap* heap = map->heap();
+    MarkCompactCollector* collector = heap->mark_compact_collector();
+    if (!collector->is_code_flushing_enabled()) {
+      VisitJSFunction(map, object);
+      return;
+    }
+
     JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object);
     // The function must have a valid context and not be a builtin.
     bool flush_code_candidate = false;
     if (IsValidNotBuiltinContext(jsfunction->unchecked_context())) {
-      flush_code_candidate = FlushCodeForFunction(jsfunction);
+      flush_code_candidate = FlushCodeForFunction(heap, jsfunction);
     }
 
     if (!flush_code_candidate) {
-      MarkCompactCollector::MarkObject(
-          jsfunction->unchecked_shared()->unchecked_code());
+      collector->MarkObject(jsfunction->unchecked_shared()->unchecked_code());
 
       if (jsfunction->unchecked_code()->kind() == Code::OPTIMIZED_FUNCTION) {
         // For optimized functions we should retain both non-optimized version
@@ -761,8 +768,7 @@
              i < count;
              i++) {
           JSFunction* inlined = reinterpret_cast<JSFunction*>(literals->get(i));
-          MarkCompactCollector::MarkObject(
-              inlined->unchecked_shared()->unchecked_code());
+          collector->MarkObject(inlined->unchecked_shared()->unchecked_code());
         }
       }
     }
@@ -787,11 +793,15 @@
   static inline void VisitJSFunctionFields(Map* map,
                                            JSFunction* object,
                                            bool flush_code_candidate) {
-    VisitPointers(SLOT_ADDR(object, JSFunction::kPropertiesOffset),
+    Heap* heap = map->heap();
+    MarkCompactCollector* collector = heap->mark_compact_collector();
+
+    VisitPointers(heap,
+                  SLOT_ADDR(object, JSFunction::kPropertiesOffset),
                   SLOT_ADDR(object, JSFunction::kCodeEntryOffset));
 
     if (!flush_code_candidate) {
-      VisitCodeEntry(object->address() + JSFunction::kCodeEntryOffset);
+      VisitCodeEntry(heap, object->address() + JSFunction::kCodeEntryOffset);
     } else {
       // Don't visit code object.
 
@@ -800,15 +810,16 @@
       SharedFunctionInfo* shared_info = object->unchecked_shared();
       if (!shared_info->IsMarked()) {
         Map* shared_info_map = shared_info->map();
-        MarkCompactCollector::SetMark(shared_info);
-        MarkCompactCollector::MarkObject(shared_info_map);
+        collector->SetMark(shared_info);
+        collector->MarkObject(shared_info_map);
         VisitSharedFunctionInfoAndFlushCodeGeneric(shared_info_map,
                                                    shared_info,
                                                    true);
       }
     }
 
-    VisitPointers(SLOT_ADDR(object,
+    VisitPointers(heap,
+                  SLOT_ADDR(object,
                             JSFunction::kCodeEntryOffset + kPointerSize),
                   SLOT_ADDR(object, JSFunction::kNonWeakFieldsEndOffset));
 
@@ -816,15 +827,17 @@
   }
 
 
-  static void VisitSharedFunctionInfoFields(HeapObject* object,
+  static void VisitSharedFunctionInfoFields(Heap* heap,
+                                            HeapObject* object,
                                             bool flush_code_candidate) {
-    VisitPointer(SLOT_ADDR(object, SharedFunctionInfo::kNameOffset));
+    VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kNameOffset));
 
     if (!flush_code_candidate) {
-      VisitPointer(SLOT_ADDR(object, SharedFunctionInfo::kCodeOffset));
+      VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kCodeOffset));
     }
 
-    VisitPointers(SLOT_ADDR(object, SharedFunctionInfo::kScopeInfoOffset),
+    VisitPointers(heap,
+                  SLOT_ADDR(object, SharedFunctionInfo::kScopeInfoOffset),
                   SLOT_ADDR(object, SharedFunctionInfo::kSize));
   }
 
@@ -842,12 +855,14 @@
 
 class MarkingVisitor : public ObjectVisitor {
  public:
+  explicit MarkingVisitor(Heap* heap) : heap_(heap) { }
+
   void VisitPointer(Object** p) {
-    StaticMarkingVisitor::VisitPointer(p);
+    StaticMarkingVisitor::VisitPointer(heap_, p);
   }
 
   void VisitPointers(Object** start, Object** end) {
-    StaticMarkingVisitor::VisitPointers(start, end);
+    StaticMarkingVisitor::VisitPointers(heap_, start, end);
   }
 
   void VisitCodeTarget(RelocInfo* rinfo) {
@@ -861,21 +876,33 @@
   void VisitDebugTarget(RelocInfo* rinfo) {
     StaticMarkingVisitor::VisitDebugTarget(rinfo);
   }
+
+ private:
+  Heap* heap_;
 };
 
 
 class CodeMarkingVisitor : public ThreadVisitor {
  public:
+  explicit CodeMarkingVisitor(MarkCompactCollector* collector)
+      : collector_(collector) {}
+
   void VisitThread(ThreadLocalTop* top) {
     for (StackFrameIterator it(top); !it.done(); it.Advance()) {
-      MarkCompactCollector::MarkObject(it.frame()->unchecked_code());
+      collector_->MarkObject(it.frame()->unchecked_code());
     }
   }
+
+ private:
+  MarkCompactCollector* collector_;
 };
 
 
 class SharedFunctionInfoMarkingVisitor : public ObjectVisitor {
  public:
+  explicit SharedFunctionInfoMarkingVisitor(MarkCompactCollector* collector)
+      : collector_(collector) {}
+
   void VisitPointers(Object** start, Object** end) {
     for (Object** p = start; p < end; p++) VisitPointer(p);
   }
@@ -884,44 +911,52 @@
     Object* obj = *slot;
     if (obj->IsSharedFunctionInfo()) {
       SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(obj);
-      MarkCompactCollector::MarkObject(shared->unchecked_code());
-      MarkCompactCollector::MarkObject(shared);
+      collector_->MarkObject(shared->unchecked_code());
+      collector_->MarkObject(shared);
     }
   }
+
+ private:
+  MarkCompactCollector* collector_;
 };
 
 
 void MarkCompactCollector::PrepareForCodeFlushing() {
+  ASSERT(heap_ == Isolate::Current()->heap());
+
   if (!FLAG_flush_code) {
-    StaticMarkingVisitor::EnableCodeFlushing(false);
+    EnableCodeFlushing(false);
     return;
   }
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  if (Debug::IsLoaded() || Debug::has_break_points()) {
-    StaticMarkingVisitor::EnableCodeFlushing(false);
+  if (heap_->isolate()->debug()->IsLoaded() ||
+      heap_->isolate()->debug()->has_break_points()) {
+    EnableCodeFlushing(false);
     return;
   }
 #endif
-  StaticMarkingVisitor::EnableCodeFlushing(true);
+  EnableCodeFlushing(true);
 
   // Ensure that empty descriptor array is marked. Method MarkDescriptorArray
   // relies on it being marked before any other descriptor array.
-  MarkObject(Heap::raw_unchecked_empty_descriptor_array());
+  MarkObject(heap_->raw_unchecked_empty_descriptor_array());
 
   // Make sure we are not referencing the code from the stack.
+  ASSERT(this == heap_->mark_compact_collector());
   for (StackFrameIterator it; !it.done(); it.Advance()) {
     MarkObject(it.frame()->unchecked_code());
   }
 
   // Iterate the archived stacks in all threads to check if
   // the code is referenced.
-  CodeMarkingVisitor code_marking_visitor;
-  ThreadManager::IterateArchivedThreads(&code_marking_visitor);
+  CodeMarkingVisitor code_marking_visitor(this);
+  heap_->isolate()->thread_manager()->IterateArchivedThreads(
+      &code_marking_visitor);
 
-  SharedFunctionInfoMarkingVisitor visitor;
-  CompilationCache::IterateFunctions(&visitor);
-  HandleScopeImplementer::Iterate(&visitor);
+  SharedFunctionInfoMarkingVisitor visitor(this);
+  heap_->isolate()->compilation_cache()->IterateFunctions(&visitor);
+  heap_->isolate()->handle_scope_implementer()->Iterate(&visitor);
 
   ProcessMarkingStack();
 }
@@ -930,6 +965,9 @@
 // Visitor class for marking heap roots.
 class RootMarkingVisitor : public ObjectVisitor {
  public:
+  explicit RootMarkingVisitor(Heap* heap)
+    : collector_(heap->mark_compact_collector()) { }
+
   void VisitPointer(Object** p) {
     MarkObjectByPointer(p);
   }
@@ -948,16 +986,18 @@
 
     Map* map = object->map();
     // Mark the object.
-    MarkCompactCollector::SetMark(object);
+    collector_->SetMark(object);
 
     // Mark the map pointer and body, and push them on the marking stack.
-    MarkCompactCollector::MarkObject(map);
+    collector_->MarkObject(map);
     StaticMarkingVisitor::IterateBody(map, object);
 
     // Mark all the objects reachable from the map and body.  May leave
     // overflowed objects in the heap.
-    MarkCompactCollector::EmptyMarkingStack();
+    collector_->EmptyMarkingStack();
   }
+
+  MarkCompactCollector* collector_;
 };
 
 
@@ -976,10 +1016,10 @@
         // Since no objects have yet been moved we can safely access the map of
         // the object.
         if ((*p)->IsExternalString()) {
-          Heap::FinalizeExternalString(String::cast(*p));
+          HEAP->FinalizeExternalString(String::cast(*p));
         }
         // Set the entry to null_value (as deleted).
-        *p = Heap::raw_unchecked_null_value();
+        *p = HEAP->raw_unchecked_null_value();
         pointers_removed_++;
       }
     }
@@ -1010,11 +1050,11 @@
 
 void MarkCompactCollector::MarkUnmarkedObject(HeapObject* object) {
   ASSERT(!object->IsMarked());
-  ASSERT(Heap::Contains(object));
+  ASSERT(HEAP->Contains(object));
   if (object->IsMap()) {
     Map* map = Map::cast(object);
     if (FLAG_cleanup_caches_in_maps_at_gc) {
-      map->ClearCodeCache();
+      map->ClearCodeCache(heap_);
     }
     SetMark(map);
     if (FLAG_collect_maps &&
@@ -1022,11 +1062,11 @@
         map->instance_type() <= JS_FUNCTION_TYPE) {
       MarkMapContents(map);
     } else {
-      marking_stack.Push(map);
+      marking_stack_.Push(map);
     }
   } else {
     SetMark(object);
-    marking_stack.Push(object);
+    marking_stack_.Push(object);
   }
 }
 
@@ -1043,7 +1083,7 @@
 
   Object** end_slot = HeapObject::RawField(map, Map::kPointerFieldsEndOffset);
 
-  StaticMarkingVisitor::VisitPointers(start_slot, end_slot);
+  StaticMarkingVisitor::VisitPointers(map->heap(), start_slot, end_slot);
 }
 
 
@@ -1051,7 +1091,7 @@
     DescriptorArray* descriptors) {
   if (descriptors->IsMarked()) return;
   // Empty descriptor array is marked as a root before any maps are marked.
-  ASSERT(descriptors != Heap::raw_unchecked_empty_descriptor_array());
+  ASSERT(descriptors != HEAP->raw_unchecked_empty_descriptor_array());
   SetMark(descriptors);
 
   FixedArray* contents = reinterpret_cast<FixedArray*>(
@@ -1061,11 +1101,11 @@
   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
-  // MAP_TRANSITION and CONSTANT_TRANSITION is the value an Object* (a
-  // Map*).
+  // Contents contains (value, details) pairs.  If the details say that the type
+  // of descriptor is MAP_TRANSITION, CONSTANT_TRANSITION,
+  // EXTERNAL_ARRAY_TRANSITION or NULL_DESCRIPTOR, we don't mark the value as
+  // live.  Only for MAP_TRANSITION, EXTERNAL_ARRAY_TRANSITION and
+  // CONSTANT_TRANSITION is the value an 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.
@@ -1074,18 +1114,18 @@
       HeapObject* object = reinterpret_cast<HeapObject*>(contents->get(i));
       if (object->IsHeapObject() && !object->IsMarked()) {
         SetMark(object);
-        marking_stack.Push(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);
+  marking_stack_.Push(descriptors);
 }
 
 
 void MarkCompactCollector::CreateBackPointers() {
-  HeapObjectIterator iterator(Heap::map_space());
+  HeapObjectIterator iterator(HEAP->map_space());
   for (HeapObject* next_object = iterator.next();
        next_object != NULL; next_object = iterator.next()) {
     if (next_object->IsMap()) {  // Could also be ByteArray on free list.
@@ -1094,7 +1134,7 @@
           map->instance_type() <= JS_FUNCTION_TYPE) {
         map->CreateBackPointers();
       } else {
-        ASSERT(map->instance_descriptors() == Heap::empty_descriptor_array());
+        ASSERT(map->instance_descriptors() == HEAP->empty_descriptor_array());
       }
     }
   }
@@ -1111,25 +1151,29 @@
 }
 
 
-// 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());
+class OverflowedObjectsScanner : public AllStatic {
+ public:
+  // 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 inline void ScanOverflowedObjects(MarkCompactCollector* collector,
+                                           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(!collector->marking_stack_.is_full());
 
-  for (HeapObject* object = it->next(); object != NULL; 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;
+    for (HeapObject* object = it->next(); object != NULL; object = it->next()) {
+      if (object->IsOverflowed()) {
+        object->ClearOverflow();
+        ASSERT(object->IsMarked());
+        ASSERT(HEAP->Contains(object));
+        collector->marking_stack_.Push(object);
+        if (collector->marking_stack_.is_full()) return;
+      }
     }
   }
-}
+};
 
 
 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) {
@@ -1138,11 +1182,11 @@
 
 
 void MarkCompactCollector::MarkSymbolTable() {
-  SymbolTable* symbol_table = Heap::raw_unchecked_symbol_table();
+  SymbolTable* symbol_table = heap_->raw_unchecked_symbol_table();
   // Mark the symbol table itself.
   SetMark(symbol_table);
   // Explicitly mark the prefix.
-  MarkingVisitor marker;
+  MarkingVisitor marker(heap_);
   symbol_table->IteratePrefix(&marker);
   ProcessMarkingStack();
 }
@@ -1151,13 +1195,13 @@
 void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) {
   // Mark the heap roots including global variables, stack variables,
   // etc., and all objects reachable from them.
-  Heap::IterateStrongRoots(visitor, VISIT_ONLY_STRONG);
+  HEAP->IterateStrongRoots(visitor, VISIT_ONLY_STRONG);
 
   // Handle the symbol table specially.
   MarkSymbolTable();
 
   // There may be overflowed objects in the heap.  Visit them now.
-  while (marking_stack.overflowed()) {
+  while (marking_stack_.overflowed()) {
     RefillMarkingStack();
     EmptyMarkingStack();
   }
@@ -1165,7 +1209,8 @@
 
 
 void MarkCompactCollector::MarkObjectGroups() {
-  List<ObjectGroup*>* object_groups = GlobalHandles::ObjectGroups();
+  List<ObjectGroup*>* object_groups =
+      heap_->isolate()->global_handles()->object_groups();
 
   for (int i = 0; i < object_groups->length(); i++) {
     ObjectGroup* entry = object_groups->at(i);
@@ -1190,23 +1235,51 @@
         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);
+    delete entry;
     object_groups->at(i) = NULL;
   }
 }
 
 
+void MarkCompactCollector::MarkImplicitRefGroups() {
+  List<ImplicitRefGroup*>* ref_groups =
+      heap_->isolate()->global_handles()->implicit_ref_groups();
+
+  for (int i = 0; i < ref_groups->length(); i++) {
+    ImplicitRefGroup* entry = ref_groups->at(i);
+    if (entry == NULL) continue;
+
+    if (!entry->parent_->IsMarked()) continue;
+
+    List<Object**>& children = entry->children_;
+    // A parent object is marked, so mark as gray all child white heap
+    // objects.
+    for (int j = 0; j < children.length(); ++j) {
+      if ((*children[j])->IsHeapObject()) {
+        MarkObject(HeapObject::cast(*children[j]));
+      }
+    }
+
+    // Once the entire group has been colored gray, set the  group
+    // to NULL so it won't be processed again.
+    delete entry;
+    ref_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() {
-  while (!marking_stack.is_empty()) {
-    HeapObject* object = marking_stack.Pop();
+  while (!marking_stack_.is_empty()) {
+    HeapObject* object = marking_stack_.Pop();
     ASSERT(object->IsHeapObject());
-    ASSERT(Heap::Contains(object));
+    ASSERT(heap_->Contains(object));
     ASSERT(object->IsMarked());
     ASSERT(!object->IsOverflowed());
 
@@ -1228,38 +1301,38 @@
 // overflowed objects in the heap so the overflow flag on the markings stack
 // is cleared.
 void MarkCompactCollector::RefillMarkingStack() {
-  ASSERT(marking_stack.overflowed());
+  ASSERT(marking_stack_.overflowed());
 
-  SemiSpaceIterator new_it(Heap::new_space(), &OverflowObjectSize);
-  ScanOverflowedObjects(&new_it);
-  if (marking_stack.is_full()) return;
+  SemiSpaceIterator new_it(HEAP->new_space(), &OverflowObjectSize);
+  OverflowedObjectsScanner::ScanOverflowedObjects(this, &new_it);
+  if (marking_stack_.is_full()) return;
 
-  HeapObjectIterator old_pointer_it(Heap::old_pointer_space(),
+  HeapObjectIterator old_pointer_it(HEAP->old_pointer_space(),
                                     &OverflowObjectSize);
-  ScanOverflowedObjects(&old_pointer_it);
-  if (marking_stack.is_full()) return;
+  OverflowedObjectsScanner::ScanOverflowedObjects(this, &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 old_data_it(HEAP->old_data_space(), &OverflowObjectSize);
+  OverflowedObjectsScanner::ScanOverflowedObjects(this, &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 code_it(HEAP->code_space(), &OverflowObjectSize);
+  OverflowedObjectsScanner::ScanOverflowedObjects(this, &code_it);
+  if (marking_stack_.is_full()) return;
 
-  HeapObjectIterator map_it(Heap::map_space(), &OverflowObjectSize);
-  ScanOverflowedObjects(&map_it);
-  if (marking_stack.is_full()) return;
+  HeapObjectIterator map_it(HEAP->map_space(), &OverflowObjectSize);
+  OverflowedObjectsScanner::ScanOverflowedObjects(this, &map_it);
+  if (marking_stack_.is_full()) return;
 
-  HeapObjectIterator cell_it(Heap::cell_space(), &OverflowObjectSize);
-  ScanOverflowedObjects(&cell_it);
-  if (marking_stack.is_full()) return;
+  HeapObjectIterator cell_it(HEAP->cell_space(), &OverflowObjectSize);
+  OverflowedObjectsScanner::ScanOverflowedObjects(this, &cell_it);
+  if (marking_stack_.is_full()) return;
 
-  LargeObjectIterator lo_it(Heap::lo_space(), &OverflowObjectSize);
-  ScanOverflowedObjects(&lo_it);
-  if (marking_stack.is_full()) return;
+  LargeObjectIterator lo_it(HEAP->lo_space(), &OverflowObjectSize);
+  OverflowedObjectsScanner::ScanOverflowedObjects(this, &lo_it);
+  if (marking_stack_.is_full()) return;
 
-  marking_stack.clear_overflowed();
+  marking_stack_.clear_overflowed();
 }
 
 
@@ -1269,19 +1342,20 @@
 // objects in the heap.
 void MarkCompactCollector::ProcessMarkingStack() {
   EmptyMarkingStack();
-  while (marking_stack.overflowed()) {
+  while (marking_stack_.overflowed()) {
     RefillMarkingStack();
     EmptyMarkingStack();
   }
 }
 
 
-void MarkCompactCollector::ProcessObjectGroups() {
+void MarkCompactCollector::ProcessExternalMarking() {
   bool work_to_do = true;
-  ASSERT(marking_stack.is_empty());
+  ASSERT(marking_stack_.is_empty());
   while (work_to_do) {
     MarkObjectGroups();
-    work_to_do = !marking_stack.is_empty();
+    MarkImplicitRefGroups();
+    work_to_do = !marking_stack_.is_empty();
     ProcessMarkingStack();
   }
 }
@@ -1292,7 +1366,7 @@
   // The recursive GC marker detects when it is nearing stack overflow,
   // and switches to a different marking system.  JS interrupts interfere
   // with the C stack limit check.
-  PostponeInterruptsScope postpone;
+  PostponeInterruptsScope postpone(heap_->isolate());
 
 #ifdef DEBUG
   ASSERT(state_ == PREPARE_GC);
@@ -1300,21 +1374,20 @@
 #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());
+  marking_stack_.Initialize(heap_->new_space()->FromSpaceLow(),
+                            heap_->new_space()->FromSpaceHigh());
 
-  ASSERT(!marking_stack.overflowed());
+  ASSERT(!marking_stack_.overflowed());
 
   PrepareForCodeFlushing();
 
-  RootMarkingVisitor root_visitor;
+  RootMarkingVisitor root_visitor(heap_);
   MarkRoots(&root_visitor);
 
   // The objects reachable from the roots are marked, yet unreachable
-  // objects are unmarked.  Mark objects reachable from object groups
-  // containing at least one marked object, and continue until no new
-  // objects are reachable from the object groups.
-  ProcessObjectGroups();
+  // objects are unmarked.  Mark objects reachable due to host
+  // application specific logic.
+  ProcessExternalMarking();
 
   // The objects reachable from the roots or object groups are marked,
   // yet unreachable objects are unmarked.  Mark objects reachable
@@ -1322,61 +1395,65 @@
   //
   // First we identify nonlive weak handles and mark them as pending
   // destruction.
-  GlobalHandles::IdentifyWeakHandles(&IsUnmarkedHeapObject);
+  heap_->isolate()->global_handles()->IdentifyWeakHandles(
+      &IsUnmarkedHeapObject);
   // Then we mark the objects and process the transitive closure.
-  GlobalHandles::IterateWeakRoots(&root_visitor);
-  while (marking_stack.overflowed()) {
+  heap_->isolate()->global_handles()->IterateWeakRoots(&root_visitor);
+  while (marking_stack_.overflowed()) {
     RefillMarkingStack();
     EmptyMarkingStack();
   }
 
-  // Repeat the object groups to mark unmarked groups reachable from the
-  // weak roots.
-  ProcessObjectGroups();
+  // Repeat host application specific marking to mark unmarked objects
+  // reachable from the weak roots.
+  ProcessExternalMarking();
 
   // Prune the symbol table removing all symbols only pointed to by the
   // symbol table.  Cannot use symbol_table() here because the symbol
   // table is marked.
-  SymbolTable* symbol_table = Heap::raw_unchecked_symbol_table();
+  SymbolTable* symbol_table = heap_->raw_unchecked_symbol_table();
   SymbolTableCleaner v;
   symbol_table->IterateElements(&v);
   symbol_table->ElementsRemoved(v.PointersRemoved());
-  ExternalStringTable::Iterate(&v);
-  ExternalStringTable::CleanUp();
+  heap_->external_string_table_.Iterate(&v);
+  heap_->external_string_table_.CleanUp();
 
   // Process the weak references.
   MarkCompactWeakObjectRetainer mark_compact_object_retainer;
-  Heap::ProcessWeakReferences(&mark_compact_object_retainer);
+  heap_->ProcessWeakReferences(&mark_compact_object_retainer);
 
   // Remove object groups after marking phase.
-  GlobalHandles::RemoveObjectGroups();
+  heap_->isolate()->global_handles()->RemoveObjectGroups();
+  heap_->isolate()->global_handles()->RemoveImplicitRefGroups();
 
   // Flush code from collected candidates.
-  FlushCode::ProcessCandidates();
+  if (is_code_flushing_enabled()) {
+    code_flusher_->ProcessCandidates();
+  }
 
   // Clean up dead objects from the runtime profiler.
-  RuntimeProfiler::RemoveDeadSamples();
+  heap_->isolate()->runtime_profiler()->RemoveDeadSamples();
 }
 
 
 #ifdef DEBUG
 void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) {
   live_bytes_ += obj->Size();
-  if (Heap::new_space()->Contains(obj)) {
+  if (HEAP->new_space()->Contains(obj)) {
     live_young_objects_size_ += obj->Size();
-  } else if (Heap::map_space()->Contains(obj)) {
+  } else if (HEAP->map_space()->Contains(obj)) {
     ASSERT(obj->IsMap());
     live_map_objects_size_ += obj->Size();
-  } else if (Heap::cell_space()->Contains(obj)) {
+  } else if (HEAP->cell_space()->Contains(obj)) {
     ASSERT(obj->IsJSGlobalPropertyCell());
     live_cell_objects_size_ += obj->Size();
-  } else if (Heap::old_pointer_space()->Contains(obj)) {
+  } else if (HEAP->old_pointer_space()->Contains(obj)) {
     live_old_pointer_objects_size_ += obj->Size();
-  } else if (Heap::old_data_space()->Contains(obj)) {
+  } else if (HEAP->old_data_space()->Contains(obj)) {
     live_old_data_objects_size_ += obj->Size();
-  } else if (Heap::code_space()->Contains(obj)) {
+  } else if (HEAP->code_space()->Contains(obj)) {
     live_code_objects_size_ += obj->Size();
-  } else if (Heap::lo_space()->Contains(obj)) {
+  } else if (HEAP->lo_space()->Contains(obj)) {
     live_lo_objects_size_ += obj->Size();
   } else {
     UNREACHABLE();
@@ -1392,7 +1469,7 @@
       compacting_collection_ ? ENCODE_FORWARDING_ADDRESSES : SWEEP_SPACES;
 #endif
   // Deallocate unmarked objects and clear marked bits for marked objects.
-  Heap::lo_space()->FreeUnmarkedObjects();
+  HEAP->lo_space()->FreeUnmarkedObjects();
 }
 
 
@@ -1405,7 +1482,7 @@
 
 
 void MarkCompactCollector::ClearNonLiveTransitions() {
-  HeapObjectIterator map_iterator(Heap::map_space(), &SizeOfMarkedObject);
+  HeapObjectIterator map_iterator(HEAP->map_space(), &SizeOfMarkedObject);
   // Iterate over the map space, setting map transitions that go from
   // a marked map to an unmarked map to null transitions.  At the same time,
   // set all the prototype fields of maps back to their original value,
@@ -1455,7 +1532,7 @@
       // This test will always be false on the first iteration.
       if (on_dead_path && current->IsMarked()) {
         on_dead_path = false;
-        current->ClearNonLiveTransitions(real_prototype);
+        current->ClearNonLiveTransitions(heap_, real_prototype);
       }
       *HeapObject::RawField(current, Map::kPrototypeOffset) =
           real_prototype;
@@ -1517,20 +1594,21 @@
 // Try to promote all objects in new space.  Heap numbers and sequential
 // strings are promoted to the code space, large objects to large object space,
 // and all others to the old space.
-inline MaybeObject* MCAllocateFromNewSpace(HeapObject* object,
+inline MaybeObject* MCAllocateFromNewSpace(Heap* heap,
+                                           HeapObject* object,
                                            int object_size) {
   MaybeObject* forwarded;
-  if (object_size > Heap::MaxObjectSizeInPagedSpace()) {
+  if (object_size > heap->MaxObjectSizeInPagedSpace()) {
     forwarded = Failure::Exception();
   } else {
-    OldSpace* target_space = Heap::TargetSpace(object);
-    ASSERT(target_space == Heap::old_pointer_space() ||
-           target_space == Heap::old_data_space());
+    OldSpace* target_space = heap->TargetSpace(object);
+    ASSERT(target_space == heap->old_pointer_space() ||
+           target_space == heap->old_data_space());
     forwarded = target_space->MCAllocateRaw(object_size);
   }
   Object* result;
   if (!forwarded->ToObject(&result)) {
-    result = Heap::new_space()->MCAllocateRaw(object_size)->ToObjectUnchecked();
+    result = heap->new_space()->MCAllocateRaw(object_size)->ToObjectUnchecked();
   }
   return result;
 }
@@ -1538,48 +1616,53 @@
 
 // Allocation functions for the paged spaces call the space's MCAllocateRaw.
 MUST_USE_RESULT inline MaybeObject* MCAllocateFromOldPointerSpace(
+    Heap *heap,
     HeapObject* ignore,
     int object_size) {
-  return Heap::old_pointer_space()->MCAllocateRaw(object_size);
+  return heap->old_pointer_space()->MCAllocateRaw(object_size);
 }
 
 
 MUST_USE_RESULT inline MaybeObject* MCAllocateFromOldDataSpace(
+    Heap* heap,
     HeapObject* ignore,
     int object_size) {
-  return Heap::old_data_space()->MCAllocateRaw(object_size);
+  return heap->old_data_space()->MCAllocateRaw(object_size);
 }
 
 
 MUST_USE_RESULT inline MaybeObject* MCAllocateFromCodeSpace(
+    Heap* heap,
     HeapObject* ignore,
     int object_size) {
-  return Heap::code_space()->MCAllocateRaw(object_size);
+  return heap->code_space()->MCAllocateRaw(object_size);
 }
 
 
 MUST_USE_RESULT inline MaybeObject* MCAllocateFromMapSpace(
+    Heap* heap,
     HeapObject* ignore,
     int object_size) {
-  return Heap::map_space()->MCAllocateRaw(object_size);
+  return heap->map_space()->MCAllocateRaw(object_size);
 }
 
 
-MUST_USE_RESULT inline MaybeObject* MCAllocateFromCellSpace(HeapObject* ignore,
-                                                            int object_size) {
-  return Heap::cell_space()->MCAllocateRaw(object_size);
+MUST_USE_RESULT inline MaybeObject* MCAllocateFromCellSpace(
+    Heap* heap, HeapObject* ignore, int object_size) {
+  return heap->cell_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,
+inline void EncodeForwardingAddressInNewSpace(Heap* heap,
+                                              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) =
+      heap->new_space()->ToSpaceOffsetForAddress(old_object->address());
+  Memory::Address_at(heap->new_space()->FromSpaceLow() + offset) =
       HeapObject::cast(new_object)->address();
 }
 
@@ -1587,7 +1670,8 @@
 // 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,
+inline void EncodeForwardingAddressInPagedSpace(Heap* heap,
+                                                HeapObject* old_object,
                                                 int object_size,
                                                 Object* new_object,
                                                 int* offset) {
@@ -1620,7 +1704,8 @@
 template<MarkCompactCollector::AllocationFunction Alloc,
          MarkCompactCollector::EncodingFunction Encode,
          MarkCompactCollector::ProcessNonLiveFunction ProcessNonLive>
-inline void EncodeForwardingAddressesInRange(Address start,
+inline void EncodeForwardingAddressesInRange(MarkCompactCollector* collector,
+                                             Address start,
                                              Address end,
                                              int* offset) {
   // The start address of the current free region while sweeping the space.
@@ -1640,12 +1725,12 @@
     HeapObject* object = HeapObject::FromAddress(current);
     if (object->IsMarked()) {
       object->ClearMark();
-      MarkCompactCollector::tracer()->decrement_marked_count();
+      collector->tracer()->decrement_marked_count();
       object_size = object->Size();
 
-      // Allocation cannot fail, because we are compacting the space.
-      Object* forwarded = Alloc(object, object_size)->ToObjectUnchecked();
-      Encode(object, object_size, forwarded, offset);
+      Object* forwarded =
+          Alloc(collector->heap(), object, object_size)->ToObjectUnchecked();
+      Encode(collector->heap(), object, object_size, forwarded, offset);
 
 #ifdef DEBUG
       if (FLAG_gc_verbose) {
@@ -1681,8 +1766,9 @@
   EncodeForwardingAddressesInRange<MCAllocateFromNewSpace,
                                    EncodeForwardingAddressInNewSpace,
                                    IgnoreNonLiveObject>(
-      Heap::new_space()->bottom(),
-      Heap::new_space()->top(),
+      this,
+      heap_->new_space()->bottom(),
+      heap_->new_space()->top(),
       &ignored);
 }
 
@@ -1701,6 +1787,7 @@
     EncodeForwardingAddressesInRange<Alloc,
                                      EncodeForwardingAddressInPagedSpace,
                                      ProcessNonLive>(
+        this,
         p->ObjectAreaStart(),
         p->AllocationTop(),
         &offset);
@@ -1718,14 +1805,15 @@
 // to encounter pointers to dead objects during traversal of dirty regions we
 // should clear them to avoid encountering them during next dirty regions
 // iteration.
-static void MigrateObject(Address dst,
+static void MigrateObject(Heap* heap,
+                          Address dst,
                           Address src,
                           int size,
                           bool to_old_space) {
   if (to_old_space) {
-    Heap::CopyBlockToOldSpaceAndUpdateRegionMarks(dst, src, size);
+    heap->CopyBlockToOldSpaceAndUpdateRegionMarks(dst, src, size);
   } else {
-    Heap::CopyBlock(dst, src, size);
+    heap->CopyBlock(dst, src, size);
   }
 
   Memory::Address_at(src) = dst;
@@ -1735,14 +1823,14 @@
 class StaticPointersToNewGenUpdatingVisitor : public
   StaticNewSpaceVisitor<StaticPointersToNewGenUpdatingVisitor> {
  public:
-  static inline void VisitPointer(Object** p) {
+  static inline void VisitPointer(Heap* heap, Object** p) {
     if (!(*p)->IsHeapObject()) return;
 
     HeapObject* obj = HeapObject::cast(*p);
     Address old_addr = obj->address();
 
-    if (Heap::new_space()->Contains(obj)) {
-      ASSERT(Heap::InFromSpace(*p));
+    if (heap->new_space()->Contains(obj)) {
+      ASSERT(heap->InFromSpace(*p));
       *p = HeapObject::FromAddress(Memory::Address_at(old_addr));
     }
   }
@@ -1753,13 +1841,15 @@
 // It does not expect to encounter pointers to dead objects.
 class PointersToNewGenUpdatingVisitor: public ObjectVisitor {
  public:
+  explicit PointersToNewGenUpdatingVisitor(Heap* heap) : heap_(heap) { }
+
   void VisitPointer(Object** p) {
-    StaticPointersToNewGenUpdatingVisitor::VisitPointer(p);
+    StaticPointersToNewGenUpdatingVisitor::VisitPointer(heap_, p);
   }
 
   void VisitPointers(Object** start, Object** end) {
     for (Object** p = start; p < end; p++) {
-      StaticPointersToNewGenUpdatingVisitor::VisitPointer(p);
+      StaticPointersToNewGenUpdatingVisitor::VisitPointer(heap_, p);
     }
   }
 
@@ -1779,6 +1869,8 @@
     VisitPointer(&target);
     rinfo->set_call_address(Code::cast(target)->instruction_start());
   }
+ private:
+  Heap* heap_;
 };
 
 
@@ -1789,7 +1881,7 @@
   if (!(*p)->IsHeapObject()) return;
 
   Address old_addr = (*p)->address();
-  ASSERT(Heap::InFromSpace(*p));
+  ASSERT(HEAP->InFromSpace(*p));
 
   Address new_addr = Memory::Address_at(old_addr);
 
@@ -1803,39 +1895,42 @@
 }
 
 
-static String* UpdateNewSpaceReferenceInExternalStringTableEntry(Object **p) {
+static String* UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap,
+                                                                 Object** p) {
   Address old_addr = HeapObject::cast(*p)->address();
   Address new_addr = Memory::Address_at(old_addr);
   return String::cast(HeapObject::FromAddress(new_addr));
 }
 
 
-static bool TryPromoteObject(HeapObject* object, int object_size) {
+static bool TryPromoteObject(Heap* heap, HeapObject* object, int object_size) {
   Object* result;
 
-  if (object_size > Heap::MaxObjectSizeInPagedSpace()) {
+  if (object_size > heap->MaxObjectSizeInPagedSpace()) {
     MaybeObject* maybe_result =
-        Heap::lo_space()->AllocateRawFixedArray(object_size);
+        heap->lo_space()->AllocateRawFixedArray(object_size);
     if (maybe_result->ToObject(&result)) {
       HeapObject* target = HeapObject::cast(result);
-      MigrateObject(target->address(), object->address(), object_size, true);
-      MarkCompactCollector::tracer()->
+      MigrateObject(heap, target->address(), object->address(), object_size,
+                    true);
+      heap->mark_compact_collector()->tracer()->
           increment_promoted_objects_size(object_size);
       return true;
     }
   } else {
-    OldSpace* target_space = Heap::TargetSpace(object);
+    OldSpace* target_space = heap->TargetSpace(object);
 
-    ASSERT(target_space == Heap::old_pointer_space() ||
-           target_space == Heap::old_data_space());
+    ASSERT(target_space == heap->old_pointer_space() ||
+           target_space == heap->old_data_space());
     MaybeObject* maybe_result = target_space->AllocateRaw(object_size);
     if (maybe_result->ToObject(&result)) {
       HeapObject* target = HeapObject::cast(result);
-      MigrateObject(target->address(),
+      MigrateObject(heap,
+                    target->address(),
                     object->address(),
                     object_size,
-                    target_space == Heap::old_pointer_space());
-      MarkCompactCollector::tracer()->
+                    target_space == heap->old_pointer_space());
+      heap->mark_compact_collector()->tracer()->
           increment_promoted_objects_size(object_size);
       return true;
     }
@@ -1845,8 +1940,8 @@
 }
 
 
-static void SweepNewSpace(NewSpace* space) {
-  Heap::CheckNewSpaceExpansionCriteria();
+static void SweepNewSpace(Heap* heap, NewSpace* space) {
+  heap->CheckNewSpaceExpansionCriteria();
 
   Address from_bottom = space->bottom();
   Address from_top = space->top();
@@ -1866,13 +1961,13 @@
 
     if (object->IsMarked()) {
       object->ClearMark();
-      MarkCompactCollector::tracer()->decrement_marked_count();
+      heap->mark_compact_collector()->tracer()->decrement_marked_count();
 
       size = object->Size();
       survivors_size += size;
 
       // Aggressively promote young survivors to the old space.
-      if (TryPromoteObject(object, size)) {
+      if (TryPromoteObject(heap, object, size)) {
         continue;
       }
 
@@ -1880,7 +1975,8 @@
       // Allocation cannot fail at this point: semispaces are of equal size.
       Object* target = space->AllocateRaw(size)->ToObjectUnchecked();
 
-      MigrateObject(HeapObject::cast(target)->address(),
+      MigrateObject(heap,
+                    HeapObject::cast(target)->address(),
                     current,
                     size,
                     false);
@@ -1894,7 +1990,7 @@
   }
 
   // Second pass: find pointers to new space and update them.
-  PointersToNewGenUpdatingVisitor updating_visitor;
+  PointersToNewGenUpdatingVisitor updating_visitor(heap);
 
   // Update pointers in to space.
   Address current = space->bottom();
@@ -1906,19 +2002,19 @@
   }
 
   // Update roots.
-  Heap::IterateRoots(&updating_visitor, VISIT_ALL_IN_SCAVENGE);
+  heap->IterateRoots(&updating_visitor, VISIT_ALL_IN_SCAVENGE);
   LiveObjectList::IterateElements(&updating_visitor);
 
   // Update pointers in old spaces.
-  Heap::IterateDirtyRegions(Heap::old_pointer_space(),
+  heap->IterateDirtyRegions(heap->old_pointer_space(),
                             &Heap::IteratePointersInDirtyRegion,
                             &UpdatePointerToNewGen,
-                            Heap::WATERMARK_SHOULD_BE_VALID);
+                            heap->WATERMARK_SHOULD_BE_VALID);
 
-  Heap::lo_space()->IterateDirtyRegions(&UpdatePointerToNewGen);
+  heap->lo_space()->IterateDirtyRegions(&UpdatePointerToNewGen);
 
   // Update pointers from cells.
-  HeapObjectIterator cell_iterator(Heap::cell_space());
+  HeapObjectIterator cell_iterator(heap->cell_space());
   for (HeapObject* cell = cell_iterator.next();
        cell != NULL;
        cell = cell_iterator.next()) {
@@ -1931,22 +2027,22 @@
   }
 
   // Update pointer from the global contexts list.
-  updating_visitor.VisitPointer(Heap::global_contexts_list_address());
+  updating_visitor.VisitPointer(heap->global_contexts_list_address());
 
   // Update pointers from external string table.
-  Heap::UpdateNewSpaceReferencesInExternalStringTable(
+  heap->UpdateNewSpaceReferencesInExternalStringTable(
       &UpdateNewSpaceReferenceInExternalStringTableEntry);
 
   // All pointers were updated. Update auxiliary allocation info.
-  Heap::IncrementYoungSurvivorsCounter(survivors_size);
+  heap->IncrementYoungSurvivorsCounter(survivors_size);
   space->set_age_mark(space->top());
 
   // Update JSFunction pointers from the runtime profiler.
-  RuntimeProfiler::UpdateSamplesAfterScavenge();
+  heap->isolate()->runtime_profiler()->UpdateSamplesAfterScavenge();
 }
 
 
-static void SweepSpace(PagedSpace* space) {
+static void SweepSpace(Heap* heap, PagedSpace* space) {
   PageIterator it(space, PageIterator::PAGES_IN_USE);
 
   // During sweeping of paged space we are trying to find longest sequences
@@ -1984,7 +2080,7 @@
       object = HeapObject::FromAddress(current);
       if (object->IsMarked()) {
         object->ClearMark();
-        MarkCompactCollector::tracer()->decrement_marked_count();
+        heap->mark_compact_collector()->tracer()->decrement_marked_count();
 
         if (!is_previous_alive) {  // Transition from free to live.
           space->DeallocateBlock(free_start,
@@ -1993,7 +2089,7 @@
           is_previous_alive = true;
         }
       } else {
-        MarkCompactCollector::ReportDeleteIfNeeded(object);
+        heap->mark_compact_collector()->ReportDeleteIfNeeded(object);
         if (is_previous_alive) {  // Transition from live to free.
           free_start = current;
           is_previous_alive = false;
@@ -2093,24 +2189,24 @@
   // 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();
+  heap_->new_space()->MCResetRelocationInfo();
 
   // Compute the forwarding pointers in each space.
   EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldPointerSpace,
                                         ReportDeleteIfNeeded>(
-      Heap::old_pointer_space());
+      heap_->old_pointer_space());
 
   EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldDataSpace,
                                         IgnoreNonLiveObject>(
-      Heap::old_data_space());
+      heap_->old_data_space());
 
   EncodeForwardingAddressesInPagedSpace<MCAllocateFromCodeSpace,
                                         ReportDeleteIfNeeded>(
-      Heap::code_space());
+      heap_->code_space());
 
   EncodeForwardingAddressesInPagedSpace<MCAllocateFromCellSpace,
                                         IgnoreNonLiveObject>(
-      Heap::cell_space());
+      heap_->cell_space());
 
 
   // Compute new space next to last after the old and code spaces have been
@@ -2122,25 +2218,25 @@
   // non-live map pointers to get the sizes of non-live objects.
   EncodeForwardingAddressesInPagedSpace<MCAllocateFromMapSpace,
                                         IgnoreNonLiveObject>(
-      Heap::map_space());
+      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();
-  Heap::cell_space()->MCWriteRelocationInfoToPage();
+  heap_->old_pointer_space()->MCWriteRelocationInfoToPage();
+  heap_->old_data_space()->MCWriteRelocationInfoToPage();
+  heap_->code_space()->MCWriteRelocationInfoToPage();
+  heap_->map_space()->MCWriteRelocationInfoToPage();
+  heap_->cell_space()->MCWriteRelocationInfoToPage();
 }
 
 
 class MapIterator : public HeapObjectIterator {
  public:
-  MapIterator() : HeapObjectIterator(Heap::map_space(), &SizeCallback) { }
+  MapIterator() : HeapObjectIterator(HEAP->map_space(), &SizeCallback) { }
 
   explicit MapIterator(Address start)
-      : HeapObjectIterator(Heap::map_space(), start, &SizeCallback) { }
+      : HeapObjectIterator(HEAP->map_space(), start, &SizeCallback) { }
 
  private:
   static int SizeCallback(HeapObject* unused) {
@@ -2152,9 +2248,10 @@
 
 class MapCompact {
  public:
-  explicit MapCompact(int live_maps)
-    : live_maps_(live_maps),
-      to_evacuate_start_(Heap::map_space()->TopAfterCompaction(live_maps)),
+  explicit MapCompact(Heap* heap, int live_maps)
+    : heap_(heap),
+      live_maps_(live_maps),
+      to_evacuate_start_(heap->map_space()->TopAfterCompaction(live_maps)),
       map_to_evacuate_it_(to_evacuate_start_),
       first_map_to_evacuate_(
           reinterpret_cast<Map*>(HeapObject::FromAddress(to_evacuate_start_))) {
@@ -2175,37 +2272,39 @@
   }
 
   void UpdateMapPointersInRoots() {
-    Heap::IterateRoots(&map_updating_visitor_, VISIT_ONLY_STRONG);
-    GlobalHandles::IterateWeakRoots(&map_updating_visitor_);
-    LiveObjectList::IterateElements(&map_updating_visitor_);
+    MapUpdatingVisitor map_updating_visitor;
+    heap_->IterateRoots(&map_updating_visitor, VISIT_ONLY_STRONG);
+    heap_->isolate()->global_handles()->IterateWeakRoots(&map_updating_visitor);
+    LiveObjectList::IterateElements(&map_updating_visitor);
   }
 
   void UpdateMapPointersInPagedSpace(PagedSpace* space) {
-    ASSERT(space != Heap::map_space());
+    ASSERT(space != heap_->map_space());
 
     PageIterator it(space, PageIterator::PAGES_IN_USE);
     while (it.has_next()) {
       Page* p = it.next();
-      UpdateMapPointersInRange(p->ObjectAreaStart(), p->AllocationTop());
+      UpdateMapPointersInRange(heap_, p->ObjectAreaStart(), p->AllocationTop());
     }
   }
 
   void UpdateMapPointersInNewSpace() {
-    NewSpace* space = Heap::new_space();
-    UpdateMapPointersInRange(space->bottom(), space->top());
+    NewSpace* space = heap_->new_space();
+    UpdateMapPointersInRange(heap_, space->bottom(), space->top());
   }
 
   void UpdateMapPointersInLargeObjectSpace() {
-    LargeObjectIterator it(Heap::lo_space());
+    LargeObjectIterator it(heap_->lo_space());
     for (HeapObject* obj = it.next(); obj != NULL; obj = it.next())
-      UpdateMapPointersInObject(obj);
+      UpdateMapPointersInObject(heap_, obj);
   }
 
   void Finish() {
-    Heap::map_space()->FinishCompaction(to_evacuate_start_, live_maps_);
+    heap_->map_space()->FinishCompaction(to_evacuate_start_, live_maps_);
   }
 
  private:
+  Heap* heap_;
   int live_maps_;
   Address to_evacuate_start_;
   MapIterator vacant_map_it_;
@@ -2215,6 +2314,8 @@
   // Helper class for updating map pointers in HeapObjects.
   class MapUpdatingVisitor: public ObjectVisitor {
   public:
+    MapUpdatingVisitor() {}
+
     void VisitPointer(Object** p) {
       UpdateMapPointer(p);
     }
@@ -2237,8 +2338,6 @@
     }
   };
 
-  static MapUpdatingVisitor map_updating_visitor_;
-
   static Map* NextMap(MapIterator* it, HeapObject* last, bool live) {
     while (true) {
       HeapObject* next = it->next();
@@ -2272,9 +2371,8 @@
 
     ASSERT(Map::kSize % 4 == 0);
 
-    Heap::CopyBlockToOldSpaceAndUpdateRegionMarks(vacant_map->address(),
-                                                  map_to_evacuate->address(),
-                                                  Map::kSize);
+    map_to_evacuate->heap()->CopyBlockToOldSpaceAndUpdateRegionMarks(
+        vacant_map->address(), map_to_evacuate->address(), Map::kSize);
 
     ASSERT(vacant_map->IsMap());  // Due to memcpy above.
 
@@ -2294,15 +2392,15 @@
     return new_map;
   }
 
-  static int UpdateMapPointersInObject(HeapObject* obj) {
+  static int UpdateMapPointersInObject(Heap* heap, HeapObject* obj) {
     ASSERT(!obj->IsMarked());
     Map* map = obj->map();
-    ASSERT(Heap::map_space()->Contains(map));
+    ASSERT(heap->map_space()->Contains(map));
     MapWord map_word = map->map_word();
     ASSERT(!map_word.IsMarked());
     if (map_word.IsOverflowed()) {
       Map* new_map = GetForwardedMap(map_word);
-      ASSERT(Heap::map_space()->Contains(new_map));
+      ASSERT(heap->map_space()->Contains(new_map));
       obj->set_map(new_map);
 
 #ifdef DEBUG
@@ -2316,16 +2414,17 @@
     }
 
     int size = obj->SizeFromMap(map);
-    obj->IterateBody(map->instance_type(), size, &map_updating_visitor_);
+    MapUpdatingVisitor map_updating_visitor;
+    obj->IterateBody(map->instance_type(), size, &map_updating_visitor);
     return size;
   }
 
-  static void UpdateMapPointersInRange(Address start, Address end) {
+  static void UpdateMapPointersInRange(Heap* heap, Address start, Address end) {
     HeapObject* object;
     int size;
     for (Address current = start; current < end; current += size) {
       object = HeapObject::FromAddress(current);
-      size = UpdateMapPointersInObject(object);
+      size = UpdateMapPointersInObject(heap, object);
       ASSERT(size > 0);
     }
   }
@@ -2342,8 +2441,6 @@
 #endif
 };
 
-MapCompact::MapUpdatingVisitor MapCompact::map_updating_visitor_;
-
 
 void MarkCompactCollector::SweepSpaces() {
   GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP);
@@ -2355,26 +2452,26 @@
   // 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());
-  SweepSpace(Heap::old_data_space());
-  SweepSpace(Heap::code_space());
-  SweepSpace(Heap::cell_space());
+  SweepSpace(heap_, heap_->old_pointer_space());
+  SweepSpace(heap_, heap_->old_data_space());
+  SweepSpace(heap_, heap_->code_space());
+  SweepSpace(heap_, heap_->cell_space());
   { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE);
-    SweepNewSpace(Heap::new_space());
+    SweepNewSpace(heap_, heap_->new_space());
   }
-  SweepSpace(Heap::map_space());
+  SweepSpace(heap_, heap_->map_space());
 
-  Heap::IterateDirtyRegions(Heap::map_space(),
-                            &Heap::IteratePointersInDirtyMapsRegion,
-                            &UpdatePointerToNewGen,
-                            Heap::WATERMARK_SHOULD_BE_VALID);
+  heap_->IterateDirtyRegions(heap_->map_space(),
+                             &heap_->IteratePointersInDirtyMapsRegion,
+                             &UpdatePointerToNewGen,
+                             heap_->WATERMARK_SHOULD_BE_VALID);
 
-  intptr_t live_maps_size = Heap::map_space()->Size();
+  intptr_t live_maps_size = heap_->map_space()->Size();
   int live_maps = static_cast<int>(live_maps_size / Map::kSize);
   ASSERT(live_map_objects_size_ == live_maps_size);
 
-  if (Heap::map_space()->NeedsCompaction(live_maps)) {
-    MapCompact map_compact(live_maps);
+  if (heap_->map_space()->NeedsCompaction(live_maps)) {
+    MapCompact map_compact(heap_, live_maps);
 
     map_compact.CompactMaps();
     map_compact.UpdateMapPointersInRoots();
@@ -2382,7 +2479,7 @@
     PagedSpaces spaces;
     for (PagedSpace* space = spaces.next();
          space != NULL; space = spaces.next()) {
-      if (space == Heap::map_space()) continue;
+      if (space == heap_->map_space()) continue;
       map_compact.UpdateMapPointersInPagedSpace(space);
     }
     map_compact.UpdateMapPointersInNewSpace();
@@ -2401,7 +2498,7 @@
 int MarkCompactCollector::IterateLiveObjectsInRange(
     Address start,
     Address end,
-    HeapObjectCallback size_func) {
+    LiveObjectCallback size_func) {
   int live_objects_size = 0;
   Address current = start;
   while (current < end) {
@@ -2411,7 +2508,7 @@
     } else if (encoded_map == kMultiFreeEncoding) {
       current += Memory::int_at(current + kIntSize);
     } else {
-      int size = size_func(HeapObject::FromAddress(current));
+      int size = (this->*size_func)(HeapObject::FromAddress(current));
       current += size;
       live_objects_size += size;
     }
@@ -2420,15 +2517,15 @@
 }
 
 
-int MarkCompactCollector::IterateLiveObjects(NewSpace* space,
-                                             HeapObjectCallback size_f) {
+int MarkCompactCollector::IterateLiveObjects(
+    NewSpace* space, LiveObjectCallback 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) {
+int MarkCompactCollector::IterateLiveObjects(
+    PagedSpace* space, LiveObjectCallback size_f) {
   ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS);
   int total = 0;
   PageIterator it(space, PageIterator::PAGES_IN_USE);
@@ -2448,6 +2545,8 @@
 // Helper class for updating pointers in HeapObjects.
 class UpdatingVisitor: public ObjectVisitor {
  public:
+  explicit UpdatingVisitor(Heap* heap) : heap_(heap) {}
+
   void VisitPointer(Object** p) {
     UpdatePointer(p);
   }
@@ -2483,27 +2582,27 @@
     HeapObject* obj = HeapObject::cast(*p);
     Address old_addr = obj->address();
     Address new_addr;
-    ASSERT(!Heap::InFromSpace(obj));
+    ASSERT(!heap_->InFromSpace(obj));
 
-    if (Heap::new_space()->Contains(obj)) {
+    if (heap_->new_space()->Contains(obj)) {
       Address forwarding_pointer_addr =
-          Heap::new_space()->FromSpaceLow() +
-          Heap::new_space()->ToSpaceOffsetForAddress(old_addr);
+          heap_->new_space()->FromSpaceLow() +
+          heap_->new_space()->ToSpaceOffsetForAddress(old_addr);
       new_addr = Memory::Address_at(forwarding_pointer_addr);
 
 #ifdef DEBUG
-      ASSERT(Heap::old_pointer_space()->Contains(new_addr) ||
-             Heap::old_data_space()->Contains(new_addr) ||
-             Heap::new_space()->FromSpaceContains(new_addr) ||
-             Heap::lo_space()->Contains(HeapObject::FromAddress(new_addr)));
+      ASSERT(heap_->old_pointer_space()->Contains(new_addr) ||
+             heap_->old_data_space()->Contains(new_addr) ||
+             heap_->new_space()->FromSpaceContains(new_addr) ||
+             heap_->lo_space()->Contains(HeapObject::FromAddress(new_addr)));
 
-      if (Heap::new_space()->FromSpaceContains(new_addr)) {
-        ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <=
-               Heap::new_space()->ToSpaceOffsetForAddress(old_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)) {
+    } else if (heap_->lo_space()->Contains(obj)) {
       // Don't move objects in the large object space.
       return;
 
@@ -2532,6 +2631,8 @@
     }
 #endif
   }
+
+  Heap* heap_;
 };
 
 
@@ -2540,31 +2641,34 @@
   ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES);
   state_ = UPDATE_POINTERS;
 #endif
-  UpdatingVisitor updating_visitor;
-  RuntimeProfiler::UpdateSamplesAfterCompact(&updating_visitor);
-  Heap::IterateRoots(&updating_visitor, VISIT_ONLY_STRONG);
-  GlobalHandles::IterateWeakRoots(&updating_visitor);
+  UpdatingVisitor updating_visitor(heap_);
+  heap_->isolate()->runtime_profiler()->UpdateSamplesAfterCompact(
+      &updating_visitor);
+  heap_->IterateRoots(&updating_visitor, VISIT_ONLY_STRONG);
+  heap_->isolate()->global_handles()->IterateWeakRoots(&updating_visitor);
 
   // Update the pointer to the head of the weak list of global contexts.
-  updating_visitor.VisitPointer(&Heap::global_contexts_list_);
+  updating_visitor.VisitPointer(&heap_->global_contexts_list_);
 
   LiveObjectList::IterateElements(&updating_visitor);
 
-  int live_maps_size = IterateLiveObjects(Heap::map_space(),
-                                          &UpdatePointersInOldObject);
-  int live_pointer_olds_size = IterateLiveObjects(Heap::old_pointer_space(),
-                                                  &UpdatePointersInOldObject);
-  int live_data_olds_size = IterateLiveObjects(Heap::old_data_space(),
-                                               &UpdatePointersInOldObject);
-  int live_codes_size = IterateLiveObjects(Heap::code_space(),
-                                           &UpdatePointersInOldObject);
-  int live_cells_size = IterateLiveObjects(Heap::cell_space(),
-                                           &UpdatePointersInOldObject);
-  int live_news_size = IterateLiveObjects(Heap::new_space(),
-                                          &UpdatePointersInNewObject);
+  int live_maps_size = IterateLiveObjects(
+      heap_->map_space(), &MarkCompactCollector::UpdatePointersInOldObject);
+  int live_pointer_olds_size = IterateLiveObjects(
+      heap_->old_pointer_space(),
+      &MarkCompactCollector::UpdatePointersInOldObject);
+  int live_data_olds_size = IterateLiveObjects(
+      heap_->old_data_space(),
+      &MarkCompactCollector::UpdatePointersInOldObject);
+  int live_codes_size = IterateLiveObjects(
+      heap_->code_space(), &MarkCompactCollector::UpdatePointersInOldObject);
+  int live_cells_size = IterateLiveObjects(
+      heap_->cell_space(), &MarkCompactCollector::UpdatePointersInOldObject);
+  int live_news_size = IterateLiveObjects(
+      heap_->new_space(), &MarkCompactCollector::UpdatePointersInNewObject);
 
   // Large objects do not move, the map word can be updated directly.
-  LargeObjectIterator it(Heap::lo_space());
+  LargeObjectIterator it(heap_->lo_space());
   for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
     UpdatePointersInNewObject(obj);
   }
@@ -2591,8 +2695,8 @@
 
   Address forwarded = GetForwardingAddressInOldSpace(old_map);
 
-  ASSERT(Heap::map_space()->Contains(old_map));
-  ASSERT(Heap::map_space()->Contains(forwarded));
+  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(),
@@ -2607,7 +2711,7 @@
   int obj_size = obj->SizeFromMap(old_map);
 
   // Update pointers in the object body.
-  UpdatingVisitor updating_visitor;
+  UpdatingVisitor updating_visitor(heap_);
   obj->IterateBody(old_map->instance_type(), obj_size, &updating_visitor);
   return obj_size;
 }
@@ -2616,8 +2720,8 @@
 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)));
+  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.
@@ -2638,7 +2742,7 @@
 #endif
 
   // Update pointers in the object body.
-  UpdatingVisitor updating_visitor;
+  UpdatingVisitor updating_visitor(heap_);
   obj->IterateBody(type, obj_size, &updating_visitor);
   return obj_size;
 }
@@ -2694,18 +2798,19 @@
 #endif
   // Relocates objects, always relocate map objects first. Relocating
   // objects in other space relies on map objects to get object size.
-  int live_maps_size = IterateLiveObjects(Heap::map_space(),
-                                          &RelocateMapObject);
-  int live_pointer_olds_size = IterateLiveObjects(Heap::old_pointer_space(),
-                                                  &RelocateOldPointerObject);
-  int live_data_olds_size = IterateLiveObjects(Heap::old_data_space(),
-                                               &RelocateOldDataObject);
-  int live_codes_size = IterateLiveObjects(Heap::code_space(),
-                                           &RelocateCodeObject);
-  int live_cells_size = IterateLiveObjects(Heap::cell_space(),
-                                           &RelocateCellObject);
-  int live_news_size = IterateLiveObjects(Heap::new_space(),
-                                          &RelocateNewObject);
+  int live_maps_size = IterateLiveObjects(
+      heap_->map_space(), &MarkCompactCollector::RelocateMapObject);
+  int live_pointer_olds_size = IterateLiveObjects(
+      heap_->old_pointer_space(),
+      &MarkCompactCollector::RelocateOldPointerObject);
+  int live_data_olds_size = IterateLiveObjects(
+      heap_->old_data_space(), &MarkCompactCollector::RelocateOldDataObject);
+  int live_codes_size = IterateLiveObjects(
+      heap_->code_space(), &MarkCompactCollector::RelocateCodeObject);
+  int live_cells_size = IterateLiveObjects(
+      heap_->cell_space(), &MarkCompactCollector::RelocateCellObject);
+  int live_news_size = IterateLiveObjects(
+      heap_->new_space(), &MarkCompactCollector::RelocateNewObject);
 
   USE(live_maps_size);
   USE(live_pointer_olds_size);
@@ -2721,28 +2826,28 @@
   ASSERT(live_news_size == live_young_objects_size_);
 
   // Flip from and to spaces
-  Heap::new_space()->Flip();
+  heap_->new_space()->Flip();
 
-  Heap::new_space()->MCCommitRelocationInfo();
+  heap_->new_space()->MCCommitRelocationInfo();
 
   // Set age_mark to bottom in to space
-  Address mark = Heap::new_space()->bottom();
-  Heap::new_space()->set_age_mark(mark);
+  Address mark = heap_->new_space()->bottom();
+  heap_->new_space()->set_age_mark(mark);
 
   PagedSpaces spaces;
   for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next())
     space->MCCommitRelocationInfo();
 
-  Heap::CheckNewSpaceExpansionCriteria();
-  Heap::IncrementYoungSurvivorsCounter(live_news_size);
+  heap_->CheckNewSpaceExpansionCriteria();
+  heap_->IncrementYoungSurvivorsCounter(live_news_size);
 }
 
 
 int MarkCompactCollector::RelocateMapObject(HeapObject* obj) {
   // Recover map pointer.
   MapWord encoding = obj->map_word();
-  Address map_addr = encoding.DecodeMapAddress(Heap::map_space());
-  ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr)));
+  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);
@@ -2755,9 +2860,9 @@
 
   if (new_addr != old_addr) {
     // Move contents.
-    Heap::MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr,
-                                                  old_addr,
-                                                  Map::kSize);
+    heap_->MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr,
+                                                   old_addr,
+                                                   Map::kSize);
   }
 
 #ifdef DEBUG
@@ -2801,8 +2906,8 @@
                                                    PagedSpace* space) {
   // Recover map pointer.
   MapWord encoding = obj->map_word();
-  Address map_addr = encoding.DecodeMapAddress(Heap::map_space());
-  ASSERT(Heap::map_space()->Contains(map_addr));
+  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);
@@ -2814,12 +2919,12 @@
 
   if (new_addr != old_addr) {
     // Move contents.
-    if (space == Heap::old_data_space()) {
-      Heap::MoveBlock(new_addr, old_addr, obj_size);
+    if (space == heap_->old_data_space()) {
+      heap_->MoveBlock(new_addr, old_addr, obj_size);
     } else {
-      Heap::MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr,
-                                                    old_addr,
-                                                    obj_size);
+      heap_->MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr,
+                                                     old_addr,
+                                                     obj_size);
     }
   }
 
@@ -2827,46 +2932,47 @@
 
   HeapObject* copied_to = HeapObject::FromAddress(new_addr);
   if (copied_to->IsSharedFunctionInfo()) {
-    PROFILE(SFIMoveEvent(old_addr, new_addr));
+    PROFILE(heap_->isolate(),
+            SharedFunctionInfoMoveEvent(old_addr, new_addr));
   }
-  HEAP_PROFILE(ObjectMoveEvent(old_addr, new_addr));
+  HEAP_PROFILE(heap_, ObjectMoveEvent(old_addr, new_addr));
 
   return obj_size;
 }
 
 
 int MarkCompactCollector::RelocateOldPointerObject(HeapObject* obj) {
-  return RelocateOldNonCodeObject(obj, Heap::old_pointer_space());
+  return RelocateOldNonCodeObject(obj, heap_->old_pointer_space());
 }
 
 
 int MarkCompactCollector::RelocateOldDataObject(HeapObject* obj) {
-  return RelocateOldNonCodeObject(obj, Heap::old_data_space());
+  return RelocateOldNonCodeObject(obj, heap_->old_data_space());
 }
 
 
 int MarkCompactCollector::RelocateCellObject(HeapObject* obj) {
-  return RelocateOldNonCodeObject(obj, Heap::cell_space());
+  return RelocateOldNonCodeObject(obj, heap_->cell_space());
 }
 
 
 int MarkCompactCollector::RelocateCodeObject(HeapObject* obj) {
   // Recover map pointer.
   MapWord encoding = obj->map_word();
-  Address map_addr = encoding.DecodeMapAddress(Heap::map_space());
-  ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr)));
+  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);
 
   // Reset the map pointer.
-  int obj_size = RestoreMap(obj, Heap::code_space(), new_addr, map_addr);
+  int obj_size = RestoreMap(obj, heap_->code_space(), new_addr, map_addr);
 
   Address old_addr = obj->address();
 
   if (new_addr != old_addr) {
     // Move contents.
-    Heap::MoveBlock(new_addr, old_addr, obj_size);
+    heap_->MoveBlock(new_addr, old_addr, obj_size);
   }
 
   HeapObject* copied_to = HeapObject::FromAddress(new_addr);
@@ -2874,9 +2980,9 @@
     // May also update inline cache target.
     Code::cast(copied_to)->Relocate(new_addr - old_addr);
     // Notify the logger that compiled code has moved.
-    PROFILE(CodeMoveEvent(old_addr, new_addr));
+    PROFILE(heap_->isolate(), CodeMoveEvent(old_addr, new_addr));
   }
-  HEAP_PROFILE(ObjectMoveEvent(old_addr, new_addr));
+  HEAP_PROFILE(heap_, ObjectMoveEvent(old_addr, new_addr));
 
   return obj_size;
 }
@@ -2887,28 +2993,28 @@
 
   // Get forwarding address
   Address old_addr = obj->address();
-  int offset = Heap::new_space()->ToSpaceOffsetForAddress(old_addr);
+  int offset = heap_->new_space()->ToSpaceOffsetForAddress(old_addr);
 
   Address new_addr =
-    Memory::Address_at(Heap::new_space()->FromSpaceLow() + offset);
+    Memory::Address_at(heap_->new_space()->FromSpaceLow() + offset);
 
 #ifdef DEBUG
-  if (Heap::new_space()->FromSpaceContains(new_addr)) {
-    ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <=
-           Heap::new_space()->ToSpaceOffsetForAddress(old_addr));
+  if (heap_->new_space()->FromSpaceContains(new_addr)) {
+    ASSERT(heap_->new_space()->FromSpaceOffsetForAddress(new_addr) <=
+           heap_->new_space()->ToSpaceOffsetForAddress(old_addr));
   } else {
-    ASSERT(Heap::TargetSpace(obj) == Heap::old_pointer_space() ||
-           Heap::TargetSpace(obj) == Heap::old_data_space());
+    ASSERT(heap_->TargetSpace(obj) == heap_->old_pointer_space() ||
+           heap_->TargetSpace(obj) == heap_->old_data_space());
   }
 #endif
 
   // New and old addresses cannot overlap.
-  if (Heap::InNewSpace(HeapObject::FromAddress(new_addr))) {
-    Heap::CopyBlock(new_addr, old_addr, obj_size);
+  if (heap_->InNewSpace(HeapObject::FromAddress(new_addr))) {
+    heap_->CopyBlock(new_addr, old_addr, obj_size);
   } else {
-    Heap::CopyBlockToOldSpaceAndUpdateRegionMarks(new_addr,
-                                                  old_addr,
-                                                  obj_size);
+    heap_->CopyBlockToOldSpaceAndUpdateRegionMarks(new_addr,
+                                                   old_addr,
+                                                   obj_size);
   }
 
 #ifdef DEBUG
@@ -2919,14 +3025,27 @@
 
   HeapObject* copied_to = HeapObject::FromAddress(new_addr);
   if (copied_to->IsSharedFunctionInfo()) {
-    PROFILE(SFIMoveEvent(old_addr, new_addr));
+    PROFILE(heap_->isolate(),
+            SharedFunctionInfoMoveEvent(old_addr, new_addr));
   }
-  HEAP_PROFILE(ObjectMoveEvent(old_addr, new_addr));
+  HEAP_PROFILE(heap_, ObjectMoveEvent(old_addr, new_addr));
 
   return obj_size;
 }
 
 
+void MarkCompactCollector::EnableCodeFlushing(bool enable) {
+  if (enable) {
+    if (code_flusher_ != NULL) return;
+    code_flusher_ = new CodeFlusher(heap_->isolate());
+  } else {
+    if (code_flusher_ == NULL) return;
+    delete code_flusher_;
+    code_flusher_ = NULL;
+  }
+}
+
+
 void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj) {
 #ifdef ENABLE_GDB_JIT_INTERFACE
   if (obj->IsCode()) {
@@ -2935,7 +3054,7 @@
 #endif
 #ifdef ENABLE_LOGGING_AND_PROFILING
   if (obj->IsCode()) {
-    PROFILE(CodeDeleteEvent(obj->address()));
+    PROFILE(ISOLATE, CodeDeleteEvent(obj->address()));
   }
 #endif
 }
diff --git a/src/mark-compact.h b/src/mark-compact.h
index 1b7e600..3c9d28b 100644
--- a/src/mark-compact.h
+++ b/src/mark-compact.h
@@ -28,6 +28,8 @@
 #ifndef V8_MARK_COMPACT_H_
 #define V8_MARK_COMPACT_H_
 
+#include "spaces.h"
+
 namespace v8 {
 namespace internal {
 
@@ -37,8 +39,61 @@
 typedef bool (*IsAliveFunction)(HeapObject* obj, int* size, int* offset);
 
 // Forward declarations.
-class RootMarkingVisitor;
+class CodeFlusher;
+class GCTracer;
 class MarkingVisitor;
+class RootMarkingVisitor;
+
+
+// ----------------------------------------------------------------------------
+// Marking stack for tracing live objects.
+
+class MarkingStack {
+ public:
+  MarkingStack() : low_(NULL), top_(NULL), high_(NULL), overflowed_(false) { }
+
+  void Initialize(Address low, Address high) {
+    top_ = low_ = reinterpret_cast<HeapObject**>(low);
+    high_ = reinterpret_cast<HeapObject**>(high);
+    overflowed_ = false;
+  }
+
+  bool is_full() const { return top_ >= high_; }
+
+  bool is_empty() const { return top_ <= low_; }
+
+  bool overflowed() const { 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_;
+
+  DISALLOW_COPY_AND_ASSIGN(MarkingStack);
+};
 
 
 // -------------------------------------------------------------------------
@@ -46,14 +101,17 @@
 //
 // All methods are static.
 
-class MarkCompactCollector: public AllStatic {
+class OverflowedObjectsScanner;
+
+class MarkCompactCollector {
  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 MaybeObject* (*AllocationFunction)(HeapObject* object,
+  typedef MaybeObject* (*AllocationFunction)(Heap* heap,
+                                             HeapObject* object,
                                              int object_size);
 
   // Type of functions to encode the forwarding address for an object.
@@ -64,7 +122,8 @@
   // 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,
+  typedef void (*EncodingFunction)(Heap* heap,
+                                   HeapObject* old_object,
                                    int object_size,
                                    Object* new_object,
                                    int* offset);
@@ -72,9 +131,12 @@
   // Type of functions to process non-live objects.
   typedef void (*ProcessNonLiveFunction)(HeapObject* object);
 
+  // Pointer to member function, used in IterateLiveObjects.
+  typedef int (MarkCompactCollector::*LiveObjectCallback)(HeapObject* obj);
+
   // Set the global force_compaction flag, it must be called before Prepare
   // to take effect.
-  static void SetForceCompaction(bool value) {
+  void SetForceCompaction(bool value) {
     force_compaction_ = value;
   }
 
@@ -83,16 +145,16 @@
 
   // Prepares for GC by resetting relocation info in old and map spaces and
   // choosing spaces to compact.
-  static void Prepare(GCTracer* tracer);
+  void Prepare(GCTracer* tracer);
 
   // Performs a global garbage collection.
-  static void CollectGarbage();
+  void CollectGarbage();
 
   // True if the last full GC performed heap compaction.
-  static bool HasCompacted() { return compacting_collection_; }
+  bool HasCompacted() { return compacting_collection_; }
 
   // True after the Prepare phase if the compaction is taking place.
-  static bool IsCompacting() {
+  bool IsCompacting() {
 #ifdef DEBUG
     // For the purposes of asserts we don't want this to keep returning true
     // after the collection is completed.
@@ -104,16 +166,16 @@
 
   // 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_; }
+  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_; }
+  GCTracer* tracer() { return tracer_; }
 
 #ifdef DEBUG
   // Checks whether performing mark-compact collection.
-  static bool in_use() { return state_ > PREPARE_GC; }
-  static bool are_map_pointers_encoded() { return state_ == UPDATE_POINTERS; }
+  bool in_use() { return state_ > PREPARE_GC; }
+  bool are_map_pointers_encoded() { return state_ == UPDATE_POINTERS; }
 #endif
 
   // Determine type of object and emit deletion log event.
@@ -127,7 +189,16 @@
   static const uint32_t kSingleFreeEncoding = 0;
   static const uint32_t kMultiFreeEncoding = 1;
 
+  inline Heap* heap() const { return heap_; }
+
+  CodeFlusher* code_flusher() { return code_flusher_; }
+  inline bool is_code_flushing_enabled() const { return code_flusher_ != NULL; }
+  void EnableCodeFlushing(bool enable);
+
  private:
+  MarkCompactCollector();
+  ~MarkCompactCollector();
+
 #ifdef DEBUG
   enum CollectorState {
     IDLE,
@@ -140,28 +211,28 @@
   };
 
   // The current stage of the collector.
-  static CollectorState state_;
+  CollectorState state_;
 #endif
 
   // Global flag that forces a compaction.
-  static bool force_compaction_;
+  bool force_compaction_;
 
   // Global flag indicating whether spaces were compacted on the last GC.
-  static bool compacting_collection_;
+  bool compacting_collection_;
 
   // Global flag indicating whether spaces will be compacted on the next GC.
-  static bool compact_on_next_gc_;
+  bool compact_on_next_gc_;
 
   // The number of objects left marked at the end of the last completed full
   // GC (expected to be zero).
-  static int previous_marked_count_;
+  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_;
+  GCTracer* tracer_;
 
   // Finishes GC, performs heap verification if enabled.
-  static void Finish();
+  void Finish();
 
   // -----------------------------------------------------------------------
   // Phase 1: Marking live objects.
@@ -179,85 +250,82 @@
   friend class CodeMarkingVisitor;
   friend class SharedFunctionInfoMarkingVisitor;
 
-  static void PrepareForCodeFlushing();
+  void PrepareForCodeFlushing();
 
   // Marking operations for objects reachable from roots.
-  static void MarkLiveObjects();
+  void MarkLiveObjects();
 
-  static void MarkUnmarkedObject(HeapObject* obj);
+  void MarkUnmarkedObject(HeapObject* obj);
 
-  static inline void MarkObject(HeapObject* obj) {
+  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();
-  }
+  inline void SetMark(HeapObject* obj);
 
   // 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();
+  void CreateBackPointers();
 
   // Mark a Map and its DescriptorArray together, skipping transitions.
-  static void MarkMapContents(Map* map);
-  static void MarkDescriptorArray(DescriptorArray* descriptors);
+  void MarkMapContents(Map* map);
+  void MarkDescriptorArray(DescriptorArray* descriptors);
 
   // Mark the heap roots and all objects reachable from them.
-  static void MarkRoots(RootMarkingVisitor* visitor);
+  void MarkRoots(RootMarkingVisitor* visitor);
 
   // Mark the symbol table specially.  References to symbols from the
   // symbol table are weak.
-  static void MarkSymbolTable();
+  void MarkSymbolTable();
 
   // Mark objects in object groups that have at least one object in the
   // group marked.
-  static void MarkObjectGroups();
+  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();
+  // Mark objects in implicit references groups if their parent object
+  // is marked.
+  void MarkImplicitRefGroups();
+
+  // Mark all objects which are reachable due to host application
+  // logic like object groups or implicit references' groups.
+  void ProcessExternalMarking();
 
   // Mark objects reachable (transitively) from objects in the marking stack
   // or overflowed in the heap.
-  static void ProcessMarkingStack();
+  void ProcessMarkingStack();
 
   // 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();
+  void EmptyMarkingStack();
 
   // 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();
+  void RefillMarkingStack();
 
   // Callback function for telling whether the object *p is an unmarked
   // heap object.
   static bool IsUnmarkedHeapObject(Object** p);
 
 #ifdef DEBUG
-  static void UpdateLiveObjectCount(HeapObject* obj);
+  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();
+  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();
+  void ClearNonLiveTransitions();
 
   // -----------------------------------------------------------------------
   // Phase 2: Sweeping to clear mark bits and free non-live objects for
@@ -302,32 +370,32 @@
 
   // Encodes forwarding addresses of objects in compactable parts of the
   // heap.
-  static void EncodeForwardingAddresses();
+  void EncodeForwardingAddresses();
 
   // Encodes the forwarding addresses of objects in new space.
-  static void EncodeForwardingAddressesInNewSpace();
+  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);
+  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);
+  int IterateLiveObjects(NewSpace* space, LiveObjectCallback size_f);
+  int IterateLiveObjects(PagedSpace* space, LiveObjectCallback 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);
+  int IterateLiveObjectsInRange(Address start, Address end,
+                                LiveObjectCallback size_func);
 
   // 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();
+  void SweepSpaces();
 
   // -----------------------------------------------------------------------
   // Phase 3: Updating pointers in live objects.
@@ -341,15 +409,15 @@
   friend class UpdatingVisitor;  // helper for updating visited objects
 
   // Updates pointers in all spaces.
-  static void UpdatePointers();
+  void UpdatePointers();
 
   // Updates pointers in an object in new space.
   // Returns the heap size of the object.
-  static int UpdatePointersInNewObject(HeapObject* obj);
+  int UpdatePointersInNewObject(HeapObject* obj);
 
   // Updates pointers in an object in old spaces.
   // Returns the heap size of the object.
-  static int UpdatePointersInOldObject(HeapObject* obj);
+  int UpdatePointersInOldObject(HeapObject* obj);
 
   // Calculates the forwarding address of an object in an old space.
   static Address GetForwardingAddressInOldSpace(HeapObject* obj);
@@ -363,31 +431,31 @@
   //   After: Objects have been moved to their new addresses.
 
   // Relocates objects in all spaces.
-  static void RelocateObjects();
+  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);
+  int ConvertCodeICTargetToAddress(HeapObject* obj);
 
   // Relocate a map object.
-  static int RelocateMapObject(HeapObject* obj);
+  int RelocateMapObject(HeapObject* obj);
 
   // Relocates an old object.
-  static int RelocateOldPointerObject(HeapObject* obj);
-  static int RelocateOldDataObject(HeapObject* obj);
+  int RelocateOldPointerObject(HeapObject* obj);
+  int RelocateOldDataObject(HeapObject* obj);
 
   // Relocate a property cell object.
-  static int RelocateCellObject(HeapObject* obj);
+  int RelocateCellObject(HeapObject* obj);
 
   // Helper function.
-  static inline int RelocateOldNonCodeObject(HeapObject* obj,
-                                             PagedSpace* space);
+  inline int RelocateOldNonCodeObject(HeapObject* obj,
+                                      PagedSpace* space);
 
   // Relocates an object in the code space.
-  static int RelocateCodeObject(HeapObject* obj);
+  int RelocateCodeObject(HeapObject* obj);
 
   // Copy a new object.
-  static int RelocateNewObject(HeapObject* obj);
+  int RelocateNewObject(HeapObject* obj);
 
 #ifdef DEBUG
   // -----------------------------------------------------------------------
@@ -396,28 +464,28 @@
   // mark-sweep collection.
 
   // Size of live objects in Heap::to_space_.
-  static int live_young_objects_size_;
+  int live_young_objects_size_;
 
   // Size of live objects in Heap::old_pointer_space_.
-  static int live_old_pointer_objects_size_;
+  int live_old_pointer_objects_size_;
 
   // Size of live objects in Heap::old_data_space_.
-  static int live_old_data_objects_size_;
+  int live_old_data_objects_size_;
 
   // Size of live objects in Heap::code_space_.
-  static int live_code_objects_size_;
+  int live_code_objects_size_;
 
   // Size of live objects in Heap::map_space_.
-  static int live_map_objects_size_;
+  int live_map_objects_size_;
 
   // Size of live objects in Heap::cell_space_.
-  static int live_cell_objects_size_;
+  int live_cell_objects_size_;
 
   // Size of live objects in Heap::lo_space_.
-  static int live_lo_objects_size_;
+  int live_lo_objects_size_;
 
   // Number of live bytes in this collection.
-  static int live_bytes_;
+  int live_bytes_;
 
   friend class MarkObjectVisitor;
   static void VisitObject(HeapObject* obj);
@@ -425,6 +493,13 @@
   friend class UnmarkObjectVisitor;
   static void UnmarkObject(HeapObject* obj);
 #endif
+
+  Heap* heap_;
+  MarkingStack marking_stack_;
+  CodeFlusher* code_flusher_;
+
+  friend class Heap;
+  friend class OverflowedObjectsScanner;
 };
 
 
diff --git a/src/messages.cc b/src/messages.cc
index 990000a..cab982c 100644
--- a/src/messages.cc
+++ b/src/messages.cc
@@ -32,7 +32,6 @@
 #include "execution.h"
 #include "messages.h"
 #include "spaces-inl.h"
-#include "top.h"
 
 namespace v8 {
 namespace internal {
@@ -68,18 +67,18 @@
     Vector< Handle<Object> > args,
     Handle<String> stack_trace,
     Handle<JSArray> stack_frames) {
-  Handle<String> type_handle = Factory::LookupAsciiSymbol(type);
+  Handle<String> type_handle = FACTORY->LookupAsciiSymbol(type);
   Handle<FixedArray> arguments_elements =
-      Factory::NewFixedArray(args.length());
+      FACTORY->NewFixedArray(args.length());
   for (int i = 0; i < args.length(); i++) {
     arguments_elements->set(i, *args[i]);
   }
   Handle<JSArray> arguments_handle =
-      Factory::NewJSArrayWithElements(arguments_elements);
+      FACTORY->NewJSArrayWithElements(arguments_elements);
 
   int start = 0;
   int end = 0;
-  Handle<Object> script_handle = Factory::undefined_value();
+  Handle<Object> script_handle = FACTORY->undefined_value();
   if (loc) {
     start = loc->start_pos();
     end = loc->end_pos();
@@ -87,15 +86,15 @@
   }
 
   Handle<Object> stack_trace_handle = stack_trace.is_null()
-      ? Factory::undefined_value()
+      ? FACTORY->undefined_value()
       : Handle<Object>::cast(stack_trace);
 
   Handle<Object> stack_frames_handle = stack_frames.is_null()
-      ? Factory::undefined_value()
+      ? FACTORY->undefined_value()
       : Handle<Object>::cast(stack_frames);
 
   Handle<JSMessageObject> message =
-      Factory::NewJSMessageObject(type_handle,
+      FACTORY->NewJSMessageObject(type_handle,
                                   arguments_handle,
                                   start,
                                   end,
@@ -111,7 +110,7 @@
                                    Handle<Object> message) {
   v8::Local<v8::Message> api_message_obj = v8::Utils::MessageToLocal(message);
 
-  v8::NeanderArray global_listeners(Factory::message_listeners());
+  v8::NeanderArray global_listeners(FACTORY->message_listeners());
   int global_length = global_listeners.length();
   if (global_length == 0) {
     DefaultMessageReport(loc, message);
@@ -131,18 +130,21 @@
 
 
 Handle<String> MessageHandler::GetMessage(Handle<Object> data) {
-  Handle<String> fmt_str = Factory::LookupAsciiSymbol("FormatMessage");
+  Handle<String> fmt_str = FACTORY->LookupAsciiSymbol("FormatMessage");
   Handle<JSFunction> fun =
-      Handle<JSFunction>(JSFunction::cast(
-          Top::builtins()->GetPropertyNoExceptionThrown(*fmt_str)));
+      Handle<JSFunction>(
+          JSFunction::cast(
+              Isolate::Current()->js_builtins_object()->
+              GetPropertyNoExceptionThrown(*fmt_str)));
   Object** argv[1] = { data.location() };
 
   bool caught_exception;
   Handle<Object> result =
-      Execution::TryCall(fun, Top::builtins(), 1, argv, &caught_exception);
+      Execution::TryCall(fun,
+          Isolate::Current()->js_builtins_object(), 1, argv, &caught_exception);
 
   if (caught_exception || !result->IsString()) {
-    return Factory::LookupAsciiSymbol("<error>");
+    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
diff --git a/src/messages.js b/src/messages.js
index 2c94912..3eb056f 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -230,6 +230,11 @@
       strict_function:              ["In strict mode code, functions can only be declared at top level or immediately within another function." ],
       strict_read_only_property:    ["Cannot assign to read only property '", "%0", "' of ", "%1"],
       strict_cannot_assign:         ["Cannot assign to read only '", "%0", "' in strict mode"],
+      strict_arguments_callee:      ["Cannot access property 'callee' of strict mode arguments"],
+      strict_arguments_caller:      ["Cannot access property 'caller' of strict mode arguments"],
+      strict_function_caller:       ["Cannot access property 'caller' of a strict mode function"],
+      strict_function_arguments:    ["Cannot access property 'arguments' of a strict mode function"],
+      strict_caller:                ["Illegal access to a strict mode caller function."],
     };
   }
   var message_type = %MessageGetType(message);
@@ -491,10 +496,24 @@
   // because this file is being processed by js2c whose handling of spaces
   // in regexps is broken. Also, ['"] are excluded from allowed URLs to
   // avoid matches against sources that invoke evals with sourceURL.
-  var sourceUrlPattern =
-    /\/\/@[\040\t]sourceURL=[\040\t]*([^\s'"]*)[\040\t]*$/m;
-  var match = sourceUrlPattern.exec(this.source);
-  return match ? match[1] : this.name;
+  // A better solution would be to detect these special comments in
+  // the scanner/parser.
+  var source = ToString(this.source);
+  var sourceUrlPos = %StringIndexOf(source, "sourceURL=", 0);
+  if (sourceUrlPos > 4) {
+    var sourceUrlPattern =
+        /\/\/@[\040\t]sourceURL=[\040\t]*([^\s\'\"]*)[\040\t]*$/gm;
+    // Don't reuse lastMatchInfo here, so we create a new array with room
+    // for four captures (array with length one longer than the index
+    // of the fourth capture, where the numbering is zero-based).
+    var matchInfo = new InternalArray(CAPTURE(3) + 1);
+    var match =
+        %_RegExpExec(sourceUrlPattern, source, sourceUrlPos - 4, matchInfo);
+    if (match) {
+      return SubString(source, matchInfo[CAPTURE(2)], matchInfo[CAPTURE(3)]);
+    }
+  }
+  return this.name;
 }
 
 
@@ -1067,5 +1086,5 @@
 InstallFunctions($Error.prototype, DONT_ENUM, ['toString', errorToString]);
 
 // Boilerplate for exceptions for stack overflows. Used from
-// Top::StackOverflow().
+// Isolate::StackOverflow().
 const kStackOverflowBoilerplate = MakeRangeError('stack_overflow', []);
diff --git a/src/mips/assembler-mips-inl.h b/src/mips/assembler-mips-inl.h
index 2e63461..f7453d1 100644
--- a/src/mips/assembler-mips-inl.h
+++ b/src/mips/assembler-mips-inl.h
@@ -38,21 +38,13 @@
 
 #include "mips/assembler-mips.h"
 #include "cpu.h"
+#include "debug.h"
 
 
 namespace v8 {
 namespace internal {
 
 // -----------------------------------------------------------------------------
-// Condition
-
-Condition NegateCondition(Condition cc) {
-  ASSERT(cc != cc_always);
-  return static_cast<Condition>(cc ^ 1);
-}
-
-
-// -----------------------------------------------------------------------------
 // Operand and MemOperand
 
 Operand::Operand(int32_t immediate, RelocInfo::Mode rmode)  {
@@ -61,17 +53,13 @@
   rmode_ = rmode;
 }
 
+
 Operand::Operand(const ExternalReference& f)  {
   rm_ = no_reg;
   imm32_ = reinterpret_cast<int32_t>(f.address());
   rmode_ = RelocInfo::EXTERNAL_REFERENCE;
 }
 
-Operand::Operand(const char* s) {
-  rm_ = no_reg;
-  imm32_ = reinterpret_cast<int32_t>(s);
-  rmode_ = RelocInfo::EMBEDDED_STRING;
-}
 
 Operand::Operand(Smi* value) {
   rm_ = no_reg;
@@ -79,10 +67,12 @@
   rmode_ = RelocInfo::NONE;
 }
 
+
 Operand::Operand(Register rm) {
   rm_ = rm;
 }
 
+
 bool Operand::is_reg() const {
   return rm_.is_valid();
 }
@@ -105,8 +95,29 @@
 
 
 Address RelocInfo::target_address_address() {
-  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
-  return reinterpret_cast<Address>(pc_);
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY
+                              || rmode_ == EMBEDDED_OBJECT
+                              || rmode_ == EXTERNAL_REFERENCE);
+  // Read the address of the word containing the target_address in an
+  // instruction stream.
+  // The only architecture-independent user of this function is the serializer.
+  // The serializer uses it to find out how many raw bytes of instruction to
+  // output before the next target.
+  // For an instructions like LUI/ORI where the target bits are mixed into the
+  // instruction bits, the size of the target will be zero, indicating that the
+  // serializer should not step forward in memory after a target is resolved
+  // and written.  In this case the target_address_address function should
+  // return the end of the instructions to be patched, allowing the
+  // deserializer to deserialize the instructions as raw bytes and put them in
+  // place, ready to be patched with the target. In our case, that is the
+  // address of the instruction that follows LUI/ORI instruction pair.
+  return reinterpret_cast<Address>(
+    pc_ + Assembler::kInstructionsFor32BitConstant * Assembler::kInstrSize);
+}
+
+
+int RelocInfo::target_address_size() {
+  return Assembler::kExternalTargetSize;
 }
 
 
@@ -130,8 +141,15 @@
 
 
 Object** RelocInfo::target_object_address() {
+  // Provide a "natural pointer" to the embedded object,
+  // which can be de-referenced during heap iteration.
   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
-  return reinterpret_cast<Object**>(pc_);
+  // TODO(mips): Commenting out, to simplify arch-independent changes.
+  // GC won't work like this, but this commit is for asm/disasm/sim.
+  // reconstructed_obj_ptr_ =
+  //   reinterpret_cast<Object*>(Assembler::target_address_at(pc_));
+  // return &reconstructed_obj_ptr_;
+  return NULL;
 }
 
 
@@ -143,23 +161,55 @@
 
 Address* RelocInfo::target_reference_address() {
   ASSERT(rmode_ == EXTERNAL_REFERENCE);
-  return reinterpret_cast<Address*>(pc_);
+  // TODO(mips): Commenting out, to simplify arch-independent changes.
+  // GC won't work like this, but this commit is for asm/disasm/sim.
+  // reconstructed_adr_ptr_ = Assembler::target_address_at(pc_);
+  // return &reconstructed_adr_ptr_;
+  return NULL;
+}
+
+
+Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
+  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
+  Address address = Memory::Address_at(pc_);
+  return Handle<JSGlobalPropertyCell>(
+      reinterpret_cast<JSGlobalPropertyCell**>(address));
+}
+
+
+JSGlobalPropertyCell* RelocInfo::target_cell() {
+  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
+  Address address = Memory::Address_at(pc_);
+  Object* object = HeapObject::FromAddress(
+      address - JSGlobalPropertyCell::kValueOffset);
+  return reinterpret_cast<JSGlobalPropertyCell*>(object);
+}
+
+
+void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell) {
+  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
+  Address address = cell->address() + JSGlobalPropertyCell::kValueOffset;
+  Memory::Address_at(pc_) = address;
 }
 
 
 Address RelocInfo::call_address() {
-  ASSERT(IsPatchedReturnSequence());
-  // The 2 instructions offset assumes patched return sequence.
-  ASSERT(IsJSReturn(rmode()));
-  return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize);
+  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
+         (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
+  // The pc_ offset of 0 assumes mips patched return sequence per
+  // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or
+  // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot().
+  return Assembler::target_address_at(pc_);
 }
 
 
 void RelocInfo::set_call_address(Address target) {
-  ASSERT(IsPatchedReturnSequence());
-  // The 2 instructions offset assumes patched return sequence.
-  ASSERT(IsJSReturn(rmode()));
-  Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target;
+  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
+         (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
+  // The pc_ offset of 0 assumes mips patched return sequence per
+  // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or
+  // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot().
+  Assembler::set_target_address_at(pc_, target);
 }
 
 
@@ -169,9 +219,8 @@
 
 
 Object** RelocInfo::call_object_address() {
-  ASSERT(IsPatchedReturnSequence());
-  // The 2 instructions offset assumes patched return sequence.
-  ASSERT(IsJSReturn(rmode()));
+  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
+         (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
   return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize);
 }
 
@@ -182,13 +231,76 @@
 
 
 bool RelocInfo::IsPatchedReturnSequence() {
-#ifdef DEBUG
-  PrintF("%s - %d - %s : Checking for jal(r)",
-      __FILE__, __LINE__, __func__);
+  Instr instr0 = Assembler::instr_at(pc_);
+  Instr instr1 = Assembler::instr_at(pc_ + 1 * Assembler::kInstrSize);
+  Instr instr2 = Assembler::instr_at(pc_ + 2 * Assembler::kInstrSize);
+  bool patched_return = ((instr0 & kOpcodeMask) == LUI &&
+                         (instr1 & kOpcodeMask) == ORI &&
+                         (instr2 & kOpcodeMask) == SPECIAL &&
+                         (instr2 & kFunctionFieldMask) == JALR);
+  return patched_return;
+}
+
+
+bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
+  Instr current_instr = Assembler::instr_at(pc_);
+  return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP);
+}
+
+
+void RelocInfo::Visit(ObjectVisitor* visitor) {
+  RelocInfo::Mode mode = rmode();
+  if (mode == RelocInfo::EMBEDDED_OBJECT) {
+    // RelocInfo is needed when pointer must be updated/serialized, such as
+    // UpdatingVisitor in mark-compact.cc or Serializer in serialize.cc.
+    // It is ignored by visitors that do not need it.
+    // Commenting out, to simplify arch-independednt changes.
+    // GC won't work like this, but this commit is for asm/disasm/sim.
+    // visitor->VisitPointer(target_object_address(), this);
+  } else if (RelocInfo::IsCodeTarget(mode)) {
+    visitor->VisitCodeTarget(this);
+  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
+    // RelocInfo is needed when external-references must be serialized by
+    // Serializer Visitor in serialize.cc. It is ignored by visitors that
+    // do not need it.
+    // Commenting out, to simplify arch-independednt changes.
+    // Serializer won't work like this, but this commit is for asm/disasm/sim.
+    // visitor->VisitExternalReference(target_reference_address(), this);
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  // TODO(isolates): Get a cached isolate below.
+  } else if (((RelocInfo::IsJSReturn(mode) &&
+               IsPatchedReturnSequence()) ||
+             (RelocInfo::IsDebugBreakSlot(mode) &&
+               IsPatchedDebugBreakSlotSequence())) &&
+             Isolate::Current()->debug()->has_break_points()) {
+    visitor->VisitDebugTarget(this);
 #endif
-  return ((Assembler::instr_at(pc_) & kOpcodeMask) == SPECIAL) &&
-         (((Assembler::instr_at(pc_) & kFunctionFieldMask) == JAL) ||
-          ((Assembler::instr_at(pc_) & kFunctionFieldMask) == JALR));
+  } else if (mode == RelocInfo::RUNTIME_ENTRY) {
+    visitor->VisitRuntimeEntry(this);
+  }
+}
+
+
+template<typename StaticVisitor>
+void RelocInfo::Visit(Heap* heap) {
+  RelocInfo::Mode mode = rmode();
+  if (mode == RelocInfo::EMBEDDED_OBJECT) {
+    StaticVisitor::VisitPointer(heap, target_object_address());
+  } else if (RelocInfo::IsCodeTarget(mode)) {
+    StaticVisitor::VisitCodeTarget(this);
+  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
+    StaticVisitor::VisitExternalReference(target_reference_address());
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  } else if (heap->isolate()->debug()->has_break_points() &&
+             ((RelocInfo::IsJSReturn(mode) &&
+              IsPatchedReturnSequence()) ||
+             (RelocInfo::IsDebugBreakSlot(mode) &&
+              IsPatchedDebugBreakSlotSequence()))) {
+    StaticVisitor::VisitDebugTarget(this);
+#endif
+  } else if (mode == RelocInfo::RUNTIME_ENTRY) {
+    StaticVisitor::VisitRuntimeEntry(this);
+  }
 }
 
 
@@ -203,10 +315,18 @@
 }
 
 
+void Assembler::CheckTrampolinePoolQuick() {
+  if (pc_offset() >= next_buffer_check_) {
+    CheckTrampolinePool();
+  }
+}
+
+
 void Assembler::emit(Instr x) {
   CheckBuffer();
   *reinterpret_cast<Instr*>(pc_) = x;
   pc_ += kInstrSize;
+  CheckTrampolinePoolQuick();
 }
 
 
diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc
index a3b316b..7d00da1 100644
--- a/src/mips/assembler-mips.cc
+++ b/src/mips/assembler-mips.cc
@@ -40,83 +40,41 @@
 #include "mips/assembler-mips-inl.h"
 #include "serialize.h"
 
-
 namespace v8 {
 namespace internal {
 
+CpuFeatures::CpuFeatures()
+    : supported_(0),
+      enabled_(0),
+      found_by_runtime_probing_(0) {
+}
 
+void CpuFeatures::Probe(bool portable) {
+  // If the compiler is allowed to use fpu then we can use fpu too in our
+  // code generation.
+#if !defined(__mips__)
+  // For the simulator=mips build, use FPU when FLAG_enable_fpu is enabled.
+  if (FLAG_enable_fpu) {
+      supported_ |= 1u << FPU;
+  }
+#else
+  if (portable && Serializer::enabled()) {
+    supported_ |= OS::CpuFeaturesImpliedByPlatform();
+    return;  // No features if we might serialize.
+  }
 
-const Register no_reg = { -1 };
+  if (OS::MipsCpuHasFeature(FPU)) {
+    // This implementation also sets the FPU flags if
+    // runtime detection of FPU returns true.
+    supported_ |= 1u << FPU;
+    found_by_runtime_probing_ |= 1u << FPU;
+  }
 
-const Register zero_reg = { 0 };
-const Register at = { 1 };
-const Register v0 = { 2 };
-const Register v1 = { 3 };
-const Register a0 = { 4 };
-const Register a1 = { 5 };
-const Register a2 = { 6 };
-const Register a3 = { 7 };
-const Register t0 = { 8 };
-const Register t1 = { 9 };
-const Register t2 = { 10 };
-const Register t3 = { 11 };
-const Register t4 = { 12 };
-const Register t5 = { 13 };
-const Register t6 = { 14 };
-const Register t7 = { 15 };
-const Register s0 = { 16 };
-const Register s1 = { 17 };
-const Register s2 = { 18 };
-const Register s3 = { 19 };
-const Register s4 = { 20 };
-const Register s5 = { 21 };
-const Register s6 = { 22 };
-const Register s7 = { 23 };
-const Register t8 = { 24 };
-const Register t9 = { 25 };
-const Register k0 = { 26 };
-const Register k1 = { 27 };
-const Register gp = { 28 };
-const Register sp = { 29 };
-const Register s8_fp = { 30 };
-const Register ra = { 31 };
+  if (!portable) found_by_runtime_probing_ = 0;
+#endif
+}
 
 
-const FPURegister no_creg = { -1 };
-
-const FPURegister f0 = { 0 };
-const FPURegister f1 = { 1 };
-const FPURegister f2 = { 2 };
-const FPURegister f3 = { 3 };
-const FPURegister f4 = { 4 };
-const FPURegister f5 = { 5 };
-const FPURegister f6 = { 6 };
-const FPURegister f7 = { 7 };
-const FPURegister f8 = { 8 };
-const FPURegister f9 = { 9 };
-const FPURegister f10 = { 10 };
-const FPURegister f11 = { 11 };
-const FPURegister f12 = { 12 };
-const FPURegister f13 = { 13 };
-const FPURegister f14 = { 14 };
-const FPURegister f15 = { 15 };
-const FPURegister f16 = { 16 };
-const FPURegister f17 = { 17 };
-const FPURegister f18 = { 18 };
-const FPURegister f19 = { 19 };
-const FPURegister f20 = { 20 };
-const FPURegister f21 = { 21 };
-const FPURegister f22 = { 22 };
-const FPURegister f23 = { 23 };
-const FPURegister f24 = { 24 };
-const FPURegister f25 = { 25 };
-const FPURegister f26 = { 26 };
-const FPURegister f27 = { 27 };
-const FPURegister f28 = { 28 };
-const FPURegister f29 = { 29 };
-const FPURegister f30 = { 30 };
-const FPURegister f31 = { 31 };
-
 int ToNumber(Register reg) {
   ASSERT(reg.is_valid());
   const int kNumbers[] = {
@@ -156,6 +114,7 @@
   return kNumbers[reg.code()];
 }
 
+
 Register ToRegister(int num) {
   ASSERT(num >= 0 && num < kNumRegisters);
   const Register kRegisters[] = {
@@ -181,6 +140,15 @@
 
 const int RelocInfo::kApplyMask = 0;
 
+
+bool RelocInfo::IsCodedSpecially() {
+  // The deserializer needs to know whether a pointer is specially coded.  Being
+  // specially coded on MIPS means that it is a lui/ori instruction, and that is
+  // always the case inside code objects.
+  return true;
+}
+
+
 // Patch the code at the current address with the supplied instructions.
 void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
   Instr* pc = reinterpret_cast<Instr*>(pc_);
@@ -210,7 +178,7 @@
   rm_ = no_reg;
   // Verify all Objects referred by code are NOT in new space.
   Object* obj = *handle;
-  ASSERT(!Heap::InNewSpace(obj));
+  ASSERT(!HEAP->InNewSpace(obj));
   if (obj->IsHeapObject()) {
     imm32_ = reinterpret_cast<intptr_t>(handle.location());
     rmode_ = RelocInfo::EMBEDDED_OBJECT;
@@ -221,26 +189,66 @@
   }
 }
 
-MemOperand::MemOperand(Register rm, int16_t offset) : Operand(rm) {
+
+MemOperand::MemOperand(Register rm, int32_t offset) : Operand(rm) {
   offset_ = offset;
 }
 
 
 // -----------------------------------------------------------------------------
-// Implementation of Assembler.
+// Specific instructions, constants, and masks.
 
-static const int kMinimalBufferSize = 4*KB;
-static byte* spare_buffer_ = NULL;
+static const int kNegOffset = 0x00008000;
+// addiu(sp, sp, 4) aka Pop() operation or part of Pop(r)
+// operations as post-increment of sp.
+const Instr kPopInstruction = ADDIU | (sp.code() << kRsShift)
+      | (sp.code() << kRtShift) | (kPointerSize & kImm16Mask);
+// addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp.
+const Instr kPushInstruction = ADDIU | (sp.code() << kRsShift)
+      | (sp.code() << kRtShift) | (-kPointerSize & kImm16Mask);
+// sw(r, MemOperand(sp, 0))
+const Instr kPushRegPattern = SW | (sp.code() << kRsShift)
+      |  (0 & kImm16Mask);
+//  lw(r, MemOperand(sp, 0))
+const Instr kPopRegPattern = LW | (sp.code() << kRsShift)
+      |  (0 & kImm16Mask);
 
-Assembler::Assembler(void* buffer, int buffer_size) {
+const Instr kLwRegFpOffsetPattern = LW | (s8_fp.code() << kRsShift)
+      |  (0 & kImm16Mask);
+
+const Instr kSwRegFpOffsetPattern = SW | (s8_fp.code() << kRsShift)
+      |  (0 & kImm16Mask);
+
+const Instr kLwRegFpNegOffsetPattern = LW | (s8_fp.code() << kRsShift)
+      |  (kNegOffset & kImm16Mask);
+
+const Instr kSwRegFpNegOffsetPattern = SW | (s8_fp.code() << kRsShift)
+      |  (kNegOffset & kImm16Mask);
+// A mask for the Rt register for push, pop, lw, sw instructions.
+const Instr kRtMask = kRtFieldMask;
+const Instr kLwSwInstrTypeMask = 0xffe00000;
+const Instr kLwSwInstrArgumentMask  = ~kLwSwInstrTypeMask;
+const Instr kLwSwOffsetMask = kImm16Mask;
+
+
+// Spare buffer.
+static const int kMinimalBufferSize = 4 * KB;
+
+
+Assembler::Assembler(void* buffer, int buffer_size)
+    : AssemblerBase(Isolate::Current()),
+      positions_recorder_(this),
+      allow_peephole_optimization_(false) {
+  // BUG(3245989): disable peephole optimization if crankshaft is enabled.
+  allow_peephole_optimization_ = FLAG_peephole_optimization;
   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 (isolate()->assembler_spare_buffer() != NULL) {
+        buffer = isolate()->assembler_spare_buffer();
+        isolate()->set_assembler_spare_buffer(NULL);
       }
     }
     if (buffer == NULL) {
@@ -263,17 +271,19 @@
   ASSERT(buffer_ != NULL);
   pc_ = buffer_;
   reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
-  current_statement_position_ = RelocInfo::kNoPosition;
-  current_position_ = RelocInfo::kNoPosition;
-  written_statement_position_ = current_statement_position_;
-  written_position_ = current_position_;
+
+  last_trampoline_pool_end_ = 0;
+  no_trampoline_pool_before_ = 0;
+  trampoline_pool_blocked_nesting_ = 0;
+  next_buffer_check_ = kMaxBranchOffset - kTrampolineSize;
 }
 
 
 Assembler::~Assembler() {
   if (own_buffer_) {
-    if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
-      spare_buffer_ = buffer_;
+    if (isolate()->assembler_spare_buffer() == NULL &&
+      buffer_size_ == kMinimalBufferSize) {
+      isolate()->set_assembler_spare_buffer(buffer_);
     } else {
       DeleteArray(buffer_);
     }
@@ -282,7 +292,7 @@
 
 
 void Assembler::GetCode(CodeDesc* desc) {
-  ASSERT(pc_ <= reloc_info_writer.pos());  // no overlap
+  ASSERT(pc_ <= reloc_info_writer.pos());  // No overlap.
   // Setup code descriptor.
   desc->buffer = buffer_;
   desc->buffer_size = buffer_size_;
@@ -291,6 +301,60 @@
 }
 
 
+void Assembler::Align(int m) {
+  ASSERT(m >= 4 && IsPowerOf2(m));
+  while ((pc_offset() & (m - 1)) != 0) {
+    nop();
+  }
+}
+
+
+void Assembler::CodeTargetAlign() {
+  // No advantage to aligning branch/call targets to more than
+  // single instruction, that I am aware of.
+  Align(4);
+}
+
+
+Register Assembler::GetRt(Instr instr) {
+  Register rt;
+  rt.code_ = (instr & kRtMask) >> kRtShift;
+  return rt;
+}
+
+
+bool Assembler::IsPop(Instr instr) {
+  return (instr & ~kRtMask) == kPopRegPattern;
+}
+
+
+bool Assembler::IsPush(Instr instr) {
+  return (instr & ~kRtMask) == kPushRegPattern;
+}
+
+
+bool Assembler::IsSwRegFpOffset(Instr instr) {
+  return ((instr & kLwSwInstrTypeMask) == kSwRegFpOffsetPattern);
+}
+
+
+bool Assembler::IsLwRegFpOffset(Instr instr) {
+  return ((instr & kLwSwInstrTypeMask) == kLwRegFpOffsetPattern);
+}
+
+
+bool Assembler::IsSwRegFpNegOffset(Instr instr) {
+  return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
+          kSwRegFpNegOffsetPattern);
+}
+
+
+bool Assembler::IsLwRegFpNegOffset(Instr instr) {
+  return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
+          kLwRegFpNegOffsetPattern);
+}
+
+
 // Labels refer to positions in the (to be) generated code.
 // There are bound, linked, and unused labels.
 //
@@ -301,14 +365,19 @@
 // to be generated; pos() is the position of the last
 // instruction using the label.
 
+// The link chain is terminated by a value in the instruction of -1,
+// which is an otherwise illegal value (branch -1 is inf loop).
+// The instruction 16-bit offset field addresses 32-bit words, but in
+// code is conv to an 18-bit value addressing bytes, hence the -4 value.
 
-// The link chain is terminated by a negative code position (must be aligned).
 const int kEndOfChain = -4;
 
-bool Assembler::is_branch(Instr instr) {
+
+bool Assembler::IsBranch(Instr instr) {
   uint32_t opcode   = ((instr & kOpcodeMask));
   uint32_t rt_field = ((instr & kRtFieldMask));
   uint32_t rs_field = ((instr & kRsFieldMask));
+  uint32_t label_constant = (instr & ~kImm16Mask);
   // Checks if the instruction is a branch.
   return opcode == BEQ ||
       opcode == BNE ||
@@ -320,7 +389,79 @@
       opcode == BGTZL||
       (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
                             rt_field == BLTZAL || rt_field == BGEZAL)) ||
-      (opcode == COP1 && rs_field == BC1);  // Coprocessor branch.
+      (opcode == COP1 && rs_field == BC1) ||  // Coprocessor branch.
+      label_constant == 0;  // Emitted label const in reg-exp engine.
+}
+
+
+bool Assembler::IsNop(Instr instr, unsigned int type) {
+  // See Assembler::nop(type).
+  ASSERT(type < 32);
+  uint32_t opcode = ((instr & kOpcodeMask));
+  uint32_t rt = ((instr & kRtFieldMask) >> kRtShift);
+  uint32_t rs = ((instr & kRsFieldMask) >> kRsShift);
+  uint32_t sa = ((instr & kSaFieldMask) >> kSaShift);
+
+  // nop(type) == sll(zero_reg, zero_reg, type);
+  // Technically all these values will be 0 but
+  // this makes more sense to the reader.
+
+  bool ret = (opcode == SLL &&
+              rt == static_cast<uint32_t>(ToNumber(zero_reg)) &&
+              rs == static_cast<uint32_t>(ToNumber(zero_reg)) &&
+              sa == type);
+
+  return ret;
+}
+
+
+int32_t Assembler::GetBranchOffset(Instr instr) {
+  ASSERT(IsBranch(instr));
+  return ((int16_t)(instr & kImm16Mask)) << 2;
+}
+
+
+bool Assembler::IsLw(Instr instr) {
+  return ((instr & kOpcodeMask) == LW);
+}
+
+
+int16_t Assembler::GetLwOffset(Instr instr) {
+  ASSERT(IsLw(instr));
+  return ((instr & kImm16Mask));
+}
+
+
+Instr Assembler::SetLwOffset(Instr instr, int16_t offset) {
+  ASSERT(IsLw(instr));
+
+  // We actually create a new lw instruction based on the original one.
+  Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask)
+      | (offset & kImm16Mask);
+
+  return temp_instr;
+}
+
+
+bool Assembler::IsSw(Instr instr) {
+  return ((instr & kOpcodeMask) == SW);
+}
+
+
+Instr Assembler::SetSwOffset(Instr instr, int16_t offset) {
+  ASSERT(IsSw(instr));
+  return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
+}
+
+
+bool Assembler::IsAddImmediate(Instr instr) {
+  return ((instr & kOpcodeMask) == ADDIU);
+}
+
+
+Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) {
+  ASSERT(IsAddImmediate(instr));
+  return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
 }
 
 
@@ -328,16 +469,25 @@
   Instr instr = instr_at(pos);
   if ((instr & ~kImm16Mask) == 0) {
     // Emitted label constant, not part of a branch.
-    return instr - (Code::kHeaderSize - kHeapObjectTag);
+    if (instr == 0) {
+       return kEndOfChain;
+     } else {
+       int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
+       return (imm18 + pos);
+     }
   }
   // Check we have a branch instruction.
-  ASSERT(is_branch(instr));
+  ASSERT(IsBranch(instr));
   // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
   // the compiler uses arithmectic shifts for signed integers.
-  int32_t imm18 = ((instr &
-                    static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
+  int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
 
-  return pos + kBranchPCOffset + imm18;
+  if (imm18 == kEndOfChain) {
+    // EndOfChain sentinel is returned directly, not relative to pc or pos.
+    return kEndOfChain;
+  } else {
+    return pos + kBranchPCOffset + imm18;
+  }
 }
 
 
@@ -351,7 +501,7 @@
     return;
   }
 
-  ASSERT(is_branch(instr));
+  ASSERT(IsBranch(instr));
   int32_t imm18 = target_pos - (pos + kBranchPCOffset);
   ASSERT((imm18 & 3) == 0);
 
@@ -388,10 +538,28 @@
 
 
 void Assembler::bind_to(Label* L, int pos) {
-  ASSERT(0 <= pos && pos <= pc_offset());  // must have a valid binding position
+  ASSERT(0 <= pos && pos <= pc_offset());  // Must have valid binding position.
   while (L->is_linked()) {
     int32_t fixup_pos = L->pos();
-    next(L);  // call next before overwriting link with target at fixup_pos
+    int32_t dist = pos - fixup_pos;
+    next(L);  // Call next before overwriting link with target at fixup_pos.
+    if (dist > kMaxBranchOffset) {
+      do {
+        int32_t trampoline_pos = get_trampoline_entry(fixup_pos);
+        ASSERT((trampoline_pos - fixup_pos) <= kMaxBranchOffset);
+        target_at_put(fixup_pos, trampoline_pos);
+        fixup_pos = trampoline_pos;
+        dist = pos - fixup_pos;
+      } while (dist > kMaxBranchOffset);
+    } else if (dist < -kMaxBranchOffset) {
+      do {
+        int32_t trampoline_pos = get_trampoline_entry(fixup_pos, false);
+        ASSERT((trampoline_pos - fixup_pos) >= -kMaxBranchOffset);
+        target_at_put(fixup_pos, trampoline_pos);
+        fixup_pos = trampoline_pos;
+        dist = pos - fixup_pos;
+      } while (dist < -kMaxBranchOffset);
+    };
     target_at_put(fixup_pos, pos);
   }
   L->bind_to(pos);
@@ -416,16 +584,16 @@
       ASSERT(link == kEndOfChain);
       target_at_put(fixup_pos, appendix->pos());
     } else {
-      // L is empty, simply use appendix
+      // L is empty, simply use appendix.
       *L = *appendix;
     }
   }
-  appendix->Unuse();  // appendix should not be used anymore
+  appendix->Unuse();  // Appendix should not be used anymore.
 }
 
 
 void Assembler::bind(Label* L) {
-  ASSERT(!L->is_bound());  // label can only be bound once
+  ASSERT(!L->is_bound());  // Label can only be bound once.
   bind_to(L, pc_offset());
 }
 
@@ -433,11 +601,11 @@
 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);
+  ASSERT(link > 0 || link == kEndOfChain);
+  if (link == kEndOfChain) {
     L->Unuse();
+  } else if (link > 0) {
+    L->link_to(link);
   }
 }
 
@@ -446,13 +614,8 @@
 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction
 // space.  There is no guarantee that the relocated location can be similarly
 // encoded.
-bool Assembler::MustUseAt(RelocInfo::Mode rmode) {
-  if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
-    return Serializer::enabled();
-  } else if (rmode == RelocInfo::NONE) {
-    return false;
-  }
-  return true;
+bool Assembler::MustUseReg(RelocInfo::Mode rmode) {
+  return rmode != RelocInfo::NONE;
 }
 
 
@@ -470,14 +633,28 @@
 
 
 void Assembler::GenInstrRegister(Opcode opcode,
+                                 Register rs,
+                                 Register rt,
+                                 uint16_t msb,
+                                 uint16_t lsb,
+                                 SecondaryField func) {
+  ASSERT(rs.is_valid() && rt.is_valid() && is_uint5(msb) && is_uint5(lsb));
+  Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
+      | (msb << kRdShift) | (lsb << kSaShift) | func;
+  emit(instr);
+}
+
+
+void Assembler::GenInstrRegister(Opcode opcode,
                                  SecondaryField fmt,
                                  FPURegister ft,
                                  FPURegister fs,
                                  FPURegister fd,
                                  SecondaryField func) {
   ASSERT(fd.is_valid() && fs.is_valid() && ft.is_valid());
-  Instr instr = opcode | fmt | (ft.code() << 16) | (fs.code() << kFsShift)
-      | (fd.code() << 6) | func;
+  ASSERT(isolate()->cpu_features()->IsEnabled(FPU));
+  Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift)
+      | (fd.code() << kFdShift) | func;
   emit(instr);
 }
 
@@ -489,8 +666,22 @@
                                  FPURegister fd,
                                  SecondaryField func) {
   ASSERT(fd.is_valid() && fs.is_valid() && rt.is_valid());
+  ASSERT(isolate()->cpu_features()->IsEnabled(FPU));
   Instr instr = opcode | fmt | (rt.code() << kRtShift)
-      | (fs.code() << kFsShift) | (fd.code() << 6) | func;
+      | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
+  emit(instr);
+}
+
+
+void Assembler::GenInstrRegister(Opcode opcode,
+                                 SecondaryField fmt,
+                                 Register rt,
+                                 FPUControlRegister fs,
+                                 SecondaryField func) {
+  ASSERT(fs.is_valid() && rt.is_valid());
+  ASSERT(isolate()->cpu_features()->IsEnabled(FPU));
+  Instr instr =
+      opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func;
   emit(instr);
 }
 
@@ -523,6 +714,7 @@
                                   FPURegister ft,
                                   int32_t j) {
   ASSERT(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
+  ASSERT(isolate()->cpu_features()->IsEnabled(FPU));
   Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
       | (j & kImm16Mask);
   emit(instr);
@@ -532,26 +724,122 @@
 // Registers are in the order of the instruction encoding, from left to right.
 void Assembler::GenInstrJump(Opcode opcode,
                               uint32_t address) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
   ASSERT(is_uint26(address));
   Instr instr = opcode | address;
   emit(instr);
+  BlockTrampolinePoolFor(1);  // For associated delay slot.
+}
+
+
+// Returns the next free label entry from the next trampoline pool.
+int32_t Assembler::get_label_entry(int32_t pos, bool next_pool) {
+  int trampoline_count = trampolines_.length();
+  int32_t label_entry = 0;
+  ASSERT(trampoline_count > 0);
+
+  if (next_pool) {
+    for (int i = 0; i < trampoline_count; i++) {
+      if (trampolines_[i].start() > pos) {
+       label_entry = trampolines_[i].take_label();
+       break;
+      }
+    }
+  } else {  //  Caller needs a label entry from the previous pool.
+    for (int i = trampoline_count-1; i >= 0; i--) {
+      if (trampolines_[i].end() < pos) {
+       label_entry = trampolines_[i].take_label();
+       break;
+      }
+    }
+  }
+  return label_entry;
+}
+
+
+// Returns the next free trampoline entry from the next trampoline pool.
+int32_t Assembler::get_trampoline_entry(int32_t pos, bool next_pool) {
+  int trampoline_count = trampolines_.length();
+  int32_t trampoline_entry = 0;
+  ASSERT(trampoline_count > 0);
+
+  if (next_pool) {
+    for (int i = 0; i < trampoline_count; i++) {
+      if (trampolines_[i].start() > pos) {
+       trampoline_entry = trampolines_[i].take_slot();
+       break;
+      }
+    }
+  } else {  // Caller needs a trampoline entry from the previous pool.
+    for (int i = trampoline_count-1; i >= 0; i--) {
+      if (trampolines_[i].end() < pos) {
+       trampoline_entry = trampolines_[i].take_slot();
+       break;
+      }
+    }
+  }
+  return trampoline_entry;
 }
 
 
 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
   int32_t target_pos;
+  int32_t pc_offset_v = pc_offset();
+
   if (L->is_bound()) {
     target_pos = L->pos();
+    int32_t dist = pc_offset_v - target_pos;
+    if (dist > kMaxBranchOffset) {
+      do {
+        int32_t trampoline_pos = get_trampoline_entry(target_pos);
+        ASSERT((trampoline_pos - target_pos) > 0);
+        ASSERT((trampoline_pos - target_pos) <= kMaxBranchOffset);
+        target_at_put(trampoline_pos, target_pos);
+        target_pos = trampoline_pos;
+        dist = pc_offset_v - target_pos;
+      } while (dist > kMaxBranchOffset);
+    } else if (dist < -kMaxBranchOffset) {
+      do {
+        int32_t trampoline_pos = get_trampoline_entry(target_pos, false);
+        ASSERT((target_pos - trampoline_pos) > 0);
+        ASSERT((target_pos - trampoline_pos) <= kMaxBranchOffset);
+        target_at_put(trampoline_pos, target_pos);
+        target_pos = trampoline_pos;
+        dist = pc_offset_v - target_pos;
+      } while (dist < -kMaxBranchOffset);
+    }
   } else {
     if (L->is_linked()) {
-      target_pos = L->pos();  // L's link
+      target_pos = L->pos();  // L's link.
+      int32_t dist = pc_offset_v - target_pos;
+      if (dist > kMaxBranchOffset) {
+        do {
+          int32_t label_pos = get_label_entry(target_pos);
+          ASSERT((label_pos - target_pos) < kMaxBranchOffset);
+          label_at_put(L, label_pos);
+          target_pos = label_pos;
+          dist = pc_offset_v - target_pos;
+        } while (dist > kMaxBranchOffset);
+      } else if (dist < -kMaxBranchOffset) {
+        do {
+          int32_t label_pos = get_label_entry(target_pos, false);
+          ASSERT((label_pos - target_pos) > -kMaxBranchOffset);
+          label_at_put(L, label_pos);
+          target_pos = label_pos;
+          dist = pc_offset_v - target_pos;
+        } while (dist < -kMaxBranchOffset);
+      }
+      L->link_to(pc_offset());
     } else {
-      target_pos = kEndOfChain;
+      L->link_to(pc_offset());
+      return kEndOfChain;
     }
-    L->link_to(pc_offset());
   }
 
   int32_t offset = target_pos - (pc_offset() + kBranchPCOffset);
+  ASSERT((offset & 3) == 0);
+  ASSERT(is_int16(offset >> 2));
+
   return offset;
 }
 
@@ -560,14 +848,20 @@
   int target_pos;
   if (L->is_bound()) {
     target_pos = L->pos();
+    instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
   } else {
     if (L->is_linked()) {
-      target_pos = L->pos();  // L's link
+      target_pos = L->pos();  // L's link.
+      int32_t imm18 = target_pos - at_offset;
+      ASSERT((imm18 & 3) == 0);
+      int32_t imm16 = imm18 >> 2;
+      ASSERT(is_int16(imm16));
+      instr_at_put(at_offset, (imm16 & kImm16Mask));
     } else {
       target_pos = kEndOfChain;
+      instr_at_put(at_offset, 0);
     }
     L->link_to(at_offset);
-    instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
   }
 }
 
@@ -580,47 +874,66 @@
 
 
 void Assembler::bal(int16_t offset) {
+  positions_recorder()->WriteRecordedPositions();
   bgezal(zero_reg, offset);
 }
 
 
 void Assembler::beq(Register rs, Register rt, int16_t offset) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
   GenInstrImmediate(BEQ, rs, rt, offset);
+  BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
 
 
 void Assembler::bgez(Register rs, int16_t offset) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
   GenInstrImmediate(REGIMM, rs, BGEZ, offset);
+  BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
 
 
 void Assembler::bgezal(Register rs, int16_t offset) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
+  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
+  BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
 
 
 void Assembler::bgtz(Register rs, int16_t offset) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
   GenInstrImmediate(BGTZ, rs, zero_reg, offset);
+  BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
 
 
 void Assembler::blez(Register rs, int16_t offset) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
   GenInstrImmediate(BLEZ, rs, zero_reg, offset);
+  BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
 
 
 void Assembler::bltz(Register rs, int16_t offset) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
   GenInstrImmediate(REGIMM, rs, BLTZ, offset);
+  BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
 
 
 void Assembler::bltzal(Register rs, int16_t offset) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
+  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
+  BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
 
 
 void Assembler::bne(Register rs, Register rt, int16_t offset) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
   GenInstrImmediate(BNE, rs, rt, offset);
+  BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
 
 
@@ -631,18 +944,27 @@
 
 
 void Assembler::jr(Register rs) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
+  if (rs.is(ra)) {
+    positions_recorder()->WriteRecordedPositions();
+  }
   GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
+  BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
 
 
 void Assembler::jal(int32_t target) {
+  positions_recorder()->WriteRecordedPositions();
   ASSERT(is_uint28(target) && ((target & 3) == 0));
   GenInstrJump(JAL, target >> 2);
 }
 
 
 void Assembler::jalr(Register rs, Register rd) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
+  positions_recorder()->WriteRecordedPositions();
   GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
+  BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
 
 
@@ -650,28 +972,164 @@
 
 // Arithmetic.
 
-void Assembler::add(Register rd, Register rs, Register rt) {
-  GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADD);
-}
-
-
 void Assembler::addu(Register rd, Register rs, Register rt) {
   GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
 }
 
 
-void Assembler::addi(Register rd, Register rs, int32_t j) {
-  GenInstrImmediate(ADDI, rs, rd, j);
-}
-
-
 void Assembler::addiu(Register rd, Register rs, int32_t j) {
   GenInstrImmediate(ADDIU, rs, rd, j);
-}
 
+  // Eliminate pattern: push(r), pop().
+  //   addiu(sp, sp, Operand(-kPointerSize));
+  //   sw(src, MemOperand(sp, 0);
+  //   addiu(sp, sp, Operand(kPointerSize));
+  // Both instructions can be eliminated.
+  if (can_peephole_optimize(3) &&
+      // Pattern.
+      instr_at(pc_ - 1 * kInstrSize) == kPopInstruction &&
+      (instr_at(pc_ - 2 * kInstrSize) & ~kRtMask) == kPushRegPattern &&
+      (instr_at(pc_ - 3 * kInstrSize)) == kPushInstruction) {
+    pc_ -= 3 * kInstrSize;
+    if (FLAG_print_peephole_optimization) {
+      PrintF("%x push(reg)/pop() eliminated\n", pc_offset());
+    }
+  }
 
-void Assembler::sub(Register rd, Register rs, Register rt) {
-  GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUB);
+  // Eliminate pattern: push(ry), pop(rx).
+  //   addiu(sp, sp, -kPointerSize)
+  //   sw(ry, MemOperand(sp, 0)
+  //   lw(rx, MemOperand(sp, 0)
+  //   addiu(sp, sp, kPointerSize);
+  // Both instructions can be eliminated if ry = rx.
+  // If ry != rx, a register copy from ry to rx is inserted
+  // after eliminating the push and the pop instructions.
+  if (can_peephole_optimize(4)) {
+    Instr pre_push_sp_set = instr_at(pc_ - 4 * kInstrSize);
+    Instr push_instr = instr_at(pc_ - 3 * kInstrSize);
+    Instr pop_instr = instr_at(pc_ - 2 * kInstrSize);
+    Instr post_pop_sp_set = instr_at(pc_ - 1 * kInstrSize);
+
+    if (IsPush(push_instr) &&
+        IsPop(pop_instr) && pre_push_sp_set == kPushInstruction &&
+        post_pop_sp_set == kPopInstruction) {
+      if ((pop_instr & kRtMask) != (push_instr & kRtMask)) {
+        // For consecutive push and pop on different registers,
+        // we delete both the push & pop and insert a register move.
+        // push ry, pop rx --> mov rx, ry.
+        Register reg_pushed, reg_popped;
+        reg_pushed = GetRt(push_instr);
+        reg_popped = GetRt(pop_instr);
+        pc_ -= 4 * kInstrSize;
+        // Insert a mov instruction, which is better than a pair of push & pop.
+        or_(reg_popped, reg_pushed, zero_reg);
+        if (FLAG_print_peephole_optimization) {
+          PrintF("%x push/pop (diff reg) replaced by a reg move\n",
+                 pc_offset());
+        }
+      } else {
+        // For consecutive push and pop on the same register,
+        // both the push and the pop can be deleted.
+        pc_ -= 4 * kInstrSize;
+        if (FLAG_print_peephole_optimization) {
+          PrintF("%x push/pop (same reg) eliminated\n", pc_offset());
+        }
+      }
+    }
+  }
+
+  if (can_peephole_optimize(5)) {
+    Instr pre_push_sp_set = instr_at(pc_ - 5 * kInstrSize);
+    Instr mem_write_instr = instr_at(pc_ - 4 * kInstrSize);
+    Instr lw_instr = instr_at(pc_ - 3 * kInstrSize);
+    Instr mem_read_instr = instr_at(pc_ - 2 * kInstrSize);
+    Instr post_pop_sp_set = instr_at(pc_ - 1 * kInstrSize);
+
+    if (IsPush(mem_write_instr) &&
+        pre_push_sp_set == kPushInstruction &&
+        IsPop(mem_read_instr) &&
+        post_pop_sp_set == kPopInstruction) {
+      if ((IsLwRegFpOffset(lw_instr) ||
+        IsLwRegFpNegOffset(lw_instr))) {
+        if ((mem_write_instr & kRtMask) ==
+              (mem_read_instr & kRtMask)) {
+          // Pattern: push & pop from/to same register,
+          // with a fp+offset lw in between.
+          //
+          // The following:
+          // addiu sp, sp, -4
+          // sw rx, [sp, #0]!
+          // lw rz, [fp, #-24]
+          // lw rx, [sp, 0],
+          // addiu sp, sp, 4
+          //
+          // Becomes:
+          // if(rx == rz)
+          //   delete all
+          // else
+          //   lw rz, [fp, #-24]
+
+          if ((mem_write_instr & kRtMask) == (lw_instr & kRtMask)) {
+            pc_ -= 5 * kInstrSize;
+          } else {
+            pc_ -= 5 * kInstrSize;
+            // Reinsert back the lw rz.
+            emit(lw_instr);
+          }
+          if (FLAG_print_peephole_optimization) {
+            PrintF("%x push/pop -dead ldr fp+offset in middle\n", pc_offset());
+          }
+        } else {
+          // Pattern: push & pop from/to different registers
+          // with a fp + offset lw in between.
+          //
+          // The following:
+          // addiu sp, sp ,-4
+          // sw rx, [sp, 0]
+          // lw rz, [fp, #-24]
+          // lw ry, [sp, 0]
+          // addiu sp, sp, 4
+          //
+          // Becomes:
+          // if(ry == rz)
+          //   mov ry, rx;
+          // else if(rx != rz)
+          //   lw rz, [fp, #-24]
+          //   mov ry, rx
+          // else if((ry != rz) || (rx == rz)) becomes:
+          //   mov ry, rx
+          //   lw rz, [fp, #-24]
+
+          Register reg_pushed, reg_popped;
+          if ((mem_read_instr & kRtMask) == (lw_instr & kRtMask)) {
+            reg_pushed = GetRt(mem_write_instr);
+            reg_popped = GetRt(mem_read_instr);
+            pc_ -= 5 * kInstrSize;
+            or_(reg_popped, reg_pushed, zero_reg);  // Move instruction.
+          } else if ((mem_write_instr & kRtMask)
+                                != (lw_instr & kRtMask)) {
+            reg_pushed = GetRt(mem_write_instr);
+            reg_popped = GetRt(mem_read_instr);
+            pc_ -= 5 * kInstrSize;
+            emit(lw_instr);
+            or_(reg_popped, reg_pushed, zero_reg);  // Move instruction.
+          } else if (((mem_read_instr & kRtMask)
+                                     != (lw_instr & kRtMask)) ||
+                    ((mem_write_instr & kRtMask)
+                                     == (lw_instr & kRtMask)) ) {
+            reg_pushed = GetRt(mem_write_instr);
+            reg_popped = GetRt(mem_read_instr);
+            pc_ -= 5 * kInstrSize;
+            or_(reg_popped, reg_pushed, zero_reg);  // Move instruction.
+            emit(lw_instr);
+          }
+          if (FLAG_print_peephole_optimization) {
+            PrintF("%x push/pop (ldr fp+off in middle)\n", pc_offset());
+          }
+        }
+      }
+    }
+  }
 }
 
 
@@ -743,7 +1201,15 @@
 
 
 // Shifts.
-void Assembler::sll(Register rd, Register rt, uint16_t sa) {
+void Assembler::sll(Register rd,
+                    Register rt,
+                    uint16_t sa,
+                    bool coming_from_nop) {
+  // Don't allow nop instructions in the form sll zero_reg, zero_reg to be
+  // generated using the sll instruction. They must be generated using
+  // nop(int/NopMarkerTypes) or MarkCode(int/NopMarkerTypes) pseudo
+  // instructions.
+  ASSERT(coming_from_nop || !(rd.is(zero_reg) && rt.is(zero_reg)));
   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SLL);
 }
 
@@ -773,30 +1239,199 @@
 }
 
 
+void Assembler::rotr(Register rd, Register rt, uint16_t sa) {
+  // Should be called via MacroAssembler::Ror.
+  ASSERT(rd.is_valid() && rt.is_valid() && is_uint5(sa));
+  ASSERT(mips32r2);
+  Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift)
+      | (rd.code() << kRdShift) | (sa << kSaShift) | SRL;
+  emit(instr);
+}
+
+
+void Assembler::rotrv(Register rd, Register rt, Register rs) {
+  // Should be called via MacroAssembler::Ror.
+  ASSERT(rd.is_valid() && rt.is_valid() && rs.is_valid() );
+  ASSERT(mips32r2);
+  Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift)
+     | (rd.code() << kRdShift) | (1 << kSaShift) | SRLV;
+  emit(instr);
+}
+
+
 //------------Memory-instructions-------------
 
+// Helper for base-reg + offset, when offset is larger than int16.
+void Assembler::LoadRegPlusOffsetToAt(const MemOperand& src) {
+  ASSERT(!src.rm().is(at));
+  lui(at, src.offset_ >> kLuiShift);
+  ori(at, at, src.offset_ & kImm16Mask);  // Load 32-bit offset.
+  addu(at, at, src.rm());  // Add base register.
+}
+
+
 void Assembler::lb(Register rd, const MemOperand& rs) {
-  GenInstrImmediate(LB, rs.rm(), rd, rs.offset_);
+  if (is_int16(rs.offset_)) {
+    GenInstrImmediate(LB, rs.rm(), rd, rs.offset_);
+  } else {  // Offset > 16 bits, use multiple instructions to load.
+    LoadRegPlusOffsetToAt(rs);
+    GenInstrImmediate(LB, at, rd, 0);  // Equiv to lb(rd, MemOperand(at, 0));
+  }
 }
 
 
 void Assembler::lbu(Register rd, const MemOperand& rs) {
-  GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_);
+  if (is_int16(rs.offset_)) {
+    GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_);
+  } else {  // Offset > 16 bits, use multiple instructions to load.
+    LoadRegPlusOffsetToAt(rs);
+    GenInstrImmediate(LBU, at, rd, 0);  // Equiv to lbu(rd, MemOperand(at, 0));
+  }
+}
+
+
+void Assembler::lh(Register rd, const MemOperand& rs) {
+  if (is_int16(rs.offset_)) {
+    GenInstrImmediate(LH, rs.rm(), rd, rs.offset_);
+  } else {  // Offset > 16 bits, use multiple instructions to load.
+    LoadRegPlusOffsetToAt(rs);
+    GenInstrImmediate(LH, at, rd, 0);  // Equiv to lh(rd, MemOperand(at, 0));
+  }
+}
+
+
+void Assembler::lhu(Register rd, const MemOperand& rs) {
+  if (is_int16(rs.offset_)) {
+    GenInstrImmediate(LHU, rs.rm(), rd, rs.offset_);
+  } else {  // Offset > 16 bits, use multiple instructions to load.
+    LoadRegPlusOffsetToAt(rs);
+    GenInstrImmediate(LHU, at, rd, 0);  // Equiv to lhu(rd, MemOperand(at, 0));
+  }
 }
 
 
 void Assembler::lw(Register rd, const MemOperand& rs) {
-  GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
+  if (is_int16(rs.offset_)) {
+    GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
+  } else {  // Offset > 16 bits, use multiple instructions to load.
+    LoadRegPlusOffsetToAt(rs);
+    GenInstrImmediate(LW, at, rd, 0);  // Equiv to lw(rd, MemOperand(at, 0));
+  }
+
+  if (can_peephole_optimize(2)) {
+    Instr sw_instr = instr_at(pc_ - 2 * kInstrSize);
+    Instr lw_instr = instr_at(pc_ - 1 * kInstrSize);
+
+    if ((IsSwRegFpOffset(sw_instr) &&
+         IsLwRegFpOffset(lw_instr)) ||
+       (IsSwRegFpNegOffset(sw_instr) &&
+         IsLwRegFpNegOffset(lw_instr))) {
+      if ((lw_instr & kLwSwInstrArgumentMask) ==
+            (sw_instr & kLwSwInstrArgumentMask)) {
+        // Pattern: Lw/sw same fp+offset, same register.
+        //
+        // The following:
+        // sw rx, [fp, #-12]
+        // lw rx, [fp, #-12]
+        //
+        // Becomes:
+        // sw rx, [fp, #-12]
+
+        pc_ -= 1 * kInstrSize;
+        if (FLAG_print_peephole_optimization) {
+          PrintF("%x sw/lw (fp + same offset), same reg\n", pc_offset());
+        }
+      } else if ((lw_instr & kLwSwOffsetMask) ==
+                 (sw_instr & kLwSwOffsetMask)) {
+        // Pattern: Lw/sw same fp+offset, different register.
+        //
+        // The following:
+        // sw rx, [fp, #-12]
+        // lw ry, [fp, #-12]
+        //
+        // Becomes:
+        // sw rx, [fp, #-12]
+        // mov ry, rx
+
+        Register reg_stored, reg_loaded;
+        reg_stored = GetRt(sw_instr);
+        reg_loaded = GetRt(lw_instr);
+        pc_ -= 1 * kInstrSize;
+        // Insert a mov instruction, which is better than lw.
+        or_(reg_loaded, reg_stored, zero_reg);  // Move instruction.
+        if (FLAG_print_peephole_optimization) {
+          PrintF("%x sw/lw (fp + same offset), diff reg \n", pc_offset());
+        }
+      }
+    }
+  }
+}
+
+
+void Assembler::lwl(Register rd, const MemOperand& rs) {
+  GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_);
+}
+
+
+void Assembler::lwr(Register rd, const MemOperand& rs) {
+  GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_);
 }
 
 
 void Assembler::sb(Register rd, const MemOperand& rs) {
-  GenInstrImmediate(SB, rs.rm(), rd, rs.offset_);
+  if (is_int16(rs.offset_)) {
+    GenInstrImmediate(SB, rs.rm(), rd, rs.offset_);
+  } else {  // Offset > 16 bits, use multiple instructions to store.
+    LoadRegPlusOffsetToAt(rs);
+    GenInstrImmediate(SB, at, rd, 0);  // Equiv to sb(rd, MemOperand(at, 0));
+  }
+}
+
+
+void Assembler::sh(Register rd, const MemOperand& rs) {
+  if (is_int16(rs.offset_)) {
+    GenInstrImmediate(SH, rs.rm(), rd, rs.offset_);
+  } else {  // Offset > 16 bits, use multiple instructions to store.
+    LoadRegPlusOffsetToAt(rs);
+    GenInstrImmediate(SH, at, rd, 0);  // Equiv to sh(rd, MemOperand(at, 0));
+  }
 }
 
 
 void Assembler::sw(Register rd, const MemOperand& rs) {
-  GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
+  if (is_int16(rs.offset_)) {
+    GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
+  } else {  // Offset > 16 bits, use multiple instructions to store.
+    LoadRegPlusOffsetToAt(rs);
+    GenInstrImmediate(SW, at, rd, 0);  // Equiv to sw(rd, MemOperand(at, 0));
+  }
+
+  // Eliminate pattern: pop(), push(r).
+  //     addiu sp, sp, Operand(kPointerSize);
+  //     addiu sp, sp, Operand(-kPointerSize);
+  // ->  sw r, MemOpernad(sp, 0);
+  if (can_peephole_optimize(3) &&
+     // Pattern.
+     instr_at(pc_ - 1 * kInstrSize) ==
+       (kPushRegPattern | (rd.code() << kRtShift)) &&
+     instr_at(pc_ - 2 * kInstrSize) == kPushInstruction &&
+     instr_at(pc_ - 3 * kInstrSize) == kPopInstruction) {
+    pc_ -= 3 * kInstrSize;
+    GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
+    if (FLAG_print_peephole_optimization) {
+      PrintF("%x pop()/push(reg) eliminated\n", pc_offset());
+    }
+  }
+}
+
+
+void Assembler::swl(Register rd, const MemOperand& rs) {
+  GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_);
+}
+
+
+void Assembler::swr(Register rd, const MemOperand& rs) {
+  GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_);
 }
 
 
@@ -841,7 +1476,8 @@
 
 void Assembler::tltu(Register rs, Register rt, uint16_t code) {
   ASSERT(is_uint10(code));
-  Instr instr = SPECIAL | TLTU | rs.code() << kRsShift
+  Instr instr =
+      SPECIAL | TLTU | rs.code() << kRsShift
       | rt.code() << kRtShift | code << 6;
   emit(instr);
 }
@@ -896,6 +1532,54 @@
 }
 
 
+// Conditional move.
+void Assembler::movz(Register rd, Register rs, Register rt) {
+  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVZ);
+}
+
+
+void Assembler::movn(Register rd, Register rs, Register rt) {
+  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVN);
+}
+
+
+void Assembler::movt(Register rd, Register rs, uint16_t cc) {
+  Register rt;
+  rt.code_ = (cc & 0x0003) << 2 | 1;
+  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
+}
+
+
+void Assembler::movf(Register rd, Register rs, uint16_t cc) {
+  Register rt;
+  rt.code_ = (cc & 0x0003) << 2 | 0;
+  GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
+}
+
+
+// Bit twiddling.
+void Assembler::clz(Register rd, Register rs) {
+  // Clz instr requires same GPR number in 'rd' and 'rt' fields.
+  GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ);
+}
+
+
+void Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) {
+  // Should be called via MacroAssembler::Ins.
+  // Ins instr has 'rt' field as dest, and two uint5: msb, lsb.
+  ASSERT(mips32r2);
+  GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS);
+}
+
+
+void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
+  // Should be called via MacroAssembler::Ext.
+  // Ext instr has 'rt' field as dest, and two uint5: msb, lsb.
+  ASSERT(mips32r2);
+  GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT);
+}
+
+
 //--------Coprocessor-instructions----------------
 
 // Load, store, move.
@@ -905,7 +1589,12 @@
 
 
 void Assembler::ldc1(FPURegister fd, const MemOperand& src) {
-  GenInstrImmediate(LDC1, src.rm(), fd, src.offset_);
+  // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
+  // load to two 32-bit loads.
+  GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
+  FPURegister nextfpreg;
+  nextfpreg.setcode(fd.code() + 1);
+  GenInstrImmediate(LWC1, src.rm(), nextfpreg, src.offset_ + 4);
 }
 
 
@@ -915,27 +1604,74 @@
 
 
 void Assembler::sdc1(FPURegister fd, const MemOperand& src) {
-  GenInstrImmediate(SDC1, src.rm(), fd, src.offset_);
+  // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
+  // store to two 32-bit stores.
+  GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
+  FPURegister nextfpreg;
+  nextfpreg.setcode(fd.code() + 1);
+  GenInstrImmediate(SWC1, src.rm(), nextfpreg, src.offset_ + 4);
 }
 
 
-void Assembler::mtc1(FPURegister fs, Register rt) {
+void Assembler::mtc1(Register rt, FPURegister fs) {
   GenInstrRegister(COP1, MTC1, rt, fs, f0);
 }
 
 
-void Assembler::mthc1(FPURegister fs, Register rt) {
-  GenInstrRegister(COP1, MTHC1, rt, fs, f0);
-}
-
-
-void Assembler::mfc1(FPURegister fs, Register rt) {
+void Assembler::mfc1(Register rt, FPURegister fs) {
   GenInstrRegister(COP1, MFC1, rt, fs, f0);
 }
 
 
-void Assembler::mfhc1(FPURegister fs, Register rt) {
-  GenInstrRegister(COP1, MFHC1, rt, fs, f0);
+void Assembler::ctc1(Register rt, FPUControlRegister fs) {
+  GenInstrRegister(COP1, CTC1, rt, fs);
+}
+
+
+void Assembler::cfc1(Register rt, FPUControlRegister fs) {
+  GenInstrRegister(COP1, CFC1, rt, fs);
+}
+
+
+// Arithmetic.
+
+void Assembler::add_d(FPURegister fd, FPURegister fs, FPURegister ft) {
+  GenInstrRegister(COP1, D, ft, fs, fd, ADD_D);
+}
+
+
+void Assembler::sub_d(FPURegister fd, FPURegister fs, FPURegister ft) {
+  GenInstrRegister(COP1, D, ft, fs, fd, SUB_D);
+}
+
+
+void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) {
+  GenInstrRegister(COP1, D, ft, fs, fd, MUL_D);
+}
+
+
+void Assembler::div_d(FPURegister fd, FPURegister fs, FPURegister ft) {
+  GenInstrRegister(COP1, D, ft, fs, fd, DIV_D);
+}
+
+
+void Assembler::abs_d(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, D, f0, fs, fd, ABS_D);
+}
+
+
+void Assembler::mov_d(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, D, f0, fs, fd, MOV_D);
+}
+
+
+void Assembler::neg_d(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, D, f0, fs, fd, NEG_D);
+}
+
+
+void Assembler::sqrt_d(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, D, f0, fs, fd, SQRT_D);
 }
 
 
@@ -951,22 +1687,107 @@
 }
 
 
+void Assembler::trunc_w_s(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_W_S);
+}
+
+
+void Assembler::trunc_w_d(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_W_D);
+}
+
+
+void Assembler::round_w_s(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, S, f0, fs, fd, ROUND_W_S);
+}
+
+
+void Assembler::round_w_d(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, D, f0, fs, fd, ROUND_W_D);
+}
+
+
+void Assembler::floor_w_s(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_W_S);
+}
+
+
+void Assembler::floor_w_d(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_W_D);
+}
+
+
+void Assembler::ceil_w_s(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S);
+}
+
+
+void Assembler::ceil_w_d(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D);
+}
+
+
 void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) {
+  ASSERT(mips32r2);
   GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S);
 }
 
 
 void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) {
+  ASSERT(mips32r2);
   GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D);
 }
 
 
+void Assembler::trunc_l_s(FPURegister fd, FPURegister fs) {
+  ASSERT(mips32r2);
+  GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S);
+}
+
+
+void Assembler::trunc_l_d(FPURegister fd, FPURegister fs) {
+  ASSERT(mips32r2);
+  GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D);
+}
+
+
+void Assembler::round_l_s(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S);
+}
+
+
+void Assembler::round_l_d(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, D, f0, fs, fd, ROUND_L_D);
+}
+
+
+void Assembler::floor_l_s(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_L_S);
+}
+
+
+void Assembler::floor_l_d(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_L_D);
+}
+
+
+void Assembler::ceil_l_s(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, S, f0, fs, fd, CEIL_L_S);
+}
+
+
+void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) {
+  GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D);
+}
+
+
 void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) {
   GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W);
 }
 
 
 void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) {
+  ASSERT(mips32r2);
   GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L);
 }
 
@@ -982,6 +1803,7 @@
 
 
 void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) {
+  ASSERT(mips32r2);
   GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L);
 }
 
@@ -993,7 +1815,8 @@
 
 // Conditions.
 void Assembler::c(FPUCondition cond, SecondaryField fmt,
-    FPURegister ft, FPURegister fs, uint16_t cc) {
+    FPURegister fs, FPURegister ft, uint16_t cc) {
+  ASSERT(isolate()->cpu_features()->IsEnabled(FPU));
   ASSERT(is_uint3(cc));
   ASSERT((fmt & ~(31 << kRsShift)) == 0);
   Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift
@@ -1002,7 +1825,18 @@
 }
 
 
+void Assembler::fcmp(FPURegister src1, const double src2,
+      FPUCondition cond) {
+  ASSERT(isolate()->cpu_features()->IsSupported(FPU));
+  ASSERT(src2 == 0.0);
+  mtc1(zero_reg, f14);
+  cvt_d_w(f14, f14);
+  c(cond, D, src1, f14, 0);
+}
+
+
 void Assembler::bc1f(int16_t offset, uint16_t cc) {
+  ASSERT(isolate()->cpu_features()->IsEnabled(FPU));
   ASSERT(is_uint3(cc));
   Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask);
   emit(instr);
@@ -1010,6 +1844,7 @@
 
 
 void Assembler::bc1t(int16_t offset, uint16_t cc) {
+  ASSERT(isolate()->cpu_features()->IsEnabled(FPU));
   ASSERT(is_uint3(cc));
   Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
   emit(instr);
@@ -1018,66 +1853,32 @@
 
 // Debugging.
 void Assembler::RecordJSReturn() {
-  WriteRecordedPositions();
+  positions_recorder()->WriteRecordedPositions();
   CheckBuffer();
   RecordRelocInfo(RelocInfo::JS_RETURN);
 }
 
 
+void Assembler::RecordDebugBreakSlot() {
+  positions_recorder()->WriteRecordedPositions();
+  CheckBuffer();
+  RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
+}
+
+
 void Assembler::RecordComment(const char* msg) {
-  if (FLAG_debug_code) {
+  if (FLAG_code_comments) {
     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;
-}
-
-
-void Assembler::RecordStatementPosition(int pos) {
-  if (pos == RelocInfo::kNoPosition) return;
-  ASSERT(pos >= 0);
-  current_statement_position_ = pos;
-}
-
-
-bool Assembler::WriteRecordedPositions() {
-  bool written = false;
-
-  // 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_;
-    written = true;
-  }
-
-  // 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_;
-    written = true;
-  }
-
-  // Return whether something was written.
-  return written;
-}
-
-
 void Assembler::GrowBuffer() {
   if (!own_buffer_) FATAL("external code buffer is too small");
 
   // Compute new buffer size.
-  CodeDesc desc;  // the new buffer
+  CodeDesc desc;  // The new buffer.
   if (buffer_size_ < 4*KB) {
     desc.buffer_size = 4*KB;
   } else if (buffer_size_ < 1*MB) {
@@ -1085,7 +1886,7 @@
   } else {
     desc.buffer_size = buffer_size_ + 1*MB;
   }
-  CHECK_GT(desc.buffer_size, 0);  // no overflow
+  CHECK_GT(desc.buffer_size, 0);  // No overflow.
 
   // Setup new buffer.
   desc.buffer = NewArray<byte>(desc.buffer_size);
@@ -1108,7 +1909,6 @@
   reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
                                reloc_info_writer.last_pc() + pc_delta);
 
-
   // On ia32 and ARM pc relative addressing is used, and we thus need to apply a
   // shift by pc_delta. But on MIPS the target address it directly loaded, so
   // we do not need to relocate here.
@@ -1117,11 +1917,26 @@
 }
 
 
+void Assembler::db(uint8_t data) {
+  CheckBuffer();
+  *reinterpret_cast<uint8_t*>(pc_) = data;
+  pc_ += sizeof(uint8_t);
+}
+
+
+void Assembler::dd(uint32_t data) {
+  CheckBuffer();
+  *reinterpret_cast<uint32_t*>(pc_) = data;
+  pc_ += sizeof(uint32_t);
+}
+
+
 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::JS_RETURN && rmode <= RelocInfo::STATEMENT_POSITION) {
+  RelocInfo rinfo(pc_, rmode, data);  // We do not try to reuse pool constants.
+  if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) {
     // Adjust code for new modes.
-    ASSERT(RelocInfo::IsJSReturn(rmode)
+    ASSERT(RelocInfo::IsDebugBreakSlot(rmode)
+           || RelocInfo::IsJSReturn(rmode)
            || RelocInfo::IsComment(rmode)
            || RelocInfo::IsPosition(rmode));
     // These modes do not need an entry in the constant pool.
@@ -1133,12 +1948,72 @@
         !FLAG_debug_code) {
       return;
     }
-    ASSERT(buffer_space() >= kMaxRelocSize);  // too late to grow buffer here
+    ASSERT(buffer_space() >= kMaxRelocSize);  // Too late to grow buffer here.
     reloc_info_writer.Write(&rinfo);
   }
 }
 
 
+void Assembler::BlockTrampolinePoolFor(int instructions) {
+  BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
+}
+
+
+void Assembler::CheckTrampolinePool(bool force_emit) {
+  // Calculate the offset of the next check.
+  next_buffer_check_ = pc_offset() + kCheckConstInterval;
+
+  int dist = pc_offset() - last_trampoline_pool_end_;
+
+  if (dist <= kMaxDistBetweenPools && !force_emit) {
+    return;
+  }
+
+  // Some small sequences of instructions must not be broken up by the
+  // insertion of a trampoline pool; such sequences are protected by setting
+  // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_,
+  // which are both checked here. Also, recursive calls to CheckTrampolinePool
+  // are blocked by trampoline_pool_blocked_nesting_.
+  if ((trampoline_pool_blocked_nesting_ > 0) ||
+      (pc_offset() < no_trampoline_pool_before_)) {
+    // Emission is currently blocked; make sure we try again as soon as
+    // possible.
+    if (trampoline_pool_blocked_nesting_ > 0) {
+      next_buffer_check_ = pc_offset() + kInstrSize;
+    } else {
+      next_buffer_check_ = no_trampoline_pool_before_;
+    }
+    return;
+  }
+
+  // First we emit jump (2 instructions), then we emit trampoline pool.
+  { BlockTrampolinePoolScope block_trampoline_pool(this);
+    Label after_pool;
+    b(&after_pool);
+    nop();
+
+    int pool_start = pc_offset();
+    for (int i = 0; i < kSlotsPerTrampoline; i++) {
+      b(&after_pool);
+      nop();
+    }
+    for (int i = 0; i < kLabelsPerTrampoline; i++) {
+      emit(0);
+    }
+    last_trampoline_pool_end_ = pc_offset() - kInstrSize;
+    bind(&after_pool);
+    trampolines_.Add(Trampoline(pool_start,
+                                kSlotsPerTrampoline,
+                                kLabelsPerTrampoline));
+
+    // Since a trampoline pool was just emitted,
+    // move the check offset forward by the standard interval.
+    next_buffer_check_ = last_trampoline_pool_end_ + kMaxDistBetweenPools;
+  }
+  return;
+}
+
+
 Address Assembler::target_address_at(Address pc) {
   Instr instr1 = instr_at(pc);
   Instr instr2 = instr_at(pc + kInstrSize);
@@ -1157,7 +2032,7 @@
       return reinterpret_cast<Address>((instr2 & kImm16Mask) << 16);
     }
   } else if ((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) {
-    // 32 bits value.
+    // 32 bit value.
     return reinterpret_cast<Address>(
         (instr1 & kImm16Mask) << 16 | (instr2 & kImm16Mask));
   }
@@ -1176,38 +2051,37 @@
 #ifdef DEBUG
   Instr instr1 = instr_at(pc);
 
-  // Check we have indeed the result from a li with MustUseAt true.
+  // Check we have indeed the result from a li with MustUseReg true.
   CHECK(((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) ||
         ((instr1 == 0) && ((instr2 & kOpcodeMask)== ADDIU ||
                            (instr2 & kOpcodeMask)== ORI ||
                            (instr2 & kOpcodeMask)== LUI)));
 #endif
 
-
   uint32_t rt_code = (instr2 & kRtFieldMask);
   uint32_t* p = reinterpret_cast<uint32_t*>(pc);
   uint32_t itarget = reinterpret_cast<uint32_t>(target);
 
   if (is_int16(itarget)) {
-    // nop
-    // addiu rt zero_reg j
+    // nop.
+    // addiu rt zero_reg j.
     *p = nopInstr;
-    *(p+1) = ADDIU | rt_code | (itarget & LOMask);
-  } else if (!(itarget & HIMask)) {
-    // nop
-    // ori rt zero_reg j
+    *(p+1) = ADDIU | rt_code | (itarget & kImm16Mask);
+  } else if (!(itarget & kHiMask)) {
+    // nop.
+    // ori rt zero_reg j.
     *p = nopInstr;
-    *(p+1) = ORI | rt_code | (itarget & LOMask);
-  } else if (!(itarget & LOMask)) {
-    // nop
-    // lui rt (HIMask & itarget)>>16
+    *(p+1) = ORI | rt_code | (itarget & kImm16Mask);
+  } else if (!(itarget & kImm16Mask)) {
+    // nop.
+    // lui rt (kHiMask & itarget) >> kLuiShift.
     *p = nopInstr;
-    *(p+1) = LUI | rt_code | ((itarget & HIMask)>>16);
+    *(p+1) = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift);
   } else {
-    // lui rt (HIMask & itarget)>>16
-    // ori rt rt, (LOMask & itarget)
-    *p = LUI | rt_code | ((itarget & HIMask)>>16);
-    *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & LOMask);
+    // lui rt (kHiMask & itarget) >> kLuiShift.
+    // ori rt rt, (kImm16Mask & itarget).
+    *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift);
+    *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask);
   }
 
   CPU::FlushICache(pc, 2 * sizeof(int32_t));
diff --git a/src/mips/assembler-mips.h b/src/mips/assembler-mips.h
index a687c2b..5a6e271 100644
--- a/src/mips/assembler-mips.h
+++ b/src/mips/assembler-mips.h
@@ -41,8 +41,6 @@
 #include "constants-mips.h"
 #include "serialize.h"
 
-using namespace assembler::mips;
-
 namespace v8 {
 namespace internal {
 
@@ -73,6 +71,44 @@
 
 // Core register.
 struct Register {
+  static const int kNumRegisters = v8::internal::kNumRegisters;
+  static const int kNumAllocatableRegisters = 14;  // v0 through t7
+
+  static int ToAllocationIndex(Register reg) {
+    return reg.code() - 2;  // zero_reg and 'at' are skipped.
+  }
+
+  static Register FromAllocationIndex(int index) {
+    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
+    return from_code(index + 2);  // zero_reg and 'at' are skipped.
+  }
+
+  static const char* AllocationIndexToString(int index) {
+    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
+    const char* const names[] = {
+      "v0",
+      "v1",
+      "a0",
+      "a1",
+      "a2",
+      "a3",
+      "t0",
+      "t1",
+      "t2",
+      "t3",
+      "t4",
+      "t5",
+      "t6",
+      "t7",
+    };
+    return names[index];
+  }
+
+  static Register from_code(int code) {
+    Register r = { code };
+    return r;
+  }
+
   bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
   bool is(Register reg) const { return code_ == reg.code_; }
   int code() const {
@@ -88,40 +124,41 @@
   int code_;
 };
 
-extern const Register no_reg;
+const Register no_reg = { -1 };
 
-extern const Register zero_reg;
-extern const Register at;
-extern const Register v0;
-extern const Register v1;
-extern const Register a0;
-extern const Register a1;
-extern const Register a2;
-extern const Register a3;
-extern const Register t0;
-extern const Register t1;
-extern const Register t2;
-extern const Register t3;
-extern const Register t4;
-extern const Register t5;
-extern const Register t6;
-extern const Register t7;
-extern const Register s0;
-extern const Register s1;
-extern const Register s2;
-extern const Register s3;
-extern const Register s4;
-extern const Register s5;
-extern const Register s6;
-extern const Register s7;
-extern const Register t8;
-extern const Register t9;
-extern const Register k0;
-extern const Register k1;
-extern const Register gp;
-extern const Register sp;
-extern const Register s8_fp;
-extern const Register ra;
+const Register zero_reg = { 0 };
+const Register at = { 1 };
+const Register v0 = { 2 };
+const Register v1 = { 3 };
+const Register a0 = { 4 };
+const Register a1 = { 5 };
+const Register a2 = { 6 };
+const Register a3 = { 7 };
+const Register t0 = { 8 };
+const Register t1 = { 9 };
+const Register t2 = { 10 };
+const Register t3 = { 11 };
+const Register t4 = { 12 };
+const Register t5 = { 13 };
+const Register t6 = { 14 };
+const Register t7 = { 15 };
+const Register s0 = { 16 };
+const Register s1 = { 17 };
+const Register s2 = { 18 };
+const Register s3 = { 19 };
+const Register s4 = { 20 };
+const Register s5 = { 21 };
+const Register s6 = { 22 };
+const Register s7 = { 23 };
+const Register t8 = { 24 };
+const Register t9 = { 25 };
+const Register k0 = { 26 };
+const Register k1 = { 27 };
+const Register gp = { 28 };
+const Register sp = { 29 };
+const Register s8_fp = { 30 };
+const Register ra = { 31 };
+
 
 int ToNumber(Register reg);
 
@@ -129,7 +166,50 @@
 
 // Coprocessor register.
 struct FPURegister {
-  bool is_valid() const { return 0 <= code_ && code_ < kNumFPURegister ; }
+  static const int kNumRegisters = v8::internal::kNumFPURegisters;
+  // f0 has been excluded from allocation. This is following ia32
+  // where xmm0 is excluded.
+  static const int kNumAllocatableRegisters = 15;
+
+  static int ToAllocationIndex(FPURegister reg) {
+    ASSERT(reg.code() != 0);
+    ASSERT(reg.code() % 2 == 0);
+    return (reg.code() / 2) - 1;
+  }
+
+  static FPURegister FromAllocationIndex(int index) {
+    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
+    return from_code((index + 1) * 2);
+  }
+
+  static const char* AllocationIndexToString(int index) {
+    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
+    const char* const names[] = {
+      "f2",
+      "f4",
+      "f6",
+      "f8",
+      "f10",
+      "f12",
+      "f14",
+      "f16",
+      "f18",
+      "f20",
+      "f22",
+      "f24",
+      "f26",
+      "f28",
+      "f30"
+    };
+    return names[index];
+  }
+
+  static FPURegister from_code(int code) {
+    FPURegister r = { code };
+    return r;
+  }
+
+  bool is_valid() const { return 0 <= code_ && code_ < kNumFPURegisters ; }
   bool is(FPURegister creg) const { return code_ == creg.code_; }
   int code() const {
     ASSERT(is_valid());
@@ -139,84 +219,77 @@
     ASSERT(is_valid());
     return 1 << code_;
   }
-
+  void setcode(int f) {
+    code_ = f;
+    ASSERT(is_valid());
+  }
   // Unfortunately we can't make this private in a struct.
   int code_;
 };
 
-extern const FPURegister no_creg;
+typedef FPURegister DoubleRegister;
 
-extern const FPURegister f0;
-extern const FPURegister f1;
-extern const FPURegister f2;
-extern const FPURegister f3;
-extern const FPURegister f4;
-extern const FPURegister f5;
-extern const FPURegister f6;
-extern const FPURegister f7;
-extern const FPURegister f8;
-extern const FPURegister f9;
-extern const FPURegister f10;
-extern const FPURegister f11;
-extern const FPURegister f12;  // arg
-extern const FPURegister f13;
-extern const FPURegister f14;  // arg
-extern const FPURegister f15;
-extern const FPURegister f16;
-extern const FPURegister f17;
-extern const FPURegister f18;
-extern const FPURegister f19;
-extern const FPURegister f20;
-extern const FPURegister f21;
-extern const FPURegister f22;
-extern const FPURegister f23;
-extern const FPURegister f24;
-extern const FPURegister f25;
-extern const FPURegister f26;
-extern const FPURegister f27;
-extern const FPURegister f28;
-extern const FPURegister f29;
-extern const FPURegister f30;
-extern const FPURegister f31;
+const FPURegister no_creg = { -1 };
 
+const FPURegister f0 = { 0 };  // Return value in hard float mode.
+const FPURegister f1 = { 1 };
+const FPURegister f2 = { 2 };
+const FPURegister f3 = { 3 };
+const FPURegister f4 = { 4 };
+const FPURegister f5 = { 5 };
+const FPURegister f6 = { 6 };
+const FPURegister f7 = { 7 };
+const FPURegister f8 = { 8 };
+const FPURegister f9 = { 9 };
+const FPURegister f10 = { 10 };
+const FPURegister f11 = { 11 };
+const FPURegister f12 = { 12 };  // Arg 0 in hard float mode.
+const FPURegister f13 = { 13 };
+const FPURegister f14 = { 14 };  // Arg 1 in hard float mode.
+const FPURegister f15 = { 15 };
+const FPURegister f16 = { 16 };
+const FPURegister f17 = { 17 };
+const FPURegister f18 = { 18 };
+const FPURegister f19 = { 19 };
+const FPURegister f20 = { 20 };
+const FPURegister f21 = { 21 };
+const FPURegister f22 = { 22 };
+const FPURegister f23 = { 23 };
+const FPURegister f24 = { 24 };
+const FPURegister f25 = { 25 };
+const FPURegister f26 = { 26 };
+const FPURegister f27 = { 27 };
+const FPURegister f28 = { 28 };
+const FPURegister f29 = { 29 };
+const FPURegister f30 = { 30 };
+const FPURegister f31 = { 31 };
 
-// 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);
+// FPU (coprocessor 1) control registers.
+// Currently only FCSR (#31) is implemented.
+struct FPUControlRegister {
+  static const int kFCSRRegister = 31;
+  static const int kInvalidFPUControlRegister = -1;
 
-inline Condition ReverseCondition(Condition cc) {
-  switch (cc) {
-    case Uless:
-      return Ugreater;
-    case Ugreater:
-      return Uless;
-    case Ugreater_equal:
-      return Uless_equal;
-    case Uless_equal:
-      return Ugreater_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
+  bool is_valid() const { return code_ == kFCSRRegister; }
+  bool is(FPUControlRegister creg) const { return code_ == creg.code_; }
+  int code() const {
+    ASSERT(is_valid());
+    return code_;
+  }
+  int bit() const {
+    ASSERT(is_valid());
+    return 1 << code_;
+  }
+  void setcode(int f) {
+    code_ = f;
+    ASSERT(is_valid());
+  }
+  // Unfortunately we can't make this private in a struct.
+  int code_;
 };
 
-inline Hint NegateHint(Hint hint) {
-  return no_hint;
-}
+const FPUControlRegister no_fpucreg = { -1 };
+const FPUControlRegister FCSR = { kFCSRRegister };
 
 
 // -----------------------------------------------------------------------------
@@ -258,16 +331,75 @@
 class MemOperand : public Operand {
  public:
 
-  explicit MemOperand(Register rn, int16_t offset = 0);
+  explicit MemOperand(Register rn, int32_t offset = 0);
 
  private:
-  int16_t offset_;
+  int32_t offset_;
 
   friend class Assembler;
 };
 
 
-class Assembler : public Malloced {
+// CpuFeatures keeps track of which features are supported by the target CPU.
+// Supported features must be enabled by a Scope before use.
+class CpuFeatures {
+ public:
+  // Detect features of the target CPU. Set safe defaults if the serializer
+  // is enabled (snapshots must be portable).
+  void Probe(bool portable);
+
+  // Check whether a feature is supported by the target CPU.
+  bool IsSupported(CpuFeature f) const {
+    if (f == FPU && !FLAG_enable_fpu) return false;
+    return (supported_ & (1u << f)) != 0;
+  }
+
+  // Check whether a feature is currently enabled.
+  bool IsEnabled(CpuFeature f) const {
+    return (enabled_ & (1u << f)) != 0;
+  }
+
+  // Enable a specified feature within a scope.
+  class Scope BASE_EMBEDDED {
+#ifdef DEBUG
+   public:
+    explicit Scope(CpuFeature f)
+        : cpu_features_(Isolate::Current()->cpu_features()),
+          isolate_(Isolate::Current()) {
+      ASSERT(cpu_features_->IsSupported(f));
+      ASSERT(!Serializer::enabled() ||
+             (cpu_features_->found_by_runtime_probing_ & (1u << f)) == 0);
+      old_enabled_ = cpu_features_->enabled_;
+      cpu_features_->enabled_ |= 1u << f;
+    }
+    ~Scope() {
+      ASSERT_EQ(Isolate::Current(), isolate_);
+      cpu_features_->enabled_ = old_enabled_;
+     }
+   private:
+    unsigned old_enabled_;
+    CpuFeatures* cpu_features_;
+    Isolate* isolate_;
+#else
+   public:
+    explicit Scope(CpuFeature f) {}
+#endif
+  };
+
+ private:
+  CpuFeatures();
+
+  unsigned supported_;
+  unsigned enabled_;
+  unsigned found_by_runtime_probing_;
+
+  friend class Isolate;
+
+  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
+};
+
+
+class Assembler : public AssemblerBase {
  public:
   // Create an assembler. Instructions and relocation information are emitted
   // into a buffer, with the instructions starting from the beginning and the
@@ -285,6 +417,9 @@
   Assembler(void* buffer, int buffer_size);
   ~Assembler();
 
+  // Overrides the default provided by FLAG_debug_code.
+  void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
+
   // 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.
@@ -320,12 +455,6 @@
   // The high 8 bits are set to zero.
   void label_at_put(Label* L, int at_offset);
 
-  // Size of an instruction.
-  static const int kInstrSize = sizeof(Instr);
-
-  // Difference between address of current opcode and target address offset.
-  static const int kBranchPCOffset = 4;
-
   // Read/Modify the code target address in the branch/call instruction at pc.
   static Address target_address_at(Address pc);
   static void set_target_address_at(Address pc, Address target);
@@ -344,8 +473,25 @@
     set_target_address_at(instruction_payload, target);
   }
 
-  static const int kCallTargetSize = 3 * kPointerSize;
-  static const int kExternalTargetSize = 3 * kPointerSize;
+  // Size of an instruction.
+  static const int kInstrSize = sizeof(Instr);
+
+  // Difference between address of current opcode and target address offset.
+  static const int kBranchPCOffset = 4;
+
+  // Here we are patching the address in the LUI/ORI instruction pair.
+  // These values are used in the serialization process and must be zero for
+  // MIPS platform, as Code, Embedded Object or External-reference pointers
+  // are split across two consecutive instructions and don't exist separately
+  // in the code, so the serializer should not step forwards in memory after
+  // a target is resolved and written.
+  static const int kCallTargetSize = 0 * kInstrSize;
+  static const int kExternalTargetSize = 0 * kInstrSize;
+
+  // Number of consecutive instructions used to store 32bit constant.
+  // Used in RelocInfo::target_address_address() function to tell serializer
+  // address of the instruction that follows LUI/ORI instruction pair.
+  static const int kInstructionsFor32BitConstant = 2;
 
   // Distance between the instruction referring to the address of the call
   // target and the return address.
@@ -353,16 +499,53 @@
 
   // Distance between start of patched return sequence and the emitted address
   // to jump to.
-  static const int kPatchReturnSequenceAddressOffset = kInstrSize;
+  static const int kPatchReturnSequenceAddressOffset = 0;
 
   // Distance between start of patched debug break slot and the emitted address
   // to jump to.
-  static const int kPatchDebugBreakSlotAddressOffset = kInstrSize;
+  static const int kPatchDebugBreakSlotAddressOffset =  0 * kInstrSize;
+
+  // Difference between address of current opcode and value read from pc
+  // register.
+  static const int kPcLoadDelta = 4;
+
+  // Number of instructions used for the JS return sequence. The constant is
+  // used by the debugger to patch the JS return sequence.
+  static const int kJSReturnSequenceInstructions = 7;
+  static const int kDebugBreakSlotInstructions = 4;
+  static const int kDebugBreakSlotLength =
+      kDebugBreakSlotInstructions * kInstrSize;
+
 
   // ---------------------------------------------------------------------------
   // Code generation.
 
-  void nop() { sll(zero_reg, zero_reg, 0); }
+  // 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);
+  // Aligns code to something that's optimal for a jump target for the platform.
+  void CodeTargetAlign();
+
+  // Different nop operations are used by the code generator to detect certain
+  // states of the generated code.
+  enum NopMarkerTypes {
+    NON_MARKING_NOP = 0,
+    DEBUG_BREAK_NOP,
+    // IC markers.
+    PROPERTY_ACCESS_INLINED,
+    PROPERTY_ACCESS_INLINED_CONTEXT,
+    PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
+    // Helper values.
+    LAST_CODE_MARKER,
+    FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
+  };
+
+  // type == 0 is the default non-marking type.
+  void nop(unsigned int type = 0) {
+    ASSERT(type < 32);
+    sll(zero_reg, zero_reg, type, true);
+  }
 
 
   //------- Branch and jump  instructions --------
@@ -400,9 +583,7 @@
   //-------Data-processing-instructions---------
 
   // Arithmetic.
-  void add(Register rd, Register rs, Register rt);
   void addu(Register rd, Register rs, Register rt);
-  void sub(Register rd, Register rs, Register rt);
   void subu(Register rd, Register rs, Register rt);
   void mult(Register rs, Register rt);
   void multu(Register rs, Register rt);
@@ -410,7 +591,6 @@
   void divu(Register rs, Register rt);
   void mul(Register rd, Register rs, Register rt);
 
-  void addi(Register rd, Register rs, int32_t j);
   void addiu(Register rd, Register rs, int32_t j);
 
   // Logical.
@@ -425,21 +605,33 @@
   void lui(Register rd, int32_t j);
 
   // Shifts.
-  void sll(Register rd, Register rt, uint16_t sa);
+  // Please note: sll(zero_reg, zero_reg, x) instructions are reserved as nop
+  // and may cause problems in normal code. coming_from_nop makes sure this
+  // doesn't happen.
+  void sll(Register rd, Register rt, uint16_t sa, bool coming_from_nop = false);
   void sllv(Register rd, Register rt, Register rs);
   void srl(Register rd, Register rt, uint16_t sa);
   void srlv(Register rd, Register rt, Register rs);
   void sra(Register rt, Register rd, uint16_t sa);
   void srav(Register rt, Register rd, Register rs);
+  void rotr(Register rd, Register rt, uint16_t sa);
+  void rotrv(Register rd, Register rt, Register rs);
 
 
   //------------Memory-instructions-------------
 
   void lb(Register rd, const MemOperand& rs);
   void lbu(Register rd, const MemOperand& rs);
+  void lh(Register rd, const MemOperand& rs);
+  void lhu(Register rd, const MemOperand& rs);
   void lw(Register rd, const MemOperand& rs);
+  void lwl(Register rd, const MemOperand& rs);
+  void lwr(Register rd, const MemOperand& rs);
   void sb(Register rd, const MemOperand& rs);
+  void sh(Register rd, const MemOperand& rs);
   void sw(Register rd, const MemOperand& rs);
+  void swl(Register rd, const MemOperand& rs);
+  void swr(Register rd, const MemOperand& rs);
 
 
   //-------------Misc-instructions--------------
@@ -463,6 +655,16 @@
   void slti(Register rd, Register rs, int32_t j);
   void sltiu(Register rd, Register rs, int32_t j);
 
+  // Conditional move.
+  void movz(Register rd, Register rs, Register rt);
+  void movn(Register rd, Register rs, Register rt);
+  void movt(Register rd, Register rs, uint16_t cc = 0);
+  void movf(Register rd, Register rs, uint16_t cc = 0);
+
+  // Bit twiddling.
+  void clz(Register rd, Register rs);
+  void ins_(Register rt, Register rs, uint16_t pos, uint16_t size);
+  void ext_(Register rt, Register rs, uint16_t pos, uint16_t size);
 
   //--------Coprocessor-instructions----------------
 
@@ -473,19 +675,44 @@
   void swc1(FPURegister fs, const MemOperand& dst);
   void sdc1(FPURegister fs, const MemOperand& dst);
 
-  // When paired with MTC1 to write a value to a 64-bit FPR, the MTC1 must be
-  // executed first, followed by the MTHC1.
-  void mtc1(FPURegister fs, Register rt);
-  void mthc1(FPURegister fs, Register rt);
-  void mfc1(FPURegister fs, Register rt);
-  void mfhc1(FPURegister fs, Register rt);
+  void mtc1(Register rt, FPURegister fs);
+  void mfc1(Register rt, FPURegister fs);
+
+  void ctc1(Register rt, FPUControlRegister fs);
+  void cfc1(Register rt, FPUControlRegister fs);
+
+  // Arithmetic.
+  void add_d(FPURegister fd, FPURegister fs, FPURegister ft);
+  void sub_d(FPURegister fd, FPURegister fs, FPURegister ft);
+  void mul_d(FPURegister fd, FPURegister fs, FPURegister ft);
+  void div_d(FPURegister fd, FPURegister fs, FPURegister ft);
+  void abs_d(FPURegister fd, FPURegister fs);
+  void mov_d(FPURegister fd, FPURegister fs);
+  void neg_d(FPURegister fd, FPURegister fs);
+  void sqrt_d(FPURegister fd, FPURegister fs);
 
   // Conversion.
   void cvt_w_s(FPURegister fd, FPURegister fs);
   void cvt_w_d(FPURegister fd, FPURegister fs);
+  void trunc_w_s(FPURegister fd, FPURegister fs);
+  void trunc_w_d(FPURegister fd, FPURegister fs);
+  void round_w_s(FPURegister fd, FPURegister fs);
+  void round_w_d(FPURegister fd, FPURegister fs);
+  void floor_w_s(FPURegister fd, FPURegister fs);
+  void floor_w_d(FPURegister fd, FPURegister fs);
+  void ceil_w_s(FPURegister fd, FPURegister fs);
+  void ceil_w_d(FPURegister fd, FPURegister fs);
 
   void cvt_l_s(FPURegister fd, FPURegister fs);
   void cvt_l_d(FPURegister fd, FPURegister fs);
+  void trunc_l_s(FPURegister fd, FPURegister fs);
+  void trunc_l_d(FPURegister fd, FPURegister fs);
+  void round_l_s(FPURegister fd, FPURegister fs);
+  void round_l_d(FPURegister fd, FPURegister fs);
+  void floor_l_s(FPURegister fd, FPURegister fs);
+  void floor_l_d(FPURegister fd, FPURegister fs);
+  void ceil_l_s(FPURegister fd, FPURegister fs);
+  void ceil_l_d(FPURegister fd, FPURegister fs);
 
   void cvt_s_w(FPURegister fd, FPURegister fs);
   void cvt_s_l(FPURegister fd, FPURegister fs);
@@ -503,32 +730,60 @@
   void bc1f(Label* L, uint16_t cc = 0) { bc1f(branch_offset(L, false)>>2, cc); }
   void bc1t(int16_t offset, uint16_t cc = 0);
   void bc1t(Label* L, uint16_t cc = 0) { bc1t(branch_offset(L, false)>>2, cc); }
-
+  void fcmp(FPURegister src1, const double src2, FPUCondition cond);
 
   // Check the code size generated from label to here.
   int InstructionsGeneratedSince(Label* l) {
     return (pc_offset() - l->pos()) / kInstrSize;
   }
 
+  // Class for scoping postponing the trampoline pool generation.
+  class BlockTrampolinePoolScope {
+   public:
+    explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
+      assem_->StartBlockTrampolinePool();
+    }
+    ~BlockTrampolinePoolScope() {
+      assem_->EndBlockTrampolinePool();
+    }
+
+   private:
+    Assembler* assem_;
+
+    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
+  };
+
   // Debugging.
 
   // Mark address of the ExitJSFrame code.
   void RecordJSReturn();
 
+  // Mark address of a debug break slot.
+  void RecordDebugBreakSlot();
+
   // Record a comment relocation entry that can be used by a disassembler.
-  // Use --debug_code to enable.
+  // Use --code-comments to enable.
   void RecordComment(const char* msg);
 
-  void RecordPosition(int pos);
-  void RecordStatementPosition(int pos);
-  bool WriteRecordedPositions();
+  // Writes a single byte or word of data in the code stream.  Used for
+  // inline tables, e.g., jump-tables.
+  void db(uint8_t data);
+  void dd(uint32_t data);
 
   int32_t pc_offset() const { return pc_ - buffer_; }
-  int32_t current_position() const { return current_position_; }
-  int32_t current_statement_position() const {
-    return current_statement_position_;
+
+  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
+
+  bool can_peephole_optimize(int instructions) {
+    if (!allow_peephole_optimization_) return false;
+    if (last_bound_pos_ > pc_offset() - instructions * kInstrSize) return false;
+    return reloc_info_writer.last_pc() <= pc_ - instructions * kInstrSize;
   }
 
+  // Postpone the generation of the trampoline pool for the specified number of
+  // instructions.
+  void BlockTrampolinePoolFor(int instructions);
+
   // 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.
@@ -537,12 +792,9 @@
   // Get the number of bytes available in the buffer.
   inline int available_space() const { return reloc_info_writer.pos() - pc_; }
 
- protected:
-  int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; }
-
   // Read/patch instructions.
   static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
-  void instr_at_put(byte* pc, Instr instr) {
+  static void instr_at_put(byte* pc, Instr instr) {
     *reinterpret_cast<Instr*>(pc) = instr;
   }
   Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
@@ -551,7 +803,34 @@
   }
 
   // Check if an instruction is a branch of some kind.
-  bool is_branch(Instr instr);
+  static bool IsBranch(Instr instr);
+
+  static bool IsNop(Instr instr, unsigned int type);
+  static bool IsPop(Instr instr);
+  static bool IsPush(Instr instr);
+  static bool IsLwRegFpOffset(Instr instr);
+  static bool IsSwRegFpOffset(Instr instr);
+  static bool IsLwRegFpNegOffset(Instr instr);
+  static bool IsSwRegFpNegOffset(Instr instr);
+
+  static Register GetRt(Instr instr);
+
+  static int32_t GetBranchOffset(Instr instr);
+  static bool IsLw(Instr instr);
+  static int16_t GetLwOffset(Instr instr);
+  static Instr SetLwOffset(Instr instr, int16_t offset);
+
+  static bool IsSw(Instr instr);
+  static Instr SetSwOffset(Instr instr, int16_t offset);
+  static bool IsAddImmediate(Instr instr);
+  static Instr SetAddImmediateOffset(Instr instr, int16_t offset);
+
+  void CheckTrampolinePool(bool force_emit = false);
+
+ protected:
+  bool emit_debug_code() const { return emit_debug_code_; }
+
+  int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; }
 
   // Decode branch instruction at pos and return branch target pos.
   int target_at(int32_t pos);
@@ -560,11 +839,28 @@
   void target_at_put(int32_t pos, int32_t target_pos);
 
   // Say if we need to relocate with this mode.
-  bool MustUseAt(RelocInfo::Mode rmode);
+  bool MustUseReg(RelocInfo::Mode rmode);
 
   // Record reloc info for current pc_.
   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
 
+  // Block the emission of the trampoline pool before pc_offset.
+  void BlockTrampolinePoolBefore(int pc_offset) {
+    if (no_trampoline_pool_before_ < pc_offset)
+      no_trampoline_pool_before_ = pc_offset;
+  }
+
+  void StartBlockTrampolinePool() {
+    trampoline_pool_blocked_nesting_++;
+  }
+  void EndBlockTrampolinePool() {
+    trampoline_pool_blocked_nesting_--;
+  }
+
+  bool is_trampoline_pool_blocked() const {
+    return trampoline_pool_blocked_nesting_ > 0;
+  }
+
  private:
   // Code buffer:
   // The buffer into which code and relocation info are generated.
@@ -585,6 +881,22 @@
   static const int kGap = 32;
   byte* pc_;  // The program counter - moves forward.
 
+
+  // Repeated checking whether the trampoline pool should be emitted is rather
+  // expensive. By default we only check again once a number of instructions
+  // has been generated.
+  static const int kCheckConstIntervalInst = 32;
+  static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
+
+  int next_buffer_check_;  // pc offset of next buffer check.
+
+  // Emission of the trampoline pool may be blocked in some code sequences.
+  int trampoline_pool_blocked_nesting_;  // Block emission if this is not zero.
+  int no_trampoline_pool_before_;  // Block emission before this pc offset.
+
+  // Keep track of the last emitted pool to guarantee a maximal distance.
+  int last_trampoline_pool_end_;  // pc offset of the end of the last pool.
+
   // Relocation information generation.
   // Each relocation is encoded as a variable size value.
   static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
@@ -593,16 +905,11 @@
   // 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);
+  inline void CheckTrampolinePoolQuick();
 
   // Instruction generation.
   // We have 3 different kind of encoding layout on MIPS.
@@ -620,6 +927,13 @@
                         SecondaryField func = NULLSF);
 
   void GenInstrRegister(Opcode opcode,
+                        Register rs,
+                        Register rt,
+                        uint16_t msb,
+                        uint16_t lsb,
+                        SecondaryField func);
+
+  void GenInstrRegister(Opcode opcode,
                         SecondaryField fmt,
                         FPURegister ft,
                         FPURegister fs,
@@ -633,6 +947,12 @@
                         FPURegister fd,
                         SecondaryField func = NULLSF);
 
+  void GenInstrRegister(Opcode opcode,
+                        SecondaryField fmt,
+                        Register rt,
+                        FPUControlRegister fs,
+                        SecondaryField func = NULLSF);
+
 
   void GenInstrImmediate(Opcode opcode,
                          Register rs,
@@ -651,6 +971,8 @@
   void GenInstrJump(Opcode opcode,
                      uint32_t address);
 
+  // Helpers.
+  void LoadRegPlusOffsetToAt(const MemOperand& src);
 
   // Labels.
   void print(Label* L);
@@ -658,8 +980,85 @@
   void link_to(Label* L, Label* appendix);
   void next(Label* L);
 
+  // One trampoline consists of:
+  // - space for trampoline slots,
+  // - space for labels.
+  //
+  // Space for trampoline slots is equal to slot_count * 2 * kInstrSize.
+  // Space for trampoline slots preceeds space for labels. Each label is of one
+  // instruction size, so total amount for labels is equal to
+  // label_count *  kInstrSize.
+  class Trampoline {
+   public:
+    Trampoline(int start, int slot_count, int label_count) {
+      start_ = start;
+      next_slot_ = start;
+      free_slot_count_ = slot_count;
+      next_label_ = start + slot_count * 2 * kInstrSize;
+      free_label_count_ = label_count;
+      end_ = next_label_ + (label_count - 1) * kInstrSize;
+    }
+    int start() {
+      return start_;
+    }
+    int end() {
+      return end_;
+    }
+    int take_slot() {
+      int trampoline_slot = next_slot_;
+      ASSERT(free_slot_count_ > 0);
+      free_slot_count_--;
+      next_slot_ += 2 * kInstrSize;
+      return trampoline_slot;
+    }
+    int take_label() {
+      int label_pos = next_label_;
+      ASSERT(free_label_count_ > 0);
+      free_label_count_--;
+      next_label_ += kInstrSize;
+      return label_pos;
+    }
+   private:
+    int start_;
+    int end_;
+    int next_slot_;
+    int free_slot_count_;
+    int next_label_;
+    int free_label_count_;
+  };
+
+  int32_t get_label_entry(int32_t pos, bool next_pool = true);
+  int32_t get_trampoline_entry(int32_t pos, bool next_pool = true);
+
+  static const int kSlotsPerTrampoline = 2304;
+  static const int kLabelsPerTrampoline = 8;
+  static const int kTrampolineInst =
+      2 * kSlotsPerTrampoline + kLabelsPerTrampoline;
+  static const int kTrampolineSize = kTrampolineInst * kInstrSize;
+  static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
+  static const int kMaxDistBetweenPools =
+      kMaxBranchOffset - 2 * kTrampolineSize;
+
+  List<Trampoline> trampolines_;
+
   friend class RegExpMacroAssemblerMIPS;
   friend class RelocInfo;
+  friend class CodePatcher;
+  friend class BlockTrampolinePoolScope;
+
+  PositionsRecorder positions_recorder_;
+  bool allow_peephole_optimization_;
+  bool emit_debug_code_;
+  friend class PositionsRecorder;
+  friend class EnsureSpace;
+};
+
+
+class EnsureSpace BASE_EMBEDDED {
+ public:
+  explicit EnsureSpace(Assembler* assembler) {
+    assembler->CheckBuffer();
+  }
 };
 
 } }  // namespace v8::internal
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index 9532938..b4bab8e 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -33,6 +33,8 @@
 
 #include "codegen-inl.h"
 #include "debug.h"
+#include "deoptimizer.h"
+#include "full-codegen.h"
 #include "runtime.h"
 
 namespace v8 {
@@ -59,11 +61,21 @@
 }
 
 
+void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
   UNIMPLEMENTED_MIPS();
 }
 
 
+void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
   UNIMPLEMENTED_MIPS();
 }
@@ -74,111 +86,43 @@
 }
 
 
-static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
-                                             bool is_construct) {
-  // Called from JSEntryStub::GenerateBody
-
-  // Registers:
-  // a0: entry_address
-  // a1: function
-  // a2: reveiver_pointer
-  // a3: argc
-  // s0: argv
-  //
-  // Stack:
-  // arguments slots
-  // handler frame
-  // entry frame
-  // callee saved registers + ra
-  // 4 args slots
-  // args
-
-  // Clear the context before we push it when entering the JS frame.
-  __ li(cp, Operand(0, RelocInfo::NONE));
-
-  // Enter an internal frame.
-  __ EnterInternalFrame();
-
-  // Set up the context from the function argument.
-  __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
-
-  // Set up the roots register.
-  ExternalReference roots_address = ExternalReference::roots_address();
-  __ li(s6, Operand(roots_address));
-
-  // Push the function and the receiver onto the stack.
-  __ MultiPushReversed(a1.bit() | a2.bit());
-
-  // Copy arguments to the stack in a loop.
-  // a3: argc
-  // s0: argv, ie points to first arg
-  Label loop, entry;
-  __ sll(t0, a3, kPointerSizeLog2);
-  __ add(t2, s0, t0);
-  __ b(&entry);
-  __ nop();   // Branch delay slot nop.
-  // t2 points past last arg.
-  __ bind(&loop);
-  __ lw(t0, MemOperand(s0));  // Read next parameter.
-  __ addiu(s0, s0, kPointerSize);
-  __ lw(t0, MemOperand(t0));  // Dereference handle.
-  __ Push(t0);  // Push parameter.
-  __ bind(&entry);
-  __ Branch(ne, &loop, s0, Operand(t2));
-
-  // Registers:
-  // a0: entry_address
-  // a1: function
-  // a2: reveiver_pointer
-  // a3: argc
-  // s0: argv
-  // s6: roots_address
-  //
-  // Stack:
-  // arguments
-  // receiver
-  // function
-  // arguments slots
-  // handler frame
-  // entry frame
-  // callee saved registers + ra
-  // 4 args slots
-  // args
-
-  // Initialize all JavaScript callee-saved registers, since they will be seen
-  // by the garbage collector as part of handlers.
-  __ LoadRoot(t4, Heap::kUndefinedValueRootIndex);
-  __ mov(s1, t4);
-  __ mov(s2, t4);
-  __ mov(s3, t4);
-  __ mov(s4, s4);
-  __ mov(s5, t4);
-  // s6 holds the root address. Do not clobber.
-  // s7 is cp. Do not init.
-
-  // Invoke the code and pass argc as a0.
-  __ mov(a0, a3);
-  if (is_construct) {
-    UNIMPLEMENTED_MIPS();
-    __ break_(0x164);
-  } else {
-    ParameterCount actual(a0);
-    __ InvokeFunction(a1, actual, CALL_FUNCTION);
-  }
-
-  __ LeaveInternalFrame();
-
-  __ Jump(ra);
-}
-
-
 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
-  Generate_JSEntryTrampolineHelper(masm, false);
+  UNIMPLEMENTED_MIPS();
 }
 
 
 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
-  Generate_JSEntryTrampolineHelper(masm, true);
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
 }
 
 
@@ -194,7 +138,6 @@
 
 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
   UNIMPLEMENTED_MIPS();
-  __ break_(0x201);
 }
 
 
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
new file mode 100644
index 0000000..6cc272c
--- /dev/null
+++ b/src/mips/code-stubs-mips.cc
@@ -0,0 +1,752 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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"
+
+#if defined(V8_TARGET_ARCH_MIPS)
+
+#include "bootstrapper.h"
+#include "code-stubs.h"
+#include "codegen-inl.h"
+#include "regexp-macro-assembler.h"
+
+namespace v8 {
+namespace internal {
+
+
+#define __ ACCESS_MASM(masm)
+
+
+void ToNumberStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FastNewClosureStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FastNewContextStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// Takes a Smi and converts to an IEEE 64 bit floating point value in two
+// registers.  The format is 1 sign bit, 11 exponent bits (biased 1023) and
+// 52 fraction bits (20 in the first word, 32 in the second).  Zeros is a
+// scratch register.  Destroys the source register.  No GC occurs during this
+// stub so you don't have to set up the frame.
+class ConvertToDoubleStub : public CodeStub {
+ public:
+  ConvertToDoubleStub(Register result_reg_1,
+                      Register result_reg_2,
+                      Register source_reg,
+                      Register scratch_reg)
+      : result1_(result_reg_1),
+        result2_(result_reg_2),
+        source_(source_reg),
+        zeros_(scratch_reg) { }
+
+ private:
+  Register result1_;
+  Register result2_;
+  Register source_;
+  Register zeros_;
+
+  // Minor key encoding in 16 bits.
+  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
+  class OpBits: public BitField<Token::Value, 2, 14> {};
+
+  Major MajorKey() { return ConvertToDouble; }
+  int MinorKey() {
+    // Encode the parameters in a unique 16 bit value.
+    return  result1_.code() +
+           (result2_.code() << 4) +
+           (source_.code() << 8) +
+           (zeros_.code() << 12);
+  }
+
+  void Generate(MacroAssembler* masm);
+
+  const char* GetName() { return "ConvertToDoubleStub"; }
+
+#ifdef DEBUG
+  void Print() { PrintF("ConvertToDoubleStub\n"); }
+#endif
+};
+
+
+void ConvertToDoubleStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+class FloatingPointHelper : public AllStatic {
+ public:
+
+  enum Destination {
+    kFPURegisters,
+    kCoreRegisters
+  };
+
+
+  // Loads smis from a0 and a1 (right and left in binary operations) into
+  // floating point registers. Depending on the destination the values ends up
+  // either f14 and f12 or in a2/a3 and a0/a1 respectively. If the destination
+  // is floating point registers FPU must be supported. If core registers are
+  // requested when FPU is supported f12 and f14 will be scratched.
+  static void LoadSmis(MacroAssembler* masm,
+                       Destination destination,
+                       Register scratch1,
+                       Register scratch2);
+
+  // Loads objects from a0 and a1 (right and left in binary operations) into
+  // floating point registers. Depending on the destination the values ends up
+  // either f14 and f12 or in a2/a3 and a0/a1 respectively. If the destination
+  // is floating point registers FPU must be supported. If core registers are
+  // requested when FPU is supported f12 and f14 will still be scratched. If
+  // either a0 or a1 is not a number (not smi and not heap number object) the
+  // not_number label is jumped to with a0 and a1 intact.
+  static void LoadOperands(MacroAssembler* masm,
+                           FloatingPointHelper::Destination destination,
+                           Register heap_number_map,
+                           Register scratch1,
+                           Register scratch2,
+                           Label* not_number);
+  // Loads the number from object into dst as a 32-bit integer if possible. If
+  // the object is not a 32-bit integer control continues at the label
+  // not_int32. If FPU is supported double_scratch is used but not scratch2.
+  static void LoadNumberAsInteger(MacroAssembler* masm,
+                                  Register object,
+                                  Register dst,
+                                  Register heap_number_map,
+                                  Register scratch1,
+                                  Register scratch2,
+                                  FPURegister double_scratch,
+                                  Label* not_int32);
+ private:
+  static void LoadNumber(MacroAssembler* masm,
+                         FloatingPointHelper::Destination destination,
+                         Register object,
+                         FPURegister dst,
+                         Register dst1,
+                         Register dst2,
+                         Register heap_number_map,
+                         Register scratch1,
+                         Register scratch2,
+                         Label* not_number);
+};
+
+
+void FloatingPointHelper::LoadSmis(MacroAssembler* masm,
+                                   FloatingPointHelper::Destination destination,
+                                   Register scratch1,
+                                   Register scratch2) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FloatingPointHelper::LoadOperands(
+    MacroAssembler* masm,
+    FloatingPointHelper::Destination destination,
+    Register heap_number_map,
+    Register scratch1,
+    Register scratch2,
+    Label* slow) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FloatingPointHelper::LoadNumber(MacroAssembler* masm,
+                                     Destination destination,
+                                     Register object,
+                                     FPURegister dst,
+                                     Register dst1,
+                                     Register dst2,
+                                     Register heap_number_map,
+                                     Register scratch1,
+                                     Register scratch2,
+                                     Label* not_number) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FloatingPointHelper::LoadNumberAsInteger(MacroAssembler* masm,
+                                              Register object,
+                                              Register dst,
+                                              Register heap_number_map,
+                                              Register scratch1,
+                                              Register scratch2,
+                                              FPURegister double_scratch,
+                                              Label* not_int32) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// See comment for class, this does NOT work for int32's that are in Smi range.
+void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void EmitNanCheck(MacroAssembler* masm, Condition cc) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
+                                                         Register object,
+                                                         Register result,
+                                                         Register scratch1,
+                                                         Register scratch2,
+                                                         Register scratch3,
+                                                         bool object_is_smi,
+                                                         Label* not_found) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void NumberToStringStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// On entry lhs_ (lhs) and rhs_ (rhs) are the things to be compared.
+// On exit, v0 is 0, positive, or negative (smi) to indicate the result
+// of the comparison.
+void CompareStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// This stub does not handle the inlined cases (Smis, Booleans, undefined).
+// The stub returns zero for false, and a non-zero value for true.
+void ToBooleanStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// We fall into this code if the operands were Smis, but the result was
+// not (eg. overflow).  We branch into this code (to the not_smi label) if
+// the operands were not both Smi.  The operands are in lhs and rhs.
+// To call the C-implemented binary fp operation routines we need to end up
+// with the double precision floating point operands in a0 and a1 (for the
+// value in a1) and a2 and a3 (for the value in a0).
+void GenericBinaryOpStub::HandleBinaryOpSlowCases(MacroAssembler* masm,
+                                    Label* not_smi,
+                                    Register lhs,
+                                    Register rhs,
+                                    const Builtins::JavaScript& builtin) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// For bitwise ops where the inputs are not both Smis we here try to determine
+// whether both inputs are either Smis or at least heap numbers that can be
+// represented by a 32 bit signed value.  We truncate towards zero as required
+// by the ES spec.  If this is the case we do the bitwise op and see if the
+// result is a Smi.  If so, great, otherwise we try to find a heap number to
+// write the answer into (either by allocating or by overwriting).
+// On entry the operands are in lhs (x) and rhs (y). (Result = x op y).
+// On exit the result is in v0.
+void GenericBinaryOpStub::HandleNonSmiBitwiseOp(MacroAssembler* masm,
+                                                Register lhs,
+                                                Register rhs) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void GenericBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) {
+  GenericBinaryOpStub stub(key, type_info);
+  return stub.GetCode();
+}
+
+
+Handle<Code> GetTypeRecordingBinaryOpStub(int key,
+    TRBinaryOpIC::TypeInfo type_info,
+    TRBinaryOpIC::TypeInfo result_type_info) {
+  TypeRecordingBinaryOpStub stub(key, type_info, result_type_info);
+  return stub.GetCode();
+}
+
+
+void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void TypeRecordingBinaryOpStub::GenerateTypeTransitionWithSavedArgs(
+    MacroAssembler* masm) {
+  UNIMPLEMENTED();
+}
+
+
+void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+const char* TypeRecordingBinaryOpStub::GetName() {
+  UNIMPLEMENTED_MIPS();
+  return name_;
+}
+
+
+
+void TypeRecordingBinaryOpStub::GenerateSmiSmiOperation(
+    MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
+                                                    bool smi_operands,
+                                                    Label* not_numbers,
+                                                    Label* gc_required) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// Generate the smi code. If the operation on smis are successful this return is
+// generated. If the result is not a smi and heap number allocation is not
+// requested the code falls through. If number allocation is requested but a
+// heap number cannot be allocated the code jumps to the lable gc_required.
+void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm,
+    Label* gc_required,
+    SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void TypeRecordingBinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation(
+    MacroAssembler* masm,
+    Register result,
+    Register heap_number_map,
+    Register scratch1,
+    Register scratch2,
+    Label* gc_required) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+
+void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
+  UNIMPLEMENTED_MIPS();
+  return Runtime::kAbort;
+}
+
+
+void StackCheckStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+bool CEntryStub::NeedsImmovableCode() {
+  return true;
+}
+
+
+void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm,
+                                          UncatchableExceptionType type) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CEntryStub::GenerateCore(MacroAssembler* masm,
+                              Label* throw_normal_exception,
+                              Label* throw_termination_exception,
+                              Label* throw_out_of_memory_exception,
+                              bool do_gc,
+                              bool always_allocate) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CEntryStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// Uses registers a0 to t0. Expected input is
+// object in a0 (or at sp+1*kPointerSize) and function in
+// a1 (or at sp), depending on whether or not
+// args_in_registers() is true.
+void InstanceofStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpExecStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CallFunctionStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// Unfortunately you have to run without snapshots to see most of these
+// names in the profile since most compare stubs end up in the snapshot.
+const char* CompareStub::GetName() {
+  UNIMPLEMENTED_MIPS();
+  return name_;
+}
+
+
+int CompareStub::MinorKey() {
+  UNIMPLEMENTED_MIPS();
+  return 0;
+}
+
+
+// StringCharCodeAtGenerator
+
+void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void StringCharCodeAtGenerator::GenerateSlow(
+    MacroAssembler* masm, const RuntimeCallHelper& call_helper) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// -------------------------------------------------------------------------
+// StringCharFromCodeGenerator
+
+void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void StringCharFromCodeGenerator::GenerateSlow(
+    MacroAssembler* masm, const RuntimeCallHelper& call_helper) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// -------------------------------------------------------------------------
+// StringCharAtGenerator
+
+void StringCharAtGenerator::GenerateFast(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void StringCharAtGenerator::GenerateSlow(
+    MacroAssembler* masm, const RuntimeCallHelper& call_helper) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+class StringHelper : public AllStatic {
+ public:
+  // Generate code for copying characters using a simple loop. This should only
+  // be used in places where the number of characters is small and the
+  // additional setup and checking in GenerateCopyCharactersLong adds too much
+  // overhead. Copying of overlapping regions is not supported.
+  // Dest register ends at the position after the last character written.
+  static void GenerateCopyCharacters(MacroAssembler* masm,
+                                     Register dest,
+                                     Register src,
+                                     Register count,
+                                     Register scratch,
+                                     bool ascii);
+
+  // Generate code for copying a large number of characters. This function
+  // is allowed to spend extra time setting up conditions to make copying
+  // faster. Copying of overlapping regions is not supported.
+  // Dest register ends at the position after the last character written.
+  static void GenerateCopyCharactersLong(MacroAssembler* masm,
+                                         Register dest,
+                                         Register src,
+                                         Register count,
+                                         Register scratch1,
+                                         Register scratch2,
+                                         Register scratch3,
+                                         Register scratch4,
+                                         Register scratch5,
+                                         int flags);
+
+
+  // Probe the symbol table for a two character string. If the string is
+  // not found by probing a jump to the label not_found is performed. This jump
+  // does not guarantee that the string is not in the symbol table. If the
+  // string is found the code falls through with the string in register r0.
+  // Contents of both c1 and c2 registers are modified. At the exit c1 is
+  // guaranteed to contain halfword with low and high bytes equal to
+  // initial contents of c1 and c2 respectively.
+  static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
+                                                   Register c1,
+                                                   Register c2,
+                                                   Register scratch1,
+                                                   Register scratch2,
+                                                   Register scratch3,
+                                                   Register scratch4,
+                                                   Register scratch5,
+                                                   Label* not_found);
+
+  // Generate string hash.
+  static void GenerateHashInit(MacroAssembler* masm,
+                               Register hash,
+                               Register character);
+
+  static void GenerateHashAddCharacter(MacroAssembler* masm,
+                                       Register hash,
+                                       Register character);
+
+  static void GenerateHashGetHash(MacroAssembler* masm,
+                                  Register hash);
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
+};
+
+
+void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
+                                          Register dest,
+                                          Register src,
+                                          Register count,
+                                          Register scratch,
+                                          bool ascii) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+enum CopyCharactersFlags {
+  COPY_ASCII = 1,
+  DEST_ALWAYS_ALIGNED = 2
+};
+
+
+void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm,
+                                              Register dest,
+                                              Register src,
+                                              Register count,
+                                              Register scratch1,
+                                              Register scratch2,
+                                              Register scratch3,
+                                              Register scratch4,
+                                              Register scratch5,
+                                              int flags) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
+                                                        Register c1,
+                                                        Register c2,
+                                                        Register scratch1,
+                                                        Register scratch2,
+                                                        Register scratch3,
+                                                        Register scratch4,
+                                                        Register scratch5,
+                                                        Label* not_found) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void StringHelper::GenerateHashInit(MacroAssembler* masm,
+                                      Register hash,
+                                      Register character) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
+                                              Register hash,
+                                              Register character) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
+                                         Register hash) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void SubStringStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
+                                                        Register right,
+                                                        Register left,
+                                                        Register scratch1,
+                                                        Register scratch2,
+                                                        Register scratch3,
+                                                        Register scratch4) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void StringCompareStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void StringAddStub::Generate(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void ICCompareStub::GenerateMiss(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void GenerateFastPixelArrayLoad(MacroAssembler* masm,
+                                Register receiver,
+                                Register key,
+                                Register elements_map,
+                                Register elements,
+                                Register scratch1,
+                                Register scratch2,
+                                Register result,
+                                Label* not_pixel_array,
+                                Label* key_not_smi,
+                                Label* out_of_range) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+#undef __
+
+} }  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_MIPS
+
diff --git a/src/mips/code-stubs-mips.h b/src/mips/code-stubs-mips.h
new file mode 100644
index 0000000..675730a
--- /dev/null
+++ b/src/mips/code-stubs-mips.h
@@ -0,0 +1,511 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_MIPS_CODE_STUBS_ARM_H_
+#define V8_MIPS_CODE_STUBS_ARM_H_
+
+#include "ic-inl.h"
+
+
+namespace v8 {
+namespace internal {
+
+
+// Compute a transcendental math function natively, or call the
+// TranscendentalCache runtime function.
+class TranscendentalCacheStub: public CodeStub {
+ public:
+  explicit TranscendentalCacheStub(TranscendentalCache::Type type)
+      : type_(type) {}
+  void Generate(MacroAssembler* masm);
+ private:
+  TranscendentalCache::Type type_;
+  Major MajorKey() { return TranscendentalCache; }
+  int MinorKey() { return type_; }
+  Runtime::FunctionId RuntimeFunction();
+};
+
+
+class ToBooleanStub: public CodeStub {
+ public:
+  explicit ToBooleanStub(Register tos) : tos_(tos) { }
+
+  void Generate(MacroAssembler* masm);
+
+ private:
+  Register tos_;
+  Major MajorKey() { return ToBoolean; }
+  int MinorKey() { return tos_.code(); }
+};
+
+
+class GenericBinaryOpStub : public CodeStub {
+ public:
+  static const int kUnknownIntValue = -1;
+
+  GenericBinaryOpStub(Token::Value op,
+                      OverwriteMode mode,
+                      Register lhs,
+                      Register rhs,
+                      int constant_rhs = kUnknownIntValue)
+      : op_(op),
+        mode_(mode),
+        lhs_(lhs),
+        rhs_(rhs),
+        constant_rhs_(constant_rhs),
+        specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op, constant_rhs)),
+        runtime_operands_type_(BinaryOpIC::UNINIT_OR_SMI),
+        name_(NULL) { }
+
+  GenericBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info)
+      : op_(OpBits::decode(key)),
+        mode_(ModeBits::decode(key)),
+        lhs_(LhsRegister(RegisterBits::decode(key))),
+        rhs_(RhsRegister(RegisterBits::decode(key))),
+        constant_rhs_(KnownBitsForMinorKey(KnownIntBits::decode(key))),
+        specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op_, constant_rhs_)),
+        runtime_operands_type_(type_info),
+        name_(NULL) { }
+
+ private:
+  Token::Value op_;
+  OverwriteMode mode_;
+  Register lhs_;
+  Register rhs_;
+  int constant_rhs_;
+  bool specialized_on_rhs_;
+  BinaryOpIC::TypeInfo runtime_operands_type_;
+  char* name_;
+
+  static const int kMaxKnownRhs = 0x40000000;
+  static const int kKnownRhsKeyBits = 6;
+
+  // Minor key encoding in 16 bits.
+  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
+  class OpBits: public BitField<Token::Value, 2, 6> {};
+  class TypeInfoBits: public BitField<int, 8, 3> {};
+  class RegisterBits: public BitField<bool, 11, 1> {};
+  class KnownIntBits: public BitField<int, 12, kKnownRhsKeyBits> {};
+
+  Major MajorKey() { return GenericBinaryOp; }
+  int MinorKey() {
+    ASSERT((lhs_.is(a0) && rhs_.is(a1)) ||
+           (lhs_.is(a1) && rhs_.is(a0)));
+    // Encode the parameters in a unique 16 bit value.
+    return OpBits::encode(op_)
+           | ModeBits::encode(mode_)
+           | KnownIntBits::encode(MinorKeyForKnownInt())
+           | TypeInfoBits::encode(runtime_operands_type_)
+           | RegisterBits::encode(lhs_.is(a0));
+  }
+
+  void Generate(MacroAssembler* masm);
+  void HandleNonSmiBitwiseOp(MacroAssembler* masm,
+                             Register lhs,
+                             Register rhs);
+  void HandleBinaryOpSlowCases(MacroAssembler* masm,
+                               Label* not_smi,
+                               Register lhs,
+                               Register rhs,
+                               const Builtins::JavaScript& builtin);
+  void GenerateTypeTransition(MacroAssembler* masm);
+
+  static bool RhsIsOneWeWantToOptimizeFor(Token::Value op, int constant_rhs) {
+    if (constant_rhs == kUnknownIntValue) return false;
+    if (op == Token::DIV) return constant_rhs >= 2 && constant_rhs <= 3;
+    if (op == Token::MOD) {
+      if (constant_rhs <= 1) return false;
+      if (constant_rhs <= 10) return true;
+      if (constant_rhs <= kMaxKnownRhs && IsPowerOf2(constant_rhs)) return true;
+      return false;
+    }
+    return false;
+  }
+
+  int MinorKeyForKnownInt() {
+    if (!specialized_on_rhs_) return 0;
+    if (constant_rhs_ <= 10) return constant_rhs_ + 1;
+    ASSERT(IsPowerOf2(constant_rhs_));
+    int key = 12;
+    int d = constant_rhs_;
+    while ((d & 1) == 0) {
+      key++;
+      d >>= 1;
+    }
+    ASSERT(key >= 0 && key < (1 << kKnownRhsKeyBits));
+    return key;
+  }
+
+  int KnownBitsForMinorKey(int key) {
+    if (!key) return 0;
+    if (key <= 11) return key - 1;
+    int d = 1;
+    while (key != 12) {
+      key--;
+      d <<= 1;
+    }
+    return d;
+  }
+
+  Register LhsRegister(bool lhs_is_a0) {
+    return lhs_is_a0 ? a0 : a1;
+  }
+
+  Register RhsRegister(bool lhs_is_a0) {
+    return lhs_is_a0 ? a1 : a0;
+  }
+
+  bool HasSmiSmiFastPath() {
+    return op_ != Token::DIV;
+  }
+
+  bool ShouldGenerateSmiCode() {
+    return ((op_ != Token::DIV && op_ != Token::MOD) || specialized_on_rhs_) &&
+        runtime_operands_type_ != BinaryOpIC::HEAP_NUMBERS &&
+        runtime_operands_type_ != BinaryOpIC::STRINGS;
+  }
+
+  bool ShouldGenerateFPCode() {
+    return runtime_operands_type_ != BinaryOpIC::STRINGS;
+  }
+
+  virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
+
+  virtual InlineCacheState GetICState() {
+    return BinaryOpIC::ToState(runtime_operands_type_);
+  }
+
+  const char* GetName();
+
+  virtual void FinishCode(Code* code) {
+    code->set_binary_op_type(runtime_operands_type_);
+  }
+
+#ifdef DEBUG
+  void Print() {
+    if (!specialized_on_rhs_) {
+      PrintF("GenericBinaryOpStub (%s)\n", Token::String(op_));
+    } else {
+      PrintF("GenericBinaryOpStub (%s by %d)\n",
+             Token::String(op_),
+             constant_rhs_);
+    }
+  }
+#endif
+};
+
+class TypeRecordingBinaryOpStub: public CodeStub {
+ public:
+  TypeRecordingBinaryOpStub(Token::Value op, OverwriteMode mode)
+      : op_(op),
+        mode_(mode),
+        operands_type_(TRBinaryOpIC::UNINITIALIZED),
+        result_type_(TRBinaryOpIC::UNINITIALIZED),
+        name_(NULL) {
+    UNIMPLEMENTED_MIPS();
+  }
+
+  TypeRecordingBinaryOpStub(
+      int key,
+      TRBinaryOpIC::TypeInfo operands_type,
+      TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED)
+      : op_(OpBits::decode(key)),
+        mode_(ModeBits::decode(key)),
+        use_fpu_(FPUBits::decode(key)),
+        operands_type_(operands_type),
+        result_type_(result_type),
+        name_(NULL) { }
+
+ private:
+  enum SmiCodeGenerateHeapNumberResults {
+    ALLOW_HEAPNUMBER_RESULTS,
+    NO_HEAPNUMBER_RESULTS
+  };
+
+  Token::Value op_;
+  OverwriteMode mode_;
+  bool use_fpu_;
+
+  // Operand type information determined at runtime.
+  TRBinaryOpIC::TypeInfo operands_type_;
+  TRBinaryOpIC::TypeInfo result_type_;
+
+  char* name_;
+
+  const char* GetName();
+
+#ifdef DEBUG
+  void Print() {
+    PrintF("TypeRecordingBinaryOpStub %d (op %s), "
+           "(mode %d, runtime_type_info %s)\n",
+           MinorKey(),
+           Token::String(op_),
+           static_cast<int>(mode_),
+           TRBinaryOpIC::GetName(operands_type_));
+  }
+#endif
+
+  // Minor key encoding in 16 bits RRRTTTVOOOOOOOMM.
+  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
+  class OpBits: public BitField<Token::Value, 2, 7> {};
+  class FPUBits: public BitField<bool, 9, 1> {};
+  class OperandTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 10, 3> {};
+  class ResultTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 13, 3> {};
+
+  Major MajorKey() { return TypeRecordingBinaryOp; }
+  int MinorKey() {
+    return OpBits::encode(op_)
+           | ModeBits::encode(mode_)
+           | FPUBits::encode(use_fpu_)
+           | OperandTypeInfoBits::encode(operands_type_)
+           | ResultTypeInfoBits::encode(result_type_);
+  }
+
+  void Generate(MacroAssembler* masm);
+  void GenerateGeneric(MacroAssembler* masm);
+  void GenerateSmiSmiOperation(MacroAssembler* masm);
+  void GenerateFPOperation(MacroAssembler* masm,
+                           bool smi_operands,
+                           Label* not_numbers,
+                           Label* gc_required);
+  void GenerateSmiCode(MacroAssembler* masm,
+                       Label* gc_required,
+                       SmiCodeGenerateHeapNumberResults heapnumber_results);
+  void GenerateLoadArguments(MacroAssembler* masm);
+  void GenerateReturn(MacroAssembler* masm);
+  void GenerateUninitializedStub(MacroAssembler* masm);
+  void GenerateSmiStub(MacroAssembler* masm);
+  void GenerateInt32Stub(MacroAssembler* masm);
+  void GenerateHeapNumberStub(MacroAssembler* masm);
+  void GenerateStringStub(MacroAssembler* masm);
+  void GenerateGenericStub(MacroAssembler* masm);
+  void GenerateAddStrings(MacroAssembler* masm);
+  void GenerateCallRuntime(MacroAssembler* masm);
+
+  void GenerateHeapResultAllocation(MacroAssembler* masm,
+                                    Register result,
+                                    Register heap_number_map,
+                                    Register scratch1,
+                                    Register scratch2,
+                                    Label* gc_required);
+  void GenerateRegisterArgsPush(MacroAssembler* masm);
+  void GenerateTypeTransition(MacroAssembler* masm);
+  void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
+
+  virtual int GetCodeKind() { return Code::TYPE_RECORDING_BINARY_OP_IC; }
+
+  virtual InlineCacheState GetICState() {
+    return TRBinaryOpIC::ToState(operands_type_);
+  }
+
+  virtual void FinishCode(Code* code) {
+    code->set_type_recording_binary_op_type(operands_type_);
+    code->set_type_recording_binary_op_result_type(result_type_);
+  }
+
+  friend class CodeGenerator;
+};
+
+
+// Flag that indicates how to generate code for the stub StringAddStub.
+enum StringAddFlags {
+  NO_STRING_ADD_FLAGS = 0,
+  NO_STRING_CHECK_IN_STUB = 1 << 0  // Omit string check in stub.
+};
+
+
+class StringAddStub: public CodeStub {
+ public:
+  explicit StringAddStub(StringAddFlags flags) {
+    string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0);
+  }
+
+ private:
+  Major MajorKey() { return StringAdd; }
+  int MinorKey() { return string_check_ ? 0 : 1; }
+
+  void Generate(MacroAssembler* masm);
+
+  // Should the stub check whether arguments are strings?
+  bool string_check_;
+};
+
+
+class SubStringStub: public CodeStub {
+ public:
+  SubStringStub() {}
+
+ private:
+  Major MajorKey() { return SubString; }
+  int MinorKey() { return 0; }
+
+  void Generate(MacroAssembler* masm);
+};
+
+
+class StringCompareStub: public CodeStub {
+ public:
+  StringCompareStub() { }
+
+  // Compare two flat ASCII strings and returns result in v0.
+  // Does not use the stack.
+  static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
+                                              Register left,
+                                              Register right,
+                                              Register scratch1,
+                                              Register scratch2,
+                                              Register scratch3,
+                                              Register scratch4);
+
+ private:
+  Major MajorKey() { return StringCompare; }
+  int MinorKey() { return 0; }
+
+  void Generate(MacroAssembler* masm);
+};
+
+
+// This stub can convert a signed int32 to a heap number (double).  It does
+// not work for int32s that are in Smi range!  No GC occurs during this stub
+// so you don't have to set up the frame.
+class WriteInt32ToHeapNumberStub : public CodeStub {
+ public:
+  WriteInt32ToHeapNumberStub(Register the_int,
+                             Register the_heap_number,
+                             Register scratch,
+                             Register scratch2)
+      : the_int_(the_int),
+        the_heap_number_(the_heap_number),
+        scratch_(scratch),
+        sign_(scratch2) { }
+
+ private:
+  Register the_int_;
+  Register the_heap_number_;
+  Register scratch_;
+  Register sign_;
+
+  // Minor key encoding in 16 bits.
+  class IntRegisterBits: public BitField<int, 0, 4> {};
+  class HeapNumberRegisterBits: public BitField<int, 4, 4> {};
+  class ScratchRegisterBits: public BitField<int, 8, 4> {};
+
+  Major MajorKey() { return WriteInt32ToHeapNumber; }
+  int MinorKey() {
+    // Encode the parameters in a unique 16 bit value.
+    return IntRegisterBits::encode(the_int_.code())
+           | HeapNumberRegisterBits::encode(the_heap_number_.code())
+           | ScratchRegisterBits::encode(scratch_.code());
+  }
+
+  void Generate(MacroAssembler* masm);
+
+  const char* GetName() { return "WriteInt32ToHeapNumberStub"; }
+
+#ifdef DEBUG
+  void Print() { PrintF("WriteInt32ToHeapNumberStub\n"); }
+#endif
+};
+
+
+class NumberToStringStub: public CodeStub {
+ public:
+  NumberToStringStub() { }
+
+  // Generate code to do a lookup in the number string cache. If the number in
+  // the register object is found in the cache the generated code falls through
+  // with the result in the result register. The object and the result register
+  // can be the same. If the number is not found in the cache the code jumps to
+  // the label not_found with only the content of register object unchanged.
+  static void GenerateLookupNumberStringCache(MacroAssembler* masm,
+                                              Register object,
+                                              Register result,
+                                              Register scratch1,
+                                              Register scratch2,
+                                              Register scratch3,
+                                              bool object_is_smi,
+                                              Label* not_found);
+
+ private:
+  Major MajorKey() { return NumberToString; }
+  int MinorKey() { return 0; }
+
+  void Generate(MacroAssembler* masm);
+
+  const char* GetName() { return "NumberToStringStub"; }
+
+#ifdef DEBUG
+  void Print() {
+    PrintF("NumberToStringStub\n");
+  }
+#endif
+};
+
+
+// Enter C code from generated RegExp code in a way that allows
+// the C code to fix the return address in case of a GC.
+// Currently only needed on ARM and MIPS.
+class RegExpCEntryStub: public CodeStub {
+ public:
+  RegExpCEntryStub() {}
+  virtual ~RegExpCEntryStub() {}
+  void Generate(MacroAssembler* masm);
+
+ private:
+  Major MajorKey() { return RegExpCEntry; }
+  int MinorKey() { return 0; }
+
+  bool NeedsImmovableCode() { return true; }
+
+  const char* GetName() { return "RegExpCEntryStub"; }
+};
+
+
+// Generate code the to load an element from a pixel array. The receiver is
+// assumed to not be a smi and to have elements, the caller must guarantee this
+// precondition. If the receiver does not have elements that are pixel arrays,
+// the generated code jumps to not_pixel_array. If key is not a smi, then the
+// generated code branches to key_not_smi. Callers can specify NULL for
+// key_not_smi to signal that a smi check has already been performed on key so
+// that the smi check is not generated . If key is not a valid index within the
+// bounds of the pixel array, the generated code jumps to out_of_range.
+void GenerateFastPixelArrayLoad(MacroAssembler* masm,
+                                Register receiver,
+                                Register key,
+                                Register elements_map,
+                                Register elements,
+                                Register scratch1,
+                                Register scratch2,
+                                Register result,
+                                Label* not_pixel_array,
+                                Label* key_not_smi,
+                                Label* out_of_range);
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_MIPS_CODE_STUBS_ARM_H_
diff --git a/src/mips/codegen-mips-inl.h b/src/mips/codegen-mips-inl.h
index 3a511b8..be9ae9e 100644
--- a/src/mips/codegen-mips-inl.h
+++ b/src/mips/codegen-mips-inl.h
@@ -29,6 +29,8 @@
 #ifndef V8_MIPS_CODEGEN_MIPS_INL_H_
 #define V8_MIPS_CODEGEN_MIPS_INL_H_
 
+#include "virtual-frame-mips.h"
+
 namespace v8 {
 namespace internal {
 
@@ -42,26 +44,18 @@
 }
 
 
+// Note: this has been hacked for submisson. Mips branches require two
+//  additional operands: Register src1, const Operand& src2.
+void DeferredCode::Branch(Condition cond) {
+  __ Branch(&entry_label_, cond, zero_reg, Operand(0));
+}
+
+
 void Reference::GetValueAndSpill() {
   GetValue();
 }
 
 
-void CodeGenerator::VisitAndSpill(Statement* statement) {
-  Visit(statement);
-}
-
-
-void CodeGenerator::VisitStatementsAndSpill(ZoneList<Statement*>* statements) {
-  VisitStatements(statements);
-}
-
-
-void CodeGenerator::LoadAndSpill(Expression* expression) {
-  Load(expression);
-}
-
-
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc
index 79801f0..c1149df 100644
--- a/src/mips/codegen-mips.cc
+++ b/src/mips/codegen-mips.cc
@@ -31,36 +31,62 @@
 #if defined(V8_TARGET_ARCH_MIPS)
 
 #include "bootstrapper.h"
+#include "code-stubs.h"
 #include "codegen-inl.h"
 #include "compiler.h"
 #include "debug.h"
 #include "ic-inl.h"
+#include "jsregexp.h"
+#include "jump-target-inl.h"
 #include "parser.h"
+#include "regexp-macro-assembler.h"
+#include "regexp-stack.h"
 #include "register-allocator-inl.h"
 #include "runtime.h"
 #include "scopes.h"
+#include "stub-cache.h"
 #include "virtual-frame-inl.h"
-
-
+#include "virtual-frame-mips-inl.h"
 
 namespace v8 {
 namespace internal {
 
+
 #define __ ACCESS_MASM(masm_)
 
-
-
-// -----------------------------------------------------------------------------
+// -------------------------------------------------------------------------
 // Platform-specific DeferredCode functions.
 
-
 void DeferredCode::SaveRegisters() {
-  UNIMPLEMENTED_MIPS();
+  // On MIPS you either have a completely spilled frame or you
+  // handle it yourself, but at the moment there's no automation
+  // of registers and deferred code.
 }
 
 
 void DeferredCode::RestoreRegisters() {
-  UNIMPLEMENTED_MIPS();
+}
+
+
+// -------------------------------------------------------------------------
+// Platform-specific RuntimeCallHelper functions.
+
+void VirtualFrameRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const {
+  frame_state_->frame()->AssertIsSpilled();
+}
+
+
+void VirtualFrameRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
+}
+
+
+void StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const {
+  masm->EnterInternalFrame();
+}
+
+
+void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
+  masm->LeaveInternalFrame();
 }
 
 
@@ -69,21 +95,28 @@
 
 CodeGenState::CodeGenState(CodeGenerator* owner)
     : owner_(owner),
-      true_target_(NULL),
-      false_target_(NULL),
-      previous_(NULL) {
-  owner_->set_state(this);
+      previous_(owner->state()) {
+  owner->set_state(this);
 }
 
 
-CodeGenState::CodeGenState(CodeGenerator* owner,
+ConditionCodeGenState::ConditionCodeGenState(CodeGenerator* owner,
                            JumpTarget* true_target,
                            JumpTarget* false_target)
-    : owner_(owner),
+    : CodeGenState(owner),
       true_target_(true_target),
-      false_target_(false_target),
-      previous_(owner->state()) {
-  owner_->set_state(this);
+      false_target_(false_target) {
+  owner->set_state(this);
+}
+
+
+TypeInfoCodeGenState::TypeInfoCodeGenState(CodeGenerator* owner,
+                                           Slot* slot,
+                                           TypeInfo type_info)
+    : CodeGenState(owner),
+      slot_(slot) {
+  owner->set_state(this);
+  old_type_info_ = owner->set_type_info(slot, type_info);
 }
 
 
@@ -93,16 +126,25 @@
 }
 
 
+TypeInfoCodeGenState::~TypeInfoCodeGenState() {
+  owner()->set_type_info(slot_, old_type_info_);
+}
+
+
 // -----------------------------------------------------------------------------
-// CodeGenerator implementation
+// CodeGenerator implementation.
 
 CodeGenerator::CodeGenerator(MacroAssembler* masm)
     : deferred_(8),
       masm_(masm),
+      info_(NULL),
       frame_(NULL),
       allocator_(NULL),
       cc_reg_(cc_always),
       state_(NULL),
+      loop_nesting_(0),
+      type_info_(NULL),
+      function_return_(JumpTarget::BIDIRECTIONAL),
       function_return_is_shadowed_(false) {
 }
 
@@ -114,356 +156,249 @@
 // cp: callee's context
 
 void CodeGenerator::Generate(CompilationInfo* info) {
-  // Record the position for debugging purposes.
-  CodeForFunctionPosition(info->function());
-
-  // Initialize state.
-  info_ = info;
-  ASSERT(allocator_ == NULL);
-  RegisterAllocator register_allocator(this);
-  allocator_ = &register_allocator;
-  ASSERT(frame_ == NULL);
-  frame_ = new VirtualFrame();
-  cc_reg_ = cc_always;
-
-  {
-    CodeGenState state(this);
-
-    // Registers:
-    // a1: called JS function
-    // ra: return address
-    // fp: caller's frame pointer
-    // sp: stack pointer
-    // cp: callee's context
-    //
-    // Stack:
-    // arguments
-    // receiver
-
-    frame_->Enter();
-
-    // Allocate space for locals and initialize them.
-    frame_->AllocateStackSlots();
-
-    // Initialize the function return target.
-    function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
-    function_return_is_shadowed_ = false;
-
-    VirtualFrame::SpilledScope spilled_scope;
-    if (scope()->num_heap_slots() > 0) {
-      UNIMPLEMENTED_MIPS();
-    }
-
-    {
-      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++) {
-        UNIMPLEMENTED_MIPS();
-      }
-    }
-
-    // Store the arguments object.  This must happen after context
-    // initialization because the arguments object may be stored in the
-    // context.
-    if (scope()->arguments() != NULL) {
-      UNIMPLEMENTED_MIPS();
-    }
-
-    // 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) {
-      UNIMPLEMENTED_MIPS();
-    }
-
-    // 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) {
-        UNIMPLEMENTED_MIPS();
-      }
-#endif
-      VisitStatementsAndSpill(info->function()->body());
-    }
-  }
-
-  if (has_valid_frame() || function_return_.is_linked()) {
-    if (!function_return_.is_linked()) {
-      CodeForReturnPosition(info->function());
-    }
-    // Registers:
-    // v0: result
-    // sp: stack pointer
-    // fp: frame pointer
-    // cp: callee's context
-
-    __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
-
-    function_return_.Bind();
-    if (FLAG_trace) {
-      UNIMPLEMENTED_MIPS();
-    }
-
-    // Add a label for checking the size of the code used for returning.
-    Label check_exit_codesize;
-    masm_->bind(&check_exit_codesize);
-
-    masm_->mov(sp, fp);
-    masm_->lw(fp, MemOperand(sp, 0));
-    masm_->lw(ra, MemOperand(sp, 4));
-    masm_->addiu(sp, sp, 8);
-
-    // Here we use masm_-> instead of the __ macro to avoid the code coverage
-    // tool from instrumenting as we rely on the code size here.
-    // TODO(MIPS): Should we be able to use more than 0x1ffe parameters?
-    masm_->addiu(sp, sp, (scope()->num_parameters() + 1) * kPointerSize);
-    masm_->Jump(ra);
-    // The Jump automatically generates a nop in the branch delay slot.
-
-    // Check that the size of the code used for returning matches what is
-    // expected by the debugger.
-    ASSERT_EQ(kJSReturnSequenceLength,
-              masm_->InstructionsGeneratedSince(&check_exit_codesize));
-  }
-
-  // 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()) {
-    ProcessDeferred();
-  }
-
-  allocator_ = NULL;
+  UNIMPLEMENTED_MIPS();
 }
 
 
-void CodeGenerator::LoadReference(Reference* ref) {
-  VirtualFrame::SpilledScope spilled_scope;
-  Comment cmnt(masm_, "[ LoadReference");
-  Expression* e = ref->expression();
-  Property* property = e->AsProperty();
-  Variable* var = e->AsVariableProxy()->AsVariable();
-
-  if (property != NULL) {
-    UNIMPLEMENTED_MIPS();
-  } 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 {
-    UNIMPLEMENTED_MIPS();
-  }
-}
-
-
-void CodeGenerator::UnloadReference(Reference* ref) {
-  VirtualFrame::SpilledScope spilled_scope;
-  // Pop a reference from the stack while preserving TOS.
-  Comment cmnt(masm_, "[ UnloadReference");
-  int size = ref->size();
-  if (size > 0) {
-    frame_->EmitPop(a0);
-    frame_->Drop(size);
-    frame_->EmitPush(a0);
-  }
-  ref->set_unloaded();
+int CodeGenerator::NumberOfSlot(Slot* slot) {
+  UNIMPLEMENTED_MIPS();
+  return 0;
 }
 
 
 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:
-      UNIMPLEMENTED_MIPS();
-      return MemOperand(no_reg, 0);
-
-    case Slot::LOCAL:
-      return frame_->LocalAt(index);
-
-    case Slot::CONTEXT: {
-      UNIMPLEMENTED_MIPS();
-      return MemOperand(no_reg, 0);
-    }
-
-    default:
-      UNREACHABLE();
-      return MemOperand(no_reg, 0);
-  }
+  UNIMPLEMENTED_MIPS();
+  return MemOperand(zero_reg, 0);
 }
 
 
-// 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'.
+MemOperand CodeGenerator::ContextSlotOperandCheckExtensions(
+    Slot* slot,
+    Register tmp,
+    Register tmp2,
+    JumpTarget* slow) {
+  UNIMPLEMENTED_MIPS();
+  return MemOperand(zero_reg, 0);
+}
+
+
 void CodeGenerator::LoadCondition(Expression* x,
                                   JumpTarget* true_target,
                                   JumpTarget* false_target,
                                   bool force_cc) {
-  ASSERT(!has_cc());
-  int original_height = frame_->height();
-
-  { CodeGenState new_state(this, 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.
-    UNIMPLEMENTED_MIPS();
-  }
-  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));
+  UNIMPLEMENTED_MIPS();
 }
 
 
 void CodeGenerator::Load(Expression* x) {
-#ifdef DEBUG
-  int original_height = frame_->height();
-#endif
-  JumpTarget true_target;
-  JumpTarget false_target;
-  LoadCondition(x, &true_target, &false_target, false);
-
-  if (has_cc()) {
-    UNIMPLEMENTED_MIPS();
-  }
-
-  if (true_target.is_linked() || false_target.is_linked()) {
-    UNIMPLEMENTED_MIPS();
-  }
-  ASSERT(has_valid_frame());
-  ASSERT(!has_cc());
-  ASSERT(frame_->height() == original_height + 1);
+  UNIMPLEMENTED_MIPS();
 }
 
 
 void CodeGenerator::LoadGlobal() {
-  VirtualFrame::SpilledScope spilled_scope;
-  __ lw(a0, GlobalObject());
-  frame_->EmitPush(a0);
+  UNIMPLEMENTED_MIPS();
 }
 
 
-void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
-  VirtualFrame::SpilledScope spilled_scope;
-  if (slot->type() == Slot::LOOKUP) {
-    UNIMPLEMENTED_MIPS();
-  } else {
-    __ lw(a0, SlotOperand(slot, a2));
-    frame_->EmitPush(a0);
-    if (slot->var()->mode() == Variable::CONST) {
-      UNIMPLEMENTED_MIPS();
-    }
-  }
+void CodeGenerator::LoadGlobalReceiver(Register scratch) {
+  UNIMPLEMENTED_MIPS();
 }
 
 
-void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
-  ASSERT(slot != NULL);
-  if (slot->type() == Slot::LOOKUP) {
-      UNIMPLEMENTED_MIPS();
-  } else {
-    ASSERT(!slot->var()->is_dynamic());
+ArgumentsAllocationMode CodeGenerator::ArgumentsMode() {
+  UNIMPLEMENTED_MIPS();
+  return EAGER_ARGUMENTS_ALLOCATION;
+}
 
-    JumpTarget exit;
-    if (init_state == CONST_INIT) {
-      UNIMPLEMENTED_MIPS();
-    }
 
-    // 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. a2 may be loaded with context; used below in
-    // RecordWrite.
-    frame_->EmitPop(a0);
-    __ sw(a0, SlotOperand(slot, a2));
-    frame_->EmitPush(a0);
-    if (slot->type() == Slot::CONTEXT) {
-      UNIMPLEMENTED_MIPS();
-    }
-    // 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();
-    }
+void CodeGenerator::StoreArgumentsObject(bool initial) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::LoadTypeofExpression(Expression* x) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+Reference::Reference(CodeGenerator* cgen,
+                     Expression* expression,
+                     bool persist_after_get)
+    : cgen_(cgen),
+      expression_(expression),
+      type_(ILLEGAL),
+      persist_after_get_(persist_after_get) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+Reference::~Reference() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::LoadReference(Reference* ref) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::UnloadReference(Reference* ref) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// 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) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenericBinaryOperation(Token::Value op,
+                                           OverwriteMode overwrite_mode,
+                                           GenerateInlineSmi inline_smi,
+                                           int constant_rhs) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+class DeferredInlineSmiOperation: public DeferredCode {
+ public:
+  DeferredInlineSmiOperation(Token::Value op,
+                             int value,
+                             bool reversed,
+                             OverwriteMode overwrite_mode,
+                             Register tos)
+      : op_(op),
+        value_(value),
+        reversed_(reversed),
+        overwrite_mode_(overwrite_mode),
+        tos_register_(tos) {
+    set_comment("[ DeferredInlinedSmiOperation");
   }
+
+  virtual void Generate();
+  // This stub makes explicit calls to SaveRegisters(), RestoreRegisters() and
+  // Exit(). Currently on MIPS SaveRegisters() and RestoreRegisters() are empty
+  // methods, it is the responsibility of the deferred code to save and restore
+  // registers.
+  virtual bool AutoSaveAndRestore() { return false; }
+
+  void JumpToNonSmiInput(Condition cond, Register cmp1, const Operand& cmp2);
+  void JumpToAnswerOutOfRange(Condition cond,
+                              Register cmp1,
+                              const Operand& cmp2);
+
+ private:
+  void GenerateNonSmiInput();
+  void GenerateAnswerOutOfRange();
+  void WriteNonSmiAnswer(Register answer,
+                         Register heap_number,
+                         Register scratch);
+
+  Token::Value op_;
+  int value_;
+  bool reversed_;
+  OverwriteMode overwrite_mode_;
+  Register tos_register_;
+  Label non_smi_input_;
+  Label answer_out_of_range_;
+};
+
+
+// For bit operations we try harder and handle the case where the input is not
+// a Smi but a 32bits integer without calling the generic stub.
+void DeferredInlineSmiOperation::JumpToNonSmiInput(Condition cond,
+                                                   Register cmp1,
+                                                   const Operand& cmp2) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// For bit operations the result is always 32bits so we handle the case where
+// the result does not fit in a Smi without calling the generic stub.
+void DeferredInlineSmiOperation::JumpToAnswerOutOfRange(Condition cond,
+                                                        Register cmp1,
+                                                        const Operand& cmp2) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// On entry the non-constant side of the binary operation is in tos_register_
+// and the constant smi side is nowhere.  The tos_register_ is not used by the
+// virtual frame.  On exit the answer is in the tos_register_ and the virtual
+// frame is unchanged.
+void DeferredInlineSmiOperation::Generate() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// Convert and write the integer answer into heap_number.
+void DeferredInlineSmiOperation::WriteNonSmiAnswer(Register answer,
+                                                   Register heap_number,
+                                                   Register scratch) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void DeferredInlineSmiOperation::GenerateNonSmiInput() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void DeferredInlineSmiOperation::GenerateAnswerOutOfRange() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::SmiOperation(Token::Value op,
+                                 Handle<Object> value,
+                                 bool reversed,
+                                 OverwriteMode mode) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// On MIPS we load registers condReg1 and condReg2 with the values which should
+// be compared. With the CodeGenerator::cc_reg_ condition, functions will be
+// able to evaluate correctly the condition. (eg CodeGenerator::Branch)
+void CodeGenerator::Comparison(Condition cc,
+                               Expression* left,
+                               Expression* right,
+                               bool strict) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
+                                      CallFunctionFlags flags,
+                                      int position) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::CallApplyLazy(Expression* applicand,
+                                  Expression* receiver,
+                                  VariableProxy* arguments,
+                                  int position) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::Branch(bool if_true, JumpTarget* target) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::CheckStack() {
+  UNIMPLEMENTED_MIPS();
 }
 
 
 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
-  VirtualFrame::SpilledScope spilled_scope;
-  for (int i = 0; frame_ != NULL && i < statements->length(); i++) {
-    VisitAndSpill(statements->at(i));
-  }
+  UNIMPLEMENTED_MIPS();
 }
 
 
@@ -473,14 +408,7 @@
 
 
 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
-  VirtualFrame::SpilledScope spilled_scope;
-  frame_->EmitPush(cp);
-  __ li(t0, Operand(pairs));
-  frame_->EmitPush(t0);
-  __ li(t0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
-  frame_->EmitPush(t0);
-  frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
-  // The result is discarded.
+  UNIMPLEMENTED_MIPS();
 }
 
 
@@ -490,17 +418,7 @@
 
 
 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
-#ifdef DEBUG
-  int original_height = frame_->height();
-#endif
-  VirtualFrame::SpilledScope spilled_scope;
-  Comment cmnt(masm_, "[ ExpressionStatement");
-  CodeForStatementPosition(node);
-  Expression* expression = node->expression();
-  expression->MarkAsStatement();
-  LoadAndSpill(expression);
-  frame_->Drop();
-  ASSERT(frame_->height() == original_height);
+  UNIMPLEMENTED_MIPS();
 }
 
 
@@ -525,22 +443,12 @@
 
 
 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
-  VirtualFrame::SpilledScope spilled_scope;
-  Comment cmnt(masm_, "[ ReturnStatement");
+  UNIMPLEMENTED_MIPS();
+}
 
-  CodeForStatementPosition(node);
-  LoadAndSpill(node->expression());
-  if (function_return_is_shadowed_) {
-    frame_->EmitPop(v0);
-    function_return_.Jump();
-  } else {
-    // Pop the result from the frame and prepare the frame for
-    // returning thus making it easier to merge.
-    frame_->EmitPop(v0);
-    frame_->PrepareForReturn();
 
-    function_return_.Jump();
-  }
+void CodeGenerator::GenerateReturnSequence() {
+  UNIMPLEMENTED_MIPS();
 }
 
 
@@ -594,6 +502,13 @@
 }
 
 
+void CodeGenerator::InstantiateFunction(
+    Handle<SharedFunctionInfo> function_info,
+    bool pretenure) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
   UNIMPLEMENTED_MIPS();
 }
@@ -610,46 +525,49 @@
 }
 
 
+void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::LoadFromSlotCheckForArguments(Slot* slot,
+                                                  TypeofState state) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::LoadFromGlobalSlotCheckExtensions(Slot* slot,
+                                                      TypeofState typeof_state,
+                                                      JumpTarget* slow) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::EmitDynamicLoadFromSlotFastCase(Slot* slot,
+                                                    TypeofState typeof_state,
+                                                    JumpTarget* slow,
+                                                    JumpTarget* done) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void CodeGenerator::VisitSlot(Slot* node) {
-#ifdef DEBUG
-  int original_height = frame_->height();
-#endif
-  VirtualFrame::SpilledScope spilled_scope;
-  Comment cmnt(masm_, "[ Slot");
-  LoadFromSlot(node, typeof_state());
-  ASSERT(frame_->height() == original_height + 1);
+  UNIMPLEMENTED_MIPS();
 }
 
 
 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
-#ifdef DEBUG
-  int original_height = frame_->height();
-#endif
-  VirtualFrame::SpilledScope spilled_scope;
-  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();
-  }
-  ASSERT(frame_->height() == original_height + 1);
+  UNIMPLEMENTED_MIPS();
 }
 
 
 void CodeGenerator::VisitLiteral(Literal* node) {
-#ifdef DEBUG
-  int original_height = frame_->height();
-#endif
-  VirtualFrame::SpilledScope spilled_scope;
-  Comment cmnt(masm_, "[ Literal");
-  __ li(t0, Operand(node->handle()));
-  frame_->EmitPush(t0);
-  ASSERT(frame_->height() == original_height + 1);
+  UNIMPLEMENTED_MIPS();
 }
 
 
@@ -673,48 +591,23 @@
 }
 
 
+void CodeGenerator::EmitSlotAssignment(Assignment* node) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void CodeGenerator::VisitAssignment(Assignment* node) {
-#ifdef DEBUG
-  int original_height = frame_->height();
-#endif
-  VirtualFrame::SpilledScope spilled_scope;
-  Comment cmnt(masm_, "[ Assignment");
-
-  { 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_->EmitPush(zero_reg);
-      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 {
-      UNIMPLEMENTED_MIPS();
-    }
-
-    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);
+  UNIMPLEMENTED_MIPS();
 }
 
 
@@ -729,73 +622,7 @@
 
 
 void CodeGenerator::VisitCall(Call* node) {
-#ifdef DEBUG
-  int original_height = frame_->height();
-#endif
-  VirtualFrame::SpilledScope spilled_scope;
-  Comment cmnt(masm_, "[ Call");
-
-  Expression* function = node->expression();
-  ZoneList<Expression*>* args = node->arguments();
-
-  // Standard function call.
-  // Check if the function is a variable or a property.
-  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_possibly_eval()) {
-    UNIMPLEMENTED_MIPS();
-  } else if (var != NULL && !var->is_this() && var->is_global()) {
-    // ----------------------------------
-    // JavaScript example: 'foo(1, 2, 3)'  // foo is global
-    // ----------------------------------
-
-    int arg_count = args->length();
-
-    // We need sp to be 8 bytes aligned when calling the stub.
-    __ SetupAlignedCall(t0, arg_count);
-
-    // 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.
-    for (int i = 0; i < arg_count; i++) {
-      LoadAndSpill(args->at(i));
-    }
-
-    // Setup the receiver register and call the IC initialization code.
-    __ li(a2, Operand(var->name()));
-    InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
-    Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop);
-    CodeForSourcePosition(node->position());
-    frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
-                           arg_count + 1);
-    __ ReturnFromAlignedCall();
-    __ lw(cp, frame_->Context());
-    // Remove the function from the stack.
-    frame_->EmitPush(v0);
-
-  } else if (var != NULL && var->slot() != NULL &&
-             var->slot()->type() == Slot::LOOKUP) {
-    UNIMPLEMENTED_MIPS();
-  } else if (property != NULL) {
-    UNIMPLEMENTED_MIPS();
-  } else {
-    UNIMPLEMENTED_MIPS();
-  }
-
-  ASSERT(frame_->height() == original_height + 1);
+  UNIMPLEMENTED_MIPS();
 }
 
 
@@ -839,30 +666,112 @@
 }
 
 
-void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) {
   UNIMPLEMENTED_MIPS();
 }
 
 
-// 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) {
+class DeferredStringCharCodeAt : public DeferredCode {
+ public:
+  DeferredStringCharCodeAt(Register object,
+                           Register index,
+                           Register scratch,
+                           Register result)
+      : result_(result),
+        char_code_at_generator_(object,
+                                index,
+                                scratch,
+                                result,
+                                &need_conversion_,
+                                &need_conversion_,
+                                &index_out_of_range_,
+                                STRING_INDEX_IS_NUMBER) {}
+
+  StringCharCodeAtGenerator* fast_case_generator() {
+    return &char_code_at_generator_;
+  }
+
+  virtual void Generate() {
+    UNIMPLEMENTED_MIPS();
+  }
+
+ private:
+  Register result_;
+
+  Label need_conversion_;
+  Label index_out_of_range_;
+
+  StringCharCodeAtGenerator char_code_at_generator_;
+};
+
+
+void CodeGenerator::GenerateStringCharCodeAt(ZoneList<Expression*>* args) {
   UNIMPLEMENTED_MIPS();
 }
 
 
-void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) {
+class DeferredStringCharFromCode : public DeferredCode {
+ public:
+  DeferredStringCharFromCode(Register code,
+                             Register result)
+      : char_from_code_generator_(code, result) {}
+
+  StringCharFromCodeGenerator* fast_case_generator() {
+    return &char_from_code_generator_;
+  }
+
+  virtual void Generate() {
+    VirtualFrameRuntimeCallHelper call_helper(frame_state());
+    char_from_code_generator_.GenerateSlow(masm(), call_helper);
+  }
+
+ private:
+  StringCharFromCodeGenerator char_from_code_generator_;
+};
+
+
+void CodeGenerator::GenerateStringCharFromCode(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+class DeferredStringCharAt : public DeferredCode {
+ public:
+  DeferredStringCharAt(Register object,
+                       Register index,
+                       Register scratch1,
+                       Register scratch2,
+                       Register result)
+      : result_(result),
+        char_at_generator_(object,
+                           index,
+                           scratch1,
+                           scratch2,
+                           result,
+                           &need_conversion_,
+                           &need_conversion_,
+                           &index_out_of_range_,
+                           STRING_INDEX_IS_NUMBER) {}
+
+  StringCharAtGenerator* fast_case_generator() {
+    return &char_at_generator_;
+  }
+
+  virtual void Generate() {
+  UNIMPLEMENTED_MIPS();
+}
+
+ private:
+  Register result_;
+
+  Label need_conversion_;
+  Label index_out_of_range_;
+
+  StringCharAtGenerator char_at_generator_;
+};
+
+
+void CodeGenerator::GenerateStringCharAt(ZoneList<Expression*>* args) {
   UNIMPLEMENTED_MIPS();
 }
 
@@ -877,6 +786,55 @@
 }
 
 
+void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenerateIsSpecObject(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+class DeferredIsStringWrapperSafeForDefaultValueOf : public DeferredCode {
+ public:
+  DeferredIsStringWrapperSafeForDefaultValueOf(Register object,
+                                               Register map_result,
+                                               Register scratch1,
+                                               Register scratch2)
+      : object_(object),
+        map_result_(map_result),
+        scratch1_(scratch1),
+        scratch2_(scratch2) { }
+
+  virtual void Generate() {
+    UNIMPLEMENTED_MIPS();
+  }
+
+ private:
+  Register object_;
+  Register map_result_;
+  Register scratch1_;
+  Register scratch2_;
+};
+
+
+void CodeGenerator::GenerateIsStringWrapperSafeForDefaultValueOf(
+    ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenerateIsUndetectableObject(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) {
   UNIMPLEMENTED_MIPS();
 }
@@ -892,32 +850,8 @@
 }
 
 
-void CodeGenerator::GenerateRandomHeapNumber(ZoneList<Expression*>* args) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void CodeGenerator::GenerateIsSpecObject(ZoneList<Expression*>* args) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void CodeGenerator::GenerateIsUndetectableObject(ZoneList<Expression*>* args) {
+void CodeGenerator::GenerateRandomHeapNumber(
+    ZoneList<Expression*>* args) {
   UNIMPLEMENTED_MIPS();
 }
 
@@ -942,11 +876,109 @@
 }
 
 
+void CodeGenerator::GenerateRegExpConstructResult(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+class DeferredSearchCache: public DeferredCode {
+ public:
+  DeferredSearchCache(Register dst, Register cache, Register key)
+      : dst_(dst), cache_(cache), key_(key) {
+    set_comment("[ DeferredSearchCache");
+  }
+
+  virtual void Generate();
+
+ private:
+  Register dst_, cache_, key_;
+};
+
+
+void DeferredSearchCache::Generate() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenerateGetFromCache(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) {
   UNIMPLEMENTED_MIPS();
 }
 
 
+class DeferredSwapElements: public DeferredCode {
+ public:
+  DeferredSwapElements(Register object, Register index1, Register index2)
+      : object_(object), index1_(index1), index2_(index2) {
+    set_comment("[ DeferredSwapElements");
+  }
+
+  virtual void Generate();
+
+ private:
+  Register object_, index1_, index2_;
+};
+
+
+void DeferredSwapElements::Generate() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenerateCallFunction(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenerateIsRegExpEquivalent(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenerateHasCachedArrayIndex(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenerateGetCachedArrayIndex(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
   UNIMPLEMENTED_MIPS();
 }
@@ -957,11 +989,39 @@
 }
 
 
+class DeferredCountOperation: public DeferredCode {
+ public:
+  DeferredCountOperation(Register value,
+                         bool is_increment,
+                         bool is_postfix,
+                         int target_size)
+      : value_(value),
+        is_increment_(is_increment),
+        is_postfix_(is_postfix),
+        target_size_(target_size) {}
+
+  virtual void Generate() {
+    UNIMPLEMENTED_MIPS();
+  }
+
+ private:
+  Register value_;
+  bool is_increment_;
+  bool is_postfix_;
+  int target_size_;
+};
+
+
 void CodeGenerator::VisitCountOperation(CountOperation* node) {
   UNIMPLEMENTED_MIPS();
 }
 
 
+void CodeGenerator::GenerateLogicalBooleanOperation(BinaryOperation* node) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
   UNIMPLEMENTED_MIPS();
 }
@@ -977,8 +1037,138 @@
 }
 
 
+void CodeGenerator::VisitCompareToNull(CompareToNull* node) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+class DeferredReferenceGetNamedValue: public DeferredCode {
+ public:
+  explicit DeferredReferenceGetNamedValue(Register receiver,
+                                          Handle<String> name,
+                                          bool is_contextual)
+      : receiver_(receiver),
+        name_(name),
+        is_contextual_(is_contextual),
+        is_dont_delete_(false) {
+    set_comment(is_contextual
+                ? "[ DeferredReferenceGetNamedValue (contextual)"
+                : "[ DeferredReferenceGetNamedValue");
+  }
+
+  virtual void Generate();
+
+  void set_is_dont_delete(bool value) {
+    ASSERT(is_contextual_);
+    is_dont_delete_ = value;
+  }
+
+ private:
+  Register receiver_;
+  Handle<String> name_;
+  bool is_contextual_;
+  bool is_dont_delete_;
+};
+
+
+
+void DeferredReferenceGetNamedValue::Generate() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+class DeferredReferenceGetKeyedValue: public DeferredCode {
+ public:
+  DeferredReferenceGetKeyedValue(Register key, Register receiver)
+      : key_(key), receiver_(receiver) {
+    set_comment("[ DeferredReferenceGetKeyedValue");
+  }
+
+  virtual void Generate();
+
+ private:
+  Register key_;
+  Register receiver_;
+};
+
+
+void DeferredReferenceGetKeyedValue::Generate() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+class DeferredReferenceSetKeyedValue: public DeferredCode {
+ public:
+  DeferredReferenceSetKeyedValue(Register value,
+                                 Register key,
+                                 Register receiver)
+      : value_(value), key_(key), receiver_(receiver) {
+    set_comment("[ DeferredReferenceSetKeyedValue");
+  }
+
+  virtual void Generate();
+
+ private:
+  Register value_;
+  Register key_;
+  Register receiver_;
+};
+
+
+void DeferredReferenceSetKeyedValue::Generate() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+class DeferredReferenceSetNamedValue: public DeferredCode {
+ public:
+  DeferredReferenceSetNamedValue(Register value,
+                                 Register receiver,
+                                 Handle<String> name)
+      : value_(value), receiver_(receiver), name_(name) {
+    set_comment("[ DeferredReferenceSetNamedValue");
+  }
+
+  virtual void Generate();
+
+ private:
+  Register value_;
+  Register receiver_;
+  Handle<String> name_;
+};
+
+
+void DeferredReferenceSetNamedValue::Generate() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::EmitKeyedLoad() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::EmitKeyedStore(StaticType* key_type,
+                                   WriteBarrierCharacter wb_info) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 #ifdef DEBUG
-bool CodeGenerator::HasValidEntryRegisters() { return true; }
+bool CodeGenerator::HasValidEntryRegisters() {
+  UNIMPLEMENTED_MIPS();
+  return false;
+}
 #endif
 
 
@@ -986,447 +1176,33 @@
 #define __ ACCESS_MASM(masm)
 
 // -----------------------------------------------------------------------------
-// Reference support
-
-Reference::Reference(CodeGenerator* cgen,
-                     Expression* expression,
-                     bool persist_after_get)
-    : cgen_(cgen),
-      expression_(expression),
-      type_(ILLEGAL),
-      persist_after_get_(persist_after_get) {
-  cgen->LoadReference(this);
-}
-
-
-Reference::~Reference() {
-  ASSERT(is_unloaded() || is_illegal());
-}
+// Reference support.
 
 
 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()));
-  }
+  UNIMPLEMENTED_MIPS();
+  return Handle<String>();
+}
+
+
+void Reference::DupIfPersist() {
+  UNIMPLEMENTED_MIPS();
 }
 
 
 void Reference::GetValue() {
-  ASSERT(cgen_->HasValidEntryRegisters());
-  ASSERT(!is_illegal());
-  ASSERT(!cgen_->has_cc());
-  Property* property = expression_->AsProperty();
-  if (property != NULL) {
-    cgen_->CodeForSourcePosition(property->position());
-  }
-
-  switch (type_) {
-    case SLOT: {
-      UNIMPLEMENTED_MIPS();
-      break;
-    }
-
-    case NAMED: {
-      UNIMPLEMENTED_MIPS();
-      break;
-    }
-
-    case KEYED: {
-      UNIMPLEMENTED_MIPS();
-      break;
-    }
-
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void Reference::SetValue(InitState init_state) {
-  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, "[ Store to Slot");
-      Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
-      cgen_->StoreToSlot(slot, init_state);
-      cgen_->UnloadReference(this);
-      break;
-    }
-
-    case NAMED: {
-      UNIMPLEMENTED_MIPS();
-      break;
-    }
-
-    case KEYED: {
-      UNIMPLEMENTED_MIPS();
-      break;
-    }
-
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-// On entry a0 and a1 are the things to be compared. On exit v0 is 0,
-// positive or negative to indicate the result of the comparison.
-void CompareStub::Generate(MacroAssembler* masm) {
   UNIMPLEMENTED_MIPS();
-  __ break_(0x765);
 }
 
 
-Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) {
+void Reference::SetValue(InitState init_state, WriteBarrierCharacter wb_info) {
   UNIMPLEMENTED_MIPS();
-  return Handle<Code>::null();
 }
 
 
-void StackCheckStub::Generate(MacroAssembler* masm) {
+const char* GenericBinaryOpStub::GetName() {
   UNIMPLEMENTED_MIPS();
-  __ break_(0x790);
-}
-
-
-void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
-  UNIMPLEMENTED_MIPS();
-  __ break_(0x808);
-}
-
-
-void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm,
-                                          UncatchableExceptionType type) {
-  UNIMPLEMENTED_MIPS();
-  __ break_(0x815);
-}
-
-void CEntryStub::GenerateCore(MacroAssembler* masm,
-                              Label* throw_normal_exception,
-                              Label* throw_termination_exception,
-                              Label* throw_out_of_memory_exception,
-                              bool do_gc,
-                              bool always_allocate) {
-  // s0: number of arguments including receiver (C callee-saved)
-  // s1: pointer to the first argument          (C callee-saved)
-  // s2: pointer to builtin function            (C callee-saved)
-
-  if (do_gc) {
-    UNIMPLEMENTED_MIPS();
-  }
-
-  ExternalReference scope_depth =
-      ExternalReference::heap_always_allocate_scope_depth();
-  if (always_allocate) {
-    UNIMPLEMENTED_MIPS();
-  }
-
-  // Call C built-in.
-  // a0 = argc, a1 = argv
-  __ mov(a0, s0);
-  __ mov(a1, s1);
-
-  __ CallBuiltin(s2);
-
-  if (always_allocate) {
-    UNIMPLEMENTED_MIPS();
-  }
-
-  // Check for failure result.
-  Label failure_returned;
-  ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
-  __ addiu(a2, v0, 1);
-  __ andi(t0, a2, kFailureTagMask);
-  __ Branch(eq, &failure_returned, t0, Operand(zero_reg));
-
-  // Exit C frame and return.
-  // v0:v1: result
-  // sp: stack pointer
-  // fp: frame pointer
-  __ LeaveExitFrame(mode_);
-
-  // Check if we should retry or throw exception.
-  Label retry;
-  __ bind(&failure_returned);
-  ASSERT(Failure::RETRY_AFTER_GC == 0);
-  __ andi(t0, v0, ((1 << kFailureTypeTagSize) - 1) << kFailureTagSize);
-  __ Branch(eq, &retry, t0, Operand(zero_reg));
-
-  // Special handling of out of memory exceptions.
-  Failure* out_of_memory = Failure::OutOfMemoryException();
-  __ Branch(eq, throw_out_of_memory_exception,
-            v0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
-
-  // Retrieve the pending exception and clear the variable.
-  __ LoadExternalReference(t0, ExternalReference::the_hole_value_location());
-  __ lw(a3, MemOperand(t0));
-  __ LoadExternalReference(t0,
-      ExternalReference(Top::k_pending_exception_address));
-  __ lw(v0, MemOperand(t0));
-  __ sw(a3, MemOperand(t0));
-
-  // Special handling of termination exceptions which are uncatchable
-  // by javascript code.
-  __ Branch(eq, throw_termination_exception,
-            v0, Operand(Factory::termination_exception()));
-
-  // Handle normal exception.
-  __ b(throw_normal_exception);
-  __ nop();   // Branch delay slot nop.
-
-  __ bind(&retry);  // pass last failure (r0) as parameter (r0) when retrying
-}
-
-void CEntryStub::Generate(MacroAssembler* masm) {
-  // Called from JavaScript; parameters are on stack as if calling JS function
-  // a0: number of arguments including receiver
-  // a1: pointer to builtin function
-  // fp: frame pointer    (restored after C call)
-  // sp: stack pointer    (restored as callee's sp after C call)
-  // cp: current context  (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.
-
-  // Enter the exit frame that transitions from JavaScript to C++.
-  __ EnterExitFrame(mode_, s0, s1, s2);
-
-  // s0: number of arguments (C callee-saved)
-  // s1: pointer to first argument (C callee-saved)
-  // s2: pointer to builtin function (C callee-saved)
-
-  Label throw_normal_exception;
-  Label throw_termination_exception;
-  Label throw_out_of_memory_exception;
-
-  // Call into the runtime system.
-  GenerateCore(masm,
-               &throw_normal_exception,
-               &throw_termination_exception,
-               &throw_out_of_memory_exception,
-               false,
-               false);
-
-  // Do space-specific GC and retry runtime call.
-  GenerateCore(masm,
-               &throw_normal_exception,
-               &throw_termination_exception,
-               &throw_out_of_memory_exception,
-               true,
-               false);
-
-  // Do full GC and retry runtime call one final time.
-  Failure* failure = Failure::InternalError();
-  __ li(v0, Operand(reinterpret_cast<int32_t>(failure)));
-  GenerateCore(masm,
-               &throw_normal_exception,
-               &throw_termination_exception,
-               &throw_out_of_memory_exception,
-               true,
-               true);
-
-  __ bind(&throw_out_of_memory_exception);
-  GenerateThrowUncatchable(masm, OUT_OF_MEMORY);
-
-  __ bind(&throw_termination_exception);
-  GenerateThrowUncatchable(masm, TERMINATION);
-
-  __ bind(&throw_normal_exception);
-  GenerateThrowTOS(masm);
-}
-
-void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
-  Label invoke, exit;
-
-  // Registers:
-  // a0: entry address
-  // a1: function
-  // a2: reveiver
-  // a3: argc
-  //
-  // Stack:
-  // 4 args slots
-  // args
-
-  // Save callee saved registers on the stack.
-  __ MultiPush((kCalleeSaved | ra.bit()) & ~sp.bit());
-
-  // We build an EntryFrame.
-  __ li(t3, Operand(-1));  // Push a bad frame pointer to fail if it is used.
-  int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
-  __ li(t2, Operand(Smi::FromInt(marker)));
-  __ li(t1, Operand(Smi::FromInt(marker)));
-  __ LoadExternalReference(t0, ExternalReference(Top::k_c_entry_fp_address));
-  __ lw(t0, MemOperand(t0));
-  __ MultiPush(t0.bit() | t1.bit() | t2.bit() | t3.bit());
-
-  // Setup frame pointer for the frame to be pushed.
-  __ addiu(fp, sp, -EntryFrameConstants::kCallerFPOffset);
-
-  // Load argv in s0 register.
-  __ lw(s0, MemOperand(sp, (kNumCalleeSaved + 1) * kPointerSize +
-                           StandardFrameConstants::kCArgsSlotsSize));
-
-  // Registers:
-  // a0: entry_address
-  // a1: function
-  // a2: reveiver_pointer
-  // a3: argc
-  // s0: argv
-  //
-  // Stack:
-  // caller fp          |
-  // function slot      | entry frame
-  // context slot       |
-  // bad fp (0xff...f)  |
-  // callee saved registers + ra
-  // 4 args slots
-  // args
-
-  // Call a faked try-block that does the invoke.
-  __ bal(&invoke);
-  __ nop();   // Branch delay slot nop.
-
-  // 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.
-  __ LoadExternalReference(t0,
-      ExternalReference(Top::k_pending_exception_address));
-  __ sw(v0, MemOperand(t0));  // We come back from 'invoke'. result is in v0.
-  __ li(v0, Operand(reinterpret_cast<int32_t>(Failure::Exception())));
-  __ b(&exit);
-  __ nop();   // Branch delay slot nop.
-
-  // Invoke: Link this frame into the handler chain.
-  __ bind(&invoke);
-  __ 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 bal(&invoke) above, which
-  // restores all kCalleeSaved registers (including cp and fp) to their
-  // saved values before returning a failure to C.
-
-  // Clear any pending exceptions.
-  __ LoadExternalReference(t0, ExternalReference::the_hole_value_location());
-  __ lw(t1, MemOperand(t0));
-  __ LoadExternalReference(t0,
-      ExternalReference(Top::k_pending_exception_address));
-  __ sw(t1, MemOperand(t0));
-
-  // 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.
-
-  // Registers:
-  // a0: entry_address
-  // a1: function
-  // a2: reveiver_pointer
-  // a3: argc
-  // s0: argv
-  //
-  // Stack:
-  // handler frame
-  // entry frame
-  // callee saved registers + ra
-  // 4 args slots
-  // args
-
-  if (is_construct) {
-    ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline);
-    __ LoadExternalReference(t0, construct_entry);
-  } else {
-    ExternalReference entry(Builtins::JSEntryTrampoline);
-    __ LoadExternalReference(t0, entry);
-  }
-  __ lw(t9, MemOperand(t0));  // deref address
-
-  // Call JSEntryTrampoline.
-  __ addiu(t9, t9, Code::kHeaderSize - kHeapObjectTag);
-  __ CallBuiltin(t9);
-
-  // 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.
-  __ lw(t1, MemOperand(sp, StackHandlerConstants::kNextOffset));
-  __ LoadExternalReference(t0, ExternalReference(Top::k_handler_address));
-  __ sw(t1, MemOperand(t0));
-
-  // This restores sp to its position before PushTryHandler.
-  __ addiu(sp, sp, StackHandlerConstants::kSize);
-
-  __ bind(&exit);  // v0 holds result
-  // Restore the top frame descriptors from the stack.
-  __ Pop(t1);
-  __ LoadExternalReference(t0, ExternalReference(Top::k_c_entry_fp_address));
-  __ sw(t1, MemOperand(t0));
-
-  // Reset the stack to the callee saved registers.
-  __ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset);
-
-  // Restore callee saved registers from the stack.
-  __ MultiPop((kCalleeSaved | ra.bit()) & ~sp.bit());
-  // Return.
-  __ Jump(ra);
-}
-
-
-// This stub performs an instanceof, calling the builtin function if
-// necessary. Uses a1 for the object, a0 for the function that it may
-// be an instance of (these are fetched from the stack).
-void InstanceofStub::Generate(MacroAssembler* masm) {
-  UNIMPLEMENTED_MIPS();
-  __ break_(0x845);
-}
-
-
-void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) {
-  UNIMPLEMENTED_MIPS();
-  __ break_(0x851);
-}
-
-
-void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
-  UNIMPLEMENTED_MIPS();
-  __ break_(0x857);
-}
-
-
-void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
-  UNIMPLEMENTED_MIPS();
-  __ break_(0x863);
-}
-
-
-const char* CompareStub::GetName() {
-  UNIMPLEMENTED_MIPS();
-  return NULL;  // UNIMPLEMENTED RETURN
-}
-
-
-int CompareStub::MinorKey() {
-  // Encode the two parameters in a unique 16 bit value.
-  ASSERT(static_cast<unsigned>(cc_) >> 28 < (1 << 15));
-  return (static_cast<unsigned>(cc_) >> 27) | (strict_ ? 1 : 0);
+  return name_;
 }
 
 
diff --git a/src/mips/codegen-mips.h b/src/mips/codegen-mips.h
index 66f891b..0a2cd45 100644
--- a/src/mips/codegen-mips.h
+++ b/src/mips/codegen-mips.h
@@ -29,17 +29,37 @@
 #ifndef V8_MIPS_CODEGEN_MIPS_H_
 #define V8_MIPS_CODEGEN_MIPS_H_
 
+
+#include "ast.h"
+#include "code-stubs-mips.h"
+#include "ic-inl.h"
+
 namespace v8 {
 namespace internal {
 
+#if(defined(__mips_hard_float) && __mips_hard_float != 0)
+// Use floating-point coprocessor instructions. This flag is raised when
+// -mhard-float is passed to the compiler.
+static const bool IsMipsSoftFloatABI = false;
+#elif(defined(__mips_soft_float) && __mips_soft_float != 0)
+// Not using floating-point coprocessor instructions. This flag is raised when
+// -msoft-float is passed to the compiler.
+static const bool IsMipsSoftFloatABI = true;
+#else
+static const bool IsMipsSoftFloatABI = true;
+#endif
+
 // Forward declarations
 class CompilationInfo;
 class DeferredCode;
+class JumpTarget;
 class RegisterAllocator;
 class RegisterFile;
 
 enum InitState { CONST_INIT, NOT_CONST_INIT };
 enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
+enum GenerateInlineSmi { DONT_GENERATE_INLINE_SMI, GENERATE_INLINE_SMI };
+enum WriteBarrierCharacter { UNLIKELY_SMI, LIKELY_SMI, NEVER_NEWSPACE };
 
 
 // -----------------------------------------------------------------------------
@@ -101,7 +121,12 @@
   // on the expression stack.  The  value is stored in the location specified
   // by the reference, and is left on top of the stack, after the reference
   // is popped from beneath it (unloaded).
-  void SetValue(InitState init_state);
+  void SetValue(InitState init_state, WriteBarrierCharacter wb);
+
+  // This is in preparation for something that uses the reference on the stack.
+  // If we need this reference afterwards get then dup it now.  Otherwise mark
+  // it as used.
+  inline void DupIfPersist();
 
  private:
   CodeGenerator* cgen_;
@@ -126,31 +151,24 @@
   // 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,
-               JumpTarget* true_target,
-               JumpTarget* false_target);
+
 
   // Destroy a code generator state and restore the owning code generator's
   // previous state.
-  ~CodeGenState();
+  virtual ~CodeGenState();
 
-  TypeofState typeof_state() const { return typeof_state_; }
-  JumpTarget* true_target() const { return true_target_; }
-  JumpTarget* false_target() const { return false_target_; }
+  virtual JumpTarget* true_target() const { return NULL; }
+  virtual JumpTarget* false_target() const { return NULL; }
+
+ protected:
+  inline CodeGenerator* owner() { return owner_; }
+  inline CodeGenState* previous() const { return previous_; }
 
  private:
   // The owning code generator.
   CodeGenerator* owner_;
 
-  // A flag indicating whether we are compiling the immediate subexpression
-  // of a typeof expression.
-  TypeofState typeof_state_;
 
-  JumpTarget* true_target_;
-  JumpTarget* false_target_;
 
   // The previous state of the owning code generator, restored when
   // this state is destroyed.
@@ -158,6 +176,50 @@
 };
 
 
+class ConditionCodeGenState : public CodeGenState {
+ public:
+  // Create a code generator state based on a code generator's current
+  // state.  The new state has its own pair of branch labels.
+  ConditionCodeGenState(CodeGenerator* owner,
+                        JumpTarget* true_target,
+                        JumpTarget* false_target);
+
+  virtual JumpTarget* true_target() const { return true_target_; }
+  virtual JumpTarget* false_target() const { return false_target_; }
+
+ private:
+  JumpTarget* true_target_;
+  JumpTarget* false_target_;
+};
+
+
+class TypeInfoCodeGenState : public CodeGenState {
+ public:
+  TypeInfoCodeGenState(CodeGenerator* owner,
+                       Slot* slot_number,
+                       TypeInfo info);
+  virtual ~TypeInfoCodeGenState();
+
+  virtual JumpTarget* true_target() const { return previous()->true_target(); }
+  virtual JumpTarget* false_target() const {
+    return previous()->false_target();
+  }
+
+ private:
+  Slot* slot_;
+  TypeInfo old_type_info_;
+};
+
+
+// -------------------------------------------------------------------------
+// Arguments allocation mode
+
+enum ArgumentsAllocationMode {
+  NO_ARGUMENTS_ALLOCATION,
+  EAGER_ARGUMENTS_ALLOCATION,
+  LAZY_ARGUMENTS_ALLOCATION
+};
+
 
 // -----------------------------------------------------------------------------
 // CodeGenerator
@@ -173,9 +235,7 @@
     SECONDARY
   };
 
-  // Takes a function literal, generates code for it. This function should only
-  // be called by compiler.cc.
-  static Handle<Code> MakeCode(CompilationInfo* info);
+  static bool MakeCode(CompilationInfo* info);
 
   // Printing of AST, etc. as requested by flags.
   static void MakeCodePrologue(CompilationInfo* info);
@@ -185,6 +245,9 @@
                                        Code::Flags flags,
                                        CompilationInfo* info);
 
+  // Print the code after compiling it.
+  static void PrintCode(Handle<Code> code, CompilationInfo* info);
+
 #ifdef ENABLE_LOGGING_AND_PROFILING
   static bool ShouldGenerateLog(Expression* type);
 #endif
@@ -194,7 +257,9 @@
                               bool is_toplevel,
                               Handle<Script> script);
 
-  static void RecordPositions(MacroAssembler* masm, int pos);
+  static bool RecordPositions(MacroAssembler* masm,
+                              int pos,
+                              bool right_here = false);
 
   // Accessors
   MacroAssembler* masm() { return masm_; }
@@ -216,73 +281,105 @@
   CodeGenState* state() { return state_; }
   void set_state(CodeGenState* state) { state_ = state; }
 
+  TypeInfo type_info(Slot* slot) {
+    int index = NumberOfSlot(slot);
+    if (index == kInvalidSlotNumber) return TypeInfo::Unknown();
+    return (*type_info_)[index];
+  }
+
+  TypeInfo set_type_info(Slot* slot, TypeInfo info) {
+    int index = NumberOfSlot(slot);
+    ASSERT(index >= kInvalidSlotNumber);
+    if (index != kInvalidSlotNumber) {
+      TypeInfo previous_value = (*type_info_)[index];
+      (*type_info_)[index] = info;
+      return previous_value;
+    }
+    return TypeInfo::Unknown();
+  }
   void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
 
-  static const int kUnknownIntValue = -1;
-
-  // Number of instructions used for the JS return sequence. The constant is
-  // used by the debugger to patch the JS return sequence.
-  static const int kJSReturnSequenceLength = 7;
-
-  // If the name is an inline runtime function call return the number of
-  // expected arguments. Otherwise return -1.
-  static int InlineRuntimeCallArgumentsCount(Handle<String> name);
+  // Constants related to patching of inlined load/store.
+  static int GetInlinedKeyedLoadInstructionsAfterPatch() {
+    // This is in correlation with the padding in MacroAssembler::Abort.
+    return FLAG_debug_code ? 45 : 20;
+  }
+  static const int kInlinedKeyedStoreInstructionsAfterPatch = 9;
+  static int GetInlinedNamedStoreInstructionsAfterPatch() {
+    ASSERT(Isolate::Current()->inlined_write_barrier_size() != -1);
+    // Magic number 5: instruction count after patched map load:
+    //  li: 2 (liu & ori), Branch : 2 (bne & nop), sw : 1
+    return Isolate::Current()->inlined_write_barrier_size() + 5;
+  }
 
  private:
+  // Type of a member function that generates inline code for a native function.
+  typedef void (CodeGenerator::*InlineFunctionGenerator)
+      (ZoneList<Expression*>*);
+
+  static const InlineFunctionGenerator kInlineFunctionGenerators[];
+
+
   // Construction/Destruction.
   explicit CodeGenerator(MacroAssembler* masm);
 
   // Accessors.
   inline bool is_eval();
   inline Scope* scope();
+  inline bool is_strict_mode();
+  inline StrictModeFlag strict_mode_flag();
 
   // Generating deferred code.
   void ProcessDeferred();
 
+  static const int kInvalidSlotNumber = -1;
+
+  int NumberOfSlot(Slot* slot);
   // State
   bool has_cc() const { return cc_reg_ != cc_always; }
-  TypeofState typeof_state() const { return state_->typeof_state(); }
+
   JumpTarget* true_target() const { return state_->true_target(); }
   JumpTarget* false_target() const { return state_->false_target(); }
 
-  // We don't track loop nesting level on mips yet.
-  int loop_nesting() const { return 0; }
+  // 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);
 
+  virtual void VisitSlot(Slot* node);
 #define DEF_VISIT(type) \
-  void Visit##type(type* node);
+  virtual void Visit##type(type* node);
   AST_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.
-  inline 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.
-  inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
-
   // Main code generation function
   void Generate(CompilationInfo* info);
 
+  // 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).  The return value should
+  // be in v0.
+  void GenerateReturnSequence();
+
+  // Returns the arguments allocation mode.
+  ArgumentsAllocationMode ArgumentsMode();
+
+  // Store the arguments object and allocate it if necessary.
+  void StoreArgumentsObject(bool initial);
+
   // 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);
 
-  // Expressions
-  MemOperand GlobalObject() const {
-    return ContextOperand(cp, Context::GLOBAL_INDEX);
-  }
+  MemOperand ContextSlotOperandCheckExtensions(Slot* slot,
+                                               Register tmp,
+                                               Register tmp2,
+                                               JumpTarget* slow);
 
   void LoadCondition(Expression* x,
                      JumpTarget* true_target,
@@ -290,35 +387,113 @@
                      bool force_cc);
   void Load(Expression* x);
   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.
-  inline void LoadAndSpill(Expression* expression);
+
+  // 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);
+
+  // Store a keyed property. Key and receiver are on the stack and the value is
+  // in a0. Result is returned in r0.
+  void EmitKeyedStore(StaticType* key_type, WriteBarrierCharacter wb_info);
 
   // 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,
+                                         JumpTarget* slow);
+  void LoadFromSlotCheckForArguments(Slot* slot, TypeofState state);
+
+  // Support for loading from local/global variables and arguments
+  // whose location is known unless they are shadowed by
+  // eval-introduced bindings. Generates no code for unsupported slot
+  // types and therefore expects to fall through to the slow jump target.
+  void EmitDynamicLoadFromSlotFastCase(Slot* slot,
+                                       TypeofState typeof_state,
+                                       JumpTarget* slow,
+                                       JumpTarget* done);
+
   // Store the value on top of the stack to a slot.
   void StoreToSlot(Slot* slot, InitState init_state);
 
-  struct InlineRuntimeLUT {
-    void (CodeGenerator::*method)(ZoneList<Expression*>*);
-    const char* name;
-    int nargs;
-  };
+  // Support for compiling assignment expressions.
+  void EmitSlotAssignment(Assignment* node);
+  void EmitNamedPropertyAssignment(Assignment* node);
+  void EmitKeyedPropertyAssignment(Assignment* node);
 
-  static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
+  // Load a named property, returning it in v0. The receiver is passed on the
+  // stack, and remains there.
+  void EmitNamedLoad(Handle<String> name, bool is_contextual);
+
+  // Store to a named property. If the store is contextual, value is passed on
+  // the frame and consumed. Otherwise, receiver and value are passed on the
+  // frame and consumed. The result is returned in v0.
+  void EmitNamedStore(Handle<String> name, bool is_contextual);
+
+  // Load a keyed property, leaving it in v0. The receiver and key are
+  // passed on the stack, and remain there.
+  void EmitKeyedLoad();
+
+  void ToBoolean(JumpTarget* true_target, JumpTarget* false_target);
+
+  // Generate code that computes a shortcutting logical operation.
+  void GenerateLogicalBooleanOperation(BinaryOperation* node);
+
+  void GenericBinaryOperation(Token::Value op,
+                              OverwriteMode overwrite_mode,
+                              GenerateInlineSmi inline_smi,
+                              int known_rhs =
+                                GenericBinaryOpStub::kUnknownIntValue);
+
+  void VirtualFrameBinaryOperation(Token::Value op,
+                                   OverwriteMode overwrite_mode,
+                                   int known_rhs =
+                                      GenericBinaryOpStub::kUnknownIntValue);
+
+  void SmiOperation(Token::Value op,
+                    Handle<Object> value,
+                    bool reversed,
+                    OverwriteMode mode);
+
+  void Comparison(Condition cc,
+                  Expression* left,
+                  Expression* right,
+                  bool strict = false);
+
+  void CallWithArguments(ZoneList<Expression*>* arguments,
+                         CallFunctionFlags flags,
+                         int position);
+
+  // An optimized implementation of expressions of the form
+  // x.apply(y, arguments).  We call x the applicand and y the receiver.
+  // The optimization avoids allocating an arguments object if possible.
+  void CallApplyLazy(Expression* applicand,
+                     Expression* receiver,
+                     VariableProxy* arguments,
+                     int position);
+
+  // Control flow
+  void Branch(bool if_true, JumpTarget* target);
+  void CheckStack();
+
   bool CheckForInlineRuntimeCall(CallRuntime* node);
 
   static Handle<Code> ComputeLazyCompile(int argc);
   void ProcessDeclarations(ZoneList<Declaration*>* declarations);
 
-  Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
-
   // Declare global variables and functions in the given array of
   // name/value pairs.
   void DeclareGlobals(Handle<FixedArray> pairs);
 
+  // Instantiate the function based on the shared function info.
+  void InstantiateFunction(Handle<SharedFunctionInfo> function_info,
+                           bool pretenure);
+
   // Support for type checks.
   void GenerateIsSmi(ZoneList<Expression*>* args);
   void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
@@ -338,10 +513,13 @@
   void GenerateSetValueOf(ZoneList<Expression*>* args);
 
   // Fast support for charCodeAt(n).
-  void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
+  void GenerateStringCharCodeAt(ZoneList<Expression*>* args);
 
   // Fast support for string.charAt(n) and string[n].
-  void GenerateCharFromCode(ZoneList<Expression*>* args);
+  void GenerateStringCharFromCode(ZoneList<Expression*>* args);
+
+  // Fast support for string.charAt(n) and string[n].
+  void GenerateStringCharAt(ZoneList<Expression*>* args);
 
   // Fast support for object equality testing.
   void GenerateObjectEquals(ZoneList<Expression*>* args);
@@ -358,14 +536,38 @@
   void GenerateStringAdd(ZoneList<Expression*>* args);
   void GenerateSubString(ZoneList<Expression*>* args);
   void GenerateStringCompare(ZoneList<Expression*>* args);
+  void GenerateIsStringWrapperSafeForDefaultValueOf(
+      ZoneList<Expression*>* args);
+
+  // Support for direct calls from JavaScript to native RegExp code.
   void GenerateRegExpExec(ZoneList<Expression*>* args);
+
+  void GenerateRegExpConstructResult(ZoneList<Expression*>* args);
+
+  // Support for fast native caches.
+  void GenerateGetFromCache(ZoneList<Expression*>* args);
+
+  // Fast support for number to string.
   void GenerateNumberToString(ZoneList<Expression*>* args);
 
+  // Fast swapping of elements.
+  void GenerateSwapElements(ZoneList<Expression*>* args);
+
+  // Fast call for custom callbacks.
+  void GenerateCallFunction(ZoneList<Expression*>* args);
+
   // Fast call to math functions.
   void GenerateMathPow(ZoneList<Expression*>* args);
   void GenerateMathSin(ZoneList<Expression*>* args);
   void GenerateMathCos(ZoneList<Expression*>* args);
   void GenerateMathSqrt(ZoneList<Expression*>* args);
+  void GenerateMathLog(ZoneList<Expression*>* args);
+
+  void GenerateIsRegExpEquivalent(ZoneList<Expression*>* args);
+
+  void GenerateHasCachedArrayIndex(ZoneList<Expression*>* args);
+  void GenerateGetCachedArrayIndex(ZoneList<Expression*>* args);
+  void GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args);
 
   // Simple condition analysis.
   enum ConditionAnalysis {
@@ -389,9 +591,6 @@
   bool HasValidEntryRegisters();
 #endif
 
-  bool is_eval_;  // Tells whether code is generated for eval.
-
-  Handle<Script> script_;
   List<DeferredCode*> deferred_;
 
   // Assembler
@@ -404,7 +603,9 @@
   RegisterAllocator* allocator_;
   Condition cc_reg_;
   CodeGenState* state_;
+  int loop_nesting_;
 
+  Vector<TypeInfo>* type_info_;
   // Jump targets
   BreakTarget function_return_;
 
@@ -413,14 +614,15 @@
   // to some unlinking code).
   bool function_return_is_shadowed_;
 
-  static InlineRuntimeLUT kInlineRuntimeLUT[];
-
   friend class VirtualFrame;
+  friend class Isolate;
   friend class JumpTarget;
   friend class Reference;
   friend class FastCodeGenerator;
   friend class FullCodeGenerator;
   friend class FullCodeGenSyntaxChecker;
+  friend class InlineRuntimeFunctionsTable;
+  friend class LCodeGen;
 
   DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
 };
diff --git a/src/mips/constants-mips.cc b/src/mips/constants-mips.cc
index 49502bd..16e49c9 100644
--- a/src/mips/constants-mips.cc
+++ b/src/mips/constants-mips.cc
@@ -31,10 +31,8 @@
 
 #include "constants-mips.h"
 
-namespace assembler {
-namespace mips {
-
-namespace v8i = v8::internal;
+namespace v8 {
+namespace internal {
 
 
 // -----------------------------------------------------------------------------
@@ -102,20 +100,20 @@
 }
 
 
-const char* FPURegister::names_[kNumFPURegister] = {
+const char* FPURegisters::names_[kNumFPURegisters] = {
   "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11",
   "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21",
   "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
 };
 
 // List of alias names which can be used when referring to MIPS registers.
-const FPURegister::RegisterAlias FPURegister::aliases_[] = {
+const FPURegisters::RegisterAlias FPURegisters::aliases_[] = {
   {kInvalidRegister, NULL}
 };
 
-const char* FPURegister::Name(int creg) {
+const char* FPURegisters::Name(int creg) {
   const char* result;
-  if ((0 <= creg) && (creg < kNumFPURegister)) {
+  if ((0 <= creg) && (creg < kNumFPURegisters)) {
     result = names_[creg];
   } else {
     result = "nocreg";
@@ -124,9 +122,9 @@
 }
 
 
-int FPURegister::Number(const char* name) {
+int FPURegisters::Number(const char* name) {
   // Look through the canonical names.
-  for (int i = 0; i < kNumSimuRegisters; i++) {
+  for (int i = 0; i < kNumFPURegisters; i++) {
     if (strcmp(names_[i], name) == 0) {
       return i;
     }
@@ -149,8 +147,8 @@
 // -----------------------------------------------------------------------------
 // Instruction
 
-bool Instruction::IsForbiddenInBranchDelay() {
-  int op = OpcodeFieldRaw();
+bool Instruction::IsForbiddenInBranchDelay() const {
+  const int op = OpcodeFieldRaw();
   switch (op) {
     case J:
     case JAL:
@@ -189,13 +187,18 @@
 }
 
 
-bool Instruction::IsLinkingInstruction() {
-  int op = OpcodeFieldRaw();
+bool Instruction::IsLinkingInstruction() const {
+  const int op = OpcodeFieldRaw();
   switch (op) {
     case JAL:
-    case BGEZAL:
-    case BLTZAL:
-      return true;
+    case REGIMM:
+      switch (RtFieldRaw()) {
+        case BGEZAL:
+        case BLTZAL:
+          return true;
+      default:
+        return false;
+      };
     case SPECIAL:
       switch (FunctionFieldRaw()) {
         case JALR:
@@ -209,7 +212,7 @@
 }
 
 
-bool Instruction::IsTrap() {
+bool Instruction::IsTrap() const {
   if (OpcodeFieldRaw() != SPECIAL) {
     return false;
   } else {
@@ -264,6 +267,9 @@
         case TLTU:
         case TEQ:
         case TNE:
+        case MOVZ:
+        case MOVN:
+        case MOVCI:
           return kRegisterType;
         default:
           UNREACHABLE();
@@ -272,13 +278,23 @@
     case SPECIAL2:
       switch (FunctionFieldRaw()) {
         case MUL:
+        case CLZ:
+          return kRegisterType;
+        default:
+          UNREACHABLE();
+      };
+      break;
+    case SPECIAL3:
+      switch (FunctionFieldRaw()) {
+        case INS:
+        case EXT:
           return kRegisterType;
         default:
           UNREACHABLE();
       };
       break;
     case COP1:    // Coprocessor instructions
-      switch (FunctionFieldRaw()) {
+      switch (RsFieldRawNoAssert()) {
         case BC1:   // branch on coprocessor condition
           return kImmediateType;
         default:
@@ -304,10 +320,17 @@
     case BLEZL:
     case BGTZL:
     case LB:
+    case LH:
+    case LWL:
     case LW:
     case LBU:
+    case LHU:
+    case LWR:
     case SB:
+    case SH:
+    case SWL:
     case SW:
+    case SWR:
     case LWC1:
     case LDC1:
     case SWC1:
@@ -323,6 +346,7 @@
   return kUnsupported;
 }
 
-} }   // namespace assembler::mips
+
+} }   // namespace v8::internal
 
 #endif  // V8_TARGET_ARCH_MIPS
diff --git a/src/mips/constants-mips.h b/src/mips/constants-mips.h
index d0fdf88..b20e9a2 100644
--- a/src/mips/constants-mips.h
+++ b/src/mips/constants-mips.h
@@ -28,15 +28,25 @@
 #ifndef  V8_MIPS_CONSTANTS_H_
 #define  V8_MIPS_CONSTANTS_H_
 
-#include "checks.h"
-
 // UNIMPLEMENTED_ macro for MIPS.
+#ifdef DEBUG
 #define UNIMPLEMENTED_MIPS()                                                  \
   v8::internal::PrintF("%s, \tline %d: \tfunction %s not implemented. \n",    \
                        __FILE__, __LINE__, __func__)
+#else
+#define UNIMPLEMENTED_MIPS()
+#endif
+
 #define UNSUPPORTED_MIPS() v8::internal::PrintF("Unsupported instruction.\n")
 
 
+#ifdef _MIPS_ARCH_MIPS32R2
+  #define mips32r2 1
+#else
+  #define mips32r2 0
+#endif
+
+
 // Defines constants and accessor classes to assemble, disassemble and
 // simulate MIPS32 instructions.
 //
@@ -44,8 +54,8 @@
 //      Volume II: The MIPS32 Instruction Set
 // Try www.cs.cornell.edu/courses/cs3410/2008fa/MIPS_Vol2.pdf.
 
-namespace assembler {
-namespace mips {
+namespace v8 {
+namespace internal {
 
 // -----------------------------------------------------------------------------
 // Registers and FPURegister.
@@ -61,9 +71,18 @@
 static const int kPCRegister = 34;
 
 // Number coprocessor registers.
-static const int kNumFPURegister = 32;
+static const int kNumFPURegisters = 32;
 static const int kInvalidFPURegister = -1;
 
+// FPU (coprocessor 1) control registers. Currently only FCSR is implemented.
+static const int kFCSRRegister = 31;
+static const int kInvalidFPUControlRegister = -1;
+static const uint32_t kFPUInvalidResult = (uint32_t) (1 << 31) - 1;
+
+// FCSR constants.
+static const uint32_t kFCSRFlagMask = (1 << 6) - 1;
+static const uint32_t kFCSRFlagShift = 2;
+
 // Helper functions for converting between register numbers and names.
 class Registers {
  public:
@@ -88,7 +107,7 @@
 };
 
 // Helper functions for converting between register numbers and names.
-class FPURegister {
+class FPURegisters {
  public:
   // Return the name of the register.
   static const char* Name(int reg);
@@ -103,7 +122,7 @@
 
  private:
 
-  static const char* names_[kNumFPURegister];
+  static const char* names_[kNumFPURegisters];
   static const RegisterAlias aliases_[];
 };
 
@@ -136,6 +155,7 @@
 static const int kSaBits        = 5;
 static const int kFunctionShift = 0;
 static const int kFunctionBits  = 6;
+static const int kLuiShift      = 16;
 
 static const int kImm16Shift = 0;
 static const int kImm16Bits  = 16;
@@ -146,6 +166,14 @@
 static const int kFsBits        = 5;
 static const int kFtShift       = 16;
 static const int kFtBits        = 5;
+static const int kFdShift       = 6;
+static const int kFdBits        = 5;
+static const int kFCccShift     = 8;
+static const int kFCccBits      = 3;
+static const int kFBccShift     = 18;
+static const int kFBccBits      = 3;
+static const int kFBtrueShift   = 16;
+static const int kFBtrueBits    = 1;
 
 // ----- Miscellianous useful masks.
 // Instruction bit masks.
@@ -159,9 +187,9 @@
 static const int  kFunctionFieldMask =
     ((1 << kFunctionBits) - 1) << kFunctionShift;
 // Misc masks.
-static const int  HIMask        =   0xffff << 16;
-static const int  LOMask        =   0xffff;
-static const int  signMask      =   0x80000000;
+static const int  kHiMask       =   0xffff << 16;
+static const int  kLoMask       =   0xffff;
+static const int  kSignMask     =   0x80000000;
 
 
 // ----- MIPS Opcodes and Function Fields.
@@ -194,12 +222,20 @@
   BGTZL     =   ((2 << 3) + 7) << kOpcodeShift,
 
   SPECIAL2  =   ((3 << 3) + 4) << kOpcodeShift,
+  SPECIAL3  =   ((3 << 3) + 7) << kOpcodeShift,
 
   LB        =   ((4 << 3) + 0) << kOpcodeShift,
+  LH        =   ((4 << 3) + 1) << kOpcodeShift,
+  LWL       =   ((4 << 3) + 2) << kOpcodeShift,
   LW        =   ((4 << 3) + 3) << kOpcodeShift,
   LBU       =   ((4 << 3) + 4) << kOpcodeShift,
+  LHU       =   ((4 << 3) + 5) << kOpcodeShift,
+  LWR       =   ((4 << 3) + 6) << kOpcodeShift,
   SB        =   ((5 << 3) + 0) << kOpcodeShift,
+  SH        =   ((5 << 3) + 1) << kOpcodeShift,
+  SWL       =   ((5 << 3) + 2) << kOpcodeShift,
   SW        =   ((5 << 3) + 3) << kOpcodeShift,
+  SWR       =   ((5 << 3) + 6) << kOpcodeShift,
 
   LWC1      =   ((6 << 3) + 1) << kOpcodeShift,
   LDC1      =   ((6 << 3) + 5) << kOpcodeShift,
@@ -216,9 +252,12 @@
   SLLV      =   ((0 << 3) + 4),
   SRLV      =   ((0 << 3) + 6),
   SRAV      =   ((0 << 3) + 7),
+  MOVCI     =   ((0 << 3) + 1),
 
   JR        =   ((1 << 3) + 0),
   JALR      =   ((1 << 3) + 1),
+  MOVZ      =   ((1 << 3) + 2),
+  MOVN      =   ((1 << 3) + 3),
   BREAK     =   ((1 << 3) + 5),
 
   MFHI      =   ((2 << 3) + 0),
@@ -250,6 +289,12 @@
 
   // SPECIAL2 Encoding of Function Field.
   MUL       =   ((0 << 3) + 2),
+  CLZ       =   ((4 << 3) + 0),
+  CLO       =   ((4 << 3) + 1),
+
+  // SPECIAL3 Encoding of Function Field.
+  EXT       =   ((0 << 3) + 0),
+  INS       =   ((0 << 3) + 4),
 
   // REGIMM  encoding of rt Field.
   BLTZ      =   ((0 << 3) + 0) << 16,
@@ -259,8 +304,10 @@
 
   // COP1 Encoding of rs Field.
   MFC1      =   ((0 << 3) + 0) << 21,
+  CFC1      =   ((0 << 3) + 2) << 21,
   MFHC1     =   ((0 << 3) + 3) << 21,
   MTC1      =   ((0 << 3) + 4) << 21,
+  CTC1      =   ((0 << 3) + 6) << 21,
   MTHC1     =   ((0 << 3) + 7) << 21,
   BC1       =   ((1 << 3) + 0) << 21,
   S         =   ((2 << 3) + 0) << 21,
@@ -269,14 +316,46 @@
   L         =   ((2 << 3) + 5) << 21,
   PS        =   ((2 << 3) + 6) << 21,
   // COP1 Encoding of Function Field When rs=S.
+  ROUND_L_S =   ((1 << 3) + 0),
+  TRUNC_L_S =   ((1 << 3) + 1),
+  CEIL_L_S  =   ((1 << 3) + 2),
+  FLOOR_L_S =   ((1 << 3) + 3),
+  ROUND_W_S =   ((1 << 3) + 4),
+  TRUNC_W_S =   ((1 << 3) + 5),
+  CEIL_W_S  =   ((1 << 3) + 6),
+  FLOOR_W_S =   ((1 << 3) + 7),
   CVT_D_S   =   ((4 << 3) + 1),
   CVT_W_S   =   ((4 << 3) + 4),
   CVT_L_S   =   ((4 << 3) + 5),
   CVT_PS_S  =   ((4 << 3) + 6),
   // COP1 Encoding of Function Field When rs=D.
+  ADD_D     =   ((0 << 3) + 0),
+  SUB_D     =   ((0 << 3) + 1),
+  MUL_D     =   ((0 << 3) + 2),
+  DIV_D     =   ((0 << 3) + 3),
+  SQRT_D    =   ((0 << 3) + 4),
+  ABS_D     =   ((0 << 3) + 5),
+  MOV_D     =   ((0 << 3) + 6),
+  NEG_D     =   ((0 << 3) + 7),
+  ROUND_L_D =   ((1 << 3) + 0),
+  TRUNC_L_D =   ((1 << 3) + 1),
+  CEIL_L_D  =   ((1 << 3) + 2),
+  FLOOR_L_D =   ((1 << 3) + 3),
+  ROUND_W_D =   ((1 << 3) + 4),
+  TRUNC_W_D =   ((1 << 3) + 5),
+  CEIL_W_D  =   ((1 << 3) + 6),
+  FLOOR_W_D =   ((1 << 3) + 7),
   CVT_S_D   =   ((4 << 3) + 0),
   CVT_W_D   =   ((4 << 3) + 4),
   CVT_L_D   =   ((4 << 3) + 5),
+  C_F_D     =   ((6 << 3) + 0),
+  C_UN_D    =   ((6 << 3) + 1),
+  C_EQ_D    =   ((6 << 3) + 2),
+  C_UEQ_D   =   ((6 << 3) + 3),
+  C_OLT_D   =   ((6 << 3) + 4),
+  C_ULT_D   =   ((6 << 3) + 5),
+  C_OLE_D   =   ((6 << 3) + 6),
+  C_ULE_D   =   ((6 << 3) + 7),
   // COP1 Encoding of Function Field When rs=W or L.
   CVT_S_W   =   ((4 << 3) + 0),
   CVT_D_W   =   ((4 << 3) + 1),
@@ -293,7 +372,7 @@
 // the 'U' prefix is used to specify unsigned comparisons.
 enum Condition {
   // Any value < 0 is considered no_condition.
-  no_condition  = -1,
+  kNoCondition  = -1,
 
   overflow      =  0,
   no_overflow   =  1,
@@ -321,12 +400,59 @@
   eq            = equal,
   not_zero      = not_equal,
   ne            = not_equal,
+  nz            = not_equal,
   sign          = negative,
   not_sign      = positive,
+  mi            = negative,
+  pl            = positive,
+  hi            = Ugreater,
+  ls            = Uless_equal,
+  ge            = greater_equal,
+  lt            = less,
+  gt            = greater,
+  le            = less_equal,
+  hs            = Ugreater_equal,
+  lo            = Uless,
+  al            = cc_always,
 
-  cc_default    = no_condition
+  cc_default    = kNoCondition
 };
 
+
+// Returns the equivalent of !cc.
+// Negation of the default kNoCondition (-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) {
+  ASSERT(cc != cc_always);
+  return static_cast<Condition>(cc ^ 1);
+}
+
+
+inline Condition ReverseCondition(Condition cc) {
+  switch (cc) {
+    case Uless:
+      return Ugreater;
+    case Ugreater:
+      return Uless;
+    case Ugreater_equal:
+      return Uless_equal;
+    case Uless_equal:
+      return Ugreater_equal;
+    case less:
+      return greater;
+    case greater:
+      return less;
+    case greater_equal:
+      return less_equal;
+    case less_equal:
+      return greater_equal;
+    default:
+      return cc;
+  };
+}
+
+
 // ----- Coprocessor conditions.
 enum FPUCondition {
   F,    // False
@@ -340,6 +466,46 @@
 };
 
 
+// -----------------------------------------------------------------------------
+// Hints.
+
+// Branch hints are not used on the MIPS.  They are defined so that they can
+// appear in shared function signatures, but will be ignored in MIPS
+// implementations.
+enum Hint {
+  no_hint = 0
+};
+
+
+inline Hint NegateHint(Hint hint) {
+  return no_hint;
+}
+
+
+// -----------------------------------------------------------------------------
+// Specific instructions, constants, and masks.
+// These constants are declared in assembler-mips.cc, as they use named
+// registers and other constants.
+
+// addiu(sp, sp, 4) aka Pop() operation or part of Pop(r)
+// operations as post-increment of sp.
+extern const Instr kPopInstruction;
+// addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp.
+extern const Instr kPushInstruction;
+// sw(r, MemOperand(sp, 0))
+extern const Instr kPushRegPattern;
+//  lw(r, MemOperand(sp, 0))
+extern const Instr kPopRegPattern;
+extern const Instr kLwRegFpOffsetPattern;
+extern const Instr kSwRegFpOffsetPattern;
+extern const Instr kLwRegFpNegOffsetPattern;
+extern const Instr kSwRegFpNegOffsetPattern;
+// A mask for the Rt register for push, pop, lw, sw instructions.
+extern const Instr kRtMask;
+extern const Instr kLwSwInstrTypeMask;
+extern const Instr kLwSwInstrArgumentMask;
+extern const Instr kLwSwOffsetMask;
+
 // Break 0xfffff, reserved for redirected real time call.
 const Instr rtCallRedirInstr = SPECIAL | BREAK | call_rt_redirected << 6;
 // A nop instruction. (Encoding of sll 0 0 0).
@@ -348,10 +514,10 @@
 class Instruction {
  public:
   enum {
-    kInstructionSize = 4,
-    kInstructionSizeLog2 = 2,
+    kInstrSize = 4,
+    kInstrSizeLog2 = 2,
     // On MIPS PC cannot actually be directly accessed. We behave as if PC was
-    // always the value of the current instruction being exectued.
+    // always the value of the current instruction being executed.
     kPCReadOffset = 0
   };
 
@@ -388,45 +554,64 @@
 
 
   // Accessors for the different named fields used in the MIPS encoding.
-  inline Opcode OpcodeField() const {
+  inline Opcode OpcodeValue() const {
     return static_cast<Opcode>(
         Bits(kOpcodeShift + kOpcodeBits - 1, kOpcodeShift));
   }
 
-  inline int RsField() const {
+  inline int RsValue() const {
     ASSERT(InstructionType() == kRegisterType ||
            InstructionType() == kImmediateType);
     return Bits(kRsShift + kRsBits - 1, kRsShift);
   }
 
-  inline int RtField() const {
+  inline int RtValue() const {
     ASSERT(InstructionType() == kRegisterType ||
            InstructionType() == kImmediateType);
     return Bits(kRtShift + kRtBits - 1, kRtShift);
   }
 
-  inline int RdField() const {
+  inline int RdValue() const {
     ASSERT(InstructionType() == kRegisterType);
     return Bits(kRdShift + kRdBits - 1, kRdShift);
   }
 
-  inline int SaField() const {
+  inline int SaValue() const {
     ASSERT(InstructionType() == kRegisterType);
     return Bits(kSaShift + kSaBits - 1, kSaShift);
   }
 
-  inline int FunctionField() const {
+  inline int FunctionValue() const {
     ASSERT(InstructionType() == kRegisterType ||
            InstructionType() == kImmediateType);
     return Bits(kFunctionShift + kFunctionBits - 1, kFunctionShift);
   }
 
-  inline int FsField() const {
-    return Bits(kFsShift + kRsBits - 1, kFsShift);
+  inline int FdValue() const {
+    return Bits(kFdShift + kFdBits - 1, kFdShift);
   }
 
-  inline int FtField() const {
-    return Bits(kFtShift + kRsBits - 1, kFtShift);
+  inline int FsValue() const {
+    return Bits(kFsShift + kFsBits - 1, kFsShift);
+  }
+
+  inline int FtValue() const {
+    return Bits(kFtShift + kFtBits - 1, kFtShift);
+  }
+
+  // Float Compare condition code instruction bits.
+  inline int FCccValue() const {
+    return Bits(kFCccShift + kFCccBits - 1, kFCccShift);
+  }
+
+  // Float Branch condition code instruction bits.
+  inline int FBccValue() const {
+    return Bits(kFBccShift + kFBccBits - 1, kFBccShift);
+  }
+
+  // Float Branch true/false instruction bit.
+  inline int FBtrueValue() const {
+    return Bits(kFBtrueShift + kFBtrueBits - 1, kFBtrueShift);
   }
 
   // Return the fields at their original place in the instruction encoding.
@@ -440,6 +625,11 @@
     return InstructionBits() & kRsFieldMask;
   }
 
+  // Same as above function, but safe to call within InstructionType().
+  inline int RsFieldRawNoAssert() const {
+    return InstructionBits() & kRsFieldMask;
+  }
+
   inline int RtFieldRaw() const {
     ASSERT(InstructionType() == kRegisterType ||
            InstructionType() == kImmediateType);
@@ -461,37 +651,37 @@
   }
 
   // Get the secondary field according to the opcode.
-  inline int SecondaryField() const {
+  inline int SecondaryValue() const {
     Opcode op = OpcodeFieldRaw();
     switch (op) {
       case SPECIAL:
       case SPECIAL2:
-        return FunctionField();
+        return FunctionValue();
       case COP1:
-        return RsField();
+        return RsValue();
       case REGIMM:
-        return RtField();
+        return RtValue();
       default:
         return NULLSF;
     }
   }
 
-  inline int32_t Imm16Field() const {
+  inline int32_t Imm16Value() const {
     ASSERT(InstructionType() == kImmediateType);
     return Bits(kImm16Shift + kImm16Bits - 1, kImm16Shift);
   }
 
-  inline int32_t Imm26Field() const {
+  inline int32_t Imm26Value() const {
     ASSERT(InstructionType() == kJumpType);
     return Bits(kImm16Shift + kImm26Bits - 1, kImm26Shift);
   }
 
   // Say if the instruction should not be used in a branch delay slot.
-  bool IsForbiddenInBranchDelay();
+  bool IsForbiddenInBranchDelay() const;
   // Say if the instruction 'links'. eg: jal, bal.
-  bool IsLinkingInstruction();
+  bool IsLinkingInstruction() const;
   // Say if the instruction is a break or a trap.
-  bool IsTrap();
+  bool IsTrap() const;
 
   // 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
@@ -510,16 +700,24 @@
 // -----------------------------------------------------------------------------
 // MIPS assembly various constants.
 
-static const int kArgsSlotsSize  = 4 * Instruction::kInstructionSize;
+
+static const int kArgsSlotsSize  = 4 * Instruction::kInstrSize;
 static const int kArgsSlotsNum   = 4;
+// C/C++ argument slots size.
+static const int kCArgsSlotsSize = 4 * Instruction::kInstrSize;
+// JS argument slots size.
+static const int kJSArgsSlotsSize = 0 * Instruction::kInstrSize;
+// Assembly builtins argument slots size.
+static const int kBArgsSlotsSize = 0 * Instruction::kInstrSize;
 
-static const int kBranchReturnOffset = 2 * Instruction::kInstructionSize;
+static const int kBranchReturnOffset = 2 * Instruction::kInstrSize;
 
-static const int kDoubleAlignment = 2 * 8;
-static const int kDoubleAlignmentMask = kDoubleAlignmentMask - 1;
+static const int kDoubleAlignmentBits = 3;
+static const int kDoubleAlignment = (1 << kDoubleAlignmentBits);
+static const int kDoubleAlignmentMask = kDoubleAlignment - 1;
 
 
-} }   // namespace assembler::mips
+} }   // namespace v8::internal
 
 #endif    // #ifndef V8_MIPS_CONSTANTS_H_
 
diff --git a/src/mips/cpu-mips.cc b/src/mips/cpu-mips.cc
index 659fc01..36f577b 100644
--- a/src/mips/cpu-mips.cc
+++ b/src/mips/cpu-mips.cc
@@ -39,16 +39,25 @@
 #if defined(V8_TARGET_ARCH_MIPS)
 
 #include "cpu.h"
+#include "macro-assembler.h"
+
+#include "simulator.h"  // For cache flushing.
 
 namespace v8 {
 namespace internal {
 
+
 void CPU::Setup() {
-  // Nothing to do.
+  CpuFeatures* cpu_features = Isolate::Current()->cpu_features();
+  cpu_features->Probe(true);
+  if (!cpu_features->IsSupported(FPU) || Serializer::enabled()) {
+    V8::DisableCrankshaft();
+  }
 }
 
+
 void CPU::FlushICache(void* start, size_t size) {
-#ifdef __mips
+#if !defined (USE_SIMULATOR)
   int res;
 
   // See http://www.linux-mips.org/wiki/Cacheflush_Syscall
@@ -58,7 +67,14 @@
     V8_Fatal(__FILE__, __LINE__, "Failed to flush the instruction cache");
   }
 
-#endif    // #ifdef __mips
+#else  // USE_SIMULATOR.
+  // Not generating mips instructions for C-code. This means that we are
+  // building a mips emulator based target.  We should notify the simulator
+  // that the Icache was flushed.
+  // None of this code ends up in the snapshot so there are no issues
+  // around whether or not to generate the code when building snapshots.
+  Simulator::FlushICache(Isolate::Current()->simulator_i_cache(), start, size);
+#endif  // USE_SIMULATOR.
 }
 
 
@@ -68,6 +84,7 @@
 #endif  // #ifdef __mips
 }
 
+
 } }  // namespace v8::internal
 
 #endif  // V8_TARGET_ARCH_MIPS
diff --git a/src/mips/debug-mips.cc b/src/mips/debug-mips.cc
index b8ae68e..35df69b 100644
--- a/src/mips/debug-mips.cc
+++ b/src/mips/debug-mips.cc
@@ -38,8 +38,10 @@
 namespace internal {
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
+
 bool BreakLocationIterator::IsDebugBreakAtReturn() {
-  return Debug::IsDebugBreakAtReturn(rinfo());
+  UNIMPLEMENTED_MIPS();
+  return false;
 }
 
 
@@ -54,18 +56,33 @@
 }
 
 
-// A debug break in the exit code is identified by a call.
+// A debug break in the exit code is identified by the JS frame exit code
+// having been patched with li/call psuedo-instrunction (liu/ori/jalr)
 bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
-  ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()));
-  return rinfo->IsPatchedReturnSequence();
+  UNIMPLEMENTED_MIPS();
+  return false;
+}
+
+
+bool BreakLocationIterator::IsDebugBreakAtSlot() {
+  UNIMPLEMENTED_MIPS();
+  return false;
+}
+
+
+void BreakLocationIterator::SetDebugBreakAtSlot() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void BreakLocationIterator::ClearDebugBreakAtSlot() {
+  UNIMPLEMENTED_MIPS();
 }
 
 
 #define __ ACCESS_MASM(masm)
 
 
-
-
 void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
   UNIMPLEMENTED_MIPS();
 }
@@ -106,12 +123,23 @@
 }
 
 
-void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
-  masm->Abort("LiveEdit frame dropping is not supported on mips");
+void Debug::GenerateSlot(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
 }
 
+
+void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
-  masm->Abort("LiveEdit frame dropping is not supported on mips");
+  UNIMPLEMENTED_MIPS();
 }
 
 
diff --git a/src/mips/deoptimizer-mips.cc b/src/mips/deoptimizer-mips.cc
new file mode 100644
index 0000000..4b69859
--- /dev/null
+++ b/src/mips/deoptimizer-mips.cc
@@ -0,0 +1,91 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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.h"
+#include "deoptimizer.h"
+#include "full-codegen.h"
+#include "safepoint-table.h"
+
+// Note: this file was taken from the X64 version. ARM has a partially working
+// lithium implementation, but for now it is not ported to mips.
+
+namespace v8 {
+namespace internal {
+
+
+int Deoptimizer::table_entry_size_ = 10;
+
+
+int Deoptimizer::patch_size() {
+  const int kCallInstructionSizeInWords = 3;
+  return kCallInstructionSizeInWords * Assembler::kInstrSize;
+}
+
+
+void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
+  UNIMPLEMENTED();
+}
+
+
+void Deoptimizer::PatchStackCheckCodeAt(Address pc_after,
+                                        Code* check_code,
+                                        Code* replacement_code) {
+  UNIMPLEMENTED();
+}
+
+
+void Deoptimizer::RevertStackCheckCodeAt(Address pc_after,
+                                         Code* check_code,
+                                         Code* replacement_code) {
+  UNIMPLEMENTED();
+}
+
+
+void Deoptimizer::DoComputeOsrOutputFrame() {
+  UNIMPLEMENTED();
+}
+
+
+void Deoptimizer::DoComputeFrame(TranslationIterator* iterator,
+                                 int frame_index) {
+  UNIMPLEMENTED();
+}
+
+
+void Deoptimizer::EntryGenerator::Generate() {
+  UNIMPLEMENTED();
+}
+
+
+void Deoptimizer::TableEntryGenerator::GeneratePrologue() {
+  UNIMPLEMENTED();
+}
+
+
+} }  // namespace v8::internal
diff --git a/src/mips/disasm-mips.cc b/src/mips/disasm-mips.cc
index 959a4a2..b7ceb2b 100644
--- a/src/mips/disasm-mips.cc
+++ b/src/mips/disasm-mips.cc
@@ -34,10 +34,9 @@
 //   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);
+//     v8::internal::EmbeddedVector<char, 256> buffer;
+//     byte* prev_pc = pc;
+//     pc += d.InstructionDecode(buffer, pc);
 //     printf("%p    %08x      %s\n",
 //            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
 //   }
@@ -59,17 +58,13 @@
 
 #if defined(V8_TARGET_ARCH_MIPS)
 
-#include "constants-mips.h"
+#include "mips/constants-mips.h"
 #include "disasm.h"
 #include "macro-assembler.h"
 #include "platform.h"
 
-namespace assembler {
-namespace mips {
-
-
-namespace v8i = v8::internal;
-
+namespace v8 {
+namespace internal {
 
 //------------------------------------------------------------------------------
 
@@ -99,7 +94,7 @@
 
   // Printing of common values.
   void PrintRegister(int reg);
-  void PrintCRegister(int creg);
+  void PrintFPURegister(int freg);
   void PrintRs(Instruction* instr);
   void PrintRt(Instruction* instr);
   void PrintRd(Instruction* instr);
@@ -107,6 +102,9 @@
   void PrintFt(Instruction* instr);
   void PrintFd(Instruction* instr);
   void PrintSa(Instruction* instr);
+  void PrintSd(Instruction* instr);
+  void PrintBc(Instruction* instr);
+  void PrintCc(Instruction* instr);
   void PrintFunction(Instruction* instr);
   void PrintSecondaryField(Instruction* instr);
   void PrintUImm16(Instruction* instr);
@@ -119,7 +117,7 @@
 
   // Handle formatting of instructions and their options.
   int FormatRegister(Instruction* instr, const char* option);
-  int FormatCRegister(Instruction* instr, const char* option);
+  int FormatFPURegister(Instruction* instr, const char* option);
   int FormatOption(Instruction* instr, const char* option);
   void Format(Instruction* instr, const char* format);
   void Unknown(Instruction* instr);
@@ -166,84 +164,100 @@
 
 
 void Decoder::PrintRs(Instruction* instr) {
-  int reg = instr->RsField();
+  int reg = instr->RsValue();
   PrintRegister(reg);
 }
 
 
 void Decoder::PrintRt(Instruction* instr) {
-  int reg = instr->RtField();
+  int reg = instr->RtValue();
   PrintRegister(reg);
 }
 
 
 void Decoder::PrintRd(Instruction* instr) {
-  int reg = instr->RdField();
+  int reg = instr->RdValue();
   PrintRegister(reg);
 }
 
 
-// Print the Cregister name according to the active name converter.
-void Decoder::PrintCRegister(int creg) {
-  Print(converter_.NameOfXMMRegister(creg));
+// Print the FPUregister name according to the active name converter.
+void Decoder::PrintFPURegister(int freg) {
+  Print(converter_.NameOfXMMRegister(freg));
 }
 
 
 void Decoder::PrintFs(Instruction* instr) {
-  int creg = instr->RsField();
-  PrintCRegister(creg);
+  int freg = instr->RsValue();
+  PrintFPURegister(freg);
 }
 
 
 void Decoder::PrintFt(Instruction* instr) {
-  int creg = instr->RtField();
-  PrintCRegister(creg);
+  int freg = instr->RtValue();
+  PrintFPURegister(freg);
 }
 
 
 void Decoder::PrintFd(Instruction* instr) {
-  int creg = instr->RdField();
-  PrintCRegister(creg);
+  int freg = instr->RdValue();
+  PrintFPURegister(freg);
 }
 
 
 // Print the integer value of the sa field.
 void Decoder::PrintSa(Instruction* instr) {
-  int sa = instr->SaField();
-  out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                       "%d", sa);
+  int sa = instr->SaValue();
+  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sa);
+}
+
+
+// Print the integer value of the rd field, (when it is not used as reg).
+void Decoder::PrintSd(Instruction* instr) {
+  int sd = instr->RdValue();
+  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sd);
+}
+
+
+// Print the integer value of the cc field for the bc1t/f instructions.
+void Decoder::PrintBc(Instruction* instr) {
+  int cc = instr->FBccValue();
+  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", cc);
+}
+
+
+// Print the integer value of the cc field for the FP compare instructions.
+void Decoder::PrintCc(Instruction* instr) {
+  int cc = instr->FCccValue();
+  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "cc(%d)", cc);
 }
 
 
 // Print 16-bit unsigned immediate value.
 void Decoder::PrintUImm16(Instruction* instr) {
-  int32_t imm = instr->Imm16Field();
-  out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                       "%u", imm);
+  int32_t imm = instr->Imm16Value();
+  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm);
 }
 
 
 // Print 16-bit signed immediate value.
 void Decoder::PrintSImm16(Instruction* instr) {
-  int32_t imm = ((instr->Imm16Field())<<16)>>16;
-  out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                       "%d", imm);
+  int32_t imm = ((instr->Imm16Value())<<16)>>16;
+  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm);
 }
 
 
 // Print 16-bit hexa immediate value.
 void Decoder::PrintXImm16(Instruction* instr) {
-  int32_t imm = instr->Imm16Field();
-  out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                       "0x%x", imm);
+  int32_t imm = instr->Imm16Value();
+  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
 }
 
 
 // Print 26-bit immediate value.
 void Decoder::PrintImm26(Instruction* instr) {
-  int32_t imm = instr->Imm26Field();
-  out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                       "%d", imm);
+  int32_t imm = instr->Imm26Value();
+  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm);
 }
 
 
@@ -254,8 +268,8 @@
   switch (instr->FunctionFieldRaw()) {
     case BREAK: {
       int32_t code = instr->Bits(25, 6);
-      out_buffer_pos_ +=
-          v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%05x", code);
+      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                      "0x%05x (%d)", code, code);
       break;
                 }
     case TGE:
@@ -266,7 +280,7 @@
     case TNE: {
       int32_t code = instr->Bits(15, 6);
       out_buffer_pos_ +=
-          v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%03x", code);
+          OS::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%03x", code);
       break;
     }
     default:  // Not a break or trap instruction.
@@ -285,15 +299,15 @@
 int Decoder::FormatRegister(Instruction* instr, const char* format) {
   ASSERT(format[0] == 'r');
   if (format[1] == 's') {  // 'rs: Rs register
-    int reg = instr->RsField();
+    int reg = instr->RsValue();
     PrintRegister(reg);
     return 2;
   } else if (format[1] == 't') {  // 'rt: rt register
-    int reg = instr->RtField();
+    int reg = instr->RtValue();
     PrintRegister(reg);
     return 2;
   } else if (format[1] == 'd') {  // 'rd: rd register
-    int reg = instr->RdField();
+    int reg = instr->RdValue();
     PrintRegister(reg);
     return 2;
   }
@@ -302,21 +316,21 @@
 }
 
 
-// Handle all Cregister based formatting in this function to reduce the
+// Handle all FPUregister based formatting in this function to reduce the
 // complexity of FormatOption.
-int Decoder::FormatCRegister(Instruction* instr, const char* format) {
+int Decoder::FormatFPURegister(Instruction* instr, const char* format) {
   ASSERT(format[0] == 'f');
   if (format[1] == 's') {  // 'fs: fs register
-    int reg = instr->RsField();
-    PrintCRegister(reg);
+    int reg = instr->FsValue();
+    PrintFPURegister(reg);
     return 2;
   } else if (format[1] == 't') {  // 'ft: ft register
-    int reg = instr->RtField();
-    PrintCRegister(reg);
+    int reg = instr->FtValue();
+    PrintFPURegister(reg);
     return 2;
   } else if (format[1] == 'd') {  // 'fd: fd register
-    int reg = instr->RdField();
-    PrintCRegister(reg);
+    int reg = instr->FdValue();
+    PrintFPURegister(reg);
     return 2;
   }
   UNREACHABLE();
@@ -359,12 +373,31 @@
     case 'r': {   // 'r: registers
       return FormatRegister(instr, format);
     }
-    case 'f': {   // 'f: Cregisters
-      return FormatCRegister(instr, format);
+    case 'f': {   // 'f: FPUregisters
+      return FormatFPURegister(instr, format);
     }
     case 's': {   // 'sa
-      ASSERT(STRING_STARTS_WITH(format, "sa"));
-      PrintSa(instr);
+      switch (format[1]) {
+        case 'a': {
+          ASSERT(STRING_STARTS_WITH(format, "sa"));
+          PrintSa(instr);
+          return 2;
+        }
+        case 'd': {
+          ASSERT(STRING_STARTS_WITH(format, "sd"));
+          PrintSd(instr);
+          return 2;
+        }
+      }
+    }
+    case 'b': {   // 'bc - Special for bc1 cc field.
+      ASSERT(STRING_STARTS_WITH(format, "bc"));
+      PrintBc(instr);
+      return 2;
+    }
+    case 'C': {   // 'Cc - Special for c.xx.d cc field.
+      ASSERT(STRING_STARTS_WITH(format, "Cc"));
+      PrintCc(instr);
       return 2;
     }
   };
@@ -401,45 +434,160 @@
   switch (instr->OpcodeFieldRaw()) {
     case COP1:    // Coprocessor instructions
       switch (instr->RsFieldRaw()) {
-        case BC1:   // branch on coprocessor condition
+        case BC1:   // bc1 handled in DecodeTypeImmediate.
           UNREACHABLE();
           break;
         case MFC1:
-          Format(instr, "mfc1 'rt, 'fs");
+          Format(instr, "mfc1   'rt, 'fs");
           break;
         case MFHC1:
-          Format(instr, "mfhc1  rt, 'fs");
+          Format(instr, "mfhc1  'rt, 'fs");
           break;
         case MTC1:
-          Format(instr, "mtc1 'rt, 'fs");
+          Format(instr, "mtc1   'rt, 'fs");
+          break;
+        // These are called "fs" too, although they are not FPU registers.
+        case CTC1:
+          Format(instr, "ctc1   'rt, 'fs");
+          break;
+        case CFC1:
+          Format(instr, "cfc1   'rt, 'fs");
           break;
         case MTHC1:
-          Format(instr, "mthc1  rt, 'fs");
+          Format(instr, "mthc1  'rt, 'fs");
+          break;
+        case D:
+          switch (instr->FunctionFieldRaw()) {
+            case ADD_D:
+              Format(instr, "add.d   'fd, 'fs, 'ft");
+              break;
+            case SUB_D:
+              Format(instr, "sub.d   'fd, 'fs, 'ft");
+              break;
+            case MUL_D:
+              Format(instr, "mul.d   'fd, 'fs, 'ft");
+              break;
+            case DIV_D:
+              Format(instr, "div.d   'fd, 'fs, 'ft");
+              break;
+            case ABS_D:
+              Format(instr, "abs.d   'fd, 'fs");
+              break;
+            case MOV_D:
+              Format(instr, "mov.d   'fd, 'fs");
+              break;
+            case NEG_D:
+              Format(instr, "neg.d   'fd, 'fs");
+              break;
+            case SQRT_D:
+              Format(instr, "sqrt.d   'fd, 'fs");
+              break;
+            case CVT_W_D:
+              Format(instr, "cvt.w.d 'fd, 'fs");
+              break;
+            case CVT_L_D: {
+              if (mips32r2) {
+                Format(instr, "cvt.l.d 'fd, 'fs");
+              } else {
+                Unknown(instr);
+              }
+              break;
+            }
+            case TRUNC_W_D:
+              Format(instr, "trunc.w.d 'fd, 'fs");
+              break;
+            case TRUNC_L_D: {
+              if (mips32r2) {
+                Format(instr, "trunc.l.d 'fd, 'fs");
+              } else {
+                Unknown(instr);
+              }
+              break;
+            }
+            case ROUND_W_D:
+              Format(instr, "round.w.d 'fd, 'fs");
+              break;
+            case FLOOR_W_D:
+              Format(instr, "floor.w.d 'fd, 'fs");
+              break;
+            case CEIL_W_D:
+              Format(instr, "ceil.w.d 'fd, 'fs");
+              break;
+            case CVT_S_D:
+              Format(instr, "cvt.s.d 'fd, 'fs");
+              break;
+            case C_F_D:
+              Format(instr, "c.f.d   'fs, 'ft, 'Cc");
+              break;
+            case C_UN_D:
+              Format(instr, "c.un.d  'fs, 'ft, 'Cc");
+              break;
+            case C_EQ_D:
+              Format(instr, "c.eq.d  'fs, 'ft, 'Cc");
+              break;
+            case C_UEQ_D:
+              Format(instr, "c.ueq.d 'fs, 'ft, 'Cc");
+              break;
+            case C_OLT_D:
+              Format(instr, "c.olt.d 'fs, 'ft, 'Cc");
+              break;
+            case C_ULT_D:
+              Format(instr, "c.ult.d 'fs, 'ft, 'Cc");
+              break;
+            case C_OLE_D:
+              Format(instr, "c.ole.d 'fs, 'ft, 'Cc");
+              break;
+            case C_ULE_D:
+              Format(instr, "c.ule.d 'fs, 'ft, 'Cc");
+              break;
+            default:
+              Format(instr, "unknown.cop1.d");
+              break;
+          }
           break;
         case S:
-        case D:
           UNIMPLEMENTED_MIPS();
           break;
         case W:
           switch (instr->FunctionFieldRaw()) {
-            case CVT_S_W:
-              UNIMPLEMENTED_MIPS();
+            case CVT_S_W:   // Convert word to float (single).
+              Format(instr, "cvt.s.w 'fd, 'fs");
               break;
             case CVT_D_W:   // Convert word to double.
-              Format(instr, "cvt.d.w  'fd, 'fs");
+              Format(instr, "cvt.d.w 'fd, 'fs");
               break;
             default:
               UNREACHABLE();
-          };
+          }
           break;
         case L:
+          switch (instr->FunctionFieldRaw()) {
+            case CVT_D_L: {
+              if (mips32r2) {
+                Format(instr, "cvt.d.l 'fd, 'fs");
+              } else {
+                Unknown(instr);
+              }
+              break;
+            }
+            case CVT_S_L: {
+              if (mips32r2) {
+                Format(instr, "cvt.s.l 'fd, 'fs");
+              } else {
+                Unknown(instr);
+              }
+              break;
+            }
+            default:
+              UNREACHABLE();
+          }
+          break;
         case PS:
           UNIMPLEMENTED_MIPS();
           break;
-          break;
         default:
           UNREACHABLE();
-      };
+      }
       break;
     case SPECIAL:
       switch (instr->FunctionFieldRaw()) {
@@ -456,7 +604,15 @@
             Format(instr, "sll  'rd, 'rt, 'sa");
           break;
         case SRL:
-          Format(instr, "srl  'rd, 'rt, 'sa");
+          if (instr->RsValue() == 0) {
+            Format(instr, "srl  'rd, 'rt, 'sa");
+          } else {
+            if (mips32r2) {
+              Format(instr, "rotr  'rd, 'rt, 'sa");
+            } else {
+              Unknown(instr);
+            }
+          }
           break;
         case SRA:
           Format(instr, "sra  'rd, 'rt, 'sa");
@@ -465,7 +621,15 @@
           Format(instr, "sllv 'rd, 'rt, 'rs");
           break;
         case SRLV:
-          Format(instr, "srlv 'rd, 'rt, 'rs");
+          if (instr->SaValue() == 0) {
+            Format(instr, "srlv 'rd, 'rt, 'rs");
+          } else {
+            if (mips32r2) {
+              Format(instr, "rotrv 'rd, 'rt, 'rs");
+            } else {
+              Unknown(instr);
+            }
+          }
           break;
         case SRAV:
           Format(instr, "srav 'rd, 'rt, 'rs");
@@ -504,9 +668,9 @@
           Format(instr, "and  'rd, 'rs, 'rt");
           break;
         case OR:
-          if (0 == instr->RsField()) {
+          if (0 == instr->RsValue()) {
             Format(instr, "mov  'rd, 'rt");
-          } else if (0 == instr->RtField()) {
+          } else if (0 == instr->RtValue()) {
             Format(instr, "mov  'rd, 'rs");
           } else {
             Format(instr, "or   'rd, 'rs, 'rt");
@@ -545,27 +709,79 @@
         case TNE:
           Format(instr, "tne  'rs, 'rt, code: 'code");
           break;
+        case MOVZ:
+          Format(instr, "movz 'rd, 'rs, 'rt");
+          break;
+        case MOVN:
+          Format(instr, "movn 'rd, 'rs, 'rt");
+          break;
+        case MOVCI:
+          if (instr->Bit(16)) {
+            Format(instr, "movt 'rd, 'rs, 'Cc");
+          } else {
+            Format(instr, "movf 'rd, 'rs, 'Cc");
+          }
+          break;
         default:
           UNREACHABLE();
-      };
+      }
       break;
     case SPECIAL2:
       switch (instr->FunctionFieldRaw()) {
         case MUL:
+          Format(instr, "mul  'rd, 'rs, 'rt");
+          break;
+        case CLZ:
+          Format(instr, "clz  'rd, 'rs");
           break;
         default:
           UNREACHABLE();
-      };
+      }
+      break;
+    case SPECIAL3:
+      switch (instr->FunctionFieldRaw()) {
+        case INS: {
+          if (mips32r2) {
+            Format(instr, "ins  'rt, 'rs, 'sd, 'sa");
+          } else {
+            Unknown(instr);
+          }
+          break;
+        }
+        case EXT: {
+          if (mips32r2) {
+            Format(instr, "ext  'rt, 'rs, 'sd, 'sa");
+          } else {
+            Unknown(instr);
+          }
+          break;
+        }
+        default:
+          UNREACHABLE();
+      }
       break;
     default:
       UNREACHABLE();
-  };
+  }
 }
 
 
 void Decoder::DecodeTypeImmediate(Instruction* instr) {
   switch (instr->OpcodeFieldRaw()) {
     // ------------- REGIMM class.
+    case COP1:
+      switch (instr->RsFieldRaw()) {
+        case BC1:
+          if (instr->FBtrueValue()) {
+            Format(instr, "bc1t    'bc, 'imm16u");
+          } else {
+            Format(instr, "bc1f    'bc, 'imm16u");
+          }
+          break;
+        default:
+          UNREACHABLE();
+      };
+      break;  // Case COP1.
     case REGIMM:
       switch (instr->RtFieldRaw()) {
         case BLTZ:
@@ -582,8 +798,8 @@
           break;
         default:
           UNREACHABLE();
-      };
-    break;  // case REGIMM
+      }
+    break;  // Case REGIMM.
     // ------------- Branch instructions.
     case BEQ:
       Format(instr, "beq  'rs, 'rt, 'imm16u");
@@ -626,18 +842,39 @@
     case LB:
       Format(instr, "lb     'rt, 'imm16s('rs)");
       break;
+    case LH:
+      Format(instr, "lh     'rt, 'imm16s('rs)");
+      break;
+    case LWL:
+      Format(instr, "lwl    'rt, 'imm16s('rs)");
+      break;
     case LW:
       Format(instr, "lw     'rt, 'imm16s('rs)");
       break;
     case LBU:
       Format(instr, "lbu    'rt, 'imm16s('rs)");
       break;
+    case LHU:
+      Format(instr, "lhu    'rt, 'imm16s('rs)");
+      break;
+    case LWR:
+      Format(instr, "lwr    'rt, 'imm16s('rs)");
+      break;
     case SB:
       Format(instr, "sb     'rt, 'imm16s('rs)");
       break;
+    case SH:
+      Format(instr, "sh     'rt, 'imm16s('rs)");
+      break;
+    case SWL:
+      Format(instr, "swl    'rt, 'imm16s('rs)");
+      break;
     case SW:
       Format(instr, "sw     'rt, 'imm16s('rs)");
       break;
+    case SWR:
+      Format(instr, "swr    'rt, 'imm16s('rs)");
+      break;
     case LWC1:
       Format(instr, "lwc1   'ft, 'imm16s('rs)");
       break;
@@ -645,10 +882,10 @@
       Format(instr, "ldc1   'ft, 'imm16s('rs)");
       break;
     case SWC1:
-      Format(instr, "swc1   'rt, 'imm16s('fs)");
+      Format(instr, "swc1   'ft, 'imm16s('rs)");
       break;
     case SDC1:
-      Format(instr, "sdc1   'rt, 'imm16s('fs)");
+      Format(instr, "sdc1   'ft, 'imm16s('rs)");
       break;
     default:
       UNREACHABLE();
@@ -675,7 +912,7 @@
 int Decoder::InstructionDecode(byte_* instr_ptr) {
   Instruction* instr = Instruction::At(instr_ptr);
   // Print raw instruction bytes.
-  out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
                                        "%08x       ",
                                        instr->InstructionBits());
   switch (instr->InstructionType()) {
@@ -695,11 +932,11 @@
       UNSUPPORTED_MIPS();
     }
   }
-  return Instruction::kInstructionSize;
+  return Instruction::kInstrSize;
 }
 
 
-} }  // namespace assembler::mips
+} }  // namespace v8::internal
 
 
 
@@ -707,13 +944,11 @@
 
 namespace disasm {
 
-namespace v8i = v8::internal;
-
+using v8::internal::byte_;
 
 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();
+  v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
+  return tmp_buffer_.start();
 }
 
 
@@ -723,12 +958,12 @@
 
 
 const char* NameConverter::NameOfCPURegister(int reg) const {
-  return assembler::mips::Registers::Name(reg);
+  return v8::internal::Registers::Name(reg);
 }
 
 
 const char* NameConverter::NameOfXMMRegister(int reg) const {
-  return assembler::mips::FPURegister::Name(reg);
+  return v8::internal::FPURegisters::Name(reg);
 }
 
 
@@ -756,13 +991,13 @@
 
 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
                                     byte_* instruction) {
-  assembler::mips::Decoder d(converter_, buffer);
+  v8::internal::Decoder d(converter_, buffer);
   return d.InstructionDecode(instruction);
 }
 
 
+// The MIPS assembler does not currently use constant pools.
 int Disassembler::ConstantPoolSizeAt(byte_* instruction) {
-  UNIMPLEMENTED_MIPS();
   return -1;
 }
 
@@ -780,6 +1015,7 @@
   }
 }
 
+
 #undef UNSUPPORTED
 
 }  // namespace disasm
diff --git a/src/mips/frames-mips.cc b/src/mips/frames-mips.cc
index d630562..e2e0c91 100644
--- a/src/mips/frames-mips.cc
+++ b/src/mips/frames-mips.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -37,57 +37,9 @@
 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());
-}
-
-
 Address ExitFrame::ComputeStackPointer(Address fp) {
-  Address sp = fp + ExitFrameConstants::kSPDisplacement;
-  const int offset = ExitFrameConstants::kCodeOffset;
-  Object* code = Memory::Object_at(fp + offset);
-  bool is_debug_exit = code->IsSmi();
-  if (is_debug_exit) {
-    sp -= kNumJSCallerSaved * kPointerSize;
-  }
-  return sp;
-}
-
-
-void ExitFrame::Iterate(ObjectVisitor* v) const {
-  // Do nothing
-}
-
-
-int JavaScriptFrame::GetProvidedParametersCount() const {
-  return ComputeParametersCount();
-}
-
-
-Address JavaScriptFrame::GetCallerStackPointer() const {
   UNIMPLEMENTED_MIPS();
-  return static_cast<Address>(NULL);  // UNIMPLEMENTED RETURN
-}
-
-
-Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
-  UNIMPLEMENTED_MIPS();
-  return static_cast<Address>(NULL);  // UNIMPLEMENTED RETURN
-}
-
-
-Address InternalFrame::GetCallerStackPointer() const {
-  return fp() + StandardFrameConstants::kCallerSPOffset;
+  return fp;
 }
 
 
diff --git a/src/mips/frames-mips.h b/src/mips/frames-mips.h
index 06e9979..6441470 100644
--- a/src/mips/frames-mips.h
+++ b/src/mips/frames-mips.h
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -40,16 +40,17 @@
 static const int kNumRegs = 32;
 
 static const RegList kJSCallerSaved =
+  1 << 2 |  // v0
   1 << 4 |  // a0
   1 << 5 |  // a1
   1 << 6 |  // a2
   1 << 7;   // a3
 
-static const int kNumJSCallerSaved = 4;
+static const int kNumJSCallerSaved = 5;
 
 
 // Return the code of the n-th caller-saved register available to JavaScript
-// e.g. JSCallerSavedReg(0) returns r0.code() == 0.
+// e.g. JSCallerSavedReg(0) returns a0.code() == 4.
 int JSCallerSavedCode(int n);
 
 
@@ -64,6 +65,18 @@
 static const int kNumCalleeSaved = 11;
 
 
+// Number of registers for which space is reserved in safepoints. Must be a
+// multiple of 8.
+// TODO(mips): Only 8 registers may actually be sufficient. Revisit.
+static const int kNumSafepointRegisters = 16;
+
+// Define the list of registers actually saved at safepoints.
+// Note that the number of saved registers may be smaller than the reserved
+// space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters.
+static const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved;
+static const int kNumSafepointSavedRegisters =
+    kNumJSCallerSaved + kNumCalleeSaved;
+
 typedef Object* JSCallerSavedBuffer[kNumJSCallerSaved];
 
 
@@ -88,15 +101,14 @@
 
 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;
   // Must be the same as kDebugMarkOffset. Alias introduced when upgrading.
   static const int kCodeOffset = -1 * kPointerSize;
+  static const int kSPOffset = -1 * kPointerSize;
 
-  static const int kSavedRegistersOffset = 0 * kPointerSize;
+  // TODO(mips): Use a patched sp value on the stack instead.
+  // A marker of 0 indicates that double registers are saved.
+  static const int kMarkerOffset = -2 * kPointerSize;
 
   // The caller fields are below the frame pointer on the stack.
   static const int kCallerFPOffset = +0 * kPointerSize;
@@ -126,6 +138,8 @@
   static const int kCArgsSlotsSize = 4 * kPointerSize;
   // JS argument slots size.
   static const int kJSArgsSlotsSize = 0 * kPointerSize;
+  // Assembly builtins argument slots size.
+  static const int kBArgsSlotsSize = 0 * kPointerSize;
 };
 
 
@@ -159,6 +173,7 @@
   return Memory::Object_at(fp() + offset);
 }
 
+
 } }  // namespace v8::internal
 
 #endif
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 17ee531..87507ff 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -29,18 +29,55 @@
 
 #if defined(V8_TARGET_ARCH_MIPS)
 
+// Note on Mips implementation:
+//
+// The result_register() for mips is the 'v0' register, which is defined
+// by the ABI to contain function return values. However, the first
+// parameter to a function is defined to be 'a0'. So there are many
+// places where we have to move a previous result in v0 to a0 for the
+// next call: mov(a0, v0). This is not needed on the other architectures.
+
+#include "code-stubs.h"
 #include "codegen-inl.h"
 #include "compiler.h"
 #include "debug.h"
 #include "full-codegen.h"
 #include "parser.h"
+#include "scopes.h"
+#include "stub-cache.h"
+
+#include "mips/code-stubs-mips.h"
 
 namespace v8 {
 namespace internal {
 
 #define __ ACCESS_MASM(masm_)
 
-void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
+// Generate code for a JS function.  On entry to the function the receiver
+// and arguments have been pushed on the stack left to right.  The actual
+// argument count matches the formal parameter count expected by the
+// function.
+//
+// The live registers are:
+//   o a1: the JS function object being called (ie, ourselves)
+//   o cp: our context
+//   o fp: our caller's frame pointer
+//   o sp: stack pointer
+//   o ra: return address
+//
+// The function builds a JS frame.  Please see JavaScriptFrameConstants in
+// frames-mips.h for its layout.
+void FullCodeGenerator::Generate(CompilationInfo* info) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::ClearAccumulator() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) {
   UNIMPLEMENTED_MIPS();
 }
 
@@ -50,47 +87,165 @@
 }
 
 
-void FullCodeGenerator::Apply(Expression::Context context, Register reg) {
+void FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
   UNIMPLEMENTED_MIPS();
 }
 
 
-void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) {
-  UNIMPLEMENTED_MIPS();
-}
-
-void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) {
+void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const {
   UNIMPLEMENTED_MIPS();
 }
 
 
-void FullCodeGenerator::ApplyTOS(Expression::Context context) {
+void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
   UNIMPLEMENTED_MIPS();
 }
 
 
-void FullCodeGenerator::DropAndApply(int count,
-                                     Expression::Context context,
-                                     Register reg) {
+void FullCodeGenerator::TestContext::Plug(Slot* slot) const {
   UNIMPLEMENTED_MIPS();
 }
 
 
-void FullCodeGenerator::Apply(Expression::Context context,
-                              Label* materialize_true,
-                              Label* materialize_false) {
+void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
   UNIMPLEMENTED_MIPS();
 }
 
 
-void FullCodeGenerator::DoTest(Expression::Context context) {
+void FullCodeGenerator::AccumulatorValueContext::Plug(
+    Heap::RootListIndex index) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::StackValueContext::Plug(
+    Heap::RootListIndex index) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::AccumulatorValueContext::Plug(
+    Handle<Object> lit) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EffectContext::DropAndPlug(int count,
+                                                   Register reg) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
+    int count,
+    Register reg) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
+                                                       Register reg) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::TestContext::DropAndPlug(int count,
+                                                 Register reg) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
+                                            Label* materialize_false) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::AccumulatorValueContext::Plug(
+    Label* materialize_true,
+    Label* materialize_false) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::StackValueContext::Plug(
+    Label* materialize_true,
+    Label* materialize_false) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
+                                          Label* materialize_false) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EffectContext::Plug(bool flag) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::TestContext::Plug(bool flag) const {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::DoTest(Label* if_true,
+                               Label* if_false,
+                               Label* fall_through) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// Original prototype for mips, needs arch-indep change. Leave out for now.
+// void FullCodeGenerator::Split(Condition cc,
+//                               Register lhs,
+//                               const Operand&  rhs,
+//                               Label* if_true,
+//                               Label* if_false,
+//                               Label* fall_through) {
+void FullCodeGenerator::Split(Condition cc,
+                              Label* if_true,
+                              Label* if_false,
+                              Label* fall_through) {
   UNIMPLEMENTED_MIPS();
 }
 
 
 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
   UNIMPLEMENTED_MIPS();
-  return MemOperand(zero_reg, 0);   // UNIMPLEMENTED RETURN
+  return MemOperand(zero_reg, 0);
 }
 
 
@@ -99,6 +254,14 @@
 }
 
 
+void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
+                                                     bool should_normalize,
+                                                     Label* if_true,
+                                                     Label* if_false) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void FullCodeGenerator::Move(Slot* dst,
                              Register src,
                              Register scratch1,
@@ -107,6 +270,13 @@
 }
 
 
+void FullCodeGenerator::EmitDeclaration(Variable* variable,
+                                        Variable::Mode mode,
+                                        FunctionLiteral* function) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
   UNIMPLEMENTED_MIPS();
 }
@@ -117,7 +287,18 @@
 }
 
 
-void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
+void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
+                                       bool pretenure) {
   UNIMPLEMENTED_MIPS();
 }
 
@@ -127,8 +308,32 @@
 }
 
 
-void FullCodeGenerator::EmitVariableLoad(Variable* var,
-                                         Expression::Context context) {
+MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
+    Slot* slot,
+    Label* slow) {
+  UNIMPLEMENTED_MIPS();
+  return MemOperand(zero_reg, 0);
+}
+
+
+void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
+    Slot* slot,
+    TypeofState typeof_state,
+    Label* slow,
+    Label* done) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
+    Slot* slot,
+    TypeofState typeof_state,
+    Label* slow) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitVariableLoad(Variable* var) {
   UNIMPLEMENTED_MIPS();
 }
 
@@ -163,14 +368,28 @@
 }
 
 
+void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
+                                              Token::Value op,
+                                              OverwriteMode mode,
+                                              Expression* left,
+                                              Expression* right) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void FullCodeGenerator::EmitBinaryOp(Token::Value op,
-                                     Expression::Context context) {
+                                     OverwriteMode mode) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
   UNIMPLEMENTED_MIPS();
 }
 
 
 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
-                                               Expression::Context context) {
+                                               Token::Value op) {
   UNIMPLEMENTED_MIPS();
 }
 
@@ -189,13 +408,21 @@
   UNIMPLEMENTED_MIPS();
 }
 
+
 void FullCodeGenerator::EmitCallWithIC(Call* expr,
-                                       Handle<Object> ignored,
+                                       Handle<Object> name,
                                        RelocInfo::Mode mode) {
   UNIMPLEMENTED_MIPS();
 }
 
 
+void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
+                                            Expression* key,
+                                            RelocInfo::Mode mode) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void FullCodeGenerator::EmitCallWithStub(Call* expr) {
   UNIMPLEMENTED_MIPS();
 }
@@ -211,6 +438,202 @@
 }
 
 
+void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
+    ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
   UNIMPLEMENTED_MIPS();
 }
@@ -226,25 +649,52 @@
 }
 
 
-void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
+void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
   UNIMPLEMENTED_MIPS();
 }
 
 
+bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
+                                          Expression* left,
+                                          Expression* right,
+                                          Label* if_true,
+                                          Label* if_false,
+                                          Label* fall_through) {
+  UNIMPLEMENTED_MIPS();
+  return false;
+}
+
+
 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   UNIMPLEMENTED_MIPS();
 }
 
 
+void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
   UNIMPLEMENTED_MIPS();
 }
 
 
-Register FullCodeGenerator::result_register() { return v0; }
+Register FullCodeGenerator::result_register() {
+  UNIMPLEMENTED_MIPS();
+  return v0;
+}
 
 
-Register FullCodeGenerator::context_register() { return cp; }
+Register FullCodeGenerator::context_register() {
+  UNIMPLEMENTED_MIPS();
+  return cp;
+}
+
+
+void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) {
+  UNIMPLEMENTED_MIPS();
+}
 
 
 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc
index e5c2ad8..fa8a7bb 100644
--- a/src/mips/ic-mips.cc
+++ b/src/mips/ic-mips.cc
@@ -32,6 +32,7 @@
 #if defined(V8_TARGET_ARCH_MIPS)
 
 #include "codegen-inl.h"
+#include "code-stubs.h"
 #include "ic-inl.h"
 #include "runtime.h"
 #include "stub-cache.h"
@@ -52,7 +53,7 @@
 }
 
 
-void LoadIC::GenerateStringLength(MacroAssembler* masm) {
+void LoadIC::GenerateStringLength(MacroAssembler* masm, bool support_wrappers) {
   UNIMPLEMENTED_MIPS();
 }
 
@@ -65,6 +66,12 @@
 // Defined in ic.cc.
 Object* CallIC_Miss(Arguments args);
 
+
+void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
   UNIMPLEMENTED_MIPS();
 }
@@ -74,51 +81,22 @@
   UNIMPLEMENTED_MIPS();
 }
 
-void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
+
+void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
   UNIMPLEMENTED_MIPS();
-    // Registers:
-    // a2: name
-    // ra: return address
-
-  // Get the receiver of the function from the stack.
-  __ lw(a3, MemOperand(sp, argc*kPointerSize));
-
-  __ EnterInternalFrame();
-
-  // Push the receiver and the name of the function.
-  __ MultiPush(a2.bit() | a3.bit());
-
-  // Call the entry.
-  __ li(a0, Operand(2));
-  __ li(a1, Operand(ExternalReference(IC_Utility(kCallIC_Miss))));
-
-  CEntryStub stub(1);
-  __ CallStub(&stub);
-
-  // Move result to r1 and leave the internal frame.
-  __ mov(a1, v0);
-  __ LeaveInternalFrame();
-
-  // Check if the receiver is a global object of some sort.
-  Label invoke, global;
-  __ lw(a2, MemOperand(sp, argc * kPointerSize));
-  __ andi(t0, a2, kSmiTagMask);
-  __ Branch(eq, &invoke, t0, Operand(zero_reg));
-  __ GetObjectType(a2, a3, a3);
-  __ Branch(eq, &global, a3, Operand(JS_GLOBAL_OBJECT_TYPE));
-  __ Branch(ne, &invoke, a3, Operand(JS_BUILTINS_OBJECT_TYPE));
-
-  // Patch the receiver on the stack.
-  __ bind(&global);
-  __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset));
-  __ sw(a2, MemOperand(sp, argc * kPointerSize));
-
-  // Invoke the function.
-  ParameterCount actual(argc);
-  __ bind(&invoke);
-  __ InvokeFunction(a1, actual, JUMP_FUNCTION);
 }
 
+
+void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 // Defined in ic.cc.
 Object* LoadIC_Miss(Arguments args);
 
@@ -137,19 +115,35 @@
 }
 
 
-void LoadIC::ClearInlinedVersion(Address address) {}
 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
+  UNIMPLEMENTED_MIPS();
   return false;
 }
 
-void KeyedLoadIC::ClearInlinedVersion(Address address) {}
+
+bool LoadIC::PatchInlinedContextualLoad(Address address,
+                                        Object* map,
+                                        Object* cell,
+                                        bool is_dont_delete) {
+  UNIMPLEMENTED_MIPS();
+  return false;
+}
+
+
+bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) {
+  UNIMPLEMENTED_MIPS();
+  return false;
+}
+
+
 bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) {
+  UNIMPLEMENTED_MIPS();
   return false;
 }
 
-void KeyedStoreIC::ClearInlinedVersion(Address address) {}
-void KeyedStoreIC::RestoreInlinedVersion(Address address) {}
+
 bool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) {
+  UNIMPLEMENTED_MIPS();
   return false;
 }
 
@@ -162,6 +156,11 @@
 }
 
 
+void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
   UNIMPLEMENTED_MIPS();
 }
@@ -172,7 +171,14 @@
 }
 
 
-void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
+                                              StrictModeFlag strict_mode) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
+                                   StrictModeFlag strict_mode) {
   UNIMPLEMENTED_MIPS();
 }
 
@@ -187,7 +193,8 @@
 }
 
 
-void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
+void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
+                                  StrictModeFlag strict_mode) {
   UNIMPLEMENTED_MIPS();
 }
 
@@ -201,8 +208,37 @@
   UNIMPLEMENTED_MIPS();
 }
 
+
+void StoreIC::GenerateNormal(MacroAssembler* masm) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void StoreIC::GenerateGlobalProxy(MacroAssembler* masm,
+                                  StrictModeFlag strict_mode) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 #undef __
 
+
+Condition CompareIC::ComputeCondition(Token::Value op) {
+  UNIMPLEMENTED_MIPS();
+  return kNoCondition;
+}
+
+
+void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void PatchInlinedSmiCode(Address address) {
+  // Currently there is no smi inlining in the MIPS full code generator.
+}
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_TARGET_ARCH_MIPS
diff --git a/src/mips/jump-target-mips.cc b/src/mips/jump-target-mips.cc
index 408f75e..bd6d60b 100644
--- a/src/mips/jump-target-mips.cc
+++ b/src/mips/jump-target-mips.cc
@@ -43,41 +43,19 @@
 
 #define __ ACCESS_MASM(cgen()->masm())
 
+// BRANCH_ARGS_CHECK checks that conditional jump arguments are correct.
+#define BRANCH_ARGS_CHECK(cond, rs, rt) ASSERT(                                \
+    (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) ||          \
+    (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg))))
+
+
 void JumpTarget::DoJump() {
-  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 already a frame expectation at the target.
-    ASSERT(direction_ == BIDIRECTIONAL);
-    cgen()->frame()->MergeTo(entry_frame_);
-    cgen()->DeleteFrame();
-  } else {
-    // Use the current frame as the expected one at the target if necessary.
-    if (entry_frame_ == NULL) {
-      entry_frame_ = cgen()->frame();
-      RegisterFile empty;
-      cgen()->SetFrame(NULL, &empty);
-    } else {
-      cgen()->frame()->MergeTo(entry_frame_);
-      cgen()->DeleteFrame();
-    }
-
-    // The predicate is_linked() should be made true.  Its implementation
-    // detects the presence of a frame pointer in the reaching_frames_ list.
-    if (!is_linked()) {
-      reaching_frames_.Add(NULL);
-      ASSERT(is_linked());
-    }
-  }
-  __ b(&entry_label_);
-  __ nop();   // Branch delay slot nop.
+  UNIMPLEMENTED_MIPS();
 }
 
-
+// Original prototype for mips, needs arch-indep change. Leave out for now.
+// void JumpTarget::DoBranch(Condition cc, Hint ignored,
+//     Register src1, const Operand& src2) {
 void JumpTarget::DoBranch(Condition cc, Hint ignored) {
   UNIMPLEMENTED_MIPS();
 }
@@ -89,85 +67,12 @@
 
 
 void JumpTarget::DoBind() {
-  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 (cgen()->has_valid_frame()) {
-    // If there is a current frame we can use it on the fall through.
-    if (entry_frame_ == NULL) {
-      entry_frame_ = new VirtualFrame(cgen()->frame());
-    } else {
-      ASSERT(cgen()->frame()->Equals(entry_frame_));
-    }
-  } else {
-    // If there is no current frame we must have an entry frame which we can
-    // copy.
-    ASSERT(entry_frame_ != NULL);
-    RegisterFile empty;
-    cgen()->SetFrame(new VirtualFrame(entry_frame_), &empty);
-  }
-
-  // The predicate is_linked() should be made false.  Its implementation
-  // detects the presence (or absence) of frame pointers in the
-  // reaching_frames_ list.  If we inserted a bogus frame to make
-  // is_linked() true, remove it now.
-  if (is_linked()) {
-    reaching_frames_.Clear();
-  }
-
-  __ bind(&entry_label_);
-}
-
-
-void BreakTarget::Jump() {
-  // On ARM we do not currently emit merge code for jumps, so we need to do
-  // it explicitly here.  The only merging necessary is to drop extra
-  // statement state from the stack.
-  ASSERT(cgen()->has_valid_frame());
-  int count = cgen()->frame()->height() - expected_height_;
-  cgen()->frame()->Drop(count);
-  DoJump();
-}
-
-
-void BreakTarget::Jump(Result* arg) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void BreakTarget::Bind() {
-#ifdef DEBUG
-  // 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()) {
-    int count = cgen()->frame()->height() - expected_height_;
-    // On ARM we do not currently emit merge code at binding sites, so we need
-    // to do it explicitly here.  The only merging necessary is to drop extra
-    // statement state from the stack.
-    cgen()->frame()->Drop(count);
-  }
-
-  DoBind();
-}
-
-
-void BreakTarget::Bind(Result* arg) {
   UNIMPLEMENTED_MIPS();
 }
 
 
 #undef __
+#undef BRANCH_ARGS_CHECK
 
 
 } }  // namespace v8::internal
diff --git a/src/mips/fast-codegen-mips.cc b/src/mips/lithium-codegen-mips.h
similarity index 63%
rename from src/mips/fast-codegen-mips.cc
rename to src/mips/lithium-codegen-mips.h
index 186f9fa..345d912 100644
--- a/src/mips/fast-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.h
@@ -25,53 +25,41 @@
 // (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"
+#ifndef V8_MIPS_LITHIUM_CODEGEN_MIPS_H_
+#define V8_MIPS_LITHIUM_CODEGEN_MIPS_H_
 
-#if defined(V8_TARGET_ARCH_MIPS)
+#include "mips/lithium-mips.h"
 
-#include "codegen-inl.h"
-#include "fast-codegen.h"
+#include "deoptimizer.h"
+#include "safepoint-table.h"
+#include "scopes.h"
+
+// Note: this file was taken from the X64 version. ARM has a partially working
+// lithium implementation, but for now it is not ported to mips.
 
 namespace v8 {
 namespace internal {
 
-#define __ ACCESS_MASM(masm_)
+// Forward declarations.
+class LDeferredCode;
 
-Register FastCodeGenerator::accumulator0() { return no_reg; }
-Register FastCodeGenerator::accumulator1() { return no_reg; }
-Register FastCodeGenerator::scratch0() { return no_reg; }
-Register FastCodeGenerator::scratch1() { return no_reg; }
-Register FastCodeGenerator::receiver_reg() { return no_reg; }
-Register FastCodeGenerator::context_reg() { return no_reg; }
+class LCodeGen BASE_EMBEDDED {
+ public:
+  LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info) { }
 
+  // Try to generate code for the entire chunk, but it may fail if the
+  // chunk contains constructs we cannot handle. Returns true if the
+  // code generation attempt succeeded.
+  bool GenerateCode() {
+    UNIMPLEMENTED();
+    return false;
+  }
 
-void FastCodeGenerator::Generate(CompilationInfo* info) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void FastCodeGenerator::EmitThisPropertyStore(Handle<String> name) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void FastCodeGenerator::EmitGlobalVariableLoad(Handle<Object> name) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void FastCodeGenerator::EmitThisPropertyLoad(Handle<String> name) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void FastCodeGenerator::EmitBitOr() {
-  UNIMPLEMENTED_MIPS();
-}
-
-#undef __
-
+  // Finish the code by setting stack height, safepoint, and bailout
+  // information on it.
+  void FinishCode(Handle<Code> code) { UNIMPLEMENTED(); }
+};
 
 } }  // namespace v8::internal
 
-#endif  // V8_TARGET_ARCH_MIPS
+#endif  // V8_MIPS_LITHIUM_CODEGEN_MIPS_H_
diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h
new file mode 100644
index 0000000..e11dfab
--- /dev/null
+++ b/src/mips/lithium-mips.h
@@ -0,0 +1,304 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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_MIPS_LITHIUM_MIPS_H_
+#define V8_MIPS_LITHIUM_MIPS_H_
+
+#include "hydrogen.h"
+#include "lithium-allocator.h"
+#include "lithium.h"
+#include "safepoint-table.h"
+
+// Note: this file was taken from the X64 version. ARM has a partially working
+// lithium implementation, but for now it is not ported to mips.
+
+namespace v8 {
+namespace internal {
+
+// Forward declarations.
+class LCodeGen;
+class LEnvironment;
+class Translation;
+
+class LInstruction: public ZoneObject {
+ public:
+  LInstruction() { }
+  virtual ~LInstruction() { }
+
+  // Predicates should be generated by macro as in lithium-ia32.h.
+  virtual bool IsLabel() const {
+    UNIMPLEMENTED();
+    return false;
+  }
+  virtual bool IsOsrEntry() const {
+    UNIMPLEMENTED();
+    return false;
+  }
+
+  LPointerMap* pointer_map() const {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  bool HasPointerMap() const {
+    UNIMPLEMENTED();
+    return false;
+  }
+
+  void set_environment(LEnvironment* env) { UNIMPLEMENTED(); }
+
+  LEnvironment* environment() const {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  bool HasEnvironment() const {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  virtual void PrintTo(StringStream* stream) const { UNIMPLEMENTED(); }
+
+  virtual bool IsControl() const {
+    UNIMPLEMENTED();
+    return false;
+  }
+
+  void MarkAsCall() { UNIMPLEMENTED(); }
+  void MarkAsSaveDoubles() { UNIMPLEMENTED(); }
+
+  // Interface to the register allocator and iterators.
+  bool IsMarkedAsCall() const {
+    UNIMPLEMENTED();
+    return false;
+  }
+
+  bool IsMarkedAsSaveDoubles() const {
+    UNIMPLEMENTED();
+    return false;
+  }
+
+  virtual bool HasResult() const {
+    UNIMPLEMENTED();
+    return false;
+  }
+
+  virtual LOperand* result() {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  virtual int InputCount() {
+    UNIMPLEMENTED();
+    return 0;
+  }
+
+  virtual LOperand* InputAt(int i) {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  virtual int TempCount() {
+    UNIMPLEMENTED();
+    return 0;
+  }
+
+  virtual LOperand* TempAt(int i) {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  LOperand* FirstInput() {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  LOperand* Output() {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+#ifdef DEBUG
+  void VerifyCall() { UNIMPLEMENTED(); }
+#endif
+};
+
+
+class LGap: public LInstruction {
+ public:
+  explicit LGap(HBasicBlock* block) { }
+
+  HBasicBlock* block() const {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  enum InnerPosition {
+    BEFORE,
+    START,
+    END,
+    AFTER,
+    FIRST_INNER_POSITION = BEFORE,
+    LAST_INNER_POSITION = AFTER
+  };
+
+  LParallelMove* GetOrCreateParallelMove(InnerPosition pos) {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  LParallelMove* GetParallelMove(InnerPosition pos)  {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+};
+
+
+class LLabel: public LGap {
+ public:
+  explicit LLabel(HBasicBlock* block) : LGap(block) { }
+};
+
+
+class LOsrEntry: public LInstruction {
+ public:
+  // Function could be generated by a macro as in lithium-ia32.h.
+  static LOsrEntry* cast(LInstruction* instr) {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  LOperand** SpilledRegisterArray() {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+  LOperand** SpilledDoubleRegisterArray() {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  void MarkSpilledRegister(int allocation_index, LOperand* spill_operand) {
+    UNIMPLEMENTED();
+  }
+  void MarkSpilledDoubleRegister(int allocation_index,
+                                 LOperand* spill_operand) {
+    UNIMPLEMENTED();
+  }
+};
+
+
+class LChunk: public ZoneObject {
+ public:
+  explicit LChunk(CompilationInfo* info, HGraph* graph) { }
+
+  HGraph* graph() const {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  CompilationInfo* info() const { return NULL; }
+
+  const ZoneList<LPointerMap*>* pointer_maps() const {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  LOperand* GetNextSpillSlot(bool double_slot) {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  LConstantOperand* DefineConstantOperand(HConstant* constant) {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  LLabel* GetLabel(int block_id) const {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  const ZoneList<LInstruction*>* instructions() const {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  int GetParameterStackSlot(int index) const {
+    UNIMPLEMENTED();
+    return 0;
+  }
+
+  void AddGapMove(int index, LOperand* from, LOperand* to) { UNIMPLEMENTED(); }
+
+  LGap* GetGapAt(int index) const {
+    UNIMPLEMENTED();
+    return NULL;
+  }
+
+  bool IsGapAt(int index) const {
+    UNIMPLEMENTED();
+    return false;
+  }
+
+  int NearestGapPos(int index) const {
+    UNIMPLEMENTED();
+    return 0;
+  }
+
+  void MarkEmptyBlocks() { UNIMPLEMENTED(); }
+
+#ifdef DEBUG
+  void Verify() { UNIMPLEMENTED(); }
+#endif
+};
+
+
+class LChunkBuilder BASE_EMBEDDED {
+ public:
+  LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator) { }
+
+  // Build the sequence for the graph.
+  LChunk* Build() {
+    UNIMPLEMENTED();
+    return NULL;
+  };
+
+  // Declare methods that deal with the individual node types.
+#define DECLARE_DO(type) LInstruction* Do##type(H##type* node) { \
+    UNIMPLEMENTED(); \
+    return NULL; \
+  }
+  HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
+#undef DECLARE_DO
+
+  DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_MIPS_LITHIUM_MIPS_H_
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index e096028..bd4ab48 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -25,7 +25,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-
+#include <limits.h>  // For LONG_MIN, LONG_MAX
 
 #include "v8.h"
 
@@ -41,68 +41,90 @@
 
 MacroAssembler::MacroAssembler(void* buffer, int size)
     : Assembler(buffer, size),
-      unresolved_(0),
       generating_stub_(false),
       allow_stub_calls_(true),
-      code_object_(Heap::undefined_value()) {
+      code_object_(HEAP->undefined_value()) {
 }
 
 
+// Arguments macros
+#define COND_TYPED_ARGS Condition cond, Register r1, const Operand& r2
+#define COND_ARGS cond, r1, r2
 
-void MacroAssembler::Jump(Register target, Condition cond,
-                          Register r1, const Operand& r2) {
-  Jump(Operand(target), cond, r1, r2);
+#define REGISTER_TARGET_BODY(Name) \
+void MacroAssembler::Name(Register target, \
+                          BranchDelaySlot bd) { \
+  Name(Operand(target), bd); \
+} \
+void MacroAssembler::Name(Register target, COND_TYPED_ARGS, \
+                          BranchDelaySlot bd) { \
+  Name(Operand(target), COND_ARGS, bd); \
 }
 
 
-void MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode,
-                          Condition cond, Register r1, const Operand& r2) {
-  Jump(Operand(target, rmode), cond, r1, r2);
+#define INT_PTR_TARGET_BODY(Name) \
+void MacroAssembler::Name(intptr_t target, RelocInfo::Mode rmode, \
+                          BranchDelaySlot bd) { \
+  Name(Operand(target, rmode), bd); \
+} \
+void MacroAssembler::Name(intptr_t target, \
+                          RelocInfo::Mode rmode, \
+                          COND_TYPED_ARGS, \
+                          BranchDelaySlot bd) { \
+  Name(Operand(target, rmode), COND_ARGS, bd); \
 }
 
 
-void MacroAssembler::Jump(byte* target, RelocInfo::Mode rmode,
-                          Condition cond, Register r1, const Operand& r2) {
-  ASSERT(!RelocInfo::IsCodeTarget(rmode));
-  Jump(reinterpret_cast<intptr_t>(target), rmode, cond, r1, r2);
+#define BYTE_PTR_TARGET_BODY(Name) \
+void MacroAssembler::Name(byte* target, RelocInfo::Mode rmode, \
+                          BranchDelaySlot bd) { \
+  Name(reinterpret_cast<intptr_t>(target), rmode, bd); \
+} \
+void MacroAssembler::Name(byte* target, \
+                          RelocInfo::Mode rmode, \
+                          COND_TYPED_ARGS, \
+                          BranchDelaySlot bd) { \
+  Name(reinterpret_cast<intptr_t>(target), rmode, COND_ARGS, bd); \
 }
 
 
-void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
-                          Condition cond, Register r1, const Operand& r2) {
-  ASSERT(RelocInfo::IsCodeTarget(rmode));
-  Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
+#define CODE_TARGET_BODY(Name) \
+void MacroAssembler::Name(Handle<Code> target, RelocInfo::Mode rmode, \
+                          BranchDelaySlot bd) { \
+  Name(reinterpret_cast<intptr_t>(target.location()), rmode, bd); \
+} \
+void MacroAssembler::Name(Handle<Code> target, \
+                          RelocInfo::Mode rmode, \
+                          COND_TYPED_ARGS, \
+                          BranchDelaySlot bd) { \
+  Name(reinterpret_cast<intptr_t>(target.location()), rmode, COND_ARGS, bd); \
 }
 
 
-void MacroAssembler::Call(Register target,
-                          Condition cond, Register r1, const Operand& r2) {
-  Call(Operand(target), cond, r1, r2);
+REGISTER_TARGET_BODY(Jump)
+REGISTER_TARGET_BODY(Call)
+INT_PTR_TARGET_BODY(Jump)
+INT_PTR_TARGET_BODY(Call)
+BYTE_PTR_TARGET_BODY(Jump)
+BYTE_PTR_TARGET_BODY(Call)
+CODE_TARGET_BODY(Jump)
+CODE_TARGET_BODY(Call)
+
+#undef COND_TYPED_ARGS
+#undef COND_ARGS
+#undef REGISTER_TARGET_BODY
+#undef BYTE_PTR_TARGET_BODY
+#undef CODE_TARGET_BODY
+
+
+void MacroAssembler::Ret(BranchDelaySlot bd) {
+  Jump(Operand(ra), bd);
 }
 
 
-void MacroAssembler::Call(intptr_t target, RelocInfo::Mode rmode,
-                          Condition cond, Register r1, const Operand& r2) {
-  Call(Operand(target, rmode), cond, r1, r2);
-}
-
-
-void MacroAssembler::Call(byte* target, RelocInfo::Mode rmode,
-                          Condition cond, Register r1, const Operand& r2) {
-  ASSERT(!RelocInfo::IsCodeTarget(rmode));
-  Call(reinterpret_cast<intptr_t>(target), rmode, cond, r1, r2);
-}
-
-
-void MacroAssembler::Call(Handle<Code> code, RelocInfo::Mode rmode,
-                          Condition cond, Register r1, const Operand& r2) {
-  ASSERT(RelocInfo::IsCodeTarget(rmode));
-  Call(reinterpret_cast<intptr_t>(code.location()), rmode, cond, r1, r2);
-}
-
-
-void MacroAssembler::Ret(Condition cond, Register r1, const Operand& r2) {
-  Jump(Operand(ra), cond, r1, r2);
+void MacroAssembler::Ret(Condition cond, Register r1, const Operand& r2,
+    BranchDelaySlot bd) {
+  Jump(Operand(ra), cond, r1, r2, bd);
 }
 
 
@@ -111,45 +133,226 @@
   lw(destination, MemOperand(s6, index << kPointerSizeLog2));
 }
 
+
 void MacroAssembler::LoadRoot(Register destination,
                               Heap::RootListIndex index,
                               Condition cond,
                               Register src1, const Operand& src2) {
-  Branch(NegateCondition(cond), 2, src1, src2);
+  Branch(2, NegateCondition(cond), src1, src2);
   lw(destination, MemOperand(s6, index << kPointerSizeLog2));
 }
 
 
-void MacroAssembler::RecordWrite(Register object, Register offset,
+void MacroAssembler::StoreRoot(Register source,
+                               Heap::RootListIndex index) {
+  sw(source, MemOperand(s6, index << kPointerSizeLog2));
+}
+
+
+void MacroAssembler::StoreRoot(Register source,
+                               Heap::RootListIndex index,
+                               Condition cond,
+                               Register src1, const Operand& src2) {
+  Branch(2, NegateCondition(cond), src1, src2);
+  sw(source, MemOperand(s6, index << kPointerSizeLog2));
+}
+
+
+void MacroAssembler::RecordWriteHelper(Register object,
+                                       Register address,
+                                       Register scratch) {
+  if (FLAG_debug_code) {
+    // Check that the object is not in new space.
+    Label not_in_new_space;
+    InNewSpace(object, scratch, ne, &not_in_new_space);
+    Abort("new-space object passed to RecordWriteHelper");
+    bind(&not_in_new_space);
+  }
+
+  // Calculate page address: Clear bits from 0 to kPageSizeBits.
+  if (mips32r2) {
+    Ins(object, zero_reg, 0, kPageSizeBits);
+  } else {
+    // The Ins macro is slow on r1, so use shifts instead.
+    srl(object, object, kPageSizeBits);
+    sll(object, object, kPageSizeBits);
+  }
+
+  // Calculate region number.
+  Ext(address, address, Page::kRegionSizeLog2,
+      kPageSizeBits - Page::kRegionSizeLog2);
+
+  // Mark region dirty.
+  lw(scratch, MemOperand(object, Page::kDirtyFlagOffset));
+  li(at, Operand(1));
+  sllv(at, at, address);
+  or_(scratch, scratch, at);
+  sw(scratch, MemOperand(object, Page::kDirtyFlagOffset));
+}
+
+
+void MacroAssembler::InNewSpace(Register object,
+                                Register scratch,
+                                Condition cc,
+                                Label* branch) {
+  ASSERT(cc == eq || cc == ne);
+  And(scratch, object, Operand(ExternalReference::new_space_mask(isolate())));
+  Branch(branch, cc, scratch,
+         Operand(ExternalReference::new_space_start(isolate())));
+}
+
+
+// Will clobber 4 registers: object, scratch0, scratch1, at. The
+// register 'object' contains a heap object pointer.  The heap object
+// tag is shifted away.
+void MacroAssembler::RecordWrite(Register object,
+                                 Operand offset,
+                                 Register scratch0,
+                                 Register scratch1) {
+  // The compiled code assumes that record write doesn't change the
+  // context register, so we check that none of the clobbered
+  // registers are cp.
+  ASSERT(!object.is(cp) && !scratch0.is(cp) && !scratch1.is(cp));
+
+  Label done;
+
+  // First, test that the object is not in the new space.  We cannot set
+  // region marks for new space pages.
+  InNewSpace(object, scratch0, eq, &done);
+
+  // Add offset into the object.
+  Addu(scratch0, object, offset);
+
+  // Record the actual write.
+  RecordWriteHelper(object, scratch0, scratch1);
+
+  bind(&done);
+
+  // Clobber all input registers when running with the debug-code flag
+  // turned on to provoke errors.
+  if (FLAG_debug_code) {
+    li(object, Operand(BitCast<int32_t>(kZapValue)));
+    li(scratch0, Operand(BitCast<int32_t>(kZapValue)));
+    li(scratch1, Operand(BitCast<int32_t>(kZapValue)));
+  }
+}
+
+
+// Will clobber 4 registers: object, address, scratch, ip.  The
+// register 'object' contains a heap object pointer.  The heap object
+// tag is shifted away.
+void MacroAssembler::RecordWrite(Register object,
+                                 Register address,
                                  Register scratch) {
-  UNIMPLEMENTED_MIPS();
+  // The compiled code assumes that record write doesn't change the
+  // context register, so we check that none of the clobbered
+  // registers are cp.
+  ASSERT(!object.is(cp) && !address.is(cp) && !scratch.is(cp));
+
+  Label done;
+
+  // First, test that the object is not in the new space.  We cannot set
+  // region marks for new space pages.
+  InNewSpace(object, scratch, eq, &done);
+
+  // Record the actual write.
+  RecordWriteHelper(object, address, scratch);
+
+  bind(&done);
+
+  // Clobber all input registers when running with the debug-code flag
+  // turned on to provoke errors.
+  if (FLAG_debug_code) {
+    li(object, Operand(BitCast<int32_t>(kZapValue)));
+    li(address, Operand(BitCast<int32_t>(kZapValue)));
+    li(scratch, Operand(BitCast<int32_t>(kZapValue)));
+  }
+}
+
+
+// -----------------------------------------------------------------------------
+// Allocation support
+
+
+void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
+                                            Register scratch,
+                                            Label* miss) {
+  Label same_contexts;
+
+  ASSERT(!holder_reg.is(scratch));
+  ASSERT(!holder_reg.is(at));
+  ASSERT(!scratch.is(at));
+
+  // Load current lexical context from the stack frame.
+  lw(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  // In debug mode, make sure the lexical context is set.
+#ifdef DEBUG
+  Check(ne, "we should not have an empty lexical context",
+      scratch, Operand(zero_reg));
+#endif
+
+  // Load the global context of the current context.
+  int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
+  lw(scratch, FieldMemOperand(scratch, offset));
+  lw(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).
+    Push(holder_reg);  // Temporarily save holder on the stack.
+    // Read the first word and compare to the global_context_map.
+    lw(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
+    LoadRoot(at, Heap::kGlobalContextMapRootIndex);
+    Check(eq, "JSGlobalObject::global_context should be a global context.",
+          holder_reg, Operand(at));
+    Pop(holder_reg);  // Restore holder.
+  }
+
+  // Check if both contexts are the same.
+  lw(at, FieldMemOperand(holder_reg, JSGlobalProxy::kContextOffset));
+  Branch(&same_contexts, eq, scratch, Operand(at));
+
+  // Check the context is a global context.
+  if (FLAG_debug_code) {
+    // TODO(119): Avoid push(holder_reg)/pop(holder_reg).
+    Push(holder_reg);  // Temporarily save holder on the stack.
+    mov(holder_reg, at);  // Move at to its holding place.
+    LoadRoot(at, Heap::kNullValueRootIndex);
+    Check(ne, "JSGlobalProxy::context() should not be null.",
+          holder_reg, Operand(at));
+
+    lw(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
+    LoadRoot(at, Heap::kGlobalContextMapRootIndex);
+    Check(eq, "JSGlobalObject::global_context should be a global context.",
+          holder_reg, Operand(at));
+    // Restore at is not needed. at is reloaded below.
+    Pop(holder_reg);  // Restore holder.
+    // Restore at to holder's context.
+    lw(at, 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;
+
+  lw(scratch, FieldMemOperand(scratch, token_offset));
+  lw(at, FieldMemOperand(at, token_offset));
+  Branch(miss, ne, scratch, Operand(at));
+
+  bind(&same_contexts);
 }
 
 
 // ---------------------------------------------------------------------------
 // Instruction macros
 
-void MacroAssembler::Add(Register rd, Register rs, const Operand& rt) {
-  if (rt.is_reg()) {
-    add(rd, rs, rt.rm());
-  } else {
-    if (is_int16(rt.imm32_) && !MustUseAt(rt.rmode_)) {
-      addi(rd, rs, rt.imm32_);
-    } else {
-      // li handles the relocation.
-      ASSERT(!rs.is(at));
-      li(at, rt);
-      add(rd, rs, at);
-    }
-  }
-}
-
-
 void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) {
   if (rt.is_reg()) {
     addu(rd, rs, rt.rm());
   } else {
-    if (is_int16(rt.imm32_) && !MustUseAt(rt.rmode_)) {
+    if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
       addiu(rd, rs, rt.imm32_);
     } else {
       // li handles the relocation.
@@ -161,6 +364,22 @@
 }
 
 
+void MacroAssembler::Subu(Register rd, Register rs, const Operand& rt) {
+  if (rt.is_reg()) {
+    subu(rd, rs, rt.rm());
+  } else {
+    if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
+      addiu(rd, rs, -rt.imm32_);  // No subiu instr, use addiu(x, y, -imm).
+    } else {
+      // li handles the relocation.
+      ASSERT(!rs.is(at));
+      li(at, rt);
+      subu(rd, rs, at);
+    }
+  }
+}
+
+
 void MacroAssembler::Mul(Register rd, Register rs, const Operand& rt) {
   if (rt.is_reg()) {
     mul(rd, rs, rt.rm());
@@ -225,7 +444,7 @@
   if (rt.is_reg()) {
     and_(rd, rs, rt.rm());
   } else {
-    if (is_int16(rt.imm32_) && !MustUseAt(rt.rmode_)) {
+    if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
       andi(rd, rs, rt.imm32_);
     } else {
       // li handles the relocation.
@@ -241,7 +460,7 @@
   if (rt.is_reg()) {
     or_(rd, rs, rt.rm());
   } else {
-    if (is_int16(rt.imm32_) && !MustUseAt(rt.rmode_)) {
+    if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
       ori(rd, rs, rt.imm32_);
     } else {
       // li handles the relocation.
@@ -257,7 +476,7 @@
   if (rt.is_reg()) {
     xor_(rd, rs, rt.rm());
   } else {
-    if (is_int16(rt.imm32_) && !MustUseAt(rt.rmode_)) {
+    if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
       xori(rd, rs, rt.imm32_);
     } else {
       // li handles the relocation.
@@ -285,7 +504,7 @@
   if (rt.is_reg()) {
     slt(rd, rs, rt.rm());
   } else {
-    if (is_int16(rt.imm32_) && !MustUseAt(rt.rmode_)) {
+    if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
       slti(rd, rs, rt.imm32_);
     } else {
       // li handles the relocation.
@@ -301,7 +520,7 @@
   if (rt.is_reg()) {
     sltu(rd, rs, rt.rm());
   } else {
-    if (is_int16(rt.imm32_) && !MustUseAt(rt.rmode_)) {
+    if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) {
       sltiu(rd, rs, rt.imm32_);
     } else {
       // li handles the relocation.
@@ -313,31 +532,51 @@
 }
 
 
-//------------Pseudo-instructions-------------
-
-void MacroAssembler::movn(Register rd, Register rt) {
-  addiu(at, zero_reg, -1);  // Fill at with ones.
-  xor_(rd, rt, at);
+void MacroAssembler::Ror(Register rd, Register rs, const Operand& rt) {
+  if (mips32r2) {
+    if (rt.is_reg()) {
+      rotrv(rd, rs, rt.rm());
+    } else {
+      rotr(rd, rs, rt.imm32_);
+    }
+  } else {
+    if (rt.is_reg()) {
+      subu(at, zero_reg, rt.rm());
+      sllv(at, rs, at);
+      srlv(rd, rs, rt.rm());
+      or_(rd, rd, at);
+    } else {
+      if (rt.imm32_ == 0) {
+        srl(rd, rs, 0);
+      } else {
+        srl(at, rs, rt.imm32_);
+        sll(rd, rs, (0x20 - rt.imm32_) & 0x1f);
+        or_(rd, rd, at);
+      }
+    }
+  }
 }
 
 
+//------------Pseudo-instructions-------------
+
 void MacroAssembler::li(Register rd, Operand j, bool gen2instr) {
   ASSERT(!j.is_reg());
-
-  if (!MustUseAt(j.rmode_) && !gen2instr) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
+  if (!MustUseReg(j.rmode_) && !gen2instr) {
     // Normal load of an immediate value which does not need Relocation Info.
     if (is_int16(j.imm32_)) {
       addiu(rd, zero_reg, j.imm32_);
-    } else if (!(j.imm32_ & HIMask)) {
+    } else if (!(j.imm32_ & kHiMask)) {
       ori(rd, zero_reg, j.imm32_);
-    } else if (!(j.imm32_ & LOMask)) {
-      lui(rd, (HIMask & j.imm32_) >> 16);
+    } else if (!(j.imm32_ & kImm16Mask)) {
+      lui(rd, (j.imm32_ & kHiMask) >> kLuiShift);
     } else {
-      lui(rd, (HIMask & j.imm32_) >> 16);
-      ori(rd, rd, (LOMask & j.imm32_));
+      lui(rd, (j.imm32_ & kHiMask) >> kLuiShift);
+      ori(rd, rd, (j.imm32_ & kImm16Mask));
     }
-  } else if (MustUseAt(j.rmode_) || gen2instr) {
-    if (MustUseAt(j.rmode_)) {
+  } else if (MustUseReg(j.rmode_) || gen2instr) {
+    if (MustUseReg(j.rmode_)) {
       RecordRelocInfo(j.rmode_, j.imm32_);
     }
     // We need always the same number of instructions as we may need to patch
@@ -345,15 +584,15 @@
     if (is_int16(j.imm32_)) {
       nop();
       addiu(rd, zero_reg, j.imm32_);
-    } else if (!(j.imm32_ & HIMask)) {
+    } else if (!(j.imm32_ & kHiMask)) {
       nop();
       ori(rd, zero_reg, j.imm32_);
-    } else if (!(j.imm32_ & LOMask)) {
+    } else if (!(j.imm32_ & kImm16Mask)) {
       nop();
-      lui(rd, (HIMask & j.imm32_) >> 16);
+      lui(rd, (j.imm32_ & kHiMask) >> kLuiShift);
     } else {
-      lui(rd, (HIMask & j.imm32_) >> 16);
-      ori(rd, rd, (LOMask & j.imm32_));
+      lui(rd, (j.imm32_ & kHiMask) >> kLuiShift);
+      ori(rd, rd, (j.imm32_ & kImm16Mask));
     }
   }
 }
@@ -417,230 +656,772 @@
 }
 
 
-// Emulated condtional branches do not emit a nop in the branch delay slot.
+void MacroAssembler::Ext(Register rt,
+                         Register rs,
+                         uint16_t pos,
+                         uint16_t size) {
+  ASSERT(pos < 32);
+  ASSERT(pos + size < 32);
 
-// Trashes the at register if no scratch register is provided.
-void MacroAssembler::Branch(Condition cond, int16_t offset, Register rs,
-                            const Operand& rt, Register scratch) {
+  if (mips32r2) {
+    ext_(rt, rs, pos, size);
+  } else {
+    // Move rs to rt and shift it left then right to get the
+    // desired bitfield on the right side and zeroes on the left.
+    sll(rt, rs, 32 - (pos + size));
+    srl(rt, rt, 32 - size);
+  }
+}
+
+
+void MacroAssembler::Ins(Register rt,
+                         Register rs,
+                         uint16_t pos,
+                         uint16_t size) {
+  ASSERT(pos < 32);
+  ASSERT(pos + size < 32);
+
+  if (mips32r2) {
+    ins_(rt, rs, pos, size);
+  } else {
+    ASSERT(!rt.is(t8) && !rs.is(t8));
+
+    srl(t8, rt, pos + size);
+    // The left chunk from rt that needs to
+    // be saved is on the right side of t8.
+    sll(at, t8, pos + size);
+    // The 'at' register now contains the left chunk on
+    // the left (proper position) and zeroes.
+    sll(t8, rt, 32 - pos);
+    // t8 now contains the right chunk on the left and zeroes.
+    srl(t8, t8, 32 - pos);
+    // t8 now contains the right chunk on
+    // the right (proper position) and zeroes.
+    or_(rt, at, t8);
+    // rt now contains the left and right chunks from the original rt
+    // in their proper position and zeroes in the middle.
+    sll(t8, rs, 32 - size);
+    // t8 now contains the chunk from rs on the left and zeroes.
+    srl(t8, t8, 32 - size - pos);
+    // t8 now contains the original chunk from rs in
+    // the middle (proper position).
+    or_(rt, rt, t8);
+    // rt now contains the result of the ins instruction in R2 mode.
+  }
+}
+
+
+void MacroAssembler::Cvt_d_uw(FPURegister fd, FPURegister fs) {
+  // Move the data from fs to t4.
+  mfc1(t4, fs);
+  return Cvt_d_uw(fd, t4);
+}
+
+
+void MacroAssembler::Cvt_d_uw(FPURegister fd, Register rs) {
+  // Convert rs to a FP value in fd (and fd + 1).
+  // We do this by converting rs minus the MSB to avoid sign conversion,
+  // then adding 2^31-1 and 1 to the result.
+
+  ASSERT(!fd.is(f20));
+  ASSERT(!rs.is(t9));
+  ASSERT(!rs.is(t8));
+
+  // Save rs's MSB to t8
+  And(t8, rs, 0x80000000);
+  // Remove rs's MSB.
+  And(t9, rs, 0x7FFFFFFF);
+  // Move t9 to fd
+  mtc1(t9, fd);
+
+  // Convert fd to a real FP value.
+  cvt_d_w(fd, fd);
+
+  Label conversion_done;
+
+  // If rs's MSB was 0, it's done.
+  // Otherwise we need to add that to the FP register.
+  Branch(&conversion_done, eq, t8, Operand(zero_reg));
+
+  // First load 2^31 - 1 into f20.
+  Or(t9, zero_reg, 0x7FFFFFFF);
+  mtc1(t9, f20);
+
+  // Convert it to FP and add it to fd.
+  cvt_d_w(f20, f20);
+  add_d(fd, fd, f20);
+  // Now add 1.
+  Or(t9, zero_reg, 1);
+  mtc1(t9, f20);
+
+  cvt_d_w(f20, f20);
+  add_d(fd, fd, f20);
+  bind(&conversion_done);
+}
+
+
+void MacroAssembler::Trunc_uw_d(FPURegister fd, FPURegister fs) {
+  Trunc_uw_d(fs, t4);
+  mtc1(t4, fd);
+}
+
+
+void MacroAssembler::Trunc_uw_d(FPURegister fd, Register rs) {
+  ASSERT(!fd.is(f22));
+  ASSERT(!rs.is(t6));
+
+  // Load 2^31 into f22.
+  Or(t6, zero_reg, 0x80000000);
+  Cvt_d_uw(f22, t6);
+
+  // Test if f22 > fd.
+  c(OLT, D, fd, f22);
+
+  Label simple_convert;
+  // If fd < 2^31 we can convert it normally.
+  bc1t(&simple_convert);
+
+  // First we subtract 2^31 from fd, then trunc it to rs
+  // and add 2^31 to rs.
+
+  sub_d(f22, fd, f22);
+  trunc_w_d(f22, f22);
+  mfc1(rs, f22);
+  or_(rs, rs, t6);
+
+  Label done;
+  Branch(&done);
+  // Simple conversion.
+  bind(&simple_convert);
+  trunc_w_d(f22, fd);
+  mfc1(rs, f22);
+
+  bind(&done);
+}
+
+
+// Tries to get a signed int32 out of a double precision floating point heap
+// number. Rounds towards 0. Branch to 'not_int32' if the double is out of the
+// 32bits signed integer range.
+// This method implementation differs from the ARM version for performance
+// reasons.
+void MacroAssembler::ConvertToInt32(Register source,
+                                    Register dest,
+                                    Register scratch,
+                                    Register scratch2,
+                                    FPURegister double_scratch,
+                                    Label *not_int32) {
+  Label right_exponent, done;
+  // Get exponent word (ENDIAN issues).
+  lw(scratch, FieldMemOperand(source, HeapNumber::kExponentOffset));
+  // Get exponent alone in scratch2.
+  And(scratch2, scratch, Operand(HeapNumber::kExponentMask));
+  // Load dest with zero.  We use this either for the final shift or
+  // for the answer.
+  mov(dest, zero_reg);
+  // Check whether the exponent matches a 32 bit signed int that is not a Smi.
+  // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased).  This is
+  // the exponent that we are fastest at and also the highest exponent we can
+  // handle here.
+  const uint32_t non_smi_exponent =
+      (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift;
+  // If we have a match of the int32-but-not-Smi exponent then skip some logic.
+  Branch(&right_exponent, eq, scratch2, Operand(non_smi_exponent));
+  // If the exponent is higher than that then go to not_int32 case.  This
+  // catches numbers that don't fit in a signed int32, infinities and NaNs.
+  Branch(not_int32, gt, scratch2, Operand(non_smi_exponent));
+
+  // We know the exponent is smaller than 30 (biased).  If it is less than
+  // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, ie
+  // it rounds to zero.
+  const uint32_t zero_exponent =
+      (HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift;
+  Subu(scratch2, scratch2, Operand(zero_exponent));
+  // Dest already has a Smi zero.
+  Branch(&done, lt, scratch2, Operand(zero_reg));
+  if (!Isolate::Current()->cpu_features()->IsSupported(FPU)) {
+    // We have a shifted exponent between 0 and 30 in scratch2.
+    srl(dest, scratch2, HeapNumber::kExponentShift);
+    // We now have the exponent in dest.  Subtract from 30 to get
+    // how much to shift down.
+    li(at, Operand(30));
+    subu(dest, at, dest);
+  }
+  bind(&right_exponent);
+  if (Isolate::Current()->cpu_features()->IsSupported(FPU)) {
+    CpuFeatures::Scope scope(FPU);
+    // MIPS FPU instructions implementing double precision to integer
+    // conversion using round to zero. Since the FP value was qualified
+    // above, the resulting integer should be a legal int32.
+    // The original 'Exponent' word is still in scratch.
+    lwc1(double_scratch, FieldMemOperand(source, HeapNumber::kMantissaOffset));
+    mtc1(scratch, FPURegister::from_code(double_scratch.code() + 1));
+    trunc_w_d(double_scratch, double_scratch);
+    mfc1(dest, double_scratch);
+  } else {
+    // On entry, dest has final downshift, scratch has original sign/exp/mant.
+    // Save sign bit in top bit of dest.
+    And(scratch2, scratch, Operand(0x80000000));
+    Or(dest, dest, Operand(scratch2));
+    // Put back the implicit 1, just above mantissa field.
+    Or(scratch, scratch, Operand(1 << HeapNumber::kExponentShift));
+
+    // Shift up the mantissa bits to take up the space the exponent used to
+    // take. We just orred in the implicit bit so that took care of one and
+    // we want to leave the sign bit 0 so we subtract 2 bits from the shift
+    // distance. But we want to clear the sign-bit so shift one more bit
+    // left, then shift right one bit.
+    const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2;
+    sll(scratch, scratch, shift_distance + 1);
+    srl(scratch, scratch, 1);
+
+    // Get the second half of the double. For some exponents we don't
+    // actually need this because the bits get shifted out again, but
+    // it's probably slower to test than just to do it.
+    lw(scratch2, FieldMemOperand(source, HeapNumber::kMantissaOffset));
+    // Extract the top 10 bits, and insert those bottom 10 bits of scratch.
+    // The width of the field here is the same as the shift amount above.
+    const int field_width = shift_distance;
+    Ext(scratch2, scratch2, 32-shift_distance, field_width);
+    Ins(scratch, scratch2, 0, field_width);
+    // Move down according to the exponent.
+    srlv(scratch, scratch, dest);
+    // Prepare the negative version of our integer.
+    subu(scratch2, zero_reg, scratch);
+    // Trick to check sign bit (msb) held in dest, count leading zero.
+    // 0 indicates negative, save negative version with conditional move.
+    clz(dest, dest);
+    movz(scratch, scratch2, dest);
+    mov(dest, scratch);
+  }
+  bind(&done);
+}
+
+
+// Emulated condtional branches do not emit a nop in the branch delay slot.
+//
+// BRANCH_ARGS_CHECK checks that conditional jump arguments are correct.
+#define BRANCH_ARGS_CHECK(cond, rs, rt) ASSERT(                                \
+    (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) ||          \
+    (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg))))
+
+
+void MacroAssembler::Branch(int16_t offset, BranchDelaySlot bdslot) {
+  b(offset);
+
+  // Emit a nop in the branch delay slot if required.
+  if (bdslot == PROTECT)
+    nop();
+}
+
+
+void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs,
+                            const Operand& rt,
+                            BranchDelaySlot bdslot) {
+  BRANCH_ARGS_CHECK(cond, rs, rt);
+  ASSERT(!rs.is(zero_reg));
   Register r2 = no_reg;
+  Register scratch = at;
+
   if (rt.is_reg()) {
     // We don't want any other register but scratch clobbered.
     ASSERT(!scratch.is(rs) && !scratch.is(rt.rm_));
     r2 = rt.rm_;
-  } else if (cond != cc_always) {
-    // We don't want any other register but scratch clobbered.
-    ASSERT(!scratch.is(rs));
-    r2 = scratch;
-    li(r2, rt);
-  }
-
-  switch (cond) {
-    case cc_always:
-      b(offset);
-      break;
-    case eq:
-      beq(rs, r2, offset);
-      break;
-    case ne:
-      bne(rs, r2, offset);
-      break;
-
+    switch (cond) {
+      case cc_always:
+        b(offset);
+        break;
+      case eq:
+        beq(rs, r2, offset);
+        break;
+      case ne:
+        bne(rs, r2, offset);
+        break;
       // Signed comparison
-    case greater:
-      slt(scratch, r2, rs);
-      bne(scratch, zero_reg, offset);
-      break;
-    case greater_equal:
-      slt(scratch, rs, r2);
-      beq(scratch, zero_reg, offset);
-      break;
-    case less:
-      slt(scratch, rs, r2);
-      bne(scratch, zero_reg, offset);
-      break;
-    case less_equal:
-      slt(scratch, r2, rs);
-      beq(scratch, zero_reg, offset);
-      break;
-
+      case greater:
+        if (r2.is(zero_reg)) {
+          bgtz(rs, offset);
+        } else {
+          slt(scratch, r2, rs);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case greater_equal:
+        if (r2.is(zero_reg)) {
+          bgez(rs, offset);
+        } else {
+          slt(scratch, rs, r2);
+          beq(scratch, zero_reg, offset);
+        }
+        break;
+      case less:
+        if (r2.is(zero_reg)) {
+          bltz(rs, offset);
+        } else {
+          slt(scratch, rs, r2);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case less_equal:
+        if (r2.is(zero_reg)) {
+          blez(rs, offset);
+        } else {
+          slt(scratch, r2, rs);
+          beq(scratch, zero_reg, offset);
+        }
+        break;
       // Unsigned comparison.
-    case Ugreater:
-      sltu(scratch, r2, rs);
-      bne(scratch, zero_reg, offset);
-      break;
-    case Ugreater_equal:
-      sltu(scratch, rs, r2);
-      beq(scratch, zero_reg, offset);
-      break;
-    case Uless:
-      sltu(scratch, rs, r2);
-      bne(scratch, zero_reg, offset);
-      break;
-    case Uless_equal:
-      sltu(scratch, r2, rs);
-      beq(scratch, zero_reg, offset);
-      break;
-
-    default:
-      UNREACHABLE();
+      case Ugreater:
+        if (r2.is(zero_reg)) {
+          bgtz(rs, offset);
+        } else {
+          sltu(scratch, r2, rs);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case Ugreater_equal:
+        if (r2.is(zero_reg)) {
+          bgez(rs, offset);
+        } else {
+          sltu(scratch, rs, r2);
+          beq(scratch, zero_reg, offset);
+        }
+        break;
+      case Uless:
+        if (r2.is(zero_reg)) {
+          b(offset);
+        } else {
+          sltu(scratch, rs, r2);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case Uless_equal:
+        if (r2.is(zero_reg)) {
+          b(offset);
+        } else {
+          sltu(scratch, r2, rs);
+          beq(scratch, zero_reg, offset);
+        }
+        break;
+      default:
+        UNREACHABLE();
+    }
+  } else {
+    // Be careful to always use shifted_branch_offset only just before the
+    // branch instruction, as the location will be remember for patching the
+    // target.
+    switch (cond) {
+      case cc_always:
+        b(offset);
+        break;
+      case eq:
+        // We don't want any other register but scratch clobbered.
+        ASSERT(!scratch.is(rs));
+        r2 = scratch;
+        li(r2, rt);
+        beq(rs, r2, offset);
+        break;
+      case ne:
+        // We don't want any other register but scratch clobbered.
+        ASSERT(!scratch.is(rs));
+        r2 = scratch;
+        li(r2, rt);
+        bne(rs, r2, offset);
+        break;
+      // Signed comparison
+      case greater:
+        if (rt.imm32_ == 0) {
+          bgtz(rs, offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          slt(scratch, r2, rs);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case greater_equal:
+        if (rt.imm32_ == 0) {
+          bgez(rs, offset);
+        } else if (is_int16(rt.imm32_)) {
+          slti(scratch, rs, rt.imm32_);
+          beq(scratch, zero_reg, offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          sltu(scratch, rs, r2);
+          beq(scratch, zero_reg, offset);
+        }
+        break;
+      case less:
+        if (rt.imm32_ == 0) {
+          bltz(rs, offset);
+        } else if (is_int16(rt.imm32_)) {
+          slti(scratch, rs, rt.imm32_);
+          bne(scratch, zero_reg, offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          slt(scratch, rs, r2);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case less_equal:
+        if (rt.imm32_ == 0) {
+          blez(rs, offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          slt(scratch, r2, rs);
+          beq(scratch, zero_reg, offset);
+       }
+       break;
+      // Unsigned comparison.
+      case Ugreater:
+        if (rt.imm32_ == 0) {
+          bgtz(rs, offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          sltu(scratch, r2, rs);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case Ugreater_equal:
+        if (rt.imm32_ == 0) {
+          bgez(rs, offset);
+        } else if (is_int16(rt.imm32_)) {
+          sltiu(scratch, rs, rt.imm32_);
+          beq(scratch, zero_reg, offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          sltu(scratch, rs, r2);
+          beq(scratch, zero_reg, offset);
+        }
+        break;
+      case Uless:
+        if (rt.imm32_ == 0) {
+          b(offset);
+        } else if (is_int16(rt.imm32_)) {
+          sltiu(scratch, rs, rt.imm32_);
+          bne(scratch, zero_reg, offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          sltu(scratch, rs, r2);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case Uless_equal:
+        if (rt.imm32_ == 0) {
+          b(offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          sltu(scratch, r2, rs);
+          beq(scratch, zero_reg, offset);
+        }
+        break;
+      default:
+        UNREACHABLE();
+    }
   }
-  // Emit a nop in the branch delay slot.
-  nop();
+  // Emit a nop in the branch delay slot if required.
+  if (bdslot == PROTECT)
+    nop();
 }
 
 
-void MacroAssembler::Branch(Condition cond,  Label* L, Register rs,
-                            const Operand& rt, Register scratch) {
-  Register r2 = no_reg;
-  if (rt.is_reg()) {
-    r2 = rt.rm_;
-  } else if (cond != cc_always) {
-    r2 = scratch;
-    li(r2, rt);
-  }
-
+void MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) {
   // We use branch_offset as an argument for the branch instructions to be sure
   // it is called just before generating the branch instruction, as needed.
 
-  switch (cond) {
-    case cc_always:
-      b(shifted_branch_offset(L, false));
-      break;
-    case eq:
-      beq(rs, r2, shifted_branch_offset(L, false));
-      break;
-    case ne:
-      bne(rs, r2, shifted_branch_offset(L, false));
-      break;
+  b(shifted_branch_offset(L, false));
 
-    // Signed comparison
-    case greater:
-      slt(scratch, r2, rs);
-      bne(scratch, zero_reg, shifted_branch_offset(L, false));
-      break;
-    case greater_equal:
-      slt(scratch, rs, r2);
-      beq(scratch, zero_reg, shifted_branch_offset(L, false));
-      break;
-    case less:
-      slt(scratch, rs, r2);
-      bne(scratch, zero_reg, shifted_branch_offset(L, false));
-      break;
-    case less_equal:
-      slt(scratch, r2, rs);
-      beq(scratch, zero_reg, shifted_branch_offset(L, false));
-      break;
-
-    // Unsigned comparison.
-    case Ugreater:
-      sltu(scratch, r2, rs);
-      bne(scratch, zero_reg, shifted_branch_offset(L, false));
-      break;
-    case Ugreater_equal:
-      sltu(scratch, rs, r2);
-      beq(scratch, zero_reg, shifted_branch_offset(L, false));
-      break;
-    case Uless:
-      sltu(scratch, rs, r2);
-      bne(scratch, zero_reg, shifted_branch_offset(L, false));
-      break;
-    case Uless_equal:
-      sltu(scratch, r2, rs);
-      beq(scratch, zero_reg, shifted_branch_offset(L, false));
-      break;
-
-    default:
-      UNREACHABLE();
-  }
-  // Emit a nop in the branch delay slot.
-  nop();
+  // Emit a nop in the branch delay slot if required.
+  if (bdslot == PROTECT)
+    nop();
 }
 
 
-// Trashes the at register if no scratch register is provided.
+void MacroAssembler::Branch(Label* L, Condition cond, Register rs,
+                            const Operand& rt,
+                            BranchDelaySlot bdslot) {
+  BRANCH_ARGS_CHECK(cond, rs, rt);
+
+  int32_t offset;
+  Register r2 = no_reg;
+  Register scratch = at;
+  if (rt.is_reg()) {
+    r2 = rt.rm_;
+    // Be careful to always use shifted_branch_offset only just before the
+    // branch instruction, as the location will be remember for patching the
+    // target.
+    switch (cond) {
+      case cc_always:
+        offset = shifted_branch_offset(L, false);
+        b(offset);
+        break;
+      case eq:
+        offset = shifted_branch_offset(L, false);
+        beq(rs, r2, offset);
+        break;
+      case ne:
+        offset = shifted_branch_offset(L, false);
+        bne(rs, r2, offset);
+        break;
+      // Signed comparison
+      case greater:
+        if (r2.is(zero_reg)) {
+          offset = shifted_branch_offset(L, false);
+          bgtz(rs, offset);
+        } else {
+          slt(scratch, r2, rs);
+          offset = shifted_branch_offset(L, false);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case greater_equal:
+        if (r2.is(zero_reg)) {
+          offset = shifted_branch_offset(L, false);
+          bgez(rs, offset);
+        } else {
+          slt(scratch, rs, r2);
+          offset = shifted_branch_offset(L, false);
+          beq(scratch, zero_reg, offset);
+        }
+        break;
+      case less:
+        if (r2.is(zero_reg)) {
+          offset = shifted_branch_offset(L, false);
+          bltz(rs, offset);
+        } else {
+          slt(scratch, rs, r2);
+          offset = shifted_branch_offset(L, false);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case less_equal:
+        if (r2.is(zero_reg)) {
+          offset = shifted_branch_offset(L, false);
+          blez(rs, offset);
+        } else {
+          slt(scratch, r2, rs);
+          offset = shifted_branch_offset(L, false);
+          beq(scratch, zero_reg, offset);
+        }
+        break;
+      // Unsigned comparison.
+      case Ugreater:
+        if (r2.is(zero_reg)) {
+          offset = shifted_branch_offset(L, false);
+           bgtz(rs, offset);
+        } else {
+          sltu(scratch, r2, rs);
+          offset = shifted_branch_offset(L, false);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case Ugreater_equal:
+        if (r2.is(zero_reg)) {
+          offset = shifted_branch_offset(L, false);
+          bgez(rs, offset);
+        } else {
+          sltu(scratch, rs, r2);
+          offset = shifted_branch_offset(L, false);
+          beq(scratch, zero_reg, offset);
+        }
+        break;
+      case Uless:
+        if (r2.is(zero_reg)) {
+          offset = shifted_branch_offset(L, false);
+          b(offset);
+        } else {
+          sltu(scratch, rs, r2);
+          offset = shifted_branch_offset(L, false);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case Uless_equal:
+        if (r2.is(zero_reg)) {
+          offset = shifted_branch_offset(L, false);
+          b(offset);
+        } else {
+          sltu(scratch, r2, rs);
+          offset = shifted_branch_offset(L, false);
+          beq(scratch, zero_reg, offset);
+        }
+        break;
+      default:
+        UNREACHABLE();
+    }
+  } else {
+    // Be careful to always use shifted_branch_offset only just before the
+    // branch instruction, as the location will be remember for patching the
+    // target.
+    switch (cond) {
+      case cc_always:
+        offset = shifted_branch_offset(L, false);
+        b(offset);
+        break;
+      case eq:
+        r2 = scratch;
+        li(r2, rt);
+        offset = shifted_branch_offset(L, false);
+        beq(rs, r2, offset);
+        break;
+      case ne:
+        r2 = scratch;
+        li(r2, rt);
+        offset = shifted_branch_offset(L, false);
+        bne(rs, r2, offset);
+        break;
+      // Signed comparison
+      case greater:
+        if (rt.imm32_ == 0) {
+          offset = shifted_branch_offset(L, false);
+          bgtz(rs, offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          slt(scratch, r2, rs);
+          offset = shifted_branch_offset(L, false);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case greater_equal:
+        if (rt.imm32_ == 0) {
+          offset = shifted_branch_offset(L, false);
+          bgez(rs, offset);
+        } else if (is_int16(rt.imm32_)) {
+          slti(scratch, rs, rt.imm32_);
+          offset = shifted_branch_offset(L, false);
+          beq(scratch, zero_reg, offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          sltu(scratch, rs, r2);
+          offset = shifted_branch_offset(L, false);
+          beq(scratch, zero_reg, offset);
+        }
+        break;
+      case less:
+        if (rt.imm32_ == 0) {
+          offset = shifted_branch_offset(L, false);
+          bltz(rs, offset);
+        } else if (is_int16(rt.imm32_)) {
+          slti(scratch, rs, rt.imm32_);
+          offset = shifted_branch_offset(L, false);
+          bne(scratch, zero_reg, offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          slt(scratch, rs, r2);
+          offset = shifted_branch_offset(L, false);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case less_equal:
+        if (rt.imm32_ == 0) {
+          offset = shifted_branch_offset(L, false);
+          blez(rs, offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          slt(scratch, r2, rs);
+          offset = shifted_branch_offset(L, false);
+          beq(scratch, zero_reg, offset);
+        }
+        break;
+      // Unsigned comparison.
+      case Ugreater:
+        if (rt.imm32_ == 0) {
+          offset = shifted_branch_offset(L, false);
+          bgtz(rs, offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          sltu(scratch, r2, rs);
+          offset = shifted_branch_offset(L, false);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case Ugreater_equal:
+        if (rt.imm32_ == 0) {
+          offset = shifted_branch_offset(L, false);
+          bgez(rs, offset);
+        } else if (is_int16(rt.imm32_)) {
+          sltiu(scratch, rs, rt.imm32_);
+          offset = shifted_branch_offset(L, false);
+          beq(scratch, zero_reg, offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          sltu(scratch, rs, r2);
+          offset = shifted_branch_offset(L, false);
+          beq(scratch, zero_reg, offset);
+        }
+        break;
+     case Uless:
+        if (rt.imm32_ == 0) {
+          offset = shifted_branch_offset(L, false);
+          b(offset);
+        } else if (is_int16(rt.imm32_)) {
+          sltiu(scratch, rs, rt.imm32_);
+          offset = shifted_branch_offset(L, false);
+          bne(scratch, zero_reg, offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          sltu(scratch, rs, r2);
+          offset = shifted_branch_offset(L, false);
+          bne(scratch, zero_reg, offset);
+        }
+        break;
+      case Uless_equal:
+        if (rt.imm32_ == 0) {
+          offset = shifted_branch_offset(L, false);
+          b(offset);
+        } else {
+          r2 = scratch;
+          li(r2, rt);
+          sltu(scratch, r2, rs);
+          offset = shifted_branch_offset(L, false);
+          beq(scratch, zero_reg, offset);
+        }
+        break;
+      default:
+        UNREACHABLE();
+    }
+  }
+  // Check that offset could actually hold on an int16_t.
+  ASSERT(is_int16(offset));
+  // Emit a nop in the branch delay slot if required.
+  if (bdslot == PROTECT)
+    nop();
+}
+
+
 // We need to use a bgezal or bltzal, but they can't be used directly with the
 // slt instructions. We could use sub or add instead but we would miss overflow
 // cases, so we keep slt and add an intermediate third instruction.
-void MacroAssembler::BranchAndLink(Condition cond, int16_t offset, Register rs,
-                                   const Operand& rt, Register scratch) {
-  Register r2 = no_reg;
-  if (rt.is_reg()) {
-    r2 = rt.rm_;
-  } else if (cond != cc_always) {
-    r2 = scratch;
-    li(r2, rt);
-  }
+void MacroAssembler::BranchAndLink(int16_t offset,
+                                   BranchDelaySlot bdslot) {
+  bal(offset);
 
-  switch (cond) {
-    case cc_always:
-      bal(offset);
-      break;
-    case eq:
-      bne(rs, r2, 2);
-      nop();
-      bal(offset);
-      break;
-    case ne:
-      beq(rs, r2, 2);
-      nop();
-      bal(offset);
-      break;
-
-    // Signed comparison
-    case greater:
-      slt(scratch, r2, rs);
-      addiu(scratch, scratch, -1);
-      bgezal(scratch, offset);
-      break;
-    case greater_equal:
-      slt(scratch, rs, r2);
-      addiu(scratch, scratch, -1);
-      bltzal(scratch, offset);
-      break;
-    case less:
-      slt(scratch, rs, r2);
-      addiu(scratch, scratch, -1);
-      bgezal(scratch, offset);
-      break;
-    case less_equal:
-      slt(scratch, r2, rs);
-      addiu(scratch, scratch, -1);
-      bltzal(scratch, offset);
-      break;
-
-    // Unsigned comparison.
-    case Ugreater:
-      sltu(scratch, r2, rs);
-      addiu(scratch, scratch, -1);
-      bgezal(scratch, offset);
-      break;
-    case Ugreater_equal:
-      sltu(scratch, rs, r2);
-      addiu(scratch, scratch, -1);
-      bltzal(scratch, offset);
-      break;
-    case Uless:
-      sltu(scratch, rs, r2);
-      addiu(scratch, scratch, -1);
-      bgezal(scratch, offset);
-      break;
-    case Uless_equal:
-      sltu(scratch, r2, rs);
-      addiu(scratch, scratch, -1);
-      bltzal(scratch, offset);
-      break;
-
-    default:
-      UNREACHABLE();
-  }
-  // Emit a nop in the branch delay slot.
-  nop();
+  // Emit a nop in the branch delay slot if required.
+  if (bdslot == PROTECT)
+    nop();
 }
 
 
-void MacroAssembler::BranchAndLink(Condition cond, Label* L, Register rs,
-                                   const Operand& rt, Register scratch) {
+void MacroAssembler::BranchAndLink(int16_t offset, Condition cond, Register rs,
+                                   const Operand& rt,
+                                   BranchDelaySlot bdslot) {
+  BRANCH_ARGS_CHECK(cond, rs, rt);
   Register r2 = no_reg;
+  Register scratch = at;
+
   if (rt.is_reg()) {
     r2 = rt.rm_;
   } else if (cond != cc_always) {
@@ -650,157 +1431,372 @@
 
   switch (cond) {
     case cc_always:
-      bal(shifted_branch_offset(L, false));
+      bal(offset);
       break;
     case eq:
       bne(rs, r2, 2);
       nop();
-      bal(shifted_branch_offset(L, false));
+      bal(offset);
       break;
     case ne:
       beq(rs, r2, 2);
       nop();
-      bal(shifted_branch_offset(L, false));
+      bal(offset);
       break;
 
     // Signed comparison
     case greater:
       slt(scratch, r2, rs);
       addiu(scratch, scratch, -1);
-      bgezal(scratch, shifted_branch_offset(L, false));
+      bgezal(scratch, offset);
       break;
     case greater_equal:
       slt(scratch, rs, r2);
       addiu(scratch, scratch, -1);
-      bltzal(scratch, shifted_branch_offset(L, false));
+      bltzal(scratch, offset);
       break;
     case less:
       slt(scratch, rs, r2);
       addiu(scratch, scratch, -1);
-      bgezal(scratch, shifted_branch_offset(L, false));
+      bgezal(scratch, offset);
       break;
     case less_equal:
       slt(scratch, r2, rs);
       addiu(scratch, scratch, -1);
-      bltzal(scratch, shifted_branch_offset(L, false));
+      bltzal(scratch, offset);
       break;
 
     // Unsigned comparison.
     case Ugreater:
       sltu(scratch, r2, rs);
       addiu(scratch, scratch, -1);
-      bgezal(scratch, shifted_branch_offset(L, false));
+      bgezal(scratch, offset);
       break;
     case Ugreater_equal:
       sltu(scratch, rs, r2);
       addiu(scratch, scratch, -1);
-      bltzal(scratch, shifted_branch_offset(L, false));
+      bltzal(scratch, offset);
       break;
     case Uless:
       sltu(scratch, rs, r2);
       addiu(scratch, scratch, -1);
-      bgezal(scratch, shifted_branch_offset(L, false));
+      bgezal(scratch, offset);
       break;
     case Uless_equal:
       sltu(scratch, r2, rs);
       addiu(scratch, scratch, -1);
-      bltzal(scratch, shifted_branch_offset(L, false));
+      bltzal(scratch, offset);
       break;
 
     default:
       UNREACHABLE();
   }
-  // Emit a nop in the branch delay slot.
-  nop();
+  // Emit a nop in the branch delay slot if required.
+  if (bdslot == PROTECT)
+    nop();
+}
+
+
+void MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) {
+  bal(shifted_branch_offset(L, false));
+
+  // Emit a nop in the branch delay slot if required.
+  if (bdslot == PROTECT)
+    nop();
+}
+
+
+void MacroAssembler::BranchAndLink(Label* L, Condition cond, Register rs,
+                                   const Operand& rt,
+                                   BranchDelaySlot bdslot) {
+  BRANCH_ARGS_CHECK(cond, rs, rt);
+
+  int32_t offset;
+  Register r2 = no_reg;
+  Register scratch = at;
+  if (rt.is_reg()) {
+    r2 = rt.rm_;
+  } else if (cond != cc_always) {
+    r2 = scratch;
+    li(r2, rt);
+  }
+
+  switch (cond) {
+    case cc_always:
+      offset = shifted_branch_offset(L, false);
+      bal(offset);
+      break;
+    case eq:
+      bne(rs, r2, 2);
+      nop();
+      offset = shifted_branch_offset(L, false);
+      bal(offset);
+      break;
+    case ne:
+      beq(rs, r2, 2);
+      nop();
+      offset = shifted_branch_offset(L, false);
+      bal(offset);
+      break;
+
+    // Signed comparison
+    case greater:
+      slt(scratch, r2, rs);
+      addiu(scratch, scratch, -1);
+      offset = shifted_branch_offset(L, false);
+      bgezal(scratch, offset);
+      break;
+    case greater_equal:
+      slt(scratch, rs, r2);
+      addiu(scratch, scratch, -1);
+      offset = shifted_branch_offset(L, false);
+      bltzal(scratch, offset);
+      break;
+    case less:
+      slt(scratch, rs, r2);
+      addiu(scratch, scratch, -1);
+      offset = shifted_branch_offset(L, false);
+      bgezal(scratch, offset);
+      break;
+    case less_equal:
+      slt(scratch, r2, rs);
+      addiu(scratch, scratch, -1);
+      offset = shifted_branch_offset(L, false);
+      bltzal(scratch, offset);
+      break;
+
+    // Unsigned comparison.
+    case Ugreater:
+      sltu(scratch, r2, rs);
+      addiu(scratch, scratch, -1);
+      offset = shifted_branch_offset(L, false);
+      bgezal(scratch, offset);
+      break;
+    case Ugreater_equal:
+      sltu(scratch, rs, r2);
+      addiu(scratch, scratch, -1);
+      offset = shifted_branch_offset(L, false);
+      bltzal(scratch, offset);
+      break;
+    case Uless:
+      sltu(scratch, rs, r2);
+      addiu(scratch, scratch, -1);
+      offset = shifted_branch_offset(L, false);
+      bgezal(scratch, offset);
+      break;
+    case Uless_equal:
+      sltu(scratch, r2, rs);
+      addiu(scratch, scratch, -1);
+      offset = shifted_branch_offset(L, false);
+      bltzal(scratch, offset);
+      break;
+
+    default:
+      UNREACHABLE();
+  }
+
+  // Check that offset could actually hold on an int16_t.
+  ASSERT(is_int16(offset));
+
+  // Emit a nop in the branch delay slot if required.
+  if (bdslot == PROTECT)
+    nop();
+}
+
+
+void MacroAssembler::Jump(const Operand& target, BranchDelaySlot bdslot) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
+  if (target.is_reg()) {
+      jr(target.rm());
+  } else {
+    if (!MustUseReg(target.rmode_)) {
+        j(target.imm32_);
+    } else {
+      li(t9, target);
+      jr(t9);
+    }
+  }
+  // Emit a nop in the branch delay slot if required.
+  if (bdslot == PROTECT)
+    nop();
 }
 
 
 void MacroAssembler::Jump(const Operand& target,
-                          Condition cond, Register rs, const Operand& rt) {
+                          Condition cond, Register rs, const Operand& rt,
+                          BranchDelaySlot bdslot) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
+  BRANCH_ARGS_CHECK(cond, rs, rt);
   if (target.is_reg()) {
     if (cond == cc_always) {
       jr(target.rm());
     } else {
-      Branch(NegateCondition(cond), 2, rs, rt);
+      Branch(2, NegateCondition(cond), rs, rt);
       jr(target.rm());
     }
-  } else {    // !target.is_reg()
-    if (!MustUseAt(target.rmode_)) {
+  } else {  // Not register target.
+    if (!MustUseReg(target.rmode_)) {
       if (cond == cc_always) {
         j(target.imm32_);
       } else {
-        Branch(NegateCondition(cond), 2, rs, rt);
+        Branch(2, NegateCondition(cond), rs, rt);
         j(target.imm32_);  // Will generate only one instruction.
       }
-    } else {  // MustUseAt(target)
-      li(at, target);
+    } else {  // MustUseReg(target)
+      li(t9, target);
       if (cond == cc_always) {
-        jr(at);
+        jr(t9);
       } else {
-        Branch(NegateCondition(cond), 2, rs, rt);
-        jr(at);  // Will generate only one instruction.
+        Branch(2, NegateCondition(cond), rs, rt);
+        jr(t9);  // Will generate only one instruction.
       }
     }
   }
-  // Emit a nop in the branch delay slot.
-  nop();
+  // Emit a nop in the branch delay slot if required.
+  if (bdslot == PROTECT)
+    nop();
 }
 
 
+// Note: To call gcc-compiled C code on mips, you must call thru t9.
+void MacroAssembler::Call(const Operand& target, BranchDelaySlot bdslot) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
+  if (target.is_reg()) {
+      jalr(target.rm());
+  } else {    // !target.is_reg()
+    if (!MustUseReg(target.rmode_)) {
+      jal(target.imm32_);
+    } else {  // MustUseReg(target)
+      li(t9, target);
+      jalr(t9);
+    }
+  }
+  // Emit a nop in the branch delay slot if required.
+  if (bdslot == PROTECT)
+    nop();
+}
+
+
+// Note: To call gcc-compiled C code on mips, you must call thru t9.
 void MacroAssembler::Call(const Operand& target,
-                          Condition cond, Register rs, const Operand& rt) {
+                          Condition cond, Register rs, const Operand& rt,
+                          BranchDelaySlot bdslot) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
+  BRANCH_ARGS_CHECK(cond, rs, rt);
   if (target.is_reg()) {
     if (cond == cc_always) {
       jalr(target.rm());
     } else {
-      Branch(NegateCondition(cond), 2, rs, rt);
+      Branch(2, NegateCondition(cond), rs, rt);
       jalr(target.rm());
     }
   } else {    // !target.is_reg()
-    if (!MustUseAt(target.rmode_)) {
+    if (!MustUseReg(target.rmode_)) {
       if (cond == cc_always) {
         jal(target.imm32_);
       } else {
-        Branch(NegateCondition(cond), 2, rs, rt);
+        Branch(2, NegateCondition(cond), rs, rt);
         jal(target.imm32_);  // Will generate only one instruction.
       }
-    } else {  // MustUseAt(target)
-      li(at, target);
+    } else {  // MustUseReg(target)
+      li(t9, target);
       if (cond == cc_always) {
-        jalr(at);
+        jalr(t9);
       } else {
-        Branch(NegateCondition(cond), 2, rs, rt);
-        jalr(at);  // Will generate only one instruction.
+        Branch(2, NegateCondition(cond), rs, rt);
+        jalr(t9);  // Will generate only one instruction.
       }
     }
   }
-  // Emit a nop in the branch delay slot.
-  nop();
-}
-
-void MacroAssembler::StackLimitCheck(Label* on_stack_overflow) {
-  UNIMPLEMENTED_MIPS();
+  // Emit a nop in the branch delay slot if required.
+  if (bdslot == PROTECT)
+    nop();
 }
 
 
-void MacroAssembler::Drop(int count, Condition cond) {
-  UNIMPLEMENTED_MIPS();
+void MacroAssembler::Drop(int count,
+                          Condition cond,
+                          Register reg,
+                          const Operand& op) {
+  if (count <= 0) {
+    return;
+  }
+
+  Label skip;
+
+  if (cond != al) {
+    Branch(&skip, NegateCondition(cond), reg, op);
+  }
+
+  if (count > 0) {
+    addiu(sp, sp, count * kPointerSize);
+  }
+
+  if (cond != al) {
+    bind(&skip);
+  }
+}
+
+
+void MacroAssembler::DropAndRet(int drop,
+                                Condition cond,
+                                Register r1,
+                                const Operand& r2) {
+  // This is a workaround to make sure only one branch instruction is
+  // generated. It relies on Drop and Ret not creating branches if
+  // cond == cc_always.
+  Label skip;
+  if (cond != cc_always) {
+    Branch(&skip, NegateCondition(cond), r1, r2);
+  }
+
+  Drop(drop);
+  Ret();
+
+  if (cond != cc_always) {
+    bind(&skip);
+  }
+}
+
+
+void MacroAssembler::Swap(Register reg1,
+                          Register reg2,
+                          Register scratch) {
+  if (scratch.is(no_reg)) {
+    Xor(reg1, reg1, Operand(reg2));
+    Xor(reg2, reg2, Operand(reg1));
+    Xor(reg1, reg1, Operand(reg2));
+  } else {
+    mov(scratch, reg1);
+    mov(reg1, reg2);
+    mov(reg2, scratch);
+  }
 }
 
 
 void MacroAssembler::Call(Label* target) {
-  UNIMPLEMENTED_MIPS();
+  BranchAndLink(target);
+}
+
+
+void MacroAssembler::Move(Register dst, Register src) {
+  if (!dst.is(src)) {
+    mov(dst, src);
+  }
 }
 
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  // ---------------------------------------------------------------------------
-  // Debugger Support
 
-  void MacroAssembler::DebugBreak() {
-    UNIMPLEMENTED_MIPS();
-  }
-#endif
+void MacroAssembler::DebugBreak() {
+  ASSERT(allow_stub_calls());
+  mov(a0, zero_reg);
+  li(a1, Operand(ExternalReference(Runtime::kDebugBreak, isolate())));
+  CEntryStub ces(1);
+  Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
+}
+
+#endif  // ENABLE_DEBUGGER_SUPPORT
 
 
 // ---------------------------------------------------------------------------
@@ -822,7 +1818,7 @@
            && StackHandlerConstants::kPCOffset == 3 * kPointerSize
            && StackHandlerConstants::kNextOffset == 0 * kPointerSize);
     // Save the current handler as the next handler.
-    LoadExternalReference(t2, ExternalReference(Top::k_handler_address));
+    li(t2, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
     lw(t1, MemOperand(t2));
 
     addiu(sp, sp, -StackHandlerConstants::kSize);
@@ -848,7 +1844,7 @@
     li(t0, Operand(StackHandler::ENTRY));
 
     // Save the current handler as the next handler.
-    LoadExternalReference(t2, ExternalReference(Top::k_handler_address));
+    li(t2, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
     lw(t1, MemOperand(t2));
 
     addiu(sp, sp, -StackHandlerConstants::kSize);
@@ -864,45 +1860,377 @@
 
 
 void MacroAssembler::PopTryHandler() {
-  UNIMPLEMENTED_MIPS();
+  ASSERT_EQ(0, StackHandlerConstants::kNextOffset);
+  pop(a1);
+  Addu(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
+  li(at, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
+  sw(a1, MemOperand(at));
 }
 
 
-
-// -----------------------------------------------------------------------------
-// Activation frames
-
-void MacroAssembler::SetupAlignedCall(Register scratch, int arg_count) {
-  Label extra_push, end;
-
-  andi(scratch, sp, 7);
-
-  // We check for args and receiver size on the stack, all of them word sized.
-  // We add one for sp, that we also want to store on the stack.
-  if (((arg_count + 1) % kPointerSizeLog2) == 0) {
-    Branch(ne, &extra_push, at, Operand(zero_reg));
-  } else {  // ((arg_count + 1) % 2) == 1
-    Branch(eq, &extra_push, at, Operand(zero_reg));
+void MacroAssembler::AllocateInNewSpace(int object_size,
+                                        Register result,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        Label* gc_required,
+                                        AllocationFlags flags) {
+  if (!FLAG_inline_new) {
+    if (FLAG_debug_code) {
+      // Trash the registers to simulate an allocation failure.
+      li(result, 0x7091);
+      li(scratch1, 0x7191);
+      li(scratch2, 0x7291);
+    }
+    jmp(gc_required);
+    return;
   }
 
-  // Save sp on the stack.
-  mov(scratch, sp);
-  Push(scratch);
-  b(&end);
+  ASSERT(!result.is(scratch1));
+  ASSERT(!result.is(scratch2));
+  ASSERT(!scratch1.is(scratch2));
+  ASSERT(!scratch1.is(t9));
+  ASSERT(!scratch2.is(t9));
+  ASSERT(!result.is(t9));
 
-  // Align before saving sp on the stack.
-  bind(&extra_push);
-  mov(scratch, sp);
-  addiu(sp, sp, -8);
-  sw(scratch, MemOperand(sp));
+  // Make object size into bytes.
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    object_size *= kPointerSize;
+  }
+  ASSERT_EQ(0, object_size & kObjectAlignmentMask);
 
-  // The stack is aligned and sp is stored on the top.
-  bind(&end);
+  // Check relative positions of allocation top and limit addresses.
+  // ARM adds additional checks to make sure the ldm instruction can be
+  // used. On MIPS we don't have ldm so we don't need additional checks either.
+  ExternalReference new_space_allocation_top =
+      ExternalReference::new_space_allocation_top_address(isolate());
+  ExternalReference new_space_allocation_limit =
+      ExternalReference::new_space_allocation_limit_address(isolate());
+  intptr_t top   =
+      reinterpret_cast<intptr_t>(new_space_allocation_top.address());
+  intptr_t limit =
+      reinterpret_cast<intptr_t>(new_space_allocation_limit.address());
+  ASSERT((limit - top) == kPointerSize);
+
+  // Set up allocation top address and object size registers.
+  Register topaddr = scratch1;
+  Register obj_size_reg = scratch2;
+  li(topaddr, Operand(new_space_allocation_top));
+  li(obj_size_reg, Operand(object_size));
+
+  // This code stores a temporary value in t9.
+  if ((flags & RESULT_CONTAINS_TOP) == 0) {
+    // Load allocation top into result and allocation limit into t9.
+    lw(result, MemOperand(topaddr));
+    lw(t9, MemOperand(topaddr, kPointerSize));
+  } else {
+    if (FLAG_debug_code) {
+      // Assert that result actually contains top on entry. t9 is used
+      // immediately below so this use of t9 does not cause difference with
+      // respect to register content between debug and release mode.
+      lw(t9, MemOperand(topaddr));
+      Check(eq, "Unexpected allocation top", result, Operand(t9));
+    }
+    // Load allocation limit into t9. Result already contains allocation top.
+    lw(t9, MemOperand(topaddr, limit - top));
+  }
+
+  // Calculate new top and bail out if new space is exhausted. Use result
+  // to calculate the new top.
+  Addu(scratch2, result, Operand(obj_size_reg));
+  Branch(gc_required, Ugreater, scratch2, Operand(t9));
+  sw(scratch2, MemOperand(topaddr));
+
+  // Tag object if requested.
+  if ((flags & TAG_OBJECT) != 0) {
+    Addu(result, result, Operand(kHeapObjectTag));
+  }
 }
 
 
-void MacroAssembler::ReturnFromAlignedCall() {
-  lw(sp, MemOperand(sp));
+void MacroAssembler::AllocateInNewSpace(Register object_size,
+                                        Register result,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        Label* gc_required,
+                                        AllocationFlags flags) {
+  if (!FLAG_inline_new) {
+    if (FLAG_debug_code) {
+      // Trash the registers to simulate an allocation failure.
+      li(result, 0x7091);
+      li(scratch1, 0x7191);
+      li(scratch2, 0x7291);
+    }
+    jmp(gc_required);
+    return;
+  }
+
+  ASSERT(!result.is(scratch1));
+  ASSERT(!result.is(scratch2));
+  ASSERT(!scratch1.is(scratch2));
+  ASSERT(!scratch1.is(t9) && !scratch2.is(t9) && !result.is(t9));
+
+  // Check relative positions of allocation top and limit addresses.
+  // ARM adds additional checks to make sure the ldm instruction can be
+  // used. On MIPS we don't have ldm so we don't need additional checks either.
+  ExternalReference new_space_allocation_top =
+      ExternalReference::new_space_allocation_top_address(isolate());
+  ExternalReference new_space_allocation_limit =
+      ExternalReference::new_space_allocation_limit_address(isolate());
+  intptr_t top   =
+      reinterpret_cast<intptr_t>(new_space_allocation_top.address());
+  intptr_t limit =
+      reinterpret_cast<intptr_t>(new_space_allocation_limit.address());
+  ASSERT((limit - top) == kPointerSize);
+
+  // Set up allocation top address and object size registers.
+  Register topaddr = scratch1;
+  li(topaddr, Operand(new_space_allocation_top));
+
+  // This code stores a temporary value in t9.
+  if ((flags & RESULT_CONTAINS_TOP) == 0) {
+    // Load allocation top into result and allocation limit into t9.
+    lw(result, MemOperand(topaddr));
+    lw(t9, MemOperand(topaddr, kPointerSize));
+  } else {
+    if (FLAG_debug_code) {
+      // Assert that result actually contains top on entry. t9 is used
+      // immediately below so this use of t9 does not cause difference with
+      // respect to register content between debug and release mode.
+      lw(t9, MemOperand(topaddr));
+      Check(eq, "Unexpected allocation top", result, Operand(t9));
+    }
+    // Load allocation limit into t9. Result already contains allocation top.
+    lw(t9, MemOperand(topaddr, limit - top));
+  }
+
+  // Calculate new top and bail out if new space is exhausted. Use result
+  // to calculate the new top. Object size may be in words so a shift is
+  // required to get the number of bytes.
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    sll(scratch2, object_size, kPointerSizeLog2);
+    Addu(scratch2, result, scratch2);
+  } else {
+    Addu(scratch2, result, Operand(object_size));
+  }
+  Branch(gc_required, Ugreater, scratch2, Operand(t9));
+
+  // Update allocation top. result temporarily holds the new top.
+  if (FLAG_debug_code) {
+    And(t9, scratch2, Operand(kObjectAlignmentMask));
+    Check(eq, "Unaligned allocation in new space", t9, Operand(zero_reg));
+  }
+  sw(scratch2, MemOperand(topaddr));
+
+  // Tag object if requested.
+  if ((flags & TAG_OBJECT) != 0) {
+    Addu(result, result, Operand(kHeapObjectTag));
+  }
+}
+
+
+void MacroAssembler::UndoAllocationInNewSpace(Register object,
+                                              Register scratch) {
+  ExternalReference new_space_allocation_top =
+      ExternalReference::new_space_allocation_top_address(isolate());
+
+  // Make sure the object has no tag before resetting top.
+  And(object, object, Operand(~kHeapObjectTagMask));
+#ifdef DEBUG
+  // Check that the object un-allocated is below the current top.
+  li(scratch, Operand(new_space_allocation_top));
+  lw(scratch, MemOperand(scratch));
+  Check(less, "Undo allocation of non allocated memory",
+      object, Operand(scratch));
+#endif
+  // Write the address of the object to un-allocate as the current top.
+  li(scratch, Operand(new_space_allocation_top));
+  sw(object, MemOperand(scratch));
+}
+
+
+void MacroAssembler::AllocateTwoByteString(Register result,
+                                           Register length,
+                                           Register scratch1,
+                                           Register scratch2,
+                                           Register scratch3,
+                                           Label* gc_required) {
+  // Calculate the number of bytes needed for the characters in the string while
+  // observing object alignment.
+  ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
+  sll(scratch1, length, 1);  // Length in bytes, not chars.
+  addiu(scratch1, scratch1,
+       kObjectAlignmentMask + SeqTwoByteString::kHeaderSize);
+  And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
+
+  // Allocate two-byte string in new space.
+  AllocateInNewSpace(scratch1,
+                     result,
+                     scratch2,
+                     scratch3,
+                     gc_required,
+                     TAG_OBJECT);
+
+  // Set the map, length and hash field.
+  InitializeNewString(result,
+                      length,
+                      Heap::kStringMapRootIndex,
+                      scratch1,
+                      scratch2);
+}
+
+
+void MacroAssembler::AllocateAsciiString(Register result,
+                                         Register length,
+                                         Register scratch1,
+                                         Register scratch2,
+                                         Register scratch3,
+                                         Label* gc_required) {
+  // Calculate the number of bytes needed for the characters in the string
+  // while observing object alignment.
+  ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
+  ASSERT(kCharSize == 1);
+  addiu(scratch1, length, kObjectAlignmentMask + SeqAsciiString::kHeaderSize);
+  And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
+
+  // Allocate ASCII string in new space.
+  AllocateInNewSpace(scratch1,
+                     result,
+                     scratch2,
+                     scratch3,
+                     gc_required,
+                     TAG_OBJECT);
+
+  // Set the map, length and hash field.
+  InitializeNewString(result,
+                      length,
+                      Heap::kAsciiStringMapRootIndex,
+                      scratch1,
+                      scratch2);
+}
+
+
+void MacroAssembler::AllocateTwoByteConsString(Register result,
+                                               Register length,
+                                               Register scratch1,
+                                               Register scratch2,
+                                               Label* gc_required) {
+  AllocateInNewSpace(ConsString::kSize,
+                     result,
+                     scratch1,
+                     scratch2,
+                     gc_required,
+                     TAG_OBJECT);
+  InitializeNewString(result,
+                      length,
+                      Heap::kConsStringMapRootIndex,
+                      scratch1,
+                      scratch2);
+}
+
+
+void MacroAssembler::AllocateAsciiConsString(Register result,
+                                             Register length,
+                                             Register scratch1,
+                                             Register scratch2,
+                                             Label* gc_required) {
+  AllocateInNewSpace(ConsString::kSize,
+                     result,
+                     scratch1,
+                     scratch2,
+                     gc_required,
+                     TAG_OBJECT);
+  InitializeNewString(result,
+                      length,
+                      Heap::kConsAsciiStringMapRootIndex,
+                      scratch1,
+                      scratch2);
+}
+
+
+// Allocates a heap number or jumps to the label if the young space is full and
+// a scavenge is needed.
+void MacroAssembler::AllocateHeapNumber(Register result,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        Register heap_number_map,
+                                        Label* need_gc) {
+  // Allocate an object in the heap for the heap number and tag it as a heap
+  // object.
+  AllocateInNewSpace(HeapNumber::kSize,
+                     result,
+                     scratch1,
+                     scratch2,
+                     need_gc,
+                     TAG_OBJECT);
+
+  // Store heap number map in the allocated object.
+  AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+  sw(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
+}
+
+
+void MacroAssembler::AllocateHeapNumberWithValue(Register result,
+                                                 FPURegister value,
+                                                 Register scratch1,
+                                                 Register scratch2,
+                                                 Label* gc_required) {
+  LoadRoot(t6, Heap::kHeapNumberMapRootIndex);
+  AllocateHeapNumber(result, scratch1, scratch2, t6, gc_required);
+  sdc1(value, FieldMemOperand(result, HeapNumber::kValueOffset));
+}
+
+
+// Copies a fixed number of fields of heap objects from src to dst.
+void MacroAssembler::CopyFields(Register dst,
+                                Register src,
+                                RegList temps,
+                                int field_count) {
+  ASSERT((temps & dst.bit()) == 0);
+  ASSERT((temps & src.bit()) == 0);
+  // Primitive implementation using only one temporary register.
+
+  Register tmp = no_reg;
+  // Find a temp register in temps list.
+  for (int i = 0; i < kNumRegisters; i++) {
+    if ((temps & (1 << i)) != 0) {
+      tmp.code_ = i;
+      break;
+    }
+  }
+  ASSERT(!tmp.is(no_reg));
+
+  for (int i = 0; i < field_count; i++) {
+    lw(tmp, FieldMemOperand(src, i * kPointerSize));
+    sw(tmp, FieldMemOperand(dst, i * kPointerSize));
+  }
+}
+
+
+void MacroAssembler::CheckMap(Register obj,
+                              Register scratch,
+                              Handle<Map> map,
+                              Label* fail,
+                              bool is_heap_object) {
+  if (!is_heap_object) {
+    JumpIfSmi(obj, fail);
+  }
+  lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
+  li(at, Operand(map));
+  Branch(fail, ne, scratch, Operand(at));
+}
+
+
+void MacroAssembler::CheckMap(Register obj,
+                              Register scratch,
+                              Heap::RootListIndex index,
+                              Label* fail,
+                              bool is_heap_object) {
+  if (!is_heap_object) {
+    JumpIfSmi(obj, fail);
+  }
+  lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
+  LoadRoot(at, index);
+  Branch(fail, ne, scratch, Operand(at));
 }
 
 
@@ -914,7 +2242,8 @@
                                     Handle<Code> code_constant,
                                     Register code_reg,
                                     Label* done,
-                                    InvokeFlag flag) {
+                                    InvokeFlag flag,
+                                    PostCallGenerator* post_call_generator) {
   bool definitely_matches = false;
   Label regular_invoke;
 
@@ -949,11 +2278,13 @@
         li(a2, Operand(expected.immediate()));
       }
     }
-  } else if (actual.is_immediate()) {
-    Branch(eq, &regular_invoke, expected.reg(), Operand(actual.immediate()));
-    li(a0, Operand(actual.immediate()));
   } else {
-    Branch(eq, &regular_invoke, expected.reg(), Operand(actual.reg()));
+    if (actual.is_immediate()) {
+      Branch(&regular_invoke, eq, expected.reg(), Operand(actual.immediate()));
+      li(a0, Operand(actual.immediate()));
+    } else {
+      Branch(&regular_invoke, eq, expected.reg(), Operand(actual.reg()));
+    }
   }
 
   if (!definitely_matches) {
@@ -962,25 +2293,29 @@
       addiu(a3, a3, Code::kHeaderSize - kHeapObjectTag);
     }
 
-    ExternalReference adaptor(Builtins::ArgumentsAdaptorTrampoline);
+    Handle<Code> adaptor =
+        isolate()->builtins()->ArgumentsAdaptorTrampoline();
     if (flag == CALL_FUNCTION) {
-      CallBuiltin(adaptor);
-      b(done);
-      nop();
+      Call(adaptor, RelocInfo::CODE_TARGET);
+      if (post_call_generator != NULL) post_call_generator->Generate();
+      jmp(done);
     } else {
-      JumpToBuiltin(adaptor);
+      Jump(adaptor, RelocInfo::CODE_TARGET);
     }
     bind(&regular_invoke);
   }
 }
 
+
 void MacroAssembler::InvokeCode(Register code,
                                 const ParameterCount& expected,
                                 const ParameterCount& actual,
-                                InvokeFlag flag) {
+                                InvokeFlag flag,
+                                PostCallGenerator* post_call_generator) {
   Label done;
 
-  InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag);
+  InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag,
+                 post_call_generator);
   if (flag == CALL_FUNCTION) {
     Call(code);
   } else {
@@ -1014,7 +2349,8 @@
 
 void MacroAssembler::InvokeFunction(Register function,
                                     const ParameterCount& actual,
-                                    InvokeFlag flag) {
+                                    InvokeFlag flag,
+                                    PostCallGenerator* post_call_generator) {
   // Contract with called JS functions requires that function is passed in a1.
   ASSERT(function.is(a1));
   Register expected_reg = a2;
@@ -1025,68 +2361,120 @@
   lw(expected_reg,
       FieldMemOperand(code_reg,
                       SharedFunctionInfo::kFormalParameterCountOffset));
-  lw(code_reg,
-      MemOperand(code_reg, SharedFunctionInfo::kCodeOffset - kHeapObjectTag));
-  addiu(code_reg, code_reg, Code::kHeaderSize - kHeapObjectTag);
+  sra(expected_reg, expected_reg, kSmiTagSize);
+  lw(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
 
   ParameterCount expected(expected_reg);
-  InvokeCode(code_reg, expected, actual, flag);
+  InvokeCode(code_reg, expected, actual, flag, post_call_generator);
+}
+
+
+void MacroAssembler::InvokeFunction(JSFunction* function,
+                                    const ParameterCount& actual,
+                                    InvokeFlag flag) {
+  ASSERT(function->is_compiled());
+
+  // Get the function and setup the context.
+  li(a1, Operand(Handle<JSFunction>(function)));
+  lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
+
+  // Invoke the cached code.
+  Handle<Code> code(function->code());
+  ParameterCount expected(function->shared()->formal_parameter_count());
+  if (V8::UseCrankshaft()) {
+    UNIMPLEMENTED_MIPS();
+  } else {
+    InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag);
+  }
+}
+
+
+void MacroAssembler::IsObjectJSObjectType(Register heap_object,
+                                          Register map,
+                                          Register scratch,
+                                          Label* fail) {
+  lw(map, FieldMemOperand(heap_object, HeapObject::kMapOffset));
+  IsInstanceJSObjectType(map, scratch, fail);
+}
+
+
+void MacroAssembler::IsInstanceJSObjectType(Register map,
+                                            Register scratch,
+                                            Label* fail) {
+  lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
+  Branch(fail, lt, scratch, Operand(FIRST_JS_OBJECT_TYPE));
+  Branch(fail, gt, scratch, Operand(LAST_JS_OBJECT_TYPE));
+}
+
+
+void MacroAssembler::IsObjectJSStringType(Register object,
+                                          Register scratch,
+                                          Label* fail) {
+  ASSERT(kNotStringTag != 0);
+
+  lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
+  lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
+  And(scratch, scratch, Operand(kIsNotStringMask));
+  Branch(fail, ne, scratch, Operand(zero_reg));
 }
 
 
 // ---------------------------------------------------------------------------
 // Support functions.
 
-  void MacroAssembler::GetObjectType(Register function,
-                                     Register map,
-                                     Register type_reg) {
-    lw(map, FieldMemOperand(function, HeapObject::kMapOffset));
-    lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
-  }
+
+void MacroAssembler::TryGetFunctionPrototype(Register function,
+                                             Register result,
+                                             Register scratch,
+                                             Label* miss) {
+  // Check that the receiver isn't a smi.
+  JumpIfSmi(function, miss);
+
+  // Check that the function really is a function.  Load map into result reg.
+  GetObjectType(function, result, scratch);
+  Branch(miss, ne, scratch, Operand(JS_FUNCTION_TYPE));
+
+  // Make sure that the function has an instance prototype.
+  Label non_instance;
+  lbu(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
+  And(scratch, scratch, Operand(1 << Map::kHasNonInstancePrototype));
+  Branch(&non_instance, ne, scratch, Operand(zero_reg));
+
+  // Get the prototype or initial map from the function.
+  lw(result,
+     FieldMemOperand(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.
+  LoadRoot(t8, Heap::kTheHoleValueRootIndex);
+  Branch(miss, eq, result, Operand(t8));
+
+  // If the function does not have an initial map, we're done.
+  Label done;
+  GetObjectType(result, scratch, scratch);
+  Branch(&done, ne, scratch, Operand(MAP_TYPE));
+
+  // Get the prototype from the initial map.
+  lw(result, FieldMemOperand(result, Map::kPrototypeOffset));
+  jmp(&done);
+
+  // Non-instance prototype: Fetch prototype from constructor field
+  // in initial map.
+  bind(&non_instance);
+  lw(result, FieldMemOperand(result, Map::kConstructorOffset));
+
+  // All done.
+  bind(&done);
+}
 
 
-  void MacroAssembler::CallBuiltin(ExternalReference builtin_entry) {
-    // Load builtin address.
-    LoadExternalReference(t9, builtin_entry);
-    lw(t9, MemOperand(t9));  // Deref address.
-    addiu(t9, t9, Code::kHeaderSize - kHeapObjectTag);
-    // Call and allocate arguments slots.
-    jalr(t9);
-    // Use the branch delay slot to allocated argument slots.
-    addiu(sp, sp, -StandardFrameConstants::kRArgsSlotsSize);
-    addiu(sp, sp, StandardFrameConstants::kRArgsSlotsSize);
-  }
-
-
-  void MacroAssembler::CallBuiltin(Register target) {
-    // Target already holds target address.
-    // Call and allocate arguments slots.
-    jalr(target);
-    // Use the branch delay slot to allocated argument slots.
-    addiu(sp, sp, -StandardFrameConstants::kRArgsSlotsSize);
-    addiu(sp, sp, StandardFrameConstants::kRArgsSlotsSize);
-  }
-
-
-  void MacroAssembler::JumpToBuiltin(ExternalReference builtin_entry) {
-    // Load builtin address.
-    LoadExternalReference(t9, builtin_entry);
-    lw(t9, MemOperand(t9));  // Deref address.
-    addiu(t9, t9, Code::kHeaderSize - kHeapObjectTag);
-    // Call and allocate arguments slots.
-    jr(t9);
-    // Use the branch delay slot to allocated argument slots.
-    addiu(sp, sp, -StandardFrameConstants::kRArgsSlotsSize);
-  }
-
-
-  void MacroAssembler::JumpToBuiltin(Register target) {
-    // t9 already holds target address.
-    // Call and allocate arguments slots.
-    jr(t9);
-    // Use the branch delay slot to allocated argument slots.
-    addiu(sp, sp, -StandardFrameConstants::kRArgsSlotsSize);
-  }
+void MacroAssembler::GetObjectType(Register object,
+                                   Register map,
+                                   Register type_reg) {
+  lw(map, FieldMemOperand(object, HeapObject::kMapOffset));
+  lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
+}
 
 
 // -----------------------------------------------------------------------------
@@ -1099,8 +2487,9 @@
 }
 
 
-void MacroAssembler::StubReturn(int argc) {
-  UNIMPLEMENTED_MIPS();
+void MacroAssembler::TailCallStub(CodeStub* stub) {
+  ASSERT(allow_stub_calls());  // stub calls are not allowed in some stubs
+  Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
 }
 
 
@@ -1112,7 +2501,71 @@
 }
 
 
-void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
+void MacroAssembler::IndexFromHash(Register hash,
+                                   Register index) {
+  // If the hash field contains an array index pick it out. The assert checks
+  // that the constants for the maximum number of digits for an array index
+  // cached in the hash field and the number of bits reserved for it does not
+  // conflict.
+  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
+         (1 << String::kArrayIndexValueBits));
+  // We want the smi-tagged index in key.  kArrayIndexValueMask has zeros in
+  // the low kHashShift bits.
+  STATIC_ASSERT(kSmiTag == 0);
+  Ext(hash, hash, String::kHashShift, String::kArrayIndexValueBits);
+  sll(index, hash, kSmiTagSize);
+}
+
+
+void MacroAssembler::ObjectToDoubleFPURegister(Register object,
+                                               FPURegister result,
+                                               Register scratch1,
+                                               Register scratch2,
+                                               Register heap_number_map,
+                                               Label* not_number,
+                                               ObjectToDoubleFlags flags) {
+  Label done;
+  if ((flags & OBJECT_NOT_SMI) == 0) {
+    Label not_smi;
+    JumpIfNotSmi(object, &not_smi);
+    // Remove smi tag and convert to double.
+    sra(scratch1, object, kSmiTagSize);
+    mtc1(scratch1, result);
+    cvt_d_w(result, result);
+    Branch(&done);
+    bind(&not_smi);
+  }
+  // Check for heap number and load double value from it.
+  lw(scratch1, FieldMemOperand(object, HeapObject::kMapOffset));
+  Branch(not_number, ne, scratch1, Operand(heap_number_map));
+
+  if ((flags & AVOID_NANS_AND_INFINITIES) != 0) {
+    // If exponent is all ones the number is either a NaN or +/-Infinity.
+    Register exponent = scratch1;
+    Register mask_reg = scratch2;
+    lw(exponent, FieldMemOperand(object, HeapNumber::kExponentOffset));
+    li(mask_reg, HeapNumber::kExponentMask);
+
+    And(exponent, exponent, mask_reg);
+    Branch(not_number, eq, exponent, Operand(mask_reg));
+  }
+  ldc1(result, FieldMemOperand(object, HeapNumber::kValueOffset));
+  bind(&done);
+}
+
+
+
+void MacroAssembler::SmiToDoubleFPURegister(Register smi,
+                                            FPURegister value,
+                                            Register scratch1) {
+  sra(scratch1, smi, kSmiTagSize);
+  mtc1(scratch1, value);
+  cvt_d_w(value, value);
+}
+
+
+void MacroAssembler::CallRuntime(const Runtime::Function* f,
+                                 int num_arguments) {
   // All parameters are on the stack. v0 has the return value after call.
 
   // If the expected number of arguments of the runtime function is
@@ -1128,69 +2581,129 @@
   // should remove this need and make the runtime routine entry code
   // smarter.
   li(a0, num_arguments);
-  LoadExternalReference(a1, ExternalReference(f));
+  li(a1, Operand(ExternalReference(f, isolate())));
   CEntryStub stub(1);
   CallStub(&stub);
 }
 
 
+void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
+  const Runtime::Function* function = Runtime::FunctionForId(id);
+  li(a0, Operand(function->nargs));
+  li(a1, Operand(ExternalReference(function, isolate())));
+  CEntryStub stub(1);
+  stub.SaveDoubles();
+  CallStub(&stub);
+}
+
+
 void MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) {
   CallRuntime(Runtime::FunctionForId(fid), num_arguments);
 }
 
 
+void MacroAssembler::CallExternalReference(const ExternalReference& ext,
+                                           int num_arguments) {
+  li(a0, Operand(num_arguments));
+  li(a1, Operand(ext));
+
+  CEntryStub stub(1);
+  CallStub(&stub);
+}
+
+
 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
                                                int num_arguments,
                                                int result_size) {
-  UNIMPLEMENTED_MIPS();
+  // 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.
+  li(a0, Operand(num_arguments));
+  JumpToExternalReference(ext);
 }
 
 
 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
                                      int num_arguments,
                                      int result_size) {
-  TailCallExternalReference(ExternalReference(fid), num_arguments, result_size);
+  TailCallExternalReference(ExternalReference(fid, isolate()),
+                            num_arguments,
+                            result_size);
 }
 
 
 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-Handle<Code> MacroAssembler::ResolveBuiltin(Builtins::JavaScript id,
-                                            bool* resolved) {
-  UNIMPLEMENTED_MIPS();
-  return Handle<Code>(reinterpret_cast<Code*>(NULL));   // UNIMPLEMENTED RETURN
+  li(a1, Operand(builtin));
+  CEntryStub stub(1);
+  Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
 }
 
 
 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
-                                   InvokeJSFlags flags) {
-  UNIMPLEMENTED_MIPS();
+                                   InvokeJSFlags flags,
+                                   PostCallGenerator* post_call_generator) {
+  GetBuiltinEntry(t9, id);
+  if (flags == CALL_JS) {
+    Call(t9);
+    if (post_call_generator != NULL) post_call_generator->Generate();
+  } else {
+    ASSERT(flags == JUMP_JS);
+    Jump(t9);
+  }
+}
+
+
+void MacroAssembler::GetBuiltinFunction(Register target,
+                                        Builtins::JavaScript id) {
+  // Load the builtins object into target register.
+  lw(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
+  lw(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset));
+  // Load the JavaScript builtin function from the builtins object.
+  lw(target, FieldMemOperand(target,
+                          JSBuiltinsObject::OffsetOfFunctionWithId(id)));
 }
 
 
 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
-  UNIMPLEMENTED_MIPS();
+  ASSERT(!target.is(a1));
+  GetBuiltinFunction(a1, id);
+  // Load the code entry point from the builtins object.
+  lw(target, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
 }
 
 
 void MacroAssembler::SetCounter(StatsCounter* counter, int value,
                                 Register scratch1, Register scratch2) {
-  UNIMPLEMENTED_MIPS();
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    li(scratch1, Operand(value));
+    li(scratch2, Operand(ExternalReference(counter)));
+    sw(scratch1, MemOperand(scratch2));
+  }
 }
 
 
 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
                                       Register scratch1, Register scratch2) {
-  UNIMPLEMENTED_MIPS();
+  ASSERT(value > 0);
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    li(scratch2, Operand(ExternalReference(counter)));
+    lw(scratch1, MemOperand(scratch2));
+    Addu(scratch1, scratch1, Operand(value));
+    sw(scratch1, MemOperand(scratch2));
+  }
 }
 
 
 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
                                       Register scratch1, Register scratch2) {
-  UNIMPLEMENTED_MIPS();
+  ASSERT(value > 0);
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    li(scratch2, Operand(ExternalReference(counter)));
+    lw(scratch1, MemOperand(scratch2));
+    Subu(scratch1, scratch1, Operand(value));
+    sw(scratch1, MemOperand(scratch2));
+  }
 }
 
 
@@ -1199,30 +2712,144 @@
 
 void MacroAssembler::Assert(Condition cc, const char* msg,
                             Register rs, Operand rt) {
-  UNIMPLEMENTED_MIPS();
+  if (FLAG_debug_code)
+    Check(cc, msg, rs, rt);
+}
+
+
+void MacroAssembler::AssertRegisterIsRoot(Register reg,
+                                          Heap::RootListIndex index) {
+  if (FLAG_debug_code) {
+    LoadRoot(at, index);
+    Check(eq, "Register did not match expected root", reg, Operand(at));
+  }
+}
+
+
+void MacroAssembler::AssertFastElements(Register elements) {
+  if (FLAG_debug_code) {
+    ASSERT(!elements.is(at));
+    Label ok;
+    Push(elements);
+    lw(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
+    LoadRoot(at, Heap::kFixedArrayMapRootIndex);
+    Branch(&ok, eq, elements, Operand(at));
+    LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex);
+    Branch(&ok, eq, elements, Operand(at));
+    Abort("JSObject with fast elements map has slow elements");
+    bind(&ok);
+    Pop(elements);
+  }
 }
 
 
 void MacroAssembler::Check(Condition cc, const char* msg,
                            Register rs, Operand rt) {
-  UNIMPLEMENTED_MIPS();
+  Label L;
+  Branch(&L, cc, rs, rt);
+  Abort(msg);
+  // will not return here
+  bind(&L);
 }
 
 
 void MacroAssembler::Abort(const char* msg) {
-  UNIMPLEMENTED_MIPS();
+  Label abort_start;
+  bind(&abort_start);
+  // 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
+  // Disable stub call restrictions to always allow calls to abort.
+  AllowStubCallsScope allow_scope(this, true);
+
+  li(a0, Operand(p0));
+  Push(a0);
+  li(a0, Operand(Smi::FromInt(p1 - p0)));
+  Push(a0);
+  CallRuntime(Runtime::kAbort, 2);
+  // will not return here
+  if (is_trampoline_pool_blocked()) {
+    // If the calling code cares about the exact number of
+    // instructions generated, we insert padding here to keep the size
+    // of the Abort macro constant.
+    // Currently in debug mode with debug_code enabled the number of
+    // generated instructions is 14, so we use this as a maximum value.
+    static const int kExpectedAbortInstructions = 14;
+    int abort_instructions = InstructionsGeneratedSince(&abort_start);
+    ASSERT(abort_instructions <= kExpectedAbortInstructions);
+    while (abort_instructions++ < kExpectedAbortInstructions) {
+      nop();
+    }
+  }
+}
+
+
+void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
+  if (context_chain_length > 0) {
+    // Move up the chain of contexts to the context containing the slot.
+    lw(dst, MemOperand(cp, Context::SlotOffset(Context::CLOSURE_INDEX)));
+    // Load the function context (which is the incoming, outer context).
+    lw(dst, FieldMemOperand(dst, JSFunction::kContextOffset));
+    for (int i = 1; i < context_chain_length; i++) {
+      lw(dst, MemOperand(dst, Context::SlotOffset(Context::CLOSURE_INDEX)));
+      lw(dst, FieldMemOperand(dst, JSFunction::kContextOffset));
+    }
+    // The context may be an intermediate context, not a function context.
+    lw(dst, MemOperand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
+  } else {  // Slot is in the current function context.
+    // The context may be an intermediate context, not a function context.
+    lw(dst, MemOperand(cp, Context::SlotOffset(Context::FCONTEXT_INDEX)));
+  }
+}
+
+
+void MacroAssembler::LoadGlobalFunction(int index, Register function) {
+  // Load the global or builtins object from the current context.
+  lw(function, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
+  // Load the global context from the global or builtins object.
+  lw(function, FieldMemOperand(function,
+                               GlobalObject::kGlobalContextOffset));
+  // Load the function from the global context.
+  lw(function, MemOperand(function, Context::SlotOffset(index)));
+}
+
+
+void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
+                                                  Register map,
+                                                  Register scratch) {
+  // Load the initial map. The global functions all have initial maps.
+  lw(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
+  if (FLAG_debug_code) {
+    Label ok, fail;
+    CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, false);
+    Branch(&ok);
+    bind(&fail);
+    Abort("Global functions must have initial map");
+    bind(&ok);
+  }
 }
 
 
 void MacroAssembler::EnterFrame(StackFrame::Type type) {
   addiu(sp, sp, -5 * kPointerSize);
-  li(t0, Operand(Smi::FromInt(type)));
-  li(t1, Operand(CodeObject()));
+  li(t8, Operand(Smi::FromInt(type)));
+  li(t9, Operand(CodeObject()));
   sw(ra, MemOperand(sp, 4 * kPointerSize));
   sw(fp, MemOperand(sp, 3 * kPointerSize));
   sw(cp, MemOperand(sp, 2 * kPointerSize));
-  sw(t0, MemOperand(sp, 1 * kPointerSize));
-  sw(t1, MemOperand(sp, 0 * kPointerSize));
+  sw(t8, MemOperand(sp, 1 * kPointerSize));
+  sw(t9, MemOperand(sp, 0 * kPointerSize));
   addiu(fp, sp, 3 * kPointerSize);
 }
 
@@ -1235,62 +2862,98 @@
 }
 
 
-void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode,
-                                    Register hold_argc,
+void MacroAssembler::EnterExitFrame(Register hold_argc,
                                     Register hold_argv,
-                                    Register hold_function) {
-  // Compute the argv pointer and keep it in a callee-saved register.
+                                    Register hold_function,
+                                    bool save_doubles) {
   // a0 is argc.
-  sll(t0, a0, kPointerSizeLog2);
-  add(hold_argv, sp, t0);
-  addi(hold_argv, hold_argv, -kPointerSize);
+  sll(t8, a0, kPointerSizeLog2);
+  addu(hold_argv, sp, t8);
+  addiu(hold_argv, hold_argv, -kPointerSize);
 
   // Compute callee's stack pointer before making changes and save it as
-  // t1 register so that it is restored as sp register on exit, thereby
+  // t9 register so that it is restored as sp register on exit, thereby
   // popping the args.
-  // t1 = sp + kPointerSize * #args
-  add(t1, sp, t0);
+  // t9 = sp + kPointerSize * #args
+  addu(t9, sp, t8);
+
+  // Compute the argv pointer and keep it in a callee-saved register.
+  // This only seems to be needed for crankshaft and may cause problems
+  // so it's disabled for now.
+  // Subu(s6, t9, Operand(kPointerSize));
 
   // Align the stack at this point.
   AlignStack(0);
 
   // Save registers.
   addiu(sp, sp, -12);
-  sw(t1, MemOperand(sp, 8));
+  sw(t9, MemOperand(sp, 8));
   sw(ra, MemOperand(sp, 4));
   sw(fp, MemOperand(sp, 0));
   mov(fp, sp);  // Setup new frame pointer.
 
-  // Push debug marker.
-  if (mode == ExitFrame::MODE_DEBUG) {
-    Push(zero_reg);
-  } else {
-    li(t0, Operand(CodeObject()));
-    Push(t0);
-  }
+  li(t8, Operand(CodeObject()));
+  Push(t8);  // Accessed from ExitFrame::code_slot.
 
   // Save the frame pointer and the context in top.
-  LoadExternalReference(t0, ExternalReference(Top::k_c_entry_fp_address));
-  sw(fp, MemOperand(t0));
-  LoadExternalReference(t0, ExternalReference(Top::k_context_address));
-  sw(cp, MemOperand(t0));
+  li(t8, Operand(ExternalReference(Isolate::k_c_entry_fp_address, isolate())));
+  sw(fp, MemOperand(t8));
+  li(t8, Operand(ExternalReference(Isolate::k_context_address, isolate())));
+  sw(cp, MemOperand(t8));
 
   // Setup argc and the builtin function in callee-saved registers.
   mov(hold_argc, a0);
   mov(hold_function, a1);
+
+  // Optionally save all double registers.
+  if (save_doubles) {
+#ifdef DEBUG
+    int frame_alignment = ActivationFrameAlignment();
+#endif
+    // The stack alignment code above made sp unaligned, so add space for one
+    // more double register and use aligned addresses.
+    ASSERT(kDoubleSize == frame_alignment);
+    // Mark the frame as containing doubles by pushing a non-valid return
+    // address, i.e. 0.
+    ASSERT(ExitFrameConstants::kMarkerOffset == -2 * kPointerSize);
+    push(zero_reg);  // Marker and alignment word.
+    int space = FPURegister::kNumRegisters * kDoubleSize + kPointerSize;
+    Subu(sp, sp, Operand(space));
+    // Remember: we only need to save every 2nd double FPU value.
+    for (int i = 0; i < FPURegister::kNumRegisters; i+=2) {
+      FPURegister reg = FPURegister::from_code(i);
+      sdc1(reg, MemOperand(sp, i * kDoubleSize + kPointerSize));
+    }
+    // Note that f0 will be accessible at fp - 2*kPointerSize -
+    // FPURegister::kNumRegisters * kDoubleSize, since the code slot and the
+    // alignment word were pushed after the fp.
+  }
 }
 
 
-void MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode) {
+void MacroAssembler::LeaveExitFrame(bool save_doubles) {
+  // Optionally restore all double registers.
+  if (save_doubles) {
+    // TODO(regis): Use vldrm instruction.
+    // Remember: we only need to restore every 2nd double FPU value.
+    for (int i = 0; i < FPURegister::kNumRegisters; i+=2) {
+      FPURegister reg = FPURegister::from_code(i);
+      // Register f30-f31 is just below the marker.
+      const int offset = ExitFrameConstants::kMarkerOffset;
+      ldc1(reg, MemOperand(fp,
+          (i - FPURegister::kNumRegisters) * kDoubleSize + offset));
+    }
+  }
+
   // Clear top frame.
-  LoadExternalReference(t0, ExternalReference(Top::k_c_entry_fp_address));
-  sw(zero_reg, MemOperand(t0));
+  li(t8, Operand(ExternalReference(Isolate::k_c_entry_fp_address, isolate())));
+  sw(zero_reg, MemOperand(t8));
 
   // Restore current context from top and clear it in debug mode.
-  LoadExternalReference(t0, ExternalReference(Top::k_context_address));
-  lw(cp, MemOperand(t0));
+  li(t8, Operand(ExternalReference(Isolate::k_context_address, isolate())));
+  lw(cp, MemOperand(t8));
 #ifdef DEBUG
-  sw(a3, MemOperand(t0));
+  sw(a3, MemOperand(t8));
 #endif
 
   // Pop the arguments, restore registers, and return.
@@ -1303,24 +2966,362 @@
 }
 
 
+void MacroAssembler::InitializeNewString(Register string,
+                                         Register length,
+                                         Heap::RootListIndex map_index,
+                                         Register scratch1,
+                                         Register scratch2) {
+  sll(scratch1, length, kSmiTagSize);
+  LoadRoot(scratch2, map_index);
+  sw(scratch1, FieldMemOperand(string, String::kLengthOffset));
+  li(scratch1, Operand(String::kEmptyHashField));
+  sw(scratch2, FieldMemOperand(string, HeapObject::kMapOffset));
+  sw(scratch1, FieldMemOperand(string, String::kHashFieldOffset));
+}
+
+
+int MacroAssembler::ActivationFrameAlignment() {
+#if defined(V8_HOST_ARCH_MIPS)
+  // Running on the real platform. Use the alignment as mandated by the local
+  // environment.
+  // Note: This will break if we ever start generating snapshots on one Mips
+  // platform for another Mips platform with a different alignment.
+  return OS::ActivationFrameAlignment();
+#else  // defined(V8_HOST_ARCH_MIPS)
+  // If we are using the simulator then we should always align to the expected
+  // alignment. As the simulator is used to generate snapshots we do not know
+  // if the target platform will need alignment, so this is controlled from a
+  // flag.
+  return FLAG_sim_stack_alignment;
+#endif  // defined(V8_HOST_ARCH_MIPS)
+}
+
+
 void MacroAssembler::AlignStack(int offset) {
   // On MIPS an offset of 0 aligns to 0 modulo 8 bytes,
   //     and an offset of 1 aligns to 4 modulo 8 bytes.
+#if defined(V8_HOST_ARCH_MIPS)
+  // Running on the real platform. Use the alignment as mandated by the local
+  // environment.
+  // Note: This will break if we ever start generating snapshots on one MIPS
+  // platform for another MIPS platform with a different alignment.
   int activation_frame_alignment = OS::ActivationFrameAlignment();
+#else  // defined(V8_HOST_ARCH_MIPS)
+  // If we are using the simulator then we should always align to the expected
+  // alignment. As the simulator is used to generate snapshots we do not know
+  // if the target platform will need alignment, so we will always align at
+  // this point here.
+  int activation_frame_alignment = 2 * kPointerSize;
+#endif  // defined(V8_HOST_ARCH_MIPS)
   if (activation_frame_alignment != kPointerSize) {
     // This code needs to be made more general if this assert doesn't hold.
     ASSERT(activation_frame_alignment == 2 * kPointerSize);
     if (offset == 0) {
-      andi(t0, sp, activation_frame_alignment - 1);
-      Push(zero_reg, eq, t0, zero_reg);
+      andi(t8, sp, activation_frame_alignment - 1);
+      Push(zero_reg, eq, t8, zero_reg);
     } else {
-      andi(t0, sp, activation_frame_alignment - 1);
-      addiu(t0, t0, -4);
-      Push(zero_reg, eq, t0, zero_reg);
+      andi(t8, sp, activation_frame_alignment - 1);
+      addiu(t8, t8, -4);
+      Push(zero_reg, eq, t8, zero_reg);
     }
   }
 }
 
+
+
+void MacroAssembler::JumpIfNotPowerOfTwoOrZero(
+    Register reg,
+    Register scratch,
+    Label* not_power_of_two_or_zero) {
+  Subu(scratch, reg, Operand(1));
+  Branch(USE_DELAY_SLOT, not_power_of_two_or_zero, lt,
+         scratch, Operand(zero_reg));
+  and_(at, scratch, reg);  // In the delay slot.
+  Branch(not_power_of_two_or_zero, ne, at, Operand(zero_reg));
+}
+
+
+void MacroAssembler::JumpIfNotBothSmi(Register reg1,
+                                      Register reg2,
+                                      Label* on_not_both_smi) {
+  STATIC_ASSERT(kSmiTag == 0);
+  ASSERT_EQ(1, kSmiTagMask);
+  or_(at, reg1, reg2);
+  andi(at, at, kSmiTagMask);
+  Branch(on_not_both_smi, ne, at, Operand(zero_reg));
+}
+
+
+void MacroAssembler::JumpIfEitherSmi(Register reg1,
+                                     Register reg2,
+                                     Label* on_either_smi) {
+  STATIC_ASSERT(kSmiTag == 0);
+  ASSERT_EQ(1, kSmiTagMask);
+  // Both Smi tags must be 1 (not Smi).
+  and_(at, reg1, reg2);
+  andi(at, at, kSmiTagMask);
+  Branch(on_either_smi, eq, at, Operand(zero_reg));
+}
+
+
+void MacroAssembler::AbortIfSmi(Register object) {
+  STATIC_ASSERT(kSmiTag == 0);
+  andi(at, object, kSmiTagMask);
+  Assert(ne, "Operand is a smi", at, Operand(zero_reg));
+}
+
+
+void MacroAssembler::AbortIfNotSmi(Register object) {
+  STATIC_ASSERT(kSmiTag == 0);
+  andi(at, object, kSmiTagMask);
+  Assert(eq, "Operand is a smi", at, Operand(zero_reg));
+}
+
+
+void MacroAssembler::AbortIfNotRootValue(Register src,
+                                         Heap::RootListIndex root_value_index,
+                                         const char* message) {
+  ASSERT(!src.is(at));
+  LoadRoot(at, root_value_index);
+  Assert(eq, message, src, Operand(at));
+}
+
+
+void MacroAssembler::JumpIfNotHeapNumber(Register object,
+                                         Register heap_number_map,
+                                         Register scratch,
+                                         Label* on_not_heap_number) {
+  lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
+  AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+  Branch(on_not_heap_number, ne, scratch, Operand(heap_number_map));
+}
+
+
+void MacroAssembler::JumpIfNonSmisNotBothSequentialAsciiStrings(
+    Register first,
+    Register second,
+    Register scratch1,
+    Register scratch2,
+    Label* failure) {
+  // Test that both first and second are sequential ASCII strings.
+  // Assume that they are non-smis.
+  lw(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
+  lw(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
+  lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
+  lbu(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
+
+  JumpIfBothInstanceTypesAreNotSequentialAscii(scratch1,
+                                               scratch2,
+                                               scratch1,
+                                               scratch2,
+                                               failure);
+}
+
+
+void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first,
+                                                         Register second,
+                                                         Register scratch1,
+                                                         Register scratch2,
+                                                         Label* failure) {
+  // Check that neither is a smi.
+  STATIC_ASSERT(kSmiTag == 0);
+  And(scratch1, first, Operand(second));
+  And(scratch1, scratch1, Operand(kSmiTagMask));
+  Branch(failure, eq, scratch1, Operand(zero_reg));
+  JumpIfNonSmisNotBothSequentialAsciiStrings(first,
+                                             second,
+                                             scratch1,
+                                             scratch2,
+                                             failure);
+}
+
+
+void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii(
+    Register first,
+    Register second,
+    Register scratch1,
+    Register scratch2,
+    Label* failure) {
+  int kFlatAsciiStringMask =
+      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
+  int kFlatAsciiStringTag = ASCII_STRING_TYPE;
+  ASSERT(kFlatAsciiStringTag <= 0xffff);  // Ensure this fits 16-bit immed.
+  andi(scratch1, first, kFlatAsciiStringMask);
+  Branch(failure, ne, scratch1, Operand(kFlatAsciiStringTag));
+  andi(scratch2, second, kFlatAsciiStringMask);
+  Branch(failure, ne, scratch2, Operand(kFlatAsciiStringTag));
+}
+
+
+void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type,
+                                                            Register scratch,
+                                                            Label* failure) {
+  int kFlatAsciiStringMask =
+      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
+  int kFlatAsciiStringTag = ASCII_STRING_TYPE;
+  And(scratch, type, Operand(kFlatAsciiStringMask));
+  Branch(failure, ne, scratch, Operand(kFlatAsciiStringTag));
+}
+
+
+static const int kRegisterPassedArguments = 4;
+
+void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
+  int frame_alignment = ActivationFrameAlignment();
+
+  // Reserve space for Isolate address which is always passed as last parameter
+  num_arguments += 1;
+
+  // Up to four simple arguments are passed in registers a0..a3.
+  // Those four arguments must have reserved argument slots on the stack for
+  // mips, even though those argument slots are not normally used.
+  // Remaining arguments are pushed on the stack, above (higher address than)
+  // the argument slots.
+  ASSERT(StandardFrameConstants::kCArgsSlotsSize % kPointerSize == 0);
+  int stack_passed_arguments = ((num_arguments <= kRegisterPassedArguments) ?
+                                 0 : num_arguments - kRegisterPassedArguments) +
+                               (StandardFrameConstants::kCArgsSlotsSize /
+                               kPointerSize);
+  if (frame_alignment > kPointerSize) {
+    // Make stack end at alignment and make room for num_arguments - 4 words
+    // and the original value of sp.
+    mov(scratch, sp);
+    Subu(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize));
+    ASSERT(IsPowerOf2(frame_alignment));
+    And(sp, sp, Operand(-frame_alignment));
+    sw(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
+  } else {
+    Subu(sp, sp, Operand(stack_passed_arguments * kPointerSize));
+  }
+}
+
+
+void MacroAssembler::CallCFunction(ExternalReference function,
+                                   int num_arguments) {
+  CallCFunctionHelper(no_reg, function, at, num_arguments);
+}
+
+
+void MacroAssembler::CallCFunction(Register function,
+                                   Register scratch,
+                                   int num_arguments) {
+  CallCFunctionHelper(function,
+                      ExternalReference::the_hole_value_location(isolate()),
+                      scratch,
+                      num_arguments);
+}
+
+
+void MacroAssembler::CallCFunctionHelper(Register function,
+                                         ExternalReference function_reference,
+                                         Register scratch,
+                                         int num_arguments) {
+  // Push Isolate address as the last argument.
+  if (num_arguments < kRegisterPassedArguments) {
+    Register arg_to_reg[] = {a0, a1, a2, a3};
+    Register r = arg_to_reg[num_arguments];
+    li(r, Operand(ExternalReference::isolate_address()));
+  } else {
+    int stack_passed_arguments = num_arguments - kRegisterPassedArguments +
+                                 (StandardFrameConstants::kCArgsSlotsSize /
+                                  kPointerSize);
+    // Push Isolate address on the stack after the arguments.
+    li(scratch, Operand(ExternalReference::isolate_address()));
+    sw(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
+  }
+  num_arguments += 1;
+
+  // Make sure that the stack is aligned before calling a C function unless
+  // running in the simulator. The simulator has its own alignment check which
+  // provides more information.
+  // The argument stots are presumed to have been set up by
+  // PrepareCallCFunction. The C function must be called via t9, for mips ABI.
+
+#if defined(V8_HOST_ARCH_MIPS)
+  if (emit_debug_code()) {
+    int frame_alignment = OS::ActivationFrameAlignment();
+    int frame_alignment_mask = frame_alignment - 1;
+    if (frame_alignment > kPointerSize) {
+      ASSERT(IsPowerOf2(frame_alignment));
+      Label alignment_as_expected;
+      And(at, sp, Operand(frame_alignment_mask));
+      Branch(&alignment_as_expected, eq, at, Operand(zero_reg));
+      // Don't use Check here, as it will call Runtime_Abort possibly
+      // re-entering here.
+      stop("Unexpected alignment in CallCFunction");
+      bind(&alignment_as_expected);
+    }
+  }
+#endif  // V8_HOST_ARCH_MIPS
+
+  // Just call directly. The function called cannot cause a GC, or
+  // allow preemption, so the return address in the link register
+  // stays correct.
+  if (!function.is(t9)) {
+    mov(t9, function);
+    function = t9;
+  }
+
+  if (function.is(no_reg)) {
+    li(t9, Operand(function_reference));
+    function = t9;
+  }
+
+  Call(function);
+
+  ASSERT(StandardFrameConstants::kCArgsSlotsSize % kPointerSize == 0);
+  int stack_passed_arguments = ((num_arguments <= kRegisterPassedArguments) ?
+                                0 : num_arguments - kRegisterPassedArguments) +
+                               (StandardFrameConstants::kCArgsSlotsSize /
+                               kPointerSize);
+
+  if (OS::ActivationFrameAlignment() > kPointerSize) {
+    lw(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
+  } else {
+    Addu(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize)));
+  }
+}
+
+
+#undef BRANCH_ARGS_CHECK
+
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+CodePatcher::CodePatcher(byte* address, int instructions)
+    : address_(address),
+      instructions_(instructions),
+      size_(instructions * Assembler::kInstrSize),
+      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);
+}
+
+
+void CodePatcher::Emit(Instr x) {
+  masm()->emit(x);
+}
+
+
+void CodePatcher::Emit(Address addr) {
+  masm()->emit(reinterpret_cast<Instr>(addr));
+}
+
+
+#endif  // ENABLE_DEBUGGER_SUPPORT
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_TARGET_ARCH_MIPS
diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h
index 0f0365b..7ff9e17 100644
--- a/src/mips/macro-assembler-mips.h
+++ b/src/mips/macro-assembler-mips.h
@@ -36,69 +36,171 @@
 
 // Forward declaration.
 class JumpTarget;
+class PostCallGenerator;
 
-// Register at is used for instruction generation. So it is not safe to use it
-// unless we know exactly what we do.
+// Reserved Register Usage Summary.
+//
+// Registers t8, t9, and at are reserved for use by the MacroAssembler.
+//
+// The programmer should know that the MacroAssembler may clobber these three,
+// but won't touch other registers except in special cases.
+//
+// Per the MIPS ABI, register t9 must be used for indirect function call
+// via 'jalr t9' or 'jr t9' instructions. This is relied upon by gcc when
+// trying to update gp register for position-independent-code. Whenever
+// MIPS generated code calls C code, it must be via t9 register.
 
 // Registers aliases
 // cp is assumed to be a callee saved register.
+const Register roots = s6;  // Roots array pointer.
 const Register cp = s7;     // JavaScript context pointer
 const Register fp = s8_fp;  // Alias fp
+// Register used for condition evaluation.
+const Register condReg1 = s4;
+const Register condReg2 = s5;
 
 enum InvokeJSFlags {
   CALL_JS,
   JUMP_JS
 };
 
+
+// Flags used for the AllocateInNewSpace functions.
+enum AllocationFlags {
+  // No special flags.
+  NO_ALLOCATION_FLAGS = 0,
+  // Return the pointer to the allocated already tagged as a heap object.
+  TAG_OBJECT = 1 << 0,
+  // The content of the result register already contains the allocation top in
+  // new space.
+  RESULT_CONTAINS_TOP = 1 << 1,
+  // Specify that the requested size of the space to allocate is specified in
+  // words instead of bytes.
+  SIZE_IN_WORDS = 1 << 2
+};
+
+// Flags used for the ObjectToDoubleFPURegister function.
+enum ObjectToDoubleFlags {
+  // No special flags.
+  NO_OBJECT_TO_DOUBLE_FLAGS = 0,
+  // Object is known to be a non smi.
+  OBJECT_NOT_SMI = 1 << 0,
+  // Don't load NaNs or infinities, branch to the non number case instead.
+  AVOID_NANS_AND_INFINITIES = 1 << 1
+};
+
+// Allow programmer to use Branch Delay Slot of Branches, Jumps, Calls.
+enum BranchDelaySlot {
+  USE_DELAY_SLOT,
+  PROTECT
+};
+
 // MacroAssembler implements a collection of frequently used macros.
 class MacroAssembler: public Assembler {
  public:
   MacroAssembler(void* buffer, int size);
 
-  // Jump, Call, and Ret pseudo instructions implementing inter-working.
-  void Jump(const Operand& target,
-            Condition cond = cc_always,
-            Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg));
-  void Call(const Operand& target,
-            Condition cond = cc_always,
-            Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg));
-  void Jump(Register target,
-            Condition cond = cc_always,
-            Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg));
-  void Jump(byte* target, RelocInfo::Mode rmode,
-            Condition cond = cc_always,
-            Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg));
-  void Jump(Handle<Code> code, RelocInfo::Mode rmode,
-            Condition cond = cc_always,
-            Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg));
-  void Call(Register target,
-            Condition cond = cc_always,
-            Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg));
-  void Call(byte* target, RelocInfo::Mode rmode,
-            Condition cond = cc_always,
-            Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg));
-  void Call(Handle<Code> code, RelocInfo::Mode rmode,
-            Condition cond = cc_always,
-            Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg));
-  void Ret(Condition cond = cc_always,
-           Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg));
-  void Branch(Condition cond, int16_t offset, Register rs = zero_reg,
-              const Operand& rt = Operand(zero_reg), Register scratch = at);
-  void Branch(Condition cond, Label* L, Register rs = zero_reg,
-              const Operand& rt = Operand(zero_reg), Register scratch = at);
-  // conditionnal branch and link
-  void BranchAndLink(Condition cond, int16_t offset, Register rs = zero_reg,
-                     const Operand& rt = Operand(zero_reg),
-                     Register scratch = at);
-  void BranchAndLink(Condition cond, Label* L, Register rs = zero_reg,
-                     const Operand& rt = Operand(zero_reg),
-                     Register scratch = at);
+// Arguments macros
+#define COND_TYPED_ARGS Condition cond, Register r1, const Operand& r2
+#define COND_ARGS cond, r1, r2
+
+// ** Prototypes
+
+// * Prototypes for functions with no target (eg Ret()).
+#define DECLARE_NOTARGET_PROTOTYPE(Name) \
+  void Name(BranchDelaySlot bd = PROTECT); \
+  void Name(COND_TYPED_ARGS, BranchDelaySlot bd = PROTECT); \
+  inline void Name(BranchDelaySlot bd, COND_TYPED_ARGS) { \
+    Name(COND_ARGS, bd); \
+  }
+
+// * Prototypes for functions with a target.
+
+// Cases when relocation may be needed.
+#define DECLARE_RELOC_PROTOTYPE(Name, target_type) \
+  void Name(target_type target, \
+            RelocInfo::Mode rmode, \
+            BranchDelaySlot bd = PROTECT); \
+  inline void Name(BranchDelaySlot bd, \
+                   target_type target, \
+                   RelocInfo::Mode rmode) { \
+    Name(target, rmode, bd); \
+  } \
+  void Name(target_type target, \
+            RelocInfo::Mode rmode, \
+            COND_TYPED_ARGS, \
+            BranchDelaySlot bd = PROTECT); \
+  inline void Name(BranchDelaySlot bd, \
+                   target_type target, \
+                   RelocInfo::Mode rmode, \
+                   COND_TYPED_ARGS) { \
+    Name(target, rmode, COND_ARGS, bd); \
+  }
+
+// Cases when relocation is not needed.
+#define DECLARE_NORELOC_PROTOTYPE(Name, target_type) \
+  void Name(target_type target, BranchDelaySlot bd = PROTECT); \
+  inline void Name(BranchDelaySlot bd, target_type target) { \
+    Name(target, bd); \
+  } \
+  void Name(target_type target, \
+            COND_TYPED_ARGS, \
+            BranchDelaySlot bd = PROTECT); \
+  inline void Name(BranchDelaySlot bd, \
+                   target_type target, \
+                   COND_TYPED_ARGS) { \
+    Name(target, COND_ARGS, bd); \
+  }
+
+// ** Target prototypes.
+
+#define DECLARE_JUMP_CALL_PROTOTYPES(Name) \
+  DECLARE_NORELOC_PROTOTYPE(Name, Register) \
+  DECLARE_NORELOC_PROTOTYPE(Name, const Operand&) \
+  DECLARE_RELOC_PROTOTYPE(Name, byte*) \
+  DECLARE_RELOC_PROTOTYPE(Name, Handle<Code>)
+
+#define DECLARE_BRANCH_PROTOTYPES(Name) \
+  DECLARE_NORELOC_PROTOTYPE(Name, Label*) \
+  DECLARE_NORELOC_PROTOTYPE(Name, int16_t)
+
+
+DECLARE_JUMP_CALL_PROTOTYPES(Jump)
+DECLARE_JUMP_CALL_PROTOTYPES(Call)
+
+DECLARE_BRANCH_PROTOTYPES(Branch)
+DECLARE_BRANCH_PROTOTYPES(BranchAndLink)
+
+DECLARE_NOTARGET_PROTOTYPE(Ret)
+
+#undef COND_TYPED_ARGS
+#undef COND_ARGS
+#undef DECLARE_NOTARGET_PROTOTYPE
+#undef DECLARE_NORELOC_PROTOTYPE
+#undef DECLARE_RELOC_PROTOTYPE
+#undef DECLARE_JUMP_CALL_PROTOTYPES
+#undef DECLARE_BRANCH_PROTOTYPES
 
   // Emit code to discard a non-negative number of pointer-sized elements
   // from the stack, clobbering only the sp register.
-  void Drop(int count, Condition cond = cc_always);
+  void Drop(int count,
+            Condition cond = cc_always,
+            Register reg = no_reg,
+            const Operand& op = Operand(no_reg));
+
+  void DropAndRet(int drop = 0,
+                  Condition cond = cc_always,
+                  Register reg = no_reg,
+                  const Operand& op = Operand(no_reg));
+
+  // Swap two registers.  If the scratch register is omitted then a slightly
+  // less efficient form using xor instead of mov is emitted.
+  void Swap(Register reg1, Register reg2, Register scratch = no_reg);
 
   void Call(Label* target);
+  // May do nothing if the registers are identical.
+  void Move(Register dst, Register src);
+
 
   // Jump unconditionally to given label.
   // We NEED a nop in the branch delay slot, as it used by v8, for example in
@@ -106,7 +208,7 @@
   // Currently the branch delay slot is filled by the MacroAssembler.
   // Use rather b(Label) for code generation.
   void jmp(Label* L) {
-    Branch(cc_always, L);
+    Branch(L);
   }
 
   // Load an object from the root table.
@@ -116,19 +218,164 @@
                 Heap::RootListIndex index,
                 Condition cond, Register src1, const Operand& src2);
 
-  // Load an external reference.
-  void LoadExternalReference(Register reg, ExternalReference ext) {
-    li(reg, Operand(ext));
+  // Store an object to the root table.
+  void StoreRoot(Register source,
+                 Heap::RootListIndex index);
+  void StoreRoot(Register source,
+                 Heap::RootListIndex index,
+                 Condition cond, Register src1, const Operand& src2);
+
+
+  // Check if object is in new space.
+  // scratch can be object itself, but it will be clobbered.
+  void InNewSpace(Register object,
+                  Register scratch,
+                  Condition cc,  // eq for new space, ne otherwise.
+                  Label* branch);
+
+
+  // For the page containing |object| mark the region covering [address]
+  // dirty. The object address must be in the first 8K of an allocated page.
+  void RecordWriteHelper(Register object,
+                         Register address,
+                         Register scratch);
+
+  // For the page containing |object| mark the region covering
+  // [object+offset] dirty. The object address must be in the first 8K
+  // of an allocated page.  The 'scratch' registers are used in the
+  // implementation and all 3 registers are clobbered by the
+  // operation, as well as the 'at' register. RecordWrite updates the
+  // write barrier even when storing smis.
+  void RecordWrite(Register object,
+                   Operand offset,
+                   Register scratch0,
+                   Register scratch1);
+
+  // For the page containing |object| mark the region covering
+  // [address] dirty. The object address must be in the first 8K of an
+  // allocated page.  All 3 registers are clobbered by the operation,
+  // as well as the ip register. RecordWrite updates the write barrier
+  // even when storing smis.
+  void RecordWrite(Register object,
+                   Register address,
+                   Register scratch);
+
+
+  // ---------------------------------------------------------------------------
+  // Inline caching support
+
+  // 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);
+
+  inline void MarkCode(NopMarkerTypes type) {
+    nop(type);
   }
 
-  // Sets the remembered set bit for [address+offset].
-  void RecordWrite(Register object, Register offset, Register scratch);
+  // Check if the given instruction is a 'type' marker.
+  // ie. check if it is a sll zero_reg, zero_reg, <type> (referenced as
+  // nop(type)). These instructions are generated to mark special location in
+  // the code, like some special IC code.
+  static inline bool IsMarkedCode(Instr instr, int type) {
+    ASSERT((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
+    return IsNop(instr, type);
+  }
 
 
+  static inline int GetCodeMarker(Instr instr) {
+    uint32_t opcode = ((instr & kOpcodeMask));
+    uint32_t rt = ((instr & kRtFieldMask) >> kRtShift);
+    uint32_t rs = ((instr & kRsFieldMask) >> kRsShift);
+    uint32_t sa = ((instr & kSaFieldMask) >> kSaShift);
+
+    // Return <n> if we have a sll zero_reg, zero_reg, n
+    // else return -1.
+    bool sllzz = (opcode == SLL &&
+                  rt == static_cast<uint32_t>(ToNumber(zero_reg)) &&
+                  rs == static_cast<uint32_t>(ToNumber(zero_reg)));
+    int type =
+        (sllzz && FIRST_IC_MARKER <= sa && sa < LAST_CODE_MARKER) ? sa : -1;
+    ASSERT((type == -1) ||
+           ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
+    return type;
+  }
+
+
+
+  // ---------------------------------------------------------------------------
+  // Allocation support
+
+  // Allocate an object in new space. The object_size is specified
+  // either in bytes or in words if the allocation flag SIZE_IN_WORDS
+  // is passed. If the new space is exhausted control continues at the
+  // gc_required label. The allocated object is returned in result. If
+  // the flag tag_allocated_object is true the result is tagged as as
+  // a heap object. All registers are clobbered also when control
+  // continues at the gc_required label.
+  void AllocateInNewSpace(int object_size,
+                          Register result,
+                          Register scratch1,
+                          Register scratch2,
+                          Label* gc_required,
+                          AllocationFlags flags);
+  void AllocateInNewSpace(Register object_size,
+                          Register result,
+                          Register scratch1,
+                          Register scratch2,
+                          Label* gc_required,
+                          AllocationFlags flags);
+
+  // Undo allocation in new space. The object passed and objects allocated after
+  // it will no longer be allocated. The caller must make sure that no pointers
+  // are left to the object(s) no longer allocated as they would be invalid when
+  // allocation is undone.
+  void UndoAllocationInNewSpace(Register object, Register scratch);
+
+
+  void AllocateTwoByteString(Register result,
+                             Register length,
+                             Register scratch1,
+                             Register scratch2,
+                             Register scratch3,
+                             Label* gc_required);
+  void AllocateAsciiString(Register result,
+                           Register length,
+                           Register scratch1,
+                           Register scratch2,
+                           Register scratch3,
+                           Label* gc_required);
+  void AllocateTwoByteConsString(Register result,
+                                 Register length,
+                                 Register scratch1,
+                                 Register scratch2,
+                                 Label* gc_required);
+  void AllocateAsciiConsString(Register result,
+                               Register length,
+                               Register scratch1,
+                               Register scratch2,
+                               Label* gc_required);
+
+  // Allocates a heap number or jumps to the gc_required label if the young
+  // space is full and a scavenge is needed. All registers are clobbered also
+  // when control continues at the gc_required label.
+  void AllocateHeapNumber(Register result,
+                          Register scratch1,
+                          Register scratch2,
+                          Register heap_number_map,
+                          Label* gc_required);
+  void AllocateHeapNumberWithValue(Register result,
+                                   FPURegister value,
+                                   Register scratch1,
+                                   Register scratch2,
+                                   Label* gc_required);
+
   // ---------------------------------------------------------------------------
   // Instruction macros
 
-#define DEFINE_INSTRUCTION(instr)                                       \
+#define DEFINE_INSTRUCTION(instr)                                              \
   void instr(Register rd, Register rs, const Operand& rt);                     \
   void instr(Register rd, Register rs, Register rt) {                          \
     instr(rd, rs, Operand(rt));                                                \
@@ -137,7 +384,7 @@
     instr(rs, rt, Operand(j));                                                 \
   }
 
-#define DEFINE_INSTRUCTION2(instr)                                      \
+#define DEFINE_INSTRUCTION2(instr)                                             \
   void instr(Register rs, const Operand& rt);                                  \
   void instr(Register rs, Register rt) {                                       \
     instr(rs, Operand(rt));                                                    \
@@ -146,8 +393,8 @@
     instr(rs, Operand(j));                                                     \
   }
 
-  DEFINE_INSTRUCTION(Add);
   DEFINE_INSTRUCTION(Addu);
+  DEFINE_INSTRUCTION(Subu);
   DEFINE_INSTRUCTION(Mul);
   DEFINE_INSTRUCTION2(Mult);
   DEFINE_INSTRUCTION2(Multu);
@@ -162,6 +409,9 @@
   DEFINE_INSTRUCTION(Slt);
   DEFINE_INSTRUCTION(Sltu);
 
+  // MIPS32 R2 instruction macro.
+  DEFINE_INSTRUCTION(Ror);
+
 #undef DEFINE_INSTRUCTION
 #undef DEFINE_INSTRUCTION2
 
@@ -169,8 +419,6 @@
   //------------Pseudo-instructions-------------
 
   void mov(Register rd, Register rt) { or_(rd, rt, zero_reg); }
-  // Move the logical ones complement of source to dest.
-  void movn(Register rd, Register rt);
 
 
   // load int32 in the rd register
@@ -178,6 +426,9 @@
   inline void li(Register rd, int32_t j, bool gen2instr = false) {
     li(rd, Operand(j), gen2instr);
   }
+  inline void li(Register dst, Handle<Object> value, bool gen2instr = false) {
+    li(dst, Operand(value), gen2instr);
+  }
 
   // Exception-generating instructions and debugging support
   void stop(const char* msg);
@@ -188,19 +439,51 @@
   // saved in higher memory addresses
   void MultiPush(RegList regs);
   void MultiPushReversed(RegList regs);
+
   void Push(Register src) {
     Addu(sp, sp, Operand(-kPointerSize));
     sw(src, MemOperand(sp, 0));
   }
+
+  // Push two registers.  Pushes leftmost register first (to highest address).
+  void Push(Register src1, Register src2, Condition cond = al) {
+    ASSERT(cond == al);  // Do not support conditional versions yet.
+    Subu(sp, sp, Operand(2 * kPointerSize));
+    sw(src1, MemOperand(sp, 1 * kPointerSize));
+    sw(src2, MemOperand(sp, 0 * kPointerSize));
+  }
+
+  // Push three registers.  Pushes leftmost register first (to highest address).
+  void Push(Register src1, Register src2, Register src3, Condition cond = al) {
+    ASSERT(cond == al);  // Do not support conditional versions yet.
+    Addu(sp, sp, Operand(3 * -kPointerSize));
+    sw(src1, MemOperand(sp, 2 * kPointerSize));
+    sw(src2, MemOperand(sp, 1 * kPointerSize));
+    sw(src3, MemOperand(sp, 0 * kPointerSize));
+  }
+
+  // Push four registers.  Pushes leftmost register first (to highest address).
+  void Push(Register src1, Register src2,
+            Register src3, Register src4, Condition cond = al) {
+    ASSERT(cond == al);  // Do not support conditional versions yet.
+    Addu(sp, sp, Operand(4 * -kPointerSize));
+    sw(src1, MemOperand(sp, 3 * kPointerSize));
+    sw(src2, MemOperand(sp, 2 * kPointerSize));
+    sw(src3, MemOperand(sp, 1 * kPointerSize));
+    sw(src4, MemOperand(sp, 0 * kPointerSize));
+  }
+
   inline void push(Register src) { Push(src); }
+  inline void pop(Register src) { Pop(src); }
 
   void Push(Register src, Condition cond, Register tst1, Register tst2) {
     // Since we don't have conditionnal execution we use a Branch.
-    Branch(cond, 3, tst1, Operand(tst2));
+    Branch(3, cond, tst1, Operand(tst2));
     Addu(sp, sp, Operand(-kPointerSize));
     sw(src, MemOperand(sp, 0));
   }
 
+
   // Pops multiple values from the stack and load them in the
   // registers specified in regs. Pop order is the opposite as in MultiPush.
   void MultiPop(RegList regs);
@@ -209,44 +492,108 @@
     lw(dst, MemOperand(sp, 0));
     Addu(sp, sp, Operand(kPointerSize));
   }
-  void Pop() {
-    Add(sp, sp, Operand(kPointerSize));
+  void Pop(uint32_t count = 1) {
+    Addu(sp, sp, Operand(count * kPointerSize));
   }
 
+  // ---------------------------------------------------------------------------
+  // These functions are only used by crankshaft, so they are currently
+  // unimplemented.
+
+  // Push and pop the registers that can hold pointers, as defined by the
+  // RegList constant kSafepointSavedRegisters.
+  void PushSafepointRegisters() {
+    UNIMPLEMENTED_MIPS();
+  }
+
+  void PopSafepointRegisters() {
+    UNIMPLEMENTED_MIPS();
+  }
+
+  void PushSafepointRegistersAndDoubles() {
+    UNIMPLEMENTED_MIPS();
+  }
+
+  void PopSafepointRegistersAndDoubles() {
+    UNIMPLEMENTED_MIPS();
+  }
+
+  static int SafepointRegisterStackIndex(int reg_code) {
+    UNIMPLEMENTED_MIPS();
+    return 0;
+  }
 
   // ---------------------------------------------------------------------------
+
+  // MIPS32 R2 instruction macro.
+  void Ins(Register rt, Register rs, uint16_t pos, uint16_t size);
+  void Ext(Register rt, Register rs, uint16_t pos, uint16_t size);
+
+  // Convert unsigned word to double.
+  void Cvt_d_uw(FPURegister fd, FPURegister fs);
+  void Cvt_d_uw(FPURegister fd, Register rs);
+
+  // Convert double to unsigned word.
+  void Trunc_uw_d(FPURegister fd, FPURegister fs);
+  void Trunc_uw_d(FPURegister fd, Register rs);
+
+  // Convert the HeapNumber pointed to by source to a 32bits signed integer
+  // dest. If the HeapNumber does not fit into a 32bits signed integer branch
+  // to not_int32 label. If FPU is available double_scratch is used but not
+  // scratch2.
+  void ConvertToInt32(Register source,
+                      Register dest,
+                      Register scratch,
+                      Register scratch2,
+                      FPURegister double_scratch,
+                      Label *not_int32);
+
+  // -------------------------------------------------------------------------
   // Activation frames
 
   void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
   void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
 
-  // Enter specific kind of exit frame; either EXIT or
-  // EXIT_DEBUG. Expects the number of arguments in register a0 and
+  void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
+  void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
+
+  // Enter exit frame.
+  // Expects the number of arguments in register a0 and
   // the builtin function to call in register a1.
   // On output hold_argc, hold_function, and hold_argv are setup.
-  void EnterExitFrame(ExitFrame::Mode mode,
-                      Register hold_argc,
+  void EnterExitFrame(Register hold_argc,
                       Register hold_argv,
-                      Register hold_function);
+                      Register hold_function,
+                      bool save_doubles);
 
   // Leave the current exit frame. Expects the return value in v0.
-  void LeaveExitFrame(ExitFrame::Mode mode);
+  void LeaveExitFrame(bool save_doubles);
 
   // Align the stack by optionally pushing a Smi zero.
-  void AlignStack(int offset);
+  void AlignStack(int offset);    // TODO(mips) : remove this function.
 
-  void SetupAlignedCall(Register scratch, int arg_count = 0);
-  void ReturnFromAlignedCall();
+  // Get the actual activation frame alignment for target environment.
+  static int ActivationFrameAlignment();
 
+  void LoadContext(Register dst, int context_chain_length);
 
-  // ---------------------------------------------------------------------------
+  void LoadGlobalFunction(int index, Register function);
+
+  // Load the initial map from the global function. The registers
+  // function and map can be the same, function is then overwritten.
+  void LoadGlobalFunctionInitialMap(Register function,
+                                    Register map,
+                                    Register scratch);
+
+  // -------------------------------------------------------------------------
   // JavaScript invokes
 
   // Invoke the JavaScript function code by either calling or jumping.
   void InvokeCode(Register code,
                   const ParameterCount& expected,
                   const ParameterCount& actual,
-                  InvokeFlag flag);
+                  InvokeFlag flag,
+                  PostCallGenerator* post_call_generator = NULL);
 
   void InvokeCode(Handle<Code> code,
                   const ParameterCount& expected,
@@ -258,84 +605,135 @@
   // current context to the context in the function before invoking.
   void InvokeFunction(Register function,
                       const ParameterCount& actual,
+                      InvokeFlag flag,
+                      PostCallGenerator* post_call_generator = NULL);
+
+  void InvokeFunction(JSFunction* function,
+                      const ParameterCount& actual,
                       InvokeFlag flag);
 
 
+  void IsObjectJSObjectType(Register heap_object,
+                            Register map,
+                            Register scratch,
+                            Label* fail);
+
+  void IsInstanceJSObjectType(Register map,
+                              Register scratch,
+                              Label* fail);
+
+  void IsObjectJSStringType(Register object,
+                            Register scratch,
+                            Label* fail);
+
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  // ---------------------------------------------------------------------------
+  // -------------------------------------------------------------------------
   // Debugger Support
 
-  void SaveRegistersToMemory(RegList regs);
-  void RestoreRegistersFromMemory(RegList regs);
-  void CopyRegistersFromMemoryToStack(Register base, RegList regs);
-  void CopyRegistersFromStackToMemory(Register base,
-                                      Register scratch,
-                                      RegList regs);
   void DebugBreak();
 #endif
 
 
-  // ---------------------------------------------------------------------------
+  // -------------------------------------------------------------------------
   // Exception handling
 
   // Push a new try handler and link into try handler chain.
   // The return address must be passed in register ra.
+  // Clobber t0, t1, t2.
   void PushTryHandler(CodeLocation try_location, HandlerType type);
 
   // Unlink the stack handler on top of the stack from the try handler chain.
   // Must preserve the result register.
   void PopTryHandler();
 
+  // Copies a fixed number of fields of heap objects from src to dst.
+  void CopyFields(Register dst, Register src, RegList temps, int field_count);
 
-  // ---------------------------------------------------------------------------
+  // -------------------------------------------------------------------------
   // Support functions.
 
+  // 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);
+
   void GetObjectType(Register function,
                      Register map,
                      Register type_reg);
 
-  inline void BranchOnSmi(Register value, Label* smi_label,
-                          Register scratch = at) {
-    ASSERT_EQ(0, kSmiTag);
-    andi(scratch, value, kSmiTagMask);
-    Branch(eq, smi_label, scratch, Operand(zero_reg));
-  }
+  // Check if the map of an object is equal to a specified map (either
+  // given directly or as an index into the root list) and branch to
+  // label if not. Skip the smi check if not required (object is known
+  // to be a heap object)
+  void CheckMap(Register obj,
+                Register scratch,
+                Handle<Map> map,
+                Label* fail,
+                bool is_heap_object);
 
-
-  inline void BranchOnNotSmi(Register value, Label* not_smi_label,
-                             Register scratch = at) {
-    ASSERT_EQ(0, kSmiTag);
-    andi(scratch, value, kSmiTagMask);
-    Branch(ne, not_smi_label, scratch, Operand(zero_reg));
-  }
-
-  void CallBuiltin(ExternalReference builtin_entry);
-  void CallBuiltin(Register target);
-  void JumpToBuiltin(ExternalReference builtin_entry);
-  void JumpToBuiltin(Register target);
+  void CheckMap(Register obj,
+                Register scratch,
+                Heap::RootListIndex index,
+                Label* fail,
+                bool is_heap_object);
 
   // Generates code for reporting that an illegal operation has
   // occurred.
   void IllegalOperation(int num_arguments);
 
+  // Picks out an array index from the hash field.
+  // Register use:
+  //   hash - holds the index's hash. Clobbered.
+  //   index - holds the overwritten index on exit.
+  void IndexFromHash(Register hash, Register index);
 
-  // ---------------------------------------------------------------------------
+  // Load the value of a number object into a FPU double register. If the
+  // object is not a number a jump to the label not_number is performed
+  // and the FPU double register is unchanged.
+  void ObjectToDoubleFPURegister(
+      Register object,
+      FPURegister value,
+      Register scratch1,
+      Register scratch2,
+      Register heap_number_map,
+      Label* not_number,
+      ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS);
+
+  // Load the value of a smi object into a FPU double register. The register
+  // scratch1 can be the same register as smi in which case smi will hold the
+  // untagged value afterwards.
+  void SmiToDoubleFPURegister(Register smi,
+                              FPURegister value,
+                              Register scratch1);
+
+  // -------------------------------------------------------------------------
   // Runtime calls
 
   // Call a code stub.
   void CallStub(CodeStub* stub, Condition cond = cc_always,
                 Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg));
+
+  // Tail call a code stub (jump).
+  void TailCallStub(CodeStub* stub);
+
   void CallJSExitStub(CodeStub* stub);
 
-  // Return from a code stub after popping its arguments.
-  void StubReturn(int argc);
-
   // Call a runtime routine.
-  void CallRuntime(Runtime::Function* f, int num_arguments);
+  void CallRuntime(const Runtime::Function* f, int num_arguments);
+  void CallRuntimeSaveDoubles(Runtime::FunctionId id);
 
   // Convenience function: Same as above, but takes the fid instead.
   void CallRuntime(Runtime::FunctionId fid, int num_arguments);
 
+  // Convenience function: call an external reference.
+  void CallExternalReference(const ExternalReference& ext,
+                             int num_arguments);
+
   // Tail call of a runtime routine (jump).
   // Like JumpToExternalReference, but also takes care of passing the number
   // of parameters.
@@ -348,34 +746,54 @@
                        int num_arguments,
                        int result_size);
 
+  // Before calling a C-function from generated code, align arguments on stack
+  // and add space for the four mips argument slots.
+  // After aligning the frame, non-register arguments must be stored on the
+  // stack, after the argument-slots using helper: CFunctionArgumentOperand().
+  // 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.
+  void PrepareCallCFunction(int num_arguments, Register scratch);
+
+  // Arguments 1-4 are placed in registers a0 thru a3 respectively.
+  // Arguments 5..n are stored to stack using following:
+  //  sw(t0, CFunctionArgumentOperand(5));
+
+  // Calls a C function and cleans up the space for arguments allocated
+  // by PrepareCallCFunction. 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 by the called
+  // function).
+  void CallCFunction(ExternalReference function, int num_arguments);
+  void CallCFunction(Register function, Register scratch, int num_arguments);
+
   // Jump to the builtin routine.
   void JumpToExternalReference(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);
+  void InvokeBuiltin(Builtins::JavaScript id,
+                     InvokeJSFlags flags,
+                     PostCallGenerator* post_call_generator = NULL);
 
   // Store the code object for the given builtin in the target register and
-  // setup the function in r1.
+  // setup the function in a1.
   void GetBuiltinEntry(Register target, Builtins::JavaScript id);
 
+  // Store the function for the given builtin in the target register.
+  void GetBuiltinFunction(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_; }
 
-
-  // ---------------------------------------------------------------------------
-  // Stack limit support
-
-  void StackLimitCheck(Label* on_stack_limit_hit);
-
-
-  // ---------------------------------------------------------------------------
+  // -------------------------------------------------------------------------
   // StatsCounter support
 
   void SetCounter(StatsCounter* counter, int value,
@@ -386,12 +804,14 @@
                         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, Register rs, Operand rt);
+  void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index);
+  void AssertFastElements(Register elements);
 
   // Like Assert(), but always enabled.
   void Check(Condition cc, const char* msg, Register rs, Operand rt);
@@ -405,17 +825,132 @@
   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_;
-  // This handle will be patched with the code object on installation.
-  Handle<Object> code_object_;
+  // ---------------------------------------------------------------------------
+  // Number utilities
 
+  // Check whether the value of reg is a power of two and not zero. If not
+  // control continues at the label not_power_of_two. If reg is a power of two
+  // the register scratch contains the value of (reg - 1) when control falls
+  // through.
+  void JumpIfNotPowerOfTwoOrZero(Register reg,
+                                 Register scratch,
+                                 Label* not_power_of_two_or_zero);
+
+  // -------------------------------------------------------------------------
+  // Smi utilities
+
+  // Try to convert int32 to smi. If the value is to large, preserve
+  // the original value and jump to not_a_smi. Destroys scratch and
+  // sets flags.
+  // This is only used by crankshaft atm so it is unimplemented on MIPS.
+  void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) {
+    UNIMPLEMENTED_MIPS();
+  }
+
+  void SmiTag(Register reg) {
+    Addu(reg, reg, reg);
+  }
+
+  void SmiTag(Register dst, Register src) {
+    Addu(dst, src, src);
+  }
+
+  void SmiUntag(Register reg) {
+    sra(reg, reg, kSmiTagSize);
+  }
+
+  void SmiUntag(Register dst, Register src) {
+    sra(dst, src, kSmiTagSize);
+  }
+
+  // Jump the register contains a smi.
+  inline void JumpIfSmi(Register value, Label* smi_label,
+                        Register scratch = at) {
+    ASSERT_EQ(0, kSmiTag);
+    andi(scratch, value, kSmiTagMask);
+    Branch(smi_label, eq, scratch, Operand(zero_reg));
+  }
+
+  // Jump if the register contains a non-smi.
+  inline void JumpIfNotSmi(Register value, Label* not_smi_label,
+                           Register scratch = at) {
+    ASSERT_EQ(0, kSmiTag);
+    andi(scratch, value, kSmiTagMask);
+    Branch(not_smi_label, ne, scratch, Operand(zero_reg));
+  }
+
+  // Jump if either of the registers contain a non-smi.
+  void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
+  // Jump if either of the registers contain a smi.
+  void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
+
+  // Abort execution if argument is a smi. Used in debug code.
+  void AbortIfSmi(Register object);
+  void AbortIfNotSmi(Register object);
+
+  // Abort execution if argument is not the root value with the given index.
+  void AbortIfNotRootValue(Register src,
+                           Heap::RootListIndex root_value_index,
+                           const char* message);
+
+  // ---------------------------------------------------------------------------
+  // HeapNumber utilities
+
+  void JumpIfNotHeapNumber(Register object,
+                           Register heap_number_map,
+                           Register scratch,
+                           Label* on_not_heap_number);
+
+  // -------------------------------------------------------------------------
+  // String utilities
+
+  // Checks if both instance types are sequential ASCII strings and jumps to
+  // label if either is not.
+  void JumpIfBothInstanceTypesAreNotSequentialAscii(
+      Register first_object_instance_type,
+      Register second_object_instance_type,
+      Register scratch1,
+      Register scratch2,
+      Label* failure);
+
+  // Check if instance type is sequential ASCII string and jump to label if
+  // it is not.
+  void JumpIfInstanceTypeIsNotSequentialAscii(Register type,
+                                              Register scratch,
+                                              Label* failure);
+
+  // Test that both first and second are sequential ASCII strings.
+  // Assume that they are non-smis.
+  void JumpIfNonSmisNotBothSequentialAsciiStrings(Register first,
+                                                  Register second,
+                                                  Register scratch1,
+                                                  Register scratch2,
+                                                  Label* failure);
+
+  // Test that both first and second are sequential ASCII strings.
+  // Check that they are non-smis.
+  void JumpIfNotBothSequentialAsciiStrings(Register first,
+                                           Register second,
+                                           Register scratch1,
+                                           Register scratch2,
+                                           Label* failure);
+
+ private:
+  void CallCFunctionHelper(Register function,
+                           ExternalReference function_reference,
+                           Register scratch,
+                           int num_arguments);
+
+  void Jump(intptr_t target, RelocInfo::Mode rmode,
+            BranchDelaySlot bd = PROTECT);
   void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = cc_always,
-            Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg));
+            Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg),
+            BranchDelaySlot bd = PROTECT);
+  void Call(intptr_t target, RelocInfo::Mode rmode,
+            BranchDelaySlot bd = PROTECT);
   void Call(intptr_t target, RelocInfo::Mode rmode, Condition cond = cc_always,
-            Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg));
+            Register r1 = zero_reg, const Operand& r2 = Operand(zero_reg),
+            BranchDelaySlot bd = PROTECT);
 
   // Helper functions for generating invokes.
   void InvokePrologue(const ParameterCount& expected,
@@ -423,22 +958,84 @@
                       Handle<Code> code_constant,
                       Register code_reg,
                       Label* done,
-                      InvokeFlag flag);
+                      InvokeFlag flag,
+                      PostCallGenerator* post_call_generator = NULL);
 
   // 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.
-  // EnterFrame clobbers t0 and t1.
   void EnterFrame(StackFrame::Type type);
   void LeaveFrame(StackFrame::Type type);
+
+  void InitializeNewString(Register string,
+                           Register length,
+                           Heap::RootListIndex map_index,
+                           Register scratch1,
+                           Register scratch2);
+
+
+  bool generating_stub_;
+  bool allow_stub_calls_;
+  // This handle will be patched with the code object on installation.
+  Handle<Object> code_object_;
+};
+
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+// 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. It is not legal to emit
+// relocation information. If any of these constraints are violated it causes
+// an assertion to fail.
+class CodePatcher {
+ public:
+  CodePatcher(byte* address, int instructions);
+  virtual ~CodePatcher();
+
+  // Macro assembler to emit code.
+  MacroAssembler* masm() { return &masm_; }
+
+  // Emit an instruction directly.
+  void Emit(Instr x);
+
+  // Emit an address directly.
+  void Emit(Address addr);
+
+ private:
+  byte* address_;  // The address of the code being patched.
+  int instructions_;  // Number of instructions of the expected patch size.
+  int size_;  // Number of bytes of the expected patch size.
+  MacroAssembler masm_;  // Macro assembler used to generate the code.
+};
+#endif  // ENABLE_DEBUGGER_SUPPORT
+
+
+// Helper class for generating code or data associated with the code
+// right after a call instruction. As an example this can be used to
+// generate safepoint data after calls for crankshaft.
+class PostCallGenerator {
+ public:
+  PostCallGenerator() { }
+  virtual ~PostCallGenerator() { }
+  virtual void Generate() = 0;
 };
 
 
 // -----------------------------------------------------------------------------
 // Static helper functions.
 
+static MemOperand ContextOperand(Register context, int index) {
+  return MemOperand(context, Context::SlotOffset(index));
+}
+
+
+static inline MemOperand GlobalObjectOperand()  {
+  return ContextOperand(cp, Context::GLOBAL_INDEX);
+}
+
+
 // Generate a MemOperand for loading a field from an object.
 static inline MemOperand FieldMemOperand(Register object, int offset) {
   return MemOperand(object, offset - kHeapObjectTag);
diff --git a/src/mips/regexp-macro-assembler-mips.cc b/src/mips/regexp-macro-assembler-mips.cc
new file mode 100644
index 0000000..d1dbc43
--- /dev/null
+++ b/src/mips/regexp-macro-assembler-mips.cc
@@ -0,0 +1,478 @@
+// Copyright 2006-2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#if defined(V8_TARGET_ARCH_MIPS)
+
+#include "unicode.h"
+#include "log.h"
+#include "code-stubs.h"
+#include "regexp-stack.h"
+#include "macro-assembler.h"
+#include "regexp-macro-assembler.h"
+#include "mips/regexp-macro-assembler-mips.h"
+
+namespace v8 {
+namespace internal {
+
+#ifndef V8_INTERPRETED_REGEXP
+/*
+ * This assembler uses the following register assignment convention
+ * - t1 : Pointer to current code object (Code*) including heap object tag.
+ * - t2 : Current position in input, as negative offset from end of string.
+ *        Please notice that this is the byte offset, not the character offset!
+ * - t3 : Currently loaded character. Must be loaded using
+ *        LoadCurrentCharacter before using any of the dispatch methods.
+ * - t4 : points to tip of backtrack stack
+ * - t5 : Unused.
+ * - t6 : End of input (points to byte after last character in input).
+ * - fp : Frame pointer. Used to access arguments, local variables and
+ *         RegExp registers.
+ * - sp : points to tip of C stack.
+ *
+ * The remaining registers are free for computations.
+ *
+ * Each call to a public method should retain this convention.
+ * The stack will have the following structure:
+ *       - direct_call        (if 1, direct call from JavaScript code, if 0 call
+ *                             through the runtime system)
+ *       - stack_area_base    (High end of the memory area to use as
+ *                             backtracking stack)
+ *       - int* capture_array (int[num_saved_registers_], for output).
+ *       - stack frame header (16 bytes in size)
+ *       --- sp when called ---
+ *       - link address
+ *       - backup of registers s0..s7
+ *       - end of input       (Address of end of string)
+ *       - start of input     (Address of first character in string)
+ *       - start index        (character index of start)
+ *       --- frame pointer ----
+ *       - void* input_string (location of a handle containing the string)
+ *       - Offset of location before start of input (effectively character
+ *         position -1). Used to initialize capture registers to a non-position.
+ *       - At start (if 1, we are starting at the start of the
+ *         string, otherwise 0)
+ *       - register 0         (Only positions must be stored in the first
+ *       - register 1          num_saved_registers_ registers)
+ *       - ...
+ *       - register num_registers-1
+ *       --- sp ---
+ *
+ * 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 start out as garbage.
+ *
+ * The data up to the return address must be placed there by the calling
+ * code, by calling the code entry as cast to a function with the signature:
+ * int (*match)(String* input_string,
+ *              int start_index,
+ *              Address start,
+ *              Address end,
+ *              int* capture_output_array,
+ *              bool at_start,
+ *              byte* stack_area_base,
+ *              bool direct_call)
+ * The call is performed by NativeRegExpMacroAssembler::Execute()
+ * (in regexp-macro-assembler.cc).
+ */
+
+#define __ ACCESS_MASM(masm_)
+
+RegExpMacroAssemblerMIPS::RegExpMacroAssemblerMIPS(
+    Mode mode,
+    int registers_to_save)
+    : masm_(new MacroAssembler(NULL, kRegExpCodeSize)),
+      mode_(mode),
+      num_registers_(registers_to_save),
+      num_saved_registers_(registers_to_save),
+      entry_label_(),
+      start_label_(),
+      success_label_(),
+      backtrack_label_(),
+      exit_label_() {
+  ASSERT_EQ(0, registers_to_save % 2);
+  __ jmp(&entry_label_);   // We'll write the entry code later.
+  __ bind(&start_label_);  // And then continue from here.
+}
+
+
+RegExpMacroAssemblerMIPS::~RegExpMacroAssemblerMIPS() {
+  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 RegExpMacroAssemblerMIPS::stack_limit_slack()  {
+  return RegExpStack::kStackLimitSlack;
+}
+
+
+void RegExpMacroAssemblerMIPS::AdvanceCurrentPosition(int by) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::AdvanceRegister(int reg, int by) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::Backtrack() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::Bind(Label* label) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckCharacter(uint32_t c, Label* on_equal) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckCharacterGT(uc16 limit, Label* on_greater) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckAtStart(Label* on_at_start) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckNotAtStart(Label* on_not_at_start) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckCharacterLT(uc16 limit, Label* on_less) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckCharacters(Vector<const uc16> str,
+                                              int cp_offset,
+                                              Label* on_failure,
+                                              bool check_end_of_string) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckGreedyLoop(Label* on_equal) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckNotBackReferenceIgnoreCase(
+    int start_reg,
+    Label* on_no_match) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckNotBackReference(
+    int start_reg,
+    Label* on_no_match) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckNotRegistersEqual(int reg1,
+                                                      int reg2,
+                                                      Label* on_not_equal) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckNotCharacter(uint32_t c,
+                                                Label* on_not_equal) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckCharacterAfterAnd(uint32_t c,
+                                                     uint32_t mask,
+                                                     Label* on_equal) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterAnd(uint32_t c,
+                                                        uint32_t mask,
+                                                        Label* on_not_equal) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterMinusAnd(
+    uc16 c,
+    uc16 minus,
+    uc16 mask,
+    Label* on_not_equal) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+bool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(uc16 type,
+                                                         Label* on_no_match) {
+  UNIMPLEMENTED_MIPS();
+  return false;
+}
+
+
+void RegExpMacroAssemblerMIPS::Fail() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+Handle<Object> RegExpMacroAssemblerMIPS::GetCode(Handle<String> source) {
+  UNIMPLEMENTED_MIPS();
+  return Handle<Object>::null();
+}
+
+
+void RegExpMacroAssemblerMIPS::GoTo(Label* to) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::IfRegisterGE(int reg,
+                                           int comparand,
+                                           Label* if_ge) {
+  __ lw(a0, register_location(reg));
+    BranchOrBacktrack(if_ge, ge, a0, Operand(comparand));
+}
+
+
+void RegExpMacroAssemblerMIPS::IfRegisterLT(int reg,
+                                           int comparand,
+                                           Label* if_lt) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::IfRegisterEqPos(int reg,
+                                              Label* if_eq) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+RegExpMacroAssembler::IrregexpImplementation
+    RegExpMacroAssemblerMIPS::Implementation() {
+  return kMIPSImplementation;
+}
+
+
+void RegExpMacroAssemblerMIPS::LoadCurrentCharacter(int cp_offset,
+                                                   Label* on_end_of_input,
+                                                   bool check_bounds,
+                                                   int characters) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::PopCurrentPosition() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::PopRegister(int register_index) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+
+void RegExpMacroAssemblerMIPS::PushBacktrack(Label* label) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::PushCurrentPosition() {
+  Push(current_input_offset());
+}
+
+
+void RegExpMacroAssemblerMIPS::PushRegister(int register_index,
+                                           StackCheckFlag check_stack_limit) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::ReadCurrentPositionFromRegister(int reg) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::ReadStackPointerFromRegister(int reg) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::SetCurrentPositionFromEnd(int by) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::SetRegister(int register_index, int to) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::Succeed() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::WriteCurrentPositionToRegister(int reg,
+                                                             int cp_offset) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::ClearRegisters(int reg_from, int reg_to) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::WriteStackPointerToRegister(int reg) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// Private methods:
+
+void RegExpMacroAssemblerMIPS::CallCheckStackGuardState(Register scratch) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+// 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));
+}
+
+
+int RegExpMacroAssemblerMIPS::CheckStackGuardState(Address* return_address,
+                                                  Code* re_code,
+                                                  Address re_frame) {
+  UNIMPLEMENTED_MIPS();
+  return 0;
+}
+
+
+MemOperand RegExpMacroAssemblerMIPS::register_location(int register_index) {
+  UNIMPLEMENTED_MIPS();
+  return MemOperand(zero_reg, 0);
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckPosition(int cp_offset,
+                                            Label* on_outside_input) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::BranchOrBacktrack(Label* to,
+                                                 Condition condition,
+                                                 Register rs,
+                                                 const Operand& rt) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::SafeCall(Label* to, Condition cond, Register rs,
+                                           const Operand& rt) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::SafeReturn() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::SafeCallTarget(Label* name) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::Push(Register source) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::Pop(Register target) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckPreemption() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CheckStackLimit() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::CallCFunctionUsingStub(
+    ExternalReference function,
+    int num_arguments) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpMacroAssemblerMIPS::LoadCurrentCharacterUnchecked(int cp_offset,
+                                                             int characters) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void RegExpCEntryStub::Generate(MacroAssembler* masm_) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+#undef __
+
+#endif  // V8_INTERPRETED_REGEXP
+
+}}  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_MIPS
diff --git a/src/mips/regexp-macro-assembler-mips.h b/src/mips/regexp-macro-assembler-mips.h
new file mode 100644
index 0000000..2f4319f
--- /dev/null
+++ b/src/mips/regexp-macro-assembler-mips.h
@@ -0,0 +1,250 @@
+// Copyright 2006-2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#ifndef V8_MIPS_REGEXP_MACRO_ASSEMBLER_MIPS_H_
+#define V8_MIPS_REGEXP_MACRO_ASSEMBLER_MIPS_H_
+
+namespace v8 {
+namespace internal {
+
+#ifdef V8_INTERPRETED_REGEXP
+class RegExpMacroAssemblerMIPS: public RegExpMacroAssembler {
+ public:
+  RegExpMacroAssemblerMIPS();
+  virtual ~RegExpMacroAssemblerMIPS();
+};
+#else  // V8_INTERPRETED_REGEXP
+class RegExpMacroAssemblerMIPS: public NativeRegExpMacroAssembler {
+ public:
+  RegExpMacroAssemblerMIPS(Mode mode, int registers_to_save);
+  virtual ~RegExpMacroAssemblerMIPS();
+  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 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,
+                                          Label* on_no_match);
+  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 SetCurrentPositionFromEnd(int by);
+  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);
+
+  // 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);
+ private:
+  // Offsets from frame_pointer() of function parameters and stored registers.
+  static const int kFramePointer = 0;
+
+  // Above the frame pointer - Stored registers and stack passed parameters.
+  // Registers s0 to s7, fp, and ra.
+  static const int kStoredRegisters = kFramePointer;
+  // Return address (stored from link register, read into pc on return).
+  static const int kReturnAddress = kStoredRegisters + 9 * kPointerSize;
+  // Stack frame header.
+  static const int kStackFrameHeader = kReturnAddress + kPointerSize;
+  // Stack parameters placed by caller.
+  static const int kRegisterOutput = kStackFrameHeader + 16;
+  static const int kStackHighEnd = kRegisterOutput + kPointerSize;
+  static const int kDirectCall = kStackHighEnd + kPointerSize;
+  static const int kIsolate = kDirectCall + kPointerSize;
+
+  // Below the frame pointer.
+  // Register parameters stored by setup code.
+  static const int kInputEnd = kFramePointer - kPointerSize;
+  static const int kInputStart = kInputEnd - kPointerSize;
+  static const int kStartIndex = kInputStart - kPointerSize;
+  static const int kInputString = kStartIndex - kPointerSize;
+  // When adding local variables remember to push space for them in
+  // the frame in GetCode.
+  static const int kInputStartMinusOne = kInputString - kPointerSize;
+  static const int kAtStart = kInputStartMinusOne - kPointerSize;
+  // First register address. Following registers are below it on the stack.
+  static const int kRegisterZero = kAtStart - kPointerSize;
+
+  // Initial size of code buffer.
+  static const size_t kRegExpCodeSize = 1024;
+
+  // 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();
+
+
+  // Generate a call to CheckStackGuardState.
+  void CallCheckStackGuardState(Register scratch);
+
+  // The ebp-relative location of a regexp register.
+  MemOperand register_location(int register_index);
+
+  // Register holding the current input position as negative offset from
+  // the end of the string.
+  inline Register current_input_offset() { return t2; }
+
+  // The register containing the current character after LoadCurrentCharacter.
+  inline Register current_character() { return t3; }
+
+  // Register holding address of the end of the input string.
+  inline Register end_of_input_address() { return t6; }
+
+  // Register holding the frame address. Local variables, parameters and
+  // regexp registers are addressed relative to this.
+  inline Register frame_pointer() { return fp; }
+
+  // The register containing the backtrack stack top. Provides a meaningful
+  // name to the register.
+  inline Register backtrack_stackpointer() { return t4; }
+
+  // Register holding pointer to the current code object.
+  inline Register code_pointer() { return t1; }
+
+  // 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(Label* to,
+                         Condition condition,
+                         Register rs,
+                         const Operand& rt);
+
+  // 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,
+                       Condition cond,
+                       Register rs,
+                       const Operand& rt);
+  inline void SafeReturn();
+  inline void SafeCallTarget(Label* name);
+
+  // Pushes the value of a register on the backtrack stack. Decrements the
+  // stack pointer by a word size and stores the register's value there.
+  inline void Push(Register source);
+
+  // Pops a value from the backtrack stack. Reads the word at the stack pointer
+  // and increments it by a word size.
+  inline void Pop(Register target);
+
+  // Calls a C function and cleans up the frame alignment done by
+  // by FrameAlign. The called function *is* allowed to trigger a garbage
+  // collection, but may not take more than four arguments (no arguments
+  // passed on the stack), and the first argument will be a pointer to the
+  // return address.
+  inline void CallCFunctionUsingStub(ExternalReference function,
+                                     int num_arguments);
+
+
+  MacroAssembler* masm_;
+
+  // 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_;
+};
+
+#endif  // V8_INTERPRETED_REGEXP
+
+
+}}  // namespace v8::internal
+
+#endif  // V8_MIPS_REGEXP_MACRO_ASSEMBLER_MIPS_H_
+
diff --git a/src/mips/register-allocator-mips-inl.h b/src/mips/register-allocator-mips-inl.h
index a876bee..bbfb31d 100644
--- a/src/mips/register-allocator-mips-inl.h
+++ b/src/mips/register-allocator-mips-inl.h
@@ -125,9 +125,6 @@
 
 void RegisterAllocator::Initialize() {
   Reset();
-  // The non-reserved a1 and ra registers are live on JS function entry.
-  Use(a1);  // JS function.
-  Use(ra);  // Return address.
 }
 
 
diff --git a/src/mips/register-allocator-mips.h b/src/mips/register-allocator-mips.h
index e056fb8..c448923 100644
--- a/src/mips/register-allocator-mips.h
+++ b/src/mips/register-allocator-mips.h
@@ -35,8 +35,9 @@
 
 class RegisterAllocatorConstants : public AllStatic {
  public:
-  static const int kNumRegisters = assembler::mips::kNumRegisters;
-  static const int kInvalidRegister = assembler::mips::kInvalidRegister;
+  // No registers are currently managed by the register allocator on MIPS.
+  static const int kNumRegisters = 0;
+  static const int kInvalidRegister = -1;
 };
 
 
diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
index 59a5373..50ad7a1 100644
--- a/src/mips/simulator-mips.cc
+++ b/src/mips/simulator-mips.cc
@@ -26,6 +26,8 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <stdlib.h>
+#include <math.h>
+#include <limits.h>
 #include <cstdarg>
 #include "v8.h"
 
@@ -37,23 +39,25 @@
 #include "mips/constants-mips.h"
 #include "mips/simulator-mips.h"
 
-namespace v8i = v8::internal;
-
-#if !defined(__mips) || defined(USE_SIMULATOR)
 
 // Only build the simulator if not compiling for real MIPS hardware.
-namespace assembler {
-namespace mips {
+#if defined(USE_SIMULATOR)
 
-using ::v8::internal::Object;
-using ::v8::internal::PrintF;
-using ::v8::internal::OS;
-using ::v8::internal::ReadLine;
-using ::v8::internal::DeleteArray;
+namespace v8 {
+namespace internal {
 
 // Utils functions
 bool HaveSameSign(int32_t a, int32_t b) {
-  return ((a ^ b) > 0);
+  return ((a ^ b) >= 0);
+}
+
+
+uint32_t get_fcsr_condition_bit(uint32_t cc) {
+  if (cc == 0) {
+    return 23;
+  } else {
+    return 24 + cc;
+  }
 }
 
 
@@ -63,15 +67,18 @@
 // Library does not provide vsscanf.
 #define SScanF sscanf  // NOLINT
 
-// The Debugger class is used by the simulator while debugging simulated MIPS
+// The MipsDebugger class is used by the simulator while debugging simulated
 // code.
-class Debugger {
+class MipsDebugger {
  public:
-  explicit Debugger(Simulator* sim);
-  ~Debugger();
+  explicit MipsDebugger(Simulator* sim);
+  ~MipsDebugger();
 
   void Stop(Instruction* instr);
   void Debug();
+  // Print all registers with a nice formatting.
+  void PrintAllRegs();
+  void PrintAllRegsIncludingFPU();
 
  private:
   // We set the breakpoint code to 0xfffff to easily recognize it.
@@ -81,6 +88,10 @@
   Simulator* sim_;
 
   int32_t GetRegisterValue(int regnum);
+  int32_t GetFPURegisterValueInt(int regnum);
+  int64_t GetFPURegisterValueLong(int regnum);
+  float GetFPURegisterValueFloat(int regnum);
+  double GetFPURegisterValueDouble(int regnum);
   bool GetValue(const char* desc, int32_t* value);
 
   // Set or delete a breakpoint. Returns true if successful.
@@ -91,18 +102,17 @@
   // execution to skip past breakpoints when run from the debugger.
   void UndoBreakpoints();
   void RedoBreakpoints();
-
-  // Print all registers with a nice formatting.
-  void PrintAllRegs();
 };
 
-Debugger::Debugger(Simulator* sim) {
+MipsDebugger::MipsDebugger(Simulator* sim) {
   sim_ = sim;
 }
 
-Debugger::~Debugger() {
+
+MipsDebugger::~MipsDebugger() {
 }
 
+
 #ifdef GENERATED_CODE_COVERAGE
 static FILE* coverage_log = NULL;
 
@@ -115,7 +125,7 @@
 }
 
 
-void Debugger::Stop(Instruction* instr) {
+void MipsDebugger::Stop(Instruction* instr) {
   UNIMPLEMENTED_MIPS();
   char* str = reinterpret_cast<char*>(instr->InstructionBits());
   if (strlen(str) > 0) {
@@ -125,9 +135,10 @@
     }
     instr->SetInstructionBits(0x0);  // Overwrite with nop.
   }
-  sim_->set_pc(sim_->get_pc() + Instruction::kInstructionSize);
+  sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
 }
 
+
 #else  // ndef GENERATED_CODE_COVERAGE
 
 #define UNSUPPORTED() printf("Unsupported instruction.\n");
@@ -135,16 +146,16 @@
 static void InitializeCoverage() {}
 
 
-void Debugger::Stop(Instruction* instr) {
+void MipsDebugger::Stop(Instruction* instr) {
   const char* str = reinterpret_cast<char*>(instr->InstructionBits());
   PrintF("Simulator hit %s\n", str);
-  sim_->set_pc(sim_->get_pc() + Instruction::kInstructionSize);
+  sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
   Debug();
 }
 #endif  // GENERATED_CODE_COVERAGE
 
 
-int32_t Debugger::GetRegisterValue(int regnum) {
+int32_t MipsDebugger::GetRegisterValue(int regnum) {
   if (regnum == kNumSimuRegisters) {
     return sim_->get_pc();
   } else {
@@ -153,11 +164,54 @@
 }
 
 
-bool Debugger::GetValue(const char* desc, int32_t* value) {
+int32_t MipsDebugger::GetFPURegisterValueInt(int regnum) {
+  if (regnum == kNumFPURegisters) {
+    return sim_->get_pc();
+  } else {
+    return sim_->get_fpu_register(regnum);
+  }
+}
+
+
+int64_t MipsDebugger::GetFPURegisterValueLong(int regnum) {
+  if (regnum == kNumFPURegisters) {
+    return sim_->get_pc();
+  } else {
+    return sim_->get_fpu_register_long(regnum);
+  }
+}
+
+
+float MipsDebugger::GetFPURegisterValueFloat(int regnum) {
+  if (regnum == kNumFPURegisters) {
+    return sim_->get_pc();
+  } else {
+    return sim_->get_fpu_register_float(regnum);
+  }
+}
+
+
+double MipsDebugger::GetFPURegisterValueDouble(int regnum) {
+  if (regnum == kNumFPURegisters) {
+    return sim_->get_pc();
+  } else {
+    return sim_->get_fpu_register_double(regnum);
+  }
+}
+
+
+bool MipsDebugger::GetValue(const char* desc, int32_t* value) {
   int regnum = Registers::Number(desc);
+  int fpuregnum = FPURegisters::Number(desc);
+
   if (regnum != kInvalidRegister) {
     *value = GetRegisterValue(regnum);
     return true;
+  } else if (fpuregnum != kInvalidFPURegister) {
+    *value = GetFPURegisterValueInt(fpuregnum);
+    return true;
+  } else if (strncmp(desc, "0x", 2) == 0) {
+    return SScanF(desc, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
   } else {
     return SScanF(desc, "%i", value) == 1;
   }
@@ -165,7 +219,7 @@
 }
 
 
-bool Debugger::SetBreakpoint(Instruction* breakpc) {
+bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
   // Check if a breakpoint can be set. If not return without any side-effects.
   if (sim_->break_pc_ != NULL) {
     return false;
@@ -180,7 +234,7 @@
 }
 
 
-bool Debugger::DeleteBreakpoint(Instruction* breakpc) {
+bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
   if (sim_->break_pc_ != NULL) {
     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
   }
@@ -191,20 +245,21 @@
 }
 
 
-void Debugger::UndoBreakpoints() {
+void MipsDebugger::UndoBreakpoints() {
   if (sim_->break_pc_ != NULL) {
     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
   }
 }
 
 
-void Debugger::RedoBreakpoints() {
+void MipsDebugger::RedoBreakpoints() {
   if (sim_->break_pc_ != NULL) {
     sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
   }
 }
 
-void Debugger::PrintAllRegs() {
+
+void MipsDebugger::PrintAllRegs() {
 #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
 
   PrintF("\n");
@@ -237,10 +292,45 @@
   // pc
   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
          REG_INFO(31), REG_INFO(34));
+
 #undef REG_INFO
+#undef FPU_REG_INFO
 }
 
-void Debugger::Debug() {
+
+void MipsDebugger::PrintAllRegsIncludingFPU() {
+#define FPU_REG_INFO(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \
+        GetFPURegisterValueInt(n+1), \
+        GetFPURegisterValueInt(n), \
+                        GetFPURegisterValueDouble(n)
+
+  PrintAllRegs();
+
+  PrintF("\n\n");
+  // f0, f1, f2, ... f31
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(0) );
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(2) );
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(4) );
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(6) );
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(8) );
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(10));
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(12));
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(14));
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(16));
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(18));
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(20));
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(22));
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(24));
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(26));
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(28));
+  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(30));
+
+#undef REG_INFO
+#undef FPU_REG_INFO
+}
+
+
+void MipsDebugger::Debug() {
   intptr_t last_pc = -1;
   bool done = false;
 
@@ -253,6 +343,7 @@
   char cmd[COMMAND_SIZE + 1];
   char arg1[ARG_SIZE + 1];
   char arg2[ARG_SIZE + 1];
+  char* argv[3] = { cmd, arg1, arg2 };
 
   // make sure to have a proper terminating character if reaching the limit
   cmd[COMMAND_SIZE] = 0;
@@ -280,19 +371,21 @@
     } 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,
+      int argc = 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)) {
-        if (!(reinterpret_cast<Instruction*>(sim_->get_pc())->IsTrap())) {
+        Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc());
+        if (!(instr->IsTrap()) ||
+            instr->InstructionBits() == rtCallRedirInstr) {
           sim_->InstructionDecode(
-                                reinterpret_cast<Instruction*>(sim_->get_pc()));
+              reinterpret_cast<Instruction*>(sim_->get_pc()));
         } else {
           // Allow si to jump over generated breakpoints.
           PrintF("/!\\ Jumping over generated breakpoint.\n");
-          sim_->set_pc(sim_->get_pc() + Instruction::kInstructionSize);
+          sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
         }
       } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
         // Execute the one instruction we broke at with breakpoints disabled.
@@ -300,23 +393,65 @@
         // Leave the debugger shell.
         done = true;
       } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
-        if (args == 2) {
+        if (argc == 2) {
           int32_t value;
+          float fvalue;
           if (strcmp(arg1, "all") == 0) {
             PrintAllRegs();
+          } else if (strcmp(arg1, "allf") == 0) {
+            PrintAllRegsIncludingFPU();
           } else {
-            if (GetValue(arg1, &value)) {
+            int regnum = Registers::Number(arg1);
+            int fpuregnum = FPURegisters::Number(arg1);
+
+            if (regnum != kInvalidRegister) {
+              value = GetRegisterValue(regnum);
               PrintF("%s: 0x%08x %d \n", arg1, value, value);
+            } else if (fpuregnum != kInvalidFPURegister) {
+              if (fpuregnum % 2 == 1) {
+                value = GetFPURegisterValueInt(fpuregnum);
+                fvalue = GetFPURegisterValueFloat(fpuregnum);
+                PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
+              } else {
+                double dfvalue;
+                int32_t lvalue1 = GetFPURegisterValueInt(fpuregnum);
+                int32_t lvalue2 = GetFPURegisterValueInt(fpuregnum + 1);
+                dfvalue = GetFPURegisterValueDouble(fpuregnum);
+                PrintF("%3s,%3s: 0x%08x%08x %16.4e\n",
+                       FPURegisters::Name(fpuregnum+1),
+                       FPURegisters::Name(fpuregnum),
+                       lvalue1,
+                       lvalue2,
+                       dfvalue);
+              }
             } else {
               PrintF("%s unrecognized\n", arg1);
             }
           }
         } else {
-          PrintF("print <register>\n");
+          if (argc == 3) {
+            if (strcmp(arg2, "single") == 0) {
+              int32_t value;
+              float fvalue;
+              int fpuregnum = FPURegisters::Number(arg1);
+
+              if (fpuregnum != kInvalidFPURegister) {
+                value = GetFPURegisterValueInt(fpuregnum);
+                fvalue = GetFPURegisterValueFloat(fpuregnum);
+                PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
+              } else {
+                PrintF("%s unrecognized\n", arg1);
+              }
+            } else {
+              PrintF("print <fpu register> single\n");
+            }
+          } else {
+            PrintF("print <register> or print <fpu register> single\n");
+          }
         }
       } else if ((strcmp(cmd, "po") == 0)
                  || (strcmp(cmd, "printobject") == 0)) {
-        if (args == 2) {
+        if (argc == 2) {
           int32_t value;
           if (GetValue(arg1, &value)) {
             Object* obj = reinterpret_cast<Object*>(value);
@@ -333,6 +468,39 @@
         } else {
           PrintF("printobject <value>\n");
         }
+      } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
+        int32_t* cur = NULL;
+        int32_t* end = NULL;
+        int next_arg = 1;
+
+        if (strcmp(cmd, "stack") == 0) {
+          cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
+        } else {  // "mem"
+          int32_t value;
+          if (!GetValue(arg1, &value)) {
+            PrintF("%s unrecognized\n", arg1);
+            continue;
+          }
+          cur = reinterpret_cast<int32_t*>(value);
+          next_arg++;
+        }
+
+        int32_t words;
+        if (argc == next_arg) {
+          words = 10;
+        } else if (argc == next_arg + 1) {
+          if (!GetValue(argv[next_arg], &words)) {
+            words = 10;
+          }
+        }
+        end = cur + words;
+
+        while (cur < end) {
+          PrintF("  0x%08x:  0x%08x %10d\n",
+                 reinterpret_cast<intptr_t>(cur), *cur, *cur);
+          cur++;
+        }
+
       } else if ((strcmp(cmd, "disasm") == 0) || (strcmp(cmd, "dpc") == 0)) {
         disasm::NameConverter converter;
         disasm::Disassembler dasm(converter);
@@ -342,36 +510,37 @@
         byte_* cur = NULL;
         byte_* end = NULL;
 
-        if (args == 1) {
+        if (argc == 1) {
           cur = reinterpret_cast<byte_*>(sim_->get_pc());
-          end = cur + (10 * Instruction::kInstructionSize);
-        } else if (args == 2) {
+          end = cur + (10 * Instruction::kInstrSize);
+        } else if (argc == 2) {
           int32_t value;
           if (GetValue(arg1, &value)) {
             cur = reinterpret_cast<byte_*>(value);
             // no length parameter passed, assume 10 instructions
-            end = cur + (10 * Instruction::kInstructionSize);
+            end = cur + (10 * Instruction::kInstrSize);
           }
         } else {
           int32_t value1;
           int32_t value2;
           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
             cur = reinterpret_cast<byte_*>(value1);
-            end = cur + (value2 * Instruction::kInstructionSize);
+            end = cur + (value2 * Instruction::kInstrSize);
           }
         }
 
         while (cur < end) {
           dasm.InstructionDecode(buffer, cur);
-          PrintF("  0x%08x  %s\n", cur, buffer.start());
-          cur += Instruction::kInstructionSize;
+          PrintF("  0x%08x  %s\n",
+              reinterpret_cast<intptr_t>(cur), buffer.start());
+          cur += Instruction::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) {
+        if (argc == 2) {
           int32_t value;
           if (GetValue(arg1, &value)) {
             if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
@@ -404,29 +573,30 @@
         byte_* cur = NULL;
         byte_* end = NULL;
 
-        if (args == 1) {
+        if (argc == 1) {
           cur = reinterpret_cast<byte_*>(sim_->get_pc());
-          end = cur + (10 * Instruction::kInstructionSize);
-        } else if (args == 2) {
+          end = cur + (10 * Instruction::kInstrSize);
+        } else if (argc == 2) {
           int32_t value;
           if (GetValue(arg1, &value)) {
             cur = reinterpret_cast<byte_*>(value);
             // no length parameter passed, assume 10 instructions
-            end = cur + (10 * Instruction::kInstructionSize);
+            end = cur + (10 * Instruction::kInstrSize);
           }
         } else {
           int32_t value1;
           int32_t value2;
           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
             cur = reinterpret_cast<byte_*>(value1);
-            end = cur + (value2 * Instruction::kInstructionSize);
+            end = cur + (value2 * Instruction::kInstrSize);
           }
         }
 
         while (cur < end) {
           dasm.InstructionDecode(buffer, cur);
-          PrintF("  0x%08x  %s\n", cur, buffer.start());
-          cur += Instruction::kInstructionSize;
+          PrintF("  0x%08x  %s\n",
+                 reinterpret_cast<intptr_t>(cur), buffer.start());
+          cur += Instruction::kInstrSize;
         }
       } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
         PrintF("cont\n");
@@ -438,6 +608,10 @@
         PrintF("  use register name 'all' to print all registers\n");
         PrintF("printobject <register>\n");
         PrintF("  print an object from a register (alias 'po')\n");
+        PrintF("stack [<words>]\n");
+        PrintF("  dump stack content, default dump 10 words)\n");
+        PrintF("mem <address> [<words>]\n");
+        PrintF("  dump memory content, default dump 10 words)\n");
         PrintF("flags\n");
         PrintF("  print flags\n");
         PrintF("disasm [<instructions>]\n");
@@ -471,29 +645,120 @@
 }
 
 
-// Create one simulator per thread and keep it in thread local storage.
-static v8::internal::Thread::LocalStorageKey simulator_key;
+static bool ICacheMatch(void* one, void* two) {
+  ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
+  ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
+  return one == two;
+}
 
 
-bool Simulator::initialized_ = false;
+static uint32_t ICacheHash(void* key) {
+  return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
+}
+
+
+static bool AllOnOnePage(uintptr_t start, int size) {
+  intptr_t start_page = (start & ~CachePage::kPageMask);
+  intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
+  return start_page == end_page;
+}
+
+
+void Simulator::FlushICache(v8::internal::HashMap* i_cache,
+                            void* start_addr,
+                            size_t size) {
+  intptr_t start = reinterpret_cast<intptr_t>(start_addr);
+  int intra_line = (start & CachePage::kLineMask);
+  start -= intra_line;
+  size += intra_line;
+  size = ((size - 1) | CachePage::kLineMask) + 1;
+  int offset = (start & CachePage::kPageMask);
+  while (!AllOnOnePage(start, size - 1)) {
+    int bytes_to_flush = CachePage::kPageSize - offset;
+    FlushOnePage(i_cache, start, bytes_to_flush);
+    start += bytes_to_flush;
+    size -= bytes_to_flush;
+    ASSERT_EQ(0, start & CachePage::kPageMask);
+    offset = 0;
+  }
+  if (size != 0) {
+    FlushOnePage(i_cache, start, size);
+  }
+}
+
+
+CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
+  v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
+                                                         ICacheHash(page),
+                                                         true);
+  if (entry->value == NULL) {
+    CachePage* new_page = new CachePage();
+    entry->value = new_page;
+  }
+  return reinterpret_cast<CachePage*>(entry->value);
+}
+
+
+// Flush from start up to and not including start + size.
+void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
+                             intptr_t start,
+                             int size) {
+  ASSERT(size <= CachePage::kPageSize);
+  ASSERT(AllOnOnePage(start, size - 1));
+  ASSERT((start & CachePage::kLineMask) == 0);
+  ASSERT((size & CachePage::kLineMask) == 0);
+  void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
+  int offset = (start & CachePage::kPageMask);
+  CachePage* cache_page = GetCachePage(i_cache, page);
+  char* valid_bytemap = cache_page->ValidityByte(offset);
+  memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
+}
+
+
+void Simulator::CheckICache(v8::internal::HashMap* i_cache,
+                            Instruction* instr) {
+  intptr_t address = reinterpret_cast<intptr_t>(instr);
+  void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
+  void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
+  int offset = (address & CachePage::kPageMask);
+  CachePage* cache_page = GetCachePage(i_cache, page);
+  char* cache_valid_byte = cache_page->ValidityByte(offset);
+  bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
+  char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
+  if (cache_hit) {
+    // Check that the data in memory matches the contents of the I-cache.
+    CHECK(memcmp(reinterpret_cast<void*>(instr),
+                 cache_page->CachedData(offset),
+                 Instruction::kInstrSize) == 0);
+  } else {
+    // Cache miss.  Load memory into the cache.
+    memcpy(cached_line, line, CachePage::kLineLength);
+    *cache_valid_byte = CachePage::LINE_VALID;
+  }
+}
 
 
 void Simulator::Initialize() {
-  if (initialized_) return;
-  simulator_key = v8::internal::Thread::CreateThreadLocalKey();
-  initialized_ = true;
+  if (Isolate::Current()->simulator_initialized()) return;
+  Isolate::Current()->set_simulator_initialized(true);
   ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference);
 }
 
 
-Simulator::Simulator() {
+Simulator::Simulator() : isolate_(Isolate::Current()) {
+  i_cache_ = isolate_->simulator_i_cache();
+  if (i_cache_ == NULL) {
+    i_cache_ = new v8::internal::HashMap(&ICacheMatch);
+    isolate_->set_simulator_i_cache(i_cache_);
+  }
   Initialize();
   // 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));
+  stack_size_ = 1 * 1024*1024;  // allocate 1MB for stack
+  stack_ = reinterpret_cast<char*>(malloc(stack_size_));
   pc_modified_ = false;
   icount_ = 0;
+  break_count_ = 0;
   break_pc_ = NULL;
   break_instr_ = 0;
 
@@ -502,16 +767,23 @@
   for (int i = 0; i < kNumSimuRegisters; i++) {
     registers_[i] = 0;
   }
+  for (int i = 0; i < kNumFPURegisters; i++) {
+    FPUregisters_[i] = 0;
+  }
+  FCSR_ = 0;
 
   // 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;
+  registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size_ - 64;
   // The ra 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_ra;
   registers_[ra] = bad_ra;
   InitializeCoverage();
+  for (int i = 0; i < kNumExceptions; i++) {
+    exceptions[i] = 0;
+  }
 }
 
 
@@ -524,12 +796,18 @@
 // offset from the swi instruction so the simulator knows what to call.
 class Redirection {
  public:
-  Redirection(void* external_function, bool fp_return)
+  Redirection(void* external_function, ExternalReference::Type type)
       : external_function_(external_function),
         swi_instruction_(rtCallRedirInstr),
-        fp_return_(fp_return),
-        next_(list_) {
-    list_ = this;
+        type_(type),
+        next_(NULL) {
+    Isolate* isolate = Isolate::Current();
+    next_ = isolate->simulator_redirection();
+    Simulator::current(isolate)->
+        FlushICache(isolate->simulator_i_cache(),
+                    reinterpret_cast<void*>(&swi_instruction_),
+                    Instruction::kInstrSize);
+    isolate->set_simulator_redirection(this);
   }
 
   void* address_of_swi_instruction() {
@@ -537,14 +815,16 @@
   }
 
   void* external_function() { return external_function_; }
-  bool fp_return() { return fp_return_; }
+  ExternalReference::Type type() { return type_; }
 
-  static Redirection* Get(void* external_function, bool fp_return) {
-    Redirection* current;
-    for (current = list_; current != NULL; current = current->next_) {
+  static Redirection* Get(void* external_function,
+                          ExternalReference::Type type) {
+    Isolate* isolate = Isolate::Current();
+    Redirection* current = isolate->simulator_redirection();
+    for (; current != NULL; current = current->next_) {
       if (current->external_function_ == external_function) return current;
     }
-    return new Redirection(external_function, fp_return);
+    return new Redirection(external_function, type);
   }
 
   static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
@@ -557,31 +837,33 @@
  private:
   void* external_function_;
   uint32_t swi_instruction_;
-  bool fp_return_;
+  ExternalReference::Type type_;
   Redirection* next_;
-  static Redirection* list_;
 };
 
 
-Redirection* Redirection::list_ = NULL;
-
-
 void* Simulator::RedirectExternalReference(void* external_function,
-                                           bool fp_return) {
-  Redirection* redirection = Redirection::Get(external_function, fp_return);
+                                           ExternalReference::Type type) {
+  Redirection* redirection = Redirection::Get(external_function, type);
   return redirection->address_of_swi_instruction();
 }
 
 
 // Get the active Simulator for the current thread.
-Simulator* Simulator::current() {
-  Initialize();
-  Simulator* sim = reinterpret_cast<Simulator*>(
-      v8::internal::Thread::GetThreadLocal(simulator_key));
+Simulator* Simulator::current(Isolate* isolate) {
+  v8::internal::Isolate::PerIsolateThreadData* isolate_data =
+      Isolate::CurrentPerIsolateThreadData();
+  if (isolate_data == NULL) {
+    Isolate::EnterDefaultIsolate();
+    isolate_data = Isolate::CurrentPerIsolateThreadData();
+  }
+  ASSERT(isolate_data != NULL);
+
+  Simulator* sim = isolate_data->simulator();
   if (sim == NULL) {
-    // TODO(146): delete the simulator object when a thread goes away.
+    // TODO(146): delete the simulator object when a thread/isolate goes away.
     sim = new Simulator();
-    v8::internal::Thread::SetThreadLocal(simulator_key, sim);
+    isolate_data->set_simulator(sim);
   }
   return sim;
 }
@@ -599,14 +881,22 @@
   registers_[reg] = (reg == 0) ? 0 : value;
 }
 
+
 void Simulator::set_fpu_register(int fpureg, int32_t value) {
   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
   FPUregisters_[fpureg] = value;
 }
 
+
+void Simulator::set_fpu_register_float(int fpureg, float value) {
+  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
+  *BitCast<float*>(&FPUregisters_[fpureg]) = value;
+}
+
+
 void Simulator::set_fpu_register_double(int fpureg, double value) {
   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
-  *v8i::BitCast<double*>(&FPUregisters_[fpureg]) = value;
+  *BitCast<double*>(&FPUregisters_[fpureg]) = value;
 }
 
 
@@ -620,22 +910,75 @@
     return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
 }
 
+
 int32_t Simulator::get_fpu_register(int fpureg) const {
   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
   return FPUregisters_[fpureg];
 }
 
+
+int64_t Simulator::get_fpu_register_long(int fpureg) const {
+  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
+  return *BitCast<int64_t*>(
+      const_cast<int32_t*>(&FPUregisters_[fpureg]));
+}
+
+
+float Simulator::get_fpu_register_float(int fpureg) const {
+  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
+  return *BitCast<float*>(
+      const_cast<int32_t*>(&FPUregisters_[fpureg]));
+}
+
+
 double Simulator::get_fpu_register_double(int fpureg) const {
   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
-  return *v8i::BitCast<double*>(const_cast<int32_t*>(&FPUregisters_[fpureg]));
+  return *BitCast<double*>(const_cast<int32_t*>(&FPUregisters_[fpureg]));
 }
 
+
+// Helper functions for setting and testing the FCSR register's bits.
+void Simulator::set_fcsr_bit(uint32_t cc, bool value) {
+  if (value) {
+    FCSR_ |= (1 << cc);
+  } else {
+    FCSR_ &= ~(1 << cc);
+  }
+}
+
+
+bool Simulator::test_fcsr_bit(uint32_t cc) {
+  return FCSR_ & (1 << cc);
+}
+
+
+// Sets the rounding error codes in FCSR based on the result of the rounding.
+// Returns true if the operation was invalid.
+bool Simulator::set_fcsr_round_error(double original, double rounded) {
+  if (!isfinite(original) ||
+      rounded > LONG_MAX ||
+      rounded < LONG_MIN) {
+    set_fcsr_bit(6, true);  // Invalid operation.
+    return true;
+  } else if (original != static_cast<double>(rounded)) {
+    set_fcsr_bit(2, true);  // Inexact.
+  }
+  return false;
+}
+
+
 // Raw access to the PC register.
 void Simulator::set_pc(int32_t value) {
   pc_modified_ = true;
   registers_[pc] = value;
 }
 
+
+bool Simulator::has_bad_pc() const {
+  return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
+}
+
+
 // Raw access to the PC register without the special adjustment when reading.
 int32_t Simulator::get_pc() const {
   return registers_[pc];
@@ -651,24 +994,38 @@
 // get the correct MIPS-like behaviour on unaligned accesses.
 
 int Simulator::ReadW(int32_t addr, Instruction* instr) {
-  if ((addr & v8i::kPointerAlignmentMask) == 0) {
+  if (addr >=0 && addr < 0x400) {
+    // this has to be a NULL-dereference
+    MipsDebugger dbg(this);
+    dbg.Debug();
+  }
+  if ((addr & kPointerAlignmentMask) == 0) {
     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
     return *ptr;
   }
-  PrintF("Unaligned read at 0x%08x, pc=%p\n", addr, instr);
-  OS::Abort();
+  PrintF("Unaligned read at 0x%08x, pc=%p\n", addr,
+      reinterpret_cast<void*>(instr));
+  MipsDebugger dbg(this);
+  dbg.Debug();
   return 0;
 }
 
 
 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
-  if ((addr & v8i::kPointerAlignmentMask) == 0) {
+  if (addr >= 0 && addr < 0x400) {
+    // this has to be a NULL-dereference
+    MipsDebugger dbg(this);
+    dbg.Debug();
+  }
+  if ((addr & kPointerAlignmentMask) == 0) {
     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
     *ptr = value;
     return;
   }
-  PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr);
-  OS::Abort();
+  PrintF("Unaligned write at 0x%08x, pc=%p\n", addr,
+      reinterpret_cast<void*>(instr));
+  MipsDebugger dbg(this);
+  dbg.Debug();
 }
 
 
@@ -677,7 +1034,8 @@
     double* ptr = reinterpret_cast<double*>(addr);
     return *ptr;
   }
-  PrintF("Unaligned read at 0x%08x, pc=%p\n", addr, instr);
+  PrintF("Unaligned (double) read at 0x%08x, pc=%p\n", addr,
+      reinterpret_cast<void*>(instr));
   OS::Abort();
   return 0;
 }
@@ -689,7 +1047,8 @@
     *ptr = value;
     return;
   }
-  PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr);
+  PrintF("Unaligned (double) write at 0x%08x, pc=%p\n", addr,
+      reinterpret_cast<void*>(instr));
   OS::Abort();
 }
 
@@ -699,7 +1058,8 @@
     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
     return *ptr;
   }
-  PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr, instr);
+  PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr,
+      reinterpret_cast<void*>(instr));
   OS::Abort();
   return 0;
 }
@@ -710,7 +1070,8 @@
     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
     return *ptr;
   }
-  PrintF("Unaligned signed halfword read at 0x%08x, pc=%p\n", addr, instr);
+  PrintF("Unaligned signed halfword read at 0x%08x, pc=%p\n", addr,
+      reinterpret_cast<void*>(instr));
   OS::Abort();
   return 0;
 }
@@ -722,7 +1083,8 @@
     *ptr = value;
     return;
   }
-  PrintF("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr, instr);
+  PrintF("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr,
+      reinterpret_cast<void*>(instr));
   OS::Abort();
 }
 
@@ -733,7 +1095,8 @@
     *ptr = value;
     return;
   }
-  PrintF("Unaligned halfword write at 0x%08x, pc=%p\n", addr, instr);
+  PrintF("Unaligned halfword write at 0x%08x, pc=%p\n", addr,
+      reinterpret_cast<void*>(instr));
   OS::Abort();
 }
 
@@ -746,7 +1109,7 @@
 
 int32_t Simulator::ReadB(int32_t addr) {
   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
-  return ((*ptr << 24) >> 24) & 0xff;
+  return *ptr;
 }
 
 
@@ -773,7 +1136,7 @@
 // Unsupported instructions use Format to print an error and stop execution.
 void Simulator::Format(Instruction* instr, const char* format) {
   PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
-         instr, format);
+         reinterpret_cast<intptr_t>(instr), format);
   UNIMPLEMENTED_MIPS();
 }
 
@@ -782,75 +1145,140 @@
 // 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
+// 64 bits of result. If they don't, the v1 result register contains a bogus
 // value, which is fine because it is caller-saved.
 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
                                         int32_t arg1,
                                         int32_t arg2,
-                                        int32_t arg3);
-typedef double (*SimulatorRuntimeFPCall)(double fparg0,
-                                         double fparg1);
-
+                                        int32_t arg3,
+                                        int32_t arg4,
+                                        int32_t arg5);
+typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
+                                         int32_t arg1,
+                                         int32_t arg2,
+                                         int32_t arg3);
 
 // Software interrupt instructions are used by the simulator to call into the
-// C-based V8 runtime.
+// C-based V8 runtime. They are also used for debugging with simulator.
 void Simulator::SoftwareInterrupt(Instruction* instr) {
+  // There are several instructions that could get us here,
+  // the break_ instruction, or several variants of traps. All
+  // Are "SPECIAL" class opcode, and are distinuished by function.
+  int32_t func = instr->FunctionFieldRaw();
+  int32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1;
+
   // We first check if we met a call_rt_redirected.
   if (instr->InstructionBits() == rtCallRedirInstr) {
+    // Check if stack is aligned. Error if not aligned is reported below to
+    // include information on the function called.
+    bool stack_aligned =
+        (get_register(sp)
+         & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
     Redirection* redirection = Redirection::FromSwiInstruction(instr);
     int32_t arg0 = get_register(a0);
     int32_t arg1 = get_register(a1);
     int32_t arg2 = get_register(a2);
     int32_t arg3 = get_register(a3);
-    // fp args are (not always) in f12 and f14.
-    // See MIPS conventions for more details.
-    double fparg0 = get_fpu_register_double(f12);
-    double fparg1 = get_fpu_register_double(f14);
+    int32_t arg4 = 0;
+    int32_t arg5 = 0;
+
+    // Need to check if sp is valid before assigning arg4, arg5.
+    // This is a fix for cctest test-api/CatchStackOverflow which causes
+    // the stack to overflow. For some reason arm doesn't need this
+    // stack check here.
+    int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
+    int32_t* stack = reinterpret_cast<int32_t*>(stack_);
+    if (stack_pointer >= stack && stack_pointer < stack + stack_size_) {
+      arg4 = stack_pointer[0];
+      arg5 = stack_pointer[1];
+    }
     // This is dodgy but it works because the C entry stubs are never moved.
     // See comment in codegen-arm.cc and bug 1242173.
     int32_t saved_ra = get_register(ra);
-    if (redirection->fp_return()) {
-      intptr_t external =
-          reinterpret_cast<intptr_t>(redirection->external_function());
+
+    intptr_t external =
+        reinterpret_cast<int32_t>(redirection->external_function());
+
+    // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware
+    // FPU, or gcc soft-float routines. Hardware FPU is simulated in this
+    // simulator. Soft-float has additional abstraction of ExternalReference,
+    // to support serialization. Finally, when simulated on x86 host, the
+    // x86 softfloat routines are used, and this Redirection infrastructure
+    // lets simulated-mips make calls into x86 C code.
+    // When doing that, the 'double' return type must be handled differently
+    // than the usual int64_t return. The data is returned in different
+    // registers and cannot be cast from one type to the other. However, the
+    // calling arguments are passed the same way in both cases.
+    if (redirection->type() == ExternalReference::FP_RETURN_CALL) {
       SimulatorRuntimeFPCall target =
           reinterpret_cast<SimulatorRuntimeFPCall>(external);
-      if (::v8::internal::FLAG_trace_sim) {
-        PrintF("Call to host function at %p with args %f, %f\n",
-               FUNCTION_ADDR(target), fparg0, fparg1);
+      if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
+        PrintF("Call to host function at %p with args %08x:%08x %08x:%08x",
+               FUNCTION_ADDR(target), arg0, arg1, arg2, arg3);
+        if (!stack_aligned) {
+          PrintF(" with unaligned stack %08x\n", get_register(sp));
+        }
+        PrintF("\n");
       }
-      double result = target(fparg0, fparg1);
-      set_fpu_register_double(f0, result);
+      double result = target(arg0, arg1, arg2, arg3);
+      // fp result -> registers v0 and v1.
+      int32_t gpreg_pair[2];
+      memcpy(&gpreg_pair[0], &result, 2 * sizeof(int32_t));
+      set_register(v0, gpreg_pair[0]);
+      set_register(v1, gpreg_pair[1]);
+    } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
+      PrintF("Mips does not yet support ExternalReference::DIRECT_API_CALL\n");
+      ASSERT(redirection->type() != ExternalReference::DIRECT_API_CALL);
+    } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
+      PrintF("Mips does not support ExternalReference::DIRECT_GETTER_CALL\n");
+      ASSERT(redirection->type() != ExternalReference::DIRECT_GETTER_CALL);
     } else {
-      intptr_t external =
-          reinterpret_cast<int32_t>(redirection->external_function());
+      // Builtin call.
+      ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);
       SimulatorRuntimeCall target =
           reinterpret_cast<SimulatorRuntimeCall>(external);
-      if (::v8::internal::FLAG_trace_sim) {
+      if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
         PrintF(
-            "Call to host function at %p with args %08x, %08x, %08x, %08x\n",
+            "Call to host function at %p: %08x, %08x, %08x, %08x, %08x, %08x",
             FUNCTION_ADDR(target),
             arg0,
             arg1,
             arg2,
-            arg3);
+            arg3,
+            arg4,
+            arg5);
+        if (!stack_aligned) {
+          PrintF(" with unaligned stack %08x\n", get_register(sp));
+        }
+        PrintF("\n");
       }
-      int64_t result = target(arg0, arg1, arg2, arg3);
-      int32_t lo_res = static_cast<int32_t>(result);
-      int32_t hi_res = static_cast<int32_t>(result >> 32);
-      if (::v8::internal::FLAG_trace_sim) {
-        PrintF("Returned %08x\n", lo_res);
-      }
-      set_register(v0, lo_res);
-      set_register(v1, hi_res);
+
+      int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
+      set_register(v0, static_cast<int32_t>(result));
+      set_register(v1, static_cast<int32_t>(result >> 32));
+    }
+    if (::v8::internal::FLAG_trace_sim) {
+      PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0));
     }
     set_register(ra, saved_ra);
     set_pc(get_register(ra));
+
+  } else if (func == BREAK && code >= 0 && code < 16) {
+    // First 16 break_ codes interpreted as debug markers.
+    MipsDebugger dbg(this);
+    ++break_count_;
+    PrintF("\n---- break %d marker: %3d  (instr count: %8d) ----------"
+           "----------------------------------",
+           code, break_count_, icount_);
+    dbg.PrintAllRegs();  // Print registers and continue running.
   } else {
-    Debugger dbg(this);
+    // All remaining break_ codes, and all traps are handled here.
+    MipsDebugger dbg(this);
     dbg.Debug();
   }
 }
 
+
 void Simulator::SignalExceptions() {
   for (int i = 1; i < kNumExceptions; i++) {
     if (exceptions[i] != 0) {
@@ -859,51 +1287,52 @@
   }
 }
 
+
 // Handle execution based on instruction types.
-void Simulator::DecodeTypeRegister(Instruction* instr) {
-  // Instruction fields
-  Opcode   op     = instr->OpcodeFieldRaw();
-  int32_t  rs_reg = instr->RsField();
-  int32_t  rs     = get_register(rs_reg);
-  uint32_t rs_u   = static_cast<uint32_t>(rs);
-  int32_t  rt_reg = instr->RtField();
-  int32_t  rt     = get_register(rt_reg);
-  uint32_t rt_u   = static_cast<uint32_t>(rt);
-  int32_t  rd_reg = instr->RdField();
-  uint32_t sa     = instr->SaField();
 
-  int32_t fs_reg= instr->FsField();
+void Simulator::ConfigureTypeRegister(Instruction* instr,
+                                      int32_t& alu_out,
+                                      int64_t& i64hilo,
+                                      uint64_t& u64hilo,
+                                      int32_t& next_pc,
+                                      bool& do_interrupt) {
+  // Every local variable declared here needs to be const.
+  // This is to make sure that changed values are sent back to
+  // DecodeTypeRegister correctly.
 
-  // ALU output
-  // It should not be used as is. Instructions using it should always initialize
-  // it first.
-  int32_t alu_out = 0x12345678;
-  // Output or temporary for floating point.
-  double fp_out = 0.0;
+  // Instruction fields.
+  const Opcode   op     = instr->OpcodeFieldRaw();
+  const int32_t  rs_reg = instr->RsValue();
+  const int32_t  rs     = get_register(rs_reg);
+  const uint32_t rs_u   = static_cast<uint32_t>(rs);
+  const int32_t  rt_reg = instr->RtValue();
+  const int32_t  rt     = get_register(rt_reg);
+  const uint32_t rt_u   = static_cast<uint32_t>(rt);
+  const int32_t  rd_reg = instr->RdValue();
+  const uint32_t sa     = instr->SaValue();
 
-  // For break and trap instructions.
-  bool do_interrupt = false;
+  const int32_t  fs_reg = instr->FsValue();
 
-  // For jr and jalr
-  // Get current pc.
-  int32_t current_pc = get_pc();
-  // Next pc
-  int32_t next_pc = 0;
 
   // ---------- Configuration
   switch (op) {
     case COP1:    // Coprocessor instructions
       switch (instr->RsFieldRaw()) {
-        case BC1:   // branch on coprocessor condition
+        case BC1:   // Handled in DecodeTypeImmed, should never come here.
           UNREACHABLE();
           break;
+        case CFC1:
+          // At the moment only FCSR is supported.
+          ASSERT(fs_reg == kFCSRRegister);
+          alu_out = FCSR_;
+          break;
         case MFC1:
           alu_out = get_fpu_register(fs_reg);
           break;
         case MFHC1:
-          fp_out = get_fpu_register_double(fs_reg);
-          alu_out = *v8i::BitCast<int32_t*>(&fp_out);
+          UNIMPLEMENTED_MIPS();
           break;
+        case CTC1:
         case MTC1:
         case MTHC1:
           // Do the store in the execution step.
@@ -923,13 +1352,22 @@
       switch (instr->FunctionFieldRaw()) {
         case JR:
         case JALR:
-          next_pc = get_register(instr->RsField());
+          next_pc = get_register(instr->RsValue());
           break;
         case SLL:
           alu_out = rt << sa;
           break;
         case SRL:
-          alu_out = rt_u >> sa;
+          if (rs_reg == 0) {
+            // Regular logical right shift of a word by a fixed number of
+            // bits instruction. RS field is always equal to 0.
+            alu_out = rt_u >> sa;
+          } else {
+            // Logical right-rotate of a word by a fixed number of bits. This
+            // is special case of SRL instruction, added in MIPS32 Release 2.
+            // RS field is equal to 00001
+            alu_out = (rt_u >> sa) | (rt_u << (32 - sa));
+          }
           break;
         case SRA:
           alu_out = rt >> sa;
@@ -938,7 +1376,16 @@
           alu_out = rt << rs;
           break;
         case SRLV:
-          alu_out = rt_u >> rs;
+          if (sa == 0) {
+            // Regular logical right-shift of a word by a variable number of
+            // bits instruction. SA field is always equal to 0.
+            alu_out = rt_u >> rs;
+          } else {
+            // Logical right-rotate of a word by a variable number of bits.
+            // This is special case od SRLV instruction, added in MIPS32
+            // Release 2. SA field is equal to 00001
+            alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u));
+          }
           break;
         case SRAV:
           alu_out = rt >> rs;
@@ -950,10 +1397,10 @@
           alu_out = get_register(LO);
           break;
         case MULT:
-          UNIMPLEMENTED_MIPS();
+          i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
           break;
         case MULTU:
-          UNIMPLEMENTED_MIPS();
+          u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u);
           break;
         case DIV:
         case DIVU:
@@ -1005,6 +1452,7 @@
           break;
         // Break and trap instructions
         case BREAK:
+
           do_interrupt = true;
           break;
         case TGE:
@@ -1025,6 +1473,11 @@
         case TNE:
           do_interrupt = rs != rt;
           break;
+        case MOVN:
+        case MOVZ:
+        case MOVCI:
+          // No action taken on decode.
+          break;
         default:
           UNREACHABLE();
       };
@@ -1034,13 +1487,83 @@
         case MUL:
           alu_out = rs_u * rt_u;  // Only the lower 32 bits are kept.
           break;
+        case CLZ:
+          alu_out = __builtin_clz(rs_u);
+          break;
         default:
           UNREACHABLE();
-      }
+      };
+      break;
+    case SPECIAL3:
+      switch (instr->FunctionFieldRaw()) {
+        case INS: {   // Mips32r2 instruction.
+          // Interpret Rd field as 5-bit msb of insert.
+          uint16_t msb = rd_reg;
+          // Interpret sa field as 5-bit lsb of insert.
+          uint16_t lsb = sa;
+          uint16_t size = msb - lsb + 1;
+          uint32_t mask = (1 << size) - 1;
+          alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
+          break;
+        }
+        case EXT: {   // Mips32r2 instruction.
+          // Interpret Rd field as 5-bit msb of extract.
+          uint16_t msb = rd_reg;
+          // Interpret sa field as 5-bit lsb of extract.
+          uint16_t lsb = sa;
+          uint16_t size = msb + 1;
+          uint32_t mask = (1 << size) - 1;
+          alu_out = (rs_u & (mask << lsb)) >> lsb;
+          break;
+        }
+        default:
+          UNREACHABLE();
+      };
       break;
     default:
       UNREACHABLE();
   };
+}
+
+
+void Simulator::DecodeTypeRegister(Instruction* instr) {
+  // Instruction fields.
+  const Opcode   op     = instr->OpcodeFieldRaw();
+  const int32_t  rs_reg = instr->RsValue();
+  const int32_t  rs     = get_register(rs_reg);
+  const uint32_t rs_u   = static_cast<uint32_t>(rs);
+  const int32_t  rt_reg = instr->RtValue();
+  const int32_t  rt     = get_register(rt_reg);
+  const uint32_t rt_u   = static_cast<uint32_t>(rt);
+  const int32_t  rd_reg = instr->RdValue();
+
+  const int32_t  fs_reg = instr->FsValue();
+  const int32_t  ft_reg = instr->FtValue();
+  const int32_t  fd_reg = instr->FdValue();
+  int64_t  i64hilo = 0;
+  uint64_t u64hilo = 0;
+
+  // ALU output
+  // It should not be used as is. Instructions using it should always
+  // initialize it first.
+  int32_t alu_out = 0x12345678;
+
+  // For break and trap instructions.
+  bool do_interrupt = false;
+
+  // For jr and jalr
+  // Get current pc.
+  int32_t current_pc = get_pc();
+  // Next pc
+  int32_t next_pc = 0;
+
+  // Setup the variables if needed before executing the instruction.
+  ConfigureTypeRegister(instr,
+                        alu_out,
+                        i64hilo,
+                        u64hilo,
+                        next_pc,
+                        do_interrupt);
 
   // ---------- Raise exceptions triggered.
   SignalExceptions();
@@ -1052,25 +1575,42 @@
         case BC1:   // branch on coprocessor condition
           UNREACHABLE();
           break;
+        case CFC1:
+          set_register(rt_reg, alu_out);
         case MFC1:
-        case MFHC1:
           set_register(rt_reg, alu_out);
           break;
+        case MFHC1:
+          UNIMPLEMENTED_MIPS();
+          break;
+        case CTC1:
+          // At the moment only FCSR is supported.
+          ASSERT(fs_reg == kFCSRRegister);
+          FCSR_ = registers_[rt_reg];
+          break;
         case MTC1:
-          // We don't need to set the higher bits to 0, because MIPS ISA says
-          // they are in an unpredictable state after executing MTC1.
           FPUregisters_[fs_reg] = registers_[rt_reg];
-          FPUregisters_[fs_reg+1] = Unpredictable;
           break;
         case MTHC1:
-          // Here we need to keep the lower bits unchanged.
-          FPUregisters_[fs_reg+1] = registers_[rt_reg];
+          UNIMPLEMENTED_MIPS();
           break;
         case S:
+          float f;
           switch (instr->FunctionFieldRaw()) {
             case CVT_D_S:
+              f = get_fpu_register_float(fs_reg);
+              set_fpu_register_double(fd_reg, static_cast<double>(f));
+              break;
             case CVT_W_S:
             case CVT_L_S:
+            case TRUNC_W_S:
+            case TRUNC_L_S:
+            case ROUND_W_S:
+            case ROUND_L_S:
+            case FLOOR_W_S:
+            case FLOOR_L_S:
+            case CEIL_W_S:
+            case CEIL_L_S:
             case CVT_PS_S:
               UNIMPLEMENTED_MIPS();
               break;
@@ -1079,10 +1619,133 @@
           }
           break;
         case D:
+          double ft, fs;
+          uint32_t cc, fcsr_cc;
+          int64_t  i64;
+          fs = get_fpu_register_double(fs_reg);
+          ft = get_fpu_register_double(ft_reg);
+          cc = instr->FCccValue();
+          fcsr_cc = get_fcsr_condition_bit(cc);
           switch (instr->FunctionFieldRaw()) {
-            case CVT_S_D:
-            case CVT_W_D:
-            case CVT_L_D:
+            case ADD_D:
+              set_fpu_register_double(fd_reg, fs + ft);
+              break;
+            case SUB_D:
+              set_fpu_register_double(fd_reg, fs - ft);
+              break;
+            case MUL_D:
+              set_fpu_register_double(fd_reg, fs * ft);
+              break;
+            case DIV_D:
+              set_fpu_register_double(fd_reg, fs / ft);
+              break;
+            case ABS_D:
+              set_fpu_register_double(fd_reg, fs < 0 ? -fs : fs);
+              break;
+            case MOV_D:
+              set_fpu_register_double(fd_reg, fs);
+              break;
+            case NEG_D:
+              set_fpu_register_double(fd_reg, -fs);
+              break;
+            case SQRT_D:
+              set_fpu_register_double(fd_reg, sqrt(fs));
+              break;
+            case C_UN_D:
+              set_fcsr_bit(fcsr_cc, isnan(fs) || isnan(ft));
+              break;
+            case C_EQ_D:
+              set_fcsr_bit(fcsr_cc, (fs == ft));
+              break;
+            case C_UEQ_D:
+              set_fcsr_bit(fcsr_cc, (fs == ft) || (isnan(fs) || isnan(ft)));
+              break;
+            case C_OLT_D:
+              set_fcsr_bit(fcsr_cc, (fs < ft));
+              break;
+            case C_ULT_D:
+              set_fcsr_bit(fcsr_cc, (fs < ft) || (isnan(fs) || isnan(ft)));
+              break;
+            case C_OLE_D:
+              set_fcsr_bit(fcsr_cc, (fs <= ft));
+              break;
+            case C_ULE_D:
+              set_fcsr_bit(fcsr_cc, (fs <= ft) || (isnan(fs) || isnan(ft)));
+              break;
+            case CVT_W_D:   // Convert double to word.
+              // Rounding modes are not yet supported.
+              ASSERT((FCSR_ & 3) == 0);
+              // In rounding mode 0 it should behave like ROUND.
+            case ROUND_W_D:  // Round double to word.
+              {
+                double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
+                int32_t result = static_cast<int32_t>(rounded);
+                set_fpu_register(fd_reg, result);
+                if (set_fcsr_round_error(fs, rounded)) {
+                  set_fpu_register(fd_reg, kFPUInvalidResult);
+                }
+              }
+              break;
+            case TRUNC_W_D:  // Truncate double to word (round towards 0).
+              {
+                int32_t result = static_cast<int32_t>(fs);
+                set_fpu_register(fd_reg, result);
+                if (set_fcsr_round_error(fs, static_cast<double>(result))) {
+                  set_fpu_register(fd_reg, kFPUInvalidResult);
+                }
+              }
+              break;
+            case FLOOR_W_D:  // Round double to word towards negative infinity.
+              {
+                double rounded = floor(fs);
+                int32_t result = static_cast<int32_t>(rounded);
+                set_fpu_register(fd_reg, result);
+                if (set_fcsr_round_error(fs, rounded)) {
+                  set_fpu_register(fd_reg, kFPUInvalidResult);
+                }
+              }
+              break;
+            case CEIL_W_D:  // Round double to word towards positive infinity.
+              {
+                double rounded = ceil(fs);
+                int32_t result = static_cast<int32_t>(rounded);
+                set_fpu_register(fd_reg, result);
+                if (set_fcsr_round_error(fs, rounded)) {
+                  set_fpu_register(fd_reg, kFPUInvalidResult);
+                }
+              }
+              break;
+            case CVT_S_D:  // Convert double to float (single).
+              set_fpu_register_float(fd_reg, static_cast<float>(fs));
+              break;
+            case CVT_L_D:  // Mips32r2: Truncate double to 64-bit long-word.
+              i64 = static_cast<int64_t>(fs);
+              set_fpu_register(fd_reg, i64 & 0xffffffff);
+              set_fpu_register(fd_reg + 1, i64 >> 32);
+              break;
+            case TRUNC_L_D:  // Mips32r2 instruction.
+              i64 = static_cast<int64_t>(fs);
+              set_fpu_register(fd_reg, i64 & 0xffffffff);
+              set_fpu_register(fd_reg + 1, i64 >> 32);
+              break;
+            case ROUND_L_D: {  // Mips32r2 instruction.
+              double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
+              i64 = static_cast<int64_t>(rounded);
+              set_fpu_register(fd_reg, i64 & 0xffffffff);
+              set_fpu_register(fd_reg + 1, i64 >> 32);
+              break;
+            }
+            case FLOOR_L_D:  // Mips32r2 instruction.
+              i64 = static_cast<int64_t>(floor(fs));
+              set_fpu_register(fd_reg, i64 & 0xffffffff);
+              set_fpu_register(fd_reg + 1, i64 >> 32);
+              break;
+            case CEIL_L_D:  // Mips32r2 instruction.
+              i64 = static_cast<int64_t>(ceil(fs));
+              set_fpu_register(fd_reg, i64 & 0xffffffff);
+              set_fpu_register(fd_reg + 1, i64 >> 32);
+              break;
+            case C_F_D:
               UNIMPLEMENTED_MIPS();
               break;
             default:
@@ -1091,11 +1754,13 @@
           break;
         case W:
           switch (instr->FunctionFieldRaw()) {
-            case CVT_S_W:
-              UNIMPLEMENTED_MIPS();
+            case CVT_S_W:   // Convert word to float (single).
+              alu_out = get_fpu_register(fs_reg);
+              set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
               break;
             case CVT_D_W:   // Convert word to double.
-              set_fpu_register(rd_reg, static_cast<double>(rs));
+              alu_out = get_fpu_register(fs_reg);
+              set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
               break;
             default:
               UNREACHABLE();
@@ -1103,8 +1768,14 @@
           break;
         case L:
           switch (instr->FunctionFieldRaw()) {
+          case CVT_D_L:  // Mips32r2 instruction.
+            // Watch the signs here, we want 2 32-bit vals
+            // to make a sign-64.
+            i64 = (uint32_t) get_fpu_register(fs_reg);
+            i64 |= ((int64_t) get_fpu_register(fs_reg + 1) << 32);
+            set_fpu_register_double(fd_reg, static_cast<double>(i64));
+            break;
             case CVT_S_L:
-            case CVT_D_L:
               UNIMPLEMENTED_MIPS();
               break;
             default:
@@ -1121,7 +1792,7 @@
       switch (instr->FunctionFieldRaw()) {
         case JR: {
           Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
-              current_pc+Instruction::kInstructionSize);
+              current_pc+Instruction::kInstrSize);
           BranchDelayInstructionDecode(branch_delay_instr);
           set_pc(next_pc);
           pc_modified_ = true;
@@ -1129,16 +1800,21 @@
         }
         case JALR: {
           Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
-              current_pc+Instruction::kInstructionSize);
+              current_pc+Instruction::kInstrSize);
           BranchDelayInstructionDecode(branch_delay_instr);
-          set_register(31, current_pc + 2* Instruction::kInstructionSize);
+          set_register(31, current_pc + 2* Instruction::kInstrSize);
           set_pc(next_pc);
           pc_modified_ = true;
           break;
         }
         // Instructions using HI and LO registers.
         case MULT:
+          set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
+          set_register(HI, static_cast<int32_t>(i64hilo >> 32));
+          break;
         case MULTU:
+          set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
+          set_register(HI, static_cast<int32_t>(u64hilo >> 32));
           break;
         case DIV:
           // Divide by zero was checked in the configuration step.
@@ -1149,7 +1825,7 @@
           set_register(LO, rs_u / rt_u);
           set_register(HI, rs_u % rt_u);
           break;
-        // Break and trap instructions
+        // Break and trap instructions.
         case BREAK:
         case TGE:
         case TGEU:
@@ -1161,6 +1837,23 @@
             SoftwareInterrupt(instr);
           }
           break;
+        // Conditional moves.
+        case MOVN:
+          if (rt) set_register(rd_reg, rs);
+          break;
+        case MOVCI: {
+          uint32_t cc = instr->FCccValue();
+          uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
+          if (instr->Bit(16)) {  // Read Tf bit
+            if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
+          } else {
+            if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
+          }
+          break;
+        }
+        case MOVZ:
+          if (!rt) set_register(rd_reg, rs);
+          break;
         default:  // For other special opcodes we do the default operation.
           set_register(rd_reg, alu_out);
       };
@@ -1173,9 +1866,23 @@
           set_register(LO, Unpredictable);
           set_register(HI, Unpredictable);
           break;
+        default:  // For other special2 opcodes we do the default operation.
+          set_register(rd_reg, alu_out);
+      }
+      break;
+    case SPECIAL3:
+      switch (instr->FunctionFieldRaw()) {
+        case INS:
+          // Ins instr leaves result in Rt, rather than Rd.
+          set_register(rt_reg, alu_out);
+          break;
+        case EXT:
+          // Ext instr leaves result in Rt, rather than Rd.
+          set_register(rt_reg, alu_out);
+          break;
         default:
           UNREACHABLE();
-      }
+      };
       break;
     // Unimplemented opcodes raised an error in the configuration step before,
     // so we can use the default here to set the destination register in common
@@ -1185,22 +1892,22 @@
   };
 }
 
+
 // Type 2: instructions using a 16 bytes immediate. (eg: addi, beq)
 void Simulator::DecodeTypeImmediate(Instruction* instr) {
-  // Instruction fields
+  // Instruction fields.
   Opcode   op     = instr->OpcodeFieldRaw();
-  int32_t  rs     = get_register(instr->RsField());
+  int32_t  rs     = get_register(instr->RsValue());
   uint32_t rs_u   = static_cast<uint32_t>(rs);
-  int32_t  rt_reg = instr->RtField();  // destination register
+  int32_t  rt_reg = instr->RtValue();  // destination register
   int32_t  rt     = get_register(rt_reg);
-  int16_t  imm16  = instr->Imm16Field();
+  int16_t  imm16  = instr->Imm16Value();
 
-  int32_t  ft_reg = instr->FtField();  // destination register
-  int32_t  ft     = get_register(ft_reg);
+  int32_t  ft_reg = instr->FtValue();  // destination register
 
-  // zero extended immediate
+  // Zero extended immediate.
   uint32_t  oe_imm16 = 0xffff & imm16;
-  // sign extended immediate
+  // Sign extended immediate.
   int32_t   se_imm16 = imm16;
 
   // Get current pc.
@@ -1208,25 +1915,38 @@
   // Next pc.
   int32_t next_pc = bad_ra;
 
-  // Used for conditional branch instructions
+  // Used for conditional branch instructions.
   bool do_branch = false;
   bool execute_branch_delay_instruction = false;
 
-  // Used for arithmetic instructions
+  // Used for arithmetic instructions.
   int32_t alu_out = 0;
-  // Floating point
+  // Floating point.
   double fp_out = 0.0;
+  uint32_t cc, cc_value, fcsr_cc;
 
-  // Used for memory instructions
+  // Used for memory instructions.
   int32_t addr = 0x0;
+  // Value to be written in memory
+  uint32_t mem_value = 0x0;
 
   // ---------- Configuration (and execution for REGIMM)
   switch (op) {
-    // ------------- COP1. Coprocessor instructions
+    // ------------- COP1. Coprocessor instructions.
     case COP1:
       switch (instr->RsFieldRaw()) {
-        case BC1:   // branch on coprocessor condition
-          UNIMPLEMENTED_MIPS();
+        case BC1:   // Branch on coprocessor condition.
+          cc = instr->FBccValue();
+          fcsr_cc = get_fcsr_condition_bit(cc);
+          cc_value = test_fcsr_bit(fcsr_cc);
+          do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
+          execute_branch_delay_instruction = true;
+          // Set next_pc
+          if (do_branch) {
+            next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
+          } else {
+            next_pc = current_pc + kBranchReturnOffset;
+          }
           break;
         default:
           UNREACHABLE();
@@ -1259,7 +1979,7 @@
           execute_branch_delay_instruction = true;
           // Set next_pc
           if (do_branch) {
-            next_pc = current_pc + (imm16 << 2) + Instruction::kInstructionSize;
+            next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
             if (instr->IsLinkingInstruction()) {
               set_register(31, current_pc + kBranchReturnOffset);
             }
@@ -1323,6 +2043,21 @@
       addr = rs + se_imm16;
       alu_out = ReadB(addr);
       break;
+    case LH:
+      addr = rs + se_imm16;
+      alu_out = ReadH(addr, instr);
+      break;
+    case LWL: {
+      // al_offset is an offset of the effective address within an aligned word
+      uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
+      uint8_t byte_shift = kPointerAlignmentMask - al_offset;
+      uint32_t mask = (1 << byte_shift * 8) - 1;
+      addr = rs + se_imm16 - al_offset;
+      alu_out = ReadW(addr, instr);
+      alu_out <<= byte_shift * 8;
+      alu_out |= rt & mask;
+      break;
+    }
     case LW:
       addr = rs + se_imm16;
       alu_out = ReadW(addr, instr);
@@ -1331,12 +2066,47 @@
       addr = rs + se_imm16;
       alu_out = ReadBU(addr);
       break;
+    case LHU:
+      addr = rs + se_imm16;
+      alu_out = ReadHU(addr, instr);
+      break;
+    case LWR: {
+      // al_offset is an offset of the effective address within an aligned word
+      uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
+      uint8_t byte_shift = kPointerAlignmentMask - al_offset;
+      uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
+      addr = rs + se_imm16 - al_offset;
+      alu_out = ReadW(addr, instr);
+      alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
+      alu_out |= rt & mask;
+      break;
+    }
     case SB:
       addr = rs + se_imm16;
       break;
+    case SH:
+      addr = rs + se_imm16;
+      break;
+    case SWL: {
+      uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
+      uint8_t byte_shift = kPointerAlignmentMask - al_offset;
+      uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
+      addr = rs + se_imm16 - al_offset;
+      mem_value = ReadW(addr, instr) & mask;
+      mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
+      break;
+    }
     case SW:
       addr = rs + se_imm16;
       break;
+    case SWR: {
+      uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
+      uint32_t mask = (1 << al_offset * 8) - 1;
+      addr = rs + se_imm16 - al_offset;
+      mem_value = ReadW(addr, instr);
+      mem_value = (rt << al_offset * 8) | (mem_value & mask);
+      break;
+    }
     case LWC1:
       addr = rs + se_imm16;
       alu_out = ReadW(addr, instr);
@@ -1367,12 +2137,12 @@
       execute_branch_delay_instruction = true;
       // Set next_pc
       if (do_branch) {
-        next_pc = current_pc + (imm16 << 2) + Instruction::kInstructionSize;
+        next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
         if (instr->IsLinkingInstruction()) {
-          set_register(31, current_pc + 2* Instruction::kInstructionSize);
+          set_register(31, current_pc + 2* Instruction::kInstrSize);
         }
       } else {
-        next_pc = current_pc + 2 * Instruction::kInstructionSize;
+        next_pc = current_pc + 2 * Instruction::kInstrSize;
       }
       break;
     // ------------- Arithmetic instructions
@@ -1388,16 +2158,29 @@
       break;
     // ------------- Memory instructions
     case LB:
+    case LH:
+    case LWL:
     case LW:
     case LBU:
+    case LHU:
+    case LWR:
       set_register(rt_reg, alu_out);
       break;
     case SB:
       WriteB(addr, static_cast<int8_t>(rt));
       break;
+    case SH:
+      WriteH(addr, static_cast<uint16_t>(rt), instr);
+      break;
+    case SWL:
+      WriteW(addr, mem_value, instr);
+      break;
     case SW:
       WriteW(addr, rt, instr);
       break;
+    case SWR:
+      WriteW(addr, mem_value, instr);
+      break;
     case LWC1:
       set_fpu_register(ft_reg, alu_out);
       break;
@@ -1410,7 +2193,7 @@
       break;
     case SDC1:
       addr = rs + se_imm16;
-      WriteD(addr, ft, instr);
+      WriteD(addr, get_fpu_register_double(ft_reg), instr);
       break;
     default:
       break;
@@ -1422,7 +2205,7 @@
     // We don't check for end_sim_pc. First it should not be met as the current
     // pc is valid. Secondly a jump should always execute its branch delay slot.
     Instruction* branch_delay_instr =
-      reinterpret_cast<Instruction*>(current_pc+Instruction::kInstructionSize);
+      reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
     BranchDelayInstructionDecode(branch_delay_instr);
   }
 
@@ -1432,6 +2215,7 @@
   }
 }
 
+
 // Type 3: instructions using a 26 bytes immediate. (eg: j, jal)
 void Simulator::DecodeTypeJump(Instruction* instr) {
   // Get current pc.
@@ -1439,35 +2223,39 @@
   // Get unchanged bits of pc.
   int32_t pc_high_bits = current_pc & 0xf0000000;
   // Next pc
-  int32_t next_pc = pc_high_bits | (instr->Imm26Field() << 2);
+  int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
 
   // Execute branch delay slot
   // We don't check for end_sim_pc. First it should not be met as the current pc
   // is valid. Secondly a jump should always execute its branch delay slot.
   Instruction* branch_delay_instr =
-    reinterpret_cast<Instruction*>(current_pc+Instruction::kInstructionSize);
+    reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
   BranchDelayInstructionDecode(branch_delay_instr);
 
   // Update pc and ra if necessary.
   // Do this after the branch delay execution.
   if (instr->IsLinkingInstruction()) {
-    set_register(31, current_pc + 2* Instruction::kInstructionSize);
+    set_register(31, current_pc + 2* Instruction::kInstrSize);
   }
   set_pc(next_pc);
   pc_modified_ = true;
 }
 
+
 // Executes the current instruction.
 void Simulator::InstructionDecode(Instruction* instr) {
+  if (v8::internal::FLAG_check_icache) {
+    CheckICache(isolate_->simulator_i_cache(), instr);
+  }
   pc_modified_ = false;
   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%08x  %s\n", instr, buffer.start());
+    dasm.InstructionDecode(buffer, reinterpret_cast<byte_*>(instr));
+    PrintF("  0x%08x  %s\n", reinterpret_cast<intptr_t>(instr),
+           buffer.start());
   }
 
   switch (instr->InstructionType()) {
@@ -1485,7 +2273,7 @@
   }
   if (!pc_modified_) {
     set_register(pc, reinterpret_cast<int32_t>(instr) +
-                 Instruction::kInstructionSize);
+                 Instruction::kInstrSize);
   }
 }
 
@@ -1511,7 +2299,7 @@
       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
       icount_++;
       if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
-        Debugger dbg(this);
+        MipsDebugger dbg(this);
         dbg.Debug();
       } else {
         InstructionDecode(instr);
@@ -1538,7 +2326,7 @@
   int original_stack = get_register(sp);
   // Compute position of stack on entry to generated code.
   int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)
-                                    - kArgsSlotsSize);
+                                    - kCArgsSlotsSize);
   if (OS::ActivationFrameAlignment() != 0) {
     entry_stack &= -OS::ActivationFrameAlignment();
   }
@@ -1643,8 +2431,8 @@
 
 #undef UNSUPPORTED
 
-} }  // namespace assembler::mips
+} }  // namespace v8::internal
 
-#endif  // !__mips || USE_SIMULATOR
+#endif  // USE_SIMULATOR
 
 #endif  // V8_TARGET_ARCH_MIPS
diff --git a/src/mips/simulator-mips.h b/src/mips/simulator-mips.h
index 6e42683..0cd9bbe 100644
--- a/src/mips/simulator-mips.h
+++ b/src/mips/simulator-mips.h
@@ -37,12 +37,31 @@
 #define V8_MIPS_SIMULATOR_MIPS_H_
 
 #include "allocation.h"
+#include "constants-mips.h"
 
-#if defined(__mips) && !defined(USE_SIMULATOR)
+#if !defined(USE_SIMULATOR)
+// Running without a simulator on a native mips platform.
+
+namespace v8 {
+namespace internal {
 
 // 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);
+  entry(p0, p1, p2, p3, p4)
+
+typedef int (*mips_regexp_matcher)(String*, int, const byte*, const byte*,
+                                  void*, int*, Address, int, Isolate*);
+
+// Call the generated regexp code directly. The code at the entry address
+// should act as a function matching the type arm_regexp_matcher.
+// The fifth argument is a dummy that reserves the space used for
+// the return address added by the ExitFrame in native calls.
+#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
+  (FUNCTION_CAST<mips_regexp_matcher>(entry)(                             \
+      p0, p1, p2, p3, NULL, p4, p5, p6, p7))
+
+#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
+  reinterpret_cast<TryCatch*>(try_catch_address)
 
 // The stack limit beyond which we will throw stack overflow errors in
 // generated code. Because generated code on mips uses the C stack, we
@@ -60,6 +79,8 @@
   static inline void UnregisterCTryCatch() { }
 };
 
+} }  // namespace v8::internal
+
 // 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
@@ -70,39 +91,50 @@
   (reinterpret_cast<uintptr_t>(this) >= limit ? \
       reinterpret_cast<uintptr_t>(this) - limit : 0)
 
-// Call the generated regexp code directly. The entry function pointer should
-// expect seven int/pointer sized arguments and return an int.
-#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
-  entry(p0, p1, p2, p3, p4, p5, p6)
+#else  // !defined(USE_SIMULATOR)
+// Running with a simulator.
 
-#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
-  reinterpret_cast<TryCatch*>(try_catch_address)
+#include "hashmap.h"
 
+namespace v8 {
+namespace internal {
 
-#else  // #if !defined(__mips) || defined(USE_SIMULATOR)
+// -----------------------------------------------------------------------------
+// Utility functions
 
-// When running with the simulator transition into simulated execution at this
-// point.
-#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
-  reinterpret_cast<Object*>(\
-      assembler::mips::Simulator::current()->Call(FUNCTION_ADDR(entry), 5, \
-                                                  p0, p1, p2, p3, p4))
+class CachePage {
+ public:
+  static const int LINE_VALID = 0;
+  static const int LINE_INVALID = 1;
 
-#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
-  assembler::mips::Simulator::current()->Call(\
-    FUNCTION_ADDR(entry), 7, p0, p1, p2, p3, p4, p5, p6)
+  static const int kPageShift = 12;
+  static const int kPageSize = 1 << kPageShift;
+  static const int kPageMask = kPageSize - 1;
+  static const int kLineShift = 2;  // The cache line is only 4 bytes right now.
+  static const int kLineLength = 1 << kLineShift;
+  static const int kLineMask = kLineLength - 1;
 
-#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
-  try_catch_address == NULL ? \
-      NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
+  CachePage() {
+    memset(&validity_map_, LINE_INVALID, sizeof(validity_map_));
+  }
 
+  char* ValidityByte(int offset) {
+    return &validity_map_[offset >> kLineShift];
+  }
 
-namespace assembler {
-namespace mips {
+  char* CachedData(int offset) {
+    return &data_[offset];
+  }
+
+ private:
+  char data_[kPageSize];   // The cached data.
+  static const int kValidityMapSize = kPageSize >> kLineShift;
+  char validity_map_[kValidityMapSize];  // One byte per line.
+};
 
 class Simulator {
  public:
-  friend class Debugger;
+  friend class MipsDebugger;
 
   // Registers are declared in order. See SMRL chapter 2.
   enum Register {
@@ -143,7 +175,7 @@
 
   // The currently executing Simulator instance. Potentially there can be one
   // for each native thread.
-  static Simulator* current();
+  static Simulator* current(v8::internal::Isolate* isolate);
 
   // Accessors for register state. Reading the pc value adheres to the MIPS
   // architecture specification and is off by a 8 from the currently executing
@@ -152,9 +184,15 @@
   int32_t get_register(int reg) const;
   // Same for FPURegisters
   void set_fpu_register(int fpureg, int32_t value);
+  void set_fpu_register_float(int fpureg, float value);
   void set_fpu_register_double(int fpureg, double value);
   int32_t get_fpu_register(int fpureg) const;
+  int64_t get_fpu_register_long(int fpureg) const;
+  float get_fpu_register_float(int fpureg) const;
   double get_fpu_register_double(int fpureg) const;
+  void set_fcsr_bit(uint32_t cc, bool value);
+  bool test_fcsr_bit(uint32_t cc);
+  bool set_fcsr_round_error(double original, double rounded);
 
   // Special case of set_register and get_register to access the raw PC value.
   void set_pc(int32_t value);
@@ -172,7 +210,7 @@
   // V8 generally calls into generated JS code with 5 parameters and into
   // generated RegExp code with 7 parameters. This is a convenience function,
   // which sets up the simulator state and grabs the result on return.
-  int32_t Call(byte_* entry, int argument_count, ...);
+  int32_t Call(byte* entry, int argument_count, ...);
 
   // Push an address onto the JS stack.
   uintptr_t PushAddress(uintptr_t address);
@@ -180,6 +218,14 @@
   // Pop an address from the JS stack.
   uintptr_t PopAddress();
 
+  // ICache checking.
+  static void FlushICache(v8::internal::HashMap* i_cache, void* start,
+                          size_t size);
+
+  // Returns true if pc register contains one of the 'special_values' defined
+  // below (bad_ra, end_sim_pc).
+  bool has_bad_pc() const;
+
  private:
   enum special_values {
     // Known bad pc value to ensure that the simulator does not execute
@@ -223,9 +269,17 @@
   inline int32_t SetDoubleHIW(double* addr);
   inline int32_t SetDoubleLOW(double* addr);
 
-
   // Executing is handled based on the instruction type.
   void DecodeTypeRegister(Instruction* instr);
+
+  // Helper function for DecodeTypeRegister.
+  void ConfigureTypeRegister(Instruction* instr,
+                             int32_t& alu_out,
+                             int64_t& i64hilo,
+                             uint64_t& u64hilo,
+                             int32_t& next_pc,
+                             bool& do_interrupt);
+
   void DecodeTypeImmediate(Instruction* instr);
   void DecodeTypeJump(Instruction* instr);
 
@@ -239,11 +293,18 @@
     if (instr->IsForbiddenInBranchDelay()) {
       V8_Fatal(__FILE__, __LINE__,
                "Eror:Unexpected %i opcode in a branch delay slot.",
-               instr->OpcodeField());
+               instr->OpcodeValue());
     }
     InstructionDecode(instr);
   }
 
+  // ICache.
+  static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
+  static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
+                           int size);
+  static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
+
+
   enum Exception {
     none,
     kIntegerOverflow,
@@ -258,7 +319,7 @@
 
   // Runtime call support.
   static void* RedirectExternalReference(void* external_function,
-                                         bool fp_return);
+                                         ExternalReference::Type type);
 
   // Used for real time calls that takes two double values as arguments and
   // returns a double.
@@ -269,19 +330,40 @@
   int32_t registers_[kNumSimuRegisters];
   // Coprocessor Registers.
   int32_t FPUregisters_[kNumFPURegisters];
+  // FPU control register.
+  uint32_t FCSR_;
 
   // Simulator support.
   char* stack_;
+  size_t stack_size_;
   bool pc_modified_;
   int icount_;
-  static bool initialized_;
+  int break_count_;
+
+  // Icache simulation
+  v8::internal::HashMap* i_cache_;
 
   // Registered breakpoints.
   Instruction* break_pc_;
   Instr break_instr_;
+
+  v8::internal::Isolate* isolate_;
 };
 
-} }   // namespace assembler::mips
+
+// When running with the simulator transition into simulated execution at this
+// point.
+#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
+reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->Call( \
+      FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4))
+
+#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
+  Simulator::current(Isolate::Current())->Call( \
+      entry, 9, p0, p1, p2, p3, NULL, p4, p5, p6, p7)
+
+#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
+  try_catch_address == NULL ? \
+      NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
 
 
 // The simulator has its own stack. Thus it has a different stack limit from
@@ -292,20 +374,21 @@
 class SimulatorStack : public v8::internal::AllStatic {
  public:
   static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) {
-    return assembler::mips::Simulator::current()->StackLimit();
+    return Simulator::current(Isolate::Current())->StackLimit();
   }
 
   static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
-    assembler::mips::Simulator* sim = assembler::mips::Simulator::current();
+    Simulator* sim = Simulator::current(Isolate::Current());
     return sim->PushAddress(try_catch_address);
   }
 
   static inline void UnregisterCTryCatch() {
-    assembler::mips::Simulator::current()->PopAddress();
+    Simulator::current(Isolate::Current())->PopAddress();
   }
 };
 
-#endif  // !defined(__mips) || defined(USE_SIMULATOR)
+} }  // namespace v8::internal
 
+#endif  // !defined(USE_SIMULATOR)
 #endif  // V8_MIPS_SIMULATOR_MIPS_H_
 
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index 683b862..1a49558 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -57,6 +57,12 @@
 }
 
 
+void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
+    MacroAssembler* masm, int index, Register prototype, Label* miss) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 // 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.
@@ -75,6 +81,20 @@
 }
 
 
+// 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::GenerateLoadStringLength(MacroAssembler* masm,
+                                            Register receiver,
+                                            Register scratch1,
+                                            Register scratch2,
+                                            Label* miss,
+                                            bool support_wrappers) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
                                                  Register receiver,
                                                  Register scratch1,
@@ -84,7 +104,7 @@
 }
 
 
-// Generate StoreField code, value is passed in r0 register.
+// Generate StoreField code, value is passed in a0 register.
 // After executing generated code, the receiver_reg and name_reg
 // may be clobbered.
 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
@@ -104,15 +124,94 @@
 }
 
 
+class CallInterceptorCompiler BASE_EMBEDDED {
+ public:
+  CallInterceptorCompiler(StubCompiler* stub_compiler,
+                          const ParameterCount& arguments,
+                          Register name)
+      : stub_compiler_(stub_compiler),
+        arguments_(arguments),
+        name_(name) {}
+
+  void Compile(MacroAssembler* masm,
+               JSObject* object,
+               JSObject* holder,
+               String* name,
+               LookupResult* lookup,
+               Register receiver,
+               Register scratch1,
+               Register scratch2,
+               Register scratch3,
+               Label* miss) {
+    UNIMPLEMENTED_MIPS();
+  }
+
+ private:
+  void CompileCacheable(MacroAssembler* masm,
+                       JSObject* object,
+                       Register receiver,
+                       Register scratch1,
+                       Register scratch2,
+                       Register scratch3,
+                       JSObject* interceptor_holder,
+                       LookupResult* lookup,
+                       String* name,
+                       const CallOptimization& optimization,
+                       Label* miss_label) {
+    UNIMPLEMENTED_MIPS();
+  }
+
+  void CompileRegular(MacroAssembler* masm,
+                      JSObject* object,
+                      Register receiver,
+                      Register scratch1,
+                      Register scratch2,
+                      Register scratch3,
+                      String* name,
+                      JSObject* interceptor_holder,
+                      Label* miss_label) {
+    UNIMPLEMENTED_MIPS();
+  }
+
+  void LoadWithInterceptor(MacroAssembler* masm,
+                           Register receiver,
+                           Register holder,
+                           JSObject* holder_obj,
+                           Register scratch,
+                           Label* interceptor_succeeded) {
+    UNIMPLEMENTED_MIPS();
+  }
+
+  StubCompiler* stub_compiler_;
+  const ParameterCount& arguments_;
+  Register name_;
+};
+
+
 #undef __
 #define __ ACCESS_MASM(masm())
 
 
+Register StubCompiler::CheckPrototypes(JSObject* object,
+                                       Register object_reg,
+                                       JSObject* holder,
+                                       Register holder_reg,
+                                       Register scratch1,
+                                       Register scratch2,
+                                       String* name,
+                                       int save_at_depth,
+                                       Label* miss) {
+  UNIMPLEMENTED_MIPS();
+  return no_reg;
+}
+
+
 void StubCompiler::GenerateLoadField(JSObject* object,
                                      JSObject* holder,
                                      Register receiver,
                                      Register scratch1,
                                      Register scratch2,
+                                     Register scratch3,
                                      int index,
                                      String* name,
                                      Label* miss) {
@@ -125,6 +224,7 @@
                                         Register receiver,
                                         Register scratch1,
                                         Register scratch2,
+                                        Register scratch3,
                                         Object* value,
                                         String* name,
                                         Label* miss) {
@@ -132,282 +232,365 @@
 }
 
 
-bool StubCompiler::GenerateLoadCallback(JSObject* object,
-                                        JSObject* holder,
-                                        Register receiver,
-                                        Register name_reg,
-                                        Register scratch1,
-                                        Register scratch2,
-                                        AccessorInfo* callback,
-                                        String* name,
-                                        Label* miss,
-                                        Failure** failure) {
+MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object,
+                                                JSObject* holder,
+                                                Register receiver,
+                                                Register name_reg,
+                                                Register scratch1,
+                                                Register scratch2,
+                                                Register scratch3,
+                                                AccessorInfo* callback,
+                                                String* name,
+                                                Label* miss) {
   UNIMPLEMENTED_MIPS();
-  __ break_(0x470);
-  return false;   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
 void StubCompiler::GenerateLoadInterceptor(JSObject* object,
-                                           JSObject* holder,
+                                           JSObject* interceptor_holder,
                                            LookupResult* lookup,
                                            Register receiver,
                                            Register name_reg,
                                            Register scratch1,
                                            Register scratch2,
+                                           Register scratch3,
                                            String* name,
                                            Label* miss) {
   UNIMPLEMENTED_MIPS();
-  __ break_(0x505);
 }
 
 
-Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
-  // Registers:
-  // a1: function
-  // ra: return address
-
-  // Enter an internal frame.
-  __ EnterInternalFrame();
-  // Preserve the function.
-  __ Push(a1);
-  // Setup aligned call.
-  __ SetupAlignedCall(t0, 1);
-  // Push the function on the stack as the argument to the runtime function.
-  __ Push(a1);
-  // Call the runtime function
-  __ CallRuntime(Runtime::kLazyCompile, 1);
-  __ ReturnFromAlignedCall();
-  // Calculate the entry point.
-  __ addiu(t9, v0, Code::kHeaderSize - kHeapObjectTag);
-  // Restore saved function.
-  __ Pop(a1);
-  // Tear down temporary frame.
-  __ LeaveInternalFrame();
-  // Do a tail-call of the compiled function.
-  __ Jump(t9);
-
-  return GetCodeWithFlags(flags, "LazyCompileStub");
-}
-
-
-Object* CallStubCompiler::CompileCallField(JSObject* object,
-                                           JSObject* holder,
-                                           int index,
-                                           String* name) {
+void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
 }
 
 
-Object* CallStubCompiler::CompileArrayPushCall(Object* object,
-                                               JSObject* holder,
-                                               JSFunction* function,
-                                               String* name,
-                                               CheckType check) {
+void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object,
+                                                   JSObject* holder,
+                                                   String* name,
+                                                   Label* miss) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
 }
 
 
-Object* CallStubCompiler::CompileArrayPopCall(Object* object,
-                                              JSObject* holder,
-                                              JSFunction* function,
-                                              String* name,
-                                              CheckType check) {
+void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
+                                                    JSFunction* function,
+                                                    Label* miss) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
 }
 
 
-Object* CallStubCompiler::CompileCallConstant(Object* object,
-                                              JSObject* holder,
-                                              JSFunction* function,
-                                              String* name,
-                                              CheckType check) {
+MaybeObject* CallStubCompiler::GenerateMissBranch() {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
-Object* CallStubCompiler::CompileCallInterceptor(JSObject* object,
-                                                 JSObject* holder,
-                                                 String* name) {
-  UNIMPLEMENTED_MIPS();
-  __ break_(0x782);
-  return GetCode(INTERCEPTOR, name);
-}
-
-
-Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
-                                            GlobalObject* holder,
-                                            JSGlobalPropertyCell* cell,
-                                            JSFunction* function,
-                                            String* name) {
-  UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
-}
-
-
-Object* StoreStubCompiler::CompileStoreField(JSObject* object,
-                                             int index,
-                                             Map* transition,
-                                             String* name) {
-  UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
-}
-
-
-Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
-                                                AccessorInfo* callback,
+MaybeObject* CallStubCompiler::CompileCallField(JSObject* object,
+                                                JSObject* holder,
+                                                int index,
                                                 String* name) {
   UNIMPLEMENTED_MIPS();
-  __ break_(0x906);
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
-Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
+MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
+                                                    JSObject* holder,
+                                                    JSGlobalPropertyCell* cell,
+                                                    JSFunction* function,
+                                                    String* name) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
+                                                   JSObject* holder,
+                                                   JSGlobalPropertyCell* cell,
+                                                   JSFunction* function,
                                                    String* name) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
-Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
-                                              JSGlobalPropertyCell* cell,
-                                              String* name) {
+MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
+    Object* object,
+    JSObject* holder,
+    JSGlobalPropertyCell* cell,
+    JSFunction* function,
+    String* name) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
-Object* LoadStubCompiler::CompileLoadField(JSObject* object,
-                                           JSObject* holder,
-                                           int index,
-                                           String* name) {
+MaybeObject* CallStubCompiler::CompileStringCharAtCall(
+    Object* object,
+    JSObject* holder,
+    JSGlobalPropertyCell* cell,
+    JSFunction* function,
+    String* name) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
-Object* LoadStubCompiler::CompileLoadCallback(String* name,
-                                              JSObject* object,
-                                              JSObject* holder,
-                                              AccessorInfo* callback) {
+MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
+    Object* object,
+    JSObject* holder,
+    JSGlobalPropertyCell* cell,
+    JSFunction* function,
+    String* name) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
-Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
-                                              JSObject* holder,
-                                              Object* value,
-                                              String* name) {
+MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object,
+                                                    JSObject* holder,
+                                                    JSGlobalPropertyCell* cell,
+                                                    JSFunction* function,
+                                                    String* name) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
-Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
-                                                 JSObject* holder,
-                                                 String* name) {
+MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
+                                                  JSObject* holder,
+                                                  JSGlobalPropertyCell* cell,
+                                                  JSFunction* function,
+                                                  String* name) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
-Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
-                                            GlobalObject* holder,
-                                            JSGlobalPropertyCell* cell,
-                                            String* name,
-                                            bool is_dont_delete) {
+MaybeObject* CallStubCompiler::CompileFastApiCall(
+    const CallOptimization& optimization,
+    Object* object,
+    JSObject* holder,
+    JSGlobalPropertyCell* cell,
+    JSFunction* function,
+    String* name) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
-Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
-                                                JSObject* receiver,
-                                                JSObject* holder,
-                                                int index) {
-  UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
-}
-
-
-Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
-                                                   JSObject* receiver,
+MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
                                                    JSObject* holder,
-                                                   AccessorInfo* callback) {
+                                                   JSFunction* function,
+                                                   String* name,
+                                                   CheckType check) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
-Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
-                                                   JSObject* receiver,
-                                                   JSObject* holder,
-                                                   Object* value) {
-  UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
-}
-
-
-Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
+MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
                                                       JSObject* holder,
                                                       String* name) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
-Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
+MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
+                                                 GlobalObject* holder,
+                                                 JSGlobalPropertyCell* cell,
+                                                 JSFunction* function,
+                                                 String* name) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
-Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
-  UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
-}
-
-
-// TODO(1224671): implement the fast case.
-Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
-  UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
-}
-
-
-Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
+MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object,
                                                   int index,
                                                   Map* transition,
                                                   String* name) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
-Object* ConstructStubCompiler::CompileConstructStub(
-    SharedFunctionInfo* shared) {
+MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object,
+                                                     AccessorInfo* callback,
+                                                     String* name) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
-Object* ExternalArrayStubCompiler::CompileKeyedLoadStub(
-    ExternalArrayType array_type, Code::Flags flags) {
+MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
+                                                        String* name) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
 }
 
 
-Object* ExternalArrayStubCompiler::CompileKeyedStoreStub(
-    ExternalArrayType array_type, Code::Flags flags) {
+MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
+                                                   JSGlobalPropertyCell* cell,
+                                                   String* name) {
   UNIMPLEMENTED_MIPS();
-  return reinterpret_cast<Object*>(NULL);   // UNIMPLEMENTED RETURN
+  return NULL;
+}
+
+
+MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
+                                                      JSObject* object,
+                                                      JSObject* last) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object,
+                                                JSObject* holder,
+                                                int index,
+                                                String* name) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name,
+                                                   JSObject* object,
+                                                   JSObject* holder,
+                                                   AccessorInfo* callback) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object,
+                                                   JSObject* holder,
+                                                   Object* value,
+                                                   String* name) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
+                                                      JSObject* holder,
+                                                      String* name) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
+                                                 GlobalObject* holder,
+                                                 JSGlobalPropertyCell* cell,
+                                                 String* name,
+                                                 bool is_dont_delete) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name,
+                                                     JSObject* receiver,
+                                                     JSObject* holder,
+                                                     int index) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback(
+    String* name,
+    JSObject* receiver,
+    JSObject* holder,
+    AccessorInfo* callback) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
+                                                        JSObject* receiver,
+                                                        JSObject* holder,
+                                                        Object* value) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
+                                                           JSObject* holder,
+                                                           String* name) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
+                                                       int index,
+                                                       Map* transition,
+                                                       String* name) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized(
+    JSObject* receiver) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
+    JSObject* receiver_object,
+    ExternalArrayType array_type,
+    Code::Flags flags) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
+}
+
+
+MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
+    JSObject* receiver_object,
+    ExternalArrayType array_type,
+    Code::Flags flags) {
+  UNIMPLEMENTED_MIPS();
+  return NULL;
 }
 
 
diff --git a/test/cctest/test-mips.cc b/src/mips/virtual-frame-mips-inl.h
similarity index 72%
copy from test/cctest/test-mips.cc
copy to src/mips/virtual-frame-mips-inl.h
index efd4cc9..f0d2fab 100644
--- a/test/cctest/test-mips.cc
+++ b/src/mips/virtual-frame-mips-inl.h
@@ -25,28 +25,34 @@
 // (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_MIPS_INL_H_
+#define V8_VIRTUAL_FRAME_MIPS_INL_H_
 
-#include "v8.h"
-#include "execution.h"
+#include "assembler-mips.h"
+#include "virtual-frame-mips.h"
 
-#include "cctest.h"
+namespace v8 {
+namespace internal {
 
-using ::v8::Local;
-using ::v8::String;
-using ::v8::Script;
 
-namespace i = ::v8::internal;
-
-TEST(MIPSFunctionCalls) {
-  // Disable compilation of natives.
-  i::FLAG_disable_native_files = true;
-  i::FLAG_full_compiler = false;
-
-  v8::HandleScope scope;
-  LocalContext env;  // from cctest.h
-
-  const char* c_source = "function foo() { return 0x1234; }; foo();";
-  Local<String> source = ::v8::String::New(c_source);
-  Local<Script> script = ::v8::Script::Compile(source);
-  CHECK_EQ(0x1234,  script->Run()->Int32Value());
+MemOperand VirtualFrame::ParameterAt(int index) {
+  UNIMPLEMENTED_MIPS();
+  return MemOperand(zero_reg, 0);
 }
+
+
+// The receiver frame slot.
+MemOperand VirtualFrame::Receiver() {
+  UNIMPLEMENTED_MIPS();
+  return MemOperand(zero_reg, 0);
+}
+
+
+void VirtualFrame::Forget(int count) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_VIRTUAL_FRAME_MIPS_INL_H_
diff --git a/src/mips/virtual-frame-mips.cc b/src/mips/virtual-frame-mips.cc
index b61ce75..22fe9f0 100644
--- a/src/mips/virtual-frame-mips.cc
+++ b/src/mips/virtual-frame-mips.cc
@@ -25,8 +25,6 @@
 // (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"
 
 #if defined(V8_TARGET_ARCH_MIPS)
@@ -39,44 +37,50 @@
 namespace v8 {
 namespace internal {
 
-// -------------------------------------------------------------------------
-// VirtualFrame implementation.
-
 #define __ ACCESS_MASM(masm())
 
-void VirtualFrame::SyncElementBelowStackPointer(int index) {
-  UNREACHABLE();
+void VirtualFrame::PopToA1A0() {
+  UNIMPLEMENTED_MIPS();
 }
 
 
-void VirtualFrame::SyncElementByPushing(int index) {
-  UNREACHABLE();
+void VirtualFrame::PopToA1() {
+  UNIMPLEMENTED_MIPS();
 }
 
 
-void VirtualFrame::SyncRange(int begin, int end) {
-  // All elements are in memory on MIPS (ie, synced).
-#ifdef DEBUG
-  for (int i = begin; i <= end; i++) {
-    ASSERT(elements_[i].is_synced());
-  }
-#endif
+void VirtualFrame::PopToA0() {
+  UNIMPLEMENTED_MIPS();
 }
 
 
-void VirtualFrame::MergeTo(VirtualFrame* expected) {
+void VirtualFrame::MergeTo(const VirtualFrame* expected,
+                           Condition cond,
+                           Register r1,
+                           const Operand& r2) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void VirtualFrame::MergeTo(VirtualFrame* expected,
+                           Condition cond,
+                           Register r1,
+                           const Operand& r2) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void VirtualFrame::MergeTOSTo(
+    VirtualFrame::TopOfStack expected_top_of_stack_state,
+    Condition cond,
+    Register r1,
+    const Operand& r2) {
   UNIMPLEMENTED_MIPS();
 }
 
 
 void VirtualFrame::Enter() {
-  // TODO(MIPS): Implement DEBUG
-
-  // We are about to push four values to the frame.
-  Adjust(4);
-  __ MultiPush(ra.bit() | fp.bit() | cp.bit() | a1.bit());
-  // Adjust FP to point to saved FP.
-  __ addiu(fp, sp, 2 * kPointerSize);
+  UNIMPLEMENTED_MIPS();
 }
 
 
@@ -86,232 +90,216 @@
 
 
 void VirtualFrame::AllocateStackSlots() {
-  int count = local_count();
-  if (count > 0) {
-    Comment cmnt(masm(), "[ Allocate space for locals");
-    Adjust(count);
-      // Initialize stack slots with 'undefined' value.
-    __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
-    __ addiu(sp, sp, -count * kPointerSize);
-    for (int i = 0; i < count; i++) {
-      __ sw(t0, MemOperand(sp, (count-i-1)*kPointerSize));
-    }
-  }
-}
-
-
-void VirtualFrame::SaveContextRegister() {
   UNIMPLEMENTED_MIPS();
 }
 
 
-void VirtualFrame::RestoreContextRegister() {
-  UNIMPLEMENTED_MIPS();
-}
-
 
 void VirtualFrame::PushReceiverSlotAddress() {
   UNIMPLEMENTED_MIPS();
 }
 
 
-int VirtualFrame::InvalidateFrameSlotAt(int index) {
-  return kIllegalIndex;
-}
-
-
-void VirtualFrame::TakeFrameSlotAt(int index) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void VirtualFrame::StoreToFrameSlotAt(int index) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
 void VirtualFrame::PushTryHandler(HandlerType type) {
   UNIMPLEMENTED_MIPS();
 }
 
 
-void VirtualFrame::RawCallStub(CodeStub* stub) {
+void VirtualFrame::CallJSFunction(int arg_count) {
   UNIMPLEMENTED_MIPS();
 }
 
 
-void VirtualFrame::CallStub(CodeStub* stub, Result* arg) {
+void VirtualFrame::CallRuntime(const Runtime::Function* f, int arg_count) {
   UNIMPLEMENTED_MIPS();
 }
 
 
-void VirtualFrame::CallStub(CodeStub* stub, Result* arg0, Result* arg1) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
-  PrepareForCall(arg_count, arg_count);
-  ASSERT(cgen()->HasValidEntryRegisters());
-  __ CallRuntime(f, arg_count);
-}
-
-
 void VirtualFrame::CallRuntime(Runtime::FunctionId id, int arg_count) {
-  PrepareForCall(arg_count, arg_count);
-  ASSERT(cgen()->HasValidEntryRegisters());
-  __ CallRuntime(id, arg_count);
-}
-
-
-void VirtualFrame::CallAlignedRuntime(Runtime::Function* f, int arg_count) {
   UNIMPLEMENTED_MIPS();
 }
 
 
-void VirtualFrame::CallAlignedRuntime(Runtime::FunctionId id, int arg_count) {
+#ifdef ENABLE_DEBUGGER_SUPPORT
+void VirtualFrame::DebugBreak() {
   UNIMPLEMENTED_MIPS();
 }
+#endif
 
 
 void VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
                                  InvokeJSFlags flags,
-                                 Result* arg_count_register,
                                  int arg_count) {
   UNIMPLEMENTED_MIPS();
 }
 
 
-void VirtualFrame::CallCodeObject(Handle<Code> code,
-                                  RelocInfo::Mode rmode,
-                                  int dropped_args) {
-  switch (code->kind()) {
-    case Code::CALL_IC:
-      break;
-    case Code::FUNCTION:
-      UNIMPLEMENTED_MIPS();
-      break;
-    case Code::KEYED_LOAD_IC:
-      UNIMPLEMENTED_MIPS();
-      break;
-    case Code::LOAD_IC:
-      UNIMPLEMENTED_MIPS();
-      break;
-    case Code::KEYED_STORE_IC:
-      UNIMPLEMENTED_MIPS();
-      break;
-    case Code::STORE_IC:
-      UNIMPLEMENTED_MIPS();
-      break;
-    case Code::BUILTIN:
-      UNIMPLEMENTED_MIPS();
-      break;
-    default:
-      UNREACHABLE();
-      break;
-  }
-  Forget(dropped_args);
-  ASSERT(cgen()->HasValidEntryRegisters());
-  __ Call(code, rmode);
+void VirtualFrame::CallLoadIC(Handle<String> name, RelocInfo::Mode mode) {
+  UNIMPLEMENTED_MIPS();
 }
 
 
-void VirtualFrame::CallCodeObject(Handle<Code> code,
-                                  RelocInfo::Mode rmode,
-                                  Result* arg,
-                                  int dropped_args) {
+void VirtualFrame::CallStoreIC(Handle<String> name, bool is_contextual) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void VirtualFrame::CallKeyedLoadIC() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void VirtualFrame::CallKeyedStoreIC() {
   UNIMPLEMENTED_MIPS();
 }
 
 
 void VirtualFrame::CallCodeObject(Handle<Code> code,
                                   RelocInfo::Mode rmode,
-                                  Result* arg0,
-                                  Result* arg1,
-                                  int dropped_args,
-                                  bool set_auto_args_slots) {
+                                  int dropped_args) {
   UNIMPLEMENTED_MIPS();
 }
 
 
+//    NO_TOS_REGISTERS, A0_TOS, A1_TOS, A1_A0_TOS, A0_A1_TOS.
+const bool VirtualFrame::kA0InUse[TOS_STATES] =
+    { false,            true,   false,  true,      true };
+const bool VirtualFrame::kA1InUse[TOS_STATES] =
+    { false,            false,  true,   true,      true };
+const int VirtualFrame::kVirtualElements[TOS_STATES] =
+    { 0,                1,      1,      2,         2 };
+const Register VirtualFrame::kTopRegister[TOS_STATES] =
+    { a0,               a0,     a1,     a1,        a0 };
+const Register VirtualFrame::kBottomRegister[TOS_STATES] =
+    { a0,               a0,     a1,     a0,        a1 };
+const Register VirtualFrame::kAllocatedRegisters[
+    VirtualFrame::kNumberOfAllocatedRegisters] = { a2, a3, t0, t1, t2 };
+// Popping is done by the transition implied by kStateAfterPop.  Of course if
+// there were no stack slots allocated to registers then the physical SP must
+// be adjusted.
+const VirtualFrame::TopOfStack VirtualFrame::kStateAfterPop[TOS_STATES] =
+    { NO_TOS_REGISTERS, NO_TOS_REGISTERS, NO_TOS_REGISTERS, A0_TOS, A1_TOS };
+// Pushing is done by the transition implied by kStateAfterPush.  Of course if
+// the maximum number of registers was already allocated to the top of stack
+// slots then one register must be physically pushed onto the stack.
+const VirtualFrame::TopOfStack VirtualFrame::kStateAfterPush[TOS_STATES] =
+    { A0_TOS, A1_A0_TOS, A0_A1_TOS, A0_A1_TOS, A1_A0_TOS };
+
+
 void VirtualFrame::Drop(int count) {
-  ASSERT(count >= 0);
-  ASSERT(height() >= count);
-  int num_virtual_elements = (element_count() - 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;
-    __ addiu(sp, sp, 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());
-    }
-  }
-}
-
-
-void VirtualFrame::DropFromVFrameOnly(int count) {
   UNIMPLEMENTED_MIPS();
 }
 
 
-Result VirtualFrame::Pop() {
+void VirtualFrame::Pop() {
   UNIMPLEMENTED_MIPS();
-  Result res = Result();
-  return res;    // UNIMPLEMENTED RETURN
 }
 
 
 void VirtualFrame::EmitPop(Register reg) {
-  ASSERT(stack_pointer_ == element_count() - 1);
-  stack_pointer_--;
-  elements_.RemoveLast();
-  __ Pop(reg);
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void VirtualFrame::SpillAllButCopyTOSToA0() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void VirtualFrame::SpillAllButCopyTOSToA1() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void VirtualFrame::SpillAllButCopyTOSToA1A0() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+Register VirtualFrame::Peek() {
+  UNIMPLEMENTED_MIPS();
+  return no_reg;
+}
+
+
+Register VirtualFrame::Peek2() {
+  UNIMPLEMENTED_MIPS();
+  return no_reg;
+}
+
+
+void VirtualFrame::Dup() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void VirtualFrame::Dup2() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+Register VirtualFrame::PopToRegister(Register but_not_to_this_one) {
+  UNIMPLEMENTED_MIPS();
+  return no_reg;
+}
+
+
+void VirtualFrame::EnsureOneFreeTOSRegister() {
+  UNIMPLEMENTED_MIPS();
 }
 
 
 void VirtualFrame::EmitMultiPop(RegList regs) {
-  ASSERT(stack_pointer_ == element_count() - 1);
-  for (int16_t i = 0; i < kNumRegisters; i++) {
-    if ((regs & (1 << i)) != 0) {
-      stack_pointer_--;
-      elements_.RemoveLast();
-    }
-  }
-  __ MultiPop(regs);
+  UNIMPLEMENTED_MIPS();
 }
 
 
-void VirtualFrame::EmitPush(Register reg) {
-  ASSERT(stack_pointer_ == element_count() - 1);
-  elements_.Add(FrameElement::MemoryElement(NumberInfo::Unknown()));
-  stack_pointer_++;
-  __ Push(reg);
+void VirtualFrame::EmitPush(Register reg, TypeInfo info) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void VirtualFrame::SetElementAt(Register reg, int this_far_down) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+Register VirtualFrame::GetTOSRegister() {
+  UNIMPLEMENTED_MIPS();
+  return no_reg;
+}
+
+
+void VirtualFrame::EmitPush(Operand operand, TypeInfo info) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void VirtualFrame::EmitPush(MemOperand operand, TypeInfo info) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void VirtualFrame::EmitPushRoot(Heap::RootListIndex index) {
+  UNIMPLEMENTED_MIPS();
 }
 
 
 void VirtualFrame::EmitMultiPush(RegList regs) {
-  ASSERT(stack_pointer_ == element_count() - 1);
-  for (int16_t i = kNumRegisters; i > 0; i--) {
-    if ((regs & (1 << i)) != 0) {
-      elements_.Add(FrameElement::MemoryElement(NumberInfo::Unknown()));
-      stack_pointer_++;
-    }
-  }
-  __ MultiPush(regs);
-}
-
-
-void VirtualFrame::EmitArgumentSlots(RegList reglist) {
   UNIMPLEMENTED_MIPS();
 }
 
+
+void VirtualFrame::EmitMultiPushReversed(RegList regs) {
+  UNIMPLEMENTED_MIPS();
+}
+
+
+void VirtualFrame::SpillAll() {
+  UNIMPLEMENTED_MIPS();
+}
+
+
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/mips/virtual-frame-mips.h b/src/mips/virtual-frame-mips.h
index b32e2ae..be8b74e 100644
--- a/src/mips/virtual-frame-mips.h
+++ b/src/mips/virtual-frame-mips.h
@@ -30,11 +30,13 @@
 #define V8_MIPS_VIRTUAL_FRAME_MIPS_H_
 
 #include "register-allocator.h"
-#include "scopes.h"
 
 namespace v8 {
 namespace internal {
 
+// This dummy class is only used to create invalid virtual frames.
+extern class InvalidVirtualFrameInitializer {}* kInvalidVirtualFrameInitializer;
+
 
 // -------------------------------------------------------------------------
 // Virtual frames
@@ -47,14 +49,54 @@
 
 class VirtualFrame : public ZoneObject {
  public:
+  class RegisterAllocationScope;
   // 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.
+  // generator's current frame, and keeps it spilled.
   class SpilledScope BASE_EMBEDDED {
    public:
+    explicit SpilledScope(VirtualFrame* frame)
+      : old_is_spilled_(
+          Isolate::Current()->is_virtual_frame_in_spilled_scope()) {
+      if (frame != NULL) {
+        if (!old_is_spilled_) {
+          frame->SpillAll();
+        } else {
+          frame->AssertIsSpilled();
+        }
+      }
+      Isolate::Current()->set_is_virtual_frame_in_spilled_scope(true);
+    }
+    ~SpilledScope() {
+      Isolate::Current()->set_is_virtual_frame_in_spilled_scope(
+          old_is_spilled_);
+    }
+    static bool is_spilled() {
+      return Isolate::Current()->is_virtual_frame_in_spilled_scope();
+    }
+
+   private:
+    int old_is_spilled_;
+
     SpilledScope() {}
+
+    friend class RegisterAllocationScope;
+  };
+
+  class RegisterAllocationScope BASE_EMBEDDED {
+   public:
+    // A utility class to introduce a scope where the virtual frame
+    // is not spilled, ie. where register allocation occurs.  Eventually
+    // when RegisterAllocationScope is ubiquitous it can be removed
+    // along with the (by then unused) SpilledScope class.
+    inline explicit RegisterAllocationScope(CodeGenerator* cgen);
+    inline ~RegisterAllocationScope();
+
+   private:
+    CodeGenerator* cgen_;
+    bool old_is_spilled_;
+
+    RegisterAllocationScope() {}
   };
 
   // An illegal index into the virtual frame.
@@ -63,45 +105,49 @@
   // Construct an initial virtual frame on entry to a JS function.
   inline VirtualFrame();
 
+  // Construct an invalid virtual frame, used by JumpTargets.
+  inline VirtualFrame(InvalidVirtualFrameInitializer* dummy);
+
   // Construct a virtual frame as a clone of an existing one.
   explicit inline VirtualFrame(VirtualFrame* original);
 
-  CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
-  MacroAssembler* masm() { return cgen()->masm(); }
-
-  // Create a duplicate of an existing valid frame element.
-  FrameElement CopyElementAt(int index,
-                             NumberInfo info = NumberInfo::Unknown());
+  inline CodeGenerator* cgen() const;
+  inline MacroAssembler* masm();
 
   // The number of elements on the virtual frame.
-  int element_count() { return elements_.length(); }
+  int element_count() const { return element_count_; }
 
   // The height of the virtual expression stack.
-  int height() {
-    return element_count() - expression_base_index();
-  }
-
-  int register_location(int num) {
-    ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
-    return register_locations_[num];
-  }
-
-  int register_location(Register reg) {
-    return register_locations_[RegisterAllocator::ToNumber(reg)];
-  }
-
-  void set_register_location(Register reg, int index) {
-    register_locations_[RegisterAllocator::ToNumber(reg)] = index;
-  }
+  inline int height() const;
 
   bool is_used(int num) {
-    ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
-    return register_locations_[num] != kIllegalIndex;
-  }
-
-  bool is_used(Register reg) {
-    return register_locations_[RegisterAllocator::ToNumber(reg)]
-        != kIllegalIndex;
+    switch (num) {
+      case 0: {  // a0.
+        return kA0InUse[top_of_stack_state_];
+      }
+      case 1: {  // a1.
+        return kA1InUse[top_of_stack_state_];
+      }
+      case 2:
+      case 3:
+      case 4:
+      case 5:
+      case 6: {  // a2 to a3, t0 to t2.
+        ASSERT(num - kFirstAllocatedRegister < kNumberOfAllocatedRegisters);
+        ASSERT(num >= kFirstAllocatedRegister);
+        if ((register_allocation_map_ &
+             (1 << (num - kFirstAllocatedRegister))) == 0) {
+          return false;
+        } else {
+          return true;
+        }
+      }
+      default: {
+        ASSERT(num < kFirstAllocatedRegister ||
+               num >= kFirstAllocatedRegister + kNumberOfAllocatedRegisters);
+        return false;
+      }
+    }
   }
 
   // Add extra in-memory elements to the top of the frame to match an actual
@@ -110,53 +156,60 @@
   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) {
-    ASSERT(count >= 0);
-    ASSERT(stack_pointer_ == element_count() - 1);
-    stack_pointer_ -= count;
-    // On mips, all elements are in memory, so there is no extra bookkeeping
-    // (registers, copies, etc.) beyond dropping the elements.
-    elements_.Rewind(stack_pointer_ + 1);
-  }
+  // the frame after a runtime call). No code is emitted except to bring the
+  // frame to a spilled state.
+  void Forget(int count);
 
-  // Forget count elements from the top of the frame and adjust 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();
 
+  void AssertIsSpilled() const {
+    ASSERT(top_of_stack_state_ == NO_TOS_REGISTERS);
+    ASSERT(register_allocation_map_ == 0);
+  }
+
+  void AssertIsNotSpilled() {
+    ASSERT(!SpilledScope::is_spilled());
+  }
+
   // Spill all occurrences of a specific register from the frame.
   void Spill(Register reg) {
-    if (is_used(reg)) SpillElementAt(register_location(reg));
+    UNIMPLEMENTED();
   }
 
   // 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).
+  // (ie, they all have frame-external references). Unimplemented.
   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);
+  void MergeTo(const VirtualFrame* expected,
+               Condition cond = al,
+               Register r1 = no_reg,
+               const Operand& r2 = Operand(no_reg));
+
+  void MergeTo(VirtualFrame* expected,
+               Condition cond = al,
+               Register r1 = no_reg,
+               const Operand& r2 = Operand(no_reg));
+
+  // Checks whether this frame can be branched to by the other frame.
+  bool IsCompatibleWith(const VirtualFrame* other) const {
+    return (tos_known_smi_map_ & (~other->tos_known_smi_map_)) == 0;
+  }
+
+  inline void ForgetTypeInfo() {
+    tos_known_smi_map_ = 0;
+  }
 
   // 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() {
-    RegisterAllocator* cgen_allocator = cgen()->allocator();
-    for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
-      if (is_used(i)) cgen_allocator->Unuse(i);
-    }
   }
 
   // (Re)attach a frame to its code generator. This informs the register
@@ -164,10 +217,6 @@
   // Used when a code generator's frame is switched from NULL to this one by
   // binding a label.
   void AttachToCodeGenerator() {
-    RegisterAllocator* cgen_allocator = cgen()->allocator();
-    for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
-      if (is_used(i)) cgen_allocator->Unuse(i);
-    }
   }
 
   // Emit code for the physical JS entry and exit frame sequences. After
@@ -177,176 +226,142 @@
   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();
+  // Prepare for returning from the frame by elements in the virtual frame.
+  // This avoids generating unnecessary merge code when jumping to the shared
+  // return site. No spill code emitted. Value to return should be in v0.
+  inline void PrepareForReturn();
+
+  // Number of local variables after when we use a loop for allocating.
+  static const int kLocalVarBound = 5;
 
   // Allocate and initialize the frame-allocated locals.
   void AllocateStackSlots();
 
   // The current top of the expression stack as an assembly operand.
-  MemOperand Top() { return MemOperand(sp, 0); }
+  MemOperand Top() {
+    AssertIsSpilled();
+    return MemOperand(sp, 0);
+  }
 
   // An element of the expression stack as an assembly operand.
   MemOperand ElementAt(int index) {
-    return MemOperand(sp, index * kPointerSize);
+    int adjusted_index = index - kVirtualElements[top_of_stack_state_];
+    ASSERT(adjusted_index >= 0);
+    return MemOperand(sp, adjusted_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);
-    SetElementAt(index, &temp);
+  bool KnownSmiAt(int index) {
+    if (index >= kTOSKnownSmiMapSize) return false;
+    return (tos_known_smi_map_ & (1 << index)) != 0;
   }
-
-  void PushElementAt(int index) {
-    PushFrameSlotAt(element_count() - index - 1);
-  }
-
   // A frame-allocated local as an assembly operand.
-  MemOperand LocalAt(int index) {
-    ASSERT(0 <= index);
-    ASSERT(index < local_count());
-    return MemOperand(s8_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);
-  }
+  inline MemOperand LocalAt(int index);
 
   // Push the address of the receiver slot on the frame.
   void PushReceiverSlotAddress();
 
   // The function frame slot.
-  MemOperand Function() { return MemOperand(s8_fp, kFunctionOffset); }
-
-  // Push the function on top of the frame.
-  void PushFunction() { PushFrameSlotAt(function_index()); }
+  MemOperand Function() { return MemOperand(fp, kFunctionOffset); }
 
   // The context frame slot.
-  MemOperand Context() { return MemOperand(s8_fp, kContextOffset); }
-
-  // Save the value of the cp register to the context frame slot.
-  void SaveContextRegister();
-
-  // Restore the cp register from the value of the context frame
-  // slot.
-  void RestoreContextRegister();
+  MemOperand Context() { return MemOperand(fp, kContextOffset); }
 
   // A parameter as an assembly operand.
-  MemOperand ParameterAt(int index) {
-    // Index -1 corresponds to the receiver.
-    ASSERT(-1 <= index);  // -1 is the receiver.
-    ASSERT(index <= parameter_count());
-    uint16_t a = 0;   // Number of argument slots.
-    return MemOperand(s8_fp, (1 + parameter_count() + a - 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);
-  }
+  inline MemOperand ParameterAt(int index);
 
   // The receiver frame slot.
-  MemOperand Receiver() { return ParameterAt(-1); }
+  inline MemOperand Receiver();
 
   // 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.
-  void CallStub(CodeStub* stub, int arg_count) {
-    PrepareForCall(arg_count, arg_count);
-    RawCallStub(stub);
-  }
+  inline void CallStub(CodeStub* stub, int arg_count);
 
-  void CallStub(CodeStub* stub, Result* arg);
-
-  void CallStub(CodeStub* stub, Result* arg0, Result* arg1);
+  // Call JS function from top of the stack with arguments
+  // taken from the stack.
+  void CallJSFunction(int arg_count);
 
   // Call runtime given the number of arguments expected on (and
   // removed from) the stack.
-  void CallRuntime(Runtime::Function* f, int arg_count);
+  void CallRuntime(const Runtime::Function* f, int arg_count);
   void CallRuntime(Runtime::FunctionId id, int arg_count);
 
-  // Call runtime with sp aligned to 8 bytes.
-  void CallAlignedRuntime(Runtime::Function* f, int arg_count);
-  void CallAlignedRuntime(Runtime::FunctionId id, int arg_count);
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  void DebugBreak();
+#endif
 
   // Invoke builtin given the number of arguments it expects on (and
   // removes from) the stack.
   void InvokeBuiltin(Builtins::JavaScript id,
                      InvokeJSFlags flag,
-                     Result* arg_count_register,
                      int arg_count);
 
+  // Call load IC. Receiver is on the stack and is consumed. Result is returned
+  // in v0.
+  void CallLoadIC(Handle<String> name, RelocInfo::Mode mode);
+
+  // Call store IC. If the load is contextual, value is found on top of the
+  // frame. If not, value and receiver are on the frame. Both are consumed.
+  // Result is returned in v0.
+  void CallStoreIC(Handle<String> name, bool is_contextual);
+
+  // Call keyed load IC. Key and receiver are on the stack. Both are consumed.
+  // Result is returned in v0.
+  void CallKeyedLoadIC();
+
+  // Call keyed store IC. Value, key and receiver are on the stack. All three
+  // are consumed. Result is returned in v0 (and a0).
+  void CallKeyedStoreIC();
+
   // 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.
+  // from the stack. Register arguments to the IC stub are implicit,
+  // and depend on the type of IC stub.
   void CallCodeObject(Handle<Code> ic,
                       RelocInfo::Mode rmode,
                       int dropped_args);
-  void CallCodeObject(Handle<Code> ic,
-                      RelocInfo::Mode rmode,
-                      Result* arg,
-                      int dropped_args);
-  void CallCodeObject(Handle<Code> ic,
-                      RelocInfo::Mode rmode,
-                      Result* arg0,
-                      Result* arg1,
-                      int dropped_args,
-                      bool set_auto_args_slots = false);
 
   // 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);
-  // Similar to VirtualFrame::Drop but we don't modify the actual stack.
-  // This is because we need to manually restore sp to the correct position.
-  void DropFromVFrameOnly(int count);
 
   // Drop one element.
   void Drop() { Drop(1); }
-  void DropFromVFrameOnly() { DropFromVFrameOnly(1); }
 
-  // Duplicate the top element of the frame.
-  void Dup() { PushFrameSlotAt(element_count() - 1); }
+  // Pop an element from the top of the expression stack. Discards
+  // the result.
+  void Pop();
 
-  // Pop an element from the top of the expression stack. Returns a
-  // Result, which may be a constant or a register.
-  Result Pop();
+  // Pop an element from the top of the expression stack.  The register
+  // will be one normally used for the top of stack register allocation
+  // so you can't hold on to it if you push on the stack.
+  Register PopToRegister(Register but_not_to_this_one = no_reg);
+
+  // Look at the top of the stack.  The register returned is aliased and
+  // must be copied to a scratch register before modification.
+  Register Peek();
+
+  // Look at the value beneath the top of the stack. The register returned is
+  // aliased and must be copied to a scratch register before modification.
+  Register Peek2();
+
+  // Duplicate the top of stack.
+  void Dup();
+
+  // Duplicate the two elements on top of stack.
+  void Dup2();
+
+  // Flushes all registers, but it puts a copy of the top-of-stack in a0.
+  void SpillAllButCopyTOSToA0();
+
+  // Flushes all registers, but it puts a copy of the top-of-stack in a1.
+  void SpillAllButCopyTOSToA1();
+
+  // Flushes all registers, but it puts a copy of the top-of-stack in a1
+  // and the next value on the stack in a0.
+  void SpillAllButCopyTOSToA1A0();
 
   // Pop and save an element from the top of the expression stack and
   // emit a corresponding pop instruction.
@@ -355,40 +370,41 @@
   void EmitMultiPop(RegList regs);
   void EmitMultiPopReversed(RegList regs);
 
+
+  // Takes the top two elements and puts them in a0 (top element) and a1
+  // (second element).
+  void PopToA1A0();
+
+  // Takes the top element and puts it in a1.
+  void PopToA1();
+
+  // Takes the top element and puts it in a0.
+  void PopToA0();
+
   // Push an element on top of the expression stack and emit a
   // corresponding push instruction.
-  void EmitPush(Register reg);
+  void EmitPush(Register reg, TypeInfo type_info = TypeInfo::Unknown());
+  void EmitPush(Operand operand, TypeInfo type_info = TypeInfo::Unknown());
+  void EmitPush(MemOperand operand, TypeInfo type_info = TypeInfo::Unknown());
+  void EmitPushRoot(Heap::RootListIndex index);
+
+  // Overwrite the nth thing on the stack.  If the nth position is in a
+  // register then this turns into a Move, otherwise an sw.  Afterwards
+  // you can still use the register even if it is a register that can be
+  // used for TOS (a0 or a1).
+  void SetElementAt(Register reg, int this_far_down);
+
+  // Get a register which is free and which must be immediately used to
+  // push on the top of the stack.
+  Register GetTOSRegister();
+
   // Same but for multiple registers.
   void EmitMultiPush(RegList regs);
   void EmitMultiPushReversed(RegList regs);
 
-  // Push an element on the virtual frame.
-  inline void Push(Register reg, NumberInfo info = NumberInfo::Unknown());
-  inline void Push(Handle<Object> value);
-  inline void Push(Smi* value);
-
-  // Pushing a result invalidates it (its contents become owned by the frame).
-  void Push(Result* result) {
-    if (result->is_register()) {
-      Push(result->reg());
-    } else {
-      ASSERT(result->is_constant());
-      Push(result->handle());
-    }
-    result->Unuse();
-  }
-
-  // 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).
-  inline void Nip(int num_dropped);
-
-  // This pushes 4 arguments slots on the stack and saves asked 'a' registers
-  // 'a' registers are arguments register a0 to a3.
-  void EmitArgumentSlots(RegList reglist);
-
-  inline void SetTypeForLocalAt(int index, NumberInfo info);
-  inline void SetTypeForParamAt(int index, NumberInfo info);
+  static Register scratch0() { return t4; }
+  static Register scratch1() { return t5; }
+  static Register scratch2() { return t6; }
 
  private:
   static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
@@ -398,24 +414,51 @@
   static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize;
   static const int kPreallocatedElements = 5 + 8;  // 8 expression stack slots.
 
-  ZoneList<FrameElement> elements_;
+  // 5 states for the top of stack, which can be in memory or in a0 and a1.
+  enum TopOfStack { NO_TOS_REGISTERS, A0_TOS, A1_TOS, A1_A0_TOS, A0_A1_TOS,
+                    TOS_STATES};
+  static const int kMaxTOSRegisters = 2;
+
+  static const bool kA0InUse[TOS_STATES];
+  static const bool kA1InUse[TOS_STATES];
+  static const int kVirtualElements[TOS_STATES];
+  static const TopOfStack kStateAfterPop[TOS_STATES];
+  static const TopOfStack kStateAfterPush[TOS_STATES];
+  static const Register kTopRegister[TOS_STATES];
+  static const Register kBottomRegister[TOS_STATES];
+
+  // We allocate up to 5 locals in registers.
+  static const int kNumberOfAllocatedRegisters = 5;
+  // r2 to r6 are allocated to locals.
+  static const int kFirstAllocatedRegister = 2;
+
+  static const Register kAllocatedRegisters[kNumberOfAllocatedRegisters];
+
+  static Register AllocatedRegister(int r) {
+    ASSERT(r >= 0 && r < kNumberOfAllocatedRegisters);
+    return kAllocatedRegisters[r];
+  }
+
+  // The number of elements on the stack frame.
+  int element_count_;
+  TopOfStack top_of_stack_state_:3;
+  int register_allocation_map_:kNumberOfAllocatedRegisters;
+  static const int kTOSKnownSmiMapSize = 4;
+  unsigned tos_known_smi_map_:kTOSKnownSmiMapSize;
 
   // The index of the element that is at the processor's stack pointer
-  // (the sp register).
-  int stack_pointer_;
-
-  // The index of the register frame element using each register, or
-  // kIllegalIndex if a register is not on the frame.
-  int register_locations_[RegisterAllocator::kNumRegisters];
+  // (the sp register).  For now since everything is in memory it is given
+  // by the number of elements on the not-very-virtual stack frame.
+  int stack_pointer() { return element_count_ - 1; }
 
   // The number of frame-allocated locals and parameters respectively.
-  int parameter_count() { return cgen()->scope()->num_parameters(); }
-  int local_count() { return cgen()->scope()->num_stack_slots(); }
+  inline int parameter_count() const;
+  inline int local_count() const;
 
   // The index of the element that is at the processor's frame pointer
   // (the fp register). The parameters, receiver, function, and context
   // are below the frame pointer.
-  int frame_pointer() { return parameter_count() + 3; }
+  inline int frame_pointer() const;
 
   // The index of the first parameter. The receiver lies below the first
   // parameter.
@@ -423,75 +466,22 @@
 
   // The index of the context slot in the frame. It is immediately
   // below the frame pointer.
-  int context_index() { return frame_pointer() - 1; }
+  inline int context_index();
 
   // The index of the function slot in the frame. It is below the frame
   // pointer and context slot.
-  int function_index() { return frame_pointer() - 2; }
+  inline int function_index();
 
   // The index of the first local. Between the frame pointer and the
   // locals lies the return address.
-  int local0_index() { return frame_pointer() + 2; }
+  inline int local0_index() const;
 
   // The index of the base of the expression stack.
-  int expression_base_index() { return local0_index() + local_count(); }
+  inline int expression_base_index() const;
 
   // Convert a frame index into a frame pointer relative offset into the
   // actual stack.
-  int fp_relative(int index) {
-    ASSERT(index < element_count());
-    ASSERT(frame_pointer() < element_count());  // FP is on the frame.
-    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) {
-    ASSERT(!is_used(reg));
-    set_register_location(reg, index);
-    cgen()->allocator()->Use(reg);
-  }
-
-  // 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) {
-    ASSERT(is_used(reg));
-    set_register_location(reg, kIllegalIndex);
-    cgen()->allocator()->Unuse(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] with memory.
-  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.
-  inline 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);
+  inline int fp_relative(int index);
 
   // Spill all elements in registers. Spill the top spilled_args elements
   // on the frame. Sync all other frame elements.
@@ -499,45 +489,37 @@
   // 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);
+  // If all top-of-stack registers are in use then the lowest one is pushed
+  // onto the physical stack and made free.
+  void EnsureOneFreeTOSRegister();
 
-  // 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);
+  // Emit instructions to get the top of stack state from where we are to where
+  // we want to be.
+  void MergeTOSTo(TopOfStack expected_state,
+                  Condition cond = al,
+                  Register r1 = no_reg,
+                  const Operand& r2 = Operand(no_reg));
 
-  // 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);
+  inline bool Equals(const VirtualFrame* other);
 
-  // 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);
+  inline void LowerHeight(int count) {
+    element_count_ -= count;
+    if (count >= kTOSKnownSmiMapSize) {
+      tos_known_smi_map_ = 0;
+    } else {
+      tos_known_smi_map_ >>= count;
+    }
+  }
 
-  // Call a code stub that has already been prepared for calling (via
-  // PrepareForCall).
-  void RawCallStub(CodeStub* stub);
-
-  // Calls a code object which has already been prepared for calling
-  // (via PrepareForCall).
-  void RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode);
-
-  inline bool Equals(VirtualFrame* other);
-
-  // Classes that need raw access to the elements_ array.
-  friend class DeferredCode;
+  inline void RaiseHeight(int count, unsigned known_smi_map = 0) {
+    ASSERT(known_smi_map < (1u << count));
+    element_count_ += count;
+    if (count >= kTOSKnownSmiMapSize) {
+      tos_known_smi_map_ = known_smi_map;
+    } else {
+      tos_known_smi_map_ = ((tos_known_smi_map_ << count) | known_smi_map);
+    }
+  }
   friend class JumpTarget;
 };
 
diff --git a/src/mirror-debugger.js b/src/mirror-debugger.js
index 416f887..99e9819 100644
--- a/src/mirror-debugger.js
+++ b/src/mirror-debugger.js
@@ -170,14 +170,15 @@
 
 // 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;
+PropertyType.Normal                  = 0;
+PropertyType.Field                   = 1;
+PropertyType.ConstantFunction        = 2;
+PropertyType.Callbacks               = 3;
+PropertyType.Interceptor             = 4;
+PropertyType.MapTransition           = 5;
+PropertyType.ExternalArrayTransition = 6;
+PropertyType.ConstantTransition      = 7;
+PropertyType.NullDescriptor          = 8;
 
 
 // Different attributes for a property.
diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc
index a30b450..6ecbc8c 100644
--- a/src/mksnapshot.cc
+++ b/src/mksnapshot.cc
@@ -223,12 +223,12 @@
   // Make sure all builtin scripts are cached.
   { HandleScope scope;
     for (int i = 0; i < i::Natives::GetBuiltinsCount(); i++) {
-      i::Bootstrapper::NativesSourceLookup(i);
+      i::Isolate::Current()->bootstrapper()->NativesSourceLookup(i);
     }
   }
   // If we don't do this then we end up with a stray root pointing at the
   // context even after we have disposed of the context.
-  i::Heap::CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
   i::Object* raw_context = *(v8::Utils::OpenHandle(*context));
   context.Dispose();
   CppByteSink sink(argv[1]);
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index c1caef2..dd606dc 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -91,8 +91,8 @@
     case BYTE_ARRAY_TYPE:
       ByteArray::cast(this)->ByteArrayVerify();
       break;
-    case PIXEL_ARRAY_TYPE:
-      PixelArray::cast(this)->PixelArrayVerify();
+    case EXTERNAL_PIXEL_ARRAY_TYPE:
+      ExternalPixelArray::cast(this)->ExternalPixelArrayVerify();
       break;
     case EXTERNAL_BYTE_ARRAY_TYPE:
       ExternalByteArray::cast(this)->ExternalByteArrayVerify();
@@ -178,7 +178,7 @@
 
 void HeapObject::VerifyHeapPointer(Object* p) {
   ASSERT(p->IsHeapObject());
-  ASSERT(Heap::Contains(HeapObject::cast(p)));
+  ASSERT(HEAP->Contains(HeapObject::cast(p)));
 }
 
 
@@ -192,8 +192,8 @@
 }
 
 
-void PixelArray::PixelArrayVerify() {
-  ASSERT(IsPixelArray());
+void ExternalPixelArray::ExternalPixelArrayVerify() {
+  ASSERT(IsExternalPixelArray());
 }
 
 
@@ -241,18 +241,18 @@
               map()->NextFreePropertyIndex()));
   }
   ASSERT(map()->has_fast_elements() ==
-         (elements()->map() == Heap::fixed_array_map() ||
-          elements()->map() == Heap::fixed_cow_array_map()));
+         (elements()->map() == GetHeap()->fixed_array_map() ||
+          elements()->map() == GetHeap()->fixed_cow_array_map()));
   ASSERT(map()->has_fast_elements() == HasFastElements());
 }
 
 
 void Map::MapVerify() {
-  ASSERT(!Heap::InNewSpace(this));
+  ASSERT(!HEAP->InNewSpace(this));
   ASSERT(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
   ASSERT(instance_size() == kVariableSizeSentinel ||
          (kPointerSize <= instance_size() &&
-          instance_size() < Heap::Capacity()));
+          instance_size() < HEAP->Capacity()));
   VerifyHeapPointer(prototype());
   VerifyHeapPointer(instance_descriptors());
 }
@@ -261,8 +261,7 @@
 void Map::SharedMapVerify() {
   MapVerify();
   ASSERT(is_shared());
-  ASSERT_EQ(Heap::empty_descriptor_array(), instance_descriptors());
-  ASSERT_EQ(Heap::empty_fixed_array(), code_cache());
+  ASSERT_EQ(GetHeap()->empty_descriptor_array(), instance_descriptors());
   ASSERT_EQ(0, pre_allocated_property_fields());
   ASSERT_EQ(0, unused_property_fields());
   ASSERT_EQ(StaticVisitorBase::GetVisitorId(instance_type(), instance_size()),
@@ -316,7 +315,7 @@
   CHECK(IsString());
   CHECK(length() >= 0 && length() <= Smi::kMaxValue);
   if (IsSymbol()) {
-    CHECK(!Heap::InNewSpace(this));
+    CHECK(!HEAP->InNewSpace(this));
   }
 }
 
@@ -380,7 +379,7 @@
   VerifyHeapPointer(to_string());
   Object* number = to_number();
   if (number->IsHeapObject()) {
-    ASSERT(number == Heap::nan_value());
+    ASSERT(number == HEAP->nan_value());
   } else {
     ASSERT(number->IsSmi());
     int value = Smi::cast(number)->value();
@@ -591,16 +590,17 @@
       int holes = 0;
       FixedArray* e = FixedArray::cast(elements());
       int len = e->length();
+      Heap* heap = HEAP;
       for (int i = 0; i < len; i++) {
-        if (e->get(i) == Heap::the_hole_value()) holes++;
+        if (e->get(i) == heap->the_hole_value()) holes++;
       }
       info->number_of_fast_used_elements_   += len - holes;
       info->number_of_fast_unused_elements_ += holes;
       break;
     }
-    case PIXEL_ELEMENTS: {
+    case EXTERNAL_PIXEL_ELEMENTS: {
       info->number_of_objects_with_fast_elements_++;
-      PixelArray* e = PixelArray::cast(elements());
+      ExternalPixelArray* e = ExternalPixelArray::cast(elements());
       info->number_of_fast_used_elements_ += e->length();
       break;
     }
diff --git a/src/objects-inl.h b/src/objects-inl.h
index dedb199..5395bbb 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -39,9 +39,10 @@
 #include "contexts.h"
 #include "conversions-inl.h"
 #include "heap.h"
-#include "memory.h"
+#include "isolate.h"
 #include "property.h"
 #include "spaces.h"
+#include "v8memory.h"
 
 namespace v8 {
 namespace internal {
@@ -78,7 +79,16 @@
   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);                      \
+    CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode);           \
+  }
+
+
+// GC-safe accessors do not use HeapObject::GetHeap(), but access TLS instead.
+#define ACCESSORS_GCSAFE(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(HEAP, this, offset, mode);                \
   }
 
 
@@ -330,9 +340,10 @@
 }
 
 
-bool Object::IsPixelArray() {
+bool Object::IsExternalPixelArray() {
   return Object::IsHeapObject() &&
-      HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
+      HeapObject::cast(this)->map()->instance_type() ==
+          EXTERNAL_PIXEL_ARRAY_TYPE;
 }
 
 
@@ -418,7 +429,7 @@
 
 
 bool MaybeObject::IsTheHole() {
-  return this == Heap::the_hole_value();
+  return !IsFailure() && ToObjectUnchecked()->IsTheHole();
 }
 
 
@@ -486,22 +497,27 @@
 
 
 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());
+  if (Object::IsHeapObject()) {
+    Heap* heap = HeapObject::cast(this)->GetHeap();
+    return (HeapObject::cast(this)->map() == heap->context_map() ||
+            HeapObject::cast(this)->map() == heap->catch_context_map() ||
+            HeapObject::cast(this)->map() == heap->global_context_map());
+  }
+  return false;
 }
 
 
 bool Object::IsCatchContext() {
-  return Object::IsHeapObject()
-      && HeapObject::cast(this)->map() == Heap::catch_context_map();
+  return Object::IsHeapObject() &&
+      HeapObject::cast(this)->map() ==
+      HeapObject::cast(this)->GetHeap()->catch_context_map();
 }
 
 
 bool Object::IsGlobalContext() {
-  return Object::IsHeapObject()
-      && HeapObject::cast(this)->map() == Heap::global_context_map();
+  return Object::IsHeapObject() &&
+      HeapObject::cast(this)->map() ==
+      HeapObject::cast(this)->GetHeap()->global_context_map();
 }
 
 
@@ -523,6 +539,7 @@
 
 
 bool Object::IsOddball() {
+  ASSERT(HEAP->is_safe_to_read_maps());
   return Object::IsHeapObject()
     && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
 }
@@ -567,7 +584,8 @@
 
 
 bool Object::IsBoolean() {
-  return IsTrue() || IsFalse();
+  return IsOddball() &&
+      ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
 }
 
 
@@ -589,18 +607,21 @@
 
 
 bool Object::IsHashTable() {
-  return Object::IsHeapObject()
-      && HeapObject::cast(this)->map() == Heap::hash_table_map();
+  return Object::IsHeapObject() &&
+      HeapObject::cast(this)->map() ==
+      HeapObject::cast(this)->GetHeap()->hash_table_map();
 }
 
 
 bool Object::IsDictionary() {
-  return IsHashTable() && this != Heap::symbol_table();
+  return IsHashTable() && this !=
+         HeapObject::cast(this)->GetHeap()->symbol_table();
 }
 
 
 bool Object::IsSymbolTable() {
-  return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
+  return IsHashTable() && this ==
+         HeapObject::cast(this)->GetHeap()->raw_unchecked_symbol_table();
 }
 
 
@@ -717,27 +738,32 @@
 
 
 bool Object::IsUndefined() {
-  return this == Heap::undefined_value();
+  return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
 }
 
 
 bool Object::IsNull() {
-  return this == Heap::null_value();
+  return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
+}
+
+
+bool Object::IsTheHole() {
+  return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
 }
 
 
 bool Object::IsTrue() {
-  return this == Heap::true_value();
+  return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
 }
 
 
 bool Object::IsFalse() {
-  return this == Heap::false_value();
+  return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
 }
 
 
 bool Object::IsArgumentsMarker() {
-  return this == Heap::arguments_marker();
+  return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
 }
 
 
@@ -749,7 +775,6 @@
 }
 
 
-
 MaybeObject* Object::ToSmi() {
   if (IsSmi()) return this;
   if (IsHeapNumber()) {
@@ -772,7 +797,7 @@
   // GetElement can trigger a getter which can cause allocation.
   // This was not always the case. This ASSERT is here to catch
   // leftover incorrect uses.
-  ASSERT(Heap::IsAllocationAllowed());
+  ASSERT(HEAP->IsAllocationAllowed());
   return GetElementWithReceiver(this, index);
 }
 
@@ -806,28 +831,62 @@
 #define WRITE_FIELD(p, offset, value) \
   (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
 
-
+// TODO(isolates): Pass heap in to these macros.
 #define WRITE_BARRIER(object, offset) \
-  Heap::RecordWrite(object->address(), offset);
+  object->GetHeap()->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) \
+#define CONDITIONAL_WRITE_BARRIER(heap, object, offset, mode) \
   if (mode == UPDATE_WRITE_BARRIER) { \
-    Heap::RecordWrite(object->address(), offset); \
+    heap->RecordWrite(object->address(), offset); \
   } else { \
     ASSERT(mode == SKIP_WRITE_BARRIER); \
-    ASSERT(Heap::InNewSpace(object) || \
-           !Heap::InNewSpace(READ_FIELD(object, offset)) || \
+    ASSERT(heap->InNewSpace(object) || \
+           !heap->InNewSpace(READ_FIELD(object, offset)) || \
            Page::FromAddress(object->address())->           \
                IsRegionDirty(object->address() + offset));  \
   }
 
-#define READ_DOUBLE_FIELD(p, offset) \
-  (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
+#ifndef V8_TARGET_ARCH_MIPS
+  #define READ_DOUBLE_FIELD(p, offset) \
+    (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
+#else  // V8_TARGET_ARCH_MIPS
+  // Prevent gcc from using load-double (mips ldc1) on (possibly)
+  // non-64-bit aligned HeapNumber::value.
+  static inline double read_double_field(HeapNumber* p, int offset) {
+    union conversion {
+      double d;
+      uint32_t u[2];
+    } c;
+    c.u[0] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)));
+    c.u[1] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4)));
+    return c.d;
+  }
+  #define READ_DOUBLE_FIELD(p, offset) read_double_field(p, offset)
+#endif  // V8_TARGET_ARCH_MIPS
 
-#define WRITE_DOUBLE_FIELD(p, offset, value) \
-  (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
+
+#ifndef V8_TARGET_ARCH_MIPS
+  #define WRITE_DOUBLE_FIELD(p, offset, value) \
+    (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
+#else  // V8_TARGET_ARCH_MIPS
+  // Prevent gcc from using store-double (mips sdc1) on (possibly)
+  // non-64-bit aligned HeapNumber::value.
+  static inline void write_double_field(HeapNumber* p, int offset,
+                                        double value) {
+    union conversion {
+      double d;
+      uint32_t u[2];
+    } c;
+    c.d = value;
+    (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) = c.u[0];
+    (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4))) = c.u[1];
+  }
+  #define WRITE_DOUBLE_FIELD(p, offset, value) \
+    write_double_field(p, offset, value)
+#endif  // V8_TARGET_ARCH_MIPS
+
 
 #define READ_INT_FIELD(p, offset) \
   (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
@@ -1098,6 +1157,21 @@
 #endif
 
 
+Heap* HeapObject::GetHeap() {
+  // During GC, the map pointer in HeapObject is used in various ways that
+  // prevent us from retrieving Heap from the map.
+  // Assert that we are not in GC, implement GC code in a way that it doesn't
+  // pull heap from the map.
+  ASSERT(HEAP->is_safe_to_read_maps());
+  return map()->heap();
+}
+
+
+Isolate* HeapObject::GetIsolate() {
+  return GetHeap()->isolate();
+}
+
+
 Map* HeapObject::map() {
   return map_word().ToMap();
 }
@@ -1215,34 +1289,32 @@
 HeapObject* JSObject::elements() {
   Object* array = READ_FIELD(this, kElementsOffset);
   // In the assert below Dictionary is covered under FixedArray.
-  ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
-         array->IsExternalArray());
+  ASSERT(array->IsFixedArray() || array->IsExternalArray());
   return reinterpret_cast<HeapObject*>(array);
 }
 
 
 void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) {
   ASSERT(map()->has_fast_elements() ==
-         (value->map() == Heap::fixed_array_map() ||
-          value->map() == Heap::fixed_cow_array_map()));
+         (value->map() == GetHeap()->fixed_array_map() ||
+          value->map() == GetHeap()->fixed_cow_array_map()));
   // In the assert below Dictionary is covered under FixedArray.
-  ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
-         value->IsExternalArray());
+  ASSERT(value->IsFixedArray() || value->IsExternalArray());
   WRITE_FIELD(this, kElementsOffset, value);
-  CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
+  CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, mode);
 }
 
 
 void JSObject::initialize_properties() {
-  ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
-  WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
+  ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
+  WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array());
 }
 
 
 void JSObject::initialize_elements() {
   ASSERT(map()->has_fast_elements());
-  ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
-  WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
+  ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
+  WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array());
 }
 
 
@@ -1261,6 +1333,16 @@
 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
 
 
+byte Oddball::kind() {
+  return READ_BYTE_FIELD(this, kKindOffset);
+}
+
+
+void Oddball::set_kind(byte value) {
+  WRITE_BYTE_FIELD(this, kKindOffset, value);
+}
+
+
 Object* JSGlobalPropertyCell::value() {
   return READ_FIELD(this, kValueOffset);
 }
@@ -1314,6 +1396,12 @@
 }
 
 
+int JSObject::GetInternalFieldOffset(int index) {
+  ASSERT(index < GetInternalFieldCount() && index >= 0);
+  return GetHeaderSize() + (kPointerSize * index);
+}
+
+
 Object* JSObject::GetInternalField(int index) {
   ASSERT(index < GetInternalFieldCount() && index >= 0);
   // Internal objects do follow immediately after the header, whereas in-object
@@ -1365,6 +1453,14 @@
 }
 
 
+int JSObject::GetInObjectPropertyOffset(int index) {
+  // Adjust for the number of properties stored in the object.
+  index -= map()->inobject_properties();
+  ASSERT(index < 0);
+  return map()->instance_size() + (index * kPointerSize);
+}
+
+
 Object* JSObject::InObjectPropertyAt(int index) {
   // Adjust for the number of properties stored in the object.
   index -= map()->inobject_properties();
@@ -1382,14 +1478,14 @@
   ASSERT(index < 0);
   int offset = map()->instance_size() + (index * kPointerSize);
   WRITE_FIELD(this, offset, value);
-  CONDITIONAL_WRITE_BARRIER(this, offset, mode);
+  CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode);
   return value;
 }
 
 
 
 void JSObject::InitializeBody(int object_size, Object* value) {
-  ASSERT(!value->IsHeapObject() || !Heap::InNewSpace(value));
+  ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
   for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
     WRITE_FIELD(this, offset, value);
   }
@@ -1412,7 +1508,7 @@
 
 
 void Struct::InitializeBody(int object_size) {
-  Object* value = Heap::undefined_value();
+  Object* value = GetHeap()->undefined_value();
   for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
     WRITE_FIELD(this, offset, value);
   }
@@ -1458,7 +1554,7 @@
 
 
 void FixedArray::set(int index, Smi* value) {
-  ASSERT(map() != Heap::fixed_cow_array_map());
+  ASSERT(map() != HEAP->fixed_cow_array_map());
   ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
   int offset = kHeaderSize + index * kPointerSize;
   WRITE_FIELD(this, offset, value);
@@ -1466,7 +1562,7 @@
 
 
 void FixedArray::set(int index, Object* value) {
-  ASSERT(map() != Heap::fixed_cow_array_map());
+  ASSERT(map() != HEAP->fixed_cow_array_map());
   ASSERT(index >= 0 && index < this->length());
   int offset = kHeaderSize + index * kPointerSize;
   WRITE_FIELD(this, offset, value);
@@ -1475,7 +1571,7 @@
 
 
 WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
-  if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
+  if (GetHeap()->InNewSpace(this)) return SKIP_WRITE_BARRIER;
   return UPDATE_WRITE_BARRIER;
 }
 
@@ -1483,44 +1579,55 @@
 void FixedArray::set(int index,
                      Object* value,
                      WriteBarrierMode mode) {
-  ASSERT(map() != Heap::fixed_cow_array_map());
+  ASSERT(map() != HEAP->fixed_cow_array_map());
   ASSERT(index >= 0 && index < this->length());
   int offset = kHeaderSize + index * kPointerSize;
   WRITE_FIELD(this, offset, value);
-  CONDITIONAL_WRITE_BARRIER(this, offset, mode);
+  CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode);
 }
 
 
 void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
-  ASSERT(array->map() != Heap::raw_unchecked_fixed_cow_array_map());
+  ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
   ASSERT(index >= 0 && index < array->length());
-  ASSERT(!Heap::InNewSpace(value));
+  ASSERT(!HEAP->InNewSpace(value));
   WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
 }
 
 
 void FixedArray::set_undefined(int index) {
-  ASSERT(map() != Heap::fixed_cow_array_map());
+  ASSERT(map() != HEAP->fixed_cow_array_map());
+  set_undefined(GetHeap(), index);
+}
+
+
+void FixedArray::set_undefined(Heap* heap, int index) {
   ASSERT(index >= 0 && index < this->length());
-  ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
+  ASSERT(!heap->InNewSpace(heap->undefined_value()));
   WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
-              Heap::undefined_value());
+              heap->undefined_value());
 }
 
 
 void FixedArray::set_null(int index) {
-  ASSERT(map() != Heap::fixed_cow_array_map());
+  set_null(GetHeap(), index);
+}
+
+
+void FixedArray::set_null(Heap* heap, int index) {
   ASSERT(index >= 0 && index < this->length());
-  ASSERT(!Heap::InNewSpace(Heap::null_value()));
-  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
+  ASSERT(!heap->InNewSpace(heap->null_value()));
+  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
 }
 
 
 void FixedArray::set_the_hole(int index) {
-  ASSERT(map() != Heap::fixed_cow_array_map());
+  ASSERT(map() != HEAP->fixed_cow_array_map());
   ASSERT(index >= 0 && index < this->length());
-  ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
-  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
+  ASSERT(!HEAP->InNewSpace(HEAP->the_hole_value()));
+  WRITE_FIELD(this,
+              kHeaderSize + index * kPointerSize,
+              GetHeap()->the_hole_value());
 }
 
 
@@ -1531,19 +1638,20 @@
 }
 
 
-void FixedArray::set_unchecked(int index,
+void FixedArray::set_unchecked(Heap* heap,
+                               int index,
                                Object* value,
                                WriteBarrierMode mode) {
   int offset = kHeaderSize + index * kPointerSize;
   WRITE_FIELD(this, offset, value);
-  CONDITIONAL_WRITE_BARRIER(this, offset, mode);
+  CONDITIONAL_WRITE_BARRIER(heap, this, offset, mode);
 }
 
 
-void FixedArray::set_null_unchecked(int index) {
+void FixedArray::set_null_unchecked(Heap* heap, int index) {
   ASSERT(index >= 0 && index < this->length());
-  ASSERT(!Heap::InNewSpace(Heap::null_value()));
-  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
+  ASSERT(!HEAP->InNewSpace(heap->null_value()));
+  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
 }
 
 
@@ -1553,9 +1661,9 @@
 
 
 bool DescriptorArray::IsEmpty() {
-  ASSERT(this == Heap::empty_descriptor_array() ||
-         this->length() > 2);
-  return this == Heap::empty_descriptor_array();
+  ASSERT(this->length() > kFirstIndex ||
+         this == HEAP->empty_descriptor_array());
+  return length() <= kFirstIndex;
 }
 
 
@@ -1585,10 +1693,10 @@
 
 
 int DescriptorArray::SearchWithCache(String* name) {
-  int number = DescriptorLookupCache::Lookup(this, name);
+  int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name);
   if (number == DescriptorLookupCache::kAbsent) {
     number = Search(name);
-    DescriptorLookupCache::Update(this, name, number);
+    GetIsolate()->descriptor_lookup_cache()->Update(this, name, number);
   }
   return number;
 }
@@ -1648,7 +1756,8 @@
 
 bool DescriptorArray::IsTransition(int descriptor_number) {
   PropertyType t = GetType(descriptor_number);
-  return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
+  return t == MAP_TRANSITION || t == CONSTANT_TRANSITION ||
+      t == EXTERNAL_ARRAY_TRANSITION;
 }
 
 
@@ -1674,8 +1783,8 @@
   ASSERT(descriptor_number < number_of_descriptors());
 
   // Make sure none of the elements in desc are in new space.
-  ASSERT(!Heap::InNewSpace(desc->GetKey()));
-  ASSERT(!Heap::InNewSpace(desc->GetValue()));
+  ASSERT(!HEAP->InNewSpace(desc->GetKey()));
+  ASSERT(!HEAP->InNewSpace(desc->GetValue()));
 
   fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
   FixedArray* content_array = GetContentArray();
@@ -1700,6 +1809,30 @@
 }
 
 
+template<typename Shape, typename Key>
+int HashTable<Shape, Key>::FindEntry(Key key) {
+  return FindEntry(GetIsolate(), key);
+}
+
+
+// Find entry for key otherwise return kNotFound.
+template<typename Shape, typename Key>
+int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) {
+  uint32_t capacity = Capacity();
+  uint32_t entry = FirstProbe(Shape::Hash(key), capacity);
+  uint32_t count = 1;
+  // EnsureCapacity will guarantee the hash table is never full.
+  while (true) {
+    Object* element = KeyAt(entry);
+    if (element == isolate->heap()->undefined_value()) break;  // Empty entry.
+    if (element != isolate->heap()->null_value() &&
+        Shape::IsMatch(key, element)) return entry;
+    entry = NextProbe(entry, count++, capacity);
+  }
+  return kNotFound;
+}
+
+
 bool NumberDictionary::requires_slow_elements() {
   Object* max_index_object = get(kMaxNumberKeyIndex);
   if (!max_index_object->IsSmi()) return false;
@@ -1760,7 +1893,6 @@
 CAST_ACCESSOR(JSRegExp)
 CAST_ACCESSOR(Proxy)
 CAST_ACCESSOR(ByteArray)
-CAST_ACCESSOR(PixelArray)
 CAST_ACCESSOR(ExternalArray)
 CAST_ACCESSOR(ExternalByteArray)
 CAST_ACCESSOR(ExternalUnsignedByteArray)
@@ -1769,6 +1901,7 @@
 CAST_ACCESSOR(ExternalIntArray)
 CAST_ACCESSOR(ExternalUnsignedIntArray)
 CAST_ACCESSOR(ExternalFloatArray)
+CAST_ACCESSOR(ExternalPixelArray)
 CAST_ACCESSOR(Struct)
 
 
@@ -1787,7 +1920,6 @@
 SMI_ACCESSORS(FixedArray, length, kLengthOffset)
 SMI_ACCESSORS(ByteArray, length, kLengthOffset)
 
-INT_ACCESSORS(PixelArray, length, kLengthOffset)
 INT_ACCESSORS(ExternalArray, length, kLengthOffset)
 
 
@@ -1947,7 +2079,7 @@
 
 void ConsString::set_first(String* value, WriteBarrierMode mode) {
   WRITE_FIELD(this, kFirstOffset, value);
-  CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
+  CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, mode);
 }
 
 
@@ -1963,7 +2095,7 @@
 
 void ConsString::set_second(String* value, WriteBarrierMode mode) {
   WRITE_FIELD(this, kSecondOffset, value);
-  CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
+  CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, mode);
 }
 
 
@@ -1999,7 +2131,7 @@
   int cache_size = size();
   Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
   MemsetPointer(entries_start,
-                Heap::the_hole_value(),
+                GetHeap()->the_hole_value(),
                 cache_size - kEntriesIndex);
   MakeZeroSize();
 }
@@ -2054,28 +2186,21 @@
 }
 
 
-uint8_t* PixelArray::external_pointer() {
-  intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
-  return reinterpret_cast<uint8_t*>(ptr);
+uint8_t* ExternalPixelArray::external_pixel_pointer() {
+  return reinterpret_cast<uint8_t*>(external_pointer());
 }
 
 
-void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
-  intptr_t ptr = reinterpret_cast<intptr_t>(value);
-  WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
-}
-
-
-uint8_t PixelArray::get(int index) {
+uint8_t ExternalPixelArray::get(int index) {
   ASSERT((index >= 0) && (index < this->length()));
-  uint8_t* ptr = external_pointer();
+  uint8_t* ptr = external_pixel_pointer();
   return ptr[index];
 }
 
 
-void PixelArray::set(int index, uint8_t value) {
+void ExternalPixelArray::set(int index, uint8_t value) {
   ASSERT((index >= 0) && (index < this->length()));
-  uint8_t* ptr = external_pointer();
+  uint8_t* ptr = external_pixel_pointer();
   ptr[index] = value;
 }
 
@@ -2553,6 +2678,19 @@
 }
 
 
+ExternalArrayType Code::external_array_type() {
+  ASSERT(is_external_array_load_stub() || is_external_array_store_stub());
+  byte type = READ_BYTE_FIELD(this, kExternalArrayTypeOffset);
+  return static_cast<ExternalArrayType>(type);
+}
+
+
+void Code::set_external_array_type(ExternalArrayType value) {
+  ASSERT(is_external_array_load_stub() || is_external_array_store_stub());
+  WRITE_BYTE_FIELD(this, kExternalArrayTypeOffset, value);
+}
+
+
 byte Code::binary_op_type() {
   ASSERT(is_binary_op_stub());
   return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
@@ -2710,6 +2848,20 @@
 }
 
 
+Isolate* Map::isolate() {
+  return heap()->isolate();
+}
+
+
+Heap* Map::heap() {
+  // NOTE: address() helper is not used to save one instruction.
+  Heap* heap = Page::FromAddress(reinterpret_cast<Address>(this))->heap_;
+  ASSERT(heap != NULL);
+  ASSERT(heap->isolate() == Isolate::Current());
+  return heap;
+}
+
+
 Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
   return HeapObject::
       FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
@@ -2724,7 +2876,7 @@
 void Map::set_prototype(Object* value, WriteBarrierMode mode) {
   ASSERT(value->IsNull() || value->IsJSObject());
   WRITE_FIELD(this, kPrototypeOffset, value);
-  CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
+  CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, mode);
 }
 
 
@@ -2736,7 +2888,7 @@
   }
   Map* new_map = Map::cast(obj);
   new_map->set_has_fast_elements(true);
-  Counters::map_slow_to_fast_elements.Increment();
+  isolate()->counters()->map_slow_to_fast_elements()->Increment();
   return new_map;
 }
 
@@ -2749,23 +2901,7 @@
   }
   Map* new_map = Map::cast(obj);
   new_map->set_has_fast_elements(false);
-  Counters::map_fast_to_slow_elements.Increment();
-  return new_map;
-}
-
-
-MaybeObject* Map::GetPixelArrayElementsMap() {
-  if (has_pixel_array_elements()) return this;
-  // TODO(danno): Special case empty object map (or most common case)
-  // to return a pre-canned pixel array map.
-  Object* obj;
-  { MaybeObject* maybe_obj = CopyDropTransitions();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
-  Map* new_map = Map::cast(obj);
-  new_map->set_has_fast_elements(false);
-  new_map->set_has_pixel_array_elements(true);
-  Counters::map_to_pixel_array_elements.Increment();
+  isolate()->counters()->map_fast_to_slow_elements()->Increment();
   return new_map;
 }
 
@@ -2777,7 +2913,8 @@
 
 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
 ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
-ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset)
+ACCESSORS_GCSAFE(JSFunction, next_function_link, Object,
+                 kNextFunctionLinkOffset)
 
 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
 ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
@@ -2866,8 +3003,8 @@
 #endif
 
 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
-ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
-ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
+ACCESSORS_GCSAFE(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
+ACCESSORS_GCSAFE(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
 ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
           kInstanceClassNameOffset)
 ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
@@ -2995,7 +3132,7 @@
 
 
 bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
-  return initial_map() != Heap::undefined_value();
+  return initial_map() != HEAP->undefined_value();
 }
 
 
@@ -3074,7 +3211,7 @@
 
 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
   WRITE_FIELD(this, kCodeOffset, value);
-  CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
+  ASSERT(!Isolate::Current()->heap()->InNewSpace(value));
 }
 
 
@@ -3087,7 +3224,7 @@
 void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
                                         WriteBarrierMode mode) {
   WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
-  CONDITIONAL_WRITE_BARRIER(this, kScopeInfoOffset, mode);
+  CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kScopeInfoOffset, mode);
 }
 
 
@@ -3102,7 +3239,8 @@
 
 
 bool SharedFunctionInfo::is_compiled() {
-  return code() != Builtins::builtin(Builtins::LazyCompile);
+  return code() !=
+      Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
 }
 
 
@@ -3162,7 +3300,7 @@
 
 
 bool JSFunction::IsMarkedForLazyRecompilation() {
-  return code() == Builtins::builtin(Builtins::LazyRecompile);
+  return code() == GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile);
 }
 
 
@@ -3179,7 +3317,7 @@
 
 void JSFunction::set_code(Code* value) {
   // Skip the write barrier because code is never in new space.
-  ASSERT(!Heap::InNewSpace(value));
+  ASSERT(!HEAP->InNewSpace(value));
   Address entry = value->entry();
   WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
 }
@@ -3219,7 +3357,7 @@
 
 
 void JSFunction::set_context(Object* value) {
-  ASSERT(value == Heap::undefined_value() || value->IsContext());
+  ASSERT(value->IsUndefined() || value->IsContext());
   WRITE_FIELD(this, kContextOffset, value);
   WRITE_BARRIER(this, kContextOffset);
 }
@@ -3276,7 +3414,7 @@
 
 
 bool JSFunction::is_compiled() {
-  return code() != Builtins::builtin(Builtins::LazyCompile);
+  return code() != GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
 }
 
 
@@ -3309,7 +3447,7 @@
                                                    Code* value) {
   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
   WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
-  ASSERT(!Heap::InNewSpace(value));
+  ASSERT(!HEAP->InNewSpace(value));
 }
 
 
@@ -3459,8 +3597,8 @@
 
 JSObject::ElementsKind JSObject::GetElementsKind() {
   if (map()->has_fast_elements()) {
-    ASSERT(elements()->map() == Heap::fixed_array_map() ||
-           elements()->map() == Heap::fixed_cow_array_map());
+    ASSERT(elements()->map() == GetHeap()->fixed_array_map() ||
+           elements()->map() == GetHeap()->fixed_cow_array_map());
     return FAST_ELEMENTS;
   }
   HeapObject* array = elements();
@@ -3470,6 +3608,7 @@
     ASSERT(array->IsDictionary());
     return DICTIONARY_ELEMENTS;
   }
+  ASSERT(!map()->has_fast_elements());
   if (array->IsExternalArray()) {
     switch (array->map()->instance_type()) {
       case EXTERNAL_BYTE_ARRAY_TYPE:
@@ -3484,13 +3623,14 @@
         return EXTERNAL_INT_ELEMENTS;
       case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
         return EXTERNAL_UNSIGNED_INT_ELEMENTS;
+      case EXTERNAL_PIXEL_ARRAY_TYPE:
+        return EXTERNAL_PIXEL_ELEMENTS;
       default:
-        ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
-        return EXTERNAL_FLOAT_ELEMENTS;
+        break;
     }
   }
-  ASSERT(array->IsPixelArray());
-  return PIXEL_ELEMENTS;
+  ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
+  return EXTERNAL_FLOAT_ELEMENTS;
 }
 
 
@@ -3504,55 +3644,34 @@
 }
 
 
-bool JSObject::HasPixelElements() {
-  return GetElementsKind() == PIXEL_ELEMENTS;
-}
-
-
 bool JSObject::HasExternalArrayElements() {
-  return (HasExternalByteElements() ||
-          HasExternalUnsignedByteElements() ||
-          HasExternalShortElements() ||
-          HasExternalUnsignedShortElements() ||
-          HasExternalIntElements() ||
-          HasExternalUnsignedIntElements() ||
-          HasExternalFloatElements());
+  HeapObject* array = elements();
+  ASSERT(array != NULL);
+  return array->IsExternalArray();
 }
 
 
-bool JSObject::HasExternalByteElements() {
-  return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
+#define EXTERNAL_ELEMENTS_CHECK(name, type)          \
+bool JSObject::HasExternal##name##Elements() {       \
+  HeapObject* array = elements();                    \
+  ASSERT(array != NULL);                             \
+  if (!array->IsHeapObject())                        \
+    return false;                                    \
+  return array->map()->instance_type() == type;      \
 }
 
 
-bool JSObject::HasExternalUnsignedByteElements() {
-  return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
-}
-
-
-bool JSObject::HasExternalShortElements() {
-  return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
-}
-
-
-bool JSObject::HasExternalUnsignedShortElements() {
-  return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
-}
-
-
-bool JSObject::HasExternalIntElements() {
-  return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
-}
-
-
-bool JSObject::HasExternalUnsignedIntElements() {
-  return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
-}
-
-
-bool JSObject::HasExternalFloatElements() {
-  return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
-}
+EXTERNAL_ELEMENTS_CHECK(Byte, EXTERNAL_BYTE_ARRAY_TYPE)
+EXTERNAL_ELEMENTS_CHECK(UnsignedByte, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
+EXTERNAL_ELEMENTS_CHECK(Short, EXTERNAL_SHORT_ARRAY_TYPE)
+EXTERNAL_ELEMENTS_CHECK(UnsignedShort,
+                        EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
+EXTERNAL_ELEMENTS_CHECK(Int, EXTERNAL_INT_ARRAY_TYPE)
+EXTERNAL_ELEMENTS_CHECK(UnsignedInt,
+                        EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
+EXTERNAL_ELEMENTS_CHECK(Float,
+                        EXTERNAL_FLOAT_ARRAY_TYPE)
+EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE)
 
 
 bool JSObject::HasNamedInterceptor() {
@@ -3567,7 +3686,7 @@
 
 bool JSObject::AllowsSetElementsLength() {
   bool result = elements()->IsFixedArray();
-  ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
+  ASSERT(result == !HasExternalArrayElements());
   return result;
 }
 
@@ -3575,16 +3694,17 @@
 MaybeObject* JSObject::EnsureWritableFastElements() {
   ASSERT(HasFastElements());
   FixedArray* elems = FixedArray::cast(elements());
-  if (elems->map() != Heap::fixed_cow_array_map()) return elems;
+  Isolate* isolate = GetIsolate();
+  if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
   Object* writable_elems;
-  { MaybeObject* maybe_writable_elems =
-        Heap::CopyFixedArrayWithMap(elems, Heap::fixed_array_map());
+  { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap(
+      elems, isolate->heap()->fixed_array_map());
     if (!maybe_writable_elems->ToObject(&writable_elems)) {
       return maybe_writable_elems;
     }
   }
   set_elements(FixedArray::cast(writable_elems));
-  Counters::cow_arrays_converted.Increment();
+  isolate->counters()->cow_arrays_converted()->Increment();
   return writable_elems;
 }
 
@@ -3685,6 +3805,22 @@
 }
 
 
+template <typename schar>
+uint32_t HashSequentialString(const schar* chars, int length) {
+  StringHasher hasher(length);
+  if (!hasher.has_trivial_hash()) {
+    int i;
+    for (i = 0; hasher.is_array_index() && (i < length); i++) {
+      hasher.AddCharacter(chars[i]);
+    }
+    for (; i < length; i++) {
+      hasher.AddCharacterNoIndex(chars[i]);
+    }
+  }
+  return hasher.GetHashField();
+}
+
+
 bool String::AsArrayIndex(uint32_t* index) {
   uint32_t field = hash_field();
   if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
@@ -3708,7 +3844,7 @@
 Object* JSObject::BypassGlobalProxy() {
   if (IsJSGlobalProxy()) {
     Object* proto = GetPrototype();
-    if (proto->IsNull()) return Heap::undefined_value();
+    if (proto->IsNull()) return GetHeap()->undefined_value();
     ASSERT(proto->IsJSGlobalObject());
     return proto;
   }
@@ -3719,7 +3855,7 @@
 bool JSObject::HasHiddenPropertiesObject() {
   ASSERT(!IsJSGlobalProxy());
   return GetPropertyAttributePostInterceptor(this,
-                                             Heap::hidden_symbol(),
+                                             GetHeap()->hidden_symbol(),
                                              false) != ABSENT;
 }
 
@@ -3732,7 +3868,7 @@
   // object.
   Object* result =
       GetLocalPropertyPostInterceptor(this,
-                                      Heap::hidden_symbol(),
+                                      GetHeap()->hidden_symbol(),
                                       &attributes)->ToObjectUnchecked();
   return result;
 }
@@ -3740,7 +3876,7 @@
 
 MaybeObject* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
   ASSERT(!IsJSGlobalProxy());
-  return SetPropertyPostInterceptor(Heap::hidden_symbol(),
+  return SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
                                     hidden_obj,
                                     DONT_ENUM,
                                     kNonStrictMode);
@@ -3808,12 +3944,57 @@
 }
 
 
-void Map::ClearCodeCache() {
+bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
+  ASSERT(other->IsNumber());
+  return key == static_cast<uint32_t>(other->Number());
+}
+
+
+uint32_t NumberDictionaryShape::Hash(uint32_t key) {
+  return ComputeIntegerHash(key);
+}
+
+
+uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) {
+  ASSERT(other->IsNumber());
+  return ComputeIntegerHash(static_cast<uint32_t>(other->Number()));
+}
+
+
+MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) {
+  return Isolate::Current()->heap()->NumberFromUint32(key);
+}
+
+
+bool StringDictionaryShape::IsMatch(String* key, Object* other) {
+  // We know that all entries in a hash table had their hash keys created.
+  // Use that knowledge to have fast failure.
+  if (key->Hash() != String::cast(other)->Hash()) return false;
+  return key->Equals(String::cast(other));
+}
+
+
+uint32_t StringDictionaryShape::Hash(String* key) {
+  return key->Hash();
+}
+
+
+uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
+  return String::cast(other)->Hash();
+}
+
+
+MaybeObject* StringDictionaryShape::AsObject(String* key) {
+  return key;
+}
+
+
+void Map::ClearCodeCache(Heap* heap) {
   // 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::raw_unchecked_empty_fixed_array()));
-  WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
+  ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array()));
+  WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array());
 }
 
 
@@ -3826,7 +4007,7 @@
     // constantly growing.
     Expand(required_size + (required_size >> 3));
     // It's a performance benefit to keep a frequently used array in new-space.
-  } else if (!Heap::new_space()->Contains(elts) &&
+  } else if (!GetHeap()->new_space()->Contains(elts) &&
              required_size < kArraySizeThatFitsComfortablyInNewSpace) {
     // Expand will allocate a new backing store in new space even if the size
     // we asked for isn't larger than what we had before.
@@ -3848,7 +4029,22 @@
 
 MaybeObject* FixedArray::Copy() {
   if (length() == 0) return this;
-  return Heap::CopyFixedArray(this);
+  return GetHeap()->CopyFixedArray(this);
+}
+
+
+Relocatable::Relocatable(Isolate* isolate) {
+  ASSERT(isolate == Isolate::Current());
+  isolate_ = isolate;
+  prev_ = isolate->relocatable_top();
+  isolate->set_relocatable_top(this);
+}
+
+
+Relocatable::~Relocatable() {
+  ASSERT(isolate_ == Isolate::Current());
+  ASSERT_EQ(isolate_->relocatable_top(), this);
+  isolate_->set_relocatable_top(prev_);
 }
 
 
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 237358d..b7e2fdd 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -88,8 +88,8 @@
     case BYTE_ARRAY_TYPE:
       ByteArray::cast(this)->ByteArrayPrint(out);
       break;
-    case PIXEL_ARRAY_TYPE:
-      PixelArray::cast(this)->PixelArrayPrint(out);
+    case EXTERNAL_PIXEL_ARRAY_TYPE:
+      ExternalPixelArray::cast(this)->ExternalPixelArrayPrint(out);
       break;
     case EXTERNAL_BYTE_ARRAY_TYPE:
       ExternalByteArray::cast(this)->ExternalByteArrayPrint(out);
@@ -177,8 +177,8 @@
 }
 
 
-void PixelArray::PixelArrayPrint(FILE* out) {
-  PrintF(out, "pixel array");
+void ExternalPixelArray::ExternalPixelArrayPrint(FILE* out) {
+  PrintF(out, "external pixel array");
 }
 
 
@@ -271,8 +271,8 @@
       }
       break;
     }
-    case PIXEL_ELEMENTS: {
-      PixelArray* p = PixelArray::cast(elements());
+    case EXTERNAL_PIXEL_ELEMENTS: {
+      ExternalPixelArray* p = ExternalPixelArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
         PrintF(out, "   %d: %d\n", i, p->get(i));
       }
@@ -372,7 +372,7 @@
     case EXTERNAL_STRING_TYPE: return "EXTERNAL_STRING";
     case FIXED_ARRAY_TYPE: return "FIXED_ARRAY";
     case BYTE_ARRAY_TYPE: return "BYTE_ARRAY";
-    case PIXEL_ARRAY_TYPE: return "PIXEL_ARRAY";
+    case EXTERNAL_PIXEL_ARRAY_TYPE: return "EXTERNAL_PIXEL_ARRAY";
     case EXTERNAL_BYTE_ARRAY_TYPE: return "EXTERNAL_BYTE_ARRAY";
     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
       return "EXTERNAL_UNSIGNED_BYTE_ARRAY";
diff --git a/src/objects-visiting.cc b/src/objects-visiting.cc
index 5f054bd..5a23658 100644
--- a/src/objects-visiting.cc
+++ b/src/objects-visiting.cc
@@ -113,7 +113,7 @@
       return kVisitJSFunction;
 
     case HEAP_NUMBER_TYPE:
-    case PIXEL_ARRAY_TYPE:
+    case EXTERNAL_PIXEL_ARRAY_TYPE:
     case EXTERNAL_BYTE_ARRAY_TYPE:
     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
     case EXTERNAL_SHORT_ARRAY_TYPE:
diff --git a/src/objects-visiting.h b/src/objects-visiting.h
index ea6d795..42f9060 100644
--- a/src/objects-visiting.h
+++ b/src/objects-visiting.h
@@ -186,14 +186,15 @@
 template<typename StaticVisitor>
 class BodyVisitorBase : public AllStatic {
  public:
-  INLINE(static void IteratePointers(HeapObject* object,
+  INLINE(static void IteratePointers(Heap* heap,
+                                     HeapObject* object,
                                      int start_offset,
                                      int end_offset)) {
     Object** start_slot = reinterpret_cast<Object**>(object->address() +
                                                      start_offset);
     Object** end_slot = reinterpret_cast<Object**>(object->address() +
                                                    end_offset);
-    StaticVisitor::VisitPointers(start_slot, end_slot);
+    StaticVisitor::VisitPointers(heap, start_slot, end_slot);
   }
 };
 
@@ -204,7 +205,10 @@
   static inline ReturnType Visit(Map* map, HeapObject* object) {
     int object_size = BodyDescriptor::SizeOf(map, object);
     BodyVisitorBase<StaticVisitor>::IteratePointers(
-        object, BodyDescriptor::kStartOffset, object_size);
+        map->heap(),
+        object,
+        BodyDescriptor::kStartOffset,
+        object_size);
     return static_cast<ReturnType>(object_size);
   }
 
@@ -212,7 +216,10 @@
   static inline ReturnType VisitSpecialized(Map* map, HeapObject* object) {
     ASSERT(BodyDescriptor::SizeOf(map, object) == object_size);
     BodyVisitorBase<StaticVisitor>::IteratePointers(
-        object, BodyDescriptor::kStartOffset, object_size);
+        map->heap(),
+        object,
+        BodyDescriptor::kStartOffset,
+        object_size);
     return static_cast<ReturnType>(object_size);
   }
 };
@@ -223,7 +230,10 @@
  public:
   static inline ReturnType Visit(Map* map, HeapObject* object) {
     BodyVisitorBase<StaticVisitor>::IteratePointers(
-        object, BodyDescriptor::kStartOffset, BodyDescriptor::kEndOffset);
+        map->heap(),
+        object,
+        BodyDescriptor::kStartOffset,
+        BodyDescriptor::kEndOffset);
     return static_cast<ReturnType>(BodyDescriptor::kSize);
   }
 };
@@ -299,8 +309,8 @@
     return table_.GetVisitor(map)(map, obj);
   }
 
-  static inline void VisitPointers(Object** start, Object** end) {
-    for (Object** p = start; p < end; p++) StaticVisitor::VisitPointer(p);
+  static inline void VisitPointers(Heap* heap, Object** start, Object** end) {
+    for (Object** p = start; p < end; p++) StaticVisitor::VisitPointer(heap, p);
   }
 
  private:
@@ -372,7 +382,7 @@
 
 
 template<typename StaticVisitor>
-void Code::CodeIterateBody() {
+void Code::CodeIterateBody(Heap* heap) {
   int mode_mask = RelocInfo::kCodeTargetMask |
                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
                   RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
@@ -386,12 +396,14 @@
   RelocIterator it(this, mode_mask);
 
   StaticVisitor::VisitPointer(
+      heap,
       reinterpret_cast<Object**>(this->address() + kRelocationInfoOffset));
   StaticVisitor::VisitPointer(
+      heap,
       reinterpret_cast<Object**>(this->address() + kDeoptimizationDataOffset));
 
   for (; !it.done(); it.next()) {
-    it.rinfo()->template Visit<StaticVisitor>();
+    it.rinfo()->template Visit<StaticVisitor>(heap);
   }
 }
 
diff --git a/src/objects.cc b/src/objects.cc
index 4c00591..8cb36e9 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -51,7 +51,6 @@
 #include "disassembler.h"
 #endif
 
-
 namespace v8 {
 namespace internal {
 
@@ -64,7 +63,8 @@
 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor,
                                                   Object* value) {
   Object* result;
-  { MaybeObject* maybe_result = Heap::AllocateJSObject(constructor);
+  { MaybeObject* maybe_result =
+        constructor->GetHeap()->AllocateJSObject(constructor);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   JSValue::cast(result)->set_value(value);
@@ -86,14 +86,19 @@
 
 
 MaybeObject* Object::ToObject() {
-  Context* global_context = Top::context()->global_context();
   if (IsJSObject()) {
     return this;
   } else if (IsNumber()) {
+    Isolate* isolate = Isolate::Current();
+    Context* global_context = isolate->context()->global_context();
     return CreateJSValue(global_context->number_function(), this);
   } else if (IsBoolean()) {
+    Isolate* isolate = HeapObject::cast(this)->GetIsolate();
+    Context* global_context = isolate->context()->global_context();
     return CreateJSValue(global_context->boolean_function(), this);
   } else if (IsString()) {
+    Isolate* isolate = HeapObject::cast(this)->GetIsolate();
+    Context* global_context = isolate->context()->global_context();
     return CreateJSValue(global_context->string_function(), this);
   }
 
@@ -103,35 +108,43 @@
 
 
 Object* Object::ToBoolean() {
-  if (IsTrue()) return Heap::true_value();
-  if (IsFalse()) return Heap::false_value();
+  if (IsTrue()) return this;
+  if (IsFalse()) return this;
   if (IsSmi()) {
-    return Heap::ToBoolean(Smi::cast(this)->value() != 0);
+    return Isolate::Current()->heap()->ToBoolean(Smi::cast(this)->value() != 0);
   }
-  if (IsUndefined() || IsNull()) return Heap::false_value();
+  if (IsUndefined() || IsNull()) {
+    return HeapObject::cast(this)->GetHeap()->false_value();
+  }
   // Undetectable object is false
   if (IsUndetectableObject()) {
-    return Heap::false_value();
+    return HeapObject::cast(this)->GetHeap()->false_value();
   }
   if (IsString()) {
-    return Heap::ToBoolean(String::cast(this)->length() != 0);
+    return HeapObject::cast(this)->GetHeap()->ToBoolean(
+        String::cast(this)->length() != 0);
   }
   if (IsHeapNumber()) {
     return HeapNumber::cast(this)->HeapNumberToBoolean();
   }
-  return Heap::true_value();
+  return Isolate::Current()->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()) {
+    Heap* heap = HeapObject::cast(this)->GetHeap();
+    Context* global_context = heap->isolate()->context()->global_context();
     holder = global_context->string_function()->instance_prototype();
   } else if (IsNumber()) {
+    Heap* heap = Isolate::Current()->heap();
+    Context* global_context = heap->isolate()->context()->global_context();
     holder = global_context->number_function()->instance_prototype();
   } else if (IsBoolean()) {
+    Heap* heap = HeapObject::cast(this)->GetHeap();
+    Context* global_context = heap->isolate()->context()->global_context();
     holder = global_context->boolean_function()->instance_prototype();
   }
   ASSERT(holder != NULL);  // Cannot handle null or undefined.
@@ -154,6 +167,7 @@
                                              Object* structure,
                                              String* name,
                                              Object* holder) {
+  Isolate* isolate = name->GetIsolate();
   // 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.
@@ -161,7 +175,7 @@
     AccessorDescriptor* callback =
         reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy());
     MaybeObject* value = (callback->getter)(receiver, callback->data);
-    RETURN_IF_SCHEDULED_EXCEPTION();
+    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
     return value;
   }
 
@@ -174,17 +188,19 @@
     JSObject* self = JSObject::cast(receiver);
     JSObject* holder_handle = JSObject::cast(holder);
     Handle<String> key(name);
-    LOG(ApiNamedPropertyAccess("load", self, name));
-    CustomArguments args(data->data(), self, holder_handle);
+    LOG(isolate, ApiNamedPropertyAccess("load", self, name));
+    CustomArguments args(isolate, data->data(), self, holder_handle);
     v8::AccessorInfo info(args.end());
     v8::Handle<v8::Value> result;
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       result = call_fun(v8::Utils::ToLocal(key), info);
     }
-    RETURN_IF_SCHEDULED_EXCEPTION();
-    if (result.IsEmpty()) return Heap::undefined_value();
+    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+    if (result.IsEmpty()) {
+      return isolate->heap()->undefined_value();
+    }
     return *v8::Utils::OpenHandle(*result);
   }
 
@@ -196,7 +212,7 @@
                                                   JSFunction::cast(getter));
     }
     // Getter is not a function.
-    return Heap::undefined_value();
+    return isolate->heap()->undefined_value();
   }
 
   UNREACHABLE();
@@ -210,9 +226,10 @@
   Handle<JSFunction> fun(JSFunction::cast(getter));
   Handle<Object> self(receiver);
 #ifdef ENABLE_DEBUGGER_SUPPORT
+  Debug* debug = fun->GetHeap()->isolate()->debug();
   // Handle stepping into a getter if step into is active.
-  if (Debug::StepInActive()) {
-    Debug::HandleStepIn(fun, Handle<Object>::null(), 0, false);
+  if (debug->StepInActive()) {
+    debug->HandleStepIn(fun, Handle<Object>::null(), 0, false);
   }
 #endif
   bool has_pending_exception;
@@ -230,6 +247,7 @@
     LookupResult* result,
     String* name,
     PropertyAttributes* attributes) {
+  Heap* heap = name->GetHeap();
   if (result->IsProperty()) {
     switch (result->type()) {
       case CALLBACKS: {
@@ -281,8 +299,8 @@
 
   // No accessible property found.
   *attributes = ABSENT;
-  Top::ReportFailedAccessCheck(this, v8::ACCESS_GET);
-  return Heap::undefined_value();
+  heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET);
+  return heap->undefined_value();
 }
 
 
@@ -291,6 +309,7 @@
     LookupResult* result,
     String* name,
     bool continue_search) {
+  Heap* heap = name->GetHeap();
   if (result->IsProperty()) {
     switch (result->type()) {
       case CALLBACKS: {
@@ -344,7 +363,7 @@
     }
   }
 
-  Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+  heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   return ABSENT;
 }
 
@@ -378,16 +397,14 @@
                                              Object* value,
                                              PropertyDetails details) {
   ASSERT(!HasFastProperties());
+  Heap* heap = name->GetHeap();
   int entry = property_dictionary()->FindEntry(name);
   if (entry == StringDictionary::kNotFound) {
     Object* store_value = value;
     if (IsGlobalObject()) {
-      { MaybeObject* maybe_store_value =
-            Heap::AllocateJSGlobalPropertyCell(value);
-        if (!maybe_store_value->ToObject(&store_value)) {
-          return maybe_store_value;
-        }
-      }
+      MaybeObject* maybe_store_value =
+          heap->AllocateJSGlobalPropertyCell(value);
+      if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
     }
     Object* dict;
     { MaybeObject* maybe_dict =
@@ -416,6 +433,7 @@
 
 MaybeObject* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) {
   ASSERT(!HasFastProperties());
+  Heap* heap = GetHeap();
   StringDictionary* dictionary = property_dictionary();
   int entry = dictionary->FindEntry(name);
   if (entry != StringDictionary::kNotFound) {
@@ -423,7 +441,7 @@
     if (IsGlobalObject()) {
       PropertyDetails details = dictionary->DetailsAt(entry);
       if (details.IsDontDelete()) {
-        if (mode != FORCE_DELETION) return Heap::false_value();
+        if (mode != FORCE_DELETION) return heap->false_value();
         // When forced to delete global properties, we have to make a
         // map change to invalidate any ICs that think they can load
         // from the DontDelete cell without checking if it contains
@@ -436,13 +454,13 @@
       }
       JSGlobalPropertyCell* cell =
           JSGlobalPropertyCell::cast(dictionary->ValueAt(entry));
-      cell->set_value(Heap::the_hole_value());
+      cell->set_value(heap->the_hole_value());
       dictionary->DetailsAtPut(entry, details.AsDeleted());
     } else {
       return dictionary->DeleteProperty(entry, mode);
     }
   }
-  return Heap::true_value();
+  return heap->true_value();
 }
 
 
@@ -468,6 +486,7 @@
   // Make sure that the top context does not change when doing
   // callbacks or interceptor calls.
   AssertNoContextChange ncc;
+  Heap* heap = name->GetHeap();
 
   // Traverse the prototype chain from the current object (this) to
   // the holder and check for access rights. This avoid traversing the
@@ -475,7 +494,7 @@
   // 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->IsProperty() ? result->holder() : Heap::null_value();
+  Object* last = result->IsProperty() ? 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
@@ -483,7 +502,7 @@
       // 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)) {
+      if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) {
         return checked->GetPropertyWithFailedAccessCheck(receiver,
                                                          result,
                                                          name,
@@ -498,7 +517,7 @@
 
   if (!result->IsProperty()) {
     *attributes = ABSENT;
-    return Heap::undefined_value();
+    return heap->undefined_value();
   }
   *attributes = result->GetAttributes();
   Object* value;
@@ -507,11 +526,11 @@
     case NORMAL:
       value = holder->GetNormalizedProperty(result);
       ASSERT(!value->IsTheHole() || result->IsReadOnly());
-      return value->IsTheHole() ? Heap::undefined_value() : value;
+      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;
+      return value->IsTheHole() ? heap->undefined_value() : value;
     case CONSTANT_FUNCTION:
       return result->GetConstantFunction();
     case CALLBACKS:
@@ -536,7 +555,7 @@
   }
 
   Object* holder = NULL;
-  Context* global_context = Top::context()->global_context();
+  Context* global_context = Isolate::Current()->context()->global_context();
   if (IsString()) {
     holder = global_context->string_function()->instance_prototype();
   } else if (IsNumber()) {
@@ -546,7 +565,7 @@
   } else {
     // Undefined and null have no indexed properties.
     ASSERT(IsUndefined() || IsNull());
-    return Heap::undefined_value();
+    return HEAP->undefined_value();
   }
 
   return JSObject::cast(holder)->GetElementWithReceiver(receiver, index);
@@ -556,14 +575,15 @@
 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();
+  Heap* heap = Isolate::Current()->heap();
+  Context* context = heap->isolate()->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();
+    return heap->null_value();
   }
 }
 
@@ -637,9 +657,10 @@
   // 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;
+  if (!HEAP->IsAllocationAllowed()) return this;
 #endif
 
+  Heap* heap = GetHeap();
   switch (StringShape(this).representation_tag()) {
     case kConsStringTag: {
       ConsString* cs = ConsString::cast(this);
@@ -649,12 +670,12 @@
       // 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) ? pretenure : TENURED;
+      PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED;
       int len = length();
       Object* object;
       String* result;
       if (IsAsciiRepresentation()) {
-        { MaybeObject* maybe_object = Heap::AllocateRawAsciiString(len, tenure);
+        { MaybeObject* maybe_object = heap->AllocateRawAsciiString(len, tenure);
           if (!maybe_object->ToObject(&object)) return maybe_object;
         }
         result = String::cast(object);
@@ -669,7 +690,7 @@
                     len - first_length);
       } else {
         { MaybeObject* maybe_object =
-              Heap::AllocateRawTwoByteString(len, tenure);
+              heap->AllocateRawTwoByteString(len, tenure);
           if (!maybe_object->ToObject(&object)) return maybe_object;
         }
         result = String::cast(object);
@@ -684,7 +705,7 @@
                     len - first_length);
       }
       cs->set_first(result);
-      cs->set_second(Heap::empty_string());
+      cs->set_second(heap->empty_string());
       return result;
     }
     default:
@@ -708,7 +729,7 @@
                   resource->length() * sizeof(smart_chars[0])) == 0);
   }
 #endif  // DEBUG
-
+  Heap* heap = GetHeap();
   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
@@ -724,8 +745,8 @@
   // Morph the object to an external string by adjusting the map and
   // reinitializing the fields.
   this->set_map(is_ascii ?
-                Heap::external_string_with_ascii_data_map() :
-                Heap::external_string_map());
+                heap->external_string_with_ascii_data_map() :
+                heap->external_string_map());
   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
   self->set_length(length);
   self->set_hash_field(hash_field);
@@ -736,13 +757,13 @@
     self->Hash();  // Force regeneration of the hash value.
     // Now morph this external string into a external symbol.
     this->set_map(is_ascii ?
-                  Heap::external_symbol_with_ascii_data_map() :
-                  Heap::external_symbol_map());
+                  heap->external_symbol_with_ascii_data_map() :
+                  heap->external_symbol_map());
   }
 
   // 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);
+  heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
   return true;
 }
 
@@ -759,7 +780,7 @@
                   resource->length() * sizeof(smart_chars[0])) == 0);
   }
 #endif  // DEBUG
-
+  Heap* heap = GetHeap();
   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
@@ -773,7 +794,7 @@
 
   // Morph the object to an external string by adjusting the map and
   // reinitializing the fields.
-  this->set_map(Heap::external_ascii_string_map());
+  this->set_map(heap->external_ascii_string_map());
   ExternalAsciiString* self = ExternalAsciiString::cast(this);
   self->set_length(length);
   self->set_hash_field(hash_field);
@@ -783,12 +804,12 @@
   if (is_symbol) {
     self->Hash();  // Force regeneration of the hash value.
     // Now morph this external string into a external symbol.
-    this->set_map(Heap::external_ascii_symbol_map());
+    this->set_map(heap->external_ascii_symbol_map());
   }
 
   // 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);
+  heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
   return true;
 }
 
@@ -887,15 +908,16 @@
     // All other JSObjects are rather similar to each other (JSObject,
     // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
     default: {
+      Heap* heap = GetHeap();
       Object* constructor = map()->constructor();
       bool printed = false;
       if (constructor->IsHeapObject() &&
-          !Heap::Contains(HeapObject::cast(constructor))) {
+          !heap->Contains(HeapObject::cast(constructor))) {
         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
       } else {
         bool global_object = IsJSGlobalProxy();
         if (constructor->IsJSFunction()) {
-          if (!Heap::Contains(JSFunction::cast(constructor)->shared())) {
+          if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
           } else {
             Object* constructor_name =
@@ -930,12 +952,13 @@
 
 
 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
-  // if (!Heap::InNewSpace(this)) PrintF("*", this);
-  if (!Heap::Contains(this)) {
+  // if (!HEAP->InNewSpace(this)) PrintF("*", this);
+  Heap* heap = GetHeap();
+  if (!heap->Contains(this)) {
     accumulator->Add("!!!INVALID POINTER!!!");
     return;
   }
-  if (!Heap::Contains(map())) {
+  if (!heap->Contains(map())) {
     accumulator->Add("!!!INVALID MAP!!!");
     return;
   }
@@ -960,8 +983,9 @@
     case BYTE_ARRAY_TYPE:
       accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
       break;
-    case PIXEL_ARRAY_TYPE:
-      accumulator->Add("<PixelArray[%u]>", PixelArray::cast(this)->length());
+    case EXTERNAL_PIXEL_ARRAY_TYPE:
+      accumulator->Add("<ExternalPixelArray[%u]>",
+                       ExternalPixelArray::cast(this)->length());
       break;
     case EXTERNAL_BYTE_ARRAY_TYPE:
       accumulator->Add("<ExternalByteArray[%u]>",
@@ -1112,7 +1136,7 @@
     case HEAP_NUMBER_TYPE:
     case FILLER_TYPE:
     case BYTE_ARRAY_TYPE:
-    case PIXEL_ARRAY_TYPE:
+    case EXTERNAL_PIXEL_ARRAY_TYPE:
     case EXTERNAL_BYTE_ARRAY_TYPE:
     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
     case EXTERNAL_SHORT_ARRAY_TYPE:
@@ -1149,14 +1173,14 @@
   if (u.bits.exp == 2047) {
     // Detect NaN for IEEE double precision floating point.
     if ((u.bits.man_low | u.bits.man_high) != 0)
-      return Heap::false_value();
+      return GetHeap()->false_value();
   }
   if (u.bits.exp == 0) {
     // Detect +0, and -0 for IEEE double precision floating point.
     if ((u.bits.man_low | u.bits.man_high) == 0)
-      return Heap::false_value();
+      return GetHeap()->false_value();
   }
-  return Heap::true_value();
+  return GetHeap()->true_value();
 }
 
 
@@ -1180,14 +1204,14 @@
 
 String* JSObject::class_name() {
   if (IsJSFunction()) {
-    return Heap::function_class_symbol();
+    return GetHeap()->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();
+  return GetHeap()->Object_symbol();
 }
 
 
@@ -1202,7 +1226,7 @@
     if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
   }
   // If the constructor is not present, return "Object".
-  return Heap::Object_symbol();
+  return GetHeap()->Object_symbol();
 }
 
 
@@ -1232,9 +1256,10 @@
 
   // Normalize the object if the name is an actual string (not the
   // hidden symbols) and is not a real identifier.
+  Isolate* isolate = GetHeap()->isolate();
   StringInputBuffer buffer(name);
-  if (!ScannerConstants::IsIdentifier(&buffer)
-      && name != Heap::hidden_symbol()) {
+  if (!isolate->scanner_constants()->IsIdentifier(&buffer)
+      && name != isolate->heap()->hidden_symbol()) {
     Object* obj;
     { MaybeObject* maybe_obj =
           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
@@ -1257,11 +1282,21 @@
     }
   }
 
-  // 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.
+  // Only allow map transition if the object isn't the global object and there
+  // is not a transition for the name, or there's a transition for the name but
+  // it's unrelated to properties.
+  int descriptor_index = old_descriptors->Search(name);
+
+  // External array transitions are stored in the descriptor for property "",
+  // which is not a identifier and should have forced a switch to slow
+  // properties above.
+  ASSERT(descriptor_index == DescriptorArray::kNotFound ||
+      old_descriptors->GetType(descriptor_index) != EXTERNAL_ARRAY_TRANSITION);
+  bool can_insert_transition = descriptor_index == DescriptorArray::kNotFound ||
+      old_descriptors->GetType(descriptor_index) == EXTERNAL_ARRAY_TRANSITION;
   bool allow_map_transition =
-        !old_descriptors->Contains(name) &&
-        (Top::context()->global_context()->object_function()->map() != map());
+      can_insert_transition &&
+      (isolate->context()->global_context()->object_function()->map() != map());
 
   ASSERT(index < map()->inobject_properties() ||
          (index - map()->inobject_properties()) < properties()->length() ||
@@ -1315,7 +1350,8 @@
     String* name,
     JSFunction* function,
     PropertyAttributes attributes) {
-  ASSERT(!Heap::InNewSpace(function));
+  Heap* heap = GetHeap();
+  ASSERT(!heap->InNewSpace(function));
 
   // Allocate new instance descriptors with (name, function) added
   ConstantFunctionDescriptor d(name, function, attributes);
@@ -1340,7 +1376,8 @@
 
   // 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()) {
+  if (old_map == heap->isolate()->context()->global_context()->
+      object_function()->map()) {
     return function;
   }
 
@@ -1375,6 +1412,7 @@
                                        Object* value,
                                        PropertyAttributes attributes) {
   ASSERT(!HasFastProperties());
+  Heap* heap = GetHeap();
   StringDictionary* dict = property_dictionary();
   Object* store_value = value;
   if (IsGlobalObject()) {
@@ -1392,7 +1430,7 @@
       return value;
     }
     { MaybeObject* maybe_store_value =
-          Heap::AllocateJSGlobalPropertyCell(value);
+          heap->AllocateJSGlobalPropertyCell(value);
       if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
     }
     JSGlobalPropertyCell::cast(store_value)->set_value(value);
@@ -1409,18 +1447,25 @@
 
 MaybeObject* JSObject::AddProperty(String* name,
                                    Object* value,
-                                   PropertyAttributes attributes) {
+                                   PropertyAttributes attributes,
+                                   StrictModeFlag strict_mode) {
   ASSERT(!IsJSGlobalProxy());
+  Heap* heap = GetHeap();
   if (!map()->is_extensible()) {
-    Handle<Object> args[1] = {Handle<String>(name)};
-    return Top::Throw(*Factory::NewTypeError("object_not_extensible",
-                                             HandleVector(args, 1)));
+    if (strict_mode == kNonStrictMode) {
+      return heap->undefined_value();
+    } else {
+      Handle<Object> args[1] = {Handle<String>(name)};
+      return heap->isolate()->Throw(
+          *FACTORY->NewTypeError("object_not_extensible",
+                                 HandleVector(args, 1)));
+    }
   }
   if (HasFastProperties()) {
     // Ensure the descriptor array does not get too big.
     if (map()->instance_descriptors()->number_of_descriptors() <
         DescriptorArray::kMaxNumberOfDescriptors) {
-      if (value->IsJSFunction() && !Heap::InNewSpace(value)) {
+      if (value->IsJSFunction() && !heap->InNewSpace(value)) {
         return AddConstantFunctionProperty(name,
                                            JSFunction::cast(value),
                                            attributes);
@@ -1455,7 +1500,7 @@
     return SetProperty(&result, name, value, attributes, strict_mode);
   }
   // Add a new real property.
-  return AddProperty(name, value, attributes);
+  return AddProperty(name, value, attributes, strict_mode);
 }
 
 
@@ -1492,7 +1537,8 @@
     return result;
   }
   // Do not add transitions to the map of "new Object()".
-  if (map() == Top::context()->global_context()->object_function()->map()) {
+  if (map() == GetHeap()->isolate()->context()->global_context()->
+      object_function()->map()) {
     return result;
   }
 
@@ -1579,29 +1625,31 @@
     Object* value,
     PropertyAttributes attributes,
     StrictModeFlag strict_mode) {
-  HandleScope scope;
+  Isolate* isolate = GetIsolate();
+  HandleScope scope(isolate);
   Handle<JSObject> this_handle(this);
   Handle<String> name_handle(name);
-  Handle<Object> value_handle(value);
+  Handle<Object> value_handle(value, isolate);
   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
   if (!interceptor->setter()->IsUndefined()) {
-    LOG(ApiNamedPropertyAccess("interceptor-named-set", this, name));
-    CustomArguments args(interceptor->data(), this, this);
+    LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name));
+    CustomArguments args(isolate, interceptor->data(), this, this);
     v8::AccessorInfo info(args.end());
     v8::NamedPropertySetter setter =
         v8::ToCData<v8::NamedPropertySetter>(interceptor->setter());
     v8::Handle<v8::Value> result;
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       Handle<Object> value_unhole(value->IsTheHole() ?
-                                  Heap::undefined_value() :
-                                  value);
+                                  isolate->heap()->undefined_value() :
+                                  value,
+                                  isolate);
       result = setter(v8::Utils::ToLocal(name_handle),
                       v8::Utils::ToLocal(value_unhole),
                       info);
     }
-    RETURN_IF_SCHEDULED_EXCEPTION();
+    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
     if (!result.IsEmpty()) return *value_handle;
   }
   MaybeObject* raw_result =
@@ -1609,7 +1657,7 @@
                                               *value_handle,
                                               attributes,
                                               strict_mode);
-  RETURN_IF_SCHEDULED_EXCEPTION();
+  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   return raw_result;
 }
 
@@ -1628,12 +1676,13 @@
                                                String* name,
                                                Object* value,
                                                JSObject* holder) {
-  HandleScope scope;
+  Isolate* isolate = GetIsolate();
+  HandleScope scope(isolate);
 
   // 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);
+  Handle<Object> value_handle(value, isolate);
 
   // To accommodate both the old and the new api we switch on the
   // data structure used to store the callbacks.  Eventually proxy
@@ -1642,7 +1691,7 @@
     AccessorDescriptor* callback =
         reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy());
     MaybeObject* obj = (callback->setter)(this,  value, callback->data);
-    RETURN_IF_SCHEDULED_EXCEPTION();
+    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
     if (obj->IsFailure()) return obj;
     return *value_handle;
   }
@@ -1654,17 +1703,17 @@
     v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
     if (call_fun == NULL) return value;
     Handle<String> key(name);
-    LOG(ApiNamedPropertyAccess("store", this, name));
-    CustomArguments args(data->data(), this, JSObject::cast(holder));
+    LOG(isolate, ApiNamedPropertyAccess("store", this, name));
+    CustomArguments args(isolate, data->data(), this, JSObject::cast(holder));
     v8::AccessorInfo info(args.end());
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       call_fun(v8::Utils::ToLocal(key),
                v8::Utils::ToLocal(value_handle),
                info);
     }
-    RETURN_IF_SCHEDULED_EXCEPTION();
+    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
     return *value_handle;
   }
 
@@ -1674,10 +1723,11 @@
      return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value);
     } else {
       Handle<String> key(name);
-      Handle<Object> holder_handle(holder);
+      Handle<Object> holder_handle(holder, isolate);
       Handle<Object> args[2] = { key, holder_handle };
-      return Top::Throw(*Factory::NewTypeError("no_setter_in_callback",
-                                               HandleVector(args, 2)));
+      return isolate->Throw(
+          *isolate->factory()->NewTypeError("no_setter_in_callback",
+                                            HandleVector(args, 2)));
     }
   }
 
@@ -1688,13 +1738,15 @@
 
 MaybeObject* JSObject::SetPropertyWithDefinedSetter(JSFunction* setter,
                                                     Object* value) {
-  Handle<Object> value_handle(value);
-  Handle<JSFunction> fun(JSFunction::cast(setter));
-  Handle<JSObject> self(this);
+  Isolate* isolate = GetIsolate();
+  Handle<Object> value_handle(value, isolate);
+  Handle<JSFunction> fun(JSFunction::cast(setter), isolate);
+  Handle<JSObject> self(this, isolate);
 #ifdef ENABLE_DEBUGGER_SUPPORT
+  Debug* debug = isolate->debug();
   // Handle stepping into a setter if step into is active.
-  if (Debug::StepInActive()) {
-    Debug::HandleStepIn(fun, Handle<Object>::null(), 0, false);
+  if (debug->StepInActive()) {
+    debug->HandleStepIn(fun, Handle<Object>::null(), 0, false);
   }
 #endif
   bool has_pending_exception;
@@ -1708,8 +1760,9 @@
 
 void JSObject::LookupCallbackSetterInPrototypes(String* name,
                                                 LookupResult* result) {
+  Heap* heap = GetHeap();
   for (Object* pt = GetPrototype();
-       pt != Heap::null_value();
+       pt != heap->null_value();
        pt = pt->GetPrototype()) {
     JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
     if (result->IsProperty()) {
@@ -1729,8 +1782,9 @@
 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(uint32_t index,
                                                                 Object* value,
                                                                 bool* found) {
+  Heap* heap = GetHeap();
   for (Object* pt = GetPrototype();
-       pt != Heap::null_value();
+       pt != heap->null_value();
        pt = pt->GetPrototype()) {
     if (!JSObject::cast(pt)->HasDictionaryElements()) {
         continue;
@@ -1747,7 +1801,7 @@
     }
   }
   *found = false;
-  return Heap::the_hole_value();
+  return heap->the_hole_value();
 }
 
 
@@ -1766,10 +1820,11 @@
                               String* name,
                               LookupResult* result) {
   DescriptorArray* descriptors = instance_descriptors();
-  int number = DescriptorLookupCache::Lookup(descriptors, name);
+  DescriptorLookupCache* cache = heap()->isolate()->descriptor_lookup_cache();
+  int number = cache->Lookup(descriptors, name);
   if (number == DescriptorLookupCache::kAbsent) {
     number = descriptors->Search(name);
-    DescriptorLookupCache::Update(descriptors, name, number);
+    cache->Update(descriptors, name, number);
   }
   if (number != DescriptorArray::kNotFound) {
     result->DescriptorResult(holder, descriptors->GetDetails(number), number);
@@ -1779,6 +1834,77 @@
 }
 
 
+MaybeObject* Map::GetExternalArrayElementsMap(ExternalArrayType array_type,
+                                              bool safe_to_add_transition) {
+  DescriptorArray* descriptors = instance_descriptors();
+  String* external_array_sentinel_name = GetIsolate()->heap()->empty_symbol();
+
+  if (safe_to_add_transition) {
+    // It's only safe to manipulate the descriptor array if it would be
+    // safe to add a transition.
+
+    ASSERT(!is_shared());  // no transitions can be added to shared maps.
+    // Check if the external array transition already exists.
+    DescriptorLookupCache* cache = heap()->isolate()->descriptor_lookup_cache();
+    int index = cache->Lookup(descriptors, external_array_sentinel_name);
+    if (index == DescriptorLookupCache::kAbsent) {
+      index = descriptors->Search(external_array_sentinel_name);
+      cache->Update(descriptors,
+                    external_array_sentinel_name,
+                    index);
+    }
+
+    // If the transition already exists, check the type. If there is a match,
+    // return it.
+    if (index != DescriptorArray::kNotFound) {
+      PropertyDetails details(PropertyDetails(descriptors->GetDetails(index)));
+      if (details.type() == EXTERNAL_ARRAY_TRANSITION &&
+          details.array_type() == array_type) {
+        return descriptors->GetValue(index);
+      } else {
+        safe_to_add_transition = false;
+      }
+    }
+  }
+
+  // No transition to an existing external array map. Make a new one.
+  Object* obj;
+  { MaybeObject* maybe_map = CopyDropTransitions();
+    if (!maybe_map->ToObject(&obj)) return maybe_map;
+  }
+  Map* new_map = Map::cast(obj);
+
+  new_map->set_has_fast_elements(false);
+  new_map->set_has_external_array_elements(true);
+  GetIsolate()->counters()->map_to_external_array_elements()->Increment();
+
+  // Only remember the map transition if the object's map is NOT equal to the
+  // global object_function's map and there is not an already existing
+  // non-matching external array transition.
+  bool allow_map_transition =
+      safe_to_add_transition &&
+      (GetIsolate()->context()->global_context()->object_function()->map() !=
+       map());
+  if (allow_map_transition) {
+    // Allocate new instance descriptors for the old map with map transition.
+    ExternalArrayTransitionDescriptor desc(external_array_sentinel_name,
+                                           Map::cast(new_map),
+                                           array_type);
+    Object* new_descriptors;
+    MaybeObject* maybe_new_descriptors = descriptors->CopyInsert(
+        &desc,
+        KEEP_TRANSITIONS);
+    if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
+      return maybe_new_descriptors;
+    }
+    descriptors = DescriptorArray::cast(new_descriptors);
+    set_instance_descriptors(descriptors);
+  }
+
+  return new_map;
+}
+
+
 void JSObject::LocalLookupRealNamedProperty(String* name,
                                             LookupResult* result) {
   if (IsJSGlobalProxy()) {
@@ -1837,8 +1963,9 @@
 
 void JSObject::LookupRealNamedPropertyInPrototypes(String* name,
                                                    LookupResult* result) {
+  Heap* heap = GetHeap();
   for (Object* pt = GetPrototype();
-       pt != Heap::null_value();
+       pt != heap->null_value();
        pt = JSObject::cast(pt)->GetPrototype()) {
     JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
     if (result->IsProperty() && (result->type() != INTERCEPTOR)) return;
@@ -1852,6 +1979,7 @@
                                                         String* name,
                                                         Object* value,
                                                         bool check_prototype) {
+  Heap* heap = GetHeap();
   if (check_prototype && !result->IsProperty()) {
     LookupCallbackSetterInPrototypes(name, result);
   }
@@ -1892,7 +2020,7 @@
 
   HandleScope scope;
   Handle<Object> value_handle(value);
-  Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
+  heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
   return *value_handle;
 }
 
@@ -1902,6 +2030,7 @@
                                    Object* value,
                                    PropertyAttributes attributes,
                                    StrictModeFlag strict_mode) {
+  Heap* heap = GetHeap();
   // Make sure that the top context does not change when doing callbacks or
   // interceptor calls.
   AssertNoContextChange ncc;
@@ -1911,7 +2040,7 @@
   // reallocating them.
   if (!name->IsSymbol() && name->length() <= 2) {
     Object* symbol_version;
-    { MaybeObject* maybe_symbol_version = Heap::LookupSymbol(name);
+    { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name);
       if (maybe_symbol_version->ToObject(&symbol_version)) {
         name = String::cast(symbol_version);
       }
@@ -1920,7 +2049,7 @@
 
   // Check access rights if needed.
   if (IsAccessCheckNeeded()
-      && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
+      && !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) {
     return SetPropertyWithFailedAccessCheck(result, name, value, true);
   }
 
@@ -1946,7 +2075,7 @@
   }
   if (!result->IsFound()) {
     // Neither properties nor transitions found.
-    return AddProperty(name, value, attributes);
+    return AddProperty(name, value, attributes, strict_mode);
   }
   if (result->IsReadOnly() && result->IsProperty()) {
     if (strict_mode == kStrictMode) {
@@ -1954,8 +2083,8 @@
       Handle<String> key(name);
       Handle<Object> holder(this);
       Handle<Object> args[2] = { key, holder };
-      return Top::Throw(*Factory::NewTypeError("strict_read_only_property",
-                                                HandleVector(args, 2)));
+      return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError(
+          "strict_read_only_property", HandleVector(args, 2)));
     } else {
       return value;
     }
@@ -1998,7 +2127,7 @@
       ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION);
       JSFunction* function =
           JSFunction::cast(target_descriptors->GetValue(number));
-      ASSERT(!Heap::InNewSpace(function));
+      ASSERT(!HEAP->InNewSpace(function));
       if (value == function) {
         set_map(target_map);
         return value;
@@ -2008,6 +2137,7 @@
       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
     }
     case NULL_DESCRIPTOR:
+    case EXTERNAL_ARRAY_TRANSITION:
       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
     default:
       UNREACHABLE();
@@ -2027,6 +2157,8 @@
     String* name,
     Object* value,
     PropertyAttributes attributes) {
+  Heap* heap = GetHeap();
+
   // Make sure that the top context does not change when doing callbacks or
   // interceptor calls.
   AssertNoContextChange ncc;
@@ -2034,7 +2166,7 @@
   LocalLookup(name, &result);
   // Check access rights if needed.
   if (IsAccessCheckNeeded()
-      && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
+      && !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) {
     return SetPropertyWithFailedAccessCheck(&result, name, value, false);
   }
 
@@ -2051,7 +2183,7 @@
   // Check for accessor in prototype chain removed here in clone.
   if (!result.IsFound()) {
     // Neither properties nor transitions found.
-    return AddProperty(name, value, attributes);
+    return AddProperty(name, value, attributes, kNonStrictMode);
   }
 
   PropertyDetails details = PropertyDetails(attributes, NORMAL);
@@ -2085,6 +2217,7 @@
       // if the value is a function.
       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
     case NULL_DESCRIPTOR:
+    case EXTERNAL_ARRAY_TRANSITION:
       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
     default:
       UNREACHABLE();
@@ -2106,7 +2239,7 @@
   if (continue_search) {
     // Continue searching via the prototype chain.
     Object* pt = GetPrototype();
-    if (pt != Heap::null_value()) {
+    if (!pt->IsNull()) {
       return JSObject::cast(pt)->
         GetPropertyAttributeWithReceiver(receiver, name);
     }
@@ -2119,25 +2252,28 @@
       JSObject* receiver,
       String* name,
       bool continue_search) {
+  Isolate* isolate = GetIsolate();
+
   // Make sure that the top context does not change when doing
   // callbacks or interceptor calls.
   AssertNoContextChange ncc;
 
-  HandleScope scope;
+  HandleScope scope(isolate);
   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
   Handle<JSObject> receiver_handle(receiver);
   Handle<JSObject> holder_handle(this);
   Handle<String> name_handle(name);
-  CustomArguments args(interceptor->data(), receiver, this);
+  CustomArguments args(isolate, interceptor->data(), receiver, this);
   v8::AccessorInfo info(args.end());
   if (!interceptor->query()->IsUndefined()) {
     v8::NamedPropertyQuery query =
         v8::ToCData<v8::NamedPropertyQuery>(interceptor->query());
-    LOG(ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name));
+    LOG(isolate,
+        ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name));
     v8::Handle<v8::Integer> result;
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       result = query(v8::Utils::ToLocal(name_handle), info);
     }
     if (!result.IsEmpty()) {
@@ -2147,11 +2283,12 @@
   } else if (!interceptor->getter()->IsUndefined()) {
     v8::NamedPropertyGetter getter =
         v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
-    LOG(ApiNamedPropertyAccess("interceptor-named-get-has", this, name));
+    LOG(isolate,
+        ApiNamedPropertyAccess("interceptor-named-get-has", this, name));
     v8::Handle<v8::Value> result;
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       result = getter(v8::Utils::ToLocal(name_handle), info);
     }
     if (!result.IsEmpty()) return DONT_ENUM;
@@ -2181,9 +2318,10 @@
                                                   LookupResult* result,
                                                   String* name,
                                                   bool continue_search) {
+  Heap* heap = GetHeap();
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
-      !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) {
+      !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) {
     return GetPropertyAttributeWithFailedAccessCheck(receiver,
                                                      result,
                                                      name,
@@ -2223,6 +2361,7 @@
 
 MaybeObject* NormalizedMapCache::Get(JSObject* obj,
                                      PropertyNormalizationMode mode) {
+  Isolate* isolate = obj->GetIsolate();
   Map* fast = obj->map();
   int index = Hash(fast) % kEntries;
   Object* result = get(index);
@@ -2249,7 +2388,7 @@
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   set(index, result);
-  Counters::normalized_maps.Increment();
+  isolate->counters()->normalized_maps()->Increment();
 
   return result;
 }
@@ -2309,7 +2448,7 @@
                                                      UNIQUE_NORMALIZED_MAP);
       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
     }
-    Counters::normalized_maps.Increment();
+    GetIsolate()->counters()->normalized_maps()->Increment();
 
     set_map(Map::cast(obj));
   }
@@ -2323,10 +2462,11 @@
 
   // The global object is always normalized.
   ASSERT(!IsGlobalObject());
-
   // JSGlobalProxy must never be normalized
   ASSERT(!IsJSGlobalProxy());
 
+  Heap* heap = GetHeap();
+
   // Allocate new content.
   int property_count = map()->NumberOfDescribedProperties();
   if (expected_additional_properties > 0) {
@@ -2395,8 +2535,8 @@
   int index = map()->instance_descriptors()->NextEnumerationIndex();
   dictionary->SetNextEnumerationIndex(index);
 
-  { MaybeObject* maybe_obj = Top::context()->global_context()->
-                normalized_map_cache()->Get(this, mode);
+  { MaybeObject* maybe_obj = heap->isolate()->context()->global_context()->
+        normalized_map_cache()->Get(this, mode);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
   Map* new_map = Map::cast(obj);
@@ -2408,14 +2548,15 @@
   int new_instance_size = new_map->instance_size();
   int instance_size_delta = map()->instance_size() - new_instance_size;
   ASSERT(instance_size_delta >= 0);
-  Heap::CreateFillerObjectAt(this->address() + new_instance_size,
+  heap->CreateFillerObjectAt(this->address() + new_instance_size,
                              instance_size_delta);
 
   set_map(new_map);
+  map()->set_instance_descriptors(heap->empty_descriptor_array());
 
   set_properties(dictionary);
 
-  Counters::props_to_dictionary.Increment();
+  heap->isolate()->counters()->props_to_dictionary()->Increment();
 
 #ifdef DEBUG
   if (FLAG_trace_normalization) {
@@ -2436,7 +2577,7 @@
 
 
 MaybeObject* JSObject::NormalizeElements() {
-  ASSERT(!HasPixelElements() && !HasExternalArrayElements());
+  ASSERT(!HasExternalArrayElements());
   if (HasDictionaryElements()) return this;
   ASSERT(map()->has_fast_elements());
 
@@ -2476,7 +2617,8 @@
   set_map(new_map);
   set_elements(dictionary);
 
-  Counters::elements_to_dictionary.Increment();
+  new_map->GetHeap()->isolate()->counters()->elements_to_dictionary()->
+      Increment();
 
 #ifdef DEBUG
   if (FLAG_trace_normalization) {
@@ -2492,9 +2634,10 @@
 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
                                                      DeleteMode mode) {
   // Check local property, ignore interceptor.
+  Heap* heap = GetHeap();
   LookupResult result;
   LocalLookupRealNamedProperty(name, &result);
-  if (!result.IsProperty()) return Heap::true_value();
+  if (!result.IsProperty()) return heap->true_value();
 
   // Normalize object if needed.
   Object* obj;
@@ -2507,23 +2650,25 @@
 
 
 MaybeObject* JSObject::DeletePropertyWithInterceptor(String* name) {
-  HandleScope scope;
+  Isolate* isolate = GetIsolate();
+  HandleScope scope(isolate);
   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());
-    LOG(ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name));
-    CustomArguments args(interceptor->data(), this, this);
+    LOG(isolate,
+        ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name));
+    CustomArguments args(isolate, interceptor->data(), this, this);
     v8::AccessorInfo info(args.end());
     v8::Handle<v8::Boolean> result;
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       result = deleter(v8::Utils::ToLocal(name_handle), info);
     }
-    RETURN_IF_SCHEDULED_EXCEPTION();
+    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
     if (!result.IsEmpty()) {
       ASSERT(result->IsBoolean());
       return *v8::Utils::OpenHandle(*result);
@@ -2531,14 +2676,15 @@
   }
   MaybeObject* raw_result =
       this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION);
-  RETURN_IF_SCHEDULED_EXCEPTION();
+  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   return raw_result;
 }
 
 
 MaybeObject* JSObject::DeleteElementPostInterceptor(uint32_t index,
                                                     DeleteMode mode) {
-  ASSERT(!HasPixelElements() && !HasExternalArrayElements());
+  Heap* heap = GetHeap();
+  ASSERT(!HasExternalArrayElements());
   switch (GetElementsKind()) {
     case FAST_ELEMENTS: {
       Object* obj;
@@ -2565,52 +2711,56 @@
       UNREACHABLE();
       break;
   }
-  return Heap::true_value();
+  return heap->true_value();
 }
 
 
 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) {
+  Isolate* isolate = GetIsolate();
+  Heap* heap = isolate->heap();
   // Make sure that the top context does not change when doing
   // callbacks or interceptor calls.
   AssertNoContextChange ncc;
-  HandleScope scope;
+  HandleScope scope(isolate);
   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
-  if (interceptor->deleter()->IsUndefined()) return Heap::false_value();
+  if (interceptor->deleter()->IsUndefined()) return heap->false_value();
   v8::IndexedPropertyDeleter deleter =
       v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter());
   Handle<JSObject> this_handle(this);
-  LOG(ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index));
-  CustomArguments args(interceptor->data(), this, this);
+  LOG(isolate,
+      ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index));
+  CustomArguments args(isolate, interceptor->data(), this, this);
   v8::AccessorInfo info(args.end());
   v8::Handle<v8::Boolean> result;
   {
     // Leaving JavaScript.
-    VMState state(EXTERNAL);
+    VMState state(isolate, EXTERNAL);
     result = deleter(index, info);
   }
-  RETURN_IF_SCHEDULED_EXCEPTION();
+  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   if (!result.IsEmpty()) {
     ASSERT(result->IsBoolean());
     return *v8::Utils::OpenHandle(*result);
   }
   MaybeObject* raw_result =
       this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION);
-  RETURN_IF_SCHEDULED_EXCEPTION();
+  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   return raw_result;
 }
 
 
 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
+  Isolate* isolate = GetIsolate();
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
-      !Top::MayIndexedAccess(this, index, v8::ACCESS_DELETE)) {
-    Top::ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
-    return Heap::false_value();
+      !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) {
+    isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
+    return isolate->heap()->false_value();
   }
 
   if (IsJSGlobalProxy()) {
     Object* proto = GetPrototype();
-    if (proto->IsNull()) return Heap::false_value();
+    if (proto->IsNull()) return isolate->heap()->false_value();
     ASSERT(proto->IsJSGlobalObject());
     return JSGlobalObject::cast(proto)->DeleteElement(index, mode);
   }
@@ -2637,7 +2787,7 @@
       }
       break;
     }
-    case PIXEL_ELEMENTS:
+    case EXTERNAL_PIXEL_ELEMENTS:
     case EXTERNAL_BYTE_ELEMENTS:
     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
     case EXTERNAL_SHORT_ELEMENTS:
@@ -2653,15 +2803,16 @@
       int entry = dictionary->FindEntry(index);
       if (entry != NumberDictionary::kNotFound) {
         Object* result = dictionary->DeleteProperty(entry, mode);
-        if (mode == STRICT_DELETION && result == Heap::false_value()) {
+        if (mode == STRICT_DELETION && result ==
+            isolate->heap()->false_value()) {
           // In strict mode, deleting a non-configurable property throws
           // exception. dictionary->DeleteProperty will return false_value()
           // if a non-configurable property is being deleted.
           HandleScope scope;
-          Handle<Object> i = Factory::NewNumberFromUint(index);
+          Handle<Object> i = isolate->factory()->NewNumberFromUint(index);
           Handle<Object> args[2] = { i, Handle<Object>(this) };
-          return Top::Throw(*Factory::NewTypeError("strict_delete_property",
-                                                   HandleVector(args, 2)));
+          return isolate->Throw(*isolate->factory()->NewTypeError(
+              "strict_delete_property", HandleVector(args, 2)));
         }
       }
       break;
@@ -2670,24 +2821,25 @@
       UNREACHABLE();
       break;
   }
-  return Heap::true_value();
+  return isolate->heap()->true_value();
 }
 
 
 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
+  Isolate* isolate = GetIsolate();
   // 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();
+      !isolate->MayNamedAccess(this, name, v8::ACCESS_DELETE)) {
+    isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
+    return isolate->heap()->false_value();
   }
 
   if (IsJSGlobalProxy()) {
     Object* proto = GetPrototype();
-    if (proto->IsNull()) return Heap::false_value();
+    if (proto->IsNull()) return isolate->heap()->false_value();
     ASSERT(proto->IsJSGlobalObject());
     return JSGlobalObject::cast(proto)->DeleteProperty(name, mode);
   }
@@ -2698,17 +2850,17 @@
   } else {
     LookupResult result;
     LocalLookup(name, &result);
-    if (!result.IsProperty()) return Heap::true_value();
+    if (!result.IsProperty()) return isolate->heap()->true_value();
     // Ignore attributes if forcing a deletion.
     if (result.IsDontDelete() && mode != FORCE_DELETION) {
       if (mode == STRICT_DELETION) {
         // Deleting a non-configurable property in strict mode.
-        HandleScope scope;
+        HandleScope scope(isolate);
         Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) };
-        return Top::Throw(*Factory::NewTypeError("strict_delete_property",
-                                                 HandleVector(args, 2)));
+        return isolate->Throw(*isolate->factory()->NewTypeError(
+            "strict_delete_property", HandleVector(args, 2)));
       }
-      return Heap::false_value();
+      return isolate->heap()->false_value();
     }
     // Check for interceptor.
     if (result.type() == INTERCEPTOR) {
@@ -2732,6 +2884,7 @@
 
 // Check whether this object references another object.
 bool JSObject::ReferencesObject(Object* obj) {
+  Heap* heap = GetHeap();
   AssertNoAllocation no_alloc;
 
   // Is the object the constructor for this object?
@@ -2746,13 +2899,13 @@
 
   // Check if the object is among the named properties.
   Object* key = SlowReverseLookup(obj);
-  if (key != Heap::undefined_value()) {
+  if (!key->IsUndefined()) {
     return true;
   }
 
   // Check if the object is among the indexed properties.
   switch (GetElementsKind()) {
-    case PIXEL_ELEMENTS:
+    case EXTERNAL_PIXEL_ELEMENTS:
     case EXTERNAL_BYTE_ELEMENTS:
     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
     case EXTERNAL_SHORT_ELEMENTS:
@@ -2777,7 +2930,7 @@
     }
     case DICTIONARY_ELEMENTS: {
       key = element_dictionary()->SlowReverseLookup(obj);
-      if (key != Heap::undefined_value()) {
+      if (!key->IsUndefined()) {
         return true;
       }
       break;
@@ -2791,7 +2944,8 @@
   if (IsJSFunction()) {
     // Get the constructor function for arguments array.
     JSObject* arguments_boilerplate =
-        Top::context()->global_context()->arguments_boilerplate();
+        heap->isolate()->context()->global_context()->
+            arguments_boilerplate();
     JSFunction* arguments_function =
         JSFunction::cast(arguments_boilerplate->map()->constructor());
 
@@ -2830,10 +2984,13 @@
 
 
 MaybeObject* JSObject::PreventExtensions() {
+  Isolate* isolate = GetIsolate();
   if (IsAccessCheckNeeded() &&
-      !Top::MayNamedAccess(this, Heap::undefined_value(), v8::ACCESS_KEYS)) {
-    Top::ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
-    return Heap::false_value();
+      !isolate->MayNamedAccess(this,
+                               isolate->heap()->undefined_value(),
+                               v8::ACCESS_KEYS)) {
+    isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
+    return isolate->heap()->false_value();
   }
 
   if (IsJSGlobalProxy()) {
@@ -2872,8 +3029,9 @@
 // - This object has no elements.
 // - No prototype has enumerable properties/elements.
 bool JSObject::IsSimpleEnum() {
+  Heap* heap = GetHeap();
   for (Object* o = this;
-       o != Heap::null_value();
+       o != heap->null_value();
        o = JSObject::cast(o)->GetPrototype()) {
     JSObject* curr = JSObject::cast(o);
     if (!curr->map()->instance_descriptors()->HasEnumCache()) return false;
@@ -2939,6 +3097,8 @@
 void JSObject::LocalLookup(String* name, LookupResult* result) {
   ASSERT(name->IsString());
 
+  Heap* heap = GetHeap();
+
   if (IsJSGlobalProxy()) {
     Object* proto = GetPrototype();
     if (proto->IsNull()) return result->NotFound();
@@ -2953,13 +3113,14 @@
   }
 
   // Check __proto__ before interceptor.
-  if (name->Equals(Heap::Proto_symbol()) && !IsJSContextExtensionObject()) {
+  if (name->Equals(heap->Proto_symbol()) &&
+      !IsJSContextExtensionObject()) {
     result->ConstantResult(this);
     return;
   }
 
   // Check for lookup interceptor except when bootstrapping.
-  if (HasNamedInterceptor() && !Bootstrapper::IsActive()) {
+  if (HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive()) {
     result->InterceptorResult(this);
     return;
   }
@@ -2970,8 +3131,9 @@
 
 void JSObject::Lookup(String* name, LookupResult* result) {
   // Ecma-262 3rd 8.6.2.4
+  Heap* heap = GetHeap();
   for (Object* current = this;
-       current != Heap::null_value();
+       current != heap->null_value();
        current = JSObject::cast(current)->GetPrototype()) {
     JSObject::cast(current)->LocalLookup(name, result);
     if (result->IsProperty()) return;
@@ -2982,8 +3144,9 @@
 
 // Search object and it's prototype chain for callback properties.
 void JSObject::LookupCallback(String* name, LookupResult* result) {
+  Heap* heap = GetHeap();
   for (Object* current = this;
-       current != Heap::null_value();
+       current != heap->null_value();
        current = JSObject::cast(current)->GetPrototype()) {
     JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
     if (result->IsProperty() && result->type() == CALLBACKS) return;
@@ -2994,6 +3157,7 @@
 
 MaybeObject* JSObject::DefineGetterSetter(String* name,
                                           PropertyAttributes attributes) {
+  Heap* heap = GetHeap();
   // Make sure that the top context does not change when doing callbacks or
   // interceptor calls.
   AssertNoContextChange ncc;
@@ -3002,7 +3166,7 @@
   name->TryFlatten();
 
   if (!CanSetCallback(name)) {
-    return Heap::undefined_value();
+    return heap->undefined_value();
   }
 
   uint32_t index = 0;
@@ -3012,7 +3176,7 @@
     switch (GetElementsKind()) {
       case FAST_ELEMENTS:
         break;
-      case PIXEL_ELEMENTS:
+      case EXTERNAL_PIXEL_ELEMENTS:
       case EXTERNAL_BYTE_ELEMENTS:
       case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
       case EXTERNAL_SHORT_ELEMENTS:
@@ -3022,7 +3186,7 @@
       case EXTERNAL_FLOAT_ELEMENTS:
         // Ignore getters and setters on pixel and external array
         // elements.
-        return Heap::undefined_value();
+        return heap->undefined_value();
       case DICTIONARY_ELEMENTS: {
         // Lookup the index.
         NumberDictionary* dictionary = element_dictionary();
@@ -3030,7 +3194,7 @@
         if (entry != NumberDictionary::kNotFound) {
           Object* result = dictionary->ValueAt(entry);
           PropertyDetails details = dictionary->DetailsAt(entry);
-          if (details.IsReadOnly()) return Heap::undefined_value();
+          if (details.IsReadOnly()) return heap->undefined_value();
           if (details.type() == CALLBACKS) {
             if (result->IsFixedArray()) {
               return result;
@@ -3049,7 +3213,7 @@
     LookupResult result;
     LocalLookup(name, &result);
     if (result.IsProperty()) {
-      if (result.IsReadOnly()) return Heap::undefined_value();
+      if (result.IsReadOnly()) return heap->undefined_value();
       if (result.type() == CALLBACKS) {
         Object* obj = result.GetCallbackObject();
         // Need to preserve old getters/setters.
@@ -3063,7 +3227,7 @@
 
   // Allocate the fixed array to hold getter and setter.
   Object* structure;
-  { MaybeObject* maybe_structure = Heap::AllocateFixedArray(2, TENURED);
+  { MaybeObject* maybe_structure = heap->AllocateFixedArray(2, TENURED);
     if (!maybe_structure->ToObject(&structure)) return maybe_structure;
   }
 
@@ -3077,7 +3241,7 @@
 
 bool JSObject::CanSetCallback(String* name) {
   ASSERT(!IsAccessCheckNeeded()
-         || Top::MayNamedAccess(this, name, v8::ACCESS_SET));
+         || Isolate::Current()->MayNamedAccess(this, name, v8::ACCESS_SET));
 
   // Check if there is an API defined callback object which prohibits
   // callback overwriting in this object or it's prototype chain.
@@ -3174,11 +3338,12 @@
                                       Object* fun,
                                       PropertyAttributes attributes) {
   ASSERT(fun->IsJSFunction() || fun->IsUndefined());
+  Isolate* isolate = GetIsolate();
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
-      !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
-    Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
-    return Heap::undefined_value();
+      !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
+    isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
+    return isolate->heap()->undefined_value();
   }
 
   if (IsJSGlobalProxy()) {
@@ -3200,12 +3365,13 @@
 
 
 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
+  Isolate* isolate = GetIsolate();
   String* name = String::cast(info->name());
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
-      !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
-    Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
-    return Heap::undefined_value();
+      !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
+    isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
+    return isolate->heap()->undefined_value();
   }
 
   if (IsJSGlobalProxy()) {
@@ -3223,20 +3389,20 @@
   name->TryFlatten();
 
   if (!CanSetCallback(name)) {
-    return Heap::undefined_value();
+    return isolate->heap()->undefined_value();
   }
 
   uint32_t index = 0;
   bool is_element = name->AsArrayIndex(&index);
 
   if (is_element) {
-    if (IsJSArray()) return Heap::undefined_value();
+    if (IsJSArray()) return isolate->heap()->undefined_value();
 
     // Accessors overwrite previous callbacks (cf. with getters/setters).
     switch (GetElementsKind()) {
       case FAST_ELEMENTS:
         break;
-      case PIXEL_ELEMENTS:
+      case EXTERNAL_PIXEL_ELEMENTS:
       case EXTERNAL_BYTE_ELEMENTS:
       case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
       case EXTERNAL_SHORT_ELEMENTS:
@@ -3246,7 +3412,7 @@
       case EXTERNAL_FLOAT_ELEMENTS:
         // Ignore getters and setters on pixel and external array
         // elements.
-        return Heap::undefined_value();
+        return isolate->heap()->undefined_value();
       case DICTIONARY_ELEMENTS:
         break;
       default:
@@ -3266,7 +3432,7 @@
     // ES5 forbids turning a property into an accessor if it's not
     // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5).
     if (result.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) {
-      return Heap::undefined_value();
+      return isolate->heap()->undefined_value();
     }
     Object* ok;
     { MaybeObject* maybe_ok =
@@ -3280,15 +3446,17 @@
 
 
 Object* JSObject::LookupAccessor(String* name, bool is_getter) {
+  Heap* heap = GetHeap();
+
   // 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();
+      !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) {
+    heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+    return heap->undefined_value();
   }
 
   // Make the lookup and include prototypes.
@@ -3296,7 +3464,7 @@
   uint32_t index = 0;
   if (name->AsArrayIndex(&index)) {
     for (Object* obj = this;
-         obj != Heap::null_value();
+         obj != heap->null_value();
          obj = JSObject::cast(obj)->GetPrototype()) {
       JSObject* js_object = JSObject::cast(obj);
       if (js_object->HasDictionaryElements()) {
@@ -3315,12 +3483,12 @@
     }
   } else {
     for (Object* obj = this;
-         obj != Heap::null_value();
+         obj != heap->null_value();
          obj = JSObject::cast(obj)->GetPrototype()) {
       LookupResult result;
       JSObject::cast(obj)->LocalLookup(name, &result);
       if (result.IsProperty()) {
-        if (result.IsReadOnly()) return Heap::undefined_value();
+        if (result.IsReadOnly()) return heap->undefined_value();
         if (result.type() == CALLBACKS) {
           Object* obj = result.GetCallbackObject();
           if (obj->IsFixedArray()) {
@@ -3330,11 +3498,12 @@
       }
     }
   }
-  return Heap::undefined_value();
+  return heap->undefined_value();
 }
 
 
 Object* JSObject::SlowReverseLookup(Object* value) {
+  Heap* heap = GetHeap();
   if (HasFastProperties()) {
     DescriptorArray* descs = map()->instance_descriptors();
     for (int i = 0; i < descs->number_of_descriptors(); i++) {
@@ -3348,7 +3517,7 @@
         }
       }
     }
-    return Heap::undefined_value();
+    return heap->undefined_value();
   } else {
     return property_dictionary()->SlowReverseLookup(value);
   }
@@ -3356,9 +3525,10 @@
 
 
 MaybeObject* Map::CopyDropDescriptors() {
+  Heap* heap = GetHeap();
   Object* result;
   { MaybeObject* maybe_result =
-        Heap::AllocateMap(instance_type(), instance_size());
+        heap->AllocateMap(instance_type(), instance_size());
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   Map::cast(result)->set_prototype(prototype());
@@ -3368,7 +3538,8 @@
   // pointing to the same transition which is bad because the garbage
   // collector relies on being able to reverse pointers from transitions
   // to maps.  If properties need to be retained use CopyDropTransitions.
-  Map::cast(result)->set_instance_descriptors(Heap::empty_descriptor_array());
+  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());
@@ -3391,7 +3562,7 @@
   Map::cast(result)->set_bit_field(bit_field());
   Map::cast(result)->set_bit_field2(bit_field2());
   Map::cast(result)->set_is_shared(false);
-  Map::cast(result)->ClearCodeCache();
+  Map::cast(result)->ClearCodeCache(heap);
   return result;
 }
 
@@ -3405,7 +3576,7 @@
 
   Object* result;
   { MaybeObject* maybe_result =
-        Heap::AllocateMap(instance_type(), new_instance_size);
+        GetHeap()->AllocateMap(instance_type(), new_instance_size);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
 
@@ -3450,7 +3621,7 @@
   // Allocate the code cache if not present.
   if (code_cache()->IsFixedArray()) {
     Object* result;
-    { MaybeObject* maybe_result = Heap::AllocateCodeCache();
+    { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache();
       if (!maybe_result->ToObject(&result)) return maybe_result;
     }
     set_code_cache(result);
@@ -3466,7 +3637,7 @@
   if (!code_cache()->IsFixedArray()) {
     return CodeCache::cast(code_cache())->Lookup(name, flags);
   } else {
-    return Heap::undefined_value();
+    return GetHeap()->undefined_value();
   }
 }
 
@@ -3490,12 +3661,13 @@
 
 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
   Map* current = this;
-  while (current != Heap::meta_map()) {
+  Map* meta_map = heap()->meta_map();
+  while (current != meta_map) {
     DescriptorArray* d = reinterpret_cast<DescriptorArray*>(
         *RawField(current, Map::kInstanceDescriptorsOffset));
-    if (d == Heap::empty_descriptor_array()) {
+    if (d == heap()->empty_descriptor_array()) {
       Map* prev = current->map();
-      current->set_map(Heap::meta_map());
+      current->set_map(meta_map);
       callback(current, data);
       current = prev;
       continue;
@@ -3520,9 +3692,9 @@
       }
     }
     if (!map_done) continue;
-    *map_or_index_field = Heap::fixed_array_map();
+    *map_or_index_field = heap()->fixed_array_map();
     Map* prev = current->map();
-    current->set_map(Heap::meta_map());
+    current->set_map(meta_map);
     callback(current, data);
     current = prev;
   }
@@ -3635,6 +3807,7 @@
 
 
 Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) {
+  Heap* heap = GetHeap();
   FixedArray* cache = default_cache();
   int length = cache->length();
   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
@@ -3649,7 +3822,7 @@
       }
     }
   }
-  return Heap::undefined_value();
+  return heap->undefined_value();
 }
 
 
@@ -3658,7 +3831,7 @@
     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
     return cache->Lookup(name, flags);
   } else {
-    return Heap::undefined_value();
+    return GetHeap()->undefined_value();
   }
 }
 
@@ -3740,7 +3913,7 @@
   MUST_USE_RESULT MaybeObject* AsObject() {
     ASSERT(code_ != NULL);
     Object* obj;
-    { MaybeObject* maybe_obj = Heap::AllocateFixedArray(2);
+    { MaybeObject* maybe_obj = code_->GetHeap()->AllocateFixedArray(2);
       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
     }
     FixedArray* pair = FixedArray::cast(obj);
@@ -3759,7 +3932,7 @@
 Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) {
   CodeCacheHashTableKey key(name, flags);
   int entry = FindEntry(&key);
-  if (entry == kNotFound) return Heap::undefined_value();
+  if (entry == kNotFound) return GetHeap()->undefined_value();
   return get(EntryToIndex(entry) + 1);
 }
 
@@ -3796,8 +3969,9 @@
 
 void CodeCacheHashTable::RemoveByIndex(int index) {
   ASSERT(index >= 0);
-  set(EntryToIndex(index), Heap::null_value());
-  set(EntryToIndex(index) + 1, Heap::null_value());
+  Heap* heap = GetHeap();
+  set(EntryToIndex(index), heap->null_value());
+  set(EntryToIndex(index) + 1, heap->null_value());
   ElementRemoved();
 }
 
@@ -3817,7 +3991,8 @@
 
 
 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
-  ASSERT(!array->HasPixelElements() && !array->HasExternalArrayElements());
+  Heap* heap = GetHeap();
+  ASSERT(!array->HasExternalArrayElements());
   switch (array->GetElementsKind()) {
     case JSObject::FAST_ELEMENTS:
       return UnionOfKeys(FixedArray::cast(array->elements()));
@@ -3827,7 +4002,7 @@
 
       // Allocate a temporary fixed array.
       Object* object;
-      { MaybeObject* maybe_object = Heap::AllocateFixedArray(size);
+      { MaybeObject* maybe_object = heap->AllocateFixedArray(size);
         if (!maybe_object->ToObject(&object)) return maybe_object;
       }
       FixedArray* key_array = FixedArray::cast(object);
@@ -3847,11 +4022,12 @@
       UNREACHABLE();
   }
   UNREACHABLE();
-  return Heap::null_value();  // Failure case needs to "return" a value.
+  return heap->null_value();  // Failure case needs to "return" a value.
 }
 
 
 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) {
+  Heap* heap = GetHeap();
   int len0 = length();
 #ifdef DEBUG
   if (FLAG_enable_slow_asserts) {
@@ -3877,7 +4053,7 @@
 
   // Allocate the result
   Object* obj;
-  { MaybeObject* maybe_obj = Heap::AllocateFixedArray(len0 + extra);
+  { MaybeObject* maybe_obj = heap->AllocateFixedArray(len0 + extra);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
   // Fill in the content
@@ -3906,9 +4082,10 @@
 
 
 MaybeObject* FixedArray::CopySize(int new_length) {
-  if (new_length == 0) return Heap::empty_fixed_array();
+  Heap* heap = GetHeap();
+  if (new_length == 0) return heap->empty_fixed_array();
   Object* obj;
-  { MaybeObject* maybe_obj = Heap::AllocateFixedArray(new_length);
+  { MaybeObject* maybe_obj = heap->AllocateFixedArray(new_length);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
   FixedArray* result = FixedArray::cast(obj);
@@ -3946,13 +4123,14 @@
 
 
 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) {
+  Heap* heap = Isolate::Current()->heap();
   if (number_of_descriptors == 0) {
-    return Heap::empty_descriptor_array();
+    return heap->empty_descriptor_array();
   }
   // Allocate the array of keys.
   Object* array;
   { MaybeObject* maybe_array =
-        Heap::AllocateFixedArray(ToKeyIndex(number_of_descriptors));
+        heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors));
     if (!maybe_array->ToObject(&array)) return maybe_array;
   }
   // Do not use DescriptorArray::cast on incomplete object.
@@ -3960,7 +4138,7 @@
 
   // Allocate the content array and set it in the descriptor array.
   { MaybeObject* maybe_array =
-        Heap::AllocateFixedArray(number_of_descriptors << 1);
+        heap->AllocateFixedArray(number_of_descriptors << 1);
     if (!maybe_array->ToObject(&array)) return maybe_array;
   }
   result->set(kContentArrayIndex, array);
@@ -4229,15 +4407,15 @@
 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count,
                                                PretenureFlag pretenure) {
   ASSERT(deopt_entry_count > 0);
-  return Heap::AllocateFixedArray(LengthFor(deopt_entry_count),
+  return HEAP->AllocateFixedArray(LengthFor(deopt_entry_count),
                                   pretenure);
 }
 
 
 MaybeObject* DeoptimizationOutputData::Allocate(int number_of_deopt_points,
                                                 PretenureFlag pretenure) {
-  if (number_of_deopt_points == 0) return Heap::empty_fixed_array();
-  return Heap::AllocateFixedArray(LengthOfFixedArray(number_of_deopt_points),
+  if (number_of_deopt_points == 0) return HEAP->empty_fixed_array();
+  return HEAP->AllocateFixedArray(LengthOfFixedArray(number_of_deopt_points),
                                   pretenure);
 }
 
@@ -4255,11 +4433,8 @@
 #endif
 
 
-static StaticResource<StringInputBuffer> string_input_buffer;
-
-
 bool String::LooksValid() {
-  if (!Heap::Contains(this)) return false;
+  if (!Isolate::Current()->heap()->Contains(this)) return false;
   return true;
 }
 
@@ -4270,8 +4445,10 @@
   // 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.
+  Heap* heap = GetHeap();
   TryFlatten();
-  Access<StringInputBuffer> buffer(&string_input_buffer);
+  Access<StringInputBuffer> buffer(
+      heap->isolate()->objects_string_input_buffer());
   buffer->Reset(0, this);
   int result = 0;
   while (buffer->has_more())
@@ -4337,16 +4514,17 @@
                                      int offset,
                                      int length,
                                      int* length_return) {
-  ASSERT(NativeAllocationChecker::allocation_allowed());
   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
     return SmartPointer<char>(NULL);
   }
+  Heap* heap = GetHeap();
 
   // 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);
+  Access<StringInputBuffer> buffer(
+      heap->isolate()->objects_string_input_buffer());
   buffer->Reset(offset, this);
   int character_position = offset;
   int utf8_bytes = 0;
@@ -4415,13 +4593,13 @@
 
 
 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
-  ASSERT(NativeAllocationChecker::allocation_allowed());
-
   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
     return SmartPointer<uc16>();
   }
+  Heap* heap = GetHeap();
 
-  Access<StringInputBuffer> buffer(&string_input_buffer);
+  Access<StringInputBuffer> buffer(
+      heap->isolate()->objects_string_input_buffer());
   buffer->Reset(this);
 
   uc16* result = NewArray<uc16>(length() + 1);
@@ -4704,11 +4882,9 @@
 }
 
 
-Relocatable* Relocatable::top_ = NULL;
-
-
 void Relocatable::PostGarbageCollectionProcessing() {
-  Relocatable* current = top_;
+  Isolate* isolate = Isolate::Current();
+  Relocatable* current = isolate->relocatable_top();
   while (current != NULL) {
     current->PostGarbageCollection();
     current = current->prev_;
@@ -4718,21 +4894,23 @@
 
 // Reserve space for statics needing saving and restoring.
 int Relocatable::ArchiveSpacePerThread() {
-  return sizeof(top_);
+  return sizeof(Isolate::Current()->relocatable_top());
 }
 
 
 // Archive statics that are thread local.
 char* Relocatable::ArchiveState(char* to) {
-  *reinterpret_cast<Relocatable**>(to) = top_;
-  top_ = NULL;
+  Isolate* isolate = Isolate::Current();
+  *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
+  isolate->set_relocatable_top(NULL);
   return to + ArchiveSpacePerThread();
 }
 
 
 // Restore statics that are thread local.
 char* Relocatable::RestoreState(char* from) {
-  top_ = *reinterpret_cast<Relocatable**>(from);
+  Isolate* isolate = Isolate::Current();
+  isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
   return from + ArchiveSpacePerThread();
 }
 
@@ -4745,7 +4923,8 @@
 
 
 void Relocatable::Iterate(ObjectVisitor* v) {
-  Iterate(v, top_);
+  Isolate* isolate = Isolate::Current();
+  Iterate(v, isolate->relocatable_top());
 }
 
 
@@ -4758,15 +4937,17 @@
 }
 
 
-FlatStringReader::FlatStringReader(Handle<String> str)
-    : str_(str.location()),
+FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
+    : Relocatable(isolate),
+      str_(str.location()),
       length_(str->length()) {
   PostGarbageCollection();
 }
 
 
-FlatStringReader::FlatStringReader(Vector<const char> input)
-    : str_(0),
+FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
+    : Relocatable(isolate),
+      str_(0),
       is_ascii_(true),
       length_(input.length()),
       start_(input.start()) { }
@@ -5096,11 +5277,10 @@
 }
 
 
-static StringInputBuffer string_compare_buffer_b;
-
-
 template <typename IteratorA>
-static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
+static inline bool CompareStringContentsPartial(Isolate* isolate,
+                                                IteratorA* ia,
+                                                String* b) {
   if (b->IsFlat()) {
     if (b->IsAsciiRepresentation()) {
       VectorIterator<char> ib(b->ToAsciiVector());
@@ -5110,15 +5290,13 @@
       return CompareStringContents(ia, &ib);
     }
   } else {
-    string_compare_buffer_b.Reset(0, b);
-    return CompareStringContents(ia, &string_compare_buffer_b);
+    isolate->objects_string_compare_buffer_b()->Reset(0, b);
+    return CompareStringContents(ia,
+                                 isolate->objects_string_compare_buffer_b());
   }
 }
 
 
-static StringInputBuffer string_compare_buffer_a;
-
-
 bool String::SlowEquals(String* other) {
   // Fast check: negative check with lengths.
   int len = length();
@@ -5146,6 +5324,7 @@
                                     Vector<const char>(str2, len));
   }
 
+  Isolate* isolate = GetIsolate();
   if (lhs->IsFlat()) {
     if (lhs->IsAsciiRepresentation()) {
       Vector<const char> vec1 = lhs->ToAsciiVector();
@@ -5160,8 +5339,9 @@
         }
       } else {
         VectorIterator<char> buf1(vec1);
-        string_compare_buffer_b.Reset(0, rhs);
-        return CompareStringContents(&buf1, &string_compare_buffer_b);
+        isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
+        return CompareStringContents(&buf1,
+            isolate->objects_string_compare_buffer_b());
       }
     } else {
       Vector<const uc16> vec1 = lhs->ToUC16Vector();
@@ -5176,13 +5356,15 @@
         }
       } else {
         VectorIterator<uc16> buf1(vec1);
-        string_compare_buffer_b.Reset(0, rhs);
-        return CompareStringContents(&buf1, &string_compare_buffer_b);
+        isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
+        return CompareStringContents(&buf1,
+            isolate->objects_string_compare_buffer_b());
       }
     }
   } else {
-    string_compare_buffer_a.Reset(0, lhs);
-    return CompareStringContentsPartial(&string_compare_buffer_a, rhs);
+    isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
+    return CompareStringContentsPartial(isolate,
+        isolate->objects_string_compare_buffer_a(), rhs);
   }
 }
 
@@ -5191,11 +5373,12 @@
   if (StringShape(this).IsSymbol()) return false;
 
   Map* map = this->map();
-  if (map == Heap::string_map()) {
-    this->set_map(Heap::undetectable_string_map());
+  Heap* heap = map->GetHeap();
+  if (map == heap->string_map()) {
+    this->set_map(heap->undetectable_string_map());
     return true;
-  } else if (map == Heap::ascii_string_map()) {
-    this->set_map(Heap::undetectable_ascii_string_map());
+  } else if (map == heap->ascii_string_map()) {
+    this->set_map(heap->undetectable_ascii_string_map());
     return true;
   }
   // Rest cannot be marked as undetectable
@@ -5204,9 +5387,10 @@
 
 
 bool String::IsEqualTo(Vector<const char> str) {
+  Isolate* isolate = GetIsolate();
   int slen = length();
   Access<ScannerConstants::Utf8Decoder>
-      decoder(ScannerConstants::utf8_decoder());
+      decoder(isolate->scanner_constants()->utf8_decoder());
   decoder->Reset(str.start(), str.length());
   int i;
   for (i = 0; i < slen && decoder->has_more(); i++) {
@@ -5237,22 +5421,6 @@
 }
 
 
-template <typename schar>
-static inline uint32_t HashSequentialString(const schar* chars, int length) {
-  StringHasher hasher(length);
-  if (!hasher.has_trivial_hash()) {
-    int i;
-    for (i = 0; hasher.is_array_index() && (i < length); i++) {
-      hasher.AddCharacter(chars[i]);
-    }
-    for (; i < length; i++) {
-      hasher.AddCharacterNoIndex(chars[i]);
-    }
-  }
-  return hasher.GetHashField();
-}
-
-
 uint32_t String::ComputeAndSetHash() {
   // Should only be called if hash code has not yet been computed.
   ASSERT(!HasHashCode());
@@ -5384,8 +5552,9 @@
 
 
 MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) {
+  Heap* heap = GetHeap();
   if (start == 0 && end == length()) return this;
-  MaybeObject* result = Heap::AllocateSubString(this, start, end, pretenure);
+  MaybeObject* result = heap->AllocateSubString(this, start, end, pretenure);
   return result;
 }
 
@@ -5402,6 +5571,7 @@
   DescriptorArray* descriptors = instance_descriptors();
   for (int i = 0; i < descriptors->number_of_descriptors(); i++) {
     if (descriptors->GetType(i) == MAP_TRANSITION ||
+        descriptors->GetType(i) == EXTERNAL_ARRAY_TRANSITION ||
         descriptors->GetType(i) == CONSTANT_TRANSITION) {
       // Get target.
       Map* target = Map::cast(descriptors->GetValue(i));
@@ -5425,12 +5595,12 @@
 }
 
 
-void Map::ClearNonLiveTransitions(Object* real_prototype) {
+void Map::ClearNonLiveTransitions(Heap* heap, 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::raw_unchecked_empty_descriptor_array()) return;
+  if (d == heap->raw_unchecked_empty_descriptor_array()) return;
   Smi* NullDescriptorDetails =
     PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi();
   FixedArray* contents = reinterpret_cast<FixedArray*>(
@@ -5444,13 +5614,14 @@
     // non-live object.
     PropertyDetails details(Smi::cast(contents->get(i + 1)));
     if (details.type() == MAP_TRANSITION ||
+        details.type() == EXTERNAL_ARRAY_TRANSITION ||
         details.type() == CONSTANT_TRANSITION) {
       Map* target = reinterpret_cast<Map*>(contents->get(i));
       ASSERT(target->IsHeapObject());
       if (!target->IsMarked()) {
         ASSERT(target->IsMap());
         contents->set_unchecked(i + 1, NullDescriptorDetails);
-        contents->set_null_unchecked(i);
+        contents->set_null_unchecked(heap, i);
         ASSERT(target->prototype() == this ||
                target->prototype() == real_prototype);
         // Getter prototype() is read-only, set_prototype() has side effects.
@@ -5474,7 +5645,8 @@
   ASSERT(is_compiled() && !IsOptimized());
   ASSERT(shared()->allows_lazy_compilation() ||
          code()->optimizable());
-  ReplaceCode(Builtins::builtin(Builtins::LazyRecompile));
+  Builtins* builtins = GetIsolate()->builtins();
+  ReplaceCode(builtins->builtin(Builtins::kLazyRecompile));
 }
 
 
@@ -5507,7 +5679,7 @@
 
 Object* JSFunction::SetInstancePrototype(Object* value) {
   ASSERT(value->IsJSObject());
-
+  Heap* heap = GetHeap();
   if (has_initial_map()) {
     initial_map()->set_prototype(value);
   } else {
@@ -5516,7 +5688,7 @@
     // prototype is put into the initial map where it belongs.
     set_prototype_or_initial_map(value);
   }
-  Heap::ClearInstanceofCache();
+  heap->ClearInstanceofCache();
   return value;
 }
 
@@ -5530,6 +5702,7 @@
   // used for constructing objects to the original object prototype.
   // See ECMA-262 13.2.2.
   if (!value->IsJSObject()) {
+    Heap* heap = GetHeap();
     // Copy the map so this does not affect unrelated functions.
     // Remove map transitions because they point to maps with a
     // different prototype.
@@ -5541,7 +5714,8 @@
     map()->set_constructor(value);
     map()->set_non_instance_prototype(true);
     construct_prototype =
-        Top::context()->global_context()->initial_object_prototype();
+        heap->isolate()->context()->global_context()->
+            initial_object_prototype();
   } else {
     map()->set_non_instance_prototype(false);
   }
@@ -5551,13 +5725,22 @@
 
 
 Object* JSFunction::RemovePrototype() {
-  if (map() == context()->global_context()->function_without_prototype_map()) {
+  Context* global_context = context()->global_context();
+  Map* no_prototype_map = shared()->strict_mode()
+      ? global_context->strict_mode_function_without_prototype_map()
+      : global_context->function_without_prototype_map();
+
+  if (map() == no_prototype_map) {
     // Be idempotent.
     return this;
   }
-  ASSERT(map() == context()->global_context()->function_map());
-  set_map(context()->global_context()->function_without_prototype_map());
-  set_prototype_or_initial_map(Heap::the_hole_value());
+
+  ASSERT(!shared()->strict_mode() ||
+         map() == global_context->strict_mode_function_map());
+  ASSERT(shared()->strict_mode() || map() == global_context->function_map());
+
+  set_map(no_prototype_map);
+  set_prototype_or_initial_map(GetHeap()->the_hole_value());
   return this;
 }
 
@@ -5579,13 +5762,17 @@
 }
 
 
-MaybeObject* Oddball::Initialize(const char* to_string, Object* to_number) {
+MaybeObject* Oddball::Initialize(const char* to_string,
+                                 Object* to_number,
+                                 byte kind) {
   Object* symbol;
-  { MaybeObject* maybe_symbol = Heap::LookupAsciiSymbol(to_string);
+  { MaybeObject* maybe_symbol =
+        Isolate::Current()->heap()->LookupAsciiSymbol(to_string);
     if (!maybe_symbol->ToObject(&symbol)) return maybe_symbol;
   }
   set_to_string(String::cast(symbol));
   set_to_number(to_number);
+  set_kind(kind);
   return this;
 }
 
@@ -5604,10 +5791,11 @@
 
 
 Object* SharedFunctionInfo::GetSourceCode() {
-  if (!HasSourceCode()) return Heap::undefined_value();
-  HandleScope scope;
+  Isolate* isolate = GetIsolate();
+  if (!HasSourceCode()) return isolate->heap()->undefined_value();
+  HandleScope scope(isolate);
   Object* source = Script::cast(script())->source();
-  return *SubString(Handle<String>(String::cast(source)),
+  return *SubString(Handle<String>(String::cast(source), isolate),
                     start_position(), end_position());
 }
 
@@ -5634,6 +5822,8 @@
 
 
 bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) {
+  Heap* heap = GetHeap();
+
   // Check the basic conditions for generating inline constructor code.
   if (!FLAG_inline_new
       || !has_only_simple_this_property_assignments()
@@ -5650,7 +5840,7 @@
   // Traverse the proposed prototype chain looking for setters for properties of
   // the same names as are set by the inline constructor.
   for (Object* obj = prototype;
-       obj != Heap::null_value();
+       obj != heap->null_value();
        obj = obj->GetPrototype()) {
     JSObject* js_object = JSObject::cast(obj);
     for (int i = 0; i < this_property_assignments_count(); i++) {
@@ -5686,10 +5876,11 @@
 
 
 void SharedFunctionInfo::ClearThisPropertyAssignmentsInfo() {
+  Heap* heap = GetHeap();
   set_compiler_hints(BooleanBit::set(compiler_hints(),
                                      kHasOnlySimpleThisPropertyAssignments,
                                      false));
-  set_this_property_assignments(Heap::undefined_value());
+  set_this_property_assignments(heap->undefined_value());
   set_this_property_assignments_count(0);
 }
 
@@ -5834,9 +6025,10 @@
     set_construction_count(kGenerousAllocationCount);
   }
   set_initial_map(map);
-  ASSERT_EQ(Builtins::builtin(Builtins::JSConstructStubGeneric),
+  Builtins* builtins = map->heap()->isolate()->builtins();
+  ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
             construct_stub());
-  set_construct_stub(Builtins::builtin(Builtins::JSConstructStubCountdown));
+  set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
 }
 
 
@@ -5853,10 +6045,11 @@
   // then StartInobjectTracking will be called again the next time the
   // constructor is called. The countdown will continue and (possibly after
   // several more GCs) CompleteInobjectSlackTracking will eventually be called.
-  set_initial_map(Heap::raw_unchecked_undefined_value());
-  ASSERT_EQ(Builtins::builtin(Builtins::JSConstructStubCountdown),
+  set_initial_map(map->heap()->raw_unchecked_undefined_value());
+  Builtins* builtins = map->heap()->isolate()->builtins();
+  ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
             *RawField(this, kConstructStubOffset));
-  set_construct_stub(Builtins::builtin(Builtins::JSConstructStubGeneric));
+  set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
   // It is safe to clear the flag: it will be set again if the map is live.
   set_live_objects_may_exist(false);
 }
@@ -5869,9 +6062,10 @@
 
   // Resume inobject slack tracking.
   set_initial_map(map);
-  ASSERT_EQ(Builtins::builtin(Builtins::JSConstructStubGeneric),
+  Builtins* builtins = map->heap()->isolate()->builtins();
+  ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
             *RawField(this, kConstructStubOffset));
-  set_construct_stub(Builtins::builtin(Builtins::JSConstructStubCountdown));
+  set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
   // The map survived the gc, so there may be objects referencing it.
   set_live_objects_may_exist(true);
 }
@@ -5900,10 +6094,12 @@
   ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress());
   Map* map = Map::cast(initial_map());
 
-  set_initial_map(Heap::undefined_value());
-  ASSERT_EQ(Builtins::builtin(Builtins::JSConstructStubCountdown),
+  Heap* heap = map->heap();
+  set_initial_map(heap->undefined_value());
+  Builtins* builtins = heap->isolate()->builtins();
+  ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
             construct_stub());
-  set_construct_stub(Builtins::builtin(Builtins::JSConstructStubGeneric));
+  set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
 
   int slack = map->unused_property_fields();
   map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
@@ -5960,8 +6156,7 @@
 
 
 void Code::InvalidateRelocation() {
-  HandleScope scope;
-  set_relocation_info(Heap::empty_byte_array());
+  set_relocation_info(GetHeap()->empty_byte_array());
 }
 
 
@@ -6255,8 +6450,10 @@
     case BUILTIN: return "BUILTIN";
     case LOAD_IC: return "LOAD_IC";
     case KEYED_LOAD_IC: return "KEYED_LOAD_IC";
+    case KEYED_EXTERNAL_ARRAY_LOAD_IC: return "KEYED_EXTERNAL_ARRAY_LOAD_IC";
     case STORE_IC: return "STORE_IC";
     case KEYED_STORE_IC: return "KEYED_STORE_IC";
+    case KEYED_EXTERNAL_ARRAY_STORE_IC: return "KEYED_EXTERNAL_ARRAY_STORE_IC";
     case CALL_IC: return "CALL_IC";
     case KEYED_CALL_IC: return "KEYED_CALL_IC";
     case BINARY_OP_IC: return "BINARY_OP_IC";
@@ -6291,6 +6488,7 @@
     case CALLBACKS: return "CALLBACKS";
     case INTERCEPTOR: return "INTERCEPTOR";
     case MAP_TRANSITION: return "MAP_TRANSITION";
+    case EXTERNAL_ARRAY_TRANSITION: return "EXTERNAL_ARRAY_TRANSITION";
     case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION";
     case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR";
   }
@@ -6405,11 +6603,12 @@
 
 MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity,
                                                         int length) {
+  Heap* heap = GetHeap();
   // We should never end in here with a pixel or external array.
-  ASSERT(!HasPixelElements() && !HasExternalArrayElements());
+  ASSERT(!HasExternalArrayElements());
 
   Object* obj;
-  { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(capacity);
+  { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
   FixedArray* elems = FixedArray::cast(obj);
@@ -6460,7 +6659,7 @@
 
 MaybeObject* JSObject::SetSlowElements(Object* len) {
   // We should never end in here with a pixel or external array.
-  ASSERT(!HasPixelElements() && !HasExternalArrayElements());
+  ASSERT(!HasExternalArrayElements());
 
   uint32_t new_length = static_cast<uint32_t>(len->Number());
 
@@ -6496,14 +6695,15 @@
 
 
 MaybeObject* JSArray::Initialize(int capacity) {
+  Heap* heap = GetHeap();
   ASSERT(capacity >= 0);
   set_length(Smi::FromInt(0));
   FixedArray* new_elements;
   if (capacity == 0) {
-    new_elements = Heap::empty_fixed_array();
+    new_elements = heap->empty_fixed_array();
   } else {
     Object* obj;
-    { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(capacity);
+    { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity);
       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
     }
     new_elements = FixedArray::cast(obj);
@@ -6518,21 +6718,23 @@
   Handle<FixedArray> old_backing(FixedArray::cast(elements()));
   int old_size = old_backing->length();
   int new_size = required_size > old_size ? required_size : old_size;
-  Handle<FixedArray> new_backing = Factory::NewFixedArray(new_size);
+  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);
 }
 
 
-static Failure* ArrayLengthRangeError() {
+static Failure* ArrayLengthRangeError(Heap* heap) {
   HandleScope scope;
-  return Top::Throw(*Factory::NewRangeError("invalid_array_length",
-                                            HandleVector<Object>(NULL, 0)));
+  return heap->isolate()->Throw(
+      *FACTORY->NewRangeError("invalid_array_length",
+          HandleVector<Object>(NULL, 0)));
 }
 
 
 MaybeObject* JSObject::SetElementsLength(Object* len) {
+  Heap* heap = GetHeap();
   // We should never end in here with a pixel or external array.
   ASSERT(AllowsSetElementsLength());
 
@@ -6540,7 +6742,7 @@
   Object* smi_length = Smi::FromInt(0);
   if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) {
     const int value = Smi::cast(smi_length)->value();
-    if (value < 0) return ArrayLengthRangeError();
+    if (value < 0) return ArrayLengthRangeError(heap);
     switch (GetElementsKind()) {
       case FAST_ELEMENTS: {
         int old_capacity = FixedArray::cast(elements())->length();
@@ -6606,14 +6808,14 @@
     if (len->ToArrayIndex(&length)) {
       return SetSlowElements(len);
     } else {
-      return ArrayLengthRangeError();
+      return ArrayLengthRangeError(heap);
     }
   }
 
   // len is not a number so make the array size one and
   // set only element to len.
   Object* obj;
-  { MaybeObject* maybe_obj = Heap::AllocateFixedArray(1);
+  { MaybeObject* maybe_obj = heap->AllocateFixedArray(1);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
   FixedArray::cast(obj)->set(0, len);
@@ -6625,6 +6827,7 @@
 
 MaybeObject* JSObject::SetPrototype(Object* value,
                                     bool skip_hidden_prototypes) {
+  Heap* heap = GetHeap();
   // Silently ignore the change if value is not a JSObject or null.
   // SpiderMonkey behaves this way.
   if (!value->IsJSObject() && !value->IsNull()) return value;
@@ -6633,12 +6836,12 @@
   // prototype cycles are prevented.
   // It is sufficient to validate that the receiver is not in the new prototype
   // chain.
-  for (Object* pt = value; pt != Heap::null_value(); pt = pt->GetPrototype()) {
+  for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) {
     if (JSObject::cast(pt) == this) {
       // Cycle detected.
       HandleScope scope;
-      return Top::Throw(*Factory::NewError("cyclic_proto",
-                                           HandleVector<Object>(NULL, 0)));
+      return heap->isolate()->Throw(
+          *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0)));
     }
   }
 
@@ -6663,7 +6866,7 @@
   Map::cast(new_map)->set_prototype(value);
   real_receiver->set_map(Map::cast(new_map));
 
-  Heap::ClearInstanceofCache();
+  heap->ClearInstanceofCache();
 
   return value;
 }
@@ -6682,8 +6885,8 @@
       }
       break;
     }
-    case PIXEL_ELEMENTS: {
-      PixelArray* pixels = PixelArray::cast(elements());
+    case EXTERNAL_PIXEL_ELEMENTS: {
+      ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
       if (index < static_cast<uint32_t>(pixels->length())) {
         return true;
       }
@@ -6718,29 +6921,31 @@
   if (this->IsStringObjectWithCharacterAt(index)) return true;
 
   Object* pt = GetPrototype();
-  if (pt == Heap::null_value()) return false;
+  if (pt->IsNull()) return false;
   return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
 }
 
 
 bool JSObject::HasElementWithInterceptor(JSObject* receiver, uint32_t index) {
+  Isolate* isolate = GetIsolate();
   // Make sure that the top context does not change when doing
   // callbacks or interceptor calls.
   AssertNoContextChange ncc;
-  HandleScope scope;
+  HandleScope scope(isolate);
   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
   Handle<JSObject> receiver_handle(receiver);
   Handle<JSObject> holder_handle(this);
-  CustomArguments args(interceptor->data(), receiver, this);
+  CustomArguments args(isolate, interceptor->data(), receiver, this);
   v8::AccessorInfo info(args.end());
   if (!interceptor->query()->IsUndefined()) {
     v8::IndexedPropertyQuery query =
         v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query());
-    LOG(ApiIndexedPropertyAccess("interceptor-indexed-has", this, index));
+    LOG(isolate,
+        ApiIndexedPropertyAccess("interceptor-indexed-has", this, index));
     v8::Handle<v8::Integer> result;
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       result = query(index, info);
     }
     if (!result.IsEmpty()) {
@@ -6750,11 +6955,12 @@
   } else if (!interceptor->getter()->IsUndefined()) {
     v8::IndexedPropertyGetter getter =
         v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
-    LOG(ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index));
+    LOG(isolate,
+        ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index));
     v8::Handle<v8::Value> result;
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       result = getter(index, info);
     }
     if (!result.IsEmpty()) return true;
@@ -6764,10 +6970,12 @@
 
 
 JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) {
+  Heap* heap = GetHeap();
+
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
-      !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
-    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+      !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
+    heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
     return UNDEFINED_ELEMENT;
   }
 
@@ -6801,8 +7009,8 @@
       }
       break;
     }
-    case PIXEL_ELEMENTS: {
-      PixelArray* pixels = PixelArray::cast(elements());
+    case EXTERNAL_PIXEL_ELEMENTS: {
+      ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
       if (index < static_cast<uint32_t>(pixels->length())) return FAST_ELEMENT;
       break;
     }
@@ -6834,10 +7042,12 @@
 
 
 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) {
+  Heap* heap = GetHeap();
+
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
-      !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
-    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+      !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
+    heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
     return false;
   }
 
@@ -6856,8 +7066,8 @@
           !FixedArray::cast(elements())->get(index)->IsTheHole()) return true;
       break;
     }
-    case PIXEL_ELEMENTS: {
-      PixelArray* pixels = PixelArray::cast(elements());
+    case EXTERNAL_PIXEL_ELEMENTS: {
+      ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
       if (index < static_cast<uint32_t>(pixels->length())) {
         return true;
       }
@@ -6892,7 +7102,7 @@
   if (this->IsStringObjectWithCharacterAt(index)) return true;
 
   Object* pt = GetPrototype();
-  if (pt == Heap::null_value()) return false;
+  if (pt->IsNull()) return false;
   return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
 }
 
@@ -6901,26 +7111,28 @@
                                                  Object* value,
                                                  StrictModeFlag strict_mode,
                                                  bool check_prototype) {
+  Isolate* isolate = GetIsolate();
   // Make sure that the top context does not change when doing
   // callbacks or interceptor calls.
   AssertNoContextChange ncc;
-  HandleScope scope;
+  HandleScope scope(isolate);
   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
   Handle<JSObject> this_handle(this);
-  Handle<Object> value_handle(value);
+  Handle<Object> value_handle(value, isolate);
   if (!interceptor->setter()->IsUndefined()) {
     v8::IndexedPropertySetter setter =
         v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter());
-    LOG(ApiIndexedPropertyAccess("interceptor-indexed-set", this, index));
-    CustomArguments args(interceptor->data(), this, this);
+    LOG(isolate,
+        ApiIndexedPropertyAccess("interceptor-indexed-set", this, index));
+    CustomArguments args(isolate, interceptor->data(), this, this);
     v8::AccessorInfo info(args.end());
     v8::Handle<v8::Value> result;
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       result = setter(index, v8::Utils::ToLocal(value_handle), info);
     }
-    RETURN_IF_SCHEDULED_EXCEPTION();
+    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
     if (!result.IsEmpty()) return *value_handle;
   }
   MaybeObject* raw_result =
@@ -6928,7 +7140,7 @@
                                                 *value_handle,
                                                 strict_mode,
                                                 check_prototype);
-  RETURN_IF_SCHEDULED_EXCEPTION();
+  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   return raw_result;
 }
 
@@ -6937,6 +7149,7 @@
                                               Object* structure,
                                               uint32_t index,
                                               Object* holder) {
+  Isolate* isolate = GetIsolate();
   ASSERT(!structure->IsProxy());
 
   // api style callbacks.
@@ -6944,22 +7157,22 @@
     AccessorInfo* data = AccessorInfo::cast(structure);
     Object* fun_obj = data->getter();
     v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
-    HandleScope scope;
+    HandleScope scope(isolate);
     Handle<JSObject> self(JSObject::cast(receiver));
     Handle<JSObject> holder_handle(JSObject::cast(holder));
-    Handle<Object> number = Factory::NewNumberFromUint(index);
-    Handle<String> key(Factory::NumberToString(number));
-    LOG(ApiNamedPropertyAccess("load", *self, *key));
-    CustomArguments args(data->data(), *self, *holder_handle);
+    Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
+    Handle<String> key(isolate->factory()->NumberToString(number));
+    LOG(isolate, ApiNamedPropertyAccess("load", *self, *key));
+    CustomArguments args(isolate, data->data(), *self, *holder_handle);
     v8::AccessorInfo info(args.end());
     v8::Handle<v8::Value> result;
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       result = call_fun(v8::Utils::ToLocal(key), info);
     }
-    RETURN_IF_SCHEDULED_EXCEPTION();
-    if (result.IsEmpty()) return Heap::undefined_value();
+    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+    if (result.IsEmpty()) return isolate->heap()->undefined_value();
     return *v8::Utils::OpenHandle(*result);
   }
 
@@ -6971,7 +7184,7 @@
                                                   JSFunction::cast(getter));
     }
     // Getter is not a function.
-    return Heap::undefined_value();
+    return isolate->heap()->undefined_value();
   }
 
   UNREACHABLE();
@@ -6983,12 +7196,13 @@
                                               uint32_t index,
                                               Object* value,
                                               JSObject* holder) {
-  HandleScope scope;
+  Isolate* isolate = GetIsolate();
+  HandleScope scope(isolate);
 
   // 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);
+  Handle<Object> value_handle(value, isolate);
 
   // To accommodate both the old and the new api we switch on the
   // data structure used to store the callbacks.  Eventually proxy
@@ -7001,19 +7215,19 @@
     Object* call_obj = data->setter();
     v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
     if (call_fun == NULL) return value;
-    Handle<Object> number = Factory::NewNumberFromUint(index);
-    Handle<String> key(Factory::NumberToString(number));
-    LOG(ApiNamedPropertyAccess("store", this, *key));
-    CustomArguments args(data->data(), this, JSObject::cast(holder));
+    Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
+    Handle<String> key(isolate->factory()->NumberToString(number));
+    LOG(isolate, ApiNamedPropertyAccess("store", this, *key));
+    CustomArguments args(isolate, data->data(), this, JSObject::cast(holder));
     v8::AccessorInfo info(args.end());
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       call_fun(v8::Utils::ToLocal(key),
                v8::Utils::ToLocal(value_handle),
                info);
     }
-    RETURN_IF_SCHEDULED_EXCEPTION();
+    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
     return *value_handle;
   }
 
@@ -7022,11 +7236,12 @@
     if (setter->IsJSFunction()) {
      return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value);
     } else {
-      Handle<Object> holder_handle(holder);
-      Handle<Object> key(Factory::NewNumberFromUint(index));
+      Handle<Object> holder_handle(holder, isolate);
+      Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
       Handle<Object> args[2] = { key, holder_handle };
-      return Top::Throw(*Factory::NewTypeError("no_setter_in_callback",
-                                               HandleVector(args, 2)));
+      return isolate->Throw(
+          *isolate->factory()->NewTypeError("no_setter_in_callback",
+                                            HandleVector(args, 2)));
     }
   }
 
@@ -7105,12 +7320,13 @@
                                   Object* value,
                                   StrictModeFlag strict_mode,
                                   bool check_prototype) {
+  Heap* heap = GetHeap();
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
-      !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) {
+      !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) {
     HandleScope scope;
     Handle<Object> value_handle(value);
-    Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
+    heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
     return *value_handle;
   }
 
@@ -7143,12 +7359,13 @@
                                                     Object* value,
                                                     StrictModeFlag strict_mode,
                                                     bool check_prototype) {
+  Isolate* isolate = GetIsolate();
   switch (GetElementsKind()) {
     case FAST_ELEMENTS:
       // Fast case.
       return SetFastElement(index, value, strict_mode, check_prototype);
-    case PIXEL_ELEMENTS: {
-      PixelArray* pixels = PixelArray::cast(elements());
+    case EXTERNAL_PIXEL_ELEMENTS: {
+      ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
       return pixels->SetValue(index, value);
     }
     case EXTERNAL_BYTE_ELEMENTS: {
@@ -7198,12 +7415,12 @@
           // If put fails instrict mode, throw exception.
           if (!dictionary->ValueAtPut(entry, value) &&
               strict_mode == kStrictMode) {
-            Handle<Object> number(Factory::NewNumberFromUint(index));
+            Handle<Object> number(isolate->factory()->NewNumberFromUint(index));
             Handle<Object> holder(this);
             Handle<Object> args[2] = { number, holder };
-            return Top::Throw(
-                *Factory::NewTypeError("strict_read_only_property",
-                                       HandleVector(args, 2)));
+            return isolate->Throw(
+                *isolate->factory()->NewTypeError("strict_read_only_property",
+                                                  HandleVector(args, 2)));
           }
         }
       } else {
@@ -7218,11 +7435,17 @@
         // When we set the is_extensible flag to false we always force
         // the element into dictionary mode (and force them to stay there).
         if (!map()->is_extensible()) {
-          Handle<Object> number(Factory::NewNumberFromUint(index));
-          Handle<String> index_string(Factory::NumberToString(number));
-          Handle<Object> args[1] = { index_string };
-          return Top::Throw(*Factory::NewTypeError("object_not_extensible",
-                                                   HandleVector(args, 1)));
+          if (strict_mode == kNonStrictMode) {
+            return isolate->heap()->undefined_value();
+          } else {
+            Handle<Object> number(isolate->factory()->NewNumberFromUint(index));
+            Handle<String> index_string(
+                isolate->factory()->NumberToString(number));
+            Handle<Object> args[1] = { index_string };
+            return isolate->Throw(
+                *isolate->factory()->NewTypeError("object_not_extensible",
+                                                  HandleVector(args, 1)));
+          }
         }
         Object* result;
         { MaybeObject* maybe_result = dictionary->AtNumberPut(index, value);
@@ -7275,7 +7498,7 @@
   // All possible cases have been handled above. Add a return to avoid the
   // complaints from the compiler.
   UNREACHABLE();
-  return Heap::null_value();
+  return isolate->heap()->null_value();
 }
 
 
@@ -7288,7 +7511,7 @@
   if (index >= old_len && index != 0xffffffff) {
     Object* len;
     { MaybeObject* maybe_len =
-          Heap::NumberFromDouble(static_cast<double>(index) + 1);
+          GetHeap()->NumberFromDouble(static_cast<double>(index) + 1);
       if (!maybe_len->ToObject(&len)) return maybe_len;
     }
     set_length(len);
@@ -7299,6 +7522,7 @@
 
 MaybeObject* JSObject::GetElementPostInterceptor(Object* receiver,
                                                  uint32_t index) {
+  Heap* heap = GetHeap();
   // Get element works for both JSObject and JSArray since
   // JSArray::length cannot change.
   switch (GetElementsKind()) {
@@ -7310,7 +7534,7 @@
       }
       break;
     }
-    case PIXEL_ELEMENTS:
+    case EXTERNAL_PIXEL_ELEMENTS:
     case EXTERNAL_BYTE_ELEMENTS:
     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
     case EXTERNAL_SHORT_ELEMENTS:
@@ -7347,51 +7571,54 @@
 
   // Continue searching via the prototype chain.
   Object* pt = GetPrototype();
-  if (pt == Heap::null_value()) return Heap::undefined_value();
+  if (pt->IsNull()) return heap->undefined_value();
   return pt->GetElementWithReceiver(receiver, index);
 }
 
 
 MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver,
                                                  uint32_t index) {
+  Isolate* isolate = GetIsolate();
   // Make sure that the top context does not change when doing
   // callbacks or interceptor calls.
   AssertNoContextChange ncc;
-  HandleScope scope;
-  Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
-  Handle<Object> this_handle(receiver);
-  Handle<JSObject> holder_handle(this);
+  HandleScope scope(isolate);
+  Handle<InterceptorInfo> interceptor(GetIndexedInterceptor(), isolate);
+  Handle<Object> this_handle(receiver, isolate);
+  Handle<JSObject> holder_handle(this, isolate);
 
   if (!interceptor->getter()->IsUndefined()) {
     v8::IndexedPropertyGetter getter =
         v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
-    LOG(ApiIndexedPropertyAccess("interceptor-indexed-get", this, index));
-    CustomArguments args(interceptor->data(), receiver, this);
+    LOG(isolate,
+        ApiIndexedPropertyAccess("interceptor-indexed-get", this, index));
+    CustomArguments args(isolate, interceptor->data(), receiver, this);
     v8::AccessorInfo info(args.end());
     v8::Handle<v8::Value> result;
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       result = getter(index, info);
     }
-    RETURN_IF_SCHEDULED_EXCEPTION();
+    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
   }
 
   MaybeObject* raw_result =
       holder_handle->GetElementPostInterceptor(*this_handle, index);
-  RETURN_IF_SCHEDULED_EXCEPTION();
+  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   return raw_result;
 }
 
 
 MaybeObject* JSObject::GetElementWithReceiver(Object* receiver,
                                               uint32_t index) {
+  Heap* heap = GetHeap();
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
-      !Top::MayIndexedAccess(this, index, v8::ACCESS_GET)) {
-    Top::ReportFailedAccessCheck(this, v8::ACCESS_GET);
-    return Heap::undefined_value();
+      !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_GET)) {
+    heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET);
+    return heap->undefined_value();
   }
 
   if (HasIndexedInterceptor()) {
@@ -7409,7 +7636,7 @@
       }
       break;
     }
-    case PIXEL_ELEMENTS:
+    case EXTERNAL_PIXEL_ELEMENTS:
     case EXTERNAL_BYTE_ELEMENTS:
     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
     case EXTERNAL_SHORT_ELEMENTS:
@@ -7442,7 +7669,7 @@
   }
 
   Object* pt = GetPrototype();
-  if (pt == Heap::null_value()) return Heap::undefined_value();
+  if (pt == heap->null_value()) return heap->undefined_value();
   return pt->GetElementWithReceiver(receiver, index);
 }
 
@@ -7451,8 +7678,8 @@
   // Get element works for both JSObject and JSArray since
   // JSArray::length cannot change.
   switch (GetElementsKind()) {
-    case PIXEL_ELEMENTS: {
-      PixelArray* pixels = PixelArray::cast(elements());
+    case EXTERNAL_PIXEL_ELEMENTS: {
+      ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
       if (index < static_cast<uint32_t>(pixels->length())) {
         uint8_t value = pixels->get(index);
         return Smi::FromInt(value);
@@ -7497,7 +7724,7 @@
       ExternalIntArray* array = ExternalIntArray::cast(elements());
       if (index < static_cast<uint32_t>(array->length())) {
         int32_t value = array->get(index);
-        return Heap::NumberFromInt32(value);
+        return GetHeap()->NumberFromInt32(value);
       }
       break;
     }
@@ -7506,7 +7733,7 @@
           ExternalUnsignedIntArray::cast(elements());
       if (index < static_cast<uint32_t>(array->length())) {
         uint32_t value = array->get(index);
-        return Heap::NumberFromUint32(value);
+        return GetHeap()->NumberFromUint32(value);
       }
       break;
     }
@@ -7514,7 +7741,7 @@
       ExternalFloatArray* array = ExternalFloatArray::cast(elements());
       if (index < static_cast<uint32_t>(array->length())) {
         float value = array->get(index);
-        return Heap::AllocateHeapNumber(value);
+        return GetHeap()->AllocateHeapNumber(value);
       }
       break;
     }
@@ -7523,7 +7750,7 @@
       UNREACHABLE();
       break;
   }
-  return Heap::undefined_value();
+  return GetHeap()->undefined_value();
 }
 
 
@@ -7540,7 +7767,7 @@
       }
       break;
     }
-    case PIXEL_ELEMENTS:
+    case EXTERNAL_PIXEL_ELEMENTS:
     case EXTERNAL_BYTE_ELEMENTS:
     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
     case EXTERNAL_SHORT_ELEMENTS:
@@ -7668,6 +7895,7 @@
     JSObject* receiver,
     String* name,
     PropertyAttributes* attributes) {
+  Heap* heap = GetHeap();
   // Check local property in holder, ignore interceptor.
   LookupResult result;
   LocalLookupRealNamedProperty(name, &result);
@@ -7677,7 +7905,7 @@
   // Continue searching via the prototype chain.
   Object* pt = GetPrototype();
   *attributes = ABSENT;
-  if (pt == Heap::null_value()) return Heap::undefined_value();
+  if (pt->IsNull()) return heap->undefined_value();
   return pt->GetPropertyWithReceiver(receiver, name, attributes);
 }
 
@@ -7686,13 +7914,14 @@
     JSObject* receiver,
     String* name,
     PropertyAttributes* attributes) {
+  Heap* heap = GetHeap();
   // Check local property in holder, ignore interceptor.
   LookupResult result;
   LocalLookupRealNamedProperty(name, &result);
   if (result.IsProperty()) {
     return GetProperty(receiver, &result, name, attributes);
   }
-  return Heap::undefined_value();
+  return heap->undefined_value();
 }
 
 
@@ -7700,8 +7929,9 @@
     JSObject* receiver,
     String* name,
     PropertyAttributes* attributes) {
+  Isolate* isolate = GetIsolate();
   InterceptorInfo* interceptor = GetNamedInterceptor();
-  HandleScope scope;
+  HandleScope scope(isolate);
   Handle<JSObject> receiver_handle(receiver);
   Handle<JSObject> holder_handle(this);
   Handle<String> name_handle(name);
@@ -7709,16 +7939,17 @@
   if (!interceptor->getter()->IsUndefined()) {
     v8::NamedPropertyGetter getter =
         v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
-    LOG(ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name));
-    CustomArguments args(interceptor->data(), receiver, this);
+    LOG(isolate,
+        ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name));
+    CustomArguments args(isolate, interceptor->data(), receiver, this);
     v8::AccessorInfo info(args.end());
     v8::Handle<v8::Value> result;
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       result = getter(v8::Utils::ToLocal(name_handle), info);
     }
-    RETURN_IF_SCHEDULED_EXCEPTION();
+    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
     if (!result.IsEmpty()) {
       *attributes = NONE;
       return *v8::Utils::OpenHandle(*result);
@@ -7729,16 +7960,17 @@
       *receiver_handle,
       *name_handle,
       attributes);
-  RETURN_IF_SCHEDULED_EXCEPTION();
+  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   return result;
 }
 
 
 bool JSObject::HasRealNamedProperty(String* key) {
+  Heap* heap = GetHeap();
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
-      !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) {
-    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+      !heap->isolate()->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
+    heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
     return false;
   }
 
@@ -7749,10 +7981,11 @@
 
 
 bool JSObject::HasRealElementProperty(uint32_t index) {
+  Heap* heap = GetHeap();
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
-      !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
-    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+      !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
+    heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
     return false;
   }
 
@@ -7768,8 +8001,8 @@
       return (index < length) &&
           !FixedArray::cast(elements())->get(index)->IsTheHole();
     }
-    case PIXEL_ELEMENTS: {
-      PixelArray* pixels = PixelArray::cast(elements());
+    case EXTERNAL_PIXEL_ELEMENTS: {
+      ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
       return index < static_cast<uint32_t>(pixels->length());
     }
     case EXTERNAL_BYTE_ELEMENTS:
@@ -7792,15 +8025,16 @@
   }
   // All possibilities have been handled above already.
   UNREACHABLE();
-  return Heap::null_value();
+  return heap->null_value();
 }
 
 
 bool JSObject::HasRealNamedCallbackProperty(String* key) {
+  Heap* heap = GetHeap();
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
-      !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) {
-    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+      !heap->isolate()->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
+    heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
     return false;
   }
 
@@ -8000,8 +8234,8 @@
       ASSERT(!storage || storage->length() >= counter);
       break;
     }
-    case PIXEL_ELEMENTS: {
-      int length = PixelArray::cast(elements())->length();
+    case EXTERNAL_PIXEL_ELEMENTS: {
+      int length = ExternalPixelArray::cast(elements())->length();
       while (counter < length) {
         if (storage != NULL) {
           storage->set(counter, Smi::FromInt(counter));
@@ -8063,51 +8297,6 @@
 }
 
 
-bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
-  ASSERT(other->IsNumber());
-  return key == static_cast<uint32_t>(other->Number());
-}
-
-
-uint32_t NumberDictionaryShape::Hash(uint32_t key) {
-  return ComputeIntegerHash(key);
-}
-
-
-uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) {
-  ASSERT(other->IsNumber());
-  return ComputeIntegerHash(static_cast<uint32_t>(other->Number()));
-}
-
-
-MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) {
-  return Heap::NumberFromUint32(key);
-}
-
-
-bool StringDictionaryShape::IsMatch(String* key, Object* other) {
-  // We know that all entries in a hash table had their hash keys created.
-  // Use that knowledge to have fast failure.
-  if (key->Hash() != String::cast(other)->Hash()) return false;
-  return key->Equals(String::cast(other));
-}
-
-
-uint32_t StringDictionaryShape::Hash(String* key) {
-  return key->Hash();
-}
-
-
-uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
-  return String::cast(other)->Hash();
-}
-
-
-MaybeObject* StringDictionaryShape::AsObject(String* key) {
-  return key;
-}
-
-
 // StringKey simply carries a string object as key.
 class StringKey : public HashTableKey {
  public:
@@ -8190,7 +8379,7 @@
 
   MUST_USE_RESULT MaybeObject* AsObject() {
     Object* obj;
-    { MaybeObject* maybe_obj = Heap::AllocateFixedArray(3);
+    { MaybeObject* maybe_obj = source_->GetHeap()->AllocateFixedArray(3);
       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
     }
     FixedArray* pair = FixedArray::cast(obj);
@@ -8274,7 +8463,8 @@
 
   MaybeObject* AsObject() {
     if (hash_field_ == 0) Hash();
-    return Heap::AllocateSymbol(string_, chars_, hash_field_);
+    return Isolate::Current()->heap()->AllocateSymbol(
+        string_, chars_, hash_field_);
   }
 
   Vector<const char> string_;
@@ -8341,7 +8531,7 @@
 
   MaybeObject* AsObject() {
     if (hash_field_ == 0) Hash();
-    return Heap::AllocateAsciiSymbol(string_, hash_field_);
+    return HEAP->AllocateAsciiSymbol(string_, hash_field_);
   }
 };
 
@@ -8357,7 +8547,7 @@
 
   MaybeObject* AsObject() {
     if (hash_field_ == 0) Hash();
-    return Heap::AllocateTwoByteSymbol(string_, hash_field_);
+    return HEAP->AllocateTwoByteSymbol(string_, hash_field_);
   }
 };
 
@@ -8365,7 +8555,8 @@
 // SymbolKey carries a string/symbol object as key.
 class SymbolKey : public HashTableKey {
  public:
-  explicit SymbolKey(String* string) : string_(string) { }
+  explicit SymbolKey(String* string)
+      : string_(string) { }
 
   bool IsMatch(Object* string) {
     return String::cast(string)->Equals(string_);
@@ -8381,8 +8572,9 @@
     // Attempt to flatten the string, so that symbols will most often
     // be flat strings.
     string_ = string_->TryFlattenGetString();
+    Heap* heap = string_->GetHeap();
     // Transform string to symbol if possible.
-    Map* map = Heap::SymbolMapForString(string_);
+    Map* map = heap->SymbolMapForString(string_);
     if (map != NULL) {
       string_->set_map(map);
       ASSERT(string_->IsSymbol());
@@ -8390,7 +8582,7 @@
     }
     // Otherwise allocate a new symbol.
     StringInputBuffer buffer(string_);
-    return Heap::AllocateInternalSymbol(&buffer,
+    return heap->AllocateInternalSymbol(&buffer,
                                         string_->length(),
                                         string_->hash_field());
   }
@@ -8429,8 +8621,8 @@
   }
 
   Object* obj;
-  { MaybeObject* maybe_obj =
-        Heap::AllocateHashTable(EntryToIndex(capacity), pretenure);
+  { MaybeObject* maybe_obj = Isolate::Current()->heap()->
+        AllocateHashTable(EntryToIndex(capacity), pretenure);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
   HashTable::cast(obj)->SetNumberOfElements(0);
@@ -8441,23 +8633,6 @@
 
 
 // Find entry for key otherwise return kNotFound.
-template<typename Shape, typename Key>
-int HashTable<Shape, Key>::FindEntry(Key key) {
-  uint32_t capacity = Capacity();
-  uint32_t entry = FirstProbe(Shape::Hash(key), capacity);
-  uint32_t count = 1;
-  // EnsureCapacity will guarantee the hash table is never full.
-  while (true) {
-    Object* element = KeyAt(entry);
-    if (element->IsUndefined()) break;  // Empty entry.
-    if (!element->IsNull() && Shape::IsMatch(key, element)) return entry;
-    entry = NextProbe(entry, count++, capacity);
-  }
-  return kNotFound;
-}
-
-
-// Find entry for key otherwise return kNotFound.
 int StringDictionary::FindEntry(String* key) {
   if (!key->IsSymbol()) {
     return HashTable<StringDictionaryShape, String*>::FindEntry(key);
@@ -8499,6 +8674,7 @@
 
 template<typename Shape, typename Key>
 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
+  Heap* heap = GetHeap();
   int capacity = Capacity();
   int nof = NumberOfElements() + n;
   int nod = NumberOfDeletedElements();
@@ -8512,7 +8688,7 @@
 
   const int kMinCapacityForPretenure = 256;
   bool pretenure =
-      (capacity > kMinCapacityForPretenure) && !Heap::InNewSpace(this);
+      (capacity > kMinCapacityForPretenure) && !heap->InNewSpace(this);
   Object* obj;
   { MaybeObject* maybe_obj =
         Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED);
@@ -8644,6 +8820,7 @@
 // Collates undefined and unexisting elements below limit from position
 // zero of the elements. The object stays in Dictionary mode.
 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
+  Heap* heap = GetHeap();
   ASSERT(HasDictionaryElements());
   // Must stay in dictionary mode, either because of requires_slow_elements,
   // or because we are not going to sort (and therefore compact) all of the
@@ -8653,7 +8830,7 @@
   if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
     // Allocate space for result before we start mutating the object.
     Object* new_double;
-    { MaybeObject* maybe_new_double = Heap::AllocateHeapNumber(0.0);
+    { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0);
       if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
     }
     result_double = HeapNumber::cast(new_double);
@@ -8719,7 +8896,7 @@
       // allocation. Bailout.
       return Smi::FromInt(-1);
     }
-    new_dict->AddNumberEntry(pos, Heap::undefined_value(), no_details)->
+    new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)->
         ToObjectUnchecked();
     pos++;
     undefs--;
@@ -8742,7 +8919,8 @@
 // If the object is in dictionary mode, it is converted to fast elements
 // mode.
 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) {
-  ASSERT(!HasPixelElements() && !HasExternalArrayElements());
+  Heap* heap = GetHeap();
+  ASSERT(!HasExternalArrayElements());
 
   if (HasDictionaryElements()) {
     // Convert to fast elements containing only the existing properties.
@@ -8760,10 +8938,10 @@
     }
     Map* new_map = Map::cast(obj);
 
-    PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED: TENURED;
+    PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED;
     Object* new_array;
     { MaybeObject* maybe_new_array =
-          Heap::AllocateFixedArray(dict->NumberOfElements(), tenure);
+          heap->AllocateFixedArray(dict->NumberOfElements(), tenure);
       if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array;
     }
     FixedArray* fast_elements = FixedArray::cast(new_array);
@@ -8796,7 +8974,7 @@
     // Pessimistically allocate space for return value before
     // we start mutating the array.
     Object* new_double;
-    { MaybeObject* maybe_new_double = Heap::AllocateHeapNumber(0.0);
+    { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0);
       if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
     }
     result_double = HeapNumber::cast(new_double);
@@ -8854,7 +9032,7 @@
 }
 
 
-Object* PixelArray::SetValue(uint32_t index, Object* value) {
+Object* ExternalPixelArray::SetValue(uint32_t index, Object* value) {
   uint8_t clamped_value = 0;
   if (index < static_cast<uint32_t>(length())) {
     if (value->IsSmi()) {
@@ -8890,7 +9068,8 @@
 
 
 template<typename ExternalArrayClass, typename ValueType>
-static MaybeObject* ExternalArrayIntSetter(ExternalArrayClass* receiver,
+static MaybeObject* ExternalArrayIntSetter(Heap* heap,
+                                           ExternalArrayClass* receiver,
                                            uint32_t index,
                                            Object* value) {
   ValueType cast_value = 0;
@@ -8908,45 +9087,46 @@
     }
     receiver->set(index, cast_value);
   }
-  return Heap::NumberFromInt32(cast_value);
+  return heap->NumberFromInt32(cast_value);
 }
 
 
 MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) {
   return ExternalArrayIntSetter<ExternalByteArray, int8_t>
-      (this, index, value);
+      (GetHeap(), this, index, value);
 }
 
 
 MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index,
                                                  Object* value) {
   return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t>
-      (this, index, value);
+      (GetHeap(), this, index, value);
 }
 
 
 MaybeObject* ExternalShortArray::SetValue(uint32_t index,
                                           Object* value) {
   return ExternalArrayIntSetter<ExternalShortArray, int16_t>
-      (this, index, value);
+      (GetHeap(), this, index, value);
 }
 
 
 MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index,
                                                   Object* value) {
   return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t>
-      (this, index, value);
+      (GetHeap(), this, index, value);
 }
 
 
 MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) {
   return ExternalArrayIntSetter<ExternalIntArray, int32_t>
-      (this, index, value);
+      (GetHeap(), this, index, value);
 }
 
 
 MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) {
   uint32_t cast_value = 0;
+  Heap* heap = GetHeap();
   if (index < static_cast<uint32_t>(length())) {
     if (value->IsSmi()) {
       int int_value = Smi::cast(value)->value();
@@ -8961,12 +9141,13 @@
     }
     set(index, cast_value);
   }
-  return Heap::NumberFromUint32(cast_value);
+  return heap->NumberFromUint32(cast_value);
 }
 
 
 MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) {
   float cast_value = 0;
+  Heap* heap = GetHeap();
   if (index < static_cast<uint32_t>(length())) {
     if (value->IsSmi()) {
       int int_value = Smi::cast(value)->value();
@@ -8981,7 +9162,7 @@
     }
     set(index, cast_value);
   }
-  return Heap::AllocateHeapNumber(cast_value);
+  return heap->AllocateHeapNumber(cast_value);
 }
 
 
@@ -8994,11 +9175,12 @@
 
 MaybeObject* GlobalObject::EnsurePropertyCell(String* name) {
   ASSERT(!HasFastProperties());
+  Heap* heap = GetHeap();
   int entry = property_dictionary()->FindEntry(name);
   if (entry == StringDictionary::kNotFound) {
     Object* cell;
     { MaybeObject* maybe_cell =
-          Heap::AllocateJSGlobalPropertyCell(Heap::the_hole_value());
+          heap->AllocateJSGlobalPropertyCell(heap->the_hole_value());
       if (!maybe_cell->ToObject(&cell)) return maybe_cell;
     }
     PropertyDetails details(NONE, NORMAL);
@@ -9170,9 +9352,10 @@
 
 
 Object* CompilationCacheTable::Lookup(String* src) {
+  Heap* heap = GetHeap();
   StringKey key(src);
   int entry = FindEntry(&key);
-  if (entry == kNotFound) return Heap::undefined_value();
+  if (entry == kNotFound) return heap->undefined_value();
   return get(EntryToIndex(entry) + 1);
 }
 
@@ -9182,16 +9365,17 @@
                                           StrictModeFlag strict_mode) {
   StringSharedKey key(src, context->closure()->shared(), strict_mode);
   int entry = FindEntry(&key);
-  if (entry == kNotFound) return Heap::undefined_value();
+  if (entry == kNotFound) return GetHeap()->undefined_value();
   return get(EntryToIndex(entry) + 1);
 }
 
 
 Object* CompilationCacheTable::LookupRegExp(String* src,
                                             JSRegExp::Flags flags) {
+  Heap* heap = GetHeap();
   RegExpKey key(src, flags);
   int entry = FindEntry(&key);
-  if (entry == kNotFound) return Heap::undefined_value();
+  if (entry == kNotFound) return heap->undefined_value();
   return get(EntryToIndex(entry) + 1);
 }
 
@@ -9262,12 +9446,13 @@
 
 
 void CompilationCacheTable::Remove(Object* value) {
+  Object* null_value = GetHeap()->null_value();
   for (int entry = 0, size = Capacity(); entry < size; entry++) {
     int entry_index = EntryToIndex(entry);
     int value_index = entry_index + 1;
     if (get(value_index) == value) {
-      fast_set(this, entry_index, Heap::null_value());
-      fast_set(this, value_index, Heap::null_value());
+      fast_set(this, entry_index, null_value);
+      fast_set(this, value_index, null_value);
       ElementRemoved();
     }
   }
@@ -9310,9 +9495,10 @@
 
 
 Object* MapCache::Lookup(FixedArray* array) {
+  Heap* heap = GetHeap();
   SymbolsKey key(array);
   int entry = FindEntry(&key);
-  if (entry == kNotFound) return Heap::undefined_value();
+  if (entry == kNotFound) return heap->undefined_value();
   return get(EntryToIndex(entry) + 1);
 }
 
@@ -9349,11 +9535,12 @@
 
 template<typename Shape, typename Key>
 MaybeObject* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
+  Heap* heap = Dictionary<Shape, Key>::GetHeap();
   int length = HashTable<Shape, Key>::NumberOfElements();
 
   // Allocate and initialize iteration order array.
   Object* obj;
-  { MaybeObject* maybe_obj = Heap::AllocateFixedArray(length);
+  { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
   FixedArray* iteration_order = FixedArray::cast(obj);
@@ -9362,7 +9549,7 @@
   }
 
   // Allocate array with enumeration order.
-  { MaybeObject* maybe_obj = Heap::AllocateFixedArray(length);
+  { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
   FixedArray* enumeration_order = FixedArray::cast(obj);
@@ -9423,8 +9610,9 @@
   // Do nothing if the interval [from, to) is empty.
   if (from >= to) return;
 
+  Heap* heap = GetHeap();
   int removed_entries = 0;
-  Object* sentinel = Heap::null_value();
+  Object* sentinel = heap->null_value();
   int capacity = Capacity();
   for (int i = 0; i < capacity; i++) {
     Object* key = KeyAt(i);
@@ -9445,14 +9633,15 @@
 template<typename Shape, typename Key>
 Object* Dictionary<Shape, Key>::DeleteProperty(int entry,
                                                JSObject::DeleteMode mode) {
+  Heap* heap = Dictionary<Shape, Key>::GetHeap();
   PropertyDetails details = DetailsAt(entry);
   // Ignore attributes if forcing a deletion.
   if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) {
-    return Heap::false_value();
+    return heap->false_value();
   }
-  SetEntry(entry, Heap::null_value(), Heap::null_value(), Smi::FromInt(0));
+  SetEntry(entry, heap->null_value(), heap->null_value(), Smi::FromInt(0));
   HashTable<Shape, Key>::ElementRemoved();
-  return Heap::true_value();
+  return heap->true_value();
 }
 
 
@@ -9665,6 +9854,7 @@
 // Backwards lookup (slow).
 template<typename Shape, typename Key>
 Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) {
+  Heap* heap = Dictionary<Shape, Key>::GetHeap();
   int capacity = HashTable<Shape, Key>::Capacity();
   for (int i = 0; i < capacity; i++) {
     Object* k =  HashTable<Shape, Key>::KeyAt(i);
@@ -9676,12 +9866,13 @@
       if (e == value) return k;
     }
   }
-  return Heap::undefined_value();
+  return heap->undefined_value();
 }
 
 
 MaybeObject* StringDictionary::TransformPropertiesToFastFor(
     JSObject* obj, int unused_property_fields) {
+  Heap* heap = GetHeap();
   // Make sure we preserve dictionary representation if there are too many
   // descriptors.
   if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj;
@@ -9711,7 +9902,7 @@
       ASSERT(type != FIELD);
       instance_descriptor_length++;
       if (type == NORMAL &&
-          (!value->IsJSFunction() || Heap::InNewSpace(value))) {
+          (!value->IsJSFunction() || heap->InNewSpace(value))) {
         number_of_fields += 1;
       }
     }
@@ -9739,7 +9930,7 @@
   // Allocate the fixed array for the fields.
   Object* fields;
   { MaybeObject* maybe_fields =
-        Heap::AllocateFixedArray(number_of_allocated_fields);
+        heap->AllocateFixedArray(number_of_allocated_fields);
     if (!maybe_fields->ToObject(&fields)) return maybe_fields;
   }
 
@@ -9752,13 +9943,13 @@
       Object* value = ValueAt(i);
       // Ensure the key is a symbol before writing into the instance descriptor.
       Object* key;
-      { MaybeObject* maybe_key = Heap::LookupSymbol(String::cast(k));
+      { MaybeObject* maybe_key = heap->LookupSymbol(String::cast(k));
         if (!maybe_key->ToObject(&key)) return maybe_key;
       }
       PropertyDetails details = DetailsAt(i);
       PropertyType type = details.type();
 
-      if (value->IsJSFunction() && !Heap::InNewSpace(value)) {
+      if (value->IsJSFunction() && !heap->InNewSpace(value)) {
         ConstantFunctionDescriptor d(String::cast(key),
                                      JSFunction::cast(value),
                                      details.attributes(),
@@ -9829,11 +10020,12 @@
 
 // Get the break point info object for this code position.
 Object* DebugInfo::GetBreakPointInfo(int code_position) {
+  Heap* heap = GetHeap();
   // 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();
+  if (index == kNoBreakPointInfo) return heap->undefined_value();
   return BreakPointInfo::cast(break_points()->get(index));
 }
 
@@ -9855,6 +10047,7 @@
                               int source_position,
                               int statement_position,
                               Handle<Object> break_point_object) {
+  Isolate* isolate = Isolate::Current();
   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
   if (!break_point_info->IsUndefined()) {
     BreakPointInfo::SetBreakPoint(
@@ -9877,8 +10070,9 @@
     Handle<FixedArray> old_break_points =
         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
     Handle<FixedArray> new_break_points =
-        Factory::NewFixedArray(old_break_points->length() +
-                               Debug::kEstimatedNofBreakPointsInFunction);
+        isolate->factory()->NewFixedArray(
+            old_break_points->length() +
+            Debug::kEstimatedNofBreakPointsInFunction);
 
     debug_info->set_break_points(*new_break_points);
     for (int i = 0; i < old_break_points->length(); i++) {
@@ -9889,13 +10083,14 @@
   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));
+  Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
+      isolate->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());
+  new_break_point_info->set_break_point_objects(
+      isolate->heap()->undefined_value());
   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
   debug_info->break_points()->set(index, *new_break_point_info);
 }
@@ -9903,9 +10098,10 @@
 
 // Get the break point objects for a code position.
 Object* DebugInfo::GetBreakPointObjects(int code_position) {
+  Heap* heap = GetHeap();
   Object* break_point_info = GetBreakPointInfo(code_position);
   if (break_point_info->IsUndefined()) {
-    return Heap::undefined_value();
+    return heap->undefined_value();
   }
   return BreakPointInfo::cast(break_point_info)->break_point_objects();
 }
@@ -9928,7 +10124,8 @@
 
 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
                                       Handle<Object> break_point_object) {
-  if (debug_info->break_points()->IsUndefined()) return Heap::undefined_value();
+  Heap* heap = Isolate::Current()->heap();
+  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 =
@@ -9940,7 +10137,7 @@
       }
     }
   }
-  return Heap::undefined_value();
+  return heap->undefined_value();
 }
 
 
@@ -9964,12 +10161,14 @@
 // Remove the specified break point object.
 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
                                      Handle<Object> break_point_object) {
+  Isolate* isolate = Isolate::Current();
   // 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());
+      break_point_info->set_break_point_objects(
+          isolate->heap()->undefined_value());
     }
     return;
   }
@@ -9979,7 +10178,7 @@
       Handle<FixedArray>(
           FixedArray::cast(break_point_info->break_point_objects()));
   Handle<FixedArray> new_array =
-      Factory::NewFixedArray(old_array->length() - 1);
+      isolate->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) {
@@ -10006,7 +10205,7 @@
   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);
+    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);
@@ -10017,7 +10216,7 @@
       Handle<FixedArray>(
           FixedArray::cast(break_point_info->break_point_objects()));
   Handle<FixedArray> new_array =
-      Factory::NewFixedArray(old_array->length() + 1);
+      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;
diff --git a/src/objects.h b/src/objects.h
index d7b87c6..96e5cb6 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -57,8 +57,8 @@
 //         - JSValue
 //         - JSMessageObject
 //       - ByteArray
-//       - PixelArray
 //       - ExternalArray
+//         - ExternalPixelArray
 //         - ExternalByteArray
 //         - ExternalUnsignedByteArray
 //         - ExternalShortArray
@@ -135,19 +135,37 @@
   PropertyDetails(PropertyAttributes attributes,
                   PropertyType type,
                   int index = 0) {
+    ASSERT(type != EXTERNAL_ARRAY_TRANSITION);
     ASSERT(TypeField::is_valid(type));
     ASSERT(AttributesField::is_valid(attributes));
-    ASSERT(IndexField::is_valid(index));
+    ASSERT(StorageField::is_valid(index));
 
     value_ = TypeField::encode(type)
         | AttributesField::encode(attributes)
-        | IndexField::encode(index);
+        | StorageField::encode(index);
 
     ASSERT(type == this->type());
     ASSERT(attributes == this->attributes());
     ASSERT(index == this->index());
   }
 
+  PropertyDetails(PropertyAttributes attributes,
+                  PropertyType type,
+                  ExternalArrayType array_type) {
+    ASSERT(type == EXTERNAL_ARRAY_TRANSITION);
+    ASSERT(TypeField::is_valid(type));
+    ASSERT(AttributesField::is_valid(attributes));
+    ASSERT(StorageField::is_valid(static_cast<int>(array_type)));
+
+    value_ = TypeField::encode(type)
+        | AttributesField::encode(attributes)
+        | StorageField::encode(static_cast<int>(array_type));
+
+    ASSERT(type == this->type());
+    ASSERT(attributes == this->attributes());
+    ASSERT(array_type == this->array_type());
+  }
+
   // Conversion for storing details as Object*.
   inline PropertyDetails(Smi* smi);
   inline Smi* AsSmi();
@@ -157,7 +175,8 @@
   bool IsTransition() {
     PropertyType t = type();
     ASSERT(t != INTERCEPTOR);
-    return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
+    return t == MAP_TRANSITION || t == CONSTANT_TRANSITION ||
+        t == EXTERNAL_ARRAY_TRANSITION;
   }
 
   bool IsProperty() {
@@ -166,11 +185,18 @@
 
   PropertyAttributes attributes() { return AttributesField::decode(value_); }
 
-  int index() { return IndexField::decode(value_); }
+  int index() { return StorageField::decode(value_); }
+
+  ExternalArrayType array_type() {
+    ASSERT(type() == EXTERNAL_ARRAY_TRANSITION);
+    return static_cast<ExternalArrayType>(StorageField::decode(value_));
+  }
 
   inline PropertyDetails AsDeleted();
 
-  static bool IsValidIndex(int index) { return IndexField::is_valid(index); }
+  static bool IsValidIndex(int index) {
+    return StorageField::is_valid(index);
+  }
 
   bool IsReadOnly() { return (attributes() & READ_ONLY) != 0; }
   bool IsDontDelete() { return (attributes() & DONT_DELETE) != 0; }
@@ -179,10 +205,10 @@
 
   // 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 DeletedField:    public BitField<uint32_t,           6, 1> {};
-  class IndexField:      public BitField<uint32_t,           7, 32-7> {};
+  class TypeField:       public BitField<PropertyType,       0, 4> {};
+  class AttributesField: public BitField<PropertyAttributes, 4, 3> {};
+  class DeletedField:    public BitField<uint32_t,           7, 1> {};
+  class StorageField:    public BitField<uint32_t,           8, 32-8> {};
 
   static const int kInitialIndex = 1;
  private:
@@ -262,7 +288,6 @@
   V(HEAP_NUMBER_TYPE)                                                          \
   V(PROXY_TYPE)                                                                \
   V(BYTE_ARRAY_TYPE)                                                           \
-  V(PIXEL_ARRAY_TYPE)                                                          \
   /* Note: the order of these external array */                                \
   /* types is relied upon in */                                                \
   /* Object::IsExternalArray(). */                                             \
@@ -273,6 +298,7 @@
   V(EXTERNAL_INT_ARRAY_TYPE)                                                   \
   V(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)                                          \
   V(EXTERNAL_FLOAT_ARRAY_TYPE)                                                 \
+  V(EXTERNAL_PIXEL_ARRAY_TYPE)                                                 \
   V(FILLER_TYPE)                                                               \
                                                                                \
   V(ACCESSOR_INFO_TYPE)                                                        \
@@ -490,14 +516,14 @@
   HEAP_NUMBER_TYPE,
   PROXY_TYPE,
   BYTE_ARRAY_TYPE,
-  PIXEL_ARRAY_TYPE,
   EXTERNAL_BYTE_ARRAY_TYPE,  // FIRST_EXTERNAL_ARRAY_TYPE
   EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE,
   EXTERNAL_SHORT_ARRAY_TYPE,
   EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE,
   EXTERNAL_INT_ARRAY_TYPE,
   EXTERNAL_UNSIGNED_INT_ARRAY_TYPE,
-  EXTERNAL_FLOAT_ARRAY_TYPE,  // LAST_EXTERNAL_ARRAY_TYPE
+  EXTERNAL_FLOAT_ARRAY_TYPE,
+  EXTERNAL_PIXEL_ARRAY_TYPE,  // LAST_EXTERNAL_ARRAY_TYPE
   FILLER_TYPE,  // LAST_DATA_TYPE
 
   // Structs.
@@ -544,7 +570,7 @@
   LAST_STRING_TYPE = FIRST_NONSTRING_TYPE - 1,
   // Boundaries for testing for an external array.
   FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_BYTE_ARRAY_TYPE,
-  LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_FLOAT_ARRAY_TYPE,
+  LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_PIXEL_ARRAY_TYPE,
   // Boundary for promotion to old data space/old pointer space.
   LAST_DATA_TYPE = FILLER_TYPE,
   // Boundaries for testing the type is a JavaScript "object".  Note that
@@ -557,6 +583,8 @@
   FIRST_FUNCTION_CLASS_TYPE = JS_REGEXP_TYPE
 };
 
+static const int kExternalArrayTypeCount = LAST_EXTERNAL_ARRAY_TYPE -
+    FIRST_EXTERNAL_ARRAY_TYPE + 1;
 
 STATIC_CHECK(JS_OBJECT_TYPE == Internals::kJSObjectType);
 STATIC_CHECK(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType);
@@ -655,7 +683,6 @@
   V(SeqTwoByteString)                          \
   V(SeqAsciiString)                            \
                                                \
-  V(PixelArray)                                \
   V(ExternalArray)                             \
   V(ExternalByteArray)                         \
   V(ExternalUnsignedByteArray)                 \
@@ -664,6 +691,7 @@
   V(ExternalIntArray)                          \
   V(ExternalUnsignedIntArray)                  \
   V(ExternalFloatArray)                        \
+  V(ExternalPixelArray)                        \
   V(ByteArray)                                 \
   V(JSObject)                                  \
   V(JSContextExtensionObject)                  \
@@ -729,6 +757,7 @@
   // Oddball testing.
   INLINE(bool IsUndefined());
   INLINE(bool IsNull());
+  INLINE(bool IsTheHole());  // Shadows MaybeObject's implementation.
   INLINE(bool IsTrue());
   INLINE(bool IsFalse());
   inline bool IsArgumentsMarker();
@@ -885,7 +914,7 @@
   enum Type {
     RETRY_AFTER_GC = 0,
     EXCEPTION = 1,       // Returning this marker tells the real exception
-                         // is in Top::pending_exception.
+                         // is in Isolate::pending_exception.
     INTERNAL_ERROR = 2,
     OUT_OF_MEMORY_EXCEPTION = 3
   };
@@ -1073,6 +1102,14 @@
   inline MapWord map_word();
   inline void set_map_word(MapWord map_word);
 
+  // The Heap the object was allocated in. Used also to access Isolate.
+  // This method can not be used during GC, it ASSERTs this.
+  inline Heap* GetHeap();
+  // Convenience method to get current isolate. This method can be
+  // accessed only when its result is the same as
+  // Isolate::Current(), it ASSERTs this. See also comment for GetHeap.
+  inline Isolate* GetIsolate();
+
   // Converts an address to a HeapObject pointer.
   static inline HeapObject* FromAddress(Address address);
 
@@ -1297,14 +1334,14 @@
     FAST_ELEMENTS,
     // All the kinds below are "slow".
     DICTIONARY_ELEMENTS,
-    PIXEL_ELEMENTS,
     EXTERNAL_BYTE_ELEMENTS,
     EXTERNAL_UNSIGNED_BYTE_ELEMENTS,
     EXTERNAL_SHORT_ELEMENTS,
     EXTERNAL_UNSIGNED_SHORT_ELEMENTS,
     EXTERNAL_INT_ELEMENTS,
     EXTERNAL_UNSIGNED_INT_ELEMENTS,
-    EXTERNAL_FLOAT_ELEMENTS
+    EXTERNAL_FLOAT_ELEMENTS,
+    EXTERNAL_PIXEL_ELEMENTS
   };
 
   // [properties]: Backing storage for properties.
@@ -1329,15 +1366,14 @@
   // few objects and so before writing to any element the array must
   // be copied. Use EnsureWritableFastElements in this case.
   //
-  // In the slow mode elements is either a NumberDictionary or a
-  // PixelArray or an ExternalArray.
+  // In the slow mode elements is either a NumberDictionary or an ExternalArray.
   DECL_ACCESSORS(elements, HeapObject)
   inline void initialize_elements();
   MUST_USE_RESULT inline MaybeObject* ResetElements();
   inline ElementsKind GetElementsKind();
   inline bool HasFastElements();
   inline bool HasDictionaryElements();
-  inline bool HasPixelElements();
+  inline bool HasExternalPixelElements();
   inline bool HasExternalArrayElements();
   inline bool HasExternalByteElements();
   inline bool HasExternalUnsignedByteElements();
@@ -1588,6 +1624,7 @@
   inline int GetHeaderSize();
 
   inline int GetInternalFieldCount();
+  inline int GetInternalFieldOffset(int index);
   inline Object* GetInternalField(int index);
   inline void SetInternalField(int index, Object* value);
 
@@ -1682,7 +1719,8 @@
   // Add a property to an object.
   MUST_USE_RESULT MaybeObject* AddProperty(String* name,
                                            Object* value,
-                                           PropertyAttributes attributes);
+                                           PropertyAttributes attributes,
+                                           StrictModeFlag strict_mode);
 
   // Convert the object to use the canonical dictionary
   // representation. If the object is expected to have additional properties
@@ -1705,6 +1743,7 @@
   inline Object* FastPropertyAtPut(int index, Object* value);
 
   // Access to in object properties.
+  inline int GetInObjectPropertyOffset(int index);
   inline Object* InObjectPropertyAt(int index);
   inline Object* InObjectPropertyAtPut(int index,
                                        Object* value,
@@ -1891,13 +1930,18 @@
 
   // Setters for frequently used oddballs located in old space.
   inline void set_undefined(int index);
+  // TODO(isolates): duplicate.
+  inline void set_undefined(Heap* heap, int index);
   inline void set_null(int index);
+  // TODO(isolates): duplicate.
+  inline void set_null(Heap* heap, int index);
   inline void set_the_hole(int index);
 
   // Setters with less debug checks for the GC to use.
   inline void set_unchecked(int index, Smi* value);
-  inline void set_null_unchecked(int index);
-  inline void set_unchecked(int index, Object* value, WriteBarrierMode mode);
+  inline void set_null_unchecked(Heap* heap, int index);
+  inline void set_unchecked(Heap* heap, int index, Object* value,
+                            WriteBarrierMode mode);
 
   // Gives access to raw memory which stores the array's data.
   inline Object** data_start();
@@ -1992,7 +2036,9 @@
 
   // Returns the number of descriptors in the array.
   int number_of_descriptors() {
-    return IsEmpty() ? 0 : length() - kFirstIndex;
+    ASSERT(length() > kFirstIndex || IsEmpty());
+    int len = length();
+    return len <= kFirstIndex ? 0 : len - kFirstIndex;
   }
 
   int NextEnumerationIndex() {
@@ -2284,7 +2330,8 @@
       (FixedArray::kMaxLength - kElementsStartOffset) / kEntrySize;
 
   // Find entry for key otherwise return kNotFound.
-  int FindEntry(Key key);
+  inline int FindEntry(Key key);
+  int FindEntry(Isolate* isolate, Key key);
 
  protected:
 
@@ -2356,16 +2403,16 @@
 
 class SymbolTableShape {
  public:
-  static bool IsMatch(HashTableKey* key, Object* value) {
+  static inline bool IsMatch(HashTableKey* key, Object* value) {
     return key->IsMatch(value);
   }
-  static uint32_t Hash(HashTableKey* key) {
+  static inline uint32_t Hash(HashTableKey* key) {
     return key->Hash();
   }
-  static uint32_t HashForObject(HashTableKey* key, Object* object) {
+  static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
     return key->HashForObject(object);
   }
-  MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
+  MUST_USE_RESULT static inline MaybeObject* AsObject(HashTableKey* key) {
     return key->AsObject();
   }
 
@@ -2408,18 +2455,18 @@
 
 class MapCacheShape {
  public:
-  static bool IsMatch(HashTableKey* key, Object* value) {
+  static inline bool IsMatch(HashTableKey* key, Object* value) {
     return key->IsMatch(value);
   }
-  static uint32_t Hash(HashTableKey* key) {
+  static inline uint32_t Hash(HashTableKey* key) {
     return key->Hash();
   }
 
-  static uint32_t HashForObject(HashTableKey* key, Object* object) {
+  static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
     return key->HashForObject(object);
   }
 
-  MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
+  MUST_USE_RESULT static inline MaybeObject* AsObject(HashTableKey* key) {
     return key->AsObject();
   }
 
@@ -2775,59 +2822,6 @@
 };
 
 
-// A PixelArray represents a fixed-size byte array with special semantics
-// used for implementing the CanvasPixelArray object. Please see the
-// specification at:
-// http://www.whatwg.org/specs/web-apps/current-work/
-//                      multipage/the-canvas-element.html#canvaspixelarray
-// In particular, write access clamps the value written to 0 or 255 if the
-// value written is outside this range.
-class PixelArray: public HeapObject {
- public:
-  // [length]: length of the array.
-  inline int length();
-  inline void set_length(int value);
-
-  // [external_pointer]: The pointer to the external memory area backing this
-  // pixel array.
-  DECL_ACCESSORS(external_pointer, uint8_t)  // Pointer to the data store.
-
-  // Setter and getter.
-  inline uint8_t get(int index);
-  inline void set(int index, uint8_t value);
-
-  // This accessor applies the correct conversion from Smi, HeapNumber and
-  // undefined and clamps the converted value between 0 and 255.
-  Object* SetValue(uint32_t index, Object* value);
-
-  // Casting.
-  static inline PixelArray* cast(Object* obj);
-
-#ifdef OBJECT_PRINT
-  inline void PixelArrayPrint() {
-    PixelArrayPrint(stdout);
-  }
-  void PixelArrayPrint(FILE* out);
-#endif
-#ifdef DEBUG
-  void PixelArrayVerify();
-#endif  // DEBUG
-
-  // Maximal acceptable length for a pixel array.
-  static const int kMaxLength = 0x3fffffff;
-
-  // PixelArray headers are not quadword aligned.
-  static const int kLengthOffset = HeapObject::kHeaderSize;
-  static const int kExternalPointerOffset =
-      POINTER_SIZE_ALIGN(kLengthOffset + kIntSize);
-  static const int kHeaderSize = kExternalPointerOffset + kPointerSize;
-  static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(PixelArray);
-};
-
-
 // An ExternalArray represents a fixed-size array of primitive values
 // which live outside the JavaScript heap. Its subclasses are used to
 // implement the CanvasArray types being defined in the WebGL
@@ -2867,6 +2861,44 @@
 };
 
 
+// A ExternalPixelArray represents a fixed-size byte array with special
+// semantics used for implementing the CanvasPixelArray object. Please see the
+// specification at:
+
+// http://www.whatwg.org/specs/web-apps/current-work/
+//                      multipage/the-canvas-element.html#canvaspixelarray
+// In particular, write access clamps the value written to 0 or 255 if the
+// value written is outside this range.
+class ExternalPixelArray: public ExternalArray {
+ public:
+  inline uint8_t* external_pixel_pointer();
+
+  // Setter and getter.
+  inline uint8_t get(int index);
+  inline void set(int index, uint8_t value);
+
+  // This accessor applies the correct conversion from Smi, HeapNumber and
+  // undefined and clamps the converted value between 0 and 255.
+  Object* SetValue(uint32_t index, Object* value);
+
+  // Casting.
+  static inline ExternalPixelArray* cast(Object* obj);
+
+#ifdef OBJECT_PRINT
+  inline void ExternalPixelArrayPrint() {
+    ExternalPixelArrayPrint(stdout);
+  }
+  void ExternalPixelArrayPrint(FILE* out);
+#endif
+#ifdef DEBUG
+  void ExternalPixelArrayVerify();
+#endif  // DEBUG
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalPixelArray);
+};
+
+
 class ExternalByteArray: public ExternalArray {
  public:
   // Setter and getter.
@@ -3201,10 +3233,12 @@
     BUILTIN,
     LOAD_IC,
     KEYED_LOAD_IC,
+    KEYED_EXTERNAL_ARRAY_LOAD_IC,
     CALL_IC,
     KEYED_CALL_IC,
     STORE_IC,
     KEYED_STORE_IC,
+    KEYED_EXTERNAL_ARRAY_STORE_IC,
     BINARY_OP_IC,
     TYPE_RECORDING_BINARY_OP_IC,
     COMPARE_IC,
@@ -3279,6 +3313,12 @@
     return kind() == TYPE_RECORDING_BINARY_OP_IC;
   }
   inline bool is_compare_ic_stub() { return kind() == COMPARE_IC; }
+  inline bool is_external_array_load_stub() {
+    return kind() == KEYED_EXTERNAL_ARRAY_LOAD_IC;
+  }
+  inline bool is_external_array_store_stub() {
+    return kind() == KEYED_EXTERNAL_ARRAY_STORE_IC;
+  }
 
   // [major_key]: For kind STUB or BINARY_OP_IC, the major key.
   inline int major_key();
@@ -3320,6 +3360,12 @@
   inline CheckType check_type();
   inline void set_check_type(CheckType value);
 
+  // [external array type]: For kind KEYED_EXTERNAL_ARRAY_LOAD_IC and
+  // KEYED_EXTERNAL_ARRAY_STORE_IC, identifies the type of external
+  // array that the code stub is specialized for.
+  inline ExternalArrayType external_array_type();
+  inline void set_external_array_type(ExternalArrayType value);
+
   // [binary op type]: For all BINARY_OP_IC.
   inline byte binary_op_type();
   inline void set_binary_op_type(byte value);
@@ -3430,7 +3476,7 @@
   inline void CodeIterateBody(ObjectVisitor* v);
 
   template<typename StaticVisitor>
-  inline void CodeIterateBody();
+  inline void CodeIterateBody(Heap* heap);
 #ifdef OBJECT_PRINT
   inline void CodePrint() {
     CodePrint(stdout);
@@ -3468,6 +3514,7 @@
   static const int kOptimizableOffset = kKindSpecificFlagsOffset;
   static const int kStackSlotsOffset = kKindSpecificFlagsOffset;
   static const int kCheckTypeOffset = kKindSpecificFlagsOffset;
+  static const int kExternalArrayTypeOffset = kKindSpecificFlagsOffset;
 
   static const int kCompareStateOffset = kStubMajorKeyOffset + 1;
   static const int kBinaryOpTypeOffset = kStubMajorKeyOffset + 1;
@@ -3484,18 +3531,18 @@
   static const int kFlagsICStateShift        = 0;
   static const int kFlagsICInLoopShift       = 3;
   static const int kFlagsTypeShift           = 4;
-  static const int kFlagsKindShift           = 7;
-  static const int kFlagsICHolderShift       = 11;
-  static const int kFlagsExtraICStateShift   = 12;
-  static const int kFlagsArgumentsCountShift = 14;
+  static const int kFlagsKindShift           = 8;
+  static const int kFlagsICHolderShift       = 12;
+  static const int kFlagsExtraICStateShift   = 13;
+  static const int kFlagsArgumentsCountShift = 15;
 
   static const int kFlagsICStateMask        = 0x00000007;  // 00000000111
   static const int kFlagsICInLoopMask       = 0x00000008;  // 00000001000
-  static const int kFlagsTypeMask           = 0x00000070;  // 00001110000
-  static const int kFlagsKindMask           = 0x00000780;  // 11110000000
-  static const int kFlagsCacheInPrototypeMapMask = 0x00000800;
-  static const int kFlagsExtraICStateMask   = 0x00003000;
-  static const int kFlagsArgumentsCountMask = 0xFFFFC000;
+  static const int kFlagsTypeMask           = 0x000000F0;  // 00001110000
+  static const int kFlagsKindMask           = 0x00000F00;  // 11110000000
+  static const int kFlagsCacheInPrototypeMapMask = 0x00001000;
+  static const int kFlagsExtraICStateMask   = 0x00006000;
+  static const int kFlagsArgumentsCountMask = 0xFFFF8000;
 
   static const int kFlagsNotUsedInLookup =
       (kFlagsICInLoopMask | kFlagsTypeMask | kFlagsCacheInPrototypeMapMask);
@@ -3625,16 +3672,16 @@
   }
 
   // Tells whether an instance has pixel array elements.
-  inline void set_has_pixel_array_elements(bool value) {
+  inline void set_has_external_array_elements(bool value) {
     if (value) {
-      set_bit_field2(bit_field2() | (1 << kHasPixelArrayElements));
+      set_bit_field2(bit_field2() | (1 << kHasExternalArrayElements));
     } else {
-      set_bit_field2(bit_field2() & ~(1 << kHasPixelArrayElements));
+      set_bit_field2(bit_field2() & ~(1 << kHasExternalArrayElements));
     }
   }
 
-  inline bool has_pixel_array_elements() {
-    return ((1 << kHasPixelArrayElements) & bit_field2()) != 0;
+  inline bool has_external_array_elements() {
+    return ((1 << kHasExternalArrayElements) & bit_field2()) != 0;
   }
 
   // Tells whether the map is attached to SharedFunctionInfo
@@ -3695,10 +3742,11 @@
   // from the descriptors and the fast elements bit cleared.
   MUST_USE_RESULT inline MaybeObject* GetSlowElementsMap();
 
-  // Returns this map if it has the pixel array elements bit is set, otherwise
-  // returns a copy of the map, with all transitions dropped from the
-  // descriptors and the pixel array elements bit set.
-  MUST_USE_RESULT inline MaybeObject* GetPixelArrayElementsMap();
+  // Returns a new map with all transitions dropped from the descriptors and the
+  // external array elements bit set.
+  MUST_USE_RESULT MaybeObject* GetExternalArrayElementsMap(
+      ExternalArrayType array_type,
+      bool safe_to_add_transition);
 
   // Returns the property index for name (only valid for FAST MODE).
   int PropertyIndexFor(String* name);
@@ -3718,7 +3766,7 @@
   // Code cache operations.
 
   // Clears the code cache.
-  inline void ClearCodeCache();
+  inline void ClearCodeCache(Heap* heap);
 
   // Update code cache.
   MUST_USE_RESULT MaybeObject* UpdateCodeCache(String* name, Code* code);
@@ -3742,7 +3790,7 @@
   // 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);
+  void ClearNonLiveTransitions(Heap* heap, Object* real_prototype);
 
   // Dispatched behavior.
 #ifdef OBJECT_PRINT
@@ -3759,6 +3807,10 @@
   inline int visitor_id();
   inline void set_visitor_id(int visitor_id);
 
+  // Returns the isolate/heap this map belongs to.
+  inline Isolate* isolate();
+  inline Heap* heap();
+
   typedef void (*TraverseCallback)(Map* map, void* data);
 
   void TraverseTransitionTree(TraverseCallback callback, void* data);
@@ -3818,7 +3870,7 @@
   static const int kStringWrapperSafeForDefaultValueOf = 3;
   static const int kAttachedToSharedFunctionInfo = 4;
   static const int kIsShared = 5;
-  static const int kHasPixelArrayElements = 6;
+  static const int kHasExternalArrayElements = 6;
 
   // Layout of the default cache. It holds alternating name and code objects.
   static const int kCodeCacheEntrySize = 2;
@@ -5156,6 +5208,11 @@
 };
 
 
+// Calculates string hash.
+template <typename schar>
+inline uint32_t HashSequentialString(const schar* chars, int length);
+
+
 // 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
@@ -5799,11 +5856,8 @@
 // iterating or updating after gc.
 class Relocatable BASE_EMBEDDED {
  public:
-  inline Relocatable() : prev_(top_) { top_ = this; }
-  virtual ~Relocatable() {
-    ASSERT_EQ(top_, this);
-    top_ = prev_;
-  }
+  explicit inline Relocatable(Isolate* isolate);
+  inline virtual ~Relocatable();
   virtual void IterateInstance(ObjectVisitor* v) { }
   virtual void PostGarbageCollection() { }
 
@@ -5815,7 +5869,7 @@
   static void Iterate(ObjectVisitor* v, Relocatable* top);
   static char* Iterate(ObjectVisitor* v, char* t);
  private:
-  static Relocatable* top_;
+  Isolate* isolate_;
   Relocatable* prev_;
 };
 
@@ -5825,8 +5879,8 @@
 // must be valid as long as the reader is being used.
 class FlatStringReader : public Relocatable {
  public:
-  explicit FlatStringReader(Handle<String> str);
-  explicit FlatStringReader(Vector<const char> input);
+  FlatStringReader(Isolate* isolate, Handle<String> str);
+  FlatStringReader(Isolate* isolate, Vector<const char> input);
   void PostGarbageCollection();
   inline uc32 Get(int index);
   int length() { return length_; }
@@ -5889,6 +5943,9 @@
   // [to_number]: Cached to_number computed at startup.
   DECL_ACCESSORS(to_number, Object)
 
+  inline byte kind();
+  inline void set_kind(byte kind);
+
   // Casting.
   static inline Oddball* cast(Object* obj);
 
@@ -5899,12 +5956,23 @@
 
   // Initialize the fields.
   MUST_USE_RESULT MaybeObject* Initialize(const char* to_string,
-                                          Object* to_number);
+                                          Object* to_number,
+                                          byte kind);
 
   // Layout description.
   static const int kToStringOffset = HeapObject::kHeaderSize;
   static const int kToNumberOffset = kToStringOffset + kPointerSize;
-  static const int kSize = kToNumberOffset + kPointerSize;
+  static const int kKindOffset = kToNumberOffset + kPointerSize;
+  static const int kSize = kKindOffset + kPointerSize;
+
+  static const byte kFalse = 0;
+  static const byte kTrue = 1;
+  static const byte kNotBooleanMask = ~1;
+  static const byte kTheHole = 2;
+  static const byte kNull = 3;
+  static const byte kArgumentMarker = 4;
+  static const byte kUndefined = 5;
+  static const byte kOther = 6;
 
   typedef FixedBodyDescriptor<kToStringOffset,
                               kToNumberOffset + kPointerSize,
@@ -6537,6 +6605,9 @@
     VisitExternalReferences(p, p + 1);
   }
 
+  // Visits a handle that has an embedder-assigned class ID.
+  virtual void VisitEmbedderReference(Object** p, uint16_t class_id) {}
+
 #ifdef DEBUG
   // Intended for serialization/deserialization checking: insert, or
   // check for the presence of, a tag at this position in the stream.
diff --git a/src/parser.cc b/src/parser.cc
index 3c361a7..13e0c33 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -246,93 +246,6 @@
 }
 
 
-// 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(TemporaryScope** variable);
-  ~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 SetThisPropertyAssignmentInfo(
-      bool only_simple_this_property_assignments,
-      Handle<FixedArray> this_property_assignments) {
-    only_simple_this_property_assignments_ =
-        only_simple_this_property_assignments;
-    this_property_assignments_ = this_property_assignments;
-  }
-  bool only_simple_this_property_assignments() {
-    return only_simple_this_property_assignments_;
-  }
-  Handle<FixedArray> this_property_assignments() {
-    return this_property_assignments_;
-  }
-
-  void AddProperty() { expected_property_count_++; }
-  int expected_property_count() { return expected_property_count_; }
-
-  void AddLoop() { loop_count_++; }
-  bool ContainsLoops() const { return loop_count_ > 0; }
-
-  bool StrictMode() { return strict_mode_; }
-  void EnableStrictMode() {
-    strict_mode_ = FLAG_strict_mode;
-  }
-
- private:
-  // Captures the number of literals that need materialization in the
-  // function.  Includes regexp literals, and boilerplate for object
-  // and array literals.
-  int materialized_literal_count_;
-
-  // Properties count estimation.
-  int expected_property_count_;
-
-  // Keeps track of assignments to properties of this. Used for
-  // optimizing constructors.
-  bool only_simple_this_property_assignments_;
-  Handle<FixedArray> this_property_assignments_;
-
-  // Captures the number of loops inside the scope.
-  int loop_count_;
-
-  // Parsing strict mode code.
-  bool strict_mode_;
-
-  // Bookkeeping
-  TemporaryScope** variable_;
-  TemporaryScope* parent_;
-};
-
-
-TemporaryScope::TemporaryScope(TemporaryScope** variable)
-  : materialized_literal_count_(0),
-    expected_property_count_(0),
-    only_simple_this_property_assignments_(false),
-    this_property_assignments_(Factory::empty_fixed_array()),
-    loop_count_(0),
-    variable_(variable),
-    parent_(*variable) {
-  // Inherit the strict mode from the parent scope.
-  strict_mode_ = (parent_ != NULL) && parent_->strict_mode_;
-  *variable = this;
-}
-
-
-TemporaryScope::~TemporaryScope() {
-  *variable_ = parent_;
-}
-
-
 Handle<String> Parser::LookupSymbol(int symbol_id) {
   // Length of symbol cache is the number of identified symbols.
   // If we are larger than that, or negative, it's not a cached symbol.
@@ -341,9 +254,11 @@
   if (static_cast<unsigned>(symbol_id)
       >= static_cast<unsigned>(symbol_cache_.length())) {
     if (scanner().is_literal_ascii()) {
-      return Factory::LookupAsciiSymbol(scanner().literal_ascii_string());
+      return isolate()->factory()->LookupAsciiSymbol(
+          scanner().literal_ascii_string());
     } else {
-      return Factory::LookupTwoByteSymbol(scanner().literal_uc16_string());
+      return isolate()->factory()->LookupTwoByteSymbol(
+          scanner().literal_uc16_string());
     }
   }
   return LookupCachedSymbol(symbol_id);
@@ -360,14 +275,16 @@
   Handle<String> result = symbol_cache_.at(symbol_id);
   if (result.is_null()) {
     if (scanner().is_literal_ascii()) {
-      result = Factory::LookupAsciiSymbol(scanner().literal_ascii_string());
+      result = isolate()->factory()->LookupAsciiSymbol(
+          scanner().literal_ascii_string());
     } else {
-      result = Factory::LookupTwoByteSymbol(scanner().literal_uc16_string());
+      result = isolate()->factory()->LookupTwoByteSymbol(
+          scanner().literal_uc16_string());
     }
     symbol_cache_.at(symbol_id) = result;
     return result;
   }
-  Counters::total_preparse_symbols_skipped.Increment();
+  isolate()->counters()->total_preparse_symbols_skipped()->Increment();
   return result;
 }
 
@@ -544,33 +461,94 @@
 // 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.
+//
+// Additionlaly, it stores transient information used during parsing.
+// These 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 LexicalScope BASE_EMBEDDED {
  public:
-  LexicalScope(Scope** scope_variable,
-               int* with_nesting_level_variable,
-               Scope* scope)
-    : scope_variable_(scope_variable),
-      with_nesting_level_variable_(with_nesting_level_variable),
-      prev_scope_(*scope_variable),
-      prev_level_(*with_nesting_level_variable) {
-    *scope_variable = scope;
-    *with_nesting_level_variable = 0;
+  LexicalScope(Parser* parser, Scope* scope, Isolate* isolate);
+  ~LexicalScope();
+
+  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 SetThisPropertyAssignmentInfo(
+      bool only_simple_this_property_assignments,
+      Handle<FixedArray> this_property_assignments) {
+    only_simple_this_property_assignments_ =
+        only_simple_this_property_assignments;
+    this_property_assignments_ = this_property_assignments;
+  }
+  bool only_simple_this_property_assignments() {
+    return only_simple_this_property_assignments_;
+  }
+  Handle<FixedArray> this_property_assignments() {
+    return this_property_assignments_;
   }
 
-  ~LexicalScope() {
-    (*scope_variable_)->Leave();
-    *scope_variable_ = prev_scope_;
-    *with_nesting_level_variable_ = prev_level_;
-  }
+  void AddProperty() { expected_property_count_++; }
+  int expected_property_count() { return expected_property_count_; }
+
+  void AddLoop() { loop_count_++; }
+  bool ContainsLoops() const { return loop_count_ > 0; }
 
  private:
-  Scope** scope_variable_;
-  int* with_nesting_level_variable_;
-  Scope* prev_scope_;
-  int prev_level_;
+  // Captures the number of literals that need materialization in the
+  // function.  Includes regexp literals, and boilerplate for object
+  // and array literals.
+  int materialized_literal_count_;
+
+  // Properties count estimation.
+  int expected_property_count_;
+
+  // Keeps track of assignments to properties of this. Used for
+  // optimizing constructors.
+  bool only_simple_this_property_assignments_;
+  Handle<FixedArray> this_property_assignments_;
+
+  // Captures the number of loops inside the scope.
+  int loop_count_;
+
+  // Bookkeeping
+  Parser* parser_;
+  // Previous values
+  LexicalScope* lexical_scope_parent_;
+  Scope* previous_scope_;
+  int previous_with_nesting_level_;
 };
 
+
+LexicalScope::LexicalScope(Parser* parser, Scope* scope, Isolate* isolate)
+  : materialized_literal_count_(0),
+    expected_property_count_(0),
+    only_simple_this_property_assignments_(false),
+    this_property_assignments_(isolate->factory()->empty_fixed_array()),
+    loop_count_(0),
+    parser_(parser),
+    lexical_scope_parent_(parser->lexical_scope_),
+    previous_scope_(parser->top_scope_),
+    previous_with_nesting_level_(parser->with_nesting_level_) {
+  parser->top_scope_ = scope;
+  parser->lexical_scope_ = this;
+  parser->with_nesting_level_ = 0;
+}
+
+
+LexicalScope::~LexicalScope() {
+  parser_->top_scope_->Leave();
+  parser_->top_scope_ = previous_scope_;
+  parser_->lexical_scope_ = lexical_scope_parent_;
+  parser_->with_nesting_level_ = previous_with_nesting_level_;
+}
+
+
 // ----------------------------------------------------------------------------
 // The CHECK_OK macro is a convenient macro to enforce error
 // handling for functions that may fail (by returning !*ok).
@@ -598,12 +576,13 @@
                bool allow_natives_syntax,
                v8::Extension* extension,
                ScriptDataImpl* pre_data)
-    : symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
+    : isolate_(script->GetIsolate()),
+      symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
       script_(script),
-      scanner_(),
+      scanner_(isolate_->scanner_constants()),
       top_scope_(NULL),
       with_nesting_level_(0),
-      temp_scope_(NULL),
+      lexical_scope_(NULL),
       target_stack_(NULL),
       allow_natives_syntax_(allow_natives_syntax),
       extension_(extension),
@@ -620,8 +599,8 @@
                                       StrictModeFlag strict_mode) {
   CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
 
-  HistogramTimerScope timer(&Counters::parse);
-  Counters::total_parse_size.Increment(source->length());
+  HistogramTimerScope timer(isolate()->counters()->parse());
+  isolate()->counters()->total_parse_size()->Increment(source->length());
   fni_ = new FuncNameInferrer();
 
   // Initialize parser state.
@@ -657,21 +636,19 @@
     in_global_context
       ? Scope::GLOBAL_SCOPE
       : Scope::EVAL_SCOPE;
-  Handle<String> no_name = Factory::empty_symbol();
+  Handle<String> no_name = isolate()->factory()->empty_symbol();
 
   FunctionLiteral* result = NULL;
   { Scope* scope = NewScope(top_scope_, type, inside_with());
-    LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
-                               scope);
-    TemporaryScope temp_scope(&this->temp_scope_);
+    LexicalScope lexical_scope(this, scope, isolate());
     if (strict_mode == kStrictMode) {
-      temp_scope.EnableStrictMode();
+      top_scope_->EnableStrictMode();
     }
     ZoneList<Statement*>* body = new ZoneList<Statement*>(16);
     bool ok = true;
     int beg_loc = scanner().location().beg_pos;
     ParseSourceElements(body, Token::EOS, &ok);
-    if (ok && temp_scope_->StrictMode()) {
+    if (ok && top_scope_->is_strict_mode()) {
       CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
     }
     if (ok) {
@@ -679,18 +656,17 @@
           no_name,
           top_scope_,
           body,
-          temp_scope.materialized_literal_count(),
-          temp_scope.expected_property_count(),
-          temp_scope.only_simple_this_property_assignments(),
-          temp_scope.this_property_assignments(),
+          lexical_scope.materialized_literal_count(),
+          lexical_scope.expected_property_count(),
+          lexical_scope.only_simple_this_property_assignments(),
+          lexical_scope.this_property_assignments(),
           0,
           0,
           source->length(),
           false,
-          temp_scope.ContainsLoops(),
-          temp_scope.StrictMode());
+          lexical_scope.ContainsLoops());
     } else if (stack_overflow_) {
-      Top::StackOverflow();
+      isolate()->StackOverflow();
     }
   }
 
@@ -703,38 +679,40 @@
   return result;
 }
 
-FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) {
+FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) {
   CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
-  HistogramTimerScope timer(&Counters::parse_lazy);
+  HistogramTimerScope timer(isolate()->counters()->parse_lazy());
   Handle<String> source(String::cast(script_->source()));
-  Counters::total_parse_size.Increment(source->length());
+  isolate()->counters()->total_parse_size()->Increment(source->length());
 
+  Handle<SharedFunctionInfo> shared_info = info->shared_info();
   // Initialize parser state.
   source->TryFlatten();
   if (source->IsExternalTwoByteString()) {
     ExternalTwoByteStringUC16CharacterStream stream(
         Handle<ExternalTwoByteString>::cast(source),
-        info->start_position(),
-        info->end_position());
+        shared_info->start_position(),
+        shared_info->end_position());
     FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
     return result;
   } else {
     GenericStringUC16CharacterStream stream(source,
-                                            info->start_position(),
-                                            info->end_position());
+                                            shared_info->start_position(),
+                                            shared_info->end_position());
     FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
     return result;
   }
 }
 
 
-FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
+FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
                                    UC16CharacterStream* source,
                                    ZoneScope* zone_scope) {
+  Handle<SharedFunctionInfo> shared_info = info->shared_info();
   scanner_.Initialize(source);
   ASSERT(target_stack_ == NULL);
 
-  Handle<String> name(String::cast(info->name()));
+  Handle<String> name(String::cast(shared_info->name()));
   fni_ = new FuncNameInferrer();
   fni_->PushEnclosingName(name);
 
@@ -745,19 +723,19 @@
 
   {
     // Parse the function literal.
-    Handle<String> no_name = Factory::empty_symbol();
-    Scope* scope =
-        NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
-    LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
-                               scope);
-    TemporaryScope temp_scope(&this->temp_scope_);
+    Handle<String> no_name = isolate()->factory()->empty_symbol();
+    Scope* scope = NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
+    if (!info->closure().is_null()) {
+      scope = Scope::DeserializeScopeChain(info, scope);
+    }
+    LexicalScope lexical_scope(this, scope, isolate());
 
-    if (info->strict_mode()) {
-      temp_scope.EnableStrictMode();
+    if (shared_info->strict_mode()) {
+      top_scope_->EnableStrictMode();
     }
 
     FunctionLiteralType type =
-        info->is_expression() ? EXPRESSION : DECLARATION;
+        shared_info->is_expression() ? EXPRESSION : DECLARATION;
     bool ok = true;
     result = ParseFunctionLiteral(name,
                                   false,    // Strict mode name already checked.
@@ -773,9 +751,9 @@
   // not safe to do before scope has been deleted.
   if (result == NULL) {
     zone_scope->DeleteOnExit();
-    if (stack_overflow_) Top::StackOverflow();
+    if (stack_overflow_) isolate()->StackOverflow();
   } else {
-    Handle<String> inferred_name(info->inferred_name());
+    Handle<String> inferred_name(shared_info->inferred_name());
     result->set_inferred_name(inferred_name);
   }
   return result;
@@ -803,14 +781,15 @@
   MessageLocation location(script_,
                            source_location.beg_pos,
                            source_location.end_pos);
-  Handle<FixedArray> elements = Factory::NewFixedArray(args.length());
+  Factory* factory = isolate()->factory();
+  Handle<FixedArray> elements = factory->NewFixedArray(args.length());
   for (int i = 0; i < args.length(); i++) {
-    Handle<String> arg_string = Factory::NewStringFromUtf8(CStrVector(args[i]));
+    Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
     elements->set(i, *arg_string);
   }
-  Handle<JSArray> array = Factory::NewJSArrayWithElements(elements);
-  Handle<Object> result = Factory::NewSyntaxError(type, array);
-  Top::Throw(*result, &location);
+  Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
+  Handle<Object> result = factory->NewSyntaxError(type, array);
+  isolate()->Throw(*result, &location);
 }
 
 
@@ -820,13 +799,14 @@
   MessageLocation location(script_,
                            source_location.beg_pos,
                            source_location.end_pos);
-  Handle<FixedArray> elements = Factory::NewFixedArray(args.length());
+  Factory* factory = isolate()->factory();
+  Handle<FixedArray> elements = factory->NewFixedArray(args.length());
   for (int i = 0; i < args.length(); i++) {
     elements->set(i, *args[i]);
   }
-  Handle<JSArray> array = Factory::NewJSArrayWithElements(elements);
-  Handle<Object> result = Factory::NewSyntaxError(type, array);
-  Top::Throw(*result, &location);
+  Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
+  Handle<Object> result = factory->NewSyntaxError(type, array);
+  isolate()->Throw(*result, &location);
 }
 
 
@@ -951,8 +931,9 @@
 // function contains only assignments of this type.
 class ThisNamedPropertyAssigmentFinder : public ParserFinder {
  public:
-  ThisNamedPropertyAssigmentFinder()
-      : only_simple_this_property_assignments_(true),
+  explicit ThisNamedPropertyAssigmentFinder(Isolate* isolate)
+      : isolate_(isolate),
+        only_simple_this_property_assignments_(true),
         names_(NULL),
         assigned_arguments_(NULL),
         assigned_constants_(NULL) {}
@@ -983,14 +964,14 @@
   // form this.x = y;
   Handle<FixedArray> GetThisPropertyAssignments() {
     if (names_ == NULL) {
-      return Factory::empty_fixed_array();
+      return isolate_->factory()->empty_fixed_array();
     }
     ASSERT(names_ != NULL);
     ASSERT(assigned_arguments_ != NULL);
     ASSERT_EQ(names_->length(), assigned_arguments_->length());
     ASSERT_EQ(names_->length(), assigned_constants_->length());
     Handle<FixedArray> assignments =
-        Factory::NewFixedArray(names_->length() * 3);
+        isolate_->factory()->NewFixedArray(names_->length() * 3);
     for (int i = 0; i < names_->length(); i++) {
       assignments->set(i * 3, *names_->at(i));
       assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_->at(i)));
@@ -1020,7 +1001,8 @@
     uint32_t dummy;
     if (literal != NULL &&
         literal->handle()->IsString() &&
-        !String::cast(*(literal->handle()))->Equals(Heap::Proto_symbol()) &&
+        !String::cast(*(literal->handle()))->Equals(
+            isolate_->heap()->Proto_symbol()) &&
         !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
       Handle<String> key = Handle<String>::cast(literal->handle());
 
@@ -1054,7 +1036,7 @@
     EnsureAllocation();
     names_->Add(name);
     assigned_arguments_->Add(index);
-    assigned_constants_->Add(Factory::undefined_value());
+    assigned_constants_->Add(isolate_->factory()->undefined_value());
   }
 
   void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
@@ -1079,6 +1061,7 @@
     }
   }
 
+  Isolate* isolate_;
   bool only_simple_this_property_assignments_;
   ZoneStringList* names_;
   ZoneList<int>* assigned_arguments_;
@@ -1100,7 +1083,7 @@
 
   ASSERT(processor != NULL);
   InitializationBlockFinder block_finder;
-  ThisNamedPropertyAssigmentFinder this_property_assignment_finder;
+  ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate());
   bool directive_prologue = true;     // Parsing directive prologue.
 
   while (peek() != end_token) {
@@ -1140,11 +1123,11 @@
         Handle<String> directive = Handle<String>::cast(literal->handle());
 
         // Check "use strict" directive (ES5 14.1).
-        if (!temp_scope_->StrictMode() &&
-            directive->Equals(Heap::use_strict()) &&
+        if (!top_scope_->is_strict_mode() &&
+            directive->Equals(isolate()->heap()->use_strict()) &&
             token_loc.end_pos - token_loc.beg_pos ==
-              Heap::use_strict()->length() + 2) {
-          temp_scope_->EnableStrictMode();
+              isolate()->heap()->use_strict()->length() + 2) {
+          top_scope_->EnableStrictMode();
           // "use strict" is the only directive for now.
           directive_prologue = false;
         }
@@ -1173,7 +1156,7 @@
         this_property_assignment_finder.only_simple_this_property_assignments()
         && top_scope_->declarations()->length() == 0;
     if (only_simple_this_property_assignments) {
-      temp_scope_->SetThisPropertyAssignmentInfo(
+      lexical_scope_->SetThisPropertyAssignmentInfo(
           only_simple_this_property_assignments,
           this_property_assignment_finder.GetThisPropertyAssignments());
     }
@@ -1282,7 +1265,7 @@
     case Token::FUNCTION: {
       // In strict mode, FunctionDeclaration is only allowed in the context
       // of SourceElements.
-      if (temp_scope_->StrictMode()) {
+      if (top_scope_->is_strict_mode()) {
         ReportMessageAt(scanner().peek_location(), "strict_function",
                         Vector<const char*>::empty());
         *ok = false;
@@ -1341,9 +1324,9 @@
                var->mode() == Variable::CONST);
         const char* type = (var->mode() == Variable::VAR) ? "var" : "const";
         Handle<String> type_string =
-            Factory::NewStringFromUtf8(CStrVector(type), TENURED);
+            isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED);
         Expression* expression =
-            NewThrowTypeError(Factory::redeclaration_symbol(),
+            NewThrowTypeError(isolate()->factory()->redeclaration_symbol(),
                               type_string, name);
         top_scope_->SetIllegalRedeclaration(expression);
       }
@@ -1449,7 +1432,7 @@
   Handle<Code> code = Handle<Code>(fun->shared()->code());
   Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
   Handle<SharedFunctionInfo> shared =
-      Factory::NewSharedFunctionInfo(name, literals, code,
+      isolate()->factory()->NewSharedFunctionInfo(name, literals, code,
           Handle<SerializedScopeInfo>(fun->shared()->scope_info()));
   shared->set_construct_stub(*construct_stub);
 
@@ -1518,11 +1501,13 @@
   return result;
 }
 
-static bool IsEvalOrArguments(Handle<String> string) {
-  return string.is_identical_to(Factory::eval_symbol()) ||
-         string.is_identical_to(Factory::arguments_symbol());
+
+bool Parser::IsEvalOrArguments(Handle<String> string) {
+  return string.is_identical_to(isolate()->factory()->eval_symbol()) ||
+      string.is_identical_to(isolate()->factory()->arguments_symbol());
 }
 
+
 // 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
@@ -1540,7 +1525,7 @@
     Consume(Token::VAR);
   } else if (peek() == Token::CONST) {
     Consume(Token::CONST);
-    if (temp_scope_->StrictMode()) {
+    if (top_scope_->is_strict_mode()) {
       ReportMessage("strict_const", Vector<const char*>::empty());
       *ok = false;
       return NULL;
@@ -1576,7 +1561,7 @@
     if (fni_ != NULL) fni_->PushVariableName(name);
 
     // Strict mode variables may not be named eval or arguments
-    if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) {
+    if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) {
       ReportMessage("strict_var_name", Vector<const char*>::empty());
       *ok = false;
       return NULL;
@@ -1678,14 +1663,14 @@
         // the number of arguments (1 or 2).
         initialize =
             new CallRuntime(
-              Factory::InitializeConstGlobal_symbol(),
+              isolate()->factory()->InitializeConstGlobal_symbol(),
               Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
               arguments);
       } else {
         // Add strict mode.
         // We may want to pass singleton to avoid Literal allocations.
         arguments->Add(NewNumberLiteral(
-            temp_scope_->StrictMode() ? kStrictMode : kNonStrictMode));
+            top_scope_->is_strict_mode() ? kStrictMode : kNonStrictMode));
 
         // Be careful not to assign a value to the global variable if
         // we're in a with. The initialization value should not
@@ -1702,7 +1687,7 @@
         // the number of arguments (2 or 3).
         initialize =
             new CallRuntime(
-              Factory::InitializeVarGlobal_symbol(),
+              isolate()->factory()->InitializeVarGlobal_symbol(),
               Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
               arguments);
       }
@@ -1893,7 +1878,7 @@
   //
   // To be consistent with KJS we report the syntax error at runtime.
   if (!top_scope_->is_function_scope()) {
-    Handle<String> type = Factory::illegal_return_symbol();
+    Handle<String> type = isolate()->factory()->illegal_return_symbol();
     Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
     return new ExpressionStatement(throw_error);
   }
@@ -1958,7 +1943,7 @@
 
   Expect(Token::WITH, CHECK_OK);
 
-  if (temp_scope_->StrictMode()) {
+  if (top_scope_->is_strict_mode()) {
     ReportMessage("strict_mode_with", Vector<const char*>::empty());
     *ok = false;
     return NULL;
@@ -2097,7 +2082,7 @@
     Expect(Token::LPAREN, CHECK_OK);
     Handle<String> name = ParseIdentifier(CHECK_OK);
 
-    if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) {
+    if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) {
       ReportMessage("strict_catch_variable", Vector<const char*>::empty());
       *ok = false;
       return NULL;
@@ -2108,7 +2093,8 @@
     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());
+      catch_var =
+          top_scope_->NewTemporary(isolate()->factory()->catch_var_symbol());
       Literal* name_literal = new Literal(name);
       VariableProxy* catch_var_use = new VariableProxy(catch_var);
       Expression* obj = new CatchExtensionObject(name_literal, catch_var_use);
@@ -2169,7 +2155,7 @@
   // DoStatement ::
   //   'do' Statement 'while' '(' Expression ')' ';'
 
-  temp_scope_->AddLoop();
+  lexical_scope_->AddLoop();
   DoWhileStatement* loop = new DoWhileStatement(labels);
   Target target(&this->target_stack_, loop);
 
@@ -2202,7 +2188,7 @@
   // WhileStatement ::
   //   'while' '(' Expression ')' Statement
 
-  temp_scope_->AddLoop();
+  lexical_scope_->AddLoop();
   WhileStatement* loop = new WhileStatement(labels);
   Target target(&this->target_stack_, loop);
 
@@ -2222,7 +2208,7 @@
   // ForStatement ::
   //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
 
-  temp_scope_->AddLoop();
+  lexical_scope_->AddLoop();
   Statement* init = NULL;
 
   Expect(Token::FOR, CHECK_OK);
@@ -2259,7 +2245,8 @@
         // error here but for compatibility with JSC we choose to report
         // the error at runtime.
         if (expression == NULL || !expression->IsValidLeftHandSide()) {
-          Handle<String> type = Factory::invalid_lhs_in_for_in_symbol();
+          Handle<String> type =
+              isolate()->factory()->invalid_lhs_in_for_in_symbol();
           expression = NewThrowReferenceError(type);
         }
         ForInStatement* loop = new ForInStatement(labels);
@@ -2344,11 +2331,12 @@
   // for compatibility with JSC we choose to report the error at
   // runtime.
   if (expression == NULL || !expression->IsValidLeftHandSide()) {
-    Handle<String> type = Factory::invalid_lhs_in_assignment_symbol();
+    Handle<String> type =
+        isolate()->factory()->invalid_lhs_in_assignment_symbol();
     expression = NewThrowReferenceError(type);
   }
 
-  if (temp_scope_->StrictMode()) {
+  if (top_scope_->is_strict_mode()) {
     // Assignment to eval or arguments is disallowed in strict mode.
     CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
   }
@@ -2367,7 +2355,7 @@
       property != NULL &&
       property->obj()->AsVariableProxy() != NULL &&
       property->obj()->AsVariableProxy()->is_this()) {
-    temp_scope_->AddProperty();
+    lexical_scope_->AddProperty();
   }
 
   // If we assign a function literal to a property we pretenure the
@@ -2567,7 +2555,7 @@
     }
 
     // "delete identifier" is a syntax error in strict mode.
-    if (op == Token::DELETE && temp_scope_->StrictMode()) {
+    if (op == Token::DELETE && top_scope_->is_strict_mode()) {
       VariableProxy* operand = expression->AsVariableProxy();
       if (operand != NULL && !operand->is_this()) {
         ReportMessage("strict_delete", Vector<const char*>::empty());
@@ -2586,11 +2574,12 @@
     // error here but for compatibility with JSC we choose to report the
     // error at runtime.
     if (expression == NULL || !expression->IsValidLeftHandSide()) {
-      Handle<String> type = Factory::invalid_lhs_in_prefix_op_symbol();
+      Handle<String> type =
+          isolate()->factory()->invalid_lhs_in_prefix_op_symbol();
       expression = NewThrowReferenceError(type);
     }
 
-    if (temp_scope_->StrictMode()) {
+    if (top_scope_->is_strict_mode()) {
       // Prefix expression operand in strict mode may not be eval or arguments.
       CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
     }
@@ -2617,11 +2606,12 @@
     // error here but for compatibility with JSC we choose to report the
     // error at runtime.
     if (expression == NULL || !expression->IsValidLeftHandSide()) {
-      Handle<String> type = Factory::invalid_lhs_in_postfix_op_symbol();
+      Handle<String> type =
+          isolate()->factory()->invalid_lhs_in_postfix_op_symbol();
       expression = NewThrowReferenceError(type);
     }
 
-    if (temp_scope_->StrictMode()) {
+    if (top_scope_->is_strict_mode()) {
       // Postfix expression operand in strict mode may not be eval or arguments.
       CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
     }
@@ -2674,7 +2664,8 @@
         // is called without a receiver and it refers to the original eval
         // function.
         VariableProxy* callee = result->AsVariableProxy();
-        if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) {
+        if (callee != NULL &&
+            callee->IsVariable(isolate()->factory()->eval_symbol())) {
           Handle<String> name = callee->name();
           Variable* var = top_scope_->Lookup(name);
           if (var == NULL) {
@@ -2829,7 +2820,7 @@
       return ReportMessage("unexpected_token_identifier",
                            Vector<const char*>::empty());
     case Token::FUTURE_RESERVED_WORD:
-      return ReportMessage(temp_scope_->StrictMode() ?
+      return ReportMessage(top_scope_->is_strict_mode() ?
                                "unexpected_strict_reserved" :
                                "unexpected_token_identifier",
                            Vector<const char*>::empty());
@@ -2875,17 +2866,17 @@
 
     case Token::NULL_LITERAL:
       Consume(Token::NULL_LITERAL);
-      result = new Literal(Factory::null_value());
+      result = new Literal(isolate()->factory()->null_value());
       break;
 
     case Token::TRUE_LITERAL:
       Consume(Token::TRUE_LITERAL);
-      result = new Literal(Factory::true_value());
+      result = new Literal(isolate()->factory()->true_value());
       break;
 
     case Token::FALSE_LITERAL:
       Consume(Token::FALSE_LITERAL);
-      result = new Literal(Factory::false_value());
+      result = new Literal(isolate()->factory()->false_value());
       break;
 
     case Token::IDENTIFIER:
@@ -3006,11 +2997,11 @@
   Expect(Token::RBRACK, CHECK_OK);
 
   // Update the scope information before the pre-parsing bailout.
-  int literal_index = temp_scope_->NextMaterializedLiteralIndex();
+  int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
 
   // Allocate a fixed array with all the literals.
   Handle<FixedArray> literals =
-      Factory::NewFixedArray(values->length(), TENURED);
+      isolate()->factory()->NewFixedArray(values->length(), TENURED);
 
   // Fill in the literals.
   bool is_simple = true;
@@ -3032,7 +3023,7 @@
   // Simple and shallow arrays can be lazily copied, we transform the
   // elements array to a copy-on-write array.
   if (is_simple && depth == 1 && values->length() > 0) {
-    literals->set_map(Heap::fixed_cow_array_map());
+    literals->set_map(isolate()->heap()->fixed_cow_array_map());
   }
 
   return new ArrayLiteral(literals, values,
@@ -3067,7 +3058,7 @@
 
 Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
   ASSERT(IsCompileTimeValue(expression));
-  Handle<FixedArray> result = Factory::NewFixedArray(2, TENURED);
+  Handle<FixedArray> result = FACTORY->NewFixedArray(2, TENURED);
   ObjectLiteral* object_literal = expression->AsObjectLiteral();
   if (object_literal != NULL) {
     ASSERT(object_literal->is_simple());
@@ -3105,7 +3096,7 @@
   if (CompileTimeValue::IsCompileTimeValue(expression)) {
     return CompileTimeValue::GetValue(expression);
   }
-  return Factory::undefined_value();
+  return isolate()->factory()->undefined_value();
 }
 
 // Defined in ast.cc
@@ -3171,7 +3162,7 @@
   if (handle->IsSymbol()) {
     Handle<String> name(String::cast(*handle));
     if (name->AsArrayIndex(&hash)) {
-      Handle<Object> key_handle = Factory::NewNumberFromUint(hash);
+      Handle<Object> key_handle = FACTORY->NewNumberFromUint(hash);
       key = key_handle.location();
       map = &elems;
     } else {
@@ -3188,7 +3179,7 @@
     char arr[100];
     Vector<char> buffer(arr, ARRAY_SIZE(arr));
     const char* str = DoubleToCString(num, buffer);
-    Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
+    Handle<String> name = FACTORY->NewStringFromAscii(CStrVector(str));
     key = name.location();
     hash = name->Hash();
     map = &props;
@@ -3300,7 +3291,7 @@
       next == Token::STRING || is_keyword) {
     Handle<String> name;
     if (is_keyword) {
-      name = Factory::LookupAsciiSymbol(Token::String(next));
+      name = isolate_->factory()->LookupAsciiSymbol(Token::String(next));
     } else {
       name = GetSymbol(CHECK_OK);
     }
@@ -3333,8 +3324,9 @@
   ZoneList<ObjectLiteral::Property*>* properties =
       new ZoneList<ObjectLiteral::Property*>(4);
   int number_of_boilerplate_properties = 0;
+  bool has_function = false;
 
-  ObjectLiteralPropertyChecker checker(this, temp_scope_->StrictMode());
+  ObjectLiteralPropertyChecker checker(this, top_scope_->is_strict_mode());
 
   Expect(Token::LBRACE, CHECK_OK);
   Scanner::Location loc = scanner().location();
@@ -3421,6 +3413,13 @@
     ObjectLiteral::Property* property =
         new ObjectLiteral::Property(key, value);
 
+    // Mark object literals that contain function literals and pretenure the
+    // literal so it can be added as a constant function property.
+    if (value->AsFunctionLiteral() != NULL) {
+      has_function = true;
+      value->AsFunctionLiteral()->set_pretenure(true);
+    }
+
     // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
     if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
     // Validate the property
@@ -3438,10 +3437,10 @@
   Expect(Token::RBRACE, CHECK_OK);
 
   // Computation of literal_index must happen before pre parse bailout.
-  int literal_index = temp_scope_->NextMaterializedLiteralIndex();
+  int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
 
-  Handle<FixedArray> constant_properties =
-      Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED);
+  Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray(
+      number_of_boilerplate_properties * 2, TENURED);
 
   bool is_simple = true;
   bool fast_elements = true;
@@ -3456,7 +3455,8 @@
                            literal_index,
                            is_simple,
                            fast_elements,
-                           depth);
+                           depth,
+                           has_function);
 }
 
 
@@ -3468,7 +3468,7 @@
     return NULL;
   }
 
-  int literal_index = temp_scope_->NextMaterializedLiteralIndex();
+  int literal_index = lexical_scope_->NextMaterializedLiteralIndex();
 
   Handle<String> js_pattern = NextLiteralString(TENURED);
   scanner().ScanRegExpFlags();
@@ -3510,9 +3510,10 @@
   // 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::empty_symbol();
+  Handle<String> name =
+      is_named ? var_name : isolate()->factory()->empty_symbol();
   // The function name, if any.
-  Handle<String> function_name = Factory::empty_symbol();
+  Handle<String> function_name = isolate()->factory()->empty_symbol();
   if (is_named && (type == EXPRESSION || type == NESTED)) {
     function_name = name;
   }
@@ -3521,9 +3522,7 @@
   // Parse function body.
   { Scope* scope =
         NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
-    LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
-                               scope);
-    TemporaryScope temp_scope(&this->temp_scope_);
+    LexicalScope lexical_scope(this, scope, isolate());
     top_scope_->SetScopeName(name);
 
     //  FormalParameterList ::
@@ -3609,29 +3608,30 @@
         // End position greater than end of stream is safe, and hard to check.
         ReportInvalidPreparseData(name, CHECK_OK);
       }
-      Counters::total_preparse_skipped.Increment(end_pos - function_block_pos);
+      isolate()->counters()->total_preparse_skipped()->Increment(
+          end_pos - function_block_pos);
       // Seek to position just before terminal '}'.
       scanner().SeekForward(end_pos - 1);
       materialized_literal_count = entry.literal_count();
       expected_property_count = entry.property_count();
       only_simple_this_property_assignments = false;
-      this_property_assignments = Factory::empty_fixed_array();
+      this_property_assignments = isolate()->factory()->empty_fixed_array();
       Expect(Token::RBRACE, CHECK_OK);
     } else {
       ParseSourceElements(body, Token::RBRACE, CHECK_OK);
 
-      materialized_literal_count = temp_scope.materialized_literal_count();
-      expected_property_count = temp_scope.expected_property_count();
+      materialized_literal_count = lexical_scope.materialized_literal_count();
+      expected_property_count = lexical_scope.expected_property_count();
       only_simple_this_property_assignments =
-          temp_scope.only_simple_this_property_assignments();
-      this_property_assignments = temp_scope.this_property_assignments();
+          lexical_scope.only_simple_this_property_assignments();
+      this_property_assignments = lexical_scope.this_property_assignments();
 
       Expect(Token::RBRACE, CHECK_OK);
       end_pos = scanner().location().end_pos;
     }
 
     // Validate strict mode.
-    if (temp_scope_->StrictMode()) {
+    if (top_scope_->is_strict_mode()) {
       if (IsEvalOrArguments(name)) {
         int position = function_token_position != RelocInfo::kNoPosition
             ? function_token_position
@@ -3685,8 +3685,7 @@
                             start_pos,
                             end_pos,
                             function_name->length() > 0,
-                            temp_scope.ContainsLoops(),
-                            temp_scope.StrictMode());
+                            lexical_scope.ContainsLoops());
     function_literal->set_function_token_position(function_token_position);
 
     if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal);
@@ -3709,7 +3708,7 @@
     top_scope_->ForceEagerCompilation();
   }
 
-  Runtime::Function* function = Runtime::FunctionForSymbol(name);
+  const Runtime::Function* function = Runtime::FunctionForSymbol(name);
 
   // Check for built-in IS_VAR macro.
   if (function != NULL &&
@@ -3792,12 +3791,12 @@
 
 
 Literal* Parser::GetLiteralUndefined() {
-  return new Literal(Factory::undefined_value());
+  return new Literal(isolate()->factory()->undefined_value());
 }
 
 
 Literal* Parser::GetLiteralTheHole() {
-  return new Literal(Factory::the_hole_value());
+  return new Literal(isolate()->factory()->the_hole_value());
 }
 
 
@@ -3815,7 +3814,7 @@
 Handle<String> Parser::ParseIdentifierOrReservedWord(bool* is_reserved,
                                                      bool* ok) {
   *is_reserved = false;
-  if (temp_scope_->StrictMode()) {
+  if (top_scope_->is_strict_mode()) {
     Expect(Token::IDENTIFIER, ok);
   } else {
     if (!Check(Token::IDENTIFIER)) {
@@ -3846,7 +3845,7 @@
 void Parser::CheckStrictModeLValue(Expression* expression,
                                    const char* error,
                                    bool* ok) {
-  ASSERT(temp_scope_->StrictMode());
+  ASSERT(top_scope_->is_strict_mode());
   VariableProxy* lhs = expression != NULL
       ? expression->AsVariableProxy()
       : NULL;
@@ -3945,12 +3944,12 @@
 
 
 Literal* Parser::NewNumberLiteral(double number) {
-  return new Literal(Factory::NewNumber(number, TENURED));
+  return new Literal(isolate()->factory()->NewNumber(number, TENURED));
 }
 
 
 Expression* Parser::NewThrowReferenceError(Handle<String> type) {
-  return NewThrowError(Factory::MakeReferenceError_symbol(),
+  return NewThrowError(isolate()->factory()->MakeReferenceError_symbol(),
                        type, HandleVector<Object>(NULL, 0));
 }
 
@@ -3959,7 +3958,8 @@
                                         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);
+  return NewThrowError(
+      isolate()->factory()->MakeSyntaxError_symbol(), type, arguments);
 }
 
 
@@ -3970,7 +3970,8 @@
   Handle<Object> elements[] = { first, second };
   Vector< Handle<Object> > arguments =
       HandleVector<Object>(elements, ARRAY_SIZE(elements));
-  return NewThrowError(Factory::MakeTypeError_symbol(), type, arguments);
+  return NewThrowError(
+      isolate()->factory()->MakeTypeError_symbol(), type, arguments);
 }
 
 
@@ -3978,14 +3979,16 @@
                                   Handle<String> type,
                                   Vector< Handle<Object> > arguments) {
   int argc = arguments.length();
-  Handle<FixedArray> elements = Factory::NewFixedArray(argc, TENURED);
+  Handle<FixedArray> elements = isolate()->factory()->NewFixedArray(argc,
+                                                                    TENURED);
   for (int i = 0; i < argc; i++) {
     Handle<Object> element = arguments[i];
     if (!element.is_null()) {
       elements->set(i, *element);
     }
   }
-  Handle<JSArray> array = Factory::NewJSArrayWithElements(elements, TENURED);
+  Handle<JSArray> array = isolate()->factory()->NewJSArrayWithElements(elements,
+                                                                       TENURED);
 
   ZoneList<Expression*>* args = new ZoneList<Expression*>(2);
   args->Add(new Literal(type));
@@ -4005,7 +4008,7 @@
   if (result.is_null() || scanner_.Next() != Token::EOS) {
     if (stack_overflow_) {
       // Scanner failed.
-      Top::StackOverflow();
+      isolate()->StackOverflow();
     } else {
       // Parse failed. Scanner's current token is the unexpected token.
       Token::Value token = scanner_.current_token();
@@ -4035,20 +4038,21 @@
       }
 
       Scanner::Location source_location = scanner_.location();
-      MessageLocation location(Factory::NewScript(script),
+      Factory* factory = isolate()->factory();
+      MessageLocation location(factory->NewScript(script),
                                source_location.beg_pos,
                                source_location.end_pos);
       Handle<JSArray> array;
       if (name_opt == NULL) {
-        array = Factory::NewJSArray(0);
+        array = factory->NewJSArray(0);
       } else {
-        Handle<String> name = Factory::NewStringFromUtf8(CStrVector(name_opt));
-        Handle<FixedArray> element = Factory::NewFixedArray(1);
+        Handle<String> name = factory->NewStringFromUtf8(CStrVector(name_opt));
+        Handle<FixedArray> element = factory->NewFixedArray(1);
         element->set(0, *name);
-        array = Factory::NewJSArrayWithElements(element);
+        array = factory->NewJSArrayWithElements(element);
       }
-      Handle<Object> result = Factory::NewSyntaxError(message, array);
-      Top::Throw(*result, &location);
+      Handle<Object> result = factory->NewSyntaxError(message, array);
+      isolate()->Throw(*result, &location);
       return Handle<Object>::null();
     }
   }
@@ -4059,12 +4063,14 @@
 Handle<String> JsonParser::GetString() {
   int literal_length = scanner_.literal_length();
   if (literal_length == 0) {
-    return Factory::empty_string();
+    return isolate()->factory()->empty_string();
   }
   if (scanner_.is_literal_ascii()) {
-    return Factory::NewStringFromAscii(scanner_.literal_ascii_string());
+    return isolate()->factory()->NewStringFromAscii(
+        scanner_.literal_ascii_string());
   } else {
-    return Factory::NewStringFromTwoByte(scanner_.literal_uc16_string());
+    return isolate()->factory()->NewStringFromTwoByte(
+        scanner_.literal_uc16_string());
   }
 }
 
@@ -4076,13 +4082,13 @@
     case Token::STRING:
       return GetString();
     case Token::NUMBER:
-      return Factory::NewNumber(scanner_.number());
+      return isolate()->factory()->NewNumber(scanner_.number());
     case Token::FALSE_LITERAL:
-      return Factory::false_value();
+      return isolate()->factory()->false_value();
     case Token::TRUE_LITERAL:
-      return Factory::true_value();
+      return isolate()->factory()->true_value();
     case Token::NULL_LITERAL:
-      return Factory::null_value();
+      return isolate()->factory()->null_value();
     case Token::LBRACE:
       return ParseJsonObject();
     case Token::LBRACK:
@@ -4096,12 +4102,13 @@
 // Parse a JSON object. Scanner must be right after '{' token.
 Handle<Object> JsonParser::ParseJsonObject() {
   Handle<JSFunction> object_constructor(
-      Top::global_context()->object_function());
-  Handle<JSObject> json_object = Factory::NewJSObject(object_constructor);
+      isolate()->global_context()->object_function());
+  Handle<JSObject> json_object =
+      isolate()->factory()->NewJSObject(object_constructor);
   if (scanner_.peek() == Token::RBRACE) {
     scanner_.Next();
   } else {
-    if (StackLimitCheck().HasOverflowed()) {
+    if (StackLimitCheck(isolate()).HasOverflowed()) {
       stack_overflow_ = true;
       return Handle<Object>::null();
     }
@@ -4118,7 +4125,7 @@
       uint32_t index;
       if (key->AsArrayIndex(&index)) {
         SetOwnElement(json_object, index, value, kNonStrictMode);
-      } else if (key->Equals(Heap::Proto_symbol())) {
+      } else if (key->Equals(isolate()->heap()->Proto_symbol())) {
         // We can't remove the __proto__ accessor since it's hardcoded
         // in several places. Instead go along and add the value as
         // the prototype of the created object if possible.
@@ -4144,7 +4151,7 @@
   if (token == Token::RBRACK) {
     scanner_.Next();
   } else {
-    if (StackLimitCheck().HasOverflowed()) {
+    if (StackLimitCheck(isolate()).HasOverflowed()) {
       stack_overflow_ = true;
       return Handle<Object>::null();
     }
@@ -4161,13 +4168,13 @@
 
   // Allocate a fixed array with all the elements.
   Handle<FixedArray> fast_elements =
-      Factory::NewFixedArray(elements.length());
+      isolate()->factory()->NewFixedArray(elements.length());
 
   for (int i = 0, n = elements.length(); i < n; i++) {
     fast_elements->set(i, *elements[i]);
   }
 
-  return Factory::NewJSArrayWithElements(fast_elements);
+  return isolate()->factory()->NewJSArrayWithElements(fast_elements);
 }
 
 // ----------------------------------------------------------------------------
@@ -4177,18 +4184,19 @@
 RegExpParser::RegExpParser(FlatStringReader* in,
                            Handle<String>* error,
                            bool multiline)
-  : error_(error),
-    captures_(NULL),
-    in_(in),
-    current_(kEndMarker),
-    next_pos_(0),
-    capture_count_(0),
-    has_more_(true),
-    multiline_(multiline),
-    simple_(false),
-    contains_anchor_(false),
-    is_scanned_for_captures_(false),
-    failed_(false) {
+    : isolate_(Isolate::Current()),
+      error_(error),
+      captures_(NULL),
+      in_(in),
+      current_(kEndMarker),
+      next_pos_(0),
+      capture_count_(0),
+      has_more_(true),
+      multiline_(multiline),
+      simple_(false),
+      contains_anchor_(false),
+      is_scanned_for_captures_(false),
+      failed_(false) {
   Advance();
 }
 
@@ -4204,10 +4212,10 @@
 
 void RegExpParser::Advance() {
   if (next_pos_ < in()->length()) {
-    StackLimitCheck check;
+    StackLimitCheck check(isolate());
     if (check.HasOverflowed()) {
-      ReportError(CStrVector(Top::kStackOverflowMessage));
-    } else if (Zone::excess_allocation()) {
+      ReportError(CStrVector(Isolate::kStackOverflowMessage));
+    } else if (isolate()->zone()->excess_allocation()) {
       ReportError(CStrVector("Regular expression too large"));
     } else {
       current_ = in()->Get(next_pos_);
@@ -4238,7 +4246,7 @@
 
 RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
   failed_ = true;
-  *error_ = Factory::NewStringFromAscii(message, NOT_TENURED);
+  *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
   // Zip to the end to make sure the no more input is read.
   current_ = kEndMarker;
   next_pos_ = in()->length();
@@ -4592,30 +4600,6 @@
   }
 }
 
-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.
@@ -5068,14 +5052,15 @@
 static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
                                   bool allow_lazy,
                                   ParserRecorder* recorder) {
-  V8JavaScriptScanner scanner;
+  Isolate* isolate = Isolate::Current();
+  V8JavaScriptScanner scanner(isolate->scanner_constants());
   scanner.Initialize(source);
-  intptr_t stack_limit = StackGuard::real_climit();
+  intptr_t stack_limit = isolate->stack_guard()->real_climit();
   if (!preparser::PreParser::PreParseProgram(&scanner,
                                              recorder,
                                              allow_lazy,
                                              stack_limit)) {
-    Top::StackOverflow();
+    isolate->StackOverflow();
     return NULL;
   }
 
@@ -5138,10 +5123,10 @@
   Handle<Script> script = info->script();
   if (info->is_lazy()) {
     Parser parser(script, true, NULL, NULL);
-    result = parser.ParseLazy(info->shared_info());
+    result = parser.ParseLazy(info);
   } else {
     bool allow_natives_syntax =
-        FLAG_allow_natives_syntax || Bootstrapper::IsActive();
+        info->allows_natives_syntax() || FLAG_allow_natives_syntax;
     ScriptDataImpl* pre_data = info->pre_parse_data();
     Parser parser(script, allow_natives_syntax, info->extension(), pre_data);
     if (pre_data != NULL && pre_data->has_error()) {
@@ -5154,7 +5139,7 @@
         DeleteArray(args[i]);
       }
       DeleteArray(args.start());
-      ASSERT(Top::has_pending_exception());
+      ASSERT(info->isolate()->has_pending_exception());
     } else {
       Handle<String> source = Handle<String>(String::cast(script->source()));
       result = parser.ParseProgram(source,
diff --git a/src/parser.h b/src/parser.h
index dfd909a..74cb049 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -42,7 +42,7 @@
 class ParserLog;
 class PositionStack;
 class Target;
-class TemporaryScope;
+class LexicalScope;
 
 template <typename T> class ZoneListWrapper;
 
@@ -388,6 +388,8 @@
     int disjunction_capture_index_;
   };
 
+  Isolate* isolate() { return isolate_; }
+
   uc32 current() { return current_; }
   bool has_more() { return has_more_; }
   bool has_next() { return next_pos_ < in()->length(); }
@@ -395,6 +397,7 @@
   FlatStringReader* in() { return in_; }
   void ScanForCaptures();
 
+  Isolate* isolate_;
   Handle<String>* error_;
   ZoneList<RegExpCapture*>* captures_;
   FlatStringReader* in_;
@@ -426,7 +429,7 @@
                                 bool in_global_context,
                                 StrictModeFlag strict_mode);
 
-  FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info);
+  FunctionLiteral* ParseLazy(CompilationInfo* info);
 
   void ReportMessageAt(Scanner::Location loc,
                        const char* message,
@@ -441,7 +444,7 @@
   // construct a hashable id, so if more than 2^17 are allowed, this
   // should be checked.
   static const int kMaxNumFunctionParameters = 32766;
-  FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info,
+  FunctionLiteral* ParseLazy(CompilationInfo* info,
                              UC16CharacterStream* source,
                              ZoneScope* zone_scope);
   enum Mode {
@@ -449,6 +452,8 @@
     PARSE_EAGERLY
   };
 
+  Isolate* isolate() { return isolate_; }
+
   // Called by ParseProgram after setting up the scanner.
   FunctionLiteral* DoParseProgram(Handle<String> source,
                                   bool in_global_context,
@@ -465,6 +470,9 @@
   Mode mode() const { return mode_; }
   ScriptDataImpl* pre_data() const { return pre_data_; }
 
+  // Check if the given string is 'eval' or 'arguments'.
+  bool IsEvalOrArguments(Handle<String> string);
+
   // 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
@@ -574,7 +582,7 @@
     if (stack_overflow_) {
       return Token::ILLEGAL;
     }
-    if (StackLimitCheck().HasOverflowed()) {
+    if (StackLimitCheck(isolate()).HasOverflowed()) {
       // Any further calls to Next or peek will return the illegal token.
       // The current call must return the next token, which might already
       // have been peek'ed.
@@ -592,21 +600,21 @@
 
   Handle<String> LiteralString(PretenureFlag tenured) {
     if (scanner().is_literal_ascii()) {
-      return Factory::NewStringFromAscii(scanner().literal_ascii_string(),
-                                         tenured);
+      return isolate_->factory()->NewStringFromAscii(
+          scanner().literal_ascii_string(), tenured);
     } else {
-      return Factory::NewStringFromTwoByte(scanner().literal_uc16_string(),
-                                           tenured);
+      return isolate_->factory()->NewStringFromTwoByte(
+            scanner().literal_uc16_string(), tenured);
     }
   }
 
   Handle<String> NextLiteralString(PretenureFlag tenured) {
     if (scanner().is_next_literal_ascii()) {
-      return Factory::NewStringFromAscii(scanner().next_literal_ascii_string(),
-                                         tenured);
+      return isolate_->factory()->NewStringFromAscii(
+          scanner().next_literal_ascii_string(), tenured);
     } else {
-      return Factory::NewStringFromTwoByte(scanner().next_literal_uc16_string(),
-                                           tenured);
+      return isolate_->factory()->NewStringFromTwoByte(
+          scanner().next_literal_uc16_string(), tenured);
     }
   }
 
@@ -686,6 +694,7 @@
                             Handle<String> type,
                             Vector< Handle<Object> > arguments);
 
+  Isolate* isolate_;
   ZoneList<Handle<String> > symbol_cache_;
 
   Handle<Script> script_;
@@ -694,7 +703,7 @@
   Scope* top_scope_;
   int with_nesting_level_;
 
-  TemporaryScope* temp_scope_;
+  LexicalScope* lexical_scope_;
   Mode mode_;
 
   Target* target_stack_;  // for break, continue statements
@@ -709,6 +718,8 @@
   // Heuristically that means that the function will be called immediately,
   // so never lazily compile it.
   bool parenthesized_function_;
+
+  friend class LexicalScope;
 };
 
 
@@ -765,9 +776,13 @@
   }
 
  private:
-  JsonParser() { }
+  JsonParser()
+      : isolate_(Isolate::Current()),
+        scanner_(isolate_->scanner_constants()) { }
   ~JsonParser() { }
 
+  Isolate* isolate() { return isolate_; }
+
   // Parse a string containing a single JSON value.
   Handle<Object> ParseJson(Handle<String> script, UC16CharacterStream* source);
   // Parse a single JSON value from input (grammar production JSONValue).
@@ -794,6 +809,7 @@
   // Converts the currently parsed literal to a JavaScript String.
   Handle<String> GetString();
 
+  Isolate* isolate_;
   JsonScanner scanner_;
   bool stack_overflow_;
 };
diff --git a/src/platform-cygwin.cc b/src/platform-cygwin.cc
index a7cc525..4b450c1 100644
--- a/src/platform-cygwin.cc
+++ b/src/platform-cygwin.cc
@@ -143,7 +143,7 @@
   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"));
+    LOG(ISOLATE, StringEvent("OS::Allocate", "mmap failed"));
     return NULL;
   }
   *allocated = msize;
@@ -400,12 +400,18 @@
 }
 
 
-Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
-  set_name("v8:<unknown>");
+Thread::Thread(Isolate* isolate, const Options& options)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(options.stack_size) {
+  set_name(options.name);
 }
 
 
-Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+Thread::Thread(Isolate* isolate, const char* name)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(0) {
   set_name(name);
 }
 
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index 21763b5..2a73b6e 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -42,6 +42,7 @@
 #include <sys/stat.h>   // open
 #include <sys/fcntl.h>  // open
 #include <unistd.h>     // getpagesize
+// If you don't have execinfo.h then you need devel/libexecinfo from ports.
 #include <execinfo.h>   // backtrace, backtrace_symbols
 #include <strings.h>    // index
 #include <errno.h>
@@ -74,6 +75,9 @@
 }
 
 
+static Mutex* limit_mutex = NULL;
+
+
 void OS::Setup() {
   // Seed the random number generator.
   // Convert the current time to a 64-bit integer first, before converting it
@@ -82,6 +86,7 @@
   // call this setup code within the same millisecond.
   uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
   srandom(static_cast<unsigned int>(seed));
+  limit_mutex = CreateMutex();
 }
 
 
@@ -130,6 +135,9 @@
 
 
 static void UpdateAllocatedSpaceLimits(void* address, int size) {
+  ASSERT(limit_mutex != NULL);
+  ScopedLock lock(limit_mutex);
+
   lowest_ever_allocated = Min(lowest_ever_allocated, address);
   highest_ever_allocated =
       Max(highest_ever_allocated,
@@ -155,7 +163,7 @@
   void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
 
   if (mbase == MAP_FAILED) {
-    LOG(StringEvent("OS::Allocate", "mmap failed"));
+    LOG(ISOLATE, StringEvent("OS::Allocate", "mmap failed"));
     return NULL;
   }
   *allocated = msize;
@@ -299,7 +307,7 @@
     // 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));
+    LOG(i::Isolate::Current(), SharedLibraryEvent(start_of_path, start, end));
   }
   close(fd);
 #endif
@@ -424,12 +432,18 @@
 }
 
 
-Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
-  set_name("v8:<unknown>");
+Thread::Thread(Isolate* isolate, const Options& options)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(options.stack_size) {
+  set_name(options.name);
 }
 
 
-Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+Thread::Thread(Isolate* isolate, const char* name)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(0) {
   set_name(name);
 }
 
@@ -445,6 +459,7 @@
   // one) so we initialize it here too.
   thread->thread_handle_data()->thread_ = pthread_self();
   ASSERT(thread->IsValid());
+  Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
   thread->Run();
   return NULL;
 }
@@ -457,7 +472,14 @@
 
 
 void Thread::Start() {
-  pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
+  pthread_attr_t* attr_ptr = NULL;
+  pthread_attr_t attr;
+  if (stack_size_ > 0) {
+    pthread_attr_init(&attr);
+    pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
+    attr_ptr = &attr;
+  }
+  pthread_create(&thread_handle_data()->thread_, attr_ptr, ThreadEntry, this);
   ASSERT(IsValid());
 }
 
@@ -526,6 +548,16 @@
     return result;
   }
 
+  virtual bool TryLock() {
+    int result = pthread_mutex_trylock(&mutex_);
+    // Return false if the lock is busy and locking failed.
+    if (result == EBUSY) {
+      return false;
+    }
+    ASSERT(result == 0);  // Verify no other errors.
+    return true;
+  }
+
  private:
   pthread_mutex_t mutex_;   // Pthread mutex for POSIX platforms.
 };
@@ -594,107 +626,227 @@
 
 #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;
-
-  // We always sample the VM state.
-  sample.state = VMState::current_state();
-
-  // 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 V8_HOST_ARCH_IA32
-    sample.pc = reinterpret_cast<Address>(mcontext.mc_eip);
-    sample.sp = reinterpret_cast<Address>(mcontext.mc_esp);
-    sample.fp = reinterpret_cast<Address>(mcontext.mc_ebp);
-#elif V8_HOST_ARCH_X64
-    sample.pc = reinterpret_cast<Address>(mcontext.mc_rip);
-    sample.sp = reinterpret_cast<Address>(mcontext.mc_rsp);
-    sample.fp = reinterpret_cast<Address>(mcontext.mc_rbp);
-#elif V8_HOST_ARCH_ARM
-    sample.pc = reinterpret_cast<Address>(mcontext.mc_r15);
-    sample.sp = reinterpret_cast<Address>(mcontext.mc_r13);
-    sample.fp = reinterpret_cast<Address>(mcontext.mc_r11);
-#endif
-    active_sampler_->SampleStack(&sample);
-  }
-
-  active_sampler_->Tick(&sample);
+static pthread_t GetThreadID() {
+  pthread_t thread_id = pthread_self();
+  return thread_id;
 }
 
 
 class Sampler::PlatformData : public Malloced {
  public:
-  PlatformData() {
-    signal_handler_installed_ = false;
-  }
+  PlatformData() : vm_tid_(GetThreadID()) {}
 
-  bool signal_handler_installed_;
-  struct sigaction old_signal_handler_;
-  struct itimerval old_timer_value_;
+  pthread_t vm_tid() const { return vm_tid_; }
+
+ private:
+  pthread_t vm_tid_;
 };
 
 
-Sampler::Sampler(int interval)
-    : interval_(interval),
+static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
+  USE(info);
+  if (signal != SIGPROF) return;
+  Isolate* isolate = Isolate::UncheckedCurrent();
+  if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
+    // We require a fully initialized and entered isolate.
+    return;
+  }
+  Sampler* sampler = isolate->logger()->sampler();
+  if (sampler == NULL || !sampler->IsActive()) return;
+
+  TickSample sample_obj;
+  TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
+  if (sample == NULL) sample = &sample_obj;
+
+  // Extracting the sample from the context is extremely machine dependent.
+  ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
+  mcontext_t& mcontext = ucontext->uc_mcontext;
+  sample->state = isolate->current_vm_state();
+#if V8_HOST_ARCH_IA32
+  sample->pc = reinterpret_cast<Address>(mcontext.mc_eip);
+  sample->sp = reinterpret_cast<Address>(mcontext.mc_esp);
+  sample->fp = reinterpret_cast<Address>(mcontext.mc_ebp);
+#elif V8_HOST_ARCH_X64
+  sample->pc = reinterpret_cast<Address>(mcontext.mc_rip);
+  sample->sp = reinterpret_cast<Address>(mcontext.mc_rsp);
+  sample->fp = reinterpret_cast<Address>(mcontext.mc_rbp);
+#elif V8_HOST_ARCH_ARM
+  sample->pc = reinterpret_cast<Address>(mcontext.mc_r15);
+  sample->sp = reinterpret_cast<Address>(mcontext.mc_r13);
+  sample->fp = reinterpret_cast<Address>(mcontext.mc_r11);
+#endif
+  sampler->SampleStack(sample);
+  sampler->Tick(sample);
+}
+
+
+class SignalSender : public Thread {
+ public:
+  enum SleepInterval {
+    HALF_INTERVAL,
+    FULL_INTERVAL
+  };
+
+  explicit SignalSender(int interval)
+      : Thread(NULL, "SignalSender"),
+        interval_(interval) {}
+
+  static void AddActiveSampler(Sampler* sampler) {
+    ScopedLock lock(mutex_);
+    SamplerRegistry::AddActiveSampler(sampler);
+    if (instance_ == NULL) {
+      // Install a signal handler.
+      struct sigaction sa;
+      sa.sa_sigaction = ProfilerSignalHandler;
+      sigemptyset(&sa.sa_mask);
+      sa.sa_flags = SA_RESTART | SA_SIGINFO;
+      signal_handler_installed_ =
+          (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
+
+      // Start a thread that sends SIGPROF signal to VM threads.
+      instance_ = new SignalSender(sampler->interval());
+      instance_->Start();
+    } else {
+      ASSERT(instance_->interval_ == sampler->interval());
+    }
+  }
+
+  static void RemoveActiveSampler(Sampler* sampler) {
+    ScopedLock lock(mutex_);
+    SamplerRegistry::RemoveActiveSampler(sampler);
+    if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
+      RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
+      instance_->Join();
+      delete instance_;
+      instance_ = NULL;
+
+      // Restore the old signal handler.
+      if (signal_handler_installed_) {
+        sigaction(SIGPROF, &old_signal_handler_, 0);
+        signal_handler_installed_ = false;
+      }
+    }
+  }
+
+  // Implement Thread::Run().
+  virtual void Run() {
+    SamplerRegistry::State state;
+    while ((state = SamplerRegistry::GetState()) !=
+           SamplerRegistry::HAS_NO_SAMPLERS) {
+      bool cpu_profiling_enabled =
+          (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
+      bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
+      // When CPU profiling is enabled both JavaScript and C++ code is
+      // profiled. We must not suspend.
+      if (!cpu_profiling_enabled) {
+        if (rate_limiter_.SuspendIfNecessary()) continue;
+      }
+      if (cpu_profiling_enabled && runtime_profiler_enabled) {
+        if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
+          return;
+        }
+        Sleep(HALF_INTERVAL);
+        if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
+          return;
+        }
+        Sleep(HALF_INTERVAL);
+      } else {
+        if (cpu_profiling_enabled) {
+          if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile,
+                                                      this)) {
+            return;
+          }
+        }
+        if (runtime_profiler_enabled) {
+          if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile,
+                                                      NULL)) {
+            return;
+          }
+        }
+        Sleep(FULL_INTERVAL);
+      }
+    }
+  }
+
+  static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
+    if (!sampler->IsProfiling()) return;
+    SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender);
+    sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
+  }
+
+  static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
+    if (!sampler->isolate()->IsInitialized()) return;
+    sampler->isolate()->runtime_profiler()->NotifyTick();
+  }
+
+  void SendProfilingSignal(pthread_t tid) {
+    if (!signal_handler_installed_) return;
+    pthread_kill(tid, SIGPROF);
+  }
+
+  void Sleep(SleepInterval full_or_half) {
+    // Convert ms to us and subtract 100 us to compensate delays
+    // occuring during signal delivery.
+    useconds_t interval = interval_ * 1000 - 100;
+    if (full_or_half == HALF_INTERVAL) interval /= 2;
+    int result = usleep(interval);
+#ifdef DEBUG
+    if (result != 0 && errno != EINTR) {
+      fprintf(stderr,
+              "SignalSender usleep error; interval = %u, errno = %d\n",
+              interval,
+              errno);
+      ASSERT(result == 0 || errno == EINTR);
+    }
+#endif
+    USE(result);
+  }
+
+  const int interval_;
+  RuntimeProfilerRateLimiter rate_limiter_;
+
+  // Protects the process wide state below.
+  static Mutex* mutex_;
+  static SignalSender* instance_;
+  static bool signal_handler_installed_;
+  static struct sigaction old_signal_handler_;
+
+  DISALLOW_COPY_AND_ASSIGN(SignalSender);
+};
+
+Mutex* SignalSender::mutex_ = OS::CreateMutex();
+SignalSender* SignalSender::instance_ = NULL;
+struct sigaction SignalSender::old_signal_handler_;
+bool SignalSender::signal_handler_installed_ = false;
+
+
+Sampler::Sampler(Isolate* isolate, int interval)
+    : isolate_(isolate),
+      interval_(interval),
       profiling_(false),
       active_(false),
       samples_taken_(0) {
-  data_ = new PlatformData();
+  data_ = new PlatformData;
 }
 
 
 Sampler::~Sampler() {
+  ASSERT(!IsActive());
   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;
+  ASSERT(!IsActive());
+  SetActive(true);
+  SignalSender::AddActiveSampler(this);
 }
 
 
 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;
+  ASSERT(IsActive());
+  SignalSender::RemoveActiveSampler(this);
+  SetActive(false);
 }
 
 #endif  // ENABLE_LOGGING_AND_PROFILING
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index 16aa7c8..73a6ccb 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -58,7 +58,6 @@
 #include "v8.h"
 
 #include "platform.h"
-#include "top.h"
 #include "v8threads.h"
 #include "vm-state-inl.h"
 
@@ -76,6 +75,9 @@
 }
 
 
+static Mutex* limit_mutex = NULL;
+
+
 void OS::Setup() {
   // Seed the random number generator.
   // Convert the current time to a 64-bit integer first, before converting it
@@ -84,6 +86,7 @@
   // call this setup code within the same millisecond.
   uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
   srandom(static_cast<unsigned int>(seed));
+  limit_mutex = CreateMutex();
 }
 
 
@@ -94,6 +97,10 @@
   return 1u << VFP3;
 #elif CAN_USE_ARMV7_INSTRUCTIONS
   return 1u << ARMv7;
+#elif(defined(__mips_hard_float) && __mips_hard_float != 0)
+    // Here gcc is telling us that we are on an MIPS and gcc is assuming that we
+    // have FPU instructions.  If gcc can assume it then so can we.
+    return 1u << FPU;
 #else
   return 0;  // Linux runs on anything.
 #endif
@@ -172,6 +179,58 @@
 #endif  // def __arm__
 
 
+#ifdef __mips__
+bool OS::MipsCpuHasFeature(CpuFeature feature) {
+  const char* search_string = NULL;
+  const char* file_name = "/proc/cpuinfo";
+  // Simple detection of FPU at runtime for Linux.
+  // It is based on /proc/cpuinfo, which reveals hardware configuration
+  // to user-space applications.  According to MIPS (early 2010), no similar
+  // facility is universally available on the MIPS architectures,
+  // so it's up to individual OSes to provide such.
+  //
+  // This is written as a straight shot one pass parser
+  // and not using STL string and ifstream because,
+  // on Linux, it's reading from a (non-mmap-able)
+  // character special device.
+
+  switch (feature) {
+    case FPU:
+      search_string = "FPU";
+      break;
+    default:
+      UNREACHABLE();
+  }
+
+  FILE* f = NULL;
+  const char* what = search_string;
+
+  if (NULL == (f = fopen(file_name, "r")))
+    return false;
+
+  int k;
+  while (EOF != (k = fgetc(f))) {
+    if (k == *what) {
+      ++what;
+      while ((*what != '\0') && (*what == fgetc(f))) {
+        ++what;
+      }
+      if (*what == '\0') {
+        fclose(f);
+        return true;
+      } else {
+        what = search_string;
+      }
+    }
+  }
+  fclose(f);
+
+  // Did not find string in the proc file.
+  return false;
+}
+#endif  // def __mips__
+
+
 int OS::ActivationFrameAlignment() {
 #ifdef V8_TARGET_ARCH_ARM
   // On EABI ARM targets this is required for fp correctness in the
@@ -187,8 +246,9 @@
 
 
 void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
-#if defined(V8_TARGET_ARCH_ARM) && defined(__arm__)
-  // Only use on ARM hardware.
+#if (defined(V8_TARGET_ARCH_ARM) && defined(__arm__)) || \
+    (defined(V8_TARGET_ARCH_MIPS) && defined(__mips__))
+  // Only use on ARM or MIPS hardware.
   MemoryBarrier();
 #else
   __asm__ __volatile__("" : : : "memory");
@@ -226,6 +286,9 @@
 
 
 static void UpdateAllocatedSpaceLimits(void* address, int size) {
+  ASSERT(limit_mutex != NULL);
+  ScopedLock lock(limit_mutex);
+
   lowest_ever_allocated = Min(lowest_ever_allocated, address);
   highest_ever_allocated =
       Max(highest_ever_allocated,
@@ -251,7 +314,8 @@
   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"));
+    LOG(i::Isolate::Current(),
+        StringEvent("OS::Allocate", "mmap failed"));
     return NULL;
   }
   *allocated = msize;
@@ -372,6 +436,7 @@
   const int kLibNameLen = FILENAME_MAX + 1;
   char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
 
+  i::Isolate* isolate = ISOLATE;
   // This loop will terminate once the scanning hits an EOF.
   while (true) {
     uintptr_t start, end;
@@ -405,7 +470,7 @@
         snprintf(lib_name, kLibNameLen,
                  "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end);
       }
-      LOG(SharedLibraryEvent(lib_name, start, end));
+      LOG(isolate, SharedLibraryEvent(lib_name, start, end));
     } else {
       // Entry not describing executable data. Skip to end of line to setup
       // reading the next entry.
@@ -565,12 +630,18 @@
 }
 
 
-Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
-  set_name("v8:<unknown>");
+Thread::Thread(Isolate* isolate, const Options& options)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(options.stack_size) {
+  set_name(options.name);
 }
 
 
-Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+Thread::Thread(Isolate* isolate, const char* name)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(0) {
   set_name(name);
 }
 
@@ -589,6 +660,7 @@
         0, 0, 0);
   thread->thread_handle_data()->thread_ = pthread_self();
   ASSERT(thread->IsValid());
+  Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
   thread->Run();
   return NULL;
 }
@@ -601,7 +673,14 @@
 
 
 void Thread::Start() {
-  pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
+  pthread_attr_t* attr_ptr = NULL;
+  pthread_attr_t attr;
+  if (stack_size_ > 0) {
+    pthread_attr_init(&attr);
+    pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
+    attr_ptr = &attr;
+  }
+  pthread_create(&thread_handle_data()->thread_, attr_ptr, ThreadEntry, this);
   ASSERT(IsValid());
 }
 
@@ -762,10 +841,6 @@
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
 
-static Sampler* active_sampler_ = NULL;
-static int vm_tid_ = 0;
-
-
 #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.
@@ -794,7 +869,11 @@
 
 static int GetThreadID() {
   // Glibc doesn't provide a wrapper for gettid(2).
+#if defined(ANDROID)
+  return syscall(__NR_gettid);
+#else
   return syscall(SYS_gettid);
+#endif
 }
 
 
@@ -802,17 +881,22 @@
 #ifndef V8_HOST_ARCH_MIPS
   USE(info);
   if (signal != SIGPROF) return;
-  if (active_sampler_ == NULL || !active_sampler_->IsActive()) return;
-  if (vm_tid_ != GetThreadID()) return;
+  Isolate* isolate = Isolate::UncheckedCurrent();
+  if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
+    // We require a fully initialized and entered isolate.
+    return;
+  }
+  Sampler* sampler = isolate->logger()->sampler();
+  if (sampler == NULL || !sampler->IsActive()) return;
 
   TickSample sample_obj;
-  TickSample* sample = CpuProfiler::TickSampleEvent();
+  TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
   if (sample == NULL) sample = &sample_obj;
 
   // Extracting the sample from the context is extremely machine dependent.
   ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
   mcontext_t& mcontext = ucontext->uc_mcontext;
-  sample->state = Top::current_vm_state();
+  sample->state = isolate->current_vm_state();
 #if V8_HOST_ARCH_IA32
   sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
   sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
@@ -833,55 +917,141 @@
   sample->fp = reinterpret_cast<Address>(mcontext.arm_fp);
 #endif
 #elif V8_HOST_ARCH_MIPS
-  // Implement this on MIPS.
-  UNIMPLEMENTED();
+  sample.pc = reinterpret_cast<Address>(mcontext.pc);
+  sample.sp = reinterpret_cast<Address>(mcontext.gregs[29]);
+  sample.fp = reinterpret_cast<Address>(mcontext.gregs[30]);
 #endif
-  active_sampler_->SampleStack(sample);
-  active_sampler_->Tick(sample);
+  sampler->SampleStack(sample);
+  sampler->Tick(sample);
 #endif
 }
 
 
 class Sampler::PlatformData : public Malloced {
  public:
+  PlatformData() : vm_tid_(GetThreadID()) {}
+
+  int vm_tid() const { return vm_tid_; }
+
+ private:
+  const int vm_tid_;
+};
+
+
+class SignalSender : public Thread {
+ public:
   enum SleepInterval {
-    FULL_INTERVAL,
-    HALF_INTERVAL
+    HALF_INTERVAL,
+    FULL_INTERVAL
   };
 
-  explicit PlatformData(Sampler* sampler)
-      : sampler_(sampler),
-        signal_handler_installed_(false),
+  explicit SignalSender(int interval)
+      : Thread(NULL, "SignalSender"),
         vm_tgid_(getpid()),
-        signal_sender_launched_(false) {
+        interval_(interval) {}
+
+  static void AddActiveSampler(Sampler* sampler) {
+    ScopedLock lock(mutex_);
+    SamplerRegistry::AddActiveSampler(sampler);
+    if (instance_ == NULL) {
+      // Install a signal handler.
+      struct sigaction sa;
+      sa.sa_sigaction = ProfilerSignalHandler;
+      sigemptyset(&sa.sa_mask);
+      sa.sa_flags = SA_RESTART | SA_SIGINFO;
+      signal_handler_installed_ =
+          (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
+
+      // Start a thread that sends SIGPROF signal to VM threads.
+      instance_ = new SignalSender(sampler->interval());
+      instance_->Start();
+    } else {
+      ASSERT(instance_->interval_ == sampler->interval());
+    }
   }
 
-  void SignalSender() {
-    while (sampler_->IsActive()) {
-      if (rate_limiter_.SuspendIfNecessary()) continue;
-      if (sampler_->IsProfiling() && RuntimeProfiler::IsEnabled()) {
-        SendProfilingSignal();
+  static void RemoveActiveSampler(Sampler* sampler) {
+    ScopedLock lock(mutex_);
+    SamplerRegistry::RemoveActiveSampler(sampler);
+    if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
+      RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
+      instance_->Join();
+      delete instance_;
+      instance_ = NULL;
+
+      // Restore the old signal handler.
+      if (signal_handler_installed_) {
+        sigaction(SIGPROF, &old_signal_handler_, 0);
+        signal_handler_installed_ = false;
+      }
+    }
+  }
+
+  // Implement Thread::Run().
+  virtual void Run() {
+    SamplerRegistry::State state;
+    while ((state = SamplerRegistry::GetState()) !=
+           SamplerRegistry::HAS_NO_SAMPLERS) {
+      bool cpu_profiling_enabled =
+          (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
+      bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
+      // When CPU profiling is enabled both JavaScript and C++ code is
+      // profiled. We must not suspend.
+      if (!cpu_profiling_enabled) {
+        if (rate_limiter_.SuspendIfNecessary()) continue;
+      }
+      if (cpu_profiling_enabled && runtime_profiler_enabled) {
+        if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
+          return;
+        }
         Sleep(HALF_INTERVAL);
-        RuntimeProfiler::NotifyTick();
+        if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
+          return;
+        }
         Sleep(HALF_INTERVAL);
       } else {
-        if (sampler_->IsProfiling()) SendProfilingSignal();
-        if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
+        if (cpu_profiling_enabled) {
+          if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile,
+                                                      this)) {
+            return;
+          }
+        }
+        if (runtime_profiler_enabled) {
+          if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile,
+                                                      NULL)) {
+            return;
+          }
+        }
         Sleep(FULL_INTERVAL);
       }
     }
   }
 
-  void SendProfilingSignal() {
+  static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
+    if (!sampler->IsProfiling()) return;
+    SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender);
+    sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
+  }
+
+  static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
+    if (!sampler->isolate()->IsInitialized()) return;
+    sampler->isolate()->runtime_profiler()->NotifyTick();
+  }
+
+  void SendProfilingSignal(int tid) {
     if (!signal_handler_installed_) return;
     // Glibc doesn't provide a wrapper for tgkill(2).
-    syscall(SYS_tgkill, vm_tgid_, vm_tid_, SIGPROF);
+#if defined(ANDROID)
+    syscall(__NR_tgkill, vm_tgid_, tid, SIGPROF);
+#else
+    syscall(SYS_tgkill, vm_tgid_, tid, SIGPROF);
+#endif
   }
 
   void Sleep(SleepInterval full_or_half) {
     // Convert ms to us and subtract 100 us to compensate delays
     // occuring during signal delivery.
-    useconds_t interval = sampler_->interval_ * 1000 - 100;
+    useconds_t interval = interval_ * 1000 - 100;
     if (full_or_half == HALF_INTERVAL) interval /= 2;
     int result = usleep(interval);
 #ifdef DEBUG
@@ -896,89 +1066,55 @@
     USE(result);
   }
 
-  Sampler* sampler_;
-  bool signal_handler_installed_;
-  struct sigaction old_signal_handler_;
-  int vm_tgid_;
-  bool signal_sender_launched_;
-  pthread_t signal_sender_thread_;
+  const int vm_tgid_;
+  const int interval_;
   RuntimeProfilerRateLimiter rate_limiter_;
+
+  // Protects the process wide state below.
+  static Mutex* mutex_;
+  static SignalSender* instance_;
+  static bool signal_handler_installed_;
+  static struct sigaction old_signal_handler_;
+
+  DISALLOW_COPY_AND_ASSIGN(SignalSender);
 };
 
 
-static void* SenderEntry(void* arg) {
-  Sampler::PlatformData* data =
-      reinterpret_cast<Sampler::PlatformData*>(arg);
-  data->SignalSender();
-  return 0;
-}
+Mutex* SignalSender::mutex_ = OS::CreateMutex();
+SignalSender* SignalSender::instance_ = NULL;
+struct sigaction SignalSender::old_signal_handler_;
+bool SignalSender::signal_handler_installed_ = false;
 
 
-Sampler::Sampler(int interval)
-    : interval_(interval),
+Sampler::Sampler(Isolate* isolate, int interval)
+    : isolate_(isolate),
+      interval_(interval),
       profiling_(false),
       active_(false),
       samples_taken_(0) {
-  data_ = new PlatformData(this);
+  data_ = new PlatformData;
 }
 
 
 Sampler::~Sampler() {
-  ASSERT(!data_->signal_sender_launched_);
+  ASSERT(!IsActive());
   delete data_;
 }
 
 
 void Sampler::Start() {
-  // There can only be one active sampler at the time on POSIX
-  // platforms.
   ASSERT(!IsActive());
-  vm_tid_ = GetThreadID();
-
-  // Request profiling signals.
-  struct sigaction sa;
-  sa.sa_sigaction = ProfilerSignalHandler;
-  sigemptyset(&sa.sa_mask);
-  sa.sa_flags = SA_RESTART | SA_SIGINFO;
-  data_->signal_handler_installed_ =
-      sigaction(SIGPROF, &sa, &data_->old_signal_handler_) == 0;
-
-  // Start a thread that sends SIGPROF signal to VM thread.
-  // Sending the signal ourselves instead of relying on itimer provides
-  // much better accuracy.
   SetActive(true);
-  if (pthread_create(
-          &data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
-    data_->signal_sender_launched_ = true;
-  }
-
-  // Set this sampler as the active sampler.
-  active_sampler_ = this;
+  SignalSender::AddActiveSampler(this);
 }
 
 
 void Sampler::Stop() {
+  ASSERT(IsActive());
+  SignalSender::RemoveActiveSampler(this);
   SetActive(false);
-
-  // Wait for signal sender termination (it will exit after setting
-  // active_ to false).
-  if (data_->signal_sender_launched_) {
-    Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
-    pthread_join(data_->signal_sender_thread_, NULL);
-    data_->signal_sender_launched_ = false;
-  }
-
-  // Restore old signal handler
-  if (data_->signal_handler_installed_) {
-    sigaction(SIGPROF, &data_->old_signal_handler_, 0);
-    data_->signal_handler_installed_ = false;
-  }
-
-  // This sampler is no longer the active sampler.
-  active_sampler_ = NULL;
 }
 
-
 #endif  // ENABLE_LOGGING_AND_PROFILING
 
 } }  // namespace v8::internal
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index 35724c3..17e3042 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -88,6 +88,9 @@
 }
 
 
+static Mutex* limit_mutex = NULL;
+
+
 void OS::Setup() {
   // Seed the random number generator.
   // Convert the current time to a 64-bit integer first, before converting it
@@ -96,6 +99,7 @@
   // call this setup code within the same millisecond.
   uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
   srandom(static_cast<unsigned int>(seed));
+  limit_mutex = CreateMutex();
 }
 
 
@@ -109,6 +113,9 @@
 
 
 static void UpdateAllocatedSpaceLimits(void* address, int size) {
+  ASSERT(limit_mutex != NULL);
+  ScopedLock lock(limit_mutex);
+
   lowest_ever_allocated = Min(lowest_ever_allocated, address);
   highest_ever_allocated =
       Max(highest_ever_allocated,
@@ -143,7 +150,7 @@
                      MAP_PRIVATE | MAP_ANON,
                      kMmapFd, kMmapFdOffset);
   if (mbase == MAP_FAILED) {
-    LOG(StringEvent("OS::Allocate", "mmap failed"));
+    LOG(Isolate::Current(), StringEvent("OS::Allocate", "mmap failed"));
     return NULL;
   }
   *allocated = msize;
@@ -258,7 +265,8 @@
     if (code_ptr == NULL) continue;
     const uintptr_t slide = _dyld_get_image_vmaddr_slide(i);
     const uintptr_t start = reinterpret_cast<uintptr_t>(code_ptr) + slide;
-    LOG(SharedLibraryEvent(_dyld_get_image_name(i), start, start + size));
+    LOG(Isolate::Current(),
+        SharedLibraryEvent(_dyld_get_image_name(i), start, start + size));
   }
 #endif  // ENABLE_LOGGING_AND_PROFILING
 }
@@ -424,12 +432,18 @@
 }
 
 
-Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
-  set_name("v8:<unknown>");
+Thread::Thread(Isolate* isolate, const Options& options)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(options.stack_size) {
+  set_name(options.name);
 }
 
 
-Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+Thread::Thread(Isolate* isolate, const char* name)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(0) {
   set_name(name);
 }
 
@@ -438,7 +452,6 @@
 }
 
 
-
 static void SetThreadName(const char* name) {
   // pthread_setname_np is only available in 10.6 or later, so test
   // for it at runtime.
@@ -464,6 +477,7 @@
   thread->thread_handle_data()->thread_ = pthread_self();
   SetThreadName(thread->name());
   ASSERT(thread->IsValid());
+  Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
   thread->Run();
   return NULL;
 }
@@ -476,7 +490,15 @@
 
 
 void Thread::Start() {
-  pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
+  pthread_attr_t* attr_ptr = NULL;
+  pthread_attr_t attr;
+  if (stack_size_ > 0) {
+    pthread_attr_init(&attr);
+    pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
+    attr_ptr = &attr;
+  }
+  pthread_create(&thread_handle_data()->thread_, attr_ptr, ThreadEntry, this);
+  ASSERT(IsValid());
 }
 
 
@@ -595,52 +617,111 @@
 
 class Sampler::PlatformData : public Malloced {
  public:
-  explicit PlatformData(Sampler* sampler)
-      : sampler_(sampler),
-        task_self_(mach_task_self()),
-        profiled_thread_(0),
-        sampler_thread_(0) {
+  PlatformData() : profiled_thread_(mach_thread_self()) {}
+
+  ~PlatformData() {
+    // Deallocate Mach port for thread.
+    mach_port_deallocate(mach_task_self(), profiled_thread_);
   }
 
-  Sampler* sampler_;
+  thread_act_t profiled_thread() { return profiled_thread_; }
+
+ private:
   // Note: for profiled_thread_ Mach primitives are used instead of PThread's
   // because the latter doesn't provide thread manipulation primitives required.
   // For details, consult "Mac OS X Internals" book, Section 7.3.
-  mach_port_t task_self_;
   thread_act_t profiled_thread_;
-  pthread_t sampler_thread_;
-  RuntimeProfilerRateLimiter rate_limiter_;
+};
 
-  // Sampler thread handler.
-  void Runner() {
-    while (sampler_->IsActive()) {
-      if (rate_limiter_.SuspendIfNecessary()) continue;
-      Sample();
-      OS::Sleep(sampler_->interval_);
+class SamplerThread : public Thread {
+ public:
+  explicit SamplerThread(int interval)
+      : Thread(NULL, "SamplerThread"),
+        interval_(interval) {}
+
+  static void AddActiveSampler(Sampler* sampler) {
+    ScopedLock lock(mutex_);
+    SamplerRegistry::AddActiveSampler(sampler);
+    if (instance_ == NULL) {
+      instance_ = new SamplerThread(sampler->interval());
+      instance_->Start();
+    } else {
+      ASSERT(instance_->interval_ == sampler->interval());
     }
   }
 
-  void Sample() {
-    if (sampler_->IsProfiling()) {
-      TickSample sample_obj;
-      TickSample* sample = CpuProfiler::TickSampleEvent();
-      if (sample == NULL) sample = &sample_obj;
+  static void RemoveActiveSampler(Sampler* sampler) {
+    ScopedLock lock(mutex_);
+    SamplerRegistry::RemoveActiveSampler(sampler);
+    if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
+      RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
+      instance_->Join();
+      delete instance_;
+      instance_ = NULL;
+    }
+  }
 
-      if (KERN_SUCCESS != thread_suspend(profiled_thread_)) return;
+  // Implement Thread::Run().
+  virtual void Run() {
+    SamplerRegistry::State state;
+    while ((state = SamplerRegistry::GetState()) !=
+           SamplerRegistry::HAS_NO_SAMPLERS) {
+      bool cpu_profiling_enabled =
+          (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
+      bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
+      // When CPU profiling is enabled both JavaScript and C++ code is
+      // profiled. We must not suspend.
+      if (!cpu_profiling_enabled) {
+        if (rate_limiter_.SuspendIfNecessary()) continue;
+      }
+      if (cpu_profiling_enabled) {
+        if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
+          return;
+        }
+      }
+      if (runtime_profiler_enabled) {
+        if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
+          return;
+        }
+      }
+      OS::Sleep(interval_);
+    }
+  }
+
+  static void DoCpuProfile(Sampler* sampler, void* raw_sampler_thread) {
+    if (!sampler->isolate()->IsInitialized()) return;
+    if (!sampler->IsProfiling()) return;
+    SamplerThread* sampler_thread =
+        reinterpret_cast<SamplerThread*>(raw_sampler_thread);
+    sampler_thread->SampleContext(sampler);
+  }
+
+  static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
+    if (!sampler->isolate()->IsInitialized()) return;
+    sampler->isolate()->runtime_profiler()->NotifyTick();
+  }
+
+  void SampleContext(Sampler* sampler) {
+    thread_act_t profiled_thread = sampler->platform_data()->profiled_thread();
+    TickSample sample_obj;
+    TickSample* sample = CpuProfiler::TickSampleEvent(sampler->isolate());
+    if (sample == NULL) sample = &sample_obj;
+
+    if (KERN_SUCCESS != thread_suspend(profiled_thread)) return;
 
 #if V8_HOST_ARCH_X64
-      thread_state_flavor_t flavor = x86_THREAD_STATE64;
-      x86_thread_state64_t state;
-      mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
+    thread_state_flavor_t flavor = x86_THREAD_STATE64;
+    x86_thread_state64_t state;
+    mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
 #if __DARWIN_UNIX03
 #define REGISTER_FIELD(name) __r ## name
 #else
 #define REGISTER_FIELD(name) r ## name
 #endif  // __DARWIN_UNIX03
 #elif V8_HOST_ARCH_IA32
-      thread_state_flavor_t flavor = i386_THREAD_STATE;
-      i386_thread_state_t state;
-      mach_msg_type_number_t count = i386_THREAD_STATE_COUNT;
+    thread_state_flavor_t flavor = i386_THREAD_STATE;
+    i386_thread_state_t state;
+    mach_msg_type_number_t count = i386_THREAD_STATE_COUNT;
 #if __DARWIN_UNIX03
 #define REGISTER_FIELD(name) __e ## name
 #else
@@ -650,81 +731,64 @@
 #error Unsupported Mac OS X host architecture.
 #endif  // V8_HOST_ARCH
 
-      if (thread_get_state(profiled_thread_,
-                           flavor,
-                           reinterpret_cast<natural_t*>(&state),
-                           &count) == KERN_SUCCESS) {
-        sample->state = Top::current_vm_state();
-        sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
-        sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
-        sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
-        sampler_->SampleStack(sample);
-        sampler_->Tick(sample);
-      }
-      thread_resume(profiled_thread_);
+    if (thread_get_state(profiled_thread,
+                         flavor,
+                         reinterpret_cast<natural_t*>(&state),
+                         &count) == KERN_SUCCESS) {
+      sample->state = sampler->isolate()->current_vm_state();
+      sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
+      sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
+      sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
+      sampler->SampleStack(sample);
+      sampler->Tick(sample);
     }
-    if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
+    thread_resume(profiled_thread);
   }
+
+  const int interval_;
+  RuntimeProfilerRateLimiter rate_limiter_;
+
+  // Protects the process wide state below.
+  static Mutex* mutex_;
+  static SamplerThread* instance_;
+
+  DISALLOW_COPY_AND_ASSIGN(SamplerThread);
 };
 
 #undef REGISTER_FIELD
 
 
-// Entry point for sampler thread.
-static void* SamplerEntry(void* arg) {
-  Sampler::PlatformData* data =
-      reinterpret_cast<Sampler::PlatformData*>(arg);
-  data->Runner();
-  return 0;
-}
+Mutex* SamplerThread::mutex_ = OS::CreateMutex();
+SamplerThread* SamplerThread::instance_ = NULL;
 
 
-Sampler::Sampler(int interval)
-    : interval_(interval),
+Sampler::Sampler(Isolate* isolate, int interval)
+    : isolate_(isolate),
+      interval_(interval),
       profiling_(false),
       active_(false),
       samples_taken_(0) {
-  data_ = new PlatformData(this);
+  data_ = new PlatformData;
 }
 
 
 Sampler::~Sampler() {
+  ASSERT(!IsActive());
   delete data_;
 }
 
 
 void Sampler::Start() {
-  // Do not start multiple threads for the same sampler.
   ASSERT(!IsActive());
-  data_->profiled_thread_ = mach_thread_self();
-
-  // Create sampler thread with high priority.
-  // According to POSIX spec, when SCHED_FIFO policy is used, a thread
-  // runs until it exits or blocks.
-  pthread_attr_t sched_attr;
-  sched_param fifo_param;
-  pthread_attr_init(&sched_attr);
-  pthread_attr_setinheritsched(&sched_attr, PTHREAD_EXPLICIT_SCHED);
-  pthread_attr_setschedpolicy(&sched_attr, SCHED_FIFO);
-  fifo_param.sched_priority = sched_get_priority_max(SCHED_FIFO);
-  pthread_attr_setschedparam(&sched_attr, &fifo_param);
-
   SetActive(true);
-  pthread_create(&data_->sampler_thread_, &sched_attr, SamplerEntry, data_);
+  SamplerThread::AddActiveSampler(this);
 }
 
 
 void Sampler::Stop() {
-  // Seting active to false triggers termination of the sampler
-  // thread.
+  ASSERT(IsActive());
+  SamplerThread::RemoveActiveSampler(this);
   SetActive(false);
-
-  // Wait for sampler thread to terminate.
-  Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
-  pthread_join(data_->sampler_thread_, NULL);
-
-  // Deallocate Mach port for thread.
-  mach_port_deallocate(data_->task_self_, data_->profiled_thread_);
 }
 
 #endif  // ENABLE_LOGGING_AND_PROFILING
diff --git a/src/platform-nullos.cc b/src/platform-nullos.cc
index 49d3dd9..5409936 100644
--- a/src/platform-nullos.cc
+++ b/src/platform-nullos.cc
@@ -340,13 +340,19 @@
 }
 
 
-Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
-  set_name("v8:<unknown>");
+Thread::Thread(Isolate* isolate, const Options& options)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(options.stack_size) {
+  set_name(options.name);
   UNIMPLEMENTED();
 }
 
 
-Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+Thread::Thread(Isolate* isolate, const char* name)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(0) {
   set_name(name);
   UNIMPLEMENTED();
 }
diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc
index e279629..fe1a62a 100644
--- a/src/platform-openbsd.cc
+++ b/src/platform-openbsd.cc
@@ -154,7 +154,7 @@
   void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
 
   if (mbase == MAP_FAILED) {
-    LOG(StringEvent("OS::Allocate", "mmap failed"));
+    LOG(ISOLATE, StringEvent("OS::Allocate", "mmap failed"));
     return NULL;
   }
   *allocated = msize;
@@ -400,12 +400,18 @@
 }
 
 
-Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
-  set_name("v8:<unknown>");
+Thread::Thread(Isolate* isolate, const Options& options)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(options.stack_size) {
+  set_name(options.name);
 }
 
 
-Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+Thread::Thread(Isolate* isolate, const char* name)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(0) {
   set_name(name);
 }
 
@@ -421,6 +427,7 @@
   // one) so we initialize it here too.
   thread->thread_handle_data()->thread_ = pthread_self();
   ASSERT(thread->IsValid());
+  Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
   thread->Run();
   return NULL;
 }
@@ -433,7 +440,14 @@
 
 
 void Thread::Start() {
-  pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
+  pthread_attr_t* attr_ptr = NULL;
+  pthread_attr_t attr;
+  if (stack_size_ > 0) {
+    pthread_attr_init(&attr);
+    pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
+    attr_ptr = &attr;
+  }
+  pthread_create(&thread_handle_data()->thread_, attr_ptr, ThreadEntry, this);
   ASSERT(IsValid());
 }
 
@@ -598,8 +612,9 @@
 };
 
 
-Sampler::Sampler(int interval)
-    : interval_(interval),
+Sampler::Sampler(Isolate* isolate, int interval)
+    : isolate_(isolate),
+      interval_(interval),
       profiling_(false),
       active_(false),
       samples_taken_(0) {
diff --git a/src/platform-posix.cc b/src/platform-posix.cc
index 256dc75..1dd486e 100644
--- a/src/platform-posix.cc
+++ b/src/platform-posix.cc
@@ -127,7 +127,7 @@
 }
 
 
-const char* OS::LogFileOpenMode = "w";
+const char* const OS::LogFileOpenMode = "w";
 
 
 void OS::Print(const char* format, ...) {
@@ -139,7 +139,7 @@
 
 
 void OS::VPrint(const char* format, va_list args) {
-#if defined(ANDROID)
+#if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
   LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args);
 #else
   vprintf(format, args);
@@ -156,7 +156,7 @@
 
 
 void OS::VFPrint(FILE* out, const char* format, va_list args) {
-#if defined(ANDROID)
+#if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
   LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args);
 #else
   vfprintf(out, format, args);
@@ -173,7 +173,7 @@
 
 
 void OS::VPrintError(const char* format, va_list args) {
-#if defined(ANDROID)
+#if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
   LOG_PRI_VA(ANDROID_LOG_ERROR, LOG_TAG, format, args);
 #else
   vfprintf(stderr, format, args);
diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc
index ebe0475..da278f3 100644
--- a/src/platform-solaris.cc
+++ b/src/platform-solaris.cc
@@ -45,7 +45,7 @@
 #include <errno.h>
 #include <ieeefp.h>  // finite()
 #include <signal.h>  // sigemptyset(), etc
-#include <sys/kdi_regs.h>
+#include <sys/regset.h>
 
 
 #undef MAP_TYPE
@@ -169,7 +169,7 @@
   void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
 
   if (mbase == MAP_FAILED) {
-    LOG(StringEvent("OS::Allocate", "mmap failed"));
+    LOG(ISOLATE, StringEvent("OS::Allocate", "mmap failed"));
     return NULL;
   }
   *allocated = msize;
@@ -415,12 +415,18 @@
 }
 
 
-Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
-  set_name("v8:<unknown>");
+Thread::Thread(Isolate* isolate, const Options& options)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(options.stack_size) {
+  set_name(options.name);
 }
 
 
-Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+Thread::Thread(Isolate* isolate, const char* name)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(0) {
   set_name(name);
 }
 
@@ -436,6 +442,7 @@
   // one) so we initialize it here too.
   thread->thread_handle_data()->thread_ = pthread_self();
   ASSERT(thread->IsValid());
+  Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
   thread->Run();
   return NULL;
 }
@@ -448,6 +455,13 @@
 
 
 void Thread::Start() {
+  pthread_attr_t* attr_ptr = NULL;
+  pthread_attr_t attr;
+  if (stack_size_ > 0) {
+    pthread_attr_init(&attr);
+    pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
+    attr_ptr = &attr;
+  }
   pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
   ASSERT(IsValid());
 }
@@ -612,11 +626,16 @@
 static pthread_t vm_tid_ = 0;
 
 
+static pthread_t GetThreadID() {
+  return pthread_self();
+}
+
+
 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
   USE(info);
   if (signal != SIGPROF) return;
   if (active_sampler_ == NULL || !active_sampler_->IsActive()) return;
-  if (vm_tid_ != pthread_self()) return;
+  if (vm_tid_ != GetThreadID()) return;
 
   TickSample sample_obj;
   TickSample* sample = CpuProfiler::TickSampleEvent();
@@ -627,17 +646,10 @@
   mcontext_t& mcontext = ucontext->uc_mcontext;
   sample->state = Top::current_vm_state();
 
-#if V8_HOST_ARCH_IA32
-  sample->pc = reinterpret_cast<Address>(mcontext.gregs[KDIREG_EIP]);
-  sample->sp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_ESP]);
-  sample->fp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_EBP]);
-#elif V8_HOST_ARCH_X64
-  sample->pc = reinterpret_cast<Address>(mcontext.gregs[KDIREG_RIP]);
-  sample->sp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_RSP]);
-  sample->fp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_RBP]);
-#else
-  UNIMPLEMENTED();
-#endif
+  sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]);
+  sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
+  sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
+
   active_sampler_->SampleStack(sample);
   active_sampler_->Tick(sample);
 }
@@ -645,26 +657,87 @@
 
 class Sampler::PlatformData : public Malloced {
  public:
-  PlatformData() {
-    signal_handler_installed_ = false;
+  enum SleepInterval {
+    FULL_INTERVAL,
+    HALF_INTERVAL
+  };
+
+  explicit PlatformData(Sampler* sampler)
+      : sampler_(sampler),
+        signal_handler_installed_(false),
+        vm_tgid_(getpid()),
+        signal_sender_launched_(false) {
   }
 
+  void SignalSender() {
+    while (sampler_->IsActive()) {
+      if (rate_limiter_.SuspendIfNecessary()) continue;
+      if (sampler_->IsProfiling() && RuntimeProfiler::IsEnabled()) {
+        SendProfilingSignal();
+        Sleep(HALF_INTERVAL);
+        RuntimeProfiler::NotifyTick();
+        Sleep(HALF_INTERVAL);
+      } else {
+        if (sampler_->IsProfiling()) SendProfilingSignal();
+        if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
+        Sleep(FULL_INTERVAL);
+      }
+    }
+  }
+
+  void SendProfilingSignal() {
+    if (!signal_handler_installed_) return;
+    pthread_kill(vm_tid_, SIGPROF);
+  }
+
+  void Sleep(SleepInterval full_or_half) {
+    // Convert ms to us and subtract 100 us to compensate delays
+    // occuring during signal delivery.
+    useconds_t interval = sampler_->interval_ * 1000 - 100;
+    if (full_or_half == HALF_INTERVAL) interval /= 2;
+    int result = usleep(interval);
+#ifdef DEBUG
+    if (result != 0 && errno != EINTR) {
+      fprintf(stderr,
+              "SignalSender usleep error; interval = %u, errno = %d\n",
+              interval,
+              errno);
+      ASSERT(result == 0 || errno == EINTR);
+    }
+#endif
+    USE(result);
+  }
+
+  Sampler* sampler_;
   bool signal_handler_installed_;
   struct sigaction old_signal_handler_;
-  struct itimerval old_timer_value_;
+  int vm_tgid_;
+  bool signal_sender_launched_;
+  pthread_t signal_sender_thread_;
+  RuntimeProfilerRateLimiter rate_limiter_;
 };
 
 
-Sampler::Sampler(int interval)
-    : interval_(interval),
+static void* SenderEntry(void* arg) {
+  Sampler::PlatformData* data =
+      reinterpret_cast<Sampler::PlatformData*>(arg);
+  data->SignalSender();
+  return 0;
+}
+
+
+Sampler::Sampler(Isolate* isolate, int interval)
+    : isolate_(isolate),
+      interval_(interval),
       profiling_(false),
       active_(false),
       samples_taken_(0) {
-  data_ = new PlatformData();
+  data_ = new PlatformData(this);
 }
 
 
 Sampler::~Sampler() {
+  ASSERT(!data_->signal_sender_launched_);
   delete data_;
 }
 
@@ -672,41 +745,50 @@
 void Sampler::Start() {
   // There can only be one active sampler at the time on POSIX
   // platforms.
-  if (active_sampler_ != NULL) return;
+  ASSERT(!IsActive());
+  vm_tid_ = GetThreadID();
 
   // 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;
+  sa.sa_flags = SA_RESTART | SA_SIGINFO;
+  data_->signal_handler_installed_ =
+      sigaction(SIGPROF, &sa, &data_->old_signal_handler_) == 0;
 
-  // 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_);
+  // Start a thread that sends SIGPROF signal to VM thread.
+  // Sending the signal ourselves instead of relying on itimer provides
+  // much better accuracy.
+  SetActive(true);
+  if (pthread_create(
+          &data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
+    data_->signal_sender_launched_ = true;
+  }
 
   // Set this sampler as the active sampler.
   active_sampler_ = this;
-  active_ = true;
 }
 
 
 void Sampler::Stop() {
+  SetActive(false);
+
+  // Wait for signal sender termination (it will exit after setting
+  // active_ to false).
+  if (data_->signal_sender_launched_) {
+    Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
+    pthread_join(data_->signal_sender_thread_, NULL);
+    data_->signal_sender_launched_ = false;
+  }
+
   // 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
diff --git a/test/cctest/test-mips.cc b/src/platform-tls-mac.h
similarity index 62%
copy from test/cctest/test-mips.cc
copy to src/platform-tls-mac.h
index efd4cc9..86a3347 100644
--- a/test/cctest/test-mips.cc
+++ b/src/platform-tls-mac.h
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -25,28 +25,38 @@
 // (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_PLATFORM_TLS_MAC_H_
+#define V8_PLATFORM_TLS_MAC_H_
 
-#include "v8.h"
-#include "execution.h"
+#include "globals.h"
 
-#include "cctest.h"
+namespace v8 {
+namespace internal {
 
-using ::v8::Local;
-using ::v8::String;
-using ::v8::Script;
+#if defined(V8_HOST_ARCH_IA32) || defined(V8_HOST_ARCH_X64)
 
-namespace i = ::v8::internal;
+#define V8_FAST_TLS_SUPPORTED 1
 
-TEST(MIPSFunctionCalls) {
-  // Disable compilation of natives.
-  i::FLAG_disable_native_files = true;
-  i::FLAG_full_compiler = false;
+INLINE(intptr_t InternalGetExistingThreadLocal(intptr_t index));
 
-  v8::HandleScope scope;
-  LocalContext env;  // from cctest.h
-
-  const char* c_source = "function foo() { return 0x1234; }; foo();";
-  Local<String> source = ::v8::String::New(c_source);
-  Local<Script> script = ::v8::Script::Compile(source);
-  CHECK_EQ(0x1234,  script->Run()->Int32Value());
+inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
+  // The constants below are taken from pthreads.s from the XNU kernel
+  // sources archive at www.opensource.apple.com.
+  intptr_t result;
+#if defined(V8_HOST_ARCH_IA32)
+  asm("movl %%gs:0x48(,%1,4), %0;"
+      :"=r"(result)  // Output must be a writable register.
+      :"0"(index));  // Input is the same as output.
+#else
+  asm("movq %%gs:0x60(,%1,8), %0;"
+      :"=r"(result)
+      :"0"(index));
+#endif
+  return result;
 }
+
+#endif
+
+} }  // namespace v8::internal
+
+#endif  // V8_PLATFORM_TLS_MAC_H_
diff --git a/src/mips/fast-codegen-mips.cc b/src/platform-tls-win32.h
similarity index 60%
copy from src/mips/fast-codegen-mips.cc
copy to src/platform-tls-win32.h
index 186f9fa..4056e8c 100644
--- a/src/mips/fast-codegen-mips.cc
+++ b/src/platform-tls-win32.h
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -25,53 +25,38 @@
 // (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"
+#ifndef V8_PLATFORM_TLS_WIN32_H_
+#define V8_PLATFORM_TLS_WIN32_H_
 
-#if defined(V8_TARGET_ARCH_MIPS)
-
-#include "codegen-inl.h"
-#include "fast-codegen.h"
+#include "checks.h"
+#include "globals.h"
+#include "win32-headers.h"
 
 namespace v8 {
 namespace internal {
 
-#define __ ACCESS_MASM(masm_)
+#if defined(_WIN32) && !defined(_WIN64)
 
-Register FastCodeGenerator::accumulator0() { return no_reg; }
-Register FastCodeGenerator::accumulator1() { return no_reg; }
-Register FastCodeGenerator::scratch0() { return no_reg; }
-Register FastCodeGenerator::scratch1() { return no_reg; }
-Register FastCodeGenerator::receiver_reg() { return no_reg; }
-Register FastCodeGenerator::context_reg() { return no_reg; }
+#define V8_FAST_TLS_SUPPORTED 1
 
-
-void FastCodeGenerator::Generate(CompilationInfo* info) {
-  UNIMPLEMENTED_MIPS();
+inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
+  const intptr_t kTibInlineTlsOffset = 0xE10;
+  const intptr_t kTibExtraTlsOffset = 0xF94;
+  const intptr_t kMaxInlineSlots = 64;
+  const intptr_t kMaxSlots = kMaxInlineSlots + 1024;
+  ASSERT(0 <= index && index < kMaxSlots);
+  if (index < kMaxInlineSlots) {
+    return static_cast<intptr_t>(__readfsdword(kTibInlineTlsOffset +
+                                               kPointerSize * index));
+  }
+  intptr_t extra = static_cast<intptr_t>(__readfsdword(kTibExtraTlsOffset));
+  ASSERT(extra != 0);
+  return *reinterpret_cast<intptr_t*>(extra +
+                                      kPointerSize * (index - kMaxInlineSlots));
 }
 
-
-void FastCodeGenerator::EmitThisPropertyStore(Handle<String> name) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void FastCodeGenerator::EmitGlobalVariableLoad(Handle<Object> name) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void FastCodeGenerator::EmitThisPropertyLoad(Handle<String> name) {
-  UNIMPLEMENTED_MIPS();
-}
-
-
-void FastCodeGenerator::EmitBitOr() {
-  UNIMPLEMENTED_MIPS();
-}
-
-#undef __
-
+#endif
 
 } }  // namespace v8::internal
 
-#endif  // V8_TARGET_ARCH_MIPS
+#endif  // V8_PLATFORM_TLS_WIN32_H_
diff --git a/test/cctest/test-mips.cc b/src/platform-tls.h
similarity index 69%
copy from test/cctest/test-mips.cc
copy to src/platform-tls.h
index efd4cc9..5649175 100644
--- a/test/cctest/test-mips.cc
+++ b/src/platform-tls.h
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -25,28 +25,26 @@
 // (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 and architecture specific thread local store functions.
 
-#include "v8.h"
-#include "execution.h"
+#ifndef V8_PLATFORM_TLS_H_
+#define V8_PLATFORM_TLS_H_
 
-#include "cctest.h"
+#ifdef V8_FAST_TLS
 
-using ::v8::Local;
-using ::v8::String;
-using ::v8::Script;
+// When fast TLS is requested we include the appropriate
+// implementation header.
+//
+// The implementation header defines V8_FAST_TLS_SUPPORTED if it
+// provides fast TLS support for the current platform and architecture
+// combination.
 
-namespace i = ::v8::internal;
+#if defined(_MSC_VER) && (defined(_WIN32) || defined(_WIN64))
+#include "platform-tls-win32.h"
+#elif defined(__APPLE__)
+#include "platform-tls-mac.h"
+#endif
 
-TEST(MIPSFunctionCalls) {
-  // Disable compilation of natives.
-  i::FLAG_disable_native_files = true;
-  i::FLAG_full_compiler = false;
+#endif
 
-  v8::HandleScope scope;
-  LocalContext env;  // from cctest.h
-
-  const char* c_source = "function foo() { return 0x1234; }; foo();";
-  Local<String> source = ::v8::String::New(c_source);
-  Local<Script> script = ::v8::Script::Compile(source);
-  CHECK_EQ(0x1234,  script->Run()->Int32Value());
-}
+#endif  // V8_PLATFORM_TLS_H_
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index f24994b..50a9e5b 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -173,6 +173,10 @@
   return ceil(x);
 }
 
+
+static Mutex* limit_mutex = NULL;
+
+
 #ifdef _WIN64
 typedef double (*ModuloFunction)(double, double);
 
@@ -540,6 +544,7 @@
   // call this setup code within the same millisecond.
   uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
   srand(static_cast<unsigned int>(seed));
+  limit_mutex = CreateMutex();
 }
 
 
@@ -676,7 +681,7 @@
 
 
 // Open log file in binary mode to avoid /n -> /r/n conversion.
-const char* OS::LogFileOpenMode = "wb";
+const char* const OS::LogFileOpenMode = "wb";
 
 
 // Print (debug) message to console.
@@ -749,9 +754,13 @@
 
 
 void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
+  // Use _TRUNCATE or strncpy_s crashes (by design) if buffer is too small.
+  size_t buffer_size = static_cast<size_t>(dest.length());
+  if (n + 1 > buffer_size)  // count for trailing '\0'
+    n = _TRUNCATE;
   int result = strncpy_s(dest.start(), dest.length(), src, n);
   USE(result);
-  ASSERT(result == 0);
+  ASSERT(result == 0 || (n == _TRUNCATE && result == STRUNCATE));
 }
 
 
@@ -765,6 +774,9 @@
 
 
 static void UpdateAllocatedSpaceLimits(void* address, int size) {
+  ASSERT(limit_mutex != NULL);
+  ScopedLock lock(limit_mutex);
+
   lowest_ever_allocated = Min(lowest_ever_allocated, address);
   highest_ever_allocated =
       Max(highest_ever_allocated,
@@ -835,7 +847,7 @@
   // For exectutable pages try and randomize the allocation address
   if (prot == PAGE_EXECUTE_READWRITE &&
       msize >= static_cast<size_t>(Page::kPageSize)) {
-    address = (V8::RandomPrivate() << kPageSizeBits)
+    address = (V8::RandomPrivate(Isolate::Current()) << kPageSizeBits)
       | kAllocationRandomAddressMin;
     address &= kAllocationRandomAddressMax;
   }
@@ -848,7 +860,7 @@
     mbase = VirtualAlloc(NULL, msize, MEM_COMMIT | MEM_RESERVE, prot);
 
   if (mbase == NULL) {
-    LOG(StringEvent("OS::Allocate", "VirtualAlloc failed"));
+    LOG(ISOLATE, StringEvent("OS::Allocate", "VirtualAlloc failed"));
     return NULL;
   }
 
@@ -1191,7 +1203,8 @@
       if (err != ERROR_MOD_NOT_FOUND &&
           err != ERROR_INVALID_HANDLE) return false;
     }
-    LOG(SharedLibraryEvent(
+    LOG(i::Isolate::Current(),
+        SharedLibraryEvent(
             module_entry.szExePath,
             reinterpret_cast<unsigned int>(module_entry.modBaseAddr),
             reinterpret_cast<unsigned int>(module_entry.modBaseAddr +
@@ -1450,6 +1463,7 @@
   // 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::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
   thread->Run();
   return 0;
 }
@@ -1493,13 +1507,19 @@
 // Initialize a Win32 thread object. The thread has an invalid thread
 // handle until it is started.
 
-Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
+Thread::Thread(Isolate* isolate, const Options& options)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(options.stack_size) {
   data_ = new PlatformData(kNoThread);
-  set_name("v8:<unknown>");
+  set_name(options.name);
 }
 
 
-Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+Thread::Thread(Isolate* isolate, const char* name)
+    : ThreadHandle(ThreadHandle::INVALID),
+      isolate_(isolate),
+      stack_size_(0) {
   data_ = new PlatformData(kNoThread);
   set_name(name);
 }
@@ -1524,7 +1544,7 @@
 void Thread::Start() {
   data_->thread_ = reinterpret_cast<HANDLE>(
       _beginthreadex(NULL,
-                     0,
+                     static_cast<unsigned>(stack_size_),
                      ThreadEntry,
                      this,
                      0,
@@ -1840,135 +1860,179 @@
 
 // ----------------------------------------------------------------------------
 // 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_;
-  RuntimeProfilerRateLimiter rate_limiter_;
-
-  // Sampler thread handler.
-  void Runner() {
-    while (sampler_->IsActive()) {
-      if (rate_limiter_.SuspendIfNecessary()) continue;
-      Sample();
-      Sleep(sampler_->interval_);
-    }
-  }
-
-  void Sample() {
-    if (sampler_->IsProfiling()) {
-      // Context used for sampling the register state of the profiled thread.
-      CONTEXT context;
-      memset(&context, 0, sizeof(context));
-
-      TickSample sample_obj;
-      TickSample* sample = CpuProfiler::TickSampleEvent();
-      if (sample == NULL) sample = &sample_obj;
-
-      static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
-      if (SuspendThread(profiled_thread_) == kSuspendFailed) return;
-      sample->state = Top::current_vm_state();
-
-      context.ContextFlags = CONTEXT_FULL;
-      if (GetThreadContext(profiled_thread_, &context) != 0) {
-#if V8_HOST_ARCH_X64
-        sample->pc = reinterpret_cast<Address>(context.Rip);
-        sample->sp = reinterpret_cast<Address>(context.Rsp);
-        sample->fp = reinterpret_cast<Address>(context.Rbp);
-#else
-        sample->pc = reinterpret_cast<Address>(context.Eip);
-        sample->sp = reinterpret_cast<Address>(context.Esp);
-        sample->fp = reinterpret_cast<Address>(context.Ebp);
-#endif
-        sampler_->SampleStack(sample);
-        sampler_->Tick(sample);
-      }
-      ResumeThread(profiled_thread_);
-    }
-    if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
-  }
-};
-
-
-// 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)
-    : interval_(interval),
-      profiling_(false),
-      active_(false),
-      samples_taken_(0) {
-  data_ = new PlatformData(this);
-}
-
-
-Sampler::~Sampler() {
-  delete data_;
-}
-
-
-// Start profiling.
-void Sampler::Start() {
-  // Do not start multiple threads for the same sampler.
-  ASSERT(!IsActive());
-
   // 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;
+  PlatformData() : profiled_thread_(OpenThread(THREAD_GET_CONTEXT |
+                                               THREAD_SUSPEND_RESUME |
+                                               THREAD_QUERY_INFORMATION,
+                                               false,
+                                               GetCurrentThreadId())) {}
 
-  // Start sampler thread.
-  unsigned int tid;
+  ~PlatformData() {
+    if (profiled_thread_ != NULL) {
+      CloseHandle(profiled_thread_);
+      profiled_thread_ = NULL;
+    }
+  }
+
+  HANDLE profiled_thread() { return profiled_thread_; }
+
+ private:
+  HANDLE profiled_thread_;
+};
+
+
+class SamplerThread : public Thread {
+ public:
+  explicit SamplerThread(int interval)
+      : Thread(NULL, "SamplerThread"),
+        interval_(interval) {}
+
+  static void AddActiveSampler(Sampler* sampler) {
+    ScopedLock lock(mutex_);
+    SamplerRegistry::AddActiveSampler(sampler);
+    if (instance_ == NULL) {
+      instance_ = new SamplerThread(sampler->interval());
+      instance_->Start();
+    } else {
+      ASSERT(instance_->interval_ == sampler->interval());
+    }
+  }
+
+  static void RemoveActiveSampler(Sampler* sampler) {
+    ScopedLock lock(mutex_);
+    SamplerRegistry::RemoveActiveSampler(sampler);
+    if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
+      RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
+      instance_->Join();
+      delete instance_;
+      instance_ = NULL;
+    }
+  }
+
+  // Implement Thread::Run().
+  virtual void Run() {
+    SamplerRegistry::State state;
+    while ((state = SamplerRegistry::GetState()) !=
+           SamplerRegistry::HAS_NO_SAMPLERS) {
+      bool cpu_profiling_enabled =
+          (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
+      bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
+      // When CPU profiling is enabled both JavaScript and C++ code is
+      // profiled. We must not suspend.
+      if (!cpu_profiling_enabled) {
+        if (rate_limiter_.SuspendIfNecessary()) continue;
+      }
+      if (cpu_profiling_enabled) {
+        if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
+          return;
+        }
+      }
+      if (runtime_profiler_enabled) {
+        if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
+          return;
+        }
+      }
+      OS::Sleep(interval_);
+    }
+  }
+
+  static void DoCpuProfile(Sampler* sampler, void* raw_sampler_thread) {
+    if (!sampler->isolate()->IsInitialized()) return;
+    if (!sampler->IsProfiling()) return;
+    SamplerThread* sampler_thread =
+        reinterpret_cast<SamplerThread*>(raw_sampler_thread);
+    sampler_thread->SampleContext(sampler);
+  }
+
+  static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
+    if (!sampler->isolate()->IsInitialized()) return;
+    sampler->isolate()->runtime_profiler()->NotifyTick();
+  }
+
+  void SampleContext(Sampler* sampler) {
+    HANDLE profiled_thread = sampler->platform_data()->profiled_thread();
+    if (profiled_thread == NULL) return;
+
+    // Context used for sampling the register state of the profiled thread.
+    CONTEXT context;
+    memset(&context, 0, sizeof(context));
+
+    TickSample sample_obj;
+    TickSample* sample = CpuProfiler::TickSampleEvent(sampler->isolate());
+    if (sample == NULL) sample = &sample_obj;
+
+    static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
+    if (SuspendThread(profiled_thread) == kSuspendFailed) return;
+    sample->state = sampler->isolate()->current_vm_state();
+
+    context.ContextFlags = CONTEXT_FULL;
+    if (GetThreadContext(profiled_thread, &context) != 0) {
+#if V8_HOST_ARCH_X64
+      sample->pc = reinterpret_cast<Address>(context.Rip);
+      sample->sp = reinterpret_cast<Address>(context.Rsp);
+      sample->fp = reinterpret_cast<Address>(context.Rbp);
+#else
+      sample->pc = reinterpret_cast<Address>(context.Eip);
+      sample->sp = reinterpret_cast<Address>(context.Esp);
+      sample->fp = reinterpret_cast<Address>(context.Ebp);
+#endif
+      sampler->SampleStack(sample);
+      sampler->Tick(sample);
+    }
+    ResumeThread(profiled_thread);
+  }
+
+  const int interval_;
+  RuntimeProfilerRateLimiter rate_limiter_;
+
+  // Protects the process wide state below.
+  static Mutex* mutex_;
+  static SamplerThread* instance_;
+
+  DISALLOW_COPY_AND_ASSIGN(SamplerThread);
+};
+
+
+Mutex* SamplerThread::mutex_ = OS::CreateMutex();
+SamplerThread* SamplerThread::instance_ = NULL;
+
+
+Sampler::Sampler(Isolate* isolate, int interval)
+    : isolate_(isolate),
+      interval_(interval),
+      profiling_(false),
+      active_(false),
+      samples_taken_(0) {
+  data_ = new PlatformData;
+}
+
+
+Sampler::~Sampler() {
+  ASSERT(!IsActive());
+  delete data_;
+}
+
+
+void Sampler::Start() {
+  ASSERT(!IsActive());
   SetActive(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);
+  SamplerThread::AddActiveSampler(this);
 }
 
 
-// Stop profiling.
 void Sampler::Stop() {
-  // Seting active to false triggers termination of the sampler
-  // thread.
+  ASSERT(IsActive());
+  SamplerThread::RemoveActiveSampler(this);
   SetActive(false);
-
-  // Wait for sampler thread to terminate.
-  Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
-  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/src/platform.h b/src/platform.h
index 88825e6..b2e0c48 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -114,6 +114,7 @@
 #endif  // __GNUC__
 
 #include "atomicops.h"
+#include "platform-tls.h"
 #include "utils.h"
 #include "v8globals.h"
 
@@ -177,7 +178,7 @@
   static bool Remove(const char* path);
 
   // Log file open mode is platform-dependent due to line ends issues.
-  static const char* LogFileOpenMode;
+  static const char* const LogFileOpenMode;
 
   // Print output to console. This is mostly used for debugging output.
   // On platforms that has standard terminal output, the output
@@ -293,6 +294,9 @@
   // Support runtime detection of VFP3 on ARM CPUs.
   static bool ArmCpuHasFeature(CpuFeature feature);
 
+  // Support runtime detection of FPU on MIPS CPUs.
+  static bool MipsCpuHasFeature(CpuFeature feature);
+
   // Returns the activation frame alignment constraint or zero if
   // the platform doesn't care. Guaranteed to be a power of two.
   static int ActivationFrameAlignment();
@@ -388,9 +392,16 @@
     LOCAL_STORAGE_KEY_MAX_VALUE = kMaxInt
   };
 
-  // Create new thread.
-  Thread();
-  explicit Thread(const char* name);
+  struct Options {
+    Options() : name("v8:<unknown>"), stack_size(0) {}
+
+    const char* name;
+    int stack_size;
+  };
+
+  // Create new thread (with a value for storing in the TLS isolate field).
+  Thread(Isolate* isolate, const Options& options);
+  Thread(Isolate* isolate, const char* name);
   virtual ~Thread();
 
   // Start new thread by calling the Run() method in the new thread.
@@ -421,9 +432,24 @@
     return GetThreadLocal(key) != NULL;
   }
 
+#ifdef V8_FAST_TLS_SUPPORTED
+  static inline void* GetExistingThreadLocal(LocalStorageKey key) {
+    void* result = reinterpret_cast<void*>(
+        InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
+    ASSERT(result == GetThreadLocal(key));
+    return result;
+  }
+#else
+  static inline void* GetExistingThreadLocal(LocalStorageKey key) {
+    return GetThreadLocal(key);
+  }
+#endif
+
   // A hint to the scheduler to let another thread run.
   static void YieldCPU();
 
+  Isolate* isolate() const { return isolate_; }
+
   // The thread name length is limited to 16 based on Linux's implementation of
   // prctl().
   static const int kMaxThreadNameLength = 16;
@@ -432,8 +458,9 @@
 
   class PlatformData;
   PlatformData* data_;
-
+  Isolate* isolate_;
   char name_[kMaxThreadNameLength];
+  int stack_size_;
 
   DISALLOW_COPY_AND_ASSIGN(Thread);
 };
@@ -466,13 +493,14 @@
 
 
 // ----------------------------------------------------------------------------
-// ScopedLock
+// ScopedLock/ScopedUnlock
 //
-// Stack-allocated ScopedLocks provide block-scoped locking and unlocking
-// of a mutex.
+// Stack-allocated ScopedLocks/ScopedUnlocks provide block-scoped
+// locking and unlocking of a mutex.
 class ScopedLock {
  public:
   explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
+    ASSERT(mutex_ != NULL);
     mutex_->Lock();
   }
   ~ScopedLock() {
@@ -570,22 +598,28 @@
         tos(NULL),
         frames_count(0) {}
   StateTag state;  // The state of the VM.
-  Address pc;   // Instruction pointer.
-  Address sp;   // Stack pointer.
-  Address fp;   // Frame pointer.
-  Address tos;  // Top stack value (*sp).
+  Address pc;      // Instruction pointer.
+  Address sp;      // Stack pointer.
+  Address fp;      // Frame pointer.
+  union {
+    Address tos;   // Top stack value (*sp).
+    Address external_callback;
+  };
   static const int kMaxFramesCount = 64;
   Address stack[kMaxFramesCount];  // Call stack.
-  int frames_count;  // Number of captured frames.
+  int frames_count : 8;  // Number of captured frames.
+  bool has_external_callback : 1;
 };
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
 class Sampler {
  public:
   // Initialize sampler.
-  explicit Sampler(int interval);
+  Sampler(Isolate* isolate, int interval);
   virtual ~Sampler();
 
+  int interval() const { return interval_; }
+
   // Performs stack sampling.
   void SampleStack(TickSample* sample) {
     DoSampleStack(sample);
@@ -608,11 +642,16 @@
   // Whether the sampler is running (that is, consumes resources).
   bool IsActive() const { return NoBarrier_Load(&active_); }
 
+  Isolate* isolate() { return isolate_; }
+
   // Used in tests to make sure that stack sampling is performed.
   int samples_taken() const { return samples_taken_; }
   void ResetSamplesTaken() { samples_taken_ = 0; }
 
   class PlatformData;
+  PlatformData* data() { return data_; }
+
+  PlatformData* platform_data() { return data_; }
 
  protected:
   virtual void DoSampleStack(TickSample* sample) = 0;
@@ -621,6 +660,7 @@
   void SetActive(bool value) { NoBarrier_Store(&active_, value); }
   void IncSamplesTaken() { if (++samples_taken_ < 0) samples_taken_ = 0; }
 
+  Isolate* isolate_;
   const int interval_;
   Atomic32 profiling_;
   Atomic32 active_;
@@ -629,6 +669,7 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
 };
 
+
 #endif  // ENABLE_LOGGING_AND_PROFILING
 
 } }  // namespace v8::internal
diff --git a/src/preparse-data.cc b/src/preparse-data.cc
index 7c9d8a6..92a0338 100644
--- a/src/preparse-data.cc
+++ b/src/preparse-data.cc
@@ -32,8 +32,10 @@
 #include "utils.h"
 #include "list-inl.h"
 #include "hashmap.h"
+
 #include "preparse-data.h"
 
+
 namespace v8 {
 namespace internal {
 
diff --git a/src/preparser-api.cc b/src/preparser-api.cc
index 3817935..61e9e7e 100644
--- a/src/preparser-api.cc
+++ b/src/preparser-api.cc
@@ -26,6 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "../include/v8-preparser.h"
+
 #include "globals.h"
 #include "checks.h"
 #include "allocation.h"
@@ -158,6 +159,9 @@
 
 class StandAloneJavaScriptScanner : public JavaScriptScanner {
  public:
+  explicit StandAloneJavaScriptScanner(ScannerConstants* scanner_constants)
+      : JavaScriptScanner(scanner_constants) { }
+
   void Initialize(UC16CharacterStream* source) {
     source_ = source;
     Init();
@@ -170,7 +174,8 @@
 };
 
 
-// Functions declared by allocation.h
+// Functions declared by allocation.h and implemented in both api.cc (for v8)
+// or here (for a stand-alone preparser).
 
 void FatalProcessOutOfMemory(const char* reason) {
   V8_Fatal(__FILE__, __LINE__, reason);
@@ -187,7 +192,8 @@
 PreParserData Preparse(UnicodeInputStream* input, size_t max_stack) {
   internal::InputStreamUTF16Buffer buffer(input);
   uintptr_t stack_limit = reinterpret_cast<uintptr_t>(&buffer) - max_stack;
-  internal::StandAloneJavaScriptScanner scanner;
+  internal::ScannerConstants scanner_constants;
+  internal::StandAloneJavaScriptScanner scanner(&scanner_constants);
   scanner.Initialize(&buffer);
   internal::CompleteParserRecorder recorder;
   preparser::PreParser::PreParseResult result =
diff --git a/src/preparser.cc b/src/preparser.cc
index 252e88f..fec1567 100644
--- a/src/preparser.cc
+++ b/src/preparser.cc
@@ -1,4 +1,3 @@
-
 // Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,6 +32,7 @@
 #include "allocation.h"
 #include "utils.h"
 #include "list.h"
+
 #include "scanner-base.h"
 #include "preparse-data.h"
 #include "preparser.h"
diff --git a/src/prettyprinter.cc b/src/prettyprinter.cc
index dda7abb..043ad1c 100644
--- a/src/prettyprinter.cc
+++ b/src/prettyprinter.cc
@@ -526,13 +526,13 @@
       Print("%c", string->Get(i));
     }
     if (quote) Print("\"");
-  } else if (object == Heap::null_value()) {
+  } else if (object->IsNull()) {
     Print("null");
-  } else if (object == Heap::true_value()) {
+  } else if (object->IsTrue()) {
     Print("true");
-  } else if (object == Heap::false_value()) {
+  } else if (object->IsFalse()) {
     Print("false");
-  } else if (object == Heap::undefined_value()) {
+  } else if (object->IsUndefined()) {
     Print("undefined");
   } else if (object->IsNumber()) {
     Print("%g", object->Number());
@@ -602,11 +602,12 @@
 
 class IndentedScope BASE_EMBEDDED {
  public:
-  IndentedScope() {
+  explicit IndentedScope(AstPrinter* printer) : ast_printer_(printer) {
     ast_printer_->inc_indent();
   }
 
-  explicit IndentedScope(const char* txt, AstNode* node = NULL) {
+  IndentedScope(AstPrinter* printer, const char* txt, AstNode* node = NULL)
+      : ast_printer_(printer) {
     ast_printer_->PrintIndented(txt);
     if (node != NULL && node->AsExpression() != NULL) {
       Expression* expr = node->AsExpression();
@@ -626,30 +627,20 @@
     ast_printer_->dec_indent();
   }
 
-  static void SetAstPrinter(AstPrinter* a) { ast_printer_ = a; }
-
  private:
-  static AstPrinter* ast_printer_;
+  AstPrinter* ast_printer_;
 };
 
 
-AstPrinter* IndentedScope::ast_printer_ = NULL;
-
-
 //-----------------------------------------------------------------------------
 
-int AstPrinter::indent_ = 0;
 
-
-AstPrinter::AstPrinter() {
-  ASSERT(indent_ == 0);
-  IndentedScope::SetAstPrinter(this);
+AstPrinter::AstPrinter() : indent_(0) {
 }
 
 
 AstPrinter::~AstPrinter() {
   ASSERT(indent_ == 0);
-  IndentedScope::SetAstPrinter(NULL);
 }
 
 
@@ -708,14 +699,14 @@
 
 
 void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
-  IndentedScope indent(s, node);
+  IndentedScope indent(this, s, node);
   Visit(node);
 }
 
 
 const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
   Init();
-  { IndentedScope indent("FUNC");
+  { IndentedScope indent(this, "FUNC");
     PrintLiteralIndented("NAME", program->name(), true);
     PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true);
     PrintParameters(program->scope());
@@ -728,7 +719,7 @@
 
 void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
   if (declarations->length() > 0) {
-    IndentedScope indent("DECLS");
+    IndentedScope indent(this, "DECLS");
     for (int i = 0; i < declarations->length(); i++) {
       Visit(declarations->at(i));
     }
@@ -738,7 +729,7 @@
 
 void AstPrinter::PrintParameters(Scope* scope) {
   if (scope->num_parameters() > 0) {
-    IndentedScope indent("PARAMS");
+    IndentedScope indent(this, "PARAMS");
     for (int i = 0; i < scope->num_parameters(); i++) {
       PrintLiteralWithModeIndented("VAR", scope->parameter(i),
                                    scope->parameter(i)->name(),
@@ -764,10 +755,10 @@
 
 void AstPrinter::PrintCaseClause(CaseClause* clause) {
   if (clause->is_default()) {
-    IndentedScope indent("DEFAULT");
+    IndentedScope indent(this, "DEFAULT");
     PrintStatements(clause->statements());
   } else {
-    IndentedScope indent("CASE");
+    IndentedScope indent(this, "CASE");
     Visit(clause->label());
     PrintStatements(clause->statements());
   }
@@ -776,7 +767,7 @@
 
 void AstPrinter::VisitBlock(Block* node) {
   const char* block_txt = node->is_initializer_block() ? "BLOCK INIT" : "BLOCK";
-  IndentedScope indent(block_txt);
+  IndentedScope indent(this, block_txt);
   PrintStatements(node->statements());
 }
 
@@ -844,7 +835,7 @@
 
 
 void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
-  IndentedScope indent("SWITCH");
+  IndentedScope indent(this, "SWITCH");
   PrintLabelsIndented(NULL, node->labels());
   PrintIndentedVisit("TAG", node->tag());
   for (int i = 0; i < node->cases()->length(); i++) {
@@ -854,7 +845,7 @@
 
 
 void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
-  IndentedScope indent("DO");
+  IndentedScope indent(this, "DO");
   PrintLabelsIndented(NULL, node->labels());
   PrintIndentedVisit("BODY", node->body());
   PrintIndentedVisit("COND", node->cond());
@@ -862,7 +853,7 @@
 
 
 void AstPrinter::VisitWhileStatement(WhileStatement* node) {
-  IndentedScope indent("WHILE");
+  IndentedScope indent(this, "WHILE");
   PrintLabelsIndented(NULL, node->labels());
   PrintIndentedVisit("COND", node->cond());
   PrintIndentedVisit("BODY", node->body());
@@ -870,7 +861,7 @@
 
 
 void AstPrinter::VisitForStatement(ForStatement* node) {
-  IndentedScope indent("FOR");
+  IndentedScope indent(this, "FOR");
   PrintLabelsIndented(NULL, node->labels());
   if (node->init()) PrintIndentedVisit("INIT", node->init());
   if (node->cond()) PrintIndentedVisit("COND", node->cond());
@@ -880,7 +871,7 @@
 
 
 void AstPrinter::VisitForInStatement(ForInStatement* node) {
-  IndentedScope indent("FOR IN");
+  IndentedScope indent(this, "FOR IN");
   PrintIndentedVisit("FOR", node->each());
   PrintIndentedVisit("IN", node->enumerable());
   PrintIndentedVisit("BODY", node->body());
@@ -888,7 +879,7 @@
 
 
 void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
-  IndentedScope indent("TRY CATCH");
+  IndentedScope indent(this, "TRY CATCH");
   PrintIndentedVisit("TRY", node->try_block());
   PrintIndentedVisit("CATCHVAR", node->catch_var());
   PrintIndentedVisit("CATCH", node->catch_block());
@@ -896,19 +887,19 @@
 
 
 void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
-  IndentedScope indent("TRY FINALLY");
+  IndentedScope indent(this, "TRY FINALLY");
   PrintIndentedVisit("TRY", node->try_block());
   PrintIndentedVisit("FINALLY", node->finally_block());
 }
 
 
 void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
-  IndentedScope indent("DEBUGGER");
+  IndentedScope indent(this, "DEBUGGER");
 }
 
 
 void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
-  IndentedScope indent("FUNC LITERAL");
+  IndentedScope indent(this, "FUNC LITERAL");
   PrintLiteralIndented("NAME", node->name(), false);
   PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false);
   PrintParameters(node->scope());
@@ -921,13 +912,13 @@
 
 void AstPrinter::VisitSharedFunctionInfoLiteral(
     SharedFunctionInfoLiteral* node) {
-  IndentedScope indent("FUNC LITERAL");
+  IndentedScope indent(this, "FUNC LITERAL");
   PrintLiteralIndented("SHARED INFO", node->shared_function_info(), true);
 }
 
 
 void AstPrinter::VisitConditional(Conditional* node) {
-  IndentedScope indent("CONDITIONAL");
+  IndentedScope indent(this, "CONDITIONAL");
   PrintIndentedVisit("?", node->condition());
   PrintIndentedVisit("THEN", node->then_expression());
   PrintIndentedVisit("ELSE", node->else_expression());
@@ -940,14 +931,14 @@
 
 
 void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
-  IndentedScope indent("REGEXP LITERAL");
+  IndentedScope indent(this, "REGEXP LITERAL");
   PrintLiteralIndented("PATTERN", node->pattern(), false);
   PrintLiteralIndented("FLAGS", node->flags(), false);
 }
 
 
 void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
-  IndentedScope indent("OBJ LITERAL");
+  IndentedScope indent(this, "OBJ LITERAL");
   for (int i = 0; i < node->properties()->length(); i++) {
     const char* prop_kind = NULL;
     switch (node->properties()->at(i)->kind()) {
@@ -972,7 +963,7 @@
       default:
         UNREACHABLE();
     }
-    IndentedScope prop(prop_kind);
+    IndentedScope prop(this, prop_kind);
     PrintIndentedVisit("KEY", node->properties()->at(i)->key());
     PrintIndentedVisit("VALUE", node->properties()->at(i)->value());
   }
@@ -980,9 +971,9 @@
 
 
 void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
-  IndentedScope indent("ARRAY LITERAL");
+  IndentedScope indent(this, "ARRAY LITERAL");
   if (node->values()->length() > 0) {
-    IndentedScope indent("VALUES");
+    IndentedScope indent(this, "VALUES");
     for (int i = 0; i < node->values()->length(); i++) {
       Visit(node->values()->at(i));
     }
@@ -991,7 +982,7 @@
 
 
 void AstPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) {
-  IndentedScope indent("CatchExtensionObject");
+  IndentedScope indent(this, "CatchExtensionObject");
   PrintIndentedVisit("KEY", node->key());
   PrintIndentedVisit("VALUE", node->value());
 }
@@ -1009,14 +1000,14 @@
                                node->type());
   Variable* var = node->var();
   if (var != NULL && var->rewrite() != NULL) {
-    IndentedScope indent;
+    IndentedScope indent(this);
     Visit(var->rewrite());
   }
 }
 
 
 void AstPrinter::VisitAssignment(Assignment* node) {
-  IndentedScope indent(Token::Name(node->op()), node);
+  IndentedScope indent(this, Token::Name(node->op()), node);
   Visit(node->target());
   Visit(node->value());
 }
@@ -1028,7 +1019,7 @@
 
 
 void AstPrinter::VisitProperty(Property* node) {
-  IndentedScope indent("PROPERTY", node);
+  IndentedScope indent(this, "PROPERTY", node);
   Visit(node->obj());
   Literal* literal = node->key()->AsLiteral();
   if (literal != NULL && literal->handle()->IsSymbol()) {
@@ -1040,14 +1031,14 @@
 
 
 void AstPrinter::VisitCall(Call* node) {
-  IndentedScope indent("CALL");
+  IndentedScope indent(this, "CALL");
   Visit(node->expression());
   PrintArguments(node->arguments());
 }
 
 
 void AstPrinter::VisitCallNew(CallNew* node) {
-  IndentedScope indent("CALL NEW");
+  IndentedScope indent(this, "CALL NEW");
   Visit(node->expression());
   PrintArguments(node->arguments());
 }
@@ -1055,7 +1046,7 @@
 
 void AstPrinter::VisitCallRuntime(CallRuntime* node) {
   PrintLiteralIndented("CALL RUNTIME ", node->name(), false);
-  IndentedScope indent;
+  IndentedScope indent(this);
   PrintArguments(node->arguments());
 }
 
@@ -1086,14 +1077,14 @@
 
 
 void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
-  IndentedScope indent(Token::Name(node->op()), node);
+  IndentedScope indent(this, Token::Name(node->op()), node);
   Visit(node->left());
   Visit(node->right());
 }
 
 
 void AstPrinter::VisitCompareOperation(CompareOperation* node) {
-  IndentedScope indent(Token::Name(node->op()), node);
+  IndentedScope indent(this, Token::Name(node->op()), node);
   Visit(node->left());
   Visit(node->right());
 }
@@ -1103,13 +1094,13 @@
   const char* name = node->is_strict()
       ? "COMPARE-TO-NULL-STRICT"
       : "COMPARE-TO-NULL";
-  IndentedScope indent(name, node);
+  IndentedScope indent(this, name, node);
   Visit(node->expression());
 }
 
 
 void AstPrinter::VisitThisFunction(ThisFunction* node) {
-  IndentedScope indent("THIS-FUNCTION");
+  IndentedScope indent(this, "THIS-FUNCTION");
 }
 
 
diff --git a/src/prettyprinter.h b/src/prettyprinter.h
index c83de34..284a93f 100644
--- a/src/prettyprinter.h
+++ b/src/prettyprinter.h
@@ -111,7 +111,7 @@
   void inc_indent() { indent_++; }
   void dec_indent() { indent_--; }
 
-  static int indent_;
+  int indent_;
 };
 
 
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 7612eab..c9db94f 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -29,8 +29,8 @@
 
 #include "v8.h"
 #include "global-handles.h"
+#include "heap-profiler.h"
 #include "scopeinfo.h"
-#include "top.h"
 #include "unicode.h"
 #include "zone-inl.h"
 
@@ -47,24 +47,27 @@
 
 
 TokenEnumerator::~TokenEnumerator() {
+  Isolate* isolate = Isolate::Current();
   for (int i = 0; i < token_locations_.length(); ++i) {
     if (!token_removed_[i]) {
-      GlobalHandles::ClearWeakness(token_locations_[i]);
-      GlobalHandles::Destroy(token_locations_[i]);
+      isolate->global_handles()->ClearWeakness(token_locations_[i]);
+      isolate->global_handles()->Destroy(token_locations_[i]);
     }
   }
 }
 
 
 int TokenEnumerator::GetTokenId(Object* token) {
+  Isolate* isolate = Isolate::Current();
   if (token == NULL) return TokenEnumerator::kNoSecurityToken;
   for (int i = 0; i < token_locations_.length(); ++i) {
     if (*token_locations_[i] == token && !token_removed_[i]) return i;
   }
-  Handle<Object> handle = GlobalHandles::Create(token);
+  Handle<Object> handle = isolate->global_handles()->Create(token);
   // handle.location() points to a memory cell holding a pointer
   // to a token object in the V8's heap.
-  GlobalHandles::MakeWeak(handle.location(), this, TokenRemovedCallback);
+  isolate->global_handles()->MakeWeak(handle.location(), this,
+                                      TokenRemovedCallback);
   token_locations_.Add(handle.location());
   token_removed_.Add(false);
   return token_locations_.length() - 1;
@@ -94,55 +97,74 @@
 }
 
 
-static void DeleteIndexName(char** name_ptr) {
-  DeleteArray(*name_ptr);
-}
-
-
 StringsStorage::~StringsStorage() {
   for (HashMap::Entry* p = names_.Start();
        p != NULL;
        p = names_.Next(p)) {
     DeleteArray(reinterpret_cast<const char*>(p->value));
   }
-  index_names_.Iterate(DeleteIndexName);
+}
+
+
+const char* StringsStorage::GetCopy(const char* src) {
+  int len = static_cast<int>(strlen(src));
+  Vector<char> dst = Vector<char>::New(len + 1);
+  OS::StrNCpy(dst, src, len);
+  dst[len] = '\0';
+  uint32_t hash = HashSequentialString(dst.start(), len);
+  return AddOrDisposeString(dst.start(), hash);
+}
+
+
+const char* StringsStorage::GetFormatted(const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  const char* result = GetVFormatted(format, args);
+  va_end(args);
+  return result;
+}
+
+
+const char* StringsStorage::AddOrDisposeString(char* str, uint32_t hash) {
+  HashMap::Entry* cache_entry = names_.Lookup(str, hash, true);
+  if (cache_entry->value == NULL) {
+    // New entry added.
+    cache_entry->value = str;
+  } else {
+    DeleteArray(str);
+  }
+  return reinterpret_cast<const char*>(cache_entry->value);
+}
+
+
+const char* StringsStorage::GetVFormatted(const char* format, va_list args) {
+  Vector<char> str = Vector<char>::New(1024);
+  int len = OS::VSNPrintF(str, format, args);
+  if (len == -1) {
+    DeleteArray(str.start());
+    return format;
+  }
+  uint32_t hash = HashSequentialString(str.start(), len);
+  return AddOrDisposeString(str.start(), hash);
 }
 
 
 const char* StringsStorage::GetName(String* name) {
   if (name->IsString()) {
-    char* c_name =
-        name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach();
-    HashMap::Entry* cache_entry = names_.Lookup(c_name, name->Hash(), true);
-    if (cache_entry->value == NULL) {
-      // New entry added.
-      cache_entry->value = c_name;
-    } else {
-      DeleteArray(c_name);
-    }
-    return reinterpret_cast<const char*>(cache_entry->value);
+    return AddOrDisposeString(
+        name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(),
+        name->Hash());
   }
   return "";
 }
 
 
 const char* StringsStorage::GetName(int index) {
-  ASSERT(index >= 0);
-  if (index_names_.length() <= index) {
-    index_names_.AddBlock(
-        NULL, index - index_names_.length() + 1);
-  }
-  if (index_names_[index] == NULL) {
-    const int kMaximumNameLength = 32;
-    char* name = NewArray<char>(kMaximumNameLength);
-    OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", index);
-    index_names_[index] = name;
-  }
-  return index_names_[index];
+  return GetFormatted("%d", index);
 }
 
 
-const char* CodeEntry::kEmptyNamePrefix = "";
+const char* const CodeEntry::kEmptyNamePrefix = "";
 
 
 void CodeEntry::CopyData(const CodeEntry& source) {
@@ -298,7 +320,7 @@
 
 class FilteredCloneCallback {
  public:
-  explicit FilteredCloneCallback(ProfileNode* dst_root, int security_token_id)
+  FilteredCloneCallback(ProfileNode* dst_root, int security_token_id)
       : stack_(10),
         security_token_id_(security_token_id) {
     stack_.Add(NodesPair(NULL, dst_root));
@@ -465,7 +487,7 @@
 }
 
 
-CodeEntry* const CodeMap::kSfiCodeEntry = NULL;
+CodeEntry* const CodeMap::kSharedFunctionCodeEntry = NULL;
 const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL;
 const CodeMap::CodeTreeConfig::Value CodeMap::CodeTreeConfig::kNoValue =
     CodeMap::CodeEntryInfo(NULL, 0);
@@ -483,18 +505,18 @@
 }
 
 
-int CodeMap::GetSFITag(Address addr) {
+int CodeMap::GetSharedId(Address addr) {
   CodeTree::Locator locator;
-  // For SFI entries, 'size' field is used to store their IDs.
+  // For shared function entries, 'size' field is used to store their IDs.
   if (tree_.Find(addr, &locator)) {
     const CodeEntryInfo& entry = locator.value();
-    ASSERT(entry.entry == kSfiCodeEntry);
+    ASSERT(entry.entry == kSharedFunctionCodeEntry);
     return entry.size;
   } else {
     tree_.Insert(addr, &locator);
-    int tag = next_sfi_tag_++;
-    locator.set_value(CodeEntryInfo(kSfiCodeEntry, tag));
-    return tag;
+    int id = next_shared_id_++;
+    locator.set_value(CodeEntryInfo(kSharedFunctionCodeEntry, id));
+    return id;
   }
 }
 
@@ -528,13 +550,16 @@
 }
 
 static void DeleteProfilesList(List<CpuProfile*>** list_ptr) {
-  (*list_ptr)->Iterate(DeleteCpuProfile);
-  delete *list_ptr;
+  if (*list_ptr != NULL) {
+    (*list_ptr)->Iterate(DeleteCpuProfile);
+    delete *list_ptr;
+  }
 }
 
 CpuProfilesCollection::~CpuProfilesCollection() {
   delete current_profiles_semaphore_;
   current_profiles_.Iterate(DeleteCpuProfile);
+  detached_profiles_.Iterate(DeleteCpuProfile);
   profiles_by_token_.Iterate(DeleteProfilesList);
   code_entries_.Iterate(DeleteCodeEntry);
 }
@@ -599,15 +624,8 @@
 
 CpuProfile* CpuProfilesCollection::GetProfile(int security_token_id,
                                               unsigned uid) {
-  HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid),
-                                                static_cast<uint32_t>(uid),
-                                                false);
-  int index;
-  if (entry != NULL) {
-    index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
-  } else {
-    return NULL;
-  }
+  int index = GetProfileIndex(uid);
+  if (index < 0) return NULL;
   List<CpuProfile*>* unabridged_list =
       profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)];
   if (security_token_id == TokenEnumerator::kNoSecurityToken) {
@@ -622,6 +640,15 @@
 }
 
 
+int CpuProfilesCollection::GetProfileIndex(unsigned uid) {
+  HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid),
+                                                static_cast<uint32_t>(uid),
+                                                false);
+  return entry != NULL ?
+      static_cast<int>(reinterpret_cast<intptr_t>(entry->value)) : -1;
+}
+
+
 bool CpuProfilesCollection::IsLastProfile(const char* title) {
   // Called from VM thread, and only it can mutate the list,
   // so no locking is needed here.
@@ -631,6 +658,39 @@
 }
 
 
+void CpuProfilesCollection::RemoveProfile(CpuProfile* profile) {
+  // Called from VM thread for a completed profile.
+  unsigned uid = profile->uid();
+  int index = GetProfileIndex(uid);
+  if (index < 0) {
+    detached_profiles_.RemoveElement(profile);
+    return;
+  }
+  profiles_uids_.Remove(reinterpret_cast<void*>(uid),
+                        static_cast<uint32_t>(uid));
+  // Decrement all indexes above the deleted one.
+  for (HashMap::Entry* p = profiles_uids_.Start();
+       p != NULL;
+       p = profiles_uids_.Next(p)) {
+    intptr_t p_index = reinterpret_cast<intptr_t>(p->value);
+    if (p_index > index) {
+      p->value = reinterpret_cast<void*>(p_index - 1);
+    }
+  }
+  for (int i = 0; i < profiles_by_token_.length(); ++i) {
+    List<CpuProfile*>* list = profiles_by_token_[i];
+    if (list != NULL && index < list->length()) {
+      // Move all filtered clones into detached_profiles_,
+      // so we can know that they are still in use.
+      CpuProfile* cloned_profile = list->Remove(index);
+      if (cloned_profile != NULL && cloned_profile != profile) {
+        detached_profiles_.Add(cloned_profile);
+      }
+    }
+  }
+}
+
+
 int CpuProfilesCollection::TokenToIndex(int security_token_id) {
   ASSERT(TokenEnumerator::kNoSecurityToken == -1);
   return security_token_id + 1;  // kNoSecurityToken -> 0, 0 -> 1, ...
@@ -763,10 +823,12 @@
 }
 
 
-const char* ProfileGenerator::kAnonymousFunctionName = "(anonymous function)";
-const char* ProfileGenerator::kProgramEntryName = "(program)";
-const char* ProfileGenerator::kGarbageCollectorEntryName =
-  "(garbage collector)";
+const char* const ProfileGenerator::kAnonymousFunctionName =
+    "(anonymous function)";
+const char* const ProfileGenerator::kProgramEntryName =
+    "(program)";
+const char* const ProfileGenerator::kGarbageCollectorEntryName =
+    "(garbage collector)";
 
 
 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
@@ -789,7 +851,15 @@
   if (sample.pc != NULL) {
     *entry++ = code_map_.FindEntry(sample.pc);
 
-    if (sample.tos != NULL) {
+    if (sample.has_external_callback) {
+      // Don't use PC when in external callback code, as it can point
+      // inside callback's code, and we will erroneously report
+      // that a callback calls itself.
+      *(entries.start()) = NULL;
+      *entry++ = code_map_.FindEntry(sample.external_callback);
+    } else if (sample.tos != NULL) {
+      // Find out, if top of stack was pointing inside a JS function
+      // meaning that we have encountered a frameless invocation.
       *entry = code_map_.FindEntry(sample.tos);
       if (*entry != NULL && !(*entry)->is_js_function()) {
         *entry = NULL;
@@ -914,11 +984,6 @@
 }
 
 
-List<HeapGraphPath*>* HeapEntry::GetRetainingPaths() {
-  return snapshot_->GetRetainingPaths(this);
-}
-
-
 template<class Visitor>
 void HeapEntry::ApplyAndPaintAllReachable(Visitor* visitor) {
   List<HeapEntry*> list(10);
@@ -1009,6 +1074,7 @@
     case kArray: return "/array/";
     case kRegExp: return "/regexp/";
     case kHeapNumber: return "/number/";
+    case kNative: return "/native/";
     default: return "???";
   }
 }
@@ -1076,107 +1142,6 @@
 }
 
 
-class CachedHeapGraphPath {
- public:
-  CachedHeapGraphPath()
-      : nodes_(NodesMatch) { }
-  CachedHeapGraphPath(const CachedHeapGraphPath& src)
-      : nodes_(NodesMatch, &HashMap::DefaultAllocator, src.nodes_.capacity()),
-        path_(src.path_.length() + 1) {
-    for (HashMap::Entry* p = src.nodes_.Start();
-         p != NULL;
-         p = src.nodes_.Next(p)) {
-      nodes_.Lookup(p->key, p->hash, true);
-    }
-    path_.AddAll(src.path_);
-  }
-  void Add(HeapGraphEdge* edge) {
-    nodes_.Lookup(edge->to(), Hash(edge->to()), true);
-    path_.Add(edge);
-  }
-  bool ContainsNode(HeapEntry* node) {
-    return nodes_.Lookup(node, Hash(node), false) != NULL;
-  }
-  const List<HeapGraphEdge*>* path() const { return &path_; }
-
- private:
-  static uint32_t Hash(HeapEntry* entry) {
-    return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry));
-  }
-  static bool NodesMatch(void* key1, void* key2) { return key1 == key2; }
-
-  HashMap nodes_;
-  List<HeapGraphEdge*> path_;
-};
-
-
-List<HeapGraphPath*>* HeapEntry::CalculateRetainingPaths() {
-  List<HeapGraphPath*>* retaining_paths = new List<HeapGraphPath*>(4);
-  CachedHeapGraphPath path;
-  FindRetainingPaths(&path, retaining_paths);
-  return retaining_paths;
-}
-
-
-void HeapEntry::FindRetainingPaths(CachedHeapGraphPath* prev_path,
-                                   List<HeapGraphPath*>* retaining_paths) {
-  Vector<HeapGraphEdge*> rets = retainers();
-  for (int i = 0; i < rets.length(); ++i) {
-    HeapGraphEdge* ret_edge = rets[i];
-    if (prev_path->ContainsNode(ret_edge->From())) continue;
-    if (ret_edge->From() != snapshot()->root()) {
-      CachedHeapGraphPath path(*prev_path);
-      path.Add(ret_edge);
-      ret_edge->From()->FindRetainingPaths(&path, retaining_paths);
-    } else {
-      HeapGraphPath* ret_path = new HeapGraphPath(*prev_path->path());
-      ret_path->Set(0, ret_edge);
-      retaining_paths->Add(ret_path);
-    }
-  }
-}
-
-
-HeapGraphPath::HeapGraphPath(const List<HeapGraphEdge*>& path)
-    : path_(path.length() + 1) {
-  Add(NULL);
-  for (int i = path.length() - 1; i >= 0; --i) {
-    Add(path[i]);
-  }
-}
-
-
-void HeapGraphPath::Print() {
-  path_[0]->From()->Print(1, 0);
-  for (int i = 0; i < path_.length(); ++i) {
-    OS::Print(" -> ");
-    HeapGraphEdge* edge = path_[i];
-    switch (edge->type()) {
-      case HeapGraphEdge::kContextVariable:
-        OS::Print("[#%s] ", edge->name());
-        break;
-      case HeapGraphEdge::kElement:
-      case HeapGraphEdge::kHidden:
-        OS::Print("[%d] ", edge->index());
-        break;
-      case HeapGraphEdge::kInternal:
-        OS::Print("[$%s] ", edge->name());
-        break;
-      case HeapGraphEdge::kProperty:
-        OS::Print("[%s] ", edge->name());
-        break;
-      case HeapGraphEdge::kShortcut:
-        OS::Print("[^%s] ", edge->name());
-        break;
-      default:
-        OS::Print("!!! unknown edge type: %d ", edge->type());
-    }
-    edge->to()->Print(1, 0);
-  }
-  OS::Print("\n");
-}
-
-
 // It is very important to keep objects that form a heap snapshot
 // as small as possible.
 namespace {  // Avoid littering the global namespace.
@@ -1205,9 +1170,9 @@
       uid_(uid),
       root_entry_(NULL),
       gc_roots_entry_(NULL),
+      natives_root_entry_(NULL),
       raw_entries_(NULL),
-      entries_sorted_(false),
-      retaining_paths_(HeapEntry::Match) {
+      entries_sorted_(false) {
   STATIC_ASSERT(
       sizeof(HeapGraphEdge) ==
       SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize);  // NOLINT
@@ -1216,21 +1181,14 @@
       SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize);  // NOLINT
 }
 
-
-static void DeleteHeapGraphPath(HeapGraphPath** path_ptr) {
-  delete *path_ptr;
-}
-
 HeapSnapshot::~HeapSnapshot() {
   DeleteArray(raw_entries_);
-  for (HashMap::Entry* p = retaining_paths_.Start();
-       p != NULL;
-       p = retaining_paths_.Next(p)) {
-    List<HeapGraphPath*>* list =
-        reinterpret_cast<List<HeapGraphPath*>*>(p->value);
-    list->Iterate(DeleteHeapGraphPath);
-    delete list;
-  }
+}
+
+
+void HeapSnapshot::Delete() {
+  collection_->RemoveSnapshot(this);
+  delete this;
 }
 
 
@@ -1279,6 +1237,19 @@
 }
 
 
+HeapEntry* HeapSnapshot::AddNativesRootEntry(int children_count,
+                                                 int retainers_count) {
+  ASSERT(natives_root_entry_ == NULL);
+  return (natives_root_entry_ = AddEntry(
+      HeapEntry::kObject,
+      "(Native objects)",
+      HeapObjectsMap::kNativesRootObjectId,
+      0,
+      children_count,
+      retainers_count));
+}
+
+
 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type,
                                   const char* name,
                                   uint64_t id,
@@ -1313,14 +1284,7 @@
 }
 
 
-HeapSnapshotsDiff* HeapSnapshot::CompareWith(HeapSnapshot* snapshot) {
-  return collection_->CompareSnapshots(this, snapshot);
-}
-
-
 HeapEntry* HeapSnapshot::GetEntryById(uint64_t id) {
-  // GetSortedEntriesList is used in diff algorithm and sorts
-  // entries by their id.
   List<HeapEntry*>* entries_by_id = GetSortedEntriesList();
 
   // Perform a binary search by id.
@@ -1341,16 +1305,6 @@
 }
 
 
-List<HeapGraphPath*>* HeapSnapshot::GetRetainingPaths(HeapEntry* entry) {
-  HashMap::Entry* p =
-      retaining_paths_.Lookup(entry, HeapEntry::Hash(entry), true);
-  if (p->value == NULL) {
-    p->value = entry->CalculateRetainingPaths();
-  }
-  return reinterpret_cast<List<HeapGraphPath*>*>(p->value);
-}
-
-
 template<class T>
 static int SortByIds(const T* entry1_ptr,
                      const T* entry2_ptr) {
@@ -1372,10 +1326,13 @@
 }
 
 
-const uint64_t HeapObjectsMap::kInternalRootObjectId = 0;
-const uint64_t HeapObjectsMap::kGcRootsObjectId = 1;
+// We split IDs on evens for embedder objects (see
+// HeapObjectsMap::GenerateId) and odds for native objects.
+const uint64_t HeapObjectsMap::kInternalRootObjectId = 1;
+const uint64_t HeapObjectsMap::kGcRootsObjectId = 3;
+const uint64_t HeapObjectsMap::kNativesRootObjectId = 5;
 // Increase kFirstAvailableObjectId if new 'special' objects appear.
-const uint64_t HeapObjectsMap::kFirstAvailableObjectId = 2;
+const uint64_t HeapObjectsMap::kFirstAvailableObjectId = 7;
 
 HeapObjectsMap::HeapObjectsMap()
     : initial_fill_mode_(true),
@@ -1400,7 +1357,8 @@
     uint64_t existing = FindEntry(addr);
     if (existing != 0) return existing;
   }
-  uint64_t id = next_id_++;
+  uint64_t id = next_id_;
+  next_id_ += 2;
   AddEntry(addr, id);
   return id;
 }
@@ -1468,6 +1426,17 @@
 }
 
 
+uint64_t HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) {
+  uint64_t id = static_cast<uint64_t>(info->GetHash());
+  const char* label = info->GetLabel();
+  id ^= HashSequentialString(label, static_cast<int>(strlen(label)));
+  intptr_t element_count = info->GetElementCount();
+  if (element_count != -1)
+    id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count));
+  return id << 1;
+}
+
+
 HeapSnapshotsCollection::HeapSnapshotsCollection()
     : is_tracking_objects_(false),
       snapshots_uids_(HeapSnapshotsMatch),
@@ -1517,10 +1486,11 @@
 }
 
 
-HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots(
-    HeapSnapshot* snapshot1,
-    HeapSnapshot* snapshot2) {
-  return comparator_.Compare(snapshot1, snapshot2);
+void HeapSnapshotsCollection::RemoveSnapshot(HeapSnapshot* snapshot) {
+  snapshots_.RemoveElement(snapshot);
+  unsigned uid = snapshot->uid();
+  snapshots_uids_.Remove(reinterpret_cast<void*>(uid),
+                         static_cast<uint32_t>(uid));
 }
 
 
@@ -1551,6 +1521,8 @@
         p->key,
         entry_info->children_count,
         entry_info->retainers_count);
+    ASSERT(entry_info->entry != NULL);
+    ASSERT(entry_info->entry != kHeapEntryPlaceholder);
     entry_info->children_count = 0;
     entry_info->retainers_count = 0;
   }
@@ -1630,9 +1602,11 @@
 
 
 HeapObject *const V8HeapExplorer::kInternalRootObject =
-    reinterpret_cast<HeapObject*>(1);
+    reinterpret_cast<HeapObject*>(
+        static_cast<intptr_t>(HeapObjectsMap::kInternalRootObjectId));
 HeapObject *const V8HeapExplorer::kGcRootsObject =
-    reinterpret_cast<HeapObject*>(2);
+    reinterpret_cast<HeapObject*>(
+        static_cast<intptr_t>(HeapObjectsMap::kGcRootsObjectId));
 
 
 V8HeapExplorer::V8HeapExplorer(
@@ -1669,27 +1643,28 @@
     SharedFunctionInfo* shared = func->shared();
     return AddEntry(object,
                     HeapEntry::kClosure,
-                    collection_->GetName(String::cast(shared->name())),
+                    collection_->names()->GetName(String::cast(shared->name())),
                     children_count,
                     retainers_count);
   } else if (object->IsJSRegExp()) {
     JSRegExp* re = JSRegExp::cast(object);
     return AddEntry(object,
                     HeapEntry::kRegExp,
-                    collection_->GetName(re->Pattern()),
+                    collection_->names()->GetName(re->Pattern()),
                     children_count,
                     retainers_count);
   } else if (object->IsJSObject()) {
     return AddEntry(object,
                     HeapEntry::kObject,
-                    collection_->GetName(GetConstructorNameForHeapProfile(
-                        JSObject::cast(object))),
+                    collection_->names()->GetName(
+                        GetConstructorNameForHeapProfile(
+                            JSObject::cast(object))),
                     children_count,
                     retainers_count);
   } else if (object->IsString()) {
     return AddEntry(object,
                     HeapEntry::kString,
-                    collection_->GetName(String::cast(object)),
+                    collection_->names()->GetName(String::cast(object)),
                     children_count,
                     retainers_count);
   } else if (object->IsCode()) {
@@ -1702,7 +1677,7 @@
     SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
     return AddEntry(object,
                     HeapEntry::kCode,
-                    collection_->GetName(String::cast(shared->name())),
+                    collection_->names()->GetName(String::cast(shared->name())),
                     children_count,
                     retainers_count);
   } else if (object->IsScript()) {
@@ -1710,7 +1685,9 @@
     return AddEntry(object,
                     HeapEntry::kCode,
                     script->name()->IsString() ?
-                    collection_->GetName(String::cast(script->name())) : "",
+                        collection_->names()->GetName(
+                            String::cast(script->name()))
+                        : "",
                     children_count,
                     retainers_count);
   } else if (object->IsFixedArray()) {
@@ -1749,8 +1726,8 @@
 
 
 void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) {
-  filler->AddEntry(kInternalRootObject);
-  filler->AddEntry(kGcRootsObject);
+  filler->AddEntry(kInternalRootObject, this);
+  filler->AddEntry(kGcRootsObject, this);
 }
 
 
@@ -1769,25 +1746,40 @@
   IndexedReferencesExtractor(V8HeapExplorer* generator,
                              HeapObject* parent_obj,
                              HeapEntry* parent_entry,
-                             HeapObjectsSet* known_references = NULL)
+                             bool process_field_marks = false)
       : generator_(generator),
         parent_obj_(parent_obj),
         parent_(parent_entry),
-        known_references_(known_references),
+        process_field_marks_(process_field_marks),
         next_index_(1) {
   }
   void VisitPointers(Object** start, Object** end) {
     for (Object** p = start; p < end; p++) {
-      if (!known_references_ || !known_references_->Contains(*p)) {
-        generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p);
-      }
+      if (CheckVisitedAndUnmark(p)) continue;
+      generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p);
     }
   }
+  static void MarkVisitedField(HeapObject* obj, int offset) {
+    if (offset < 0) return;
+    Address field = obj->address() + offset;
+    ASSERT(!Memory::Object_at(field)->IsFailure());
+    ASSERT(Memory::Object_at(field)->IsHeapObject());
+    *field |= kFailureTag;
+  }
  private:
+  bool CheckVisitedAndUnmark(Object** field) {
+    if (process_field_marks_ && (*field)->IsFailure()) {
+      intptr_t untagged = reinterpret_cast<intptr_t>(*field) & ~kFailureTagMask;
+      *field = reinterpret_cast<Object*>(untagged | kHeapObjectTag);
+      ASSERT((*field)->IsHeapObject());
+      return true;
+    }
+    return false;
+  }
   V8HeapExplorer* generator_;
   HeapObject* parent_obj_;
   HeapEntry* parent_;
-  HeapObjectsSet* known_references_;
+  bool process_field_marks_;
   int next_index_;
 };
 
@@ -1796,7 +1788,6 @@
   HeapEntry* entry = GetEntry(obj);
   if (entry == NULL) return;  // No interest in this object.
 
-  known_references_.Clear();
   if (obj->IsJSGlobalProxy()) {
     // We need to reference JS global objects from snapshot's root.
     // We use JSGlobalProxy because this is what embedder (e.g. browser)
@@ -1812,16 +1803,28 @@
     ExtractElementReferences(js_obj, entry);
     ExtractInternalReferences(js_obj, entry);
     SetPropertyReference(
-        obj, entry, Heap::Proto_symbol(), js_obj->GetPrototype());
+        obj, entry, HEAP->Proto_symbol(), js_obj->GetPrototype());
     if (obj->IsJSFunction()) {
-      JSFunction* js_fun = JSFunction::cast(obj);
-      if (js_fun->has_prototype()) {
-        SetPropertyReference(
-            obj, entry, Heap::prototype_symbol(), js_fun->prototype());
+      JSFunction* js_fun = JSFunction::cast(js_obj);
+      SetInternalReference(
+          js_fun, entry,
+          "code", js_fun->shared(),
+          JSFunction::kSharedFunctionInfoOffset);
+      Object* proto_or_map = js_fun->prototype_or_initial_map();
+      if (!proto_or_map->IsTheHole()) {
+        if (!proto_or_map->IsMap()) {
+          SetPropertyReference(
+              obj, entry,
+              HEAP->prototype_symbol(), proto_or_map,
+              JSFunction::kPrototypeOrInitialMapOffset);
+        } else {
+          SetPropertyReference(
+              obj, entry,
+              HEAP->prototype_symbol(), js_fun->prototype());
+        }
       }
     }
-    IndexedReferencesExtractor refs_extractor(
-        this, obj, entry, &known_references_);
+    IndexedReferencesExtractor refs_extractor(this, obj, entry, true);
     obj->Iterate(&refs_extractor);
   } else if (obj->IsString()) {
     if (obj->IsConsString()) {
@@ -1854,7 +1857,6 @@
         SetClosureReference(js_obj, entry, local_name, context->get(idx));
       }
     }
-    SetInternalReference(js_obj, entry, "code", func->shared());
   }
 }
 
@@ -1867,13 +1869,22 @@
       switch (descs->GetType(i)) {
         case FIELD: {
           int index = descs->GetFieldIndex(i);
-          SetPropertyReference(
-              js_obj, entry, descs->GetKey(i), js_obj->FastPropertyAt(index));
+          if (index < js_obj->map()->inobject_properties()) {
+            SetPropertyReference(
+                js_obj, entry,
+                descs->GetKey(i), js_obj->InObjectPropertyAt(index),
+                js_obj->GetInObjectPropertyOffset(index));
+          } else {
+            SetPropertyReference(
+                js_obj, entry,
+                descs->GetKey(i), js_obj->FastPropertyAt(index));
+          }
           break;
         }
         case CONSTANT_FUNCTION:
           SetPropertyReference(
-              js_obj, entry, descs->GetKey(i), descs->GetConstantFunction(i));
+              js_obj, entry,
+              descs->GetKey(i), descs->GetConstantFunction(i));
           break;
         default: ;
       }
@@ -1933,14 +1944,15 @@
   int length = js_obj->GetInternalFieldCount();
   for (int i = 0; i < length; ++i) {
     Object* o = js_obj->GetInternalField(i);
-    SetInternalReference(js_obj, entry, i, o);
+    SetInternalReference(
+        js_obj, entry, i, o, js_obj->GetInternalFieldOffset(i));
   }
 }
 
 
 HeapEntry* V8HeapExplorer::GetEntry(Object* obj) {
   if (!obj->IsHeapObject()) return NULL;
-  return filler_->FindOrAddEntry(obj);
+  return filler_->FindOrAddEntry(obj, this);
 }
 
 
@@ -1977,7 +1989,7 @@
   }
   SetRootGcRootsReference();
   RootsReferencesExtractor extractor(this);
-  Heap::IterateRoots(&extractor, VISIT_ALL);
+  HEAP->IterateRoots(&extractor, VISIT_ALL);
   filler_ = NULL;
   return progress_->ProgressReport(false);
 }
@@ -1992,10 +2004,9 @@
     filler_->SetNamedReference(HeapGraphEdge::kContextVariable,
                                parent_obj,
                                parent_entry,
-                               collection_->GetName(reference_name),
+                               collection_->names()->GetName(reference_name),
                                child_obj,
                                child_entry);
-    known_references_.Insert(child_obj);
   }
 }
 
@@ -2012,7 +2023,6 @@
                                  index,
                                  child_obj,
                                  child_entry);
-    known_references_.Insert(child_obj);
   }
 }
 
@@ -2020,7 +2030,8 @@
 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
                                           HeapEntry* parent_entry,
                                           const char* reference_name,
-                                          Object* child_obj) {
+                                          Object* child_obj,
+                                          int field_offset) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
     filler_->SetNamedReference(HeapGraphEdge::kInternal,
@@ -2029,7 +2040,7 @@
                                reference_name,
                                child_obj,
                                child_entry);
-    known_references_.Insert(child_obj);
+    IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
   }
 }
 
@@ -2037,16 +2048,17 @@
 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
                                           HeapEntry* parent_entry,
                                           int index,
-                                          Object* child_obj) {
+                                          Object* child_obj,
+                                          int field_offset) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
     filler_->SetNamedReference(HeapGraphEdge::kInternal,
                                parent_obj,
                                parent_entry,
-                               collection_->GetName(index),
+                               collection_->names()->GetName(index),
                                child_obj,
                                child_entry);
-    known_references_.Insert(child_obj);
+    IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
   }
 }
 
@@ -2070,7 +2082,8 @@
 void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
                                           HeapEntry* parent_entry,
                                           String* reference_name,
-                                          Object* child_obj) {
+                                          Object* child_obj,
+                                          int field_offset) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
     HeapGraphEdge::Type type = reference_name->length() > 0 ?
@@ -2078,25 +2091,24 @@
     filler_->SetNamedReference(type,
                                parent_obj,
                                parent_entry,
-                               collection_->GetName(reference_name),
+                               collection_->names()->GetName(reference_name),
                                child_obj,
                                child_entry);
-    known_references_.Insert(child_obj);
+    IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
   }
 }
 
 
-void V8HeapExplorer::SetPropertyShortcutReference(
-    HeapObject* parent_obj,
-    HeapEntry* parent_entry,
-    String* reference_name,
-    Object* child_obj) {
+void V8HeapExplorer::SetPropertyShortcutReference(HeapObject* parent_obj,
+                                                  HeapEntry* parent_entry,
+                                                  String* reference_name,
+                                                  Object* child_obj) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
     filler_->SetNamedReference(HeapGraphEdge::kShortcut,
                                parent_obj,
                                parent_entry,
-                               collection_->GetName(reference_name),
+                               collection_->names()->GetName(reference_name),
                                child_obj,
                                child_entry);
   }
@@ -2132,25 +2144,217 @@
 }
 
 
+class GlobalHandlesExtractor : public ObjectVisitor {
+ public:
+  explicit GlobalHandlesExtractor(NativeObjectsExplorer* explorer)
+      : explorer_(explorer) {}
+  virtual ~GlobalHandlesExtractor() {}
+  virtual void VisitPointers(Object** start, Object** end) {
+    UNREACHABLE();
+  }
+  virtual void VisitEmbedderReference(Object** p, uint16_t class_id) {
+    explorer_->VisitSubtreeWrapper(p, class_id);
+  }
+ private:
+  NativeObjectsExplorer* explorer_;
+};
+
+HeapThing const NativeObjectsExplorer::kNativesRootObject =
+    reinterpret_cast<HeapThing>(
+        static_cast<intptr_t>(HeapObjectsMap::kNativesRootObjectId));
+
+
+NativeObjectsExplorer::NativeObjectsExplorer(
+    HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress)
+    : snapshot_(snapshot),
+      collection_(snapshot_->collection()),
+      progress_(progress),
+      embedder_queried_(false),
+      objects_by_info_(RetainedInfosMatch),
+      filler_(NULL) {
+}
+
+
+NativeObjectsExplorer::~NativeObjectsExplorer() {
+  for (HashMap::Entry* p = objects_by_info_.Start();
+       p != NULL;
+       p = objects_by_info_.Next(p)) {
+    v8::RetainedObjectInfo* info =
+        reinterpret_cast<v8::RetainedObjectInfo*>(p->key);
+    info->Dispose();
+    List<HeapObject*>* objects =
+        reinterpret_cast<List<HeapObject*>* >(p->value);
+    delete objects;
+  }
+}
+
+
+HeapEntry* NativeObjectsExplorer::AllocateEntry(
+    HeapThing ptr, int children_count, int retainers_count) {
+  if (ptr == kNativesRootObject) {
+    return snapshot_->AddNativesRootEntry(children_count, retainers_count);
+  } else {
+    v8::RetainedObjectInfo* info =
+        reinterpret_cast<v8::RetainedObjectInfo*>(ptr);
+    intptr_t elements = info->GetElementCount();
+    intptr_t size = info->GetSizeInBytes();
+    return snapshot_->AddEntry(
+        HeapEntry::kNative,
+        elements != -1 ?
+            collection_->names()->GetFormatted(
+                "%s / %" V8_PTR_PREFIX "d entries",
+                info->GetLabel(),
+                info->GetElementCount()) :
+                collection_->names()->GetCopy(info->GetLabel()),
+        HeapObjectsMap::GenerateId(info),
+        size != -1 ? static_cast<int>(size) : 0,
+        children_count,
+        retainers_count);
+  }
+}
+
+
+void NativeObjectsExplorer::AddRootEntries(SnapshotFillerInterface* filler) {
+  if (EstimateObjectsCount() <= 0) return;
+  filler->AddEntry(kNativesRootObject, this);
+}
+
+
+int NativeObjectsExplorer::EstimateObjectsCount() {
+  FillRetainedObjects();
+  return objects_by_info_.occupancy();
+}
+
+
+void NativeObjectsExplorer::FillRetainedObjects() {
+  if (embedder_queried_) return;
+  Isolate* isolate = Isolate::Current();
+  // Record objects that are joined into ObjectGroups.
+  isolate->heap()->CallGlobalGCPrologueCallback();
+  List<ObjectGroup*>* groups = isolate->global_handles()->object_groups();
+  for (int i = 0; i < groups->length(); ++i) {
+    ObjectGroup* group = groups->at(i);
+    if (group->info_ == NULL) continue;
+    List<HeapObject*>* list = GetListMaybeDisposeInfo(group->info_);
+    for (int j = 0; j < group->objects_.length(); ++j) {
+      HeapObject* obj = HeapObject::cast(*group->objects_[j]);
+      list->Add(obj);
+      in_groups_.Insert(obj);
+    }
+    group->info_ = NULL;  // Acquire info object ownership.
+  }
+  isolate->global_handles()->RemoveObjectGroups();
+  isolate->heap()->CallGlobalGCEpilogueCallback();
+  // Record objects that are not in ObjectGroups, but have class ID.
+  GlobalHandlesExtractor extractor(this);
+  isolate->global_handles()->IterateAllRootsWithClassIds(&extractor);
+  embedder_queried_ = true;
+}
+
+
+List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo(
+    v8::RetainedObjectInfo* info) {
+  HashMap::Entry* entry =
+      objects_by_info_.Lookup(info, InfoHash(info), true);
+  if (entry->value != NULL) {
+    info->Dispose();
+  } else {
+    entry->value = new List<HeapObject*>(4);
+  }
+  return reinterpret_cast<List<HeapObject*>* >(entry->value);
+}
+
+
+bool NativeObjectsExplorer::IterateAndExtractReferences(
+    SnapshotFillerInterface* filler) {
+  if (EstimateObjectsCount() <= 0) return true;
+  filler_ = filler;
+  FillRetainedObjects();
+  for (HashMap::Entry* p = objects_by_info_.Start();
+       p != NULL;
+       p = objects_by_info_.Next(p)) {
+    v8::RetainedObjectInfo* info =
+        reinterpret_cast<v8::RetainedObjectInfo*>(p->key);
+    SetNativeRootReference(info);
+    List<HeapObject*>* objects =
+        reinterpret_cast<List<HeapObject*>* >(p->value);
+    for (int i = 0; i < objects->length(); ++i) {
+      SetWrapperNativeReferences(objects->at(i), info);
+    }
+  }
+  SetRootNativesRootReference();
+  filler_ = NULL;
+  return true;
+}
+
+
+void NativeObjectsExplorer::SetNativeRootReference(
+    v8::RetainedObjectInfo* info) {
+  HeapEntry* child_entry = filler_->FindOrAddEntry(info, this);
+  ASSERT(child_entry != NULL);
+  filler_->SetIndexedAutoIndexReference(
+      HeapGraphEdge::kElement,
+      kNativesRootObject, snapshot_->natives_root(),
+      info, child_entry);
+}
+
+
+void NativeObjectsExplorer::SetWrapperNativeReferences(
+    HeapObject* wrapper, v8::RetainedObjectInfo* info) {
+  HeapEntry* wrapper_entry = filler_->FindEntry(wrapper);
+  ASSERT(wrapper_entry != NULL);
+  HeapEntry* info_entry = filler_->FindOrAddEntry(info, this);
+  ASSERT(info_entry != NULL);
+  filler_->SetNamedReference(HeapGraphEdge::kInternal,
+                             wrapper, wrapper_entry,
+                             "Native",
+                             info, info_entry);
+  filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
+                                        info, info_entry,
+                                        wrapper, wrapper_entry);
+}
+
+
+void NativeObjectsExplorer::SetRootNativesRootReference() {
+  filler_->SetIndexedAutoIndexReference(
+      HeapGraphEdge::kElement,
+      V8HeapExplorer::kInternalRootObject, snapshot_->root(),
+      kNativesRootObject, snapshot_->natives_root());
+}
+
+
+void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) {
+  if (in_groups_.Contains(*p)) return;
+  Isolate* isolate = Isolate::Current();
+  v8::RetainedObjectInfo* info =
+      isolate->heap_profiler()->ExecuteWrapperClassCallback(class_id, p);
+  if (info == NULL) return;
+  GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p));
+}
+
+
 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot,
                                              v8::ActivityControl* control)
     : snapshot_(snapshot),
       control_(control),
-      v8_heap_explorer_(snapshot_, this) {
+      v8_heap_explorer_(snapshot_, this),
+      dom_explorer_(snapshot_, this) {
 }
 
 
 class SnapshotCounter : public SnapshotFillerInterface {
  public:
-  SnapshotCounter(HeapEntriesAllocator* allocator, HeapEntriesMap* entries)
-      : allocator_(allocator), entries_(entries) { }
-  HeapEntry* AddEntry(HeapThing ptr) {
-    entries_->Pair(ptr, allocator_, HeapEntriesMap::kHeapEntryPlaceholder);
+  explicit SnapshotCounter(HeapEntriesMap* entries) : entries_(entries) { }
+  HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
+    entries_->Pair(ptr, allocator, HeapEntriesMap::kHeapEntryPlaceholder);
     return HeapEntriesMap::kHeapEntryPlaceholder;
   }
-  HeapEntry* FindOrAddEntry(HeapThing ptr) {
-    HeapEntry* entry = entries_->Map(ptr);
-    return entry != NULL ? entry : AddEntry(ptr);
+  HeapEntry* FindEntry(HeapThing ptr) {
+    return entries_->Map(ptr);
+  }
+  HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
+    HeapEntry* entry = FindEntry(ptr);
+    return entry != NULL ? entry : AddEntry(ptr, allocator);
   }
   void SetIndexedReference(HeapGraphEdge::Type,
                            HeapThing parent_ptr,
@@ -2183,7 +2387,6 @@
     entries_->CountReference(parent_ptr, child_ptr);
   }
  private:
-  HeapEntriesAllocator* allocator_;
   HeapEntriesMap* entries_;
 };
 
@@ -2194,13 +2397,16 @@
       : snapshot_(snapshot),
         collection_(snapshot->collection()),
         entries_(entries) { }
-  HeapEntry* AddEntry(HeapThing ptr) {
+  HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
     UNREACHABLE();
     return NULL;
   }
-  HeapEntry* FindOrAddEntry(HeapThing ptr) {
-    HeapEntry* entry = entries_->Map(ptr);
-    return entry != NULL ? entry : AddEntry(ptr);
+  HeapEntry* FindEntry(HeapThing ptr) {
+    return entries_->Map(ptr);
+  }
+  HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
+    HeapEntry* entry = FindEntry(ptr);
+    return entry != NULL ? entry : AddEntry(ptr, allocator);
   }
   void SetIndexedReference(HeapGraphEdge::Type type,
                            HeapThing parent_ptr,
@@ -2247,7 +2453,7 @@
         parent_ptr, child_ptr, &child_index, &retainer_index);
     parent_entry->SetNamedReference(type,
                               child_index,
-                              collection_->GetName(child_index + 1),
+                              collection_->names()->GetName(child_index + 1),
                               child_entry,
                               retainer_index);
   }
@@ -2303,21 +2509,28 @@
 
 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) {
   if (control_ == NULL) return;
-  progress_total_ = v8_heap_explorer_.EstimateObjectsCount() * iterations_count;
+  progress_total_ = (
+      v8_heap_explorer_.EstimateObjectsCount() +
+      dom_explorer_.EstimateObjectsCount()) * iterations_count;
   progress_counter_ = 0;
 }
 
 
 bool HeapSnapshotGenerator::CountEntriesAndReferences() {
-  SnapshotCounter counter(&v8_heap_explorer_, &entries_);
+  SnapshotCounter counter(&entries_);
   v8_heap_explorer_.AddRootEntries(&counter);
-  return v8_heap_explorer_.IterateAndExtractReferences(&counter);
+  dom_explorer_.AddRootEntries(&counter);
+  return
+      v8_heap_explorer_.IterateAndExtractReferences(&counter) &&
+      dom_explorer_.IterateAndExtractReferences(&counter);
 }
 
 
 bool HeapSnapshotGenerator::FillReferences() {
   SnapshotFiller filler(snapshot_, &entries_);
-  return v8_heap_explorer_.IterateAndExtractReferences(&filler);
+  return
+      v8_heap_explorer_.IterateAndExtractReferences(&filler) &&
+      dom_explorer_.IterateAndExtractReferences(&filler);
 }
 
 
@@ -2447,83 +2660,6 @@
 }
 
 
-void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) {
-  raw_additions_root_ =
-      NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0));
-  additions_root()->Init(
-      snapshot2_, HeapEntry::kHidden, "", 0, 0, additions_count, 0);
-  raw_deletions_root_ =
-      NewArray<char>(HeapEntry::EntriesSize(1, deletions_count, 0));
-  deletions_root()->Init(
-      snapshot1_, HeapEntry::kHidden, "", 0, 0, deletions_count, 0);
-}
-
-
-static void DeleteHeapSnapshotsDiff(HeapSnapshotsDiff** diff_ptr) {
-  delete *diff_ptr;
-}
-
-HeapSnapshotsComparator::~HeapSnapshotsComparator() {
-  diffs_.Iterate(DeleteHeapSnapshotsDiff);
-}
-
-
-HeapSnapshotsDiff* HeapSnapshotsComparator::Compare(HeapSnapshot* snapshot1,
-                                                    HeapSnapshot* snapshot2) {
-  snapshot1->ClearPaint();
-  snapshot1->root()->PaintAllReachable();
-  snapshot2->ClearPaint();
-  snapshot2->root()->PaintAllReachable();
-
-  List<HeapEntry*>* entries1 = snapshot1->GetSortedEntriesList();
-  List<HeapEntry*>* entries2 = snapshot2->GetSortedEntriesList();
-  int i = 0, j = 0;
-  List<HeapEntry*> added_entries, deleted_entries;
-  while (i < entries1->length() && j < entries2->length()) {
-    uint64_t id1 = entries1->at(i)->id();
-    uint64_t id2 = entries2->at(j)->id();
-    if (id1 == id2) {
-      HeapEntry* entry1 = entries1->at(i++);
-      HeapEntry* entry2 = entries2->at(j++);
-      if (entry1->painted_reachable() != entry2->painted_reachable()) {
-        if (entry1->painted_reachable())
-          deleted_entries.Add(entry1);
-        else
-          added_entries.Add(entry2);
-      }
-    } else if (id1 < id2) {
-      HeapEntry* entry = entries1->at(i++);
-      deleted_entries.Add(entry);
-    } else {
-      HeapEntry* entry = entries2->at(j++);
-      added_entries.Add(entry);
-    }
-  }
-  while (i < entries1->length()) {
-    HeapEntry* entry = entries1->at(i++);
-    deleted_entries.Add(entry);
-  }
-  while (j < entries2->length()) {
-    HeapEntry* entry = entries2->at(j++);
-    added_entries.Add(entry);
-  }
-
-  HeapSnapshotsDiff* diff = new HeapSnapshotsDiff(snapshot1, snapshot2);
-  diffs_.Add(diff);
-  diff->CreateRoots(added_entries.length(), deleted_entries.length());
-
-  for (int i = 0; i < deleted_entries.length(); ++i) {
-    HeapEntry* entry = deleted_entries[i];
-    diff->AddDeletedEntry(i, i + 1, entry);
-  }
-  for (int i = 0; i < added_entries.length(); ++i) {
-    HeapEntry* entry = added_entries[i];
-    diff->AddAddedEntry(i, i + 1, entry);
-  }
-  return diff;
-}
-
-
 class OutputStreamWriter {
  public:
   explicit OutputStreamWriter(v8::OutputStream* stream)
@@ -2735,7 +2871,8 @@
             "," JSON_S("code")
             "," JSON_S("closure")
             "," JSON_S("regexp")
-            "," JSON_S("number"))
+            "," JSON_S("number")
+            "," JSON_S("native"))
         "," JSON_S("string")
         "," JSON_S("number")
         "," JSON_S("number")
@@ -2890,7 +3027,7 @@
 
 
 String* GetConstructorNameForHeapProfile(JSObject* object) {
-  if (object->IsJSFunction()) return Heap::closure_symbol();
+  if (object->IsJSFunction()) return HEAP->closure_symbol();
   return object->constructor_name();
 }
 
diff --git a/src/profile-generator.h b/src/profile-generator.h
index 4762eb6..377c083 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -66,6 +66,9 @@
   StringsStorage();
   ~StringsStorage();
 
+  const char* GetCopy(const char* src);
+  const char* GetFormatted(const char* format, ...);
+  const char* GetVFormatted(const char* format, va_list args);
   const char* GetName(String* name);
   const char* GetName(int index);
   inline const char* GetFunctionName(String* name);
@@ -76,11 +79,10 @@
     return strcmp(reinterpret_cast<char*>(key1),
                   reinterpret_cast<char*>(key2)) == 0;
   }
+  const char* AddOrDisposeString(char* str, uint32_t hash);
 
   // Mapping of strings by String::Hash to const char* strings.
   HashMap names_;
-  // Mapping from ints to char* strings.
-  List<char*> index_names_;
 
   DISALLOW_COPY_AND_ASSIGN(StringsStorage);
 };
@@ -112,7 +114,7 @@
   uint32_t GetCallUid() const;
   bool IsSameAs(CodeEntry* entry) const;
 
-  static const char* kEmptyNamePrefix;
+  static const char* const kEmptyNamePrefix;
 
  private:
   Logger::LogEventsAndTags tag_;
@@ -236,12 +238,12 @@
 
 class CodeMap {
  public:
-  CodeMap() : next_sfi_tag_(1) { }
+  CodeMap() : next_shared_id_(1) { }
   INLINE(void AddCode(Address addr, CodeEntry* entry, unsigned size));
   INLINE(void MoveCode(Address from, Address to));
   INLINE(void DeleteCode(Address addr));
   CodeEntry* FindEntry(Address addr);
-  int GetSFITag(Address addr);
+  int GetSharedId(Address addr);
 
   void Print();
 
@@ -269,11 +271,11 @@
     void Call(const Address& key, const CodeEntryInfo& value);
   };
 
-  // Fake CodeEntry pointer to distinguish SFI entries.
-  static CodeEntry* const kSfiCodeEntry;
+  // Fake CodeEntry pointer to distinguish shared function entries.
+  static CodeEntry* const kSharedFunctionCodeEntry;
 
   CodeTree tree_;
-  int next_sfi_tag_;
+  int next_shared_id_;
 
   DISALLOW_COPY_AND_ASSIGN(CodeMap);
 };
@@ -298,6 +300,8 @@
   }
   CpuProfile* GetProfile(int security_token_id, unsigned uid);
   bool IsLastProfile(const char* title);
+  void RemoveProfile(CpuProfile* profile);
+  bool HasDetachedProfiles() { return detached_profiles_.length() > 0; }
 
   CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
                           String* name, String* resource_name, int line_number);
@@ -320,6 +324,7 @@
   const char* GetFunctionName(const char* name) {
     return function_and_resource_names_.GetFunctionName(name);
   }
+  int GetProfileIndex(unsigned uid);
   List<CpuProfile*>* GetProfilesList(int security_token_id);
   int TokenToIndex(int security_token_id);
 
@@ -333,6 +338,7 @@
   // Mapping from profiles' uids to indexes in the second nested list
   // of profiles_by_token_.
   HashMap profiles_uids_;
+  List<CpuProfile*> detached_profiles_;
 
   // Accessed by VM thread and profile generator thread.
   List<CpuProfile*> current_profiles_;
@@ -420,9 +426,9 @@
     return sample_rate_calc_.ticks_per_ms();
   }
 
-  static const char* kAnonymousFunctionName;
-  static const char* kProgramEntryName;
-  static const char* kGarbageCollectorEntryName;
+  static const char* const kAnonymousFunctionName;
+  static const char* const kProgramEntryName;
+  static const char* const kGarbageCollectorEntryName;
 
  private:
   INLINE(CodeEntry* EntryForVMState(StateTag tag));
@@ -484,8 +490,6 @@
 };
 
 
-class CachedHeapGraphPath;
-class HeapGraphPath;
 class HeapSnapshot;
 
 // HeapEntry instances represent an entity from the heap (or a special
@@ -517,7 +521,8 @@
     kCode = v8::HeapGraphNode::kCode,
     kClosure = v8::HeapGraphNode::kClosure,
     kRegExp = v8::HeapGraphNode::kRegExp,
-    kHeapNumber = v8::HeapGraphNode::kHeapNumber
+    kHeapNumber = v8::HeapGraphNode::kHeapNumber,
+    kNative = v8::HeapGraphNode::kNative
   };
 
   HeapEntry() { }
@@ -544,7 +549,6 @@
     return Vector<HeapGraphEdge>(children_arr(), children_count_); }
   Vector<HeapGraphEdge*> retainers() {
     return Vector<HeapGraphEdge*>(retainers_arr(), retainers_count_); }
-  List<HeapGraphPath*>* GetRetainingPaths();
   HeapEntry* dominator() { return dominator_; }
   void set_dominator(HeapEntry* entry) { dominator_ = entry; }
 
@@ -578,18 +582,12 @@
 
   int EntrySize() { return EntriesSize(1, children_count_, retainers_count_); }
   int RetainedSize(bool exact);
-  List<HeapGraphPath*>* CalculateRetainingPaths();
 
   void Print(int max_depth, int indent);
 
   static int EntriesSize(int entries_count,
                          int children_count,
                          int retainers_count);
-  static uint32_t Hash(HeapEntry* entry) {
-    return ComputeIntegerHash(
-        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(entry)));
-  }
-  static bool Match(void* entry1, void* entry2) { return entry1 == entry2; }
 
  private:
   HeapGraphEdge* children_arr() {
@@ -599,13 +597,11 @@
     return reinterpret_cast<HeapGraphEdge**>(children_arr() + children_count_);
   }
   void CalculateExactRetainedSize();
-  void FindRetainingPaths(CachedHeapGraphPath* prev_path,
-                          List<HeapGraphPath*>* retaining_paths);
   const char* TypeAsString();
 
   unsigned painted_: 2;
-  unsigned type_: 3;
-  int children_count_: 27;
+  unsigned type_: 4;
+  int children_count_: 26;
   int retainers_count_;
   int self_size_;
   union {
@@ -631,27 +627,7 @@
 };
 
 
-class HeapGraphPath {
- public:
-  HeapGraphPath()
-      : path_(8) { }
-  explicit HeapGraphPath(const List<HeapGraphEdge*>& path);
-
-  void Add(HeapGraphEdge* edge) { path_.Add(edge); }
-  void Set(int index, HeapGraphEdge* edge) { path_[index] = edge; }
-  const List<HeapGraphEdge*>* path() { return &path_; }
-
-  void Print();
-
- private:
-  List<HeapGraphEdge*> path_;
-
-  DISALLOW_COPY_AND_ASSIGN(HeapGraphPath);
-};
-
-
 class HeapSnapshotsCollection;
-class HeapSnapshotsDiff;
 
 // HeapSnapshot represents a single heap snapshot. It is stored in
 // HeapSnapshotsCollection, which is also a factory for
@@ -670,6 +646,7 @@
                const char* title,
                unsigned uid);
   ~HeapSnapshot();
+  void Delete();
 
   HeapSnapshotsCollection* collection() { return collection_; }
   Type type() { return type_; }
@@ -677,6 +654,7 @@
   unsigned uid() { return uid_; }
   HeapEntry* root() { return root_entry_; }
   HeapEntry* gc_roots() { return gc_roots_entry_; }
+  HeapEntry* natives_root() { return natives_root_entry_; }
   List<HeapEntry*>* entries() { return &entries_; }
 
   void AllocateEntries(
@@ -689,10 +667,9 @@
                       int retainers_count);
   HeapEntry* AddRootEntry(int children_count);
   HeapEntry* AddGcRootsEntry(int children_count, int retainers_count);
+  HeapEntry* AddNativesRootEntry(int children_count, int retainers_count);
   void ClearPaint();
-  HeapSnapshotsDiff* CompareWith(HeapSnapshot* snapshot);
   HeapEntry* GetEntryById(uint64_t id);
-  List<HeapGraphPath*>* GetRetainingPaths(HeapEntry* entry);
   List<HeapEntry*>* GetSortedEntriesList();
   template<class Visitor>
   void IterateEntries(Visitor* visitor) { entries_.Iterate(visitor); }
@@ -710,10 +687,10 @@
   unsigned uid_;
   HeapEntry* root_entry_;
   HeapEntry* gc_roots_entry_;
+  HeapEntry* natives_root_entry_;
   char* raw_entries_;
   List<HeapEntry*> entries_;
   bool entries_sorted_;
-  HashMap retaining_paths_;
 #ifdef DEBUG
   int raw_entries_size_;
 #endif
@@ -733,8 +710,11 @@
   uint64_t FindObject(Address addr);
   void MoveObject(Address from, Address to);
 
+  static uint64_t GenerateId(v8::RetainedObjectInfo* info);
+
   static const uint64_t kInternalRootObjectId;
   static const uint64_t kGcRootsObjectId;
+  static const uint64_t kNativesRootObjectId;
   static const uint64_t kFirstAvailableObjectId;
 
  private:
@@ -767,58 +747,6 @@
 };
 
 
-class HeapSnapshotsDiff {
- public:
-  HeapSnapshotsDiff(HeapSnapshot* snapshot1, HeapSnapshot* snapshot2)
-      : snapshot1_(snapshot1),
-        snapshot2_(snapshot2),
-        raw_additions_root_(NULL),
-        raw_deletions_root_(NULL) { }
-
-  ~HeapSnapshotsDiff() {
-    DeleteArray(raw_deletions_root_);
-    DeleteArray(raw_additions_root_);
-  }
-
-  void AddAddedEntry(int child_index, int index, HeapEntry* entry) {
-    additions_root()->SetUnidirElementReference(child_index, index, entry);
-  }
-
-  void AddDeletedEntry(int child_index, int index, HeapEntry* entry) {
-    deletions_root()->SetUnidirElementReference(child_index, index, entry);
-  }
-
-  void CreateRoots(int additions_count, int deletions_count);
-
-  HeapEntry* additions_root() {
-    return reinterpret_cast<HeapEntry*>(raw_additions_root_);
-  }
-  HeapEntry* deletions_root() {
-    return reinterpret_cast<HeapEntry*>(raw_deletions_root_);
-  }
-
- private:
-  HeapSnapshot* snapshot1_;
-  HeapSnapshot* snapshot2_;
-  char* raw_additions_root_;
-  char* raw_deletions_root_;
-
-  DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsDiff);
-};
-
-
-class HeapSnapshotsComparator {
- public:
-  HeapSnapshotsComparator() { }
-  ~HeapSnapshotsComparator();
-  HeapSnapshotsDiff* Compare(HeapSnapshot* snapshot1, HeapSnapshot* snapshot2);
- private:
-  List<HeapSnapshotsDiff*> diffs_;
-
-  DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsComparator);
-};
-
-
 class HeapSnapshotsCollection {
  public:
   HeapSnapshotsCollection();
@@ -831,21 +759,14 @@
   void SnapshotGenerationFinished(HeapSnapshot* snapshot);
   List<HeapSnapshot*>* snapshots() { return &snapshots_; }
   HeapSnapshot* GetSnapshot(unsigned uid);
+  void RemoveSnapshot(HeapSnapshot* snapshot);
 
-  const char* GetName(String* name) { return names_.GetName(name); }
-  const char* GetName(int index) { return names_.GetName(index); }
-  const char* GetFunctionName(String* name) {
-    return names_.GetFunctionName(name);
-  }
-
+  StringsStorage* names() { return &names_; }
   TokenEnumerator* token_enumerator() { return token_enumerator_; }
 
   uint64_t GetObjectId(Address addr) { return ids_.FindObject(addr); }
   void ObjectMoveEvent(Address from, Address to) { ids_.MoveObject(from, to); }
 
-  HeapSnapshotsDiff* CompareSnapshots(HeapSnapshot* snapshot1,
-                                      HeapSnapshot* snapshot2);
-
  private:
   INLINE(static bool HeapSnapshotsMatch(void* key1, void* key2)) {
     return key1 == key2;
@@ -859,7 +780,6 @@
   TokenEnumerator* token_enumerator_;
   // Mapping from HeapObject addresses to objects' uids.
   HeapObjectsMap ids_;
-  HeapSnapshotsComparator comparator_;
 
   DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsCollection);
 };
@@ -950,8 +870,11 @@
 class SnapshotFillerInterface {
  public:
   virtual ~SnapshotFillerInterface() { }
-  virtual HeapEntry* AddEntry(HeapThing ptr) = 0;
-  virtual HeapEntry* FindOrAddEntry(HeapThing ptr) = 0;
+  virtual HeapEntry* AddEntry(HeapThing ptr,
+                              HeapEntriesAllocator* allocator) = 0;
+  virtual HeapEntry* FindEntry(HeapThing ptr) = 0;
+  virtual HeapEntry* FindOrAddEntry(HeapThing ptr,
+                                    HeapEntriesAllocator* allocator) = 0;
   virtual void SetIndexedReference(HeapGraphEdge::Type type,
                                    HeapThing parent_ptr,
                                    HeapEntry* parent_entry,
@@ -990,13 +913,15 @@
  public:
   V8HeapExplorer(HeapSnapshot* snapshot,
                  SnapshottingProgressReportingInterface* progress);
-  ~V8HeapExplorer();
+  virtual ~V8HeapExplorer();
   virtual HeapEntry* AllocateEntry(
       HeapThing ptr, int children_count, int retainers_count);
   void AddRootEntries(SnapshotFillerInterface* filler);
   int EstimateObjectsCount();
   bool IterateAndExtractReferences(SnapshotFillerInterface* filler);
 
+  static HeapObject* const kInternalRootObject;
+
  private:
   HeapEntry* AddEntry(
       HeapObject* object, int children_count, int retainers_count);
@@ -1021,11 +946,13 @@
   void SetInternalReference(HeapObject* parent_obj,
                             HeapEntry* parent,
                             const char* reference_name,
-                            Object* child);
+                            Object* child,
+                            int field_offset = -1);
   void SetInternalReference(HeapObject* parent_obj,
                             HeapEntry* parent,
                             int index,
-                            Object* child);
+                            Object* child,
+                            int field_offset = -1);
   void SetHiddenReference(HeapObject* parent_obj,
                           HeapEntry* parent,
                           int index,
@@ -1033,7 +960,8 @@
   void SetPropertyReference(HeapObject* parent_obj,
                             HeapEntry* parent,
                             String* reference_name,
-                            Object* child);
+                            Object* child,
+                            int field_offset = -1);
   void SetPropertyShortcutReference(HeapObject* parent_obj,
                                     HeapEntry* parent,
                                     String* reference_name,
@@ -1047,12 +975,8 @@
   HeapSnapshot* snapshot_;
   HeapSnapshotsCollection* collection_;
   SnapshottingProgressReportingInterface* progress_;
-  // Used during references extraction to mark heap objects that
-  // are references via non-hidden properties.
-  HeapObjectsSet known_references_;
   SnapshotFillerInterface* filler_;
 
-  static HeapObject* const kInternalRootObject;
   static HeapObject* const kGcRootsObject;
 
   friend class IndexedReferencesExtractor;
@@ -1062,6 +986,54 @@
 };
 
 
+// An implementation of retained native objects extractor.
+class NativeObjectsExplorer : public HeapEntriesAllocator {
+ public:
+  NativeObjectsExplorer(HeapSnapshot* snapshot,
+                      SnapshottingProgressReportingInterface* progress);
+  virtual ~NativeObjectsExplorer();
+  virtual HeapEntry* AllocateEntry(
+      HeapThing ptr, int children_count, int retainers_count);
+  void AddRootEntries(SnapshotFillerInterface* filler);
+  int EstimateObjectsCount();
+  bool IterateAndExtractReferences(SnapshotFillerInterface* filler);
+
+ private:
+  void FillRetainedObjects();
+  List<HeapObject*>* GetListMaybeDisposeInfo(v8::RetainedObjectInfo* info);
+  void SetNativeRootReference(v8::RetainedObjectInfo* info);
+  void SetRootNativesRootReference();
+  void SetWrapperNativeReferences(HeapObject* wrapper,
+                                      v8::RetainedObjectInfo* info);
+  void VisitSubtreeWrapper(Object** p, uint16_t class_id);
+
+  static uint32_t InfoHash(v8::RetainedObjectInfo* info) {
+    return ComputeIntegerHash(static_cast<uint32_t>(info->GetHash()));
+  }
+  static bool RetainedInfosMatch(void* key1, void* key2) {
+    return key1 == key2 ||
+        (reinterpret_cast<v8::RetainedObjectInfo*>(key1))->IsEquivalent(
+            reinterpret_cast<v8::RetainedObjectInfo*>(key2));
+  }
+
+  HeapSnapshot* snapshot_;
+  HeapSnapshotsCollection* collection_;
+  SnapshottingProgressReportingInterface* progress_;
+  bool embedder_queried_;
+  HeapObjectsSet in_groups_;
+  // RetainedObjectInfo* -> List<HeapObject*>*
+  HashMap objects_by_info_;
+  // Used during references extraction.
+  SnapshotFillerInterface* filler_;
+
+  static HeapThing const kNativesRootObject;
+
+  friend class GlobalHandlesExtractor;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeObjectsExplorer);
+};
+
+
 class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface {
  public:
   HeapSnapshotGenerator(HeapSnapshot* snapshot,
@@ -1083,6 +1055,7 @@
   HeapSnapshot* snapshot_;
   v8::ActivityControl* control_;
   V8HeapExplorer v8_heap_explorer_;
+  NativeObjectsExplorer dom_explorer_;
   // Mapping from HeapThing pointers to HeapEntry* pointers.
   HeapEntriesMap entries_;
   // Used during snapshot generation.
diff --git a/src/property.cc b/src/property.cc
index 9677433..c35fb83 100644
--- a/src/property.cc
+++ b/src/property.cc
@@ -52,6 +52,12 @@
       GetTransitionMap()->Print(out);
       PrintF(out, "\n");
       break;
+    case EXTERNAL_ARRAY_TRANSITION:
+      PrintF(out, " -type = external array transition\n");
+      PrintF(out, " -map:\n");
+      GetTransitionMap()->Print(out);
+      PrintF(out, "\n");
+      break;
     case CONSTANT_FUNCTION:
       PrintF(out, " -type = constant function\n");
       PrintF(out, " -function:\n");
diff --git a/src/property.h b/src/property.h
index c39fe41..fa3916e 100644
--- a/src/property.h
+++ b/src/property.h
@@ -48,7 +48,7 @@
   MUST_USE_RESULT MaybeObject* KeyToSymbol() {
     if (!StringShape(key_).IsSymbol()) {
       Object* result;
-      { MaybeObject* maybe_result = Heap::LookupSymbol(key_);
+      { MaybeObject* maybe_result = HEAP->LookupSymbol(key_);
         if (!maybe_result->ToObject(&result)) return maybe_result;
       }
       key_ = String::cast(result);
@@ -110,6 +110,16 @@
       : Descriptor(key, map, attributes, MAP_TRANSITION) { }
 };
 
+class ExternalArrayTransitionDescriptor: public Descriptor {
+ public:
+  ExternalArrayTransitionDescriptor(String* key,
+                                    Map* map,
+                                    ExternalArrayType array_type)
+      : Descriptor(key, map, PropertyDetails(NONE,
+                                             EXTERNAL_ARRAY_TRANSITION,
+                                             array_type)) { }
+};
+
 // 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
@@ -262,7 +272,8 @@
 
   Map* GetTransitionMap() {
     ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
-    ASSERT(type() == MAP_TRANSITION || type() == CONSTANT_TRANSITION);
+    ASSERT(type() == MAP_TRANSITION || type() == CONSTANT_TRANSITION ||
+           type() == EXTERNAL_ARRAY_TRANSITION);
     return Map::cast(GetValue());
   }
 
@@ -305,7 +316,7 @@
   Object* GetCallbackObject() {
     if (lookup_type_ == CONSTANT_TYPE) {
       // For now we only have the __proto__ as constant type.
-      return Heap::prototype_accessors();
+      return HEAP->prototype_accessors();
     }
     return GetValue();
   }
diff --git a/src/regexp-macro-assembler-irregexp.cc b/src/regexp-macro-assembler-irregexp.cc
index 6fbb14a..d41a97c 100644
--- a/src/regexp-macro-assembler-irregexp.cc
+++ b/src/regexp-macro-assembler-irregexp.cc
@@ -438,7 +438,7 @@
 Handle<Object> RegExpMacroAssemblerIrregexp::GetCode(Handle<String> source) {
   Bind(&backtrack_);
   Emit(BC_POP_BT, 0);
-  Handle<ByteArray> array = Factory::NewByteArray(length());
+  Handle<ByteArray> array = FACTORY->NewByteArray(length());
   Copy(array->GetDataStartAddress());
   return array;
 }
diff --git a/src/regexp-macro-assembler.cc b/src/regexp-macro-assembler.cc
index 51f4015..ea41db6 100644
--- a/src/regexp-macro-assembler.cc
+++ b/src/regexp-macro-assembler.cc
@@ -105,7 +105,8 @@
     Handle<String> subject,
     int* offsets_vector,
     int offsets_vector_length,
-    int previous_index) {
+    int previous_index,
+    Isolate* isolate) {
 
   ASSERT(subject->IsFlat());
   ASSERT(previous_index >= 0);
@@ -142,7 +143,8 @@
                        start_offset,
                        input_start,
                        input_end,
-                       offsets_vector);
+                       offsets_vector,
+                       isolate);
   return res;
 }
 
@@ -153,10 +155,12 @@
     int start_offset,
     const byte* input_start,
     const byte* input_end,
-    int* output) {
+    int* output,
+    Isolate* isolate) {
+  ASSERT(isolate == Isolate::Current());
   // Ensure that the minimum stack has been allocated.
-  RegExpStack stack;
-  Address stack_base = RegExpStack::stack_base();
+  RegExpStackScope stack_scope(isolate);
+  Address stack_base = stack_scope.stack()->stack_base();
 
   int direct_call = 0;
   int result = CALL_GENERATED_REGEXP_CODE(code->entry(),
@@ -166,23 +170,21 @@
                                           input_end,
                                           output,
                                           stack_base,
-                                          direct_call);
+                                          direct_call,
+                                          isolate);
   ASSERT(result <= SUCCESS);
   ASSERT(result >= RETRY);
 
-  if (result == EXCEPTION && !Top::has_pending_exception()) {
+  if (result == EXCEPTION && !isolate->has_pending_exception()) {
     // We detected a stack overflow (on the backtrack stack) in RegExp code,
     // but haven't created the exception yet.
-    Top::StackOverflow();
+    isolate->StackOverflow();
   }
   return static_cast<Result>(result);
 }
 
 
-static unibrow::Mapping<unibrow::Ecma262Canonicalize> canonicalize;
-
-
-byte NativeRegExpMacroAssembler::word_character_map[] = {
+const byte NativeRegExpMacroAssembler::word_character_map[] = {
     0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
     0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
     0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
@@ -208,7 +210,11 @@
 int NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16(
     Address byte_offset1,
     Address byte_offset2,
-    size_t byte_length) {
+    size_t byte_length,
+    Isolate* isolate) {
+  ASSERT(isolate == Isolate::Current());
+  unibrow::Mapping<unibrow::Ecma262Canonicalize>* canonicalize =
+      isolate->regexp_macro_assembler_canonicalize();
   // 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.
@@ -222,10 +228,10 @@
     unibrow::uchar c2 = substring2[i];
     if (c1 != c2) {
       unibrow::uchar s1[1] = { c1 };
-      canonicalize.get(c1, '\0', s1);
+      canonicalize->get(c1, '\0', s1);
       if (s1[0] != c2) {
         unibrow::uchar s2[1] = { c2 };
-        canonicalize.get(c2, '\0', s2);
+        canonicalize->get(c2, '\0', s2);
         if (s1[0] != s2[0]) {
           return 0;
         }
@@ -237,13 +243,16 @@
 
 
 Address NativeRegExpMacroAssembler::GrowStack(Address stack_pointer,
-                                              Address* stack_base) {
-  size_t size = RegExpStack::stack_capacity();
-  Address old_stack_base = RegExpStack::stack_base();
+                                              Address* stack_base,
+                                              Isolate* isolate) {
+  ASSERT(isolate == Isolate::Current());
+  RegExpStack* regexp_stack = isolate->regexp_stack();
+  size_t size = regexp_stack->stack_capacity();
+  Address old_stack_base = regexp_stack->stack_base();
   ASSERT(old_stack_base == *stack_base);
   ASSERT(stack_pointer <= old_stack_base);
   ASSERT(static_cast<size_t>(old_stack_base - stack_pointer) <= size);
-  Address new_stack_base = RegExpStack::EnsureCapacity(size * 2);
+  Address new_stack_base = regexp_stack->EnsureCapacity(size * 2);
   if (new_stack_base == NULL) {
     return NULL;
   }
diff --git a/src/regexp-macro-assembler.h b/src/regexp-macro-assembler.h
index ef85d27..1268e78 100644
--- a/src/regexp-macro-assembler.h
+++ b/src/regexp-macro-assembler.h
@@ -48,6 +48,7 @@
   enum IrregexpImplementation {
     kIA32Implementation,
     kARMImplementation,
+    kMIPSImplementation,
     kX64Implementation,
     kBytecodeImplementation
   };
@@ -190,30 +191,33 @@
                       Handle<String> subject,
                       int* offsets_vector,
                       int offsets_vector_length,
-                      int previous_index);
+                      int previous_index,
+                      Isolate* isolate);
 
   // Compares two-byte strings case insensitively.
   // Called from generated RegExp code.
   static int CaseInsensitiveCompareUC16(Address byte_offset1,
                                         Address byte_offset2,
-                                        size_t byte_length);
+                                        size_t byte_length,
+                                        Isolate* isolate);
 
   // 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);
+  static Address GrowStack(Address stack_pointer, Address* stack_top,
+                           Isolate* isolate);
 
   static const byte* StringCharacterPosition(String* subject, int start_index);
 
   // Byte map of ASCII characters with a 0xff if the character is a word
   // character (digit, letter or underscore) and 0x00 otherwise.
   // Used by generated RegExp code.
-  static byte word_character_map[128];
+  static const byte word_character_map[128];
 
   static Address word_character_map_address() {
-    return &word_character_map[0];
+    return const_cast<Address>(&word_character_map[0]);
   }
 
   static Result Execute(Code* code,
@@ -221,7 +225,8 @@
                         int start_offset,
                         const byte* input_start,
                         const byte* input_end,
-                        int* output);
+                        int* output,
+                        Isolate* isolate);
 };
 
 #endif  // V8_INTERPRETED_REGEXP
diff --git a/src/regexp-stack.cc b/src/regexp-stack.cc
index 7696279..ff9547f 100644
--- a/src/regexp-stack.cc
+++ b/src/regexp-stack.cc
@@ -26,21 +26,31 @@
 // 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() {
+RegExpStackScope::RegExpStackScope(Isolate* isolate)
+    : regexp_stack_(isolate->regexp_stack()) {
   // Initialize, if not already initialized.
-  RegExpStack::EnsureCapacity(0);
+  regexp_stack_->EnsureCapacity(0);
+}
+
+
+RegExpStackScope::~RegExpStackScope() {
+  ASSERT(Isolate::Current() == regexp_stack_->isolate_);
+  // Reset the buffer if it has grown.
+  regexp_stack_->Reset();
+}
+
+
+RegExpStack::RegExpStack()
+    : isolate_(NULL) {
 }
 
 
 RegExpStack::~RegExpStack() {
-  // Reset the buffer if it has grown.
-  RegExpStack::Reset();
 }
 
 
@@ -70,9 +80,9 @@
 
 
 void RegExpStack::ThreadLocal::Free() {
-  if (thread_local_.memory_size_ > 0) {
-    DeleteArray(thread_local_.memory_);
-    thread_local_ = ThreadLocal();
+  if (memory_size_ > 0) {
+    DeleteArray(memory_);
+    Clear();
   }
 }
 
@@ -98,6 +108,4 @@
 }
 
 
-RegExpStack::ThreadLocal RegExpStack::thread_local_;
-
 }}  // namespace v8::internal
diff --git a/src/regexp-stack.h b/src/regexp-stack.h
index b4fa2e9..5943206 100644
--- a/src/regexp-stack.h
+++ b/src/regexp-stack.h
@@ -31,11 +31,30 @@
 namespace v8 {
 namespace internal {
 
+class RegExpStack;
+
 // 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 RegExpStackScope {
+ public:
+  // Create and delete an instance to control the life-time of a growing stack.
+
+  // Initializes the stack memory area if necessary.
+  explicit RegExpStackScope(Isolate* isolate);
+  ~RegExpStackScope();  // Releases the stack if it has grown.
+
+  RegExpStack* stack() const { return regexp_stack_; }
+
+ private:
+  RegExpStack* regexp_stack_;
+
+  DISALLOW_COPY_AND_ASSIGN(RegExpStackScope);
+};
+
+
 class RegExpStack {
  public:
   // Number of allocated locations on the stack below the limit.
@@ -43,39 +62,37 @@
   // 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_base() {
+  Address stack_base() {
     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_; }
+  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_); }
+  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);
+  Address EnsureCapacity(size_t size);
 
   // Thread local archiving.
   static int ArchiveSpacePerThread() {
-    return static_cast<int>(sizeof(thread_local_));
+    return static_cast<int>(sizeof(ThreadLocal));
   }
-  static char* ArchiveStack(char* to);
-  static char* RestoreStack(char* from);
-  static void FreeThreadResources() { thread_local_.Free(); }
-
+  char* ArchiveStack(char* to);
+  char* RestoreStack(char* from);
+  void FreeThreadResources() { thread_local_.Free(); }
  private:
+  RegExpStack();
+  ~RegExpStack();
+
   // Artificial limit used when no memory has been allocated.
   static const uintptr_t kMemoryTop = static_cast<uintptr_t>(-1);
 
@@ -87,35 +104,42 @@
 
   // Structure holding the allocated memory, size and limit.
   struct ThreadLocal {
-    ThreadLocal()
-        : memory_(NULL),
-          memory_size_(0),
-          limit_(reinterpret_cast<Address>(kMemoryTop)) {}
+    ThreadLocal() { Clear(); }
     // If memory_size_ > 0 then memory_ must be non-NULL.
     Address memory_;
     size_t memory_size_;
     Address limit_;
+    void Clear() {
+      memory_ = NULL;
+      memory_size_ = 0;
+      limit_ = reinterpret_cast<Address>(kMemoryTop);
+    }
     void Free();
   };
 
   // Address of allocated memory.
-  static Address memory_address() {
+  Address memory_address() {
     return reinterpret_cast<Address>(&thread_local_.memory_);
   }
 
   // Address of size of allocated memory.
-  static Address memory_size_address() {
+  Address memory_size_address() {
     return reinterpret_cast<Address>(&thread_local_.memory_size_);
   }
 
   // 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();
+  void Reset();
 
-  static ThreadLocal thread_local_;
+  ThreadLocal thread_local_;
+  Isolate* isolate_;
 
   friend class ExternalReference;
+  friend class Isolate;
+  friend class RegExpStackScope;
+
+  DISALLOW_COPY_AND_ASSIGN(RegExpStack);
 };
 
 }}  // namespace v8::internal
diff --git a/src/register-allocator-inl.h b/src/register-allocator-inl.h
index e0ea9e1..5a68ab0 100644
--- a/src/register-allocator-inl.h
+++ b/src/register-allocator-inl.h
@@ -63,14 +63,14 @@
 
 Result::~Result() {
   if (is_register()) {
-    CodeGeneratorScope::Current()->allocator()->Unuse(reg());
+    CodeGeneratorScope::Current(Isolate::Current())->allocator()->Unuse(reg());
   }
 }
 
 
 void Result::Unuse() {
   if (is_register()) {
-    CodeGeneratorScope::Current()->allocator()->Unuse(reg());
+    CodeGeneratorScope::Current(Isolate::Current())->allocator()->Unuse(reg());
   }
   invalidate();
 }
@@ -79,7 +79,7 @@
 void Result::CopyTo(Result* destination) const {
   destination->value_ = value_;
   if (is_register()) {
-    CodeGeneratorScope::Current()->allocator()->Use(reg());
+    CodeGeneratorScope::Current(Isolate::Current())->allocator()->Use(reg());
   }
 }
 
diff --git a/src/register-allocator.cc b/src/register-allocator.cc
index 31d0a49..cb5e35f 100644
--- a/src/register-allocator.cc
+++ b/src/register-allocator.cc
@@ -40,19 +40,13 @@
 
 Result::Result(Register reg, TypeInfo info) {
   ASSERT(reg.is_valid() && !RegisterAllocator::IsReserved(reg));
-  CodeGeneratorScope::Current()->allocator()->Use(reg);
+  CodeGeneratorScope::Current(Isolate::Current())->allocator()->Use(reg);
   value_ = TypeField::encode(REGISTER)
       | TypeInfoField::encode(info.ToInt())
       | DataField::encode(reg.code_);
 }
 
 
-Result::ZoneObjectList* Result::ConstantList() {
-  static ZoneObjectList list(10);
-  return &list;
-}
-
-
 // -------------------------------------------------------------------------
 // RegisterAllocator implementation.
 
diff --git a/src/register-allocator.h b/src/register-allocator.h
index a03a9d2..f0ef9c3 100644
--- a/src/register-allocator.h
+++ b/src/register-allocator.h
@@ -69,12 +69,13 @@
 
   // Construct a Result whose value is a compile-time constant.
   explicit Result(Handle<Object> value) {
+    ZoneObjectList* constant_list = Isolate::Current()->result_constant_list();
     TypeInfo info = TypeInfo::TypeFromValue(value);
     value_ = TypeField::encode(CONSTANT)
         | TypeInfoField::encode(info.ToInt())
         | IsUntaggedInt32Field::encode(false)
-        | DataField::encode(ConstantList()->length());
-    ConstantList()->Add(value);
+        | DataField::encode(constant_list->length());
+    constant_list->Add(value);
   }
 
   // The copy constructor and assignment operators could each create a new
@@ -85,18 +86,6 @@
 
   inline ~Result();
 
-  // Static indirection table for handles to constants.  If a Result
-  // represents a constant, the data contains an index into this table
-  // of handles to the actual constants.
-  typedef ZoneList<Handle<Object> > ZoneObjectList;
-
-  static ZoneObjectList* ConstantList();
-
-  // Clear the constants indirection table.
-  static void ClearConstantList() {
-    ConstantList()->Clear();
-  }
-
   inline void Unuse();
 
   Type type() const { return TypeField::decode(value_); }
@@ -137,7 +126,8 @@
 
   Handle<Object> handle() const {
     ASSERT(type() == CONSTANT);
-    return ConstantList()->at(DataField::decode(value_));
+    return Isolate::Current()->result_constant_list()->
+        at(DataField::decode(value_));
   }
 
   // Move this result to an arbitrary register.  The register is not
diff --git a/src/rewriter.cc b/src/rewriter.cc
index fd40cdc..780314d 100644
--- a/src/rewriter.cc
+++ b/src/rewriter.cc
@@ -989,7 +989,8 @@
 
   ZoneList<Statement*>* body = function->body();
   if (!body->is_empty()) {
-    Variable* result = scope->NewTemporary(Factory::result_symbol());
+    Variable* result = scope->NewTemporary(
+        info->isolate()->factory()->result_symbol());
     Processor processor(result);
     processor.Process(body);
     if (processor.HasStackOverflow()) return false;
diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc
index df6471e..c6e2b46 100644
--- a/src/runtime-profiler.cc
+++ b/src/runtime-profiler.cc
@@ -36,8 +36,8 @@
 #include "execution.h"
 #include "global-handles.h"
 #include "mark-compact.h"
+#include "platform.h"
 #include "scopeinfo.h"
-#include "top.h"
 
 namespace v8 {
 namespace internal {
@@ -69,16 +69,9 @@
 };
 
 
-enum SamplerState {
-  IN_NON_JS_STATE = 0,
-  IN_JS_STATE = 1
-};
-
-
 // Optimization sampler constants.
 static const int kSamplerFrameCount = 2;
 static const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 };
-static const int kSamplerWindowSize = 16;
 
 static const int kSamplerTicksBetweenThresholdAdjustment = 32;
 
@@ -92,34 +85,19 @@
 
 static const int kSizeLimit = 1500;
 
-static int sampler_threshold = kSamplerThresholdInit;
-static int sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit;
-
-static int sampler_ticks_until_threshold_adjustment =
-    kSamplerTicksBetweenThresholdAdjustment;
-
-// The ratio of ticks spent in JS code in percent.
-static Atomic32 js_ratio;
-
-static Object* sampler_window[kSamplerWindowSize] = { NULL, };
-static int sampler_window_position = 0;
-static int sampler_window_weight[kSamplerWindowSize] = { 0, };
-
-
-// Support for pending 'optimize soon' requests.
-static PendingListNode* optimize_soon_list = NULL;
-
 
 PendingListNode::PendingListNode(JSFunction* function) : next_(NULL) {
-  function_ = GlobalHandles::Create(function);
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
+  function_ = global_handles->Create(function);
   start_ = OS::Ticks();
-  GlobalHandles::MakeWeak(function_.location(), this, &WeakCallback);
+  global_handles->MakeWeak(function_.location(), this, &WeakCallback);
 }
 
 
 void PendingListNode::Destroy() {
   if (!IsValid()) return;
-  GlobalHandles::Destroy(function_.location());
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
+  global_handles->Destroy(function_.location());
   function_= Handle<Object>::null();
 }
 
@@ -135,7 +113,37 @@
 }
 
 
-static void Optimize(JSFunction* function, bool eager, int delay) {
+Atomic32 RuntimeProfiler::state_ = 0;
+// TODO(isolates): Create the semaphore lazily and clean it up when no
+// longer required.
+#ifdef ENABLE_LOGGING_AND_PROFILING
+Semaphore* RuntimeProfiler::semaphore_ = OS::CreateSemaphore(0);
+#endif
+
+
+RuntimeProfiler::RuntimeProfiler(Isolate* isolate)
+    : isolate_(isolate),
+      sampler_threshold_(kSamplerThresholdInit),
+      sampler_threshold_size_factor_(kSamplerThresholdSizeFactorInit),
+      sampler_ticks_until_threshold_adjustment_(
+        kSamplerTicksBetweenThresholdAdjustment),
+      js_ratio_(0),
+      sampler_window_position_(0),
+      optimize_soon_list_(NULL),
+      state_window_position_(0) {
+  state_counts_[0] = kStateWindowSize;
+  state_counts_[1] = 0;
+  memset(state_window_, 0, sizeof(state_window_));
+  ClearSampleBuffer();
+}
+
+
+bool RuntimeProfiler::IsEnabled() {
+  return V8::UseCrankshaft() && FLAG_opt;
+}
+
+
+void RuntimeProfiler::Optimize(JSFunction* function, bool eager, int delay) {
   ASSERT(IsOptimizable(function));
   if (FLAG_trace_opt) {
     PrintF("[marking (%s) ", eager ? "eagerly" : "lazily");
@@ -152,11 +160,13 @@
 }
 
 
-static void AttemptOnStackReplacement(JSFunction* function) {
+void RuntimeProfiler::AttemptOnStackReplacement(JSFunction* function) {
   // See AlwaysFullCompiler (in compiler.cc) comment on why we need
   // Debug::has_break_points().
   ASSERT(function->IsMarkedForLazyRecompilation());
-  if (!FLAG_use_osr || Debug::has_break_points() || function->IsBuiltin()) {
+  if (!FLAG_use_osr ||
+      isolate_->debug()->has_break_points() ||
+      function->IsBuiltin()) {
     return;
   }
 
@@ -186,7 +196,8 @@
   Object* check_code;
   MaybeObject* maybe_check_code = check_stub.TryGetCode();
   if (maybe_check_code->ToObject(&check_code)) {
-    Code* replacement_code = Builtins::builtin(Builtins::OnStackReplacement);
+    Code* replacement_code =
+        isolate_->builtins()->builtin(Builtins::kOnStackReplacement);
     Code* unoptimized_code = shared->code();
     Deoptimizer::PatchStackCheckCode(unoptimized_code,
                                      Code::cast(check_code),
@@ -195,21 +206,19 @@
 }
 
 
-static void ClearSampleBuffer() {
-  for (int i = 0; i < kSamplerWindowSize; i++) {
-    sampler_window[i] = NULL;
-    sampler_window_weight[i] = 0;
-  }
+void RuntimeProfiler::ClearSampleBuffer() {
+  memset(sampler_window_, 0, sizeof(sampler_window_));
+  memset(sampler_window_weight_, 0, sizeof(sampler_window_weight_));
 }
 
 
-static int LookupSample(JSFunction* function) {
+int RuntimeProfiler::LookupSample(JSFunction* function) {
   int weight = 0;
   for (int i = 0; i < kSamplerWindowSize; i++) {
-    Object* sample = sampler_window[i];
+    Object* sample = sampler_window_[i];
     if (sample != NULL) {
       if (function == sample) {
-        weight += sampler_window_weight[i];
+        weight += sampler_window_weight_[i];
       }
     }
   }
@@ -217,18 +226,18 @@
 }
 
 
-static void AddSample(JSFunction* function, int weight) {
+void RuntimeProfiler::AddSample(JSFunction* function, int weight) {
   ASSERT(IsPowerOf2(kSamplerWindowSize));
-  sampler_window[sampler_window_position] = function;
-  sampler_window_weight[sampler_window_position] = weight;
-  sampler_window_position = (sampler_window_position + 1) &
+  sampler_window_[sampler_window_position_] = function;
+  sampler_window_weight_[sampler_window_position_] = weight;
+  sampler_window_position_ = (sampler_window_position_ + 1) &
       (kSamplerWindowSize - 1);
 }
 
 
 void RuntimeProfiler::OptimizeNow() {
-  HandleScope scope;
-  PendingListNode* current = optimize_soon_list;
+  HandleScope scope(isolate_);
+  PendingListNode* current = optimize_soon_list_;
   while (current != NULL) {
     PendingListNode* next = current->next();
     if (current->IsValid()) {
@@ -241,7 +250,7 @@
     delete current;
     current = next;
   }
-  optimize_soon_list = NULL;
+  optimize_soon_list_ = NULL;
 
   // Run through the JavaScript frames and collect them. If we already
   // have a sample of the function, we mark it for optimizations
@@ -257,14 +266,14 @@
 
     // Adjust threshold each time we have processed
     // a certain number of ticks.
-    if (sampler_ticks_until_threshold_adjustment > 0) {
-      sampler_ticks_until_threshold_adjustment--;
-      if (sampler_ticks_until_threshold_adjustment <= 0) {
+    if (sampler_ticks_until_threshold_adjustment_ > 0) {
+      sampler_ticks_until_threshold_adjustment_--;
+      if (sampler_ticks_until_threshold_adjustment_ <= 0) {
         // If the threshold is not already at the minimum
         // modify and reset the ticks until next adjustment.
-        if (sampler_threshold > kSamplerThresholdMin) {
-          sampler_threshold -= kSamplerThresholdDelta;
-          sampler_ticks_until_threshold_adjustment =
+        if (sampler_threshold_ > kSamplerThresholdMin) {
+          sampler_threshold_ -= kSamplerThresholdDelta;
+          sampler_ticks_until_threshold_adjustment_ =
               kSamplerTicksBetweenThresholdAdjustment;
         }
       }
@@ -284,11 +293,11 @@
 
     int function_size = function->shared()->SourceSize();
     int threshold_size_factor = (function_size > kSizeLimit)
-        ? sampler_threshold_size_factor
+        ? sampler_threshold_size_factor_
         : 1;
 
-    int threshold = sampler_threshold * threshold_size_factor;
-    int current_js_ratio = NoBarrier_Load(&js_ratio);
+    int threshold = sampler_threshold_ * threshold_size_factor;
+    int current_js_ratio = NoBarrier_Load(&js_ratio_);
 
     // Adjust threshold depending on the ratio of time spent
     // in JS code.
@@ -304,7 +313,8 @@
 
     if (LookupSample(function) >= threshold) {
       Optimize(function, false, 0);
-      CompilationCache::MarkForEagerOptimizing(Handle<JSFunction>(function));
+      isolate_->compilation_cache()->MarkForEagerOptimizing(
+          Handle<JSFunction>(function));
     }
   }
 
@@ -320,26 +330,21 @@
 void RuntimeProfiler::OptimizeSoon(JSFunction* function) {
   if (!IsOptimizable(function)) return;
   PendingListNode* node = new PendingListNode(function);
-  node->set_next(optimize_soon_list);
-  optimize_soon_list = node;
+  node->set_next(optimize_soon_list_);
+  optimize_soon_list_ = node;
 }
 
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
-static void UpdateStateRatio(SamplerState current_state) {
-  static const int kStateWindowSize = 128;
-  static SamplerState state_window[kStateWindowSize];
-  static int state_window_position = 0;
-  static int state_counts[2] = { kStateWindowSize, 0 };
-
-  SamplerState old_state = state_window[state_window_position];
-  state_counts[old_state]--;
-  state_window[state_window_position] = current_state;
-  state_counts[current_state]++;
+void RuntimeProfiler::UpdateStateRatio(SamplerState current_state) {
+  SamplerState old_state = state_window_[state_window_position_];
+  state_counts_[old_state]--;
+  state_window_[state_window_position_] = current_state;
+  state_counts_[current_state]++;
   ASSERT(IsPowerOf2(kStateWindowSize));
-  state_window_position = (state_window_position + 1) &
+  state_window_position_ = (state_window_position_ + 1) &
       (kStateWindowSize - 1);
-  NoBarrier_Store(&js_ratio, state_counts[IN_JS_STATE] * 100 /
+  NoBarrier_Store(&js_ratio_, state_counts_[IN_JS_STATE] * 100 /
                   kStateWindowSize);
 }
 #endif
@@ -348,11 +353,11 @@
 void RuntimeProfiler::NotifyTick() {
 #ifdef ENABLE_LOGGING_AND_PROFILING
   // Record state sample.
-  SamplerState state = Top::IsInJSState()
+  SamplerState state = IsSomeIsolateInJS()
       ? IN_JS_STATE
       : IN_NON_JS_STATE;
   UpdateStateRatio(state);
-  StackGuard::RequestRuntimeProfilerTick();
+  isolate_->stack_guard()->RequestRuntimeProfilerTick();
 #endif
 }
 
@@ -361,15 +366,15 @@
   ClearSampleBuffer();
   // If the ticker hasn't already started, make sure to do so to get
   // the ticks for the runtime profiler.
-  if (IsEnabled()) Logger::EnsureTickerStarted();
+  if (IsEnabled()) isolate_->logger()->EnsureTickerStarted();
 }
 
 
 void RuntimeProfiler::Reset() {
-  sampler_threshold = kSamplerThresholdInit;
-  sampler_ticks_until_threshold_adjustment =
+  sampler_threshold_ = kSamplerThresholdInit;
+  sampler_threshold_size_factor_ = kSamplerThresholdSizeFactorInit;
+  sampler_ticks_until_threshold_adjustment_ =
       kSamplerTicksBetweenThresholdAdjustment;
-  sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit;
 }
 
 
@@ -386,24 +391,61 @@
 // Update the pointers in the sampler window after a GC.
 void RuntimeProfiler::UpdateSamplesAfterScavenge() {
   for (int i = 0; i < kSamplerWindowSize; i++) {
-    Object* function = sampler_window[i];
-    if (function != NULL && Heap::InNewSpace(function)) {
+    Object* function = sampler_window_[i];
+    if (function != NULL && isolate_->heap()->InNewSpace(function)) {
       MapWord map_word = HeapObject::cast(function)->map_word();
       if (map_word.IsForwardingAddress()) {
-        sampler_window[i] = map_word.ToForwardingAddress();
+        sampler_window_[i] = map_word.ToForwardingAddress();
       } else {
-        sampler_window[i] = NULL;
+        sampler_window_[i] = NULL;
       }
     }
   }
 }
 
 
+void RuntimeProfiler::HandleWakeUp(Isolate* isolate) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  // The profiler thread must still be waiting.
+  ASSERT(NoBarrier_Load(&state_) >= 0);
+  // In IsolateEnteredJS we have already incremented the counter and
+  // undid the decrement done by the profiler thread. Increment again
+  // to get the right count of active isolates.
+  NoBarrier_AtomicIncrement(&state_, 1);
+  semaphore_->Signal();
+  isolate->ResetEagerOptimizingData();
+#endif
+}
+
+
+bool RuntimeProfiler::IsSomeIsolateInJS() {
+  return NoBarrier_Load(&state_) > 0;
+}
+
+
+bool RuntimeProfiler::WaitForSomeIsolateToEnterJS() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  Atomic32 old_state = NoBarrier_CompareAndSwap(&state_, 0, -1);
+  ASSERT(old_state >= -1);
+  if (old_state != 0) return false;
+  semaphore_->Wait();
+#endif
+  return true;
+}
+
+
+void RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  semaphore_->Signal();
+#endif
+}
+
+
 void RuntimeProfiler::RemoveDeadSamples() {
   for (int i = 0; i < kSamplerWindowSize; i++) {
-    Object* function = sampler_window[i];
+    Object* function = sampler_window_[i];
     if (function != NULL && !HeapObject::cast(function)->IsMarked()) {
-      sampler_window[i] = NULL;
+      sampler_window_[i] = NULL;
     }
   }
 }
@@ -411,7 +453,7 @@
 
 void RuntimeProfiler::UpdateSamplesAfterCompact(ObjectVisitor* visitor) {
   for (int i = 0; i < kSamplerWindowSize; i++) {
-    visitor->VisitPointer(&sampler_window[i]);
+    visitor->VisitPointer(&sampler_window_[i]);
   }
 }
 
@@ -419,20 +461,13 @@
 bool RuntimeProfilerRateLimiter::SuspendIfNecessary() {
 #ifdef ENABLE_LOGGING_AND_PROFILING
   static const int kNonJSTicksThreshold = 100;
-  // We suspend the runtime profiler thread when not running
-  // JavaScript. If the CPU profiler is active we must not do this
-  // because it samples both JavaScript and C++ code.
-  if (RuntimeProfiler::IsEnabled() &&
-      !CpuProfiler::is_profiling() &&
-      !(FLAG_prof && FLAG_prof_auto)) {
-    if (Top::IsInJSState()) {
-      non_js_ticks_ = 0;
+  if (RuntimeProfiler::IsSomeIsolateInJS()) {
+    non_js_ticks_ = 0;
+  } else {
+    if (non_js_ticks_ < kNonJSTicksThreshold) {
+      ++non_js_ticks_;
     } else {
-      if (non_js_ticks_ < kNonJSTicksThreshold) {
-        ++non_js_ticks_;
-      } else {
-        if (Top::WaitForJSState()) return true;
-      }
+      return RuntimeProfiler::WaitForSomeIsolateToEnterJS();
     }
   }
 #endif
diff --git a/src/runtime-profiler.h b/src/runtime-profiler.h
index 02defc9..8074035 100644
--- a/src/runtime-profiler.h
+++ b/src/runtime-profiler.h
@@ -28,29 +28,122 @@
 #ifndef V8_RUNTIME_PROFILER_H_
 #define V8_RUNTIME_PROFILER_H_
 
-#include "v8.h"
 #include "allocation.h"
+#include "atomicops.h"
 
 namespace v8 {
 namespace internal {
 
-class RuntimeProfiler : public AllStatic {
+class Isolate;
+class JSFunction;
+class Object;
+class PendingListNode;
+class Semaphore;
+
+
+enum SamplerState {
+  IN_NON_JS_STATE = 0,
+  IN_JS_STATE = 1
+};
+
+
+class RuntimeProfiler {
  public:
-  static bool IsEnabled() { return V8::UseCrankshaft() && FLAG_opt; }
+  explicit RuntimeProfiler(Isolate* isolate);
 
-  static void OptimizeNow();
-  static void OptimizeSoon(JSFunction* function);
+  static bool IsEnabled();
 
-  static void NotifyTick();
+  void OptimizeNow();
+  void OptimizeSoon(JSFunction* function);
 
-  static void Setup();
-  static void Reset();
-  static void TearDown();
+  void NotifyTick();
 
-  static int SamplerWindowSize();
-  static void UpdateSamplesAfterScavenge();
-  static void RemoveDeadSamples();
-  static void UpdateSamplesAfterCompact(ObjectVisitor* visitor);
+  void Setup();
+  void Reset();
+  void TearDown();
+
+  Object** SamplerWindowAddress();
+  int SamplerWindowSize();
+
+  // Rate limiting support.
+
+  // VM thread interface.
+  //
+  // Called by isolates when their states change.
+  static inline void IsolateEnteredJS(Isolate* isolate);
+  static inline void IsolateExitedJS(Isolate* isolate);
+
+  // Profiler thread interface.
+  //
+  // IsSomeIsolateInJS():
+  // The profiler thread can query whether some isolate is currently
+  // running JavaScript code.
+  //
+  // WaitForSomeIsolateToEnterJS():
+  // When no isolates are running JavaScript code for some time the
+  // profiler thread suspends itself by calling the wait function. The
+  // wait function returns true after it waited or false immediately.
+  // While the function was waiting the profiler may have been
+  // disabled so it *must check* whether it is allowed to continue.
+  static bool IsSomeIsolateInJS();
+  static bool WaitForSomeIsolateToEnterJS();
+
+  // When shutting down we join the profiler thread. Doing so while
+  // it's waiting on a semaphore will cause a deadlock, so we have to
+  // wake it up first.
+  static void WakeUpRuntimeProfilerThreadBeforeShutdown();
+
+  void UpdateSamplesAfterScavenge();
+  void RemoveDeadSamples();
+  void UpdateSamplesAfterCompact(ObjectVisitor* visitor);
+
+ private:
+  static const int kSamplerWindowSize = 16;
+  static const int kStateWindowSize = 128;
+
+  static void HandleWakeUp(Isolate* isolate);
+
+  void Optimize(JSFunction* function, bool eager, int delay);
+
+  void AttemptOnStackReplacement(JSFunction* function);
+
+  void ClearSampleBuffer();
+
+  void ClearSampleBufferNewSpaceEntries();
+
+  int LookupSample(JSFunction* function);
+
+  void AddSample(JSFunction* function, int weight);
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  void UpdateStateRatio(SamplerState current_state);
+#endif
+
+  Isolate* isolate_;
+
+  int sampler_threshold_;
+  int sampler_threshold_size_factor_;
+  int sampler_ticks_until_threshold_adjustment_;
+
+  // The ratio of ticks spent in JS code in percent.
+  Atomic32 js_ratio_;
+
+  Object* sampler_window_[kSamplerWindowSize];
+  int sampler_window_position_;
+  int sampler_window_weight_[kSamplerWindowSize];
+
+  // Support for pending 'optimize soon' requests.
+  PendingListNode* optimize_soon_list_;
+
+  SamplerState state_window_[kStateWindowSize];
+  int state_window_position_;
+  int state_counts_[2];
+
+  // Possible state values:
+  //   -1            => the profiler thread is waiting on the semaphore
+  //   0 or positive => the number of isolates running JavaScript code.
+  static Atomic32 state_;
+  static Semaphore* semaphore_;
 };
 
 
@@ -59,9 +152,10 @@
  public:
   RuntimeProfilerRateLimiter() : non_js_ticks_(0) { }
 
-  // Suspends the current thread when not executing JavaScript to
-  // minimize CPU usage. Returns whether this thread was suspended
-  // (and so might have to check whether profiling is still active.)
+  // Suspends the current thread (which must be the profiler thread)
+  // when not executing JavaScript to minimize CPU usage. Returns
+  // whether the thread was suspended (and so must check whether
+  // profiling is still active.)
   //
   // Does nothing when runtime profiling is not enabled.
   bool SuspendIfNecessary();
@@ -72,6 +166,27 @@
   DISALLOW_COPY_AND_ASSIGN(RuntimeProfilerRateLimiter);
 };
 
+
+// Implementation of RuntimeProfiler inline functions.
+
+void RuntimeProfiler::IsolateEnteredJS(Isolate* isolate) {
+  Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, 1);
+  if (new_state == 0) {
+    // Just incremented from -1 to 0. -1 can only be set by the
+    // profiler thread before it suspends itself and starts waiting on
+    // the semaphore.
+    HandleWakeUp(isolate);
+  }
+  ASSERT(new_state >= 0);
+}
+
+
+void RuntimeProfiler::IsolateExitedJS(Isolate* isolate) {
+  Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, -1);
+  ASSERT(new_state >= 0);
+  USE(new_state);
+}
+
 } }  // namespace v8::internal
 
 #endif  // V8_RUNTIME_PROFILER_H_
diff --git a/src/runtime.cc b/src/runtime.cc
index 965a083..c979849 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -59,7 +59,7 @@
 
 
 #define RUNTIME_ASSERT(value) \
-  if (!(value)) return Top::ThrowIllegalOperation();
+  if (!(value)) return isolate->ThrowIllegalOperation();
 
 // 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
@@ -100,16 +100,15 @@
   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;
 
+MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate,
+                                                   JSObject* boilerplate) {
+  StackLimitCheck check(isolate);
+  if (check.HasOverflowed()) return isolate->StackOverflow();
 
-MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(JSObject* boilerplate) {
-  StackLimitCheck check;
-  if (check.HasOverflowed()) return Top::StackOverflow();
-
+  Heap* heap = isolate->heap();
   Object* result;
-  { MaybeObject* maybe_result = Heap::CopyJSObject(boilerplate);
+  { MaybeObject* maybe_result = heap->CopyJSObject(boilerplate);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   JSObject* copy = JSObject::cast(result);
@@ -121,7 +120,7 @@
       Object* value = properties->get(i);
       if (value->IsJSObject()) {
         JSObject* js_object = JSObject::cast(value);
-        { MaybeObject* maybe_result = DeepCopyBoilerplate(js_object);
+        { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
           if (!maybe_result->ToObject(&result)) return maybe_result;
         }
         properties->set(i, result);
@@ -132,7 +131,7 @@
       Object* value = copy->InObjectPropertyAt(i);
       if (value->IsJSObject()) {
         JSObject* js_object = JSObject::cast(value);
-        { MaybeObject* maybe_result = DeepCopyBoilerplate(js_object);
+        { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
           if (!maybe_result->ToObject(&result)) return maybe_result;
         }
         copy->InObjectPropertyAtPut(i, result);
@@ -140,7 +139,7 @@
     }
   } else {
     { MaybeObject* maybe_result =
-          Heap::AllocateFixedArray(copy->NumberOfLocalProperties(NONE));
+          heap->AllocateFixedArray(copy->NumberOfLocalProperties(NONE));
       if (!maybe_result->ToObject(&result)) return maybe_result;
     }
     FixedArray* names = FixedArray::cast(result);
@@ -158,7 +157,7 @@
           copy->GetProperty(key_string, &attributes)->ToObjectUnchecked();
       if (value->IsJSObject()) {
         JSObject* js_object = JSObject::cast(value);
-        { MaybeObject* maybe_result = DeepCopyBoilerplate(js_object);
+        { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
           if (!maybe_result->ToObject(&result)) return maybe_result;
         }
         { MaybeObject* maybe_result =
@@ -172,12 +171,12 @@
 
   // Deep copy local elements.
   // Pixel elements cannot be created using an object literal.
-  ASSERT(!copy->HasPixelElements() && !copy->HasExternalArrayElements());
+  ASSERT(!copy->HasExternalArrayElements());
   switch (copy->GetElementsKind()) {
     case JSObject::FAST_ELEMENTS: {
       FixedArray* elements = FixedArray::cast(copy->elements());
-      if (elements->map() == Heap::fixed_cow_array_map()) {
-        Counters::cow_arrays_created_runtime.Increment();
+      if (elements->map() == heap->fixed_cow_array_map()) {
+        isolate->counters()->cow_arrays_created_runtime()->Increment();
 #ifdef DEBUG
         for (int i = 0; i < elements->length(); i++) {
           ASSERT(!elements->get(i)->IsJSObject());
@@ -188,7 +187,8 @@
           Object* value = elements->get(i);
           if (value->IsJSObject()) {
             JSObject* js_object = JSObject::cast(value);
-            { MaybeObject* maybe_result = DeepCopyBoilerplate(js_object);
+            { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
+                                                              js_object);
               if (!maybe_result->ToObject(&result)) return maybe_result;
             }
             elements->set(i, result);
@@ -206,7 +206,8 @@
           Object* value = element_dictionary->ValueAt(i);
           if (value->IsJSObject()) {
             JSObject* js_object = JSObject::cast(value);
-            { MaybeObject* maybe_result = DeepCopyBoilerplate(js_object);
+            { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
+                                                              js_object);
               if (!maybe_result->ToObject(&result)) return maybe_result;
             }
             element_dictionary->ValueAtPut(i, result);
@@ -223,15 +224,19 @@
 }
 
 
-static MaybeObject* Runtime_CloneLiteralBoilerplate(Arguments args) {
+static MaybeObject* Runtime_CloneLiteralBoilerplate(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   CONVERT_CHECKED(JSObject, boilerplate, args[0]);
-  return DeepCopyBoilerplate(boilerplate);
+  return DeepCopyBoilerplate(isolate, boilerplate);
 }
 
 
-static MaybeObject* Runtime_CloneShallowLiteralBoilerplate(Arguments args) {
+static MaybeObject* Runtime_CloneShallowLiteralBoilerplate(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   CONVERT_CHECKED(JSObject, boilerplate, args[0]);
-  return Heap::CopyJSObject(boilerplate);
+  return isolate->heap()->CopyJSObject(boilerplate);
 }
 
 
@@ -239,6 +244,7 @@
     Handle<Context> context,
     Handle<FixedArray> constant_properties,
     bool* is_result_from_cache) {
+  Isolate* isolate = context->GetIsolate();
   int properties_length = constant_properties->length();
   int number_of_properties = properties_length / 2;
   if (FLAG_canonicalize_object_literal_maps) {
@@ -265,7 +271,8 @@
     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);
+      Handle<FixedArray> keys =
+          isolate->factory()->NewFixedArray(number_of_symbol_keys);
       if (number_of_symbol_keys > 0) {
         int index = 0;
         for (int p = 0; p < properties_length; p += 2) {
@@ -277,25 +284,28 @@
         ASSERT(index == number_of_symbol_keys);
       }
       *is_result_from_cache = true;
-      return Factory::ObjectLiteralMapFromCache(context, keys);
+      return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
     }
   }
   *is_result_from_cache = false;
-  return Factory::CopyMap(
+  return isolate->factory()->CopyMap(
       Handle<Map>(context->object_function()->initial_map()),
       number_of_properties);
 }
 
 
 static Handle<Object> CreateLiteralBoilerplate(
+    Isolate* isolate,
     Handle<FixedArray> literals,
     Handle<FixedArray> constant_properties);
 
 
 static Handle<Object> CreateObjectLiteralBoilerplate(
+    Isolate* isolate,
     Handle<FixedArray> literals,
     Handle<FixedArray> constant_properties,
-    bool should_have_fast_elements) {
+    bool should_have_fast_elements,
+    bool has_function_literal) {
   // 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
@@ -305,69 +315,90 @@
   Handle<Context> context =
       Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));
 
-  bool is_result_from_cache;
-  Handle<Map> map = ComputeObjectLiteralMap(context,
-                                            constant_properties,
-                                            &is_result_from_cache);
+  // In case we have function literals, we want the object to be in
+  // slow properties mode for now. We don't go in the map cache because
+  // maps with constant functions can't be shared if the functions are
+  // not the same (which is the common case).
+  bool is_result_from_cache = false;
+  Handle<Map> map = has_function_literal
+      ? Handle<Map>(context->object_function()->initial_map())
+      : ComputeObjectLiteralMap(context,
+                                constant_properties,
+                                &is_result_from_cache);
 
-  Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map);
+  Handle<JSObject> boilerplate = isolate->factory()->NewJSObjectFromMap(map);
 
   // Normalize the elements of the boilerplate to save space if needed.
   if (!should_have_fast_elements) NormalizeElements(boilerplate);
 
-  {  // Add the constant properties to the boilerplate.
-    int length = constant_properties->length();
-    OptimizedObjectForAddingMultipleProperties opt(boilerplate,
-                                                   length / 2,
-                                                   !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 (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
-          // Array index as string (uint32).
-          result = SetOwnElement(boilerplate,
-                                 element_index,
-                                 value,
-                                 kNonStrictMode);
-        } else {
-          Handle<String> name(String::cast(*key));
-          ASSERT(!name->AsArrayIndex(&element_index));
-          result = SetLocalPropertyIgnoreAttributes(boilerplate, name,
-                                                    value, NONE);
-        }
-      } else if (key->ToArrayIndex(&element_index)) {
-        // Array index (uint32).
+  // Add the constant properties to the boilerplate.
+  int length = constant_properties->length();
+  bool should_transform =
+      !is_result_from_cache && boilerplate->HasFastProperties();
+  if (should_transform || has_function_literal) {
+    // Normalize the properties of object to avoid n^2 behavior
+    // when extending the object multiple properties. Indicate the number of
+    // properties to be added.
+    NormalizeProperties(boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
+  }
+
+  for (int index = 0; index < length; index +=2) {
+    Handle<Object> key(constant_properties->get(index+0), isolate);
+    Handle<Object> value(constant_properties->get(index+1), isolate);
+    if (value->IsFixedArray()) {
+      // The value contains the constant_properties of a
+      // simple object or array literal.
+      Handle<FixedArray> array = Handle<FixedArray>::cast(value);
+      value = CreateLiteralBoilerplate(isolate, literals, array);
+      if (value.is_null()) return value;
+    }
+    Handle<Object> result;
+    uint32_t element_index = 0;
+    if (key->IsSymbol()) {
+      if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
+        // Array index as string (uint32).
         result = SetOwnElement(boilerplate,
                                element_index,
                                value,
                                kNonStrictMode);
       } 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));
+        Handle<String> name(String::cast(*key));
+        ASSERT(!name->AsArrayIndex(&element_index));
         result = SetLocalPropertyIgnoreAttributes(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;
+    } else if (key->ToArrayIndex(&element_index)) {
+      // Array index (uint32).
+      result = SetOwnElement(boilerplate,
+                             element_index,
+                             value,
+                             kNonStrictMode);
+    } 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 =
+          isolate->factory()->NewStringFromAscii(CStrVector(str));
+      result = SetLocalPropertyIgnoreAttributes(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;
+  }
+
+  // Transform to fast properties if necessary. For object literals with
+  // containing function literals we defer this operation until after all
+  // computed properties have been assigned so that we can generate
+  // constant function properties.
+  if (should_transform && !has_function_literal) {
+    TransformToFastProperties(boilerplate,
+                              boilerplate->map()->unused_property_fields());
   }
 
   return boilerplate;
@@ -375,16 +406,18 @@
 
 
 static Handle<Object> CreateArrayLiteralBoilerplate(
+    Isolate* isolate,
     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> object = isolate->factory()->NewJSObject(constructor);
 
-  const bool is_cow = (elements->map() == Heap::fixed_cow_array_map());
+  const bool is_cow =
+      (elements->map() == isolate->heap()->fixed_cow_array_map());
   Handle<FixedArray> copied_elements =
-      is_cow ? elements : Factory::CopyFixedArray(elements);
+      is_cow ? elements : isolate->factory()->CopyFixedArray(elements);
 
   Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements);
   if (is_cow) {
@@ -398,10 +431,10 @@
     for (int i = 0; i < content->length(); i++) {
       if (content->get(i)->IsFixedArray()) {
         // The value contains the constant_properties of a
-        // simple object literal.
+        // simple object or array literal.
         Handle<FixedArray> fa(FixedArray::cast(content->get(i)));
         Handle<Object> result =
-            CreateLiteralBoilerplate(literals, fa);
+            CreateLiteralBoilerplate(isolate, literals, fa);
         if (result.is_null()) return result;
         content->set(i, *result);
       }
@@ -415,16 +448,26 @@
 
 
 static Handle<Object> CreateLiteralBoilerplate(
+    Isolate* isolate,
     Handle<FixedArray> literals,
     Handle<FixedArray> array) {
   Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
+  const bool kHasNoFunctionLiteral = false;
   switch (CompileTimeValue::GetType(array)) {
     case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
-      return CreateObjectLiteralBoilerplate(literals, elements, true);
+      return CreateObjectLiteralBoilerplate(isolate,
+                                            literals,
+                                            elements,
+                                            true,
+                                            kHasNoFunctionLiteral);
     case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
-      return CreateObjectLiteralBoilerplate(literals, elements, false);
+      return CreateObjectLiteralBoilerplate(isolate,
+                                            literals,
+                                            elements,
+                                            false,
+                                            kHasNoFunctionLiteral);
     case CompileTimeValue::ARRAY_LITERAL:
-      return CreateArrayLiteralBoilerplate(literals, elements);
+      return CreateArrayLiteralBoilerplate(isolate, literals, elements);
     default:
       UNREACHABLE();
       return Handle<Object>::null();
@@ -432,19 +475,22 @@
 }
 
 
-static MaybeObject* Runtime_CreateArrayLiteralBoilerplate(Arguments args) {
+static MaybeObject* Runtime_CreateArrayLiteralBoilerplate(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   // 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;
+  HandleScope scope(isolate);
   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);
+  Handle<Object> object =
+      CreateArrayLiteralBoilerplate(isolate, literals, elements);
   if (object.is_null()) return Failure::Exception();
 
   // Update the functions literal and return the boilerplate.
@@ -453,103 +499,118 @@
 }
 
 
-static MaybeObject* Runtime_CreateObjectLiteral(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_CreateObjectLiteral(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 4);
   CONVERT_ARG_CHECKED(FixedArray, literals, 0);
   CONVERT_SMI_CHECKED(literals_index, args[1]);
   CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
-  CONVERT_SMI_CHECKED(fast_elements, args[3]);
-  bool should_have_fast_elements = fast_elements == 1;
+  CONVERT_SMI_CHECKED(flags, args[3]);
+  bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
+  bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
 
   // Check if boilerplate exists. If not, create it first.
-  Handle<Object> boilerplate(literals->get(literals_index));
-  if (*boilerplate == Heap::undefined_value()) {
-    boilerplate = CreateObjectLiteralBoilerplate(literals,
+  Handle<Object> boilerplate(literals->get(literals_index), isolate);
+  if (*boilerplate == isolate->heap()->undefined_value()) {
+    boilerplate = CreateObjectLiteralBoilerplate(isolate,
+                                                 literals,
                                                  constant_properties,
-                                                 should_have_fast_elements);
+                                                 should_have_fast_elements,
+                                                 has_function_literal);
     if (boilerplate.is_null()) return Failure::Exception();
     // Update the functions literal and return the boilerplate.
     literals->set(literals_index, *boilerplate);
   }
-  return DeepCopyBoilerplate(JSObject::cast(*boilerplate));
+  return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
 }
 
 
-static MaybeObject* Runtime_CreateObjectLiteralShallow(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_CreateObjectLiteralShallow(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 4);
   CONVERT_ARG_CHECKED(FixedArray, literals, 0);
   CONVERT_SMI_CHECKED(literals_index, args[1]);
   CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
-  CONVERT_SMI_CHECKED(fast_elements, args[3]);
-  bool should_have_fast_elements = fast_elements == 1;
+  CONVERT_SMI_CHECKED(flags, args[3]);
+  bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
+  bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
 
   // Check if boilerplate exists. If not, create it first.
-  Handle<Object> boilerplate(literals->get(literals_index));
-  if (*boilerplate == Heap::undefined_value()) {
-    boilerplate = CreateObjectLiteralBoilerplate(literals,
+  Handle<Object> boilerplate(literals->get(literals_index), isolate);
+  if (*boilerplate == isolate->heap()->undefined_value()) {
+    boilerplate = CreateObjectLiteralBoilerplate(isolate,
+                                                 literals,
                                                  constant_properties,
-                                                 should_have_fast_elements);
+                                                 should_have_fast_elements,
+                                                 has_function_literal);
     if (boilerplate.is_null()) return Failure::Exception();
     // Update the functions literal and return the boilerplate.
     literals->set(literals_index, *boilerplate);
   }
-  return Heap::CopyJSObject(JSObject::cast(*boilerplate));
+  return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
 }
 
 
-static MaybeObject* Runtime_CreateArrayLiteral(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_CreateArrayLiteral(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 3);
   CONVERT_ARG_CHECKED(FixedArray, literals, 0);
   CONVERT_SMI_CHECKED(literals_index, args[1]);
   CONVERT_ARG_CHECKED(FixedArray, elements, 2);
 
   // Check if boilerplate exists. If not, create it first.
-  Handle<Object> boilerplate(literals->get(literals_index));
-  if (*boilerplate == Heap::undefined_value()) {
-    boilerplate = CreateArrayLiteralBoilerplate(literals, elements);
+  Handle<Object> boilerplate(literals->get(literals_index), isolate);
+  if (*boilerplate == isolate->heap()->undefined_value()) {
+    boilerplate = CreateArrayLiteralBoilerplate(isolate, literals, elements);
     if (boilerplate.is_null()) return Failure::Exception();
     // Update the functions literal and return the boilerplate.
     literals->set(literals_index, *boilerplate);
   }
-  return DeepCopyBoilerplate(JSObject::cast(*boilerplate));
+  return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
 }
 
 
-static MaybeObject* Runtime_CreateArrayLiteralShallow(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_CreateArrayLiteralShallow(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 3);
   CONVERT_ARG_CHECKED(FixedArray, literals, 0);
   CONVERT_SMI_CHECKED(literals_index, args[1]);
   CONVERT_ARG_CHECKED(FixedArray, elements, 2);
 
   // Check if boilerplate exists. If not, create it first.
-  Handle<Object> boilerplate(literals->get(literals_index));
-  if (*boilerplate == Heap::undefined_value()) {
-    boilerplate = CreateArrayLiteralBoilerplate(literals, elements);
+  Handle<Object> boilerplate(literals->get(literals_index), isolate);
+  if (*boilerplate == isolate->heap()->undefined_value()) {
+    boilerplate = CreateArrayLiteralBoilerplate(isolate, literals, elements);
     if (boilerplate.is_null()) return Failure::Exception();
     // Update the functions literal and return the boilerplate.
     literals->set(literals_index, *boilerplate);
   }
   if (JSObject::cast(*boilerplate)->elements()->map() ==
-      Heap::fixed_cow_array_map()) {
-    Counters::cow_arrays_created_runtime.Increment();
+      isolate->heap()->fixed_cow_array_map()) {
+    isolate->counters()->cow_arrays_created_runtime()->Increment();
   }
-  return Heap::CopyJSObject(JSObject::cast(*boilerplate));
+  return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
 }
 
 
-static MaybeObject* Runtime_CreateCatchExtensionObject(Arguments args) {
+static MaybeObject* Runtime_CreateCatchExtensionObject(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   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();
+      isolate->context()->global_context()->
+          context_extension_function();
   Object* object;
-  { MaybeObject* maybe_object = Heap::AllocateJSObject(constructor);
+  { MaybeObject* maybe_object = isolate->heap()->AllocateJSObject(constructor);
     if (!maybe_object->ToObject(&object)) return maybe_object;
   }
   // Assign the exception value to the catch variable and make sure
@@ -564,16 +625,18 @@
 }
 
 
-static MaybeObject* Runtime_ClassOf(Arguments args) {
+static MaybeObject* Runtime_ClassOf(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
   Object* obj = args[0];
-  if (!obj->IsJSObject()) return Heap::null_value();
+  if (!obj->IsJSObject()) return isolate->heap()->null_value();
   return JSObject::cast(obj)->class_name();
 }
 
 
-static MaybeObject* Runtime_IsInPrototypeChain(Arguments args) {
+static MaybeObject* Runtime_IsInPrototypeChain(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
   // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
@@ -581,15 +644,16 @@
   Object* V = args[1];
   while (true) {
     Object* prototype = V->GetPrototype();
-    if (prototype->IsNull()) return Heap::false_value();
-    if (O == prototype) return Heap::true_value();
+    if (prototype->IsNull()) return isolate->heap()->false_value();
+    if (O == prototype) return isolate->heap()->true_value();
     V = prototype;
   }
 }
 
 
 // Inserts an object as the hidden prototype of another object.
-static MaybeObject* Runtime_SetHiddenPrototype(Arguments args) {
+static MaybeObject* Runtime_SetHiddenPrototype(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
   CONVERT_CHECKED(JSObject, jsobject, args[0]);
@@ -627,15 +691,16 @@
   new_map->set_prototype(proto);
   jsobject->set_map(new_map);
 
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_IsConstructCall(Arguments args) {
+static MaybeObject* Runtime_IsConstructCall(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 0);
   JavaScriptFrameIterator it;
-  return Heap::ToBoolean(it.frame()->IsConstructor());
+  return isolate->heap()->ToBoolean(it.frame()->IsConstructor());
 }
 
 
@@ -682,9 +747,10 @@
 
   JSObject* holder = result->holder();
   JSObject* current = obj;
+  Isolate* isolate = obj->GetIsolate();
   while (true) {
     if (current->IsAccessCheckNeeded() &&
-        !Top::MayNamedAccess(current, name, access_type)) {
+        !isolate->MayNamedAccess(current, name, access_type)) {
       // Access check callback denied the access, but some properties
       // can have a special permissions which override callbacks descision
       // (currently see v8::AccessControl).
@@ -721,7 +787,7 @@
       break;
   }
 
-  Top::ReportFailedAccessCheck(current, access_type);
+  isolate->ReportFailedAccessCheck(current, access_type);
   return false;
 }
 
@@ -731,7 +797,7 @@
                                uint32_t index,
                                v8::AccessType access_type) {
   if (obj->IsAccessCheckNeeded() &&
-      !Top::MayIndexedAccess(obj, index, access_type)) {
+      !obj->GetIsolate()->MayIndexedAccess(obj, index, access_type)) {
     return false;
   }
 
@@ -758,11 +824,13 @@
 //         [false, value, Writeable, Enumerable, Configurable]
 //  if args[1] is an accessor on args[0]
 //         [true, GetFunction, SetFunction, Enumerable, Configurable]
-static MaybeObject* Runtime_GetOwnProperty(Arguments args) {
+static MaybeObject* Runtime_GetOwnProperty(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
-  HandleScope scope;
-  Handle<FixedArray> elms = Factory::NewFixedArray(DESCRIPTOR_SIZE);
-  Handle<JSArray> desc = Factory::NewJSArrayWithElements(elms);
+  Heap* heap = isolate->heap();
+  HandleScope scope(isolate);
+  Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
+  Handle<JSArray> desc = isolate->factory()->NewJSArrayWithElements(elms);
   LookupResult result;
   CONVERT_ARG_CHECKED(JSObject, obj, 0);
   CONVERT_ARG_CHECKED(String, name, 1);
@@ -772,7 +840,7 @@
   if (name->AsArrayIndex(&index)) {
     switch (obj->HasLocalElement(index)) {
       case JSObject::UNDEFINED_ELEMENT:
-        return Heap::undefined_value();
+        return heap->undefined_value();
 
       case JSObject::STRING_CHARACTER_ELEMENT: {
         // Special handling of string objects according to ECMAScript 5
@@ -783,23 +851,23 @@
         Handle<String> str(String::cast(js_value->value()));
         Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED);
 
-        elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
+        elms->set(IS_ACCESSOR_INDEX, heap->false_value());
         elms->set(VALUE_INDEX, *substr);
-        elms->set(WRITABLE_INDEX, Heap::false_value());
-        elms->set(ENUMERABLE_INDEX,  Heap::false_value());
-        elms->set(CONFIGURABLE_INDEX, Heap::false_value());
+        elms->set(WRITABLE_INDEX, heap->false_value());
+        elms->set(ENUMERABLE_INDEX,  heap->false_value());
+        elms->set(CONFIGURABLE_INDEX, heap->false_value());
         return *desc;
       }
 
       case JSObject::INTERCEPTED_ELEMENT:
       case JSObject::FAST_ELEMENT: {
-        elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
+        elms->set(IS_ACCESSOR_INDEX, heap->false_value());
         Handle<Object> value = GetElement(obj, index);
-        RETURN_IF_EMPTY_HANDLE(value);
+        RETURN_IF_EMPTY_HANDLE(isolate, value);
         elms->set(VALUE_INDEX, *value);
-        elms->set(WRITABLE_INDEX, Heap::true_value());
-        elms->set(ENUMERABLE_INDEX,  Heap::true_value());
-        elms->set(CONFIGURABLE_INDEX, Heap::true_value());
+        elms->set(WRITABLE_INDEX, heap->true_value());
+        elms->set(ENUMERABLE_INDEX,  heap->true_value());
+        elms->set(CONFIGURABLE_INDEX, heap->true_value());
         return *desc;
       }
 
@@ -807,7 +875,7 @@
         Handle<JSObject> holder = obj;
         if (obj->IsJSGlobalProxy()) {
           Object* proto = obj->GetPrototype();
-          if (proto->IsNull()) return Heap::undefined_value();
+          if (proto->IsNull()) return heap->undefined_value();
           ASSERT(proto->IsJSGlobalObject());
           holder = Handle<JSObject>(JSObject::cast(proto));
         }
@@ -820,7 +888,7 @@
             // This is an accessor property with getter and/or setter.
             FixedArray* callbacks =
                 FixedArray::cast(dictionary->ValueAt(entry));
-            elms->set(IS_ACCESSOR_INDEX, Heap::true_value());
+            elms->set(IS_ACCESSOR_INDEX, heap->true_value());
             if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) {
               elms->set(GETTER_INDEX, callbacks->get(0));
             }
@@ -831,19 +899,19 @@
           }
           case NORMAL: {
             // This is a data property.
-            elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
+            elms->set(IS_ACCESSOR_INDEX, heap->false_value());
             Handle<Object> value = GetElement(obj, index);
             ASSERT(!value.is_null());
             elms->set(VALUE_INDEX, *value);
-            elms->set(WRITABLE_INDEX, Heap::ToBoolean(!details.IsReadOnly()));
+            elms->set(WRITABLE_INDEX, heap->ToBoolean(!details.IsReadOnly()));
             break;
           }
           default:
             UNREACHABLE();
             break;
         }
-        elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!details.IsDontEnum()));
-        elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete()));
+        elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!details.IsDontEnum()));
+        elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!details.IsDontDelete()));
         return *desc;
       }
     }
@@ -853,22 +921,22 @@
   GetOwnPropertyImplementation(*obj, *name, &result);
 
   if (!result.IsProperty()) {
-    return Heap::undefined_value();
+    return heap->undefined_value();
   }
 
   if (!CheckAccess(*obj, *name, &result, v8::ACCESS_HAS)) {
-    return Heap::false_value();
+    return heap->false_value();
   }
 
-  elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!result.IsDontEnum()));
-  elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!result.IsDontDelete()));
+  elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!result.IsDontEnum()));
+  elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete()));
 
   bool is_js_accessor = (result.type() == CALLBACKS) &&
                         (result.GetCallbackObject()->IsFixedArray());
 
   if (is_js_accessor) {
     // __defineGetter__/__defineSetter__ callback.
-    elms->set(IS_ACCESSOR_INDEX, Heap::true_value());
+    elms->set(IS_ACCESSOR_INDEX, heap->true_value());
 
     FixedArray* structure = FixedArray::cast(result.GetCallbackObject());
     if (CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) {
@@ -878,8 +946,8 @@
       elms->set(SETTER_INDEX, structure->get(1));
     }
   } else {
-    elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
-    elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly()));
+    elms->set(IS_ACCESSOR_INDEX, heap->false_value());
+    elms->set(WRITABLE_INDEX, heap->ToBoolean(!result.IsReadOnly()));
 
     PropertyAttributes attrs;
     Object* value;
@@ -894,29 +962,32 @@
 }
 
 
-static MaybeObject* Runtime_PreventExtensions(Arguments args) {
+static MaybeObject* Runtime_PreventExtensions(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 1);
   CONVERT_CHECKED(JSObject, obj, args[0]);
   return obj->PreventExtensions();
 }
 
 
-static MaybeObject* Runtime_IsExtensible(Arguments args) {
+static MaybeObject* Runtime_IsExtensible(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 1);
   CONVERT_CHECKED(JSObject, obj, args[0]);
   if (obj->IsJSGlobalProxy()) {
     Object* proto = obj->GetPrototype();
-    if (proto->IsNull()) return Heap::false_value();
+    if (proto->IsNull()) return isolate->heap()->false_value();
     ASSERT(proto->IsJSGlobalObject());
     obj = JSObject::cast(proto);
   }
-  return obj->map()->is_extensible() ? Heap::true_value()
-                                     : Heap::false_value();
+  return obj->map()->is_extensible() ? isolate->heap()->true_value()
+                                     : isolate->heap()->false_value();
 }
 
 
-static MaybeObject* Runtime_RegExpCompile(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_RegExpCompile(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 3);
   CONVERT_ARG_CHECKED(JSRegExp, re, 0);
   CONVERT_ARG_CHECKED(String, pattern, 1);
@@ -927,23 +998,26 @@
 }
 
 
-static MaybeObject* Runtime_CreateApiFunction(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_CreateApiFunction(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   CONVERT_ARG_CHECKED(FunctionTemplateInfo, data, 0);
-  return *Factory::CreateApiFunction(data);
+  return *isolate->factory()->CreateApiFunction(data);
 }
 
 
-static MaybeObject* Runtime_IsTemplate(Arguments args) {
+static MaybeObject* Runtime_IsTemplate(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 1);
   Object* arg = args[0];
   bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
-  return Heap::ToBoolean(result);
+  return isolate->heap()->ToBoolean(result);
 }
 
 
-static MaybeObject* Runtime_GetTemplateField(Arguments args) {
+static MaybeObject* Runtime_GetTemplateField(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
   CONVERT_CHECKED(HeapObject, templ, args[0]);
   CONVERT_CHECKED(Smi, field, args[1]);
@@ -962,7 +1036,8 @@
 }
 
 
-static MaybeObject* Runtime_DisableAccessChecks(Arguments args) {
+static MaybeObject* Runtime_DisableAccessChecks(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 1);
   CONVERT_CHECKED(HeapObject, object, args[0]);
   Map* old_map = object->map();
@@ -977,11 +1052,13 @@
     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();
+  return needs_access_checks ? isolate->heap()->true_value()
+                             : isolate->heap()->false_value();
 }
 
 
-static MaybeObject* Runtime_EnableAccessChecks(Arguments args) {
+static MaybeObject* Runtime_EnableAccessChecks(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 1);
   CONVERT_CHECKED(HeapObject, object, args[0]);
   Map* old_map = object->map();
@@ -995,24 +1072,29 @@
     Map::cast(new_map)->set_is_access_check_needed(true);
     object->set_map(Map::cast(new_map));
   }
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static Failure* ThrowRedeclarationError(const char* type, Handle<String> name) {
-  HandleScope scope;
-  Handle<Object> type_handle = Factory::NewStringFromAscii(CStrVector(type));
+static Failure* ThrowRedeclarationError(Isolate* isolate,
+                                        const char* type,
+                                        Handle<String> name) {
+  HandleScope scope(isolate);
+  Handle<Object> type_handle =
+      isolate->factory()->NewStringFromAscii(CStrVector(type));
   Handle<Object> args[2] = { type_handle, name };
   Handle<Object> error =
-      Factory::NewTypeError("redeclaration", HandleVector(args, 2));
-  return Top::Throw(*error);
+      isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
+  return isolate->Throw(*error);
 }
 
 
-static MaybeObject* Runtime_DeclareGlobals(Arguments args) {
+static MaybeObject* Runtime_DeclareGlobals(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 4);
-  HandleScope scope;
-  Handle<GlobalObject> global = Handle<GlobalObject>(Top::context()->global());
+  HandleScope scope(isolate);
+  Handle<GlobalObject> global = Handle<GlobalObject>(
+      isolate->context()->global());
 
   Handle<Context> context = args.at<Context>(0);
   CONVERT_ARG_CHECKED(FixedArray, pairs, 1);
@@ -1030,9 +1112,9 @@
   // Traverse the name/value pairs and set the properties.
   int length = pairs->length();
   for (int i = 0; i < length; i += 2) {
-    HandleScope scope;
+    HandleScope scope(isolate);
     Handle<String> name(String::cast(pairs->get(i)));
-    Handle<Object> value(pairs->get(i + 1));
+    Handle<Object> value(pairs->get(i + 1), isolate);
 
     // We have to declare a global const property. To capture we only
     // assign to it when evaluating the assignment for "const x =
@@ -1062,7 +1144,7 @@
             // 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);
+              return ThrowRedeclarationError(isolate, type, name);
             };
             // The property already exists without conflicting: Go to
             // the next declaration.
@@ -1074,12 +1156,12 @@
           // For const properties, we treat a callback with this name
           // even in the prototype as a conflicting declaration.
           if (is_const_property && (lookup.type() == CALLBACKS)) {
-            return ThrowRedeclarationError("const", name);
+            return ThrowRedeclarationError(isolate, "const", name);
           }
           // Otherwise, we check for locally conflicting declarations.
           if (is_local && (is_read_only || is_const_property)) {
             const char* type = (is_read_only) ? "const" : "var";
-            return ThrowRedeclarationError(type, name);
+            return ThrowRedeclarationError(isolate, type, name);
           }
           // The property already exists without conflicting: Go to
           // the next declaration.
@@ -1091,7 +1173,9 @@
       Handle<SharedFunctionInfo> shared =
           Handle<SharedFunctionInfo>::cast(value);
       Handle<JSFunction> function =
-          Factory::NewFunctionFromSharedFunctionInfo(shared, context, TENURED);
+          isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
+                                                                context,
+                                                                TENURED);
       value = function;
     }
 
@@ -1113,7 +1197,7 @@
         (lookup.type() != INTERCEPTOR) &&
         (lookup.IsReadOnly() || is_const_property)) {
       const char* type = (lookup.IsReadOnly()) ? "const" : "var";
-      return ThrowRedeclarationError(type, name);
+      return ThrowRedeclarationError(isolate, type, name);
     }
 
     // Safari does not allow the invocation of callback setters for
@@ -1129,12 +1213,14 @@
         attributes = static_cast<PropertyAttributes>(
             attributes | (lookup.GetAttributes() & DONT_DELETE));
       }
-      RETURN_IF_EMPTY_HANDLE(SetLocalPropertyIgnoreAttributes(global,
+      RETURN_IF_EMPTY_HANDLE(isolate,
+                             SetLocalPropertyIgnoreAttributes(global,
                                                               name,
                                                               value,
                                                               attributes));
     } else {
-      RETURN_IF_EMPTY_HANDLE(SetProperty(global,
+      RETURN_IF_EMPTY_HANDLE(isolate,
+                             SetProperty(global,
                                          name,
                                          value,
                                          attributes,
@@ -1142,13 +1228,14 @@
     }
   }
 
-  ASSERT(!Top::has_pending_exception());
-  return Heap::undefined_value();
+  ASSERT(!isolate->has_pending_exception());
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_DeclareContextSlot(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_DeclareContextSlot(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 4);
 
   CONVERT_ARG_CHECKED(Context, context, 0);
@@ -1156,7 +1243,7 @@
   PropertyAttributes mode =
       static_cast<PropertyAttributes>(Smi::cast(args[2])->value());
   RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
-  Handle<Object> initial_value(args[3]);
+  Handle<Object> initial_value(args[3], isolate);
 
   // Declarations are always done in the function context.
   context = Handle<Context>(context->fcontext());
@@ -1175,7 +1262,7 @@
       // 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);
+      return ThrowRedeclarationError(isolate, type, name);
     }
 
     // Initialize it if necessary.
@@ -1200,6 +1287,7 @@
         // Slow case: The property is not in the FixedArray part of the context.
         Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
         RETURN_IF_EMPTY_HANDLE(
+            isolate,
             SetProperty(context_ext, name, initial_value,
                         mode, kNonStrictMode));
       }
@@ -1216,7 +1304,8 @@
     } else {
       // The function context's extension context does not exists - allocate
       // it.
-      context_ext = Factory::NewJSObject(Top::context_extension_function());
+      context_ext = isolate->factory()->NewJSObject(
+          isolate->context_extension_function());
       // And store it in the extension slot.
       context->set_extension(*context_ext);
     }
@@ -1226,7 +1315,7 @@
     // 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());
+    Handle<Object> value(isolate->heap()->undefined_value(), isolate);
     if (*initial_value != NULL) value = initial_value;
     // Declaring a const context slot is a conflicting declaration if
     // there is a callback with that name in a prototype. It is
@@ -1239,18 +1328,20 @@
       LookupResult lookup;
       context_ext->Lookup(*name, &lookup);
       if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) {
-        return ThrowRedeclarationError("const", name);
+        return ThrowRedeclarationError(isolate, "const", name);
       }
     }
-    RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, mode,
+    RETURN_IF_EMPTY_HANDLE(isolate,
+                           SetProperty(context_ext, name, value, mode,
                                        kNonStrictMode));
   }
 
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) {
+static MaybeObject* Runtime_InitializeVarGlobal(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation nha;
   // args[0] == name
   // args[1] == strict_mode
@@ -1262,7 +1353,7 @@
   bool assign = args.length() == 3;
 
   CONVERT_ARG_CHECKED(String, name, 0);
-  GlobalObject* global = Top::context()->global();
+  GlobalObject* global = isolate->context()->global();
   RUNTIME_ASSERT(args[1]->IsSmi());
   StrictModeFlag strict_mode =
       static_cast<StrictModeFlag>(Smi::cast(args[1])->value());
@@ -1288,8 +1379,8 @@
       if (lookup.IsReadOnly()) {
         // If we found readonly property on one of hidden prototypes,
         // just shadow it.
-        if (real_holder != Top::context()->global()) break;
-        return ThrowRedeclarationError("const", name);
+        if (real_holder != isolate->context()->global()) break;
+        return ThrowRedeclarationError(isolate, "const", name);
       }
 
       // Determine if this is a redeclaration of an intercepted read-only
@@ -1297,7 +1388,7 @@
       bool found = true;
       PropertyType type = lookup.type();
       if (type == INTERCEPTOR) {
-        HandleScope handle_scope;
+        HandleScope handle_scope(isolate);
         Handle<JSObject> holder(real_holder);
         PropertyAttributes intercepted = holder->GetPropertyAttribute(*name);
         real_holder = *holder;
@@ -1310,19 +1401,19 @@
           // overwrite it with a variable declaration we must throw a
           // re-declaration error.  However if we found readonly property
           // on one of hidden prototypes, just shadow it.
-          if (real_holder != Top::context()->global()) break;
-          return ThrowRedeclarationError("const", name);
+          if (real_holder != isolate->context()->global()) break;
+          return ThrowRedeclarationError(isolate, "const", name);
         }
       }
 
       if (found && !assign) {
         // The global property is there and we're not assigning any value
         // to it. Just return.
-        return Heap::undefined_value();
+        return isolate->heap()->undefined_value();
       }
 
       // Assign the value (or undefined) to the property.
-      Object* value = (assign) ? args[2] : Heap::undefined_value();
+      Object* value = (assign) ? args[2] : isolate->heap()->undefined_value();
       return real_holder->SetProperty(
           &lookup, *name, value, attributes, strict_mode);
     }
@@ -1337,15 +1428,16 @@
     real_holder = JSObject::cast(proto);
   }
 
-  global = Top::context()->global();
+  global = isolate->context()->global();
   if (assign) {
     return global->SetProperty(*name, args[2], attributes, strict_mode);
   }
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_InitializeConstGlobal(Arguments args) {
+static MaybeObject* Runtime_InitializeConstGlobal(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   // All constants are declared with an initial value. The name
   // of the constant is the first argument and the initial value
   // is the second.
@@ -1354,7 +1446,7 @@
   Handle<Object> value = args.at<Object>(1);
 
   // Get the current global object from top.
-  GlobalObject* global = Top::context()->global();
+  GlobalObject* global = isolate->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.
@@ -1379,7 +1471,7 @@
   // need to ask it for the property attributes.
   if (!lookup.IsReadOnly()) {
     if (lookup.type() != INTERCEPTOR) {
-      return ThrowRedeclarationError("var", name);
+      return ThrowRedeclarationError(isolate, "var", name);
     }
 
     PropertyAttributes intercepted = global->GetPropertyAttribute(*name);
@@ -1387,20 +1479,21 @@
     // 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);
+      return ThrowRedeclarationError(isolate, "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.
-    HandleScope handle_scope;
-    Handle<GlobalObject> global(Top::context()->global());
+    HandleScope handle_scope(isolate);
+    Handle<GlobalObject> global(isolate->context()->global());
 
     // BUG 1213575: 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...
     // Passing non-strict mode because the property is writable.
-    RETURN_IF_EMPTY_HANDLE(SetProperty(global,
+    RETURN_IF_EMPTY_HANDLE(isolate,
+                           SetProperty(global,
                                        name,
                                        value,
                                        attributes,
@@ -1434,11 +1527,13 @@
 }
 
 
-static MaybeObject* Runtime_InitializeConstContextSlot(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_InitializeConstContextSlot(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 3);
 
-  Handle<Object> value(args[0]);
+  Handle<Object> value(args[0], isolate);
   ASSERT(!value->IsTheHole());
   CONVERT_ARG_CHECKED(Context, context, 1);
   Handle<String> name(String::cast(args[2]));
@@ -1479,6 +1574,7 @@
       ASSERT((attributes & READ_ONLY) == 0);
       Handle<JSObject> arguments(Handle<JSObject>::cast(holder));
       RETURN_IF_EMPTY_HANDLE(
+          isolate,
           SetElement(arguments, index, value, kNonStrictMode));
     }
     return *value;
@@ -1487,9 +1583,11 @@
   // The property could not be found, we introduce it in the global
   // context.
   if (attributes == ABSENT) {
-    Handle<JSObject> global = Handle<JSObject>(Top::context()->global());
+    Handle<JSObject> global = Handle<JSObject>(
+        isolate->context()->global());
     // Strict mode not needed (const disallowed in strict mode).
     RETURN_IF_EMPTY_HANDLE(
+        isolate,
         SetProperty(global, name, value, NONE, kNonStrictMode));
     return *value;
   }
@@ -1529,6 +1627,7 @@
     if ((attributes & READ_ONLY) == 0) {
       // Strict mode not needed (const disallowed in strict mode).
       RETURN_IF_EMPTY_HANDLE(
+          isolate,
           SetProperty(context_ext, name, value, attributes, kNonStrictMode));
     }
   }
@@ -1538,8 +1637,9 @@
 
 
 static MaybeObject* Runtime_OptimizeObjectForAddingMultipleProperties(
-    Arguments args) {
-  HandleScope scope;
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 2);
   CONVERT_ARG_CHECKED(JSObject, object, 0);
   CONVERT_SMI_CHECKED(properties, args[1]);
@@ -1550,8 +1650,9 @@
 }
 
 
-static MaybeObject* Runtime_RegExpExec(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_RegExpExec(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 4);
   CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
   CONVERT_ARG_CHECKED(String, subject, 1);
@@ -1562,7 +1663,7 @@
   RUNTIME_ASSERT(last_match_info->HasFastElements());
   RUNTIME_ASSERT(index >= 0);
   RUNTIME_ASSERT(index <= subject->length());
-  Counters::regexp_entry_runtime.Increment();
+  isolate->counters()->regexp_entry_runtime()->Increment();
   Handle<Object> result = RegExpImpl::Exec(regexp,
                                            subject,
                                            index,
@@ -1572,31 +1673,31 @@
 }
 
 
-static MaybeObject* Runtime_RegExpConstructResult(Arguments args) {
+static MaybeObject* Runtime_RegExpConstructResult(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 3);
   CONVERT_SMI_CHECKED(elements_count, args[0]);
   if (elements_count > JSArray::kMaxFastElementsLength) {
-    return Top::ThrowIllegalOperation();
+    return isolate->ThrowIllegalOperation();
   }
   Object* new_object;
   { MaybeObject* maybe_new_object =
-        Heap::AllocateFixedArrayWithHoles(elements_count);
+        isolate->heap()->AllocateFixedArrayWithHoles(elements_count);
     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
   }
   FixedArray* elements = FixedArray::cast(new_object);
-  { MaybeObject* maybe_new_object = Heap::AllocateRaw(JSRegExpResult::kSize,
-                                                      NEW_SPACE,
-                                                      OLD_POINTER_SPACE);
+  { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
+      JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE);
     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
   }
   {
     AssertNoAllocation no_gc;
-    HandleScope scope;
+    HandleScope scope(isolate);
     reinterpret_cast<HeapObject*>(new_object)->
-        set_map(Top::global_context()->regexp_result_map());
+        set_map(isolate->global_context()->regexp_result_map());
   }
   JSArray* array = JSArray::cast(new_object);
-  array->set_properties(Heap::empty_fixed_array());
+  array->set_properties(isolate->heap()->empty_fixed_array());
   array->set_elements(elements);
   array->set_length(Smi::FromInt(elements_count));
   // Write in-object properties after the length of the array.
@@ -1606,20 +1707,21 @@
 }
 
 
-static MaybeObject* Runtime_RegExpInitializeObject(Arguments args) {
+static MaybeObject* Runtime_RegExpInitializeObject(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   AssertNoAllocation no_alloc;
   ASSERT(args.length() == 5);
   CONVERT_CHECKED(JSRegExp, regexp, args[0]);
   CONVERT_CHECKED(String, source, args[1]);
 
   Object* global = args[2];
-  if (!global->IsTrue()) global = Heap::false_value();
+  if (!global->IsTrue()) global = isolate->heap()->false_value();
 
   Object* ignoreCase = args[3];
-  if (!ignoreCase->IsTrue()) ignoreCase = Heap::false_value();
+  if (!ignoreCase->IsTrue()) ignoreCase = isolate->heap()->false_value();
 
   Object* multiline = args[4];
-  if (!multiline->IsTrue()) multiline = Heap::false_value();
+  if (!multiline->IsTrue()) multiline = isolate->heap()->false_value();
 
   Map* map = regexp->map();
   Object* constructor = map->constructor();
@@ -1638,33 +1740,32 @@
     return regexp;
   }
 
-  // Map has changed, so use generic, but slower, method.  Since these
-  // properties were all added as DONT_DELETE they must be present and
-  // normal so no failures can be expected.
+  // Map has changed, so use generic, but slower, method.
   PropertyAttributes final =
       static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
   PropertyAttributes writable =
       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
+  Heap* heap = isolate->heap();
   MaybeObject* result;
-  result = regexp->SetLocalPropertyIgnoreAttributes(Heap::source_symbol(),
+  result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_symbol(),
                                                     source,
                                                     final);
   ASSERT(!result->IsFailure());
-  result = regexp->SetLocalPropertyIgnoreAttributes(Heap::global_symbol(),
+  result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_symbol(),
                                                     global,
                                                     final);
   ASSERT(!result->IsFailure());
   result =
-      regexp->SetLocalPropertyIgnoreAttributes(Heap::ignore_case_symbol(),
+      regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_symbol(),
                                                ignoreCase,
                                                final);
   ASSERT(!result->IsFailure());
-  result = regexp->SetLocalPropertyIgnoreAttributes(Heap::multiline_symbol(),
+  result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_symbol(),
                                                     multiline,
                                                     final);
   ASSERT(!result->IsFailure());
   result =
-      regexp->SetLocalPropertyIgnoreAttributes(Heap::last_index_symbol(),
+      regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_symbol(),
                                                Smi::FromInt(0),
                                                writable);
   ASSERT(!result->IsFailure());
@@ -1673,59 +1774,68 @@
 }
 
 
-static MaybeObject* Runtime_FinishArrayPrototypeSetup(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_FinishArrayPrototypeSetup(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   CONVERT_ARG_CHECKED(JSArray, prototype, 0);
   // This is necessary to enable fast checks for absence of elements
   // on Array.prototype and below.
-  prototype->set_elements(Heap::empty_fixed_array());
+  prototype->set_elements(isolate->heap()->empty_fixed_array());
   return Smi::FromInt(0);
 }
 
 
-static Handle<JSFunction> InstallBuiltin(Handle<JSObject> holder,
+static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
+                                         Handle<JSObject> holder,
                                          const char* name,
                                          Builtins::Name builtin_name) {
-  Handle<String> key = Factory::LookupAsciiSymbol(name);
-  Handle<Code> code(Builtins::builtin(builtin_name));
-  Handle<JSFunction> optimized = Factory::NewFunction(key,
-                                                      JS_OBJECT_TYPE,
-                                                      JSObject::kHeaderSize,
-                                                      code,
-                                                      false);
+  Handle<String> key = isolate->factory()->LookupAsciiSymbol(name);
+  Handle<Code> code(isolate->builtins()->builtin(builtin_name));
+  Handle<JSFunction> optimized =
+      isolate->factory()->NewFunction(key,
+                                      JS_OBJECT_TYPE,
+                                      JSObject::kHeaderSize,
+                                      code,
+                                      false);
   optimized->shared()->DontAdaptArguments();
   SetProperty(holder, key, optimized, NONE, kStrictMode);
   return optimized;
 }
 
 
-static MaybeObject* Runtime_SpecialArrayFunctions(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_SpecialArrayFunctions(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   CONVERT_ARG_CHECKED(JSObject, holder, 0);
 
-  InstallBuiltin(holder, "pop", Builtins::ArrayPop);
-  InstallBuiltin(holder, "push", Builtins::ArrayPush);
-  InstallBuiltin(holder, "shift", Builtins::ArrayShift);
-  InstallBuiltin(holder, "unshift", Builtins::ArrayUnshift);
-  InstallBuiltin(holder, "slice", Builtins::ArraySlice);
-  InstallBuiltin(holder, "splice", Builtins::ArraySplice);
-  InstallBuiltin(holder, "concat", Builtins::ArrayConcat);
+  InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
+  InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
+  InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
+  InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
+  InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
+  InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
+  InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
 
   return *holder;
 }
 
 
-static MaybeObject* Runtime_GetGlobalReceiver(Arguments args) {
+static MaybeObject* Runtime_GetGlobalReceiver(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   // Returns a real global receiver, not one of builtins object.
-  Context* global_context = Top::context()->global()->global_context();
+  Context* global_context =
+      isolate->context()->global()->global_context();
   return global_context->global()->global_receiver();
 }
 
 
-static MaybeObject* Runtime_MaterializeRegExpLiteral(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_MaterializeRegExpLiteral(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 4);
   CONVERT_ARG_CHECKED(FixedArray, literals, 0);
   int index = Smi::cast(args[1])->value();
@@ -1746,7 +1856,7 @@
       RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
                                       &has_pending_exception);
   if (has_pending_exception) {
-    ASSERT(Top::has_pending_exception());
+    ASSERT(isolate->has_pending_exception());
     return Failure::Exception();
   }
   literals->set(index, *regexp);
@@ -1754,7 +1864,8 @@
 }
 
 
-static MaybeObject* Runtime_FunctionGetName(Arguments args) {
+static MaybeObject* Runtime_FunctionGetName(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
@@ -1763,44 +1874,47 @@
 }
 
 
-static MaybeObject* Runtime_FunctionSetName(Arguments args) {
+static MaybeObject* Runtime_FunctionSetName(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   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();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_FunctionRemovePrototype(Arguments args) {
+static MaybeObject* Runtime_FunctionRemovePrototype(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
   CONVERT_CHECKED(JSFunction, f, args[0]);
-  Object* obj;
-  { MaybeObject* maybe_obj = f->RemovePrototype();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  Object* obj = f->RemovePrototype();
+  if (obj->IsFailure()) return obj;
 
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_FunctionGetScript(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_FunctionGetScript(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   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();
+  Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
+  if (!script->IsScript()) return isolate->heap()->undefined_value();
 
   return *GetScriptWrapper(Handle<Script>::cast(script));
 }
 
 
-static MaybeObject* Runtime_FunctionGetSourceCode(Arguments args) {
+static MaybeObject* Runtime_FunctionGetSourceCode(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
@@ -1809,7 +1923,9 @@
 }
 
 
-static MaybeObject* Runtime_FunctionGetScriptSourcePosition(Arguments args) {
+static MaybeObject* Runtime_FunctionGetScriptSourcePosition(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
@@ -1819,7 +1935,9 @@
 }
 
 
-static MaybeObject* Runtime_FunctionGetPositionForOffset(Arguments args) {
+static MaybeObject* Runtime_FunctionGetPositionForOffset(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
 
   CONVERT_CHECKED(Code, code, args[0]);
@@ -1832,19 +1950,21 @@
 }
 
 
-
-static MaybeObject* Runtime_FunctionSetInstanceClassName(Arguments args) {
+static MaybeObject* Runtime_FunctionSetInstanceClassName(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   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();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_FunctionSetLength(Arguments args) {
+static MaybeObject* Runtime_FunctionSetLength(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
@@ -1855,7 +1975,8 @@
 }
 
 
-static MaybeObject* Runtime_FunctionSetPrototype(Arguments args) {
+static MaybeObject* Runtime_FunctionSetPrototype(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
@@ -1870,26 +1991,31 @@
 }
 
 
-static MaybeObject* Runtime_FunctionIsAPIFunction(Arguments args) {
+static MaybeObject* Runtime_FunctionIsAPIFunction(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
   CONVERT_CHECKED(JSFunction, f, args[0]);
-  return f->shared()->IsApiFunction() ? Heap::true_value()
-                                      : Heap::false_value();
+  return f->shared()->IsApiFunction() ? isolate->heap()->true_value()
+                                      : isolate->heap()->false_value();
 }
 
-static MaybeObject* Runtime_FunctionIsBuiltin(Arguments args) {
+
+static MaybeObject* Runtime_FunctionIsBuiltin(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
   CONVERT_CHECKED(JSFunction, f, args[0]);
-  return f->IsBuiltin() ? Heap::true_value() : Heap::false_value();
+  return f->IsBuiltin() ? isolate->heap()->true_value() :
+                          isolate->heap()->false_value();
 }
 
 
-static MaybeObject* Runtime_SetCode(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_SetCode(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 2);
 
   CONVERT_ARG_CHECKED(JSFunction, target, 0);
@@ -1921,7 +2047,7 @@
     // 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());
+    target->shared()->set_script(isolate->heap()->undefined_value());
     target->shared()->code()->set_optimizable(false);
     // Clear the optimization hints related to the compiled code as these are no
     // longer valid when the code is overwritten.
@@ -1932,7 +2058,7 @@
     // cross context contamination.
     int number_of_literals = fun->NumberOfLiterals();
     Handle<FixedArray> literals =
-        Factory::NewFixedArray(number_of_literals, TENURED);
+        isolate->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
@@ -1943,7 +2069,7 @@
     // It's okay to skip the write barrier here because the literals
     // are guaranteed to be in old space.
     target->set_literals(*literals, SKIP_WRITE_BARRIER);
-    target->set_next_function_link(Heap::undefined_value());
+    target->set_next_function_link(isolate->heap()->undefined_value());
   }
 
   target->set_context(*context);
@@ -1951,29 +2077,33 @@
 }
 
 
-static MaybeObject* Runtime_SetExpectedNumberOfProperties(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_SetExpectedNumberOfProperties(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 2);
   CONVERT_ARG_CHECKED(JSFunction, function, 0);
   CONVERT_SMI_CHECKED(num, args[1]);
   RUNTIME_ASSERT(num >= 0);
   SetExpectedNofProperties(function, num);
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-MUST_USE_RESULT static MaybeObject* CharFromCode(Object* char_code) {
+MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
+                                                 Object* char_code) {
   uint32_t code;
   if (char_code->ToArrayIndex(&code)) {
     if (code <= 0xffff) {
-      return Heap::LookupSingleCharacterStringFromCode(code);
+      return isolate->heap()->LookupSingleCharacterStringFromCode(code);
     }
   }
-  return Heap::empty_string();
+  return isolate->heap()->empty_string();
 }
 
 
-static MaybeObject* Runtime_StringCharCodeAt(Arguments args) {
+static MaybeObject* Runtime_StringCharCodeAt(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
@@ -1984,7 +2114,7 @@
   uint32_t i = 0;
   if (index->IsSmi()) {
     int value = Smi::cast(index)->value();
-    if (value < 0) return Heap::nan_value();
+    if (value < 0) return isolate->heap()->nan_value();
     i = value;
   } else {
     ASSERT(index->IsHeapNumber());
@@ -2002,24 +2132,25 @@
   subject = String::cast(flat);
 
   if (i >= static_cast<uint32_t>(subject->length())) {
-    return Heap::nan_value();
+    return isolate->heap()->nan_value();
   }
 
   return Smi::FromInt(subject->Get(i));
 }
 
 
-static MaybeObject* Runtime_CharFromCode(Arguments args) {
+static MaybeObject* Runtime_CharFromCode(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  return CharFromCode(args[0]);
+  return CharFromCode(isolate, args[0]);
 }
 
 
 class FixedArrayBuilder {
  public:
-  explicit FixedArrayBuilder(int initial_capacity)
-      : array_(Factory::NewFixedArrayWithHoles(initial_capacity)),
+  explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
+      : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
         length_(0) {
     // Require a non-zero initial size. Ensures that doubling the size to
     // extend the array will work.
@@ -2049,7 +2180,7 @@
         new_length *= 2;
       } while (new_length < required_length);
       Handle<FixedArray> extended_array =
-          Factory::NewFixedArrayWithHoles(new_length);
+          array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
       array_->CopyTo(0, *extended_array, 0, length_);
       array_ = extended_array;
     }
@@ -2080,7 +2211,7 @@
   }
 
   Handle<JSArray> ToJSArray() {
-    Handle<JSArray> result_array = Factory::NewJSArrayWithElements(array_);
+    Handle<JSArray> result_array = FACTORY->NewJSArrayWithElements(array_);
     result_array->set_length(Smi::FromInt(length_));
     return result_array;
   }
@@ -2117,8 +2248,11 @@
 
 class ReplacementStringBuilder {
  public:
-  ReplacementStringBuilder(Handle<String> subject, int estimated_part_count)
-      : array_builder_(estimated_part_count),
+  ReplacementStringBuilder(Heap* heap,
+                           Handle<String> subject,
+                           int estimated_part_count)
+      : heap_(heap),
+        array_builder_(heap->isolate(), estimated_part_count),
         subject_(subject),
         character_count_(0),
         is_ascii_(subject->IsAsciiRepresentation()) {
@@ -2170,7 +2304,7 @@
 
   Handle<String> ToString() {
     if (array_builder_.length() == 0) {
-      return Factory::empty_string();
+      return heap_->isolate()->factory()->empty_string();
     }
 
     Handle<String> joined_string;
@@ -2211,12 +2345,14 @@
 
  private:
   Handle<String> NewRawAsciiString(int size) {
-    CALL_HEAP_FUNCTION(Heap::AllocateRawAsciiString(size), String);
+    CALL_HEAP_FUNCTION(heap_->isolate(),
+                       heap_->AllocateRawAsciiString(size), String);
   }
 
 
   Handle<String> NewRawTwoByteString(int size) {
-    CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(size), String);
+    CALL_HEAP_FUNCTION(heap_->isolate(),
+                       heap_->AllocateRawTwoByteString(size), String);
   }
 
 
@@ -2226,6 +2362,7 @@
     array_builder_.Add(element);
   }
 
+  Heap* heap_;
   FixedArrayBuilder array_builder_;
   Handle<String> subject_;
   int character_count_;
@@ -2436,6 +2573,7 @@
                             capture_count,
                             subject_length);
   }
+  Isolate* isolate = replacement->GetIsolate();
   // 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++) {
@@ -2443,7 +2581,8 @@
     if (tag <= 0) {  // A replacement string slice.
       int from = -tag;
       int to = parts_[i].data;
-      replacement_substrings_.Add(Factory::NewSubString(replacement, from, to));
+      replacement_substrings_.Add(
+          isolate->factory()->NewSubString(replacement, from, to));
       parts_[i].tag = REPLACEMENT_SUBSTRING;
       parts_[i].data = substring_index;
       substring_index++;
@@ -2496,6 +2635,7 @@
 
 
 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString(
+    Isolate* isolate,
     String* subject,
     JSRegExp* regexp,
     String* replacement,
@@ -2503,7 +2643,7 @@
   ASSERT(subject->IsFlat());
   ASSERT(replacement->IsFlat());
 
-  HandleScope handles;
+  HandleScope handles(isolate);
 
   int length = subject->length();
   Handle<String> subject_handle(subject);
@@ -2537,7 +2677,9 @@
   // conservatively.
   int expected_parts =
       (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1;
-  ReplacementStringBuilder builder(subject_handle, expected_parts);
+  ReplacementStringBuilder builder(isolate->heap(),
+                                   subject_handle,
+                                   expected_parts);
 
   // Index of end of last match.
   int prev = 0;
@@ -2553,7 +2695,7 @@
     // so its internal buffer can safely allocate a new handle if it grows.
     builder.EnsureCapacity(parts_added_per_loop);
 
-    HandleScope loop_scope;
+    HandleScope loop_scope(isolate);
     int start, end;
     {
       AssertNoAllocation match_info_array_is_not_in_a_handle;
@@ -2605,12 +2747,13 @@
 
 template <typename ResultSeqString>
 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString(
+    Isolate* isolate,
     String* subject,
     JSRegExp* regexp,
     JSArray* last_match_info) {
   ASSERT(subject->IsFlat());
 
-  HandleScope handles;
+  HandleScope handles(isolate);
 
   Handle<String> subject_handle(subject);
   Handle<JSRegExp> regexp_handle(regexp);
@@ -2624,7 +2767,6 @@
 
   ASSERT(last_match_info_handle->HasFastElements());
 
-  HandleScope loop_scope;
   int start, end;
   {
     AssertNoAllocation match_info_array_is_not_in_a_handle;
@@ -2638,15 +2780,15 @@
   int length = subject->length();
   int new_length = length - (end - start);
   if (new_length == 0) {
-    return Heap::empty_string();
+    return isolate->heap()->empty_string();
   }
   Handle<ResultSeqString> answer;
   if (ResultSeqString::kHasAsciiEncoding) {
-    answer =
-        Handle<ResultSeqString>::cast(Factory::NewRawAsciiString(new_length));
+    answer = Handle<ResultSeqString>::cast(
+        isolate->factory()->NewRawAsciiString(new_length));
   } else {
-    answer =
-        Handle<ResultSeqString>::cast(Factory::NewRawTwoByteString(new_length));
+    answer = Handle<ResultSeqString>::cast(
+        isolate->factory()->NewRawTwoByteString(new_length));
   }
 
   // If the regexp isn't global, only match once.
@@ -2694,7 +2836,7 @@
     if (match->IsNull()) break;
 
     ASSERT(last_match_info_handle->HasFastElements());
-    HandleScope loop_scope;
+    HandleScope loop_scope(isolate);
     {
       AssertNoAllocation match_info_array_is_not_in_a_handle;
       FixedArray* match_info_array =
@@ -2714,7 +2856,7 @@
   }
 
   if (position == 0) {
-    return Heap::empty_string();
+    return isolate->heap()->empty_string();
   }
 
   // Shorten string and fill
@@ -2726,13 +2868,15 @@
   if (delta == 0) return *answer;
 
   Address end_of_string = answer->address() + string_size;
-  Heap::CreateFillerObjectAt(end_of_string, delta);
+  isolate->heap()->CreateFillerObjectAt(end_of_string, delta);
 
   return *answer;
 }
 
 
-static MaybeObject* Runtime_StringReplaceRegExpWithString(Arguments args) {
+static MaybeObject* Runtime_StringReplaceRegExpWithString(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 4);
 
   CONVERT_CHECKED(String, subject, args[0]);
@@ -2765,14 +2909,15 @@
   if (replacement->length() == 0) {
     if (subject->HasOnlyAsciiChars()) {
       return StringReplaceRegExpWithEmptyString<SeqAsciiString>(
-          subject, regexp, last_match_info);
+          isolate, subject, regexp, last_match_info);
     } else {
       return StringReplaceRegExpWithEmptyString<SeqTwoByteString>(
-          subject, regexp, last_match_info);
+          isolate, subject, regexp, last_match_info);
     }
   }
 
-  return StringReplaceRegExpWithString(subject,
+  return StringReplaceRegExpWithString(isolate,
+                                       subject,
                                        regexp,
                                        replacement,
                                        last_match_info);
@@ -2782,7 +2927,8 @@
 // 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,
+int Runtime::StringMatch(Isolate* isolate,
+                         Handle<String> sub,
                          Handle<String> pat,
                          int start_index) {
   ASSERT(0 <= start_index);
@@ -2808,20 +2954,33 @@
   if (seq_pat->IsAsciiRepresentation()) {
     Vector<const char> pat_vector = seq_pat->ToAsciiVector();
     if (seq_sub->IsAsciiRepresentation()) {
-      return SearchString(seq_sub->ToAsciiVector(), pat_vector, start_index);
+      return SearchString(isolate,
+                          seq_sub->ToAsciiVector(),
+                          pat_vector,
+                          start_index);
     }
-    return SearchString(seq_sub->ToUC16Vector(), pat_vector, start_index);
+    return SearchString(isolate,
+                        seq_sub->ToUC16Vector(),
+                        pat_vector,
+                        start_index);
   }
   Vector<const uc16> pat_vector = seq_pat->ToUC16Vector();
   if (seq_sub->IsAsciiRepresentation()) {
-    return SearchString(seq_sub->ToAsciiVector(), pat_vector, start_index);
+    return SearchString(isolate,
+                        seq_sub->ToAsciiVector(),
+                        pat_vector,
+                        start_index);
   }
-  return SearchString(seq_sub->ToUC16Vector(), pat_vector, start_index);
+  return SearchString(isolate,
+                      seq_sub->ToUC16Vector(),
+                      pat_vector,
+                      start_index);
 }
 
 
-static MaybeObject* Runtime_StringIndexOf(Arguments args) {
-  HandleScope scope;  // create a new handle scope
+static MaybeObject* Runtime_StringIndexOf(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);  // create a new handle scope
   ASSERT(args.length() == 3);
 
   CONVERT_ARG_CHECKED(String, sub, 0);
@@ -2832,7 +2991,8 @@
   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
 
   RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
-  int position = Runtime::StringMatch(sub, pat, start_index);
+  int position =
+      Runtime::StringMatch(isolate, sub, pat, start_index);
   return Smi::FromInt(position);
 }
 
@@ -2871,8 +3031,9 @@
   return -1;
 }
 
-static MaybeObject* Runtime_StringLastIndexOf(Arguments args) {
-  HandleScope scope;  // create a new handle scope
+static MaybeObject* Runtime_StringLastIndexOf(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);  // create a new handle scope
   ASSERT(args.length() == 3);
 
   CONVERT_ARG_CHECKED(String, sub, 0);
@@ -2928,7 +3089,8 @@
 }
 
 
-static MaybeObject* Runtime_StringLocaleCompare(Arguments args) {
+static MaybeObject* Runtime_StringLocaleCompare(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
@@ -2958,8 +3120,10 @@
   str1->TryFlatten();
   str2->TryFlatten();
 
-  static StringInputBuffer buf1;
-  static StringInputBuffer buf2;
+  StringInputBuffer& buf1 =
+      *isolate->runtime_state()->string_locale_compare_buf1();
+  StringInputBuffer& buf2 =
+      *isolate->runtime_state()->string_locale_compare_buf2();
 
   buf1.Reset(str1);
   buf2.Reset(str2);
@@ -2974,7 +3138,8 @@
 }
 
 
-static MaybeObject* Runtime_SubString(Arguments args) {
+static MaybeObject* Runtime_SubString(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 3);
 
@@ -2996,12 +3161,13 @@
   RUNTIME_ASSERT(end >= start);
   RUNTIME_ASSERT(start >= 0);
   RUNTIME_ASSERT(end <= value->length());
-  Counters::sub_string_runtime.Increment();
+  isolate->counters()->sub_string_runtime()->Increment();
   return value->SubString(start, end);
 }
 
 
-static MaybeObject* Runtime_StringMatch(Arguments args) {
+static MaybeObject* Runtime_StringMatch(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT_EQ(3, args.length());
 
   CONVERT_ARG_CHECKED(String, subject, 0);
@@ -3015,7 +3181,7 @@
     return Failure::Exception();
   }
   if (match->IsNull()) {
-    return Heap::null_value();
+    return isolate->heap()->null_value();
   }
   int length = subject->length();
 
@@ -3040,14 +3206,14 @@
     }
   } while (!match->IsNull());
   int matches = offsets.length() / 2;
-  Handle<FixedArray> elements = Factory::NewFixedArray(matches);
+  Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
   for (int i = 0; i < matches ; i++) {
     int from = offsets.at(i * 2);
     int to = offsets.at(i * 2 + 1);
-    Handle<String> match = Factory::NewSubString(subject, from, to);
+    Handle<String> match = isolate->factory()->NewSubString(subject, from, to);
     elements->set(i, *match);
   }
-  Handle<JSArray> result = Factory::NewJSArrayWithElements(elements);
+  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
   result->set_length(Smi::FromInt(matches));
   return *result;
 }
@@ -3074,7 +3240,8 @@
 
 
 template <typename SubjectChar, typename PatternChar>
-static bool SearchStringMultiple(Vector<const SubjectChar> subject,
+static bool SearchStringMultiple(Isolate* isolate,
+                                 Vector<const SubjectChar> subject,
                                  Vector<const PatternChar> pattern,
                                  String* pattern_string,
                                  FixedArrayBuilder* builder,
@@ -3083,7 +3250,7 @@
   int subject_length = subject.length();
   int pattern_length = pattern.length();
   int max_search_start = subject_length - pattern_length;
-  StringSearch<PatternChar, SubjectChar> search(pattern);
+  StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
   while (pos <= max_search_start) {
     if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
       *match_pos = pos;
@@ -3116,7 +3283,8 @@
 }
 
 
-static bool SearchStringMultiple(Handle<String> subject,
+static bool SearchStringMultiple(Isolate* isolate,
+                                 Handle<String> subject,
                                  Handle<String> pattern,
                                  Handle<JSArray> last_match_info,
                                  FixedArrayBuilder* builder) {
@@ -3132,13 +3300,15 @@
     if (subject->IsAsciiRepresentation()) {
       Vector<const char> subject_vector = subject->ToAsciiVector();
       if (pattern->IsAsciiRepresentation()) {
-        if (SearchStringMultiple(subject_vector,
+        if (SearchStringMultiple(isolate,
+                                 subject_vector,
                                  pattern->ToAsciiVector(),
                                  *pattern,
                                  builder,
                                  &match_pos)) break;
       } else {
-        if (SearchStringMultiple(subject_vector,
+        if (SearchStringMultiple(isolate,
+                                 subject_vector,
                                  pattern->ToUC16Vector(),
                                  *pattern,
                                  builder,
@@ -3147,13 +3317,15 @@
     } else {
       Vector<const uc16> subject_vector = subject->ToUC16Vector();
       if (pattern->IsAsciiRepresentation()) {
-        if (SearchStringMultiple(subject_vector,
+        if (SearchStringMultiple(isolate,
+                                 subject_vector,
                                  pattern->ToAsciiVector(),
                                  *pattern,
                                  builder,
                                  &match_pos)) break;
       } else {
-        if (SearchStringMultiple(subject_vector,
+        if (SearchStringMultiple(isolate,
+                                 subject_vector,
                                  pattern->ToUC16Vector(),
                                  *pattern,
                                  builder,
@@ -3174,6 +3346,7 @@
 
 
 static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple(
+    Isolate* isolate,
     Handle<String> subject,
     Handle<JSRegExp> regexp,
     Handle<JSArray> last_match_array,
@@ -3204,8 +3377,10 @@
                                                   match_start);
       }
       match_end = register_vector[1];
-      HandleScope loop_scope;
-      builder->Add(*Factory::NewSubString(subject, match_start, match_end));
+      HandleScope loop_scope(isolate);
+      builder->Add(*isolate->factory()->NewSubString(subject,
+                                                     match_start,
+                                                     match_end));
       if (match_start != match_end) {
         pos = match_end;
       } else {
@@ -3238,6 +3413,7 @@
 
 
 static RegExpImpl::IrregexpResult SearchRegExpMultiple(
+    Isolate* isolate,
     Handle<String> subject,
     Handle<JSRegExp> regexp,
     Handle<JSArray> last_match_array,
@@ -3281,31 +3457,32 @@
 
       {
         // Avoid accumulating new handles inside loop.
-        HandleScope temp_scope;
+        HandleScope temp_scope(isolate);
         // Arguments array to replace function is match, captures, index and
         // subject, i.e., 3 + capture count in total.
-        Handle<FixedArray> elements = Factory::NewFixedArray(3 + capture_count);
-        Handle<String> match = Factory::NewSubString(subject,
-                                                     match_start,
-                                                     match_end);
+        Handle<FixedArray> elements =
+            isolate->factory()->NewFixedArray(3 + capture_count);
+        Handle<String> match = isolate->factory()->NewSubString(subject,
+                                                                match_start,
+                                                                match_end);
         elements->set(0, *match);
         for (int i = 1; i <= capture_count; i++) {
           int start = register_vector[i * 2];
           if (start >= 0) {
             int end = register_vector[i * 2 + 1];
             ASSERT(start <= end);
-            Handle<String> substring = Factory::NewSubString(subject,
-                                                             start,
-                                                             end);
+            Handle<String> substring = isolate->factory()->NewSubString(subject,
+                                                                        start,
+                                                                        end);
             elements->set(i, *substring);
           } else {
             ASSERT(register_vector[i * 2 + 1] < 0);
-            elements->set(i, Heap::undefined_value());
+            elements->set(i, isolate->heap()->undefined_value());
           }
         }
         elements->set(capture_count + 1, Smi::FromInt(match_start));
         elements->set(capture_count + 2, *subject);
-        builder->Add(*Factory::NewJSArrayWithElements(elements));
+        builder->Add(*isolate->factory()->NewJSArrayWithElements(elements));
       }
       // Swap register vectors, so the last successful match is in
       // prev_register_vector.
@@ -3356,9 +3533,10 @@
 }
 
 
-static MaybeObject* Runtime_RegExpExecMultiple(Arguments args) {
+static MaybeObject* Runtime_RegExpExecMultiple(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 4);
-  HandleScope handles;
+  HandleScope handles(isolate);
 
   CONVERT_ARG_CHECKED(String, subject, 1);
   if (!subject->IsFlat()) { FlattenString(subject); }
@@ -3373,7 +3551,7 @@
     result_elements =
         Handle<FixedArray>(FixedArray::cast(result_array->elements()));
   } else {
-    result_elements = Factory::NewFixedArrayWithHoles(16);
+    result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
   }
   FixedArrayBuilder builder(result_elements);
 
@@ -3381,31 +3559,38 @@
     Handle<String> pattern(
         String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex)));
     ASSERT(pattern->IsFlat());
-    if (SearchStringMultiple(subject, pattern, last_match_info, &builder)) {
+    if (SearchStringMultiple(isolate, subject, pattern,
+                             last_match_info, &builder)) {
       return *builder.ToJSArray(result_array);
     }
-    return Heap::null_value();
+    return isolate->heap()->null_value();
   }
 
   ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
 
   RegExpImpl::IrregexpResult result;
   if (regexp->CaptureCount() == 0) {
-    result = SearchRegExpNoCaptureMultiple(subject,
+    result = SearchRegExpNoCaptureMultiple(isolate,
+                                           subject,
                                            regexp,
                                            last_match_info,
                                            &builder);
   } else {
-    result = SearchRegExpMultiple(subject, regexp, last_match_info, &builder);
+    result = SearchRegExpMultiple(isolate,
+                                  subject,
+                                  regexp,
+                                  last_match_info,
+                                  &builder);
   }
   if (result == RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array);
-  if (result == RegExpImpl::RE_FAILURE) return Heap::null_value();
+  if (result == RegExpImpl::RE_FAILURE) return isolate->heap()->null_value();
   ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
   return Failure::Exception();
 }
 
 
-static MaybeObject* Runtime_NumberToRadixString(Arguments args) {
+static MaybeObject* Runtime_NumberToRadixString(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
@@ -3417,100 +3602,108 @@
       RUNTIME_ASSERT(radix <= 36);
       // Character array used for conversion.
       static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
-      return Heap::LookupSingleCharacterStringFromCode(kCharTable[value]);
+      return isolate->heap()->
+          LookupSingleCharacterStringFromCode(kCharTable[value]);
     }
   }
 
   // Slow case.
   CONVERT_DOUBLE_CHECKED(value, args[0]);
   if (isnan(value)) {
-    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
+    return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN"));
   }
   if (isinf(value)) {
     if (value < 0) {
-      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
+      return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity"));
     }
-    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
+    return isolate->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);
-  MaybeObject* result = Heap::AllocateStringFromAscii(CStrVector(str));
+  MaybeObject* result =
+      isolate->heap()->AllocateStringFromAscii(CStrVector(str));
   DeleteArray(str);
   return result;
 }
 
 
-static MaybeObject* Runtime_NumberToFixed(Arguments args) {
+static MaybeObject* Runtime_NumberToFixed(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
   CONVERT_DOUBLE_CHECKED(value, args[0]);
   if (isnan(value)) {
-    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
+    return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN"));
   }
   if (isinf(value)) {
     if (value < 0) {
-      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
+      return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity"));
     }
-    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
+    return isolate->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);
-  MaybeObject* result = Heap::AllocateStringFromAscii(CStrVector(str));
+  MaybeObject* res =
+      isolate->heap()->AllocateStringFromAscii(CStrVector(str));
   DeleteArray(str);
-  return result;
+  return res;
 }
 
 
-static MaybeObject* Runtime_NumberToExponential(Arguments args) {
+static MaybeObject* Runtime_NumberToExponential(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
   CONVERT_DOUBLE_CHECKED(value, args[0]);
   if (isnan(value)) {
-    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
+    return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN"));
   }
   if (isinf(value)) {
     if (value < 0) {
-      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
+      return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity"));
     }
-    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
+    return isolate->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);
-  MaybeObject* result = Heap::AllocateStringFromAscii(CStrVector(str));
+  MaybeObject* res =
+      isolate->heap()->AllocateStringFromAscii(CStrVector(str));
   DeleteArray(str);
-  return result;
+  return res;
 }
 
 
-static MaybeObject* Runtime_NumberToPrecision(Arguments args) {
+static MaybeObject* Runtime_NumberToPrecision(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
   CONVERT_DOUBLE_CHECKED(value, args[0]);
   if (isnan(value)) {
-    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
+    return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN"));
   }
   if (isinf(value)) {
     if (value < 0) {
-      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
+      return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity"));
     }
-    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
+    return isolate->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);
-  MaybeObject* result = Heap::AllocateStringFromAscii(CStrVector(str));
+  MaybeObject* res =
+      isolate->heap()->AllocateStringFromAscii(CStrVector(str));
   DeleteArray(str);
-  return result;
+  return res;
 }
 
 
@@ -3526,7 +3719,8 @@
 }
 
 
-MaybeObject* Runtime::GetElementOrCharAt(Handle<Object> object,
+MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
+                                         Handle<Object> object,
                                          uint32_t index) {
   // Handle [] indexing on Strings
   if (object->IsString()) {
@@ -3556,22 +3750,23 @@
 }
 
 
-MaybeObject* Runtime::GetObjectProperty(Handle<Object> object,
+MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
+                                        Handle<Object> object,
                                         Handle<Object> key) {
-  HandleScope scope;
+  HandleScope scope(isolate);
 
   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);
+        isolate->factory()->NewTypeError("non_object_property_load",
+                                         HandleVector(args, 2));
+    return isolate->Throw(*error);
   }
 
   // Check if the given key is an array index.
   uint32_t index;
   if (key->ToArrayIndex(&index)) {
-    return GetElementOrCharAt(object, index);
+    return GetElementOrCharAt(isolate, object, index);
   }
 
   // Convert the key to a string - possibly by calling back into JavaScript.
@@ -3589,7 +3784,7 @@
   // Check if the name is trivially convertible to an index and get
   // the element if so.
   if (name->AsArrayIndex(&index)) {
-    return GetElementOrCharAt(object, index);
+    return GetElementOrCharAt(isolate, object, index);
   } else {
     PropertyAttributes attr;
     return object->GetProperty(*name, &attr);
@@ -3597,19 +3792,21 @@
 }
 
 
-static MaybeObject* Runtime_GetProperty(Arguments args) {
+static MaybeObject* Runtime_GetProperty(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   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);
+  return Runtime::GetObjectProperty(isolate, object, key);
 }
 
 
 // KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric.
-static MaybeObject* Runtime_KeyedGetProperty(Arguments args) {
+static MaybeObject* Runtime_KeyedGetProperty(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
@@ -3633,17 +3830,18 @@
     if (receiver->HasFastProperties()) {
       // Attempt to use lookup cache.
       Map* receiver_map = receiver->map();
-      int offset = KeyedLookupCache::Lookup(receiver_map, key);
+      KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
+      int offset = keyed_lookup_cache->Lookup(receiver_map, key);
       if (offset != -1) {
         Object* value = receiver->FastPropertyAt(offset);
-        return value->IsTheHole() ? Heap::undefined_value() : value;
+        return value->IsTheHole() ? isolate->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.type() == FIELD) {
         int offset = result.GetFieldIndex();
-        KeyedLookupCache::Update(receiver_map, key, offset);
+        keyed_lookup_cache->Update(receiver_map, key, offset);
         return receiver->FastPropertyAt(offset);
       }
     } else {
@@ -3661,7 +3859,7 @@
     }
   } else if (args[0]->IsString() && args[1]->IsSmi()) {
     // Fast case for string indexing using [] with a smi index.
-    HandleScope scope;
+    HandleScope scope(isolate);
     Handle<String> str = args.at<String>(0);
     int index = Smi::cast(args[1])->value();
     if (index >= 0 && index < str->length()) {
@@ -3671,7 +3869,8 @@
   }
 
   // Fall back to GetObjectProperty.
-  return Runtime::GetObjectProperty(args.at<Object>(0),
+  return Runtime::GetObjectProperty(isolate,
+                                    args.at<Object>(0),
                                     args.at<Object>(1));
 }
 
@@ -3681,9 +3880,11 @@
 // Steps 9c & 12 - replace an existing data property with an accessor property.
 // Step 12 - update an existing accessor property with an accessor or generic
 //           descriptor.
-static MaybeObject* Runtime_DefineOrRedefineAccessorProperty(Arguments args) {
+static MaybeObject* Runtime_DefineOrRedefineAccessorProperty(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 5);
-  HandleScope scope;
+  HandleScope scope(isolate);
   CONVERT_ARG_CHECKED(JSObject, obj, 0);
   CONVERT_CHECKED(String, name, args[1]);
   CONVERT_CHECKED(Smi, flag_setter, args[2]);
@@ -3718,9 +3919,11 @@
 // Steps 9b & 12 - replace an existing accessor property with a data property.
 // Step 12 - update an existing data property with a data or generic
 //           descriptor.
-static MaybeObject* Runtime_DefineOrRedefineDataProperty(Arguments args) {
+static MaybeObject* Runtime_DefineOrRedefineDataProperty(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 4);
-  HandleScope scope;
+  HandleScope scope(isolate);
   CONVERT_ARG_CHECKED(JSObject, js_object, 0);
   CONVERT_ARG_CHECKED(String, name, 1);
   Handle<Object> obj_value = args.at<Object>(2);
@@ -3762,6 +3965,14 @@
   LookupResult result;
   js_object->LookupRealNamedProperty(*name, &result);
 
+  // To be compatible with safari we do not change the value on API objects
+  // in defineProperty. Firefox disagrees here, and actually changes the value.
+  if (result.IsProperty() &&
+      (result.type() == CALLBACKS) &&
+      result.GetCallbackObject()->IsAccessorInfo()) {
+    return isolate->heap()->undefined_value();
+  }
+
   // Take special care when attributes are different and there is already
   // a property. For simplicity we normalize the property which enables us
   // to not worry about changing the instance_descriptor and creating a new
@@ -3784,23 +3995,28 @@
                                                        attr);
   }
 
-  return Runtime::ForceSetObjectProperty(js_object, name, obj_value, attr);
+  return Runtime::ForceSetObjectProperty(isolate,
+                                         js_object,
+                                         name,
+                                         obj_value,
+                                         attr);
 }
 
 
-MaybeObject* Runtime::SetObjectProperty(Handle<Object> object,
+MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
+                                        Handle<Object> object,
                                         Handle<Object> key,
                                         Handle<Object> value,
                                         PropertyAttributes attr,
                                         StrictModeFlag strict_mode) {
-  HandleScope scope;
+  HandleScope scope(isolate);
 
   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);
+        isolate->factory()->NewTypeError("non_object_property_store",
+                                         HandleVector(args, 2));
+    return isolate->Throw(*error);
   }
 
   // If the object isn't a JavaScript object, we ignore the store.
@@ -3854,11 +4070,12 @@
 }
 
 
-MaybeObject* Runtime::ForceSetObjectProperty(Handle<JSObject> js_object,
+MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate,
+                                             Handle<JSObject> js_object,
                                              Handle<Object> key,
                                              Handle<Object> value,
                                              PropertyAttributes attr) {
-  HandleScope scope;
+  HandleScope scope(isolate);
 
   // Check if the given key is an array index.
   uint32_t index;
@@ -3903,9 +4120,10 @@
 }
 
 
-MaybeObject* Runtime::ForceDeleteObjectProperty(Handle<JSObject> js_object,
+MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate,
+                                                Handle<JSObject> js_object,
                                                 Handle<Object> key) {
-  HandleScope scope;
+  HandleScope scope(isolate);
 
   // Check if the given key is an array index.
   uint32_t index;
@@ -3917,7 +4135,7 @@
     // underlying string does nothing with the deletion, we can ignore
     // such deletions.
     if (js_object->IsStringObjectWithCharacterAt(index)) {
-      return Heap::true_value();
+      return isolate->heap()->true_value();
     }
 
     return js_object->DeleteElement(index, JSObject::FORCE_DELETION);
@@ -3939,7 +4157,8 @@
 }
 
 
-static MaybeObject* Runtime_SetProperty(Arguments args) {
+static MaybeObject* Runtime_SetProperty(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
 
@@ -3961,7 +4180,8 @@
     strict_mode = static_cast<StrictModeFlag>(strict_unchecked);
   }
 
-  return Runtime::SetObjectProperty(object,
+  return Runtime::SetObjectProperty(isolate,
+                                    object,
                                     key,
                                     value,
                                     attributes,
@@ -3971,7 +4191,9 @@
 
 // Set a local property, even if it is READ_ONLY.  If the property does not
 // exist, it will be added with attributes NONE.
-static MaybeObject* Runtime_IgnoreAttributesAndSetProperty(Arguments args) {
+static MaybeObject* Runtime_IgnoreAttributesAndSetProperty(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
   CONVERT_CHECKED(JSObject, object, args[0]);
@@ -3992,7 +4214,8 @@
 }
 
 
-static MaybeObject* Runtime_DeleteProperty(Arguments args) {
+static MaybeObject* Runtime_DeleteProperty(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 3);
 
@@ -4005,22 +4228,26 @@
 }
 
 
-static Object* HasLocalPropertyImplementation(Handle<JSObject> object,
+static Object* HasLocalPropertyImplementation(Isolate* isolate,
+                                              Handle<JSObject> object,
                                               Handle<String> key) {
-  if (object->HasLocalProperty(*key)) return Heap::true_value();
+  if (object->HasLocalProperty(*key)) return isolate->heap()->true_value();
   // Handle hidden prototypes.  If there's a hidden prototype above this thing
   // then we have to check it for properties, because they are supposed to
   // look like they are on this object.
   Handle<Object> proto(object->GetPrototype());
   if (proto->IsJSObject() &&
       Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
-    return HasLocalPropertyImplementation(Handle<JSObject>::cast(proto), key);
+    return HasLocalPropertyImplementation(isolate,
+                                          Handle<JSObject>::cast(proto),
+                                          key);
   }
-  return Heap::false_value();
+  return isolate->heap()->false_value();
 }
 
 
-static MaybeObject* Runtime_HasLocalProperty(Arguments args) {
+static MaybeObject* Runtime_HasLocalProperty(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
   CONVERT_CHECKED(String, key, args[1]);
@@ -4030,11 +4257,12 @@
   if (obj->IsJSObject()) {
     JSObject* object = JSObject::cast(obj);
     // Fast case - no interceptors.
-    if (object->HasRealNamedProperty(key)) return Heap::true_value();
+    if (object->HasRealNamedProperty(key)) return isolate->heap()->true_value();
     // Slow case.  Either it's not there or we have an interceptor.  We should
     // have handles for this kind of deal.
-    HandleScope scope;
-    return HasLocalPropertyImplementation(Handle<JSObject>(object),
+    HandleScope scope(isolate);
+    return HasLocalPropertyImplementation(isolate,
+                                          Handle<JSObject>(object),
                                           Handle<String>(key));
   } else if (obj->IsString()) {
     // Well, there is one exception:  Handle [] on strings.
@@ -4042,14 +4270,15 @@
     if (key->AsArrayIndex(&index)) {
       String* string = String::cast(obj);
       if (index < static_cast<uint32_t>(string->length()))
-        return Heap::true_value();
+        return isolate->heap()->true_value();
     }
   }
-  return Heap::false_value();
+  return isolate->heap()->false_value();
 }
 
 
-static MaybeObject* Runtime_HasProperty(Arguments args) {
+static MaybeObject* Runtime_HasProperty(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation na;
   ASSERT(args.length() == 2);
 
@@ -4057,13 +4286,14 @@
   if (args[0]->IsJSObject()) {
     JSObject* object = JSObject::cast(args[0]);
     CONVERT_CHECKED(String, key, args[1]);
-    if (object->HasProperty(key)) return Heap::true_value();
+    if (object->HasProperty(key)) return isolate->heap()->true_value();
   }
-  return Heap::false_value();
+  return isolate->heap()->false_value();
 }
 
 
-static MaybeObject* Runtime_HasElement(Arguments args) {
+static MaybeObject* Runtime_HasElement(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation na;
   ASSERT(args.length() == 2);
 
@@ -4072,13 +4302,14 @@
     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();
+    if (object->HasElement(index)) return isolate->heap()->true_value();
   }
-  return Heap::false_value();
+  return isolate->heap()->false_value();
 }
 
 
-static MaybeObject* Runtime_IsPropertyEnumerable(Arguments args) {
+static MaybeObject* Runtime_IsPropertyEnumerable(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
@@ -4087,16 +4318,17 @@
 
   uint32_t index;
   if (key->AsArrayIndex(&index)) {
-    return Heap::ToBoolean(object->HasElement(index));
+    return isolate->heap()->ToBoolean(object->HasElement(index));
   }
 
   PropertyAttributes att = object->GetLocalPropertyAttribute(key);
-  return Heap::ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
+  return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
 }
 
 
-static MaybeObject* Runtime_GetPropertyNames(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetPropertyNames(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   CONVERT_ARG_CHECKED(JSObject, object, 0);
   return *GetKeysFor(object);
@@ -4108,14 +4340,15 @@
 // 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 MaybeObject* Runtime_GetPropertyNamesFast(Arguments args) {
+static MaybeObject* Runtime_GetPropertyNamesFast(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 1);
 
   CONVERT_CHECKED(JSObject, raw_object, args[0]);
 
   if (raw_object->IsSimpleEnum()) return raw_object->map();
 
-  HandleScope scope;
+  HandleScope scope(isolate);
   Handle<JSObject> object(raw_object);
   Handle<FixedArray> content = GetKeysInFixedArrayFor(object,
                                                       INCLUDE_PROTOS);
@@ -4144,11 +4377,12 @@
 
 // Return the names of the local named properties.
 // args[0]: object
-static MaybeObject* Runtime_GetLocalPropertyNames(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetLocalPropertyNames(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   if (!args[0]->IsJSObject()) {
-    return Heap::undefined_value();
+    return isolate->heap()->undefined_value();
   }
   CONVERT_ARG_CHECKED(JSObject, obj, 0);
 
@@ -4157,9 +4391,11 @@
   if (obj->IsJSGlobalProxy()) {
     // Only collect names if access is permitted.
     if (obj->IsAccessCheckNeeded() &&
-        !Top::MayNamedAccess(*obj, Heap::undefined_value(), v8::ACCESS_KEYS)) {
-      Top::ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
-      return *Factory::NewJSArray(0);
+        !isolate->MayNamedAccess(*obj,
+                                 isolate->heap()->undefined_value(),
+                                 v8::ACCESS_KEYS)) {
+      isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
+      return *isolate->factory()->NewJSArray(0);
     }
     obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
   }
@@ -4174,11 +4410,11 @@
   for (int i = 0; i < length; i++) {
     // Only collect names if access is permitted.
     if (jsproto->IsAccessCheckNeeded() &&
-        !Top::MayNamedAccess(*jsproto,
-                             Heap::undefined_value(),
-                             v8::ACCESS_KEYS)) {
-      Top::ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
-      return *Factory::NewJSArray(0);
+        !isolate->MayNamedAccess(*jsproto,
+                                 isolate->heap()->undefined_value(),
+                                 v8::ACCESS_KEYS)) {
+      isolate->ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
+      return *isolate->factory()->NewJSArray(0);
     }
     int n;
     n = jsproto->NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE));
@@ -4190,7 +4426,8 @@
   }
 
   // Allocate an array with storage for all the property names.
-  Handle<FixedArray> names = Factory::NewFixedArray(total_property_count);
+  Handle<FixedArray> names =
+      isolate->factory()->NewFixedArray(total_property_count);
 
   // Get the property names.
   jsproto = obj;
@@ -4209,43 +4446,45 @@
   // Filter out name of hidden propeties object.
   if (proto_with_hidden_properties > 0) {
     Handle<FixedArray> old_names = names;
-    names = Factory::NewFixedArray(
+    names = isolate->factory()->NewFixedArray(
         names->length() - proto_with_hidden_properties);
     int dest_pos = 0;
     for (int i = 0; i < total_property_count; i++) {
       Object* name = old_names->get(i);
-      if (name == Heap::hidden_symbol()) {
+      if (name == isolate->heap()->hidden_symbol()) {
         continue;
       }
       names->set(dest_pos++, name);
     }
   }
 
-  return *Factory::NewJSArrayWithElements(names);
+  return *isolate->factory()->NewJSArrayWithElements(names);
 }
 
 
 // Return the names of the local indexed properties.
 // args[0]: object
-static MaybeObject* Runtime_GetLocalElementNames(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetLocalElementNames(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   if (!args[0]->IsJSObject()) {
-    return Heap::undefined_value();
+    return isolate->heap()->undefined_value();
   }
   CONVERT_ARG_CHECKED(JSObject, obj, 0);
 
   int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
-  Handle<FixedArray> names = Factory::NewFixedArray(n);
+  Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
   obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
-  return *Factory::NewJSArrayWithElements(names);
+  return *isolate->factory()->NewJSArrayWithElements(names);
 }
 
 
 // Return information on whether an object has a named or indexed interceptor.
 // args[0]: object
-static MaybeObject* Runtime_GetInterceptorInfo(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetInterceptorInfo(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   if (!args[0]->IsJSObject()) {
     return Smi::FromInt(0);
@@ -4262,8 +4501,10 @@
 
 // Return property names from named interceptor.
 // args[0]: object
-static MaybeObject* Runtime_GetNamedInterceptorPropertyNames(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetNamedInterceptorPropertyNames(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   CONVERT_ARG_CHECKED(JSObject, obj, 0);
 
@@ -4271,14 +4512,16 @@
     v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
   }
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
 // Return element names from indexed interceptor.
 // args[0]: object
-static MaybeObject* Runtime_GetIndexedInterceptorElementNames(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetIndexedInterceptorElementNames(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   CONVERT_ARG_CHECKED(JSObject, obj, 0);
 
@@ -4286,28 +4529,29 @@
     v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
   }
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_LocalKeys(Arguments args) {
+static MaybeObject* Runtime_LocalKeys(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT_EQ(args.length(), 1);
   CONVERT_CHECKED(JSObject, raw_object, args[0]);
-  HandleScope scope;
+  HandleScope scope(isolate);
   Handle<JSObject> object(raw_object);
 
   if (object->IsJSGlobalProxy()) {
     // Do access checks before going to the global object.
     if (object->IsAccessCheckNeeded() &&
-        !Top::MayNamedAccess(*object, Heap::undefined_value(),
+        !isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
                              v8::ACCESS_KEYS)) {
-      Top::ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
-      return *Factory::NewJSArray(0);
+      isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
+      return *isolate->factory()->NewJSArray(0);
     }
 
     Handle<Object> proto(object->GetPrototype());
     // If proxy is detached we simply return an empty array.
-    if (proto->IsNull()) return *Factory::NewJSArray(0);
+    if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
     object = Handle<JSObject>::cast(proto);
   }
 
@@ -4317,24 +4561,26 @@
   // property array and since the result is mutable we have to create
   // a fresh clone on each invocation.
   int length = contents->length();
-  Handle<FixedArray> copy = Factory::NewFixedArray(length);
+  Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
   for (int i = 0; i < length; i++) {
     Object* entry = contents->get(i);
     if (entry->IsString()) {
       copy->set(i, entry);
     } else {
       ASSERT(entry->IsNumber());
-      HandleScope scope;
-      Handle<Object> entry_handle(entry);
-      Handle<Object> entry_str = Factory::NumberToString(entry_handle);
+      HandleScope scope(isolate);
+      Handle<Object> entry_handle(entry, isolate);
+      Handle<Object> entry_str =
+          isolate->factory()->NumberToString(entry_handle);
       copy->set(i, *entry_str);
     }
   }
-  return *Factory::NewJSArrayWithElements(copy);
+  return *isolate->factory()->NewJSArrayWithElements(copy);
 }
 
 
-static MaybeObject* Runtime_GetArgumentsProperty(Arguments args) {
+static MaybeObject* Runtime_GetArgumentsProperty(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
@@ -4344,7 +4590,7 @@
   JavaScriptFrame* frame = it.frame();
 
   // Get the actual number of provided arguments.
-  const uint32_t n = frame->GetProvidedParametersCount();
+  const uint32_t n = frame->ComputeParametersCount();
 
   // Try to convert the key to an index. If successful and within
   // index return the the argument from the frame.
@@ -4354,7 +4600,7 @@
   }
 
   // Convert the key to a string.
-  HandleScope scope;
+  HandleScope scope(isolate);
   bool exception = false;
   Handle<Object> converted =
       Execution::ToString(args.at<Object>(0), &exception);
@@ -4366,21 +4612,30 @@
     if (index < n) {
       return frame->GetParameter(index);
     } else {
-      return Top::initial_object_prototype()->GetElement(index);
+      return isolate->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();
+  if (key->Equals(isolate->heap()->length_symbol())) return Smi::FromInt(n);
+  if (key->Equals(isolate->heap()->callee_symbol())) {
+    Object* function = frame->function();
+    if (function->IsJSFunction() &&
+        JSFunction::cast(function)->shared()->strict_mode()) {
+      return isolate->Throw(*isolate->factory()->NewTypeError(
+          "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
+    }
+    return function;
+  }
 
   // Lookup in the initial Object.prototype object.
-  return Top::initial_object_prototype()->GetProperty(*key);
+  return isolate->initial_object_prototype()->GetProperty(*key);
 }
 
 
-static MaybeObject* Runtime_ToFastProperties(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_ToFastProperties(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
 
   ASSERT(args.length() == 1);
   Handle<Object> object = args.at<Object>(0);
@@ -4395,8 +4650,9 @@
 }
 
 
-static MaybeObject* Runtime_ToSlowProperties(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_ToSlowProperties(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
 
   ASSERT(args.length() == 1);
   Handle<Object> object = args.at<Object>(0);
@@ -4408,7 +4664,8 @@
 }
 
 
-static MaybeObject* Runtime_ToBool(Arguments args) {
+static MaybeObject* Runtime_ToBool(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
@@ -4418,37 +4675,40 @@
 
 // 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 MaybeObject* Runtime_Typeof(Arguments args) {
+static MaybeObject* Runtime_Typeof(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
 
   Object* obj = args[0];
-  if (obj->IsNumber()) return Heap::number_symbol();
+  if (obj->IsNumber()) return isolate->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();
+  if (heap_obj->map()->is_undetectable()) {
+    return isolate->heap()->undefined_symbol();
+  }
 
   InstanceType instance_type = heap_obj->map()->instance_type();
   if (instance_type < FIRST_NONSTRING_TYPE) {
-    return Heap::string_symbol();
+    return isolate->heap()->string_symbol();
   }
 
   switch (instance_type) {
     case ODDBALL_TYPE:
       if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
-        return Heap::boolean_symbol();
+        return isolate->heap()->boolean_symbol();
       }
       if (heap_obj->IsNull()) {
-        return Heap::object_symbol();
+        return isolate->heap()->object_symbol();
       }
       ASSERT(heap_obj->IsUndefined());
-      return Heap::undefined_symbol();
+      return isolate->heap()->undefined_symbol();
     case JS_FUNCTION_TYPE: case JS_REGEXP_TYPE:
-      return Heap::function_symbol();
+      return isolate->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();
+      return isolate->heap()->object_symbol();
   }
 }
 
@@ -4475,7 +4735,8 @@
 }
 
 
-static MaybeObject* Runtime_StringToNumber(Arguments args) {
+static MaybeObject* Runtime_StringToNumber(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
   CONVERT_CHECKED(String, subject, args[0]);
@@ -4491,21 +4752,21 @@
     int start_pos = (minus ? 1 : 0);
 
     if (start_pos == len) {
-      return Heap::nan_value();
+      return isolate->heap()->nan_value();
     } else if (data[start_pos] > '9') {
       // Fast check for a junk value. A valid string may start from a
       // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
       // the 'I' character ('Infinity'). All of that have codes not greater than
       // '9' except 'I'.
       if (data[start_pos] != 'I') {
-        return Heap::nan_value();
+        return isolate->heap()->nan_value();
       }
     } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
       // The maximal/minimal smi has 10 digits. If the string has less digits we
       // know it will fit into the smi-data type.
       int d = ParseDecimalInteger(data, start_pos, len);
       if (minus) {
-        if (d == 0) return Heap::minus_zero_value();
+        if (d == 0) return isolate->heap()->minus_zero_value();
         d = -d;
       } else if (!subject->HasHashCode() &&
                  len <= String::kMaxArrayIndexSize &&
@@ -4525,11 +4786,13 @@
   }
 
   // Slower case.
-  return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
+  return isolate->heap()->NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
 }
 
 
-static MaybeObject* Runtime_StringFromCharCodeArray(Arguments args) {
+static MaybeObject* Runtime_StringFromCharCodeArray(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
@@ -4552,9 +4815,9 @@
 
   MaybeObject* maybe_object = NULL;
   if (i == length) {  // The string is ASCII.
-    maybe_object = Heap::AllocateRawAsciiString(length);
+    maybe_object = isolate->heap()->AllocateRawAsciiString(length);
   } else {  // The string is not ASCII.
-    maybe_object = Heap::AllocateRawTwoByteString(length);
+    maybe_object = isolate->heap()->AllocateRawTwoByteString(length);
   }
 
   Object* object = NULL;
@@ -4609,7 +4872,8 @@
 }
 
 
-static MaybeObject* Runtime_URIEscape(Arguments args) {
+static MaybeObject* Runtime_URIEscape(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   const char hex_chars[] = "0123456789ABCDEF";
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
@@ -4620,7 +4884,8 @@
   int escaped_length = 0;
   int length = source->length();
   {
-    Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
+    Access<StringInputBuffer> buffer(
+        isolate->runtime_state()->string_input_buffer());
     buffer->Reset(source);
     while (buffer->has_more()) {
       uint16_t character = buffer->GetNext();
@@ -4634,7 +4899,7 @@
       // We don't allow strings that are longer than a maximal length.
       ASSERT(String::kMaxLength < 0x7fffffff - 6);  // Cannot overflow.
       if (escaped_length > String::kMaxLength) {
-        Top::context()->mark_out_of_memory();
+        isolate->context()->mark_out_of_memory();
         return Failure::OutOfMemoryException();
       }
     }
@@ -4644,13 +4909,15 @@
     return source;
   }
   Object* o;
-  { MaybeObject* maybe_o = Heap::AllocateRawAsciiString(escaped_length);
+  { MaybeObject* maybe_o =
+        isolate->heap()->AllocateRawAsciiString(escaped_length);
     if (!maybe_o->ToObject(&o)) return maybe_o;
   }
   String* destination = String::cast(o);
   int dest_position = 0;
 
-  Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
+  Access<StringInputBuffer> buffer(
+      isolate->runtime_state()->string_input_buffer());
   buffer->Rewind();
   while (buffer->has_more()) {
     uint16_t chr = buffer->GetNext();
@@ -4725,7 +4992,8 @@
 }
 
 
-static MaybeObject* Runtime_URIUnescape(Arguments args) {
+static MaybeObject* Runtime_URIUnescape(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
   CONVERT_CHECKED(String, source, args[0]);
@@ -4749,9 +5017,10 @@
     return source;
 
   Object* o;
-  { MaybeObject* maybe_o = ascii ?
-                           Heap::AllocateRawAsciiString(unescaped_length) :
-                           Heap::AllocateRawTwoByteString(unescaped_length);
+  { MaybeObject* maybe_o =
+        ascii ?
+        isolate->heap()->AllocateRawAsciiString(unescaped_length) :
+        isolate->heap()->AllocateRawTwoByteString(unescaped_length);
     if (!maybe_o->ToObject(&o)) return maybe_o;
   }
   String* destination = String::cast(o);
@@ -4836,23 +5105,24 @@
 
 
 template <typename StringType>
-MaybeObject* AllocateRawString(int length);
+MaybeObject* AllocateRawString(Isolate* isolate, int length);
 
 
 template <>
-MaybeObject* AllocateRawString<SeqTwoByteString>(int length) {
-  return Heap::AllocateRawTwoByteString(length);
+MaybeObject* AllocateRawString<SeqTwoByteString>(Isolate* isolate, int length) {
+  return isolate->heap()->AllocateRawTwoByteString(length);
 }
 
 
 template <>
-MaybeObject* AllocateRawString<SeqAsciiString>(int length) {
-  return Heap::AllocateRawAsciiString(length);
+MaybeObject* AllocateRawString<SeqAsciiString>(Isolate* isolate, int length) {
+  return isolate->heap()->AllocateRawAsciiString(length);
 }
 
 
 template <typename Char, typename StringType, bool comma>
-static MaybeObject* SlowQuoteJsonString(Vector<const Char> characters) {
+static MaybeObject* SlowQuoteJsonString(Isolate* isolate,
+                                        Vector<const Char> characters) {
   int length = characters.length();
   const Char* read_cursor = characters.start();
   const Char* end = read_cursor + length;
@@ -4866,7 +5136,8 @@
       quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)];
     }
   }
-  MaybeObject* new_alloc = AllocateRawString<StringType>(quoted_length);
+  MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
+                                                         quoted_length);
   Object* new_object;
   if (!new_alloc->ToObject(&new_object)) {
     return new_alloc;
@@ -4898,29 +5169,31 @@
 
 
 template <typename Char, typename StringType, bool comma>
-static MaybeObject* QuoteJsonString(Vector<const Char> characters) {
+static MaybeObject* QuoteJsonString(Isolate* isolate,
+                                    Vector<const Char> characters) {
   int length = characters.length();
-  Counters::quote_json_char_count.Increment(length);
+  isolate->counters()->quote_json_char_count()->Increment(length);
   const int kSpaceForQuotes = 2 + (comma ? 1 :0);
   int worst_case_length = length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes;
   if (worst_case_length > kMaxGuaranteedNewSpaceString) {
-    return SlowQuoteJsonString<Char, StringType, comma>(characters);
+    return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
   }
 
-  MaybeObject* new_alloc = AllocateRawString<StringType>(worst_case_length);
+  MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
+                                                         worst_case_length);
   Object* new_object;
   if (!new_alloc->ToObject(&new_object)) {
     return new_alloc;
   }
-  if (!Heap::new_space()->Contains(new_object)) {
+  if (!isolate->heap()->new_space()->Contains(new_object)) {
     // Even if our string is small enough to fit in new space we still have to
     // handle it being allocated in old space as may happen in the third
     // attempt.  See CALL_AND_RETRY in heap-inl.h and similar code in
     // CEntryStub::GenerateCore.
-    return SlowQuoteJsonString<Char, StringType, comma>(characters);
+    return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
   }
   StringType* new_string = StringType::cast(new_object);
-  ASSERT(Heap::new_space()->Contains(new_string));
+  ASSERT(isolate->heap()->new_space()->Contains(new_string));
 
   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize);
   Char* write_cursor = reinterpret_cast<Char*>(
@@ -4957,13 +5230,15 @@
   int final_length = static_cast<int>(
       write_cursor - reinterpret_cast<Char*>(
           new_string->address() + SeqAsciiString::kHeaderSize));
-  Heap::new_space()->ShrinkStringAtAllocationBoundary<StringType>(new_string,
-                                                                  final_length);
+  isolate->heap()->new_space()->
+      template ShrinkStringAtAllocationBoundary<StringType>(
+          new_string, final_length);
   return new_string;
 }
 
 
-static MaybeObject* Runtime_QuoteJSONString(Arguments args) {
+static MaybeObject* Runtime_QuoteJSONString(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   CONVERT_CHECKED(String, str, args[0]);
   if (!str->IsFlat()) {
@@ -4976,14 +5251,17 @@
     ASSERT(str->IsFlat());
   }
   if (str->IsTwoByteRepresentation()) {
-    return QuoteJsonString<uc16, SeqTwoByteString, false>(str->ToUC16Vector());
+    return QuoteJsonString<uc16, SeqTwoByteString, false>(isolate,
+                                                          str->ToUC16Vector());
   } else {
-    return QuoteJsonString<char, SeqAsciiString, false>(str->ToAsciiVector());
+    return QuoteJsonString<char, SeqAsciiString, false>(isolate,
+                                                        str->ToAsciiVector());
   }
 }
 
 
-static MaybeObject* Runtime_QuoteJSONStringComma(Arguments args) {
+static MaybeObject* Runtime_QuoteJSONStringComma(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   CONVERT_CHECKED(String, str, args[0]);
   if (!str->IsFlat()) {
@@ -4996,14 +5274,16 @@
     ASSERT(str->IsFlat());
   }
   if (str->IsTwoByteRepresentation()) {
-    return QuoteJsonString<uc16, SeqTwoByteString, true>(str->ToUC16Vector());
+    return QuoteJsonString<uc16, SeqTwoByteString, true>(isolate,
+                                                         str->ToUC16Vector());
   } else {
-    return QuoteJsonString<char, SeqAsciiString, true>(str->ToAsciiVector());
+    return QuoteJsonString<char, SeqAsciiString, true>(isolate,
+                                                       str->ToAsciiVector());
   }
 }
 
-
-static MaybeObject* Runtime_StringParseInt(Arguments args) {
+static MaybeObject* Runtime_StringParseInt(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
 
   CONVERT_CHECKED(String, s, args[0]);
@@ -5013,11 +5293,12 @@
 
   RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
   double value = StringToInt(s, radix);
-  return Heap::NumberFromDouble(value);
+  return isolate->heap()->NumberFromDouble(value);
 }
 
 
-static MaybeObject* Runtime_StringParseFloat(Arguments args) {
+static MaybeObject* Runtime_StringParseFloat(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   CONVERT_CHECKED(String, str, args[0]);
 
@@ -5025,16 +5306,13 @@
   double value = StringToDouble(str, ALLOW_TRAILING_JUNK, OS::nan_value());
 
   // Create a number object from the value.
-  return Heap::NumberFromDouble(value);
+  return isolate->heap()->NumberFromDouble(value);
 }
 
 
-static unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping;
-static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping;
-
-
 template <class Converter>
 MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
+    Isolate* isolate,
     String* s,
     int length,
     int input_string_length,
@@ -5052,8 +5330,8 @@
   // dependent upper/lower conversions.
   Object* o;
   { MaybeObject* maybe_o = s->IsAsciiRepresentation()
-                   ? Heap::AllocateRawAsciiString(length)
-                   : Heap::AllocateRawTwoByteString(length);
+        ? isolate->heap()->AllocateRawAsciiString(length)
+        : isolate->heap()->AllocateRawTwoByteString(length);
     if (!maybe_o->ToObject(&o)) return maybe_o;
   }
   String* result = String::cast(o);
@@ -5061,7 +5339,8 @@
 
   // Convert all characters to upper case, assuming that they will fit
   // in the buffer
-  Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
+  Access<StringInputBuffer> buffer(
+      isolate->runtime_state()->string_input_buffer());
   buffer->Reset(s);
   unibrow::uchar chars[Converter::kMaxWidth];
   // We can assume that the string is not empty
@@ -5108,7 +5387,7 @@
         if (char_length == 0) char_length = 1;
         current_length += char_length;
         if (current_length > Smi::kMaxValue) {
-          Top::context()->mark_out_of_memory();
+          isolate->context()->mark_out_of_memory();
           return Failure::OutOfMemoryException();
         }
       }
@@ -5266,6 +5545,7 @@
 template <typename ConvertTraits>
 MUST_USE_RESULT static MaybeObject* ConvertCase(
     Arguments args,
+    Isolate* isolate,
     unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) {
   NoHandleAllocation ha;
   CONVERT_CHECKED(String, s, args[0]);
@@ -5283,7 +5563,7 @@
   // dependent upper/lower conversions.
   if (s->IsSeqAsciiString()) {
     Object* o;
-    { MaybeObject* maybe_o = Heap::AllocateRawAsciiString(length);
+    { MaybeObject* maybe_o = isolate->heap()->AllocateRawAsciiString(length);
       if (!maybe_o->ToObject(&o)) return maybe_o;
     }
     SeqAsciiString* result = SeqAsciiString::cast(o);
@@ -5293,13 +5573,15 @@
   }
 
   Object* answer;
-  { MaybeObject* maybe_answer = ConvertCaseHelper(s, length, length, mapping);
+  { MaybeObject* maybe_answer =
+        ConvertCaseHelper(isolate, s, length, length, mapping);
     if (!maybe_answer->ToObject(&answer)) return maybe_answer;
   }
   if (answer->IsSmi()) {
     // Retry with correct length.
     { MaybeObject* maybe_answer =
-          ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping);
+          ConvertCaseHelper(isolate,
+                            s, Smi::cast(answer)->value(), length, mapping);
       if (!maybe_answer->ToObject(&answer)) return maybe_answer;
     }
   }
@@ -5307,13 +5589,17 @@
 }
 
 
-static MaybeObject* Runtime_StringToLowerCase(Arguments args) {
-  return ConvertCase<ToLowerTraits>(args, &to_lower_mapping);
+static MaybeObject* Runtime_StringToLowerCase(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  return ConvertCase<ToLowerTraits>(
+      args, isolate, isolate->runtime_state()->to_lower_mapping());
 }
 
 
-static MaybeObject* Runtime_StringToUpperCase(Arguments args) {
-  return ConvertCase<ToUpperTraits>(args, &to_upper_mapping);
+static MaybeObject* Runtime_StringToUpperCase(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  return ConvertCase<ToUpperTraits>(
+      args, isolate, isolate->runtime_state()->to_upper_mapping());
 }
 
 
@@ -5322,7 +5608,8 @@
 }
 
 
-static MaybeObject* Runtime_StringTrim(Arguments args) {
+static MaybeObject* Runtime_StringTrim(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 3);
 
@@ -5351,14 +5638,15 @@
 
 
 template <typename SubjectChar, typename PatternChar>
-void FindStringIndices(Vector<const SubjectChar> subject,
+void FindStringIndices(Isolate* isolate,
+                       Vector<const SubjectChar> subject,
                        Vector<const PatternChar> pattern,
                        ZoneList<int>* indices,
                        unsigned int limit) {
   ASSERT(limit > 0);
   // Collect indices of pattern in subject, and the end-of-string index.
   // Stop after finding at most limit values.
-  StringSearch<PatternChar, SubjectChar> search(pattern);
+  StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
   int pattern_length = pattern.length();
   int index = 0;
   while (limit > 0) {
@@ -5371,9 +5659,10 @@
 }
 
 
-static MaybeObject* Runtime_StringSplit(Arguments args) {
+static MaybeObject* Runtime_StringSplit(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 3);
-  HandleScope handle_scope;
+  HandleScope handle_scope(isolate);
   CONVERT_ARG_CHECKED(String, subject, 0);
   CONVERT_ARG_CHECKED(String, pattern, 1);
   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
@@ -5403,12 +5692,14 @@
     if (subject->IsAsciiRepresentation()) {
       Vector<const char> subject_vector = subject->ToAsciiVector();
       if (pattern->IsAsciiRepresentation()) {
-        FindStringIndices(subject_vector,
+        FindStringIndices(isolate,
+                          subject_vector,
                           pattern->ToAsciiVector(),
                           &indices,
                           limit);
       } else {
-        FindStringIndices(subject_vector,
+        FindStringIndices(isolate,
+                          subject_vector,
                           pattern->ToUC16Vector(),
                           &indices,
                           limit);
@@ -5416,12 +5707,14 @@
     } else {
       Vector<const uc16> subject_vector = subject->ToUC16Vector();
       if (pattern->IsAsciiRepresentation()) {
-        FindStringIndices(subject_vector,
+        FindStringIndices(isolate,
+                          subject_vector,
                           pattern->ToAsciiVector(),
                           &indices,
                           limit);
       } else {
-        FindStringIndices(subject_vector,
+        FindStringIndices(isolate,
+                          subject_vector,
                           pattern->ToUC16Vector(),
                           &indices,
                           limit);
@@ -5438,7 +5731,7 @@
   // Create JSArray of substrings separated by separator.
   int part_count = indices.length();
 
-  Handle<JSArray> result = Factory::NewJSArray(part_count);
+  Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
   result->set_length(Smi::FromInt(part_count));
 
   ASSERT(result->HasFastElements());
@@ -5454,7 +5747,7 @@
     HandleScope local_loop_handle;
     int part_end = indices.at(i);
     Handle<String> substring =
-        Factory::NewSubString(subject, part_start, part_end);
+        isolate->factory()->NewSubString(subject, part_start, part_end);
     elements->set(i, *substring);
     part_start = part_end + pattern_length;
   }
@@ -5467,17 +5760,18 @@
 // one-char strings in the cache. Gives up on the first char that is
 // not in the cache and fills the remainder with smi zeros. Returns
 // the length of the successfully copied prefix.
-static int CopyCachedAsciiCharsToArray(const char* chars,
+static int CopyCachedAsciiCharsToArray(Heap* heap,
+                                       const char* chars,
                                        FixedArray* elements,
                                        int length) {
   AssertNoAllocation nogc;
-  FixedArray* ascii_cache = Heap::single_character_string_cache();
-  Object* undefined = Heap::undefined_value();
+  FixedArray* ascii_cache = heap->single_character_string_cache();
+  Object* undefined = heap->undefined_value();
   int i;
   for (i = 0; i < length; ++i) {
     Object* value = ascii_cache->get(chars[i]);
     if (value == undefined) break;
-    ASSERT(!Heap::InNewSpace(value));
+    ASSERT(!heap->InNewSpace(value));
     elements->set(i, value, SKIP_WRITE_BARRIER);
   }
   if (i < length) {
@@ -5497,8 +5791,9 @@
 
 // Converts a String to JSArray.
 // For example, "foo" => ["f", "o", "o"].
-static MaybeObject* Runtime_StringToArray(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_StringToArray(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 2);
   CONVERT_ARG_CHECKED(String, s, 0);
   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
@@ -5509,15 +5804,17 @@
   Handle<FixedArray> elements;
   if (s->IsFlat() && s->IsAsciiRepresentation()) {
     Object* obj;
-    { MaybeObject* maybe_obj = Heap::AllocateUninitializedFixedArray(length);
+    { MaybeObject* maybe_obj =
+          isolate->heap()->AllocateUninitializedFixedArray(length);
       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
     }
-    elements = Handle<FixedArray>(FixedArray::cast(obj));
+    elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
 
     Vector<const char> chars = s->ToAsciiVector();
     // Note, this will initialize all elements (not only the prefix)
     // to prevent GC from seeing partially initialized array.
-    int num_copied_from_cache = CopyCachedAsciiCharsToArray(chars.start(),
+    int num_copied_from_cache = CopyCachedAsciiCharsToArray(isolate->heap(),
+                                                            chars.start(),
                                                             *elements,
                                                             length);
 
@@ -5526,7 +5823,7 @@
       elements->set(i, *str);
     }
   } else {
-    elements = Factory::NewFixedArray(length);
+    elements = isolate->factory()->NewFixedArray(length);
     for (int i = 0; i < length; ++i) {
       Handle<Object> str = LookupSingleCharacterStringFromCode(s->Get(i));
       elements->set(i, *str);
@@ -5539,11 +5836,12 @@
   }
 #endif
 
-  return *Factory::NewJSArrayWithElements(elements);
+  return *isolate->factory()->NewJSArrayWithElements(elements);
 }
 
 
-static MaybeObject* Runtime_NewStringWrapper(Arguments args) {
+static MaybeObject* Runtime_NewStringWrapper(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
   CONVERT_CHECKED(String, value, args[0]);
@@ -5551,36 +5849,40 @@
 }
 
 
-bool Runtime::IsUpperCaseChar(uint16_t ch) {
+bool Runtime::IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch) {
   unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
-  int char_length = to_upper_mapping.get(ch, 0, chars);
+  int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
   return char_length == 0;
 }
 
 
-static MaybeObject* Runtime_NumberToString(Arguments args) {
+static MaybeObject* Runtime_NumberToString(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
   Object* number = args[0];
   RUNTIME_ASSERT(number->IsNumber());
 
-  return Heap::NumberToString(number);
+  return isolate->heap()->NumberToString(number);
 }
 
 
-static MaybeObject* Runtime_NumberToStringSkipCache(Arguments args) {
+static MaybeObject* Runtime_NumberToStringSkipCache(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
   Object* number = args[0];
   RUNTIME_ASSERT(number->IsNumber());
 
-  return Heap::NumberToString(number, false);
+  return isolate->heap()->NumberToString(number, false);
 }
 
 
-static MaybeObject* Runtime_NumberToInteger(Arguments args) {
+static MaybeObject* Runtime_NumberToInteger(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
@@ -5590,11 +5892,13 @@
   if (number > 0 && number <= Smi::kMaxValue) {
     return Smi::FromInt(static_cast<int>(number));
   }
-  return Heap::NumberFromDouble(DoubleToInteger(number));
+  return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
 }
 
 
-static MaybeObject* Runtime_NumberToIntegerMapMinusZero(Arguments args) {
+static MaybeObject* Runtime_NumberToIntegerMapMinusZero(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
@@ -5609,20 +5913,22 @@
   // Map both -0 and +0 to +0.
   if (double_value == 0) double_value = 0;
 
-  return Heap::NumberFromDouble(double_value);
+  return isolate->heap()->NumberFromDouble(double_value);
 }
 
 
-static MaybeObject* Runtime_NumberToJSUint32(Arguments args) {
+static MaybeObject* Runtime_NumberToJSUint32(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
   CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
-  return Heap::NumberFromUint32(number);
+  return isolate->heap()->NumberFromUint32(number);
 }
 
 
-static MaybeObject* Runtime_NumberToJSInt32(Arguments args) {
+static MaybeObject* Runtime_NumberToJSInt32(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
@@ -5632,13 +5938,14 @@
   if (number > 0 && number <= Smi::kMaxValue) {
     return Smi::FromInt(static_cast<int>(number));
   }
-  return Heap::NumberFromInt32(DoubleToInt32(number));
+  return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
 }
 
 
 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
 // a small integer.
-static MaybeObject* Runtime_NumberToSmi(Arguments args) {
+static MaybeObject* Runtime_NumberToSmi(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
@@ -5653,75 +5960,83 @@
       return Smi::FromInt(int_value);
     }
   }
-  return Heap::nan_value();
+  return isolate->heap()->nan_value();
 }
 
 
-static MaybeObject* Runtime_AllocateHeapNumber(Arguments args) {
+static MaybeObject* Runtime_AllocateHeapNumber(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 0);
-  return Heap::AllocateHeapNumber(0);
+  return isolate->heap()->AllocateHeapNumber(0);
 }
 
 
-static MaybeObject* Runtime_NumberAdd(Arguments args) {
+static MaybeObject* Runtime_NumberAdd(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
   CONVERT_DOUBLE_CHECKED(y, args[1]);
-  return Heap::NumberFromDouble(x + y);
+  return isolate->heap()->NumberFromDouble(x + y);
 }
 
 
-static MaybeObject* Runtime_NumberSub(Arguments args) {
+static MaybeObject* Runtime_NumberSub(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
   CONVERT_DOUBLE_CHECKED(y, args[1]);
-  return Heap::NumberFromDouble(x - y);
+  return isolate->heap()->NumberFromDouble(x - y);
 }
 
 
-static MaybeObject* Runtime_NumberMul(Arguments args) {
+static MaybeObject* Runtime_NumberMul(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
   CONVERT_DOUBLE_CHECKED(y, args[1]);
-  return Heap::NumberFromDouble(x * y);
+  return isolate->heap()->NumberFromDouble(x * y);
 }
 
 
-static MaybeObject* Runtime_NumberUnaryMinus(Arguments args) {
+static MaybeObject* Runtime_NumberUnaryMinus(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
-  return Heap::NumberFromDouble(-x);
+  return isolate->heap()->NumberFromDouble(-x);
 }
 
 
-static MaybeObject* Runtime_NumberAlloc(Arguments args) {
+static MaybeObject* Runtime_NumberAlloc(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 0);
 
-  return Heap::NumberFromDouble(9876543210.0);
+  return isolate->heap()->NumberFromDouble(9876543210.0);
 }
 
 
-static MaybeObject* Runtime_NumberDiv(Arguments args) {
+static MaybeObject* Runtime_NumberDiv(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
   CONVERT_DOUBLE_CHECKED(y, args[1]);
-  return Heap::NumberFromDouble(x / y);
+  return isolate->heap()->NumberFromDouble(x / y);
 }
 
 
-static MaybeObject* Runtime_NumberMod(Arguments args) {
+static MaybeObject* Runtime_NumberMod(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
@@ -5730,17 +6045,18 @@
 
   x = modulo(x, y);
   // NumberFromDouble may return a Smi instead of a Number object
-  return Heap::NumberFromDouble(x);
+  return isolate->heap()->NumberFromDouble(x);
 }
 
 
-static MaybeObject* Runtime_StringAdd(Arguments args) {
+static MaybeObject* Runtime_StringAdd(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
   CONVERT_CHECKED(String, str1, args[0]);
   CONVERT_CHECKED(String, str2, args[1]);
-  Counters::string_add_runtime.Increment();
-  return Heap::AllocateConsString(str1, str2);
+  isolate->counters()->string_add_runtime()->Increment();
+  return isolate->heap()->AllocateConsString(str1, str2);
 }
 
 
@@ -5783,12 +6099,13 @@
 }
 
 
-static MaybeObject* Runtime_StringBuilderConcat(Arguments args) {
+static MaybeObject* Runtime_StringBuilderConcat(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 3);
   CONVERT_CHECKED(JSArray, array, args[0]);
   if (!args[1]->IsSmi()) {
-    Top::context()->mark_out_of_memory();
+    isolate->context()->mark_out_of_memory();
     return Failure::OutOfMemoryException();
   }
   int array_length = Smi::cast(args[1])->value();
@@ -5799,7 +6116,7 @@
 
   int special_length = special->length();
   if (!array->HasFastElements()) {
-    return Top::Throw(Heap::illegal_argument_symbol());
+    return isolate->Throw(isolate->heap()->illegal_argument_symbol());
   }
   FixedArray* fixed_array = FixedArray::cast(array->elements());
   if (fixed_array->length() < array_length) {
@@ -5807,7 +6124,7 @@
   }
 
   if (array_length == 0) {
-    return Heap::empty_string();
+    return isolate->heap()->empty_string();
   } else if (array_length == 1) {
     Object* first = fixed_array->get(0);
     if (first->IsString()) return first;
@@ -5833,21 +6150,21 @@
         // Get the position and check that it is a positive smi.
         i++;
         if (i >= array_length) {
-          return Top::Throw(Heap::illegal_argument_symbol());
+          return isolate->Throw(isolate->heap()->illegal_argument_symbol());
         }
         Object* next_smi = fixed_array->get(i);
         if (!next_smi->IsSmi()) {
-          return Top::Throw(Heap::illegal_argument_symbol());
+          return isolate->Throw(isolate->heap()->illegal_argument_symbol());
         }
         pos = Smi::cast(next_smi)->value();
         if (pos < 0) {
-          return Top::Throw(Heap::illegal_argument_symbol());
+          return isolate->Throw(isolate->heap()->illegal_argument_symbol());
         }
       }
       ASSERT(pos >= 0);
       ASSERT(len >= 0);
       if (pos > special_length || len > special_length - pos) {
-        return Top::Throw(Heap::illegal_argument_symbol());
+        return isolate->Throw(isolate->heap()->illegal_argument_symbol());
       }
       increment = len;
     } else if (elt->IsString()) {
@@ -5858,10 +6175,10 @@
         ascii = false;
       }
     } else {
-      return Top::Throw(Heap::illegal_argument_symbol());
+      return isolate->Throw(isolate->heap()->illegal_argument_symbol());
     }
     if (increment > String::kMaxLength - position) {
-      Top::context()->mark_out_of_memory();
+      isolate->context()->mark_out_of_memory();
       return Failure::OutOfMemoryException();
     }
     position += increment;
@@ -5871,7 +6188,8 @@
   Object* object;
 
   if (ascii) {
-    { MaybeObject* maybe_object = Heap::AllocateRawAsciiString(length);
+    { MaybeObject* maybe_object =
+          isolate->heap()->AllocateRawAsciiString(length);
       if (!maybe_object->ToObject(&object)) return maybe_object;
     }
     SeqAsciiString* answer = SeqAsciiString::cast(object);
@@ -5881,7 +6199,8 @@
                               array_length);
     return answer;
   } else {
-    { MaybeObject* maybe_object = Heap::AllocateRawTwoByteString(length);
+    { MaybeObject* maybe_object =
+          isolate->heap()->AllocateRawTwoByteString(length);
       if (!maybe_object->ToObject(&object)) return maybe_object;
     }
     SeqTwoByteString* answer = SeqTwoByteString::cast(object);
@@ -5894,19 +6213,20 @@
 }
 
 
-static MaybeObject* Runtime_StringBuilderJoin(Arguments args) {
+static MaybeObject* Runtime_StringBuilderJoin(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 3);
   CONVERT_CHECKED(JSArray, array, args[0]);
   if (!args[1]->IsSmi()) {
-    Top::context()->mark_out_of_memory();
+    isolate->context()->mark_out_of_memory();
     return Failure::OutOfMemoryException();
   }
   int array_length = Smi::cast(args[1])->value();
   CONVERT_CHECKED(String, separator, args[2]);
 
   if (!array->HasFastElements()) {
-    return Top::Throw(Heap::illegal_argument_symbol());
+    return isolate->Throw(isolate->heap()->illegal_argument_symbol());
   }
   FixedArray* fixed_array = FixedArray::cast(array->elements());
   if (fixed_array->length() < array_length) {
@@ -5914,7 +6234,7 @@
   }
 
   if (array_length == 0) {
-    return Heap::empty_string();
+    return isolate->heap()->empty_string();
   } else if (array_length == 1) {
     Object* first = fixed_array->get(0);
     if (first->IsString()) return first;
@@ -5924,7 +6244,7 @@
   int max_nof_separators =
       (String::kMaxLength + separator_length - 1) / separator_length;
   if (max_nof_separators < (array_length - 1)) {
-      Top::context()->mark_out_of_memory();
+      isolate->context()->mark_out_of_memory();
       return Failure::OutOfMemoryException();
   }
   int length = (array_length - 1) * separator_length;
@@ -5932,19 +6252,20 @@
     Object* element_obj = fixed_array->get(i);
     if (!element_obj->IsString()) {
       // TODO(1161): handle this case.
-      return Top::Throw(Heap::illegal_argument_symbol());
+      return isolate->Throw(isolate->heap()->illegal_argument_symbol());
     }
     String* element = String::cast(element_obj);
     int increment = element->length();
     if (increment > String::kMaxLength - length) {
-      Top::context()->mark_out_of_memory();
+      isolate->context()->mark_out_of_memory();
       return Failure::OutOfMemoryException();
     }
     length += increment;
   }
 
   Object* object;
-  { MaybeObject* maybe_object = Heap::AllocateRawTwoByteString(length);
+  { MaybeObject* maybe_object =
+        isolate->heap()->AllocateRawTwoByteString(length);
     if (!maybe_object->ToObject(&object)) return maybe_object;
   }
   SeqTwoByteString* answer = SeqTwoByteString::cast(object);
@@ -5977,76 +6298,84 @@
 }
 
 
-static MaybeObject* Runtime_NumberOr(Arguments args) {
+static MaybeObject* Runtime_NumberOr(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   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);
+  return isolate->heap()->NumberFromInt32(x | y);
 }
 
 
-static MaybeObject* Runtime_NumberAnd(Arguments args) {
+static MaybeObject* Runtime_NumberAnd(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   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);
+  return isolate->heap()->NumberFromInt32(x & y);
 }
 
 
-static MaybeObject* Runtime_NumberXor(Arguments args) {
+static MaybeObject* Runtime_NumberXor(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   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);
+  return isolate->heap()->NumberFromInt32(x ^ y);
 }
 
 
-static MaybeObject* Runtime_NumberNot(Arguments args) {
+static MaybeObject* Runtime_NumberNot(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
-  return Heap::NumberFromInt32(~x);
+  return isolate->heap()->NumberFromInt32(~x);
 }
 
 
-static MaybeObject* Runtime_NumberShl(Arguments args) {
+static MaybeObject* Runtime_NumberShl(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   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));
+  return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
 }
 
 
-static MaybeObject* Runtime_NumberShr(Arguments args) {
+static MaybeObject* Runtime_NumberShr(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   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));
+  return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
 }
 
 
-static MaybeObject* Runtime_NumberSar(Arguments args) {
+static MaybeObject* Runtime_NumberSar(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   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));
+  return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
 }
 
 
-static MaybeObject* Runtime_NumberEquals(Arguments args) {
+static MaybeObject* Runtime_NumberEquals(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
@@ -6065,7 +6394,8 @@
 }
 
 
-static MaybeObject* Runtime_StringEquals(Arguments args) {
+static MaybeObject* Runtime_StringEquals(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
@@ -6083,7 +6413,8 @@
 }
 
 
-static MaybeObject* Runtime_NumberCompare(Arguments args) {
+static MaybeObject* Runtime_NumberCompare(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 3);
 
@@ -6098,15 +6429,12 @@
 
 // Compare two Smis as if they were converted to strings and then
 // compared lexicographically.
-static MaybeObject* Runtime_SmiLexicographicCompare(Arguments args) {
+static MaybeObject* Runtime_SmiLexicographicCompare(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   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]);
@@ -6130,6 +6458,13 @@
     y_value = -y_value;
   }
 
+  // Arrays for the individual characters of the two Smis.  Smis are
+  // 31 bit integers and 10 decimal digits are therefore enough.
+  // TODO(isolates): maybe we should simply allocate 20 bytes on the stack.
+  int* x_elms = isolate->runtime_state()->smi_lexicographic_compare_x_elms();
+  int* y_elms = isolate->runtime_state()->smi_lexicographic_compare_y_elms();
+
+
   // Convert the integers to arrays of their decimal digits.
   int x_index = 0;
   int y_index = 0;
@@ -6156,9 +6491,11 @@
 }
 
 
-static Object* StringInputBufferCompare(String* x, String* y) {
-  static StringInputBuffer bufx;
-  static StringInputBuffer bufy;
+static Object* StringInputBufferCompare(RuntimeState* state,
+                                        String* x,
+                                        String* y) {
+  StringInputBuffer& bufx = *state->string_input_buffer_compare_bufx();
+  StringInputBuffer& bufy = *state->string_input_buffer_compare_bufy();
   bufx.Reset(x);
   bufy.Reset(y);
   while (bufx.has_more() && bufy.has_more()) {
@@ -6211,19 +6548,21 @@
   } else {
     result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
   }
-  ASSERT(result == StringInputBufferCompare(x, y));
+  ASSERT(result ==
+      StringInputBufferCompare(Isolate::Current()->runtime_state(), x, y));
   return result;
 }
 
 
-static MaybeObject* Runtime_StringCompare(Arguments args) {
+static MaybeObject* Runtime_StringCompare(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
   CONVERT_CHECKED(String, x, args[0]);
   CONVERT_CHECKED(String, y, args[1]);
 
-  Counters::string_compare_runtime.Increment();
+  isolate->counters()->string_compare_runtime()->Increment();
 
   // A few fast case tests before we flatten.
   if (x == y) return Smi::FromInt(EQUAL);
@@ -6239,52 +6578,59 @@
   else if (d > 0) return Smi::FromInt(GREATER);
 
   Object* obj;
-  { MaybeObject* maybe_obj = Heap::PrepareForCompare(x);
+  { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
-  { MaybeObject* maybe_obj = Heap::PrepareForCompare(y);
+  { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
 
   return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
-                                      : StringInputBufferCompare(x, y);
+      : StringInputBufferCompare(isolate->runtime_state(), x, y);
 }
 
 
-static MaybeObject* Runtime_Math_acos(Arguments args) {
+static MaybeObject* Runtime_Math_acos(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  Counters::math_acos.Increment();
+  isolate->counters()->math_acos()->Increment();
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
-  return TranscendentalCache::Get(TranscendentalCache::ACOS, x);
+  return isolate->transcendental_cache()->Get(TranscendentalCache::ACOS, x);
 }
 
 
-static MaybeObject* Runtime_Math_asin(Arguments args) {
+static MaybeObject* Runtime_Math_asin(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  Counters::math_asin.Increment();
+  isolate->counters()->math_asin()->Increment();
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
-  return TranscendentalCache::Get(TranscendentalCache::ASIN, x);
+  return isolate->transcendental_cache()->Get(TranscendentalCache::ASIN, x);
 }
 
 
-static MaybeObject* Runtime_Math_atan(Arguments args) {
+static MaybeObject* Runtime_Math_atan(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  Counters::math_atan.Increment();
+  isolate->counters()->math_atan()->Increment();
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
-  return TranscendentalCache::Get(TranscendentalCache::ATAN, x);
+  return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x);
 }
 
 
-static MaybeObject* Runtime_Math_atan2(Arguments args) {
+static const double kPiDividedBy4 = 0.78539816339744830962;
+
+
+static MaybeObject* Runtime_Math_atan2(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
-  Counters::math_atan2.Increment();
+  isolate->counters()->math_atan2()->Increment();
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
   CONVERT_DOUBLE_CHECKED(y, args[1]);
@@ -6294,71 +6640,76 @@
     // 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);
+  return isolate->heap()->AllocateHeapNumber(result);
 }
 
 
-static MaybeObject* Runtime_Math_ceil(Arguments args) {
+static MaybeObject* Runtime_Math_ceil(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  Counters::math_ceil.Increment();
+  isolate->counters()->math_ceil()->Increment();
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
-  return Heap::NumberFromDouble(ceiling(x));
+  return isolate->heap()->NumberFromDouble(ceiling(x));
 }
 
 
-static MaybeObject* Runtime_Math_cos(Arguments args) {
+static MaybeObject* Runtime_Math_cos(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  Counters::math_cos.Increment();
+  isolate->counters()->math_cos()->Increment();
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
-  return TranscendentalCache::Get(TranscendentalCache::COS, x);
+  return isolate->transcendental_cache()->Get(TranscendentalCache::COS, x);
 }
 
 
-static MaybeObject* Runtime_Math_exp(Arguments args) {
+static MaybeObject* Runtime_Math_exp(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  Counters::math_exp.Increment();
+  isolate->counters()->math_exp()->Increment();
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
-  return TranscendentalCache::Get(TranscendentalCache::EXP, x);
+  return isolate->transcendental_cache()->Get(TranscendentalCache::EXP, x);
 }
 
 
-static MaybeObject* Runtime_Math_floor(Arguments args) {
+static MaybeObject* Runtime_Math_floor(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  Counters::math_floor.Increment();
+  isolate->counters()->math_floor()->Increment();
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
-  return Heap::NumberFromDouble(floor(x));
+  return isolate->heap()->NumberFromDouble(floor(x));
 }
 
 
-static MaybeObject* Runtime_Math_log(Arguments args) {
+static MaybeObject* Runtime_Math_log(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  Counters::math_log.Increment();
+  isolate->counters()->math_log()->Increment();
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
-  return TranscendentalCache::Get(TranscendentalCache::LOG, x);
+  return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x);
 }
 
 
-static MaybeObject* Runtime_Math_pow(Arguments args) {
+static MaybeObject* Runtime_Math_pow(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
-  Counters::math_pow.Increment();
+  isolate->counters()->math_pow()->Increment();
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
 
@@ -6366,16 +6717,17 @@
   // custom powi() function than the generic pow().
   if (args[1]->IsSmi()) {
     int y = Smi::cast(args[1])->value();
-    return Heap::NumberFromDouble(power_double_int(x, y));
+    return isolate->heap()->NumberFromDouble(power_double_int(x, y));
   }
 
   CONVERT_DOUBLE_CHECKED(y, args[1]);
-  return Heap::AllocateHeapNumber(power_double_double(x, y));
+  return isolate->heap()->AllocateHeapNumber(power_double_double(x, y));
 }
 
 // Fast version of Math.pow if we know that y is not an integer and
 // y is not -0.5 or 0.5. Used as slowcase from codegen.
-static MaybeObject* Runtime_Math_pow_cfunction(Arguments args) {
+static MaybeObject* Runtime_Math_pow_cfunction(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
   CONVERT_DOUBLE_CHECKED(x, args[0]);
@@ -6383,17 +6735,18 @@
   if (y == 0) {
     return Smi::FromInt(1);
   } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
-    return Heap::nan_value();
+    return isolate->heap()->nan_value();
   } else {
-    return Heap::AllocateHeapNumber(pow(x, y));
+    return isolate->heap()->AllocateHeapNumber(pow(x, y));
   }
 }
 
 
-static MaybeObject* Runtime_RoundNumber(Arguments args) {
+static MaybeObject* Runtime_RoundNumber(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  Counters::math_round.Increment();
+  isolate->counters()->math_round()->Increment();
 
   if (!args[0]->IsHeapNumber()) {
     // Must be smi. Return the argument unchanged for all the other types
@@ -6419,40 +6772,43 @@
     return number;
   }
 
-  if (sign && value >= -0.5) return Heap::minus_zero_value();
+  if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
 
   // Do not call NumberFromDouble() to avoid extra checks.
-  return Heap::AllocateHeapNumber(floor(value + 0.5));
+  return isolate->heap()->AllocateHeapNumber(floor(value + 0.5));
 }
 
 
-static MaybeObject* Runtime_Math_sin(Arguments args) {
+static MaybeObject* Runtime_Math_sin(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  Counters::math_sin.Increment();
+  isolate->counters()->math_sin()->Increment();
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
-  return TranscendentalCache::Get(TranscendentalCache::SIN, x);
+  return isolate->transcendental_cache()->Get(TranscendentalCache::SIN, x);
 }
 
 
-static MaybeObject* Runtime_Math_sqrt(Arguments args) {
+static MaybeObject* Runtime_Math_sqrt(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  Counters::math_sqrt.Increment();
+  isolate->counters()->math_sqrt()->Increment();
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
-  return Heap::AllocateHeapNumber(sqrt(x));
+  return isolate->heap()->AllocateHeapNumber(sqrt(x));
 }
 
 
-static MaybeObject* Runtime_Math_tan(Arguments args) {
+static MaybeObject* Runtime_Math_tan(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  Counters::math_tan.Increment();
+  isolate->counters()->math_tan()->Increment();
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
-  return TranscendentalCache::Get(TranscendentalCache::TAN, x);
+  return isolate->transcendental_cache()->Get(TranscendentalCache::TAN, x);
 }
 
 
@@ -6501,7 +6857,8 @@
 }
 
 
-static MaybeObject* Runtime_DateMakeDay(Arguments args) {
+static MaybeObject* Runtime_DateMakeDay(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 3);
 
@@ -6800,7 +7157,8 @@
 }
 
 
-static MaybeObject* Runtime_DateYMDFromTime(Arguments args) {
+static MaybeObject* Runtime_DateYMDFromTime(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
@@ -6810,7 +7168,8 @@
   int year, month, day;
   DateYMDFromTime(static_cast<int>(floor(t / 86400000)), year, month, day);
 
-  RUNTIME_ASSERT(res_array->elements()->map() == Heap::fixed_array_map());
+  RUNTIME_ASSERT(res_array->elements()->map() ==
+                 isolate->heap()->fixed_array_map());
   FixedArray* elms = FixedArray::cast(res_array->elements());
   RUNTIME_ASSERT(elms->length() == 3);
 
@@ -6818,11 +7177,12 @@
   elms->set(1, Smi::FromInt(month));
   elms->set(2, Smi::FromInt(day));
 
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_NewArgumentsFast(Arguments args) {
+static MaybeObject* Runtime_NewArgumentsFast(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 3);
 
@@ -6831,20 +7191,21 @@
   const int length = Smi::cast(args[2])->value();
 
   Object* result;
-  { MaybeObject* maybe_result = Heap::AllocateArgumentsObject(callee, length);
+  { MaybeObject* maybe_result =
+        isolate->heap()->AllocateArgumentsObject(callee, length);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   // Allocate the elements if needed.
   if (length > 0) {
     // Allocate the fixed array.
     Object* obj;
-    { MaybeObject* maybe_obj = Heap::AllocateRawFixedArray(length);
+    { MaybeObject* maybe_obj = isolate->heap()->AllocateRawFixedArray(length);
       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
     }
 
     AssertNoAllocation no_gc;
     FixedArray* array = reinterpret_cast<FixedArray*>(obj);
-    array->set_map(Heap::fixed_array_map());
+    array->set_map(isolate->heap()->fixed_array_map());
     array->set_length(length);
 
     WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
@@ -6857,8 +7218,9 @@
 }
 
 
-static MaybeObject* Runtime_NewClosure(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_NewClosure(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 3);
   CONVERT_ARG_CHECKED(Context, context, 0);
   CONVERT_ARG_CHECKED(SharedFunctionInfo, shared, 1);
@@ -6870,15 +7232,15 @@
   pretenure = pretenure || (context->global_context() == *context);
   PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
   Handle<JSFunction> result =
-      Factory::NewFunctionFromSharedFunctionInfo(shared,
-                                                 context,
-                                                 pretenure_flag);
+      isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
+                                                            context,
+                                                            pretenure_flag);
   return *result;
 }
 
-
-static MaybeObject* Runtime_NewObjectFromBound(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_NewObjectFromBound(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 2);
   // First argument is a function to use as a constructor.
   CONVERT_ARG_CHECKED(JSFunction, function, 0);
@@ -6899,7 +7261,7 @@
   ASSERT(!frame->is_optimized());
   it.AdvanceToArgumentsFrame();
   frame = it.frame();
-  int argc = frame->GetProvidedParametersCount();
+  int argc = frame->ComputeParametersCount();
 
   // Prepend bound arguments to caller's arguments.
   int total_argc = bound_argc + argc;
@@ -6925,10 +7287,11 @@
 }
 
 
-static void TrySettingInlineConstructStub(Handle<JSFunction> function) {
-  Handle<Object> prototype = Factory::null_value();
+static void TrySettingInlineConstructStub(Isolate* isolate,
+                                          Handle<JSFunction> function) {
+  Handle<Object> prototype = isolate->factory()->null_value();
   if (function->has_instance_prototype()) {
-    prototype = Handle<Object>(function->instance_prototype());
+    prototype = Handle<Object>(function->instance_prototype(), isolate);
   }
   if (function->shared()->CanGenerateInlineConstructor(*prototype)) {
     ConstructStubCompiler compiler;
@@ -6941,8 +7304,9 @@
 }
 
 
-static MaybeObject* Runtime_NewObject(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_NewObject(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
 
   Handle<Object> constructor = args.at<Object>(0);
@@ -6951,8 +7315,8 @@
   if (!constructor->IsJSFunction()) {
     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
     Handle<Object> type_error =
-        Factory::NewTypeError("not_constructor", arguments);
-    return Top::Throw(*type_error);
+        isolate->factory()->NewTypeError("not_constructor", arguments);
+    return isolate->Throw(*type_error);
   }
 
   Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
@@ -6962,14 +7326,15 @@
   if (!function->should_have_prototype()) {
     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
     Handle<Object> type_error =
-        Factory::NewTypeError("not_constructor", arguments);
-    return Top::Throw(*type_error);
+        isolate->factory()->NewTypeError("not_constructor", arguments);
+    return isolate->Throw(*type_error);
   }
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
+  Debug* debug = isolate->debug();
   // Handle stepping into constructors if step into is active.
-  if (Debug::StepInActive()) {
-    Debug::HandleStepIn(function, Handle<Object>::null(), 0, true);
+  if (debug->StepInActive()) {
+    debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
   }
 #endif
 
@@ -6979,14 +7344,14 @@
       // 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. Factory::NewJSObject() should not be used to
+      // JSFunction. FACTORY->NewJSObject() 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 isolate->context()->global();
     }
   }
 
@@ -6994,7 +7359,7 @@
   // available. We cannot use EnsureCompiled because that forces a
   // compilation through the shared function info which makes it
   // impossible for us to optimize.
-  Handle<SharedFunctionInfo> shared(function->shared());
+  Handle<SharedFunctionInfo> shared(function->shared(), isolate);
   if (!function->is_compiled()) CompileLazy(function, CLEAR_EXCEPTION);
 
   if (!function->has_initial_map() &&
@@ -7006,34 +7371,36 @@
   }
 
   bool first_allocation = !shared->live_objects_may_exist();
-  Handle<JSObject> result = Factory::NewJSObject(function);
-  RETURN_IF_EMPTY_HANDLE(result);
+  Handle<JSObject> result = isolate->factory()->NewJSObject(function);
+  RETURN_IF_EMPTY_HANDLE(isolate, result);
   // Delay setting the stub if inobject slack tracking is in progress.
   if (first_allocation && !shared->IsInobjectSlackTrackingInProgress()) {
-    TrySettingInlineConstructStub(function);
+    TrySettingInlineConstructStub(isolate, function);
   }
 
-  Counters::constructed_objects.Increment();
-  Counters::constructed_objects_runtime.Increment();
+  isolate->counters()->constructed_objects()->Increment();
+  isolate->counters()->constructed_objects_runtime()->Increment();
 
   return *result;
 }
 
 
-static MaybeObject* Runtime_FinalizeInstanceSize(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_FinalizeInstanceSize(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
 
   CONVERT_ARG_CHECKED(JSFunction, function, 0);
   function->shared()->CompleteInobjectSlackTracking();
-  TrySettingInlineConstructStub(function);
+  TrySettingInlineConstructStub(isolate, function);
 
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_LazyCompile(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_LazyCompile(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
 
   Handle<JSFunction> function = args.at<JSFunction>(0);
@@ -7063,20 +7430,21 @@
 }
 
 
-static MaybeObject* Runtime_LazyRecompile(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_LazyRecompile(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   Handle<JSFunction> function = args.at<JSFunction>(0);
   // If the function is not optimizable or debugger is active continue using the
   // code from the full compiler.
   if (!function->shared()->code()->optimizable() ||
-      Debug::has_break_points()) {
+      isolate->debug()->has_break_points()) {
     if (FLAG_trace_opt) {
       PrintF("[failed to optimize ");
       function->PrintName();
       PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
           function->shared()->code()->optimizable() ? "T" : "F",
-          Debug::has_break_points() ? "T" : "F");
+          isolate->debug()->has_break_points() ? "T" : "F");
     }
     function->ReplaceCode(function->shared()->code());
     return function->code();
@@ -7094,14 +7462,15 @@
 }
 
 
-static MaybeObject* Runtime_NotifyDeoptimized(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_NotifyDeoptimized(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   RUNTIME_ASSERT(args[0]->IsSmi());
   Deoptimizer::BailoutType type =
       static_cast<Deoptimizer::BailoutType>(Smi::cast(args[0])->value());
-  Deoptimizer* deoptimizer = Deoptimizer::Grab();
-  ASSERT(Heap::IsAllocationAllowed());
+  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
+  ASSERT(isolate->heap()->IsAllocationAllowed());
   int frames = deoptimizer->output_count();
 
   JavaScriptFrameIterator it;
@@ -7114,24 +7483,24 @@
   delete deoptimizer;
 
   RUNTIME_ASSERT(frame->function()->IsJSFunction());
-  Handle<JSFunction> function(JSFunction::cast(frame->function()));
+  Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate);
   Handle<Object> arguments;
   for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) {
-    if (frame->GetExpression(i) == Heap::arguments_marker()) {
+    if (frame->GetExpression(i) == isolate->heap()->arguments_marker()) {
       if (arguments.is_null()) {
         // FunctionGetArguments can't throw an exception, so cast away the
         // doubt with an assert.
         arguments = Handle<Object>(
             Accessors::FunctionGetArguments(*function,
                                             NULL)->ToObjectUnchecked());
-        ASSERT(*arguments != Heap::null_value());
-        ASSERT(*arguments != Heap::undefined_value());
+        ASSERT(*arguments != isolate->heap()->null_value());
+        ASSERT(*arguments != isolate->heap()->undefined_value());
       }
       frame->SetExpression(i, *arguments);
     }
   }
 
-  CompilationCache::MarkForLazyOptimizing(function);
+  isolate->compilation_cache()->MarkForLazyOptimizing(function);
   if (type == Deoptimizer::EAGER) {
     RUNTIME_ASSERT(function->IsOptimized());
   } else {
@@ -7141,7 +7510,7 @@
   // Avoid doing too much work when running with --always-opt and keep
   // the optimized code around.
   if (FLAG_always_opt || type == Deoptimizer::LAZY) {
-    return Heap::undefined_value();
+    return isolate->heap()->undefined_value();
   }
 
   // Count the number of optimized activations of the function.
@@ -7164,31 +7533,35 @@
     }
     function->ReplaceCode(function->shared()->code());
   }
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_NotifyOSR(Arguments args) {
-  Deoptimizer* deoptimizer = Deoptimizer::Grab();
+static MaybeObject* Runtime_NotifyOSR(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
   delete deoptimizer;
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_DeoptimizeFunction(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_DeoptimizeFunction(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   CONVERT_ARG_CHECKED(JSFunction, function, 0);
-  if (!function->IsOptimized()) return Heap::undefined_value();
+  if (!function->IsOptimized()) return isolate->heap()->undefined_value();
 
   Deoptimizer::DeoptimizeFunction(*function);
 
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_CompileForOnStackReplacement(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_CompileForOnStackReplacement(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   CONVERT_ARG_CHECKED(JSFunction, function, 0);
 
@@ -7197,7 +7570,7 @@
 
   // We have hit a back edge in an unoptimized frame for a function that was
   // selected for on-stack replacement.  Find the unoptimized code object.
-  Handle<Code> unoptimized(function->shared()->code());
+  Handle<Code> unoptimized(function->shared()->code(), isolate);
   // Keep track of whether we've succeeded in optimizing.
   bool succeeded = unoptimized->optimizable();
   if (succeeded) {
@@ -7221,7 +7594,7 @@
     JavaScriptFrameIterator it;
     JavaScriptFrame* frame = it.frame();
     ASSERT(frame->function() == *function);
-    ASSERT(frame->code() == *unoptimized);
+    ASSERT(frame->LookupCode(isolate) == *unoptimized);
     ASSERT(unoptimized->contains(frame->pc()));
 
     // Use linear search of the unoptimized code's stack check table to find
@@ -7278,8 +7651,7 @@
   }
   StackCheckStub check_stub;
   Handle<Code> check_code = check_stub.GetCode();
-  Handle<Code> replacement_code(
-      Builtins::builtin(Builtins::OnStackReplacement));
+  Handle<Code> replacement_code = isolate->builtins()->OnStackReplacement();
   Deoptimizer::RevertStackCheckCode(*unoptimized,
                                     *check_code,
                                     *replacement_code);
@@ -7302,40 +7674,45 @@
 }
 
 
-static MaybeObject* Runtime_GetFunctionDelegate(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetFunctionDelegate(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   RUNTIME_ASSERT(!args[0]->IsJSFunction());
   return *Execution::GetFunctionDelegate(args.at<Object>(0));
 }
 
 
-static MaybeObject* Runtime_GetConstructorDelegate(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetConstructorDelegate(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   RUNTIME_ASSERT(!args[0]->IsJSFunction());
   return *Execution::GetConstructorDelegate(args.at<Object>(0));
 }
 
 
-static MaybeObject* Runtime_NewContext(Arguments args) {
+static MaybeObject* Runtime_NewContext(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
   CONVERT_CHECKED(JSFunction, function, args[0]);
   int length = function->shared()->scope_info()->NumberOfContextSlots();
   Object* result;
-  { MaybeObject* maybe_result = Heap::AllocateFunctionContext(length, function);
+  { MaybeObject* maybe_result =
+        isolate->heap()->AllocateFunctionContext(length, function);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
 
-  Top::set_context(Context::cast(result));
+  isolate->set_context(Context::cast(result));
 
   return result;  // non-failure
 }
 
 
-MUST_USE_RESULT static MaybeObject* PushContextHelper(Object* object,
+MUST_USE_RESULT static MaybeObject* PushContextHelper(Isolate* isolate,
+                                                      Object* object,
                                                       bool is_catch_context) {
   // Convert the object to a proper JavaScript object.
   Object* js_object = object;
@@ -7345,45 +7722,47 @@
       if (!Failure::cast(maybe_js_object)->IsInternalError()) {
         return maybe_js_object;
       }
-      HandleScope scope;
-      Handle<Object> handle(object);
+      HandleScope scope(isolate);
+      Handle<Object> handle(object, isolate);
       Handle<Object> result =
-          Factory::NewTypeError("with_expression", HandleVector(&handle, 1));
-      return Top::Throw(*result);
+          isolate->factory()->NewTypeError("with_expression",
+                                           HandleVector(&handle, 1));
+      return isolate->Throw(*result);
     }
   }
 
   Object* result;
-  { MaybeObject* maybe_result =
-        Heap::AllocateWithContext(Top::context(),
-                                  JSObject::cast(js_object),
-                                  is_catch_context);
+  { MaybeObject* maybe_result = isolate->heap()->AllocateWithContext(
+      isolate->context(), JSObject::cast(js_object), is_catch_context);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
 
   Context* context = Context::cast(result);
-  Top::set_context(context);
+  isolate->set_context(context);
 
   return result;
 }
 
 
-static MaybeObject* Runtime_PushContext(Arguments args) {
+static MaybeObject* Runtime_PushContext(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  return PushContextHelper(args[0], false);
+  return PushContextHelper(isolate, args[0], false);
 }
 
 
-static MaybeObject* Runtime_PushCatchContext(Arguments args) {
+static MaybeObject* Runtime_PushCatchContext(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
-  return PushContextHelper(args[0], true);
+  return PushContextHelper(isolate, args[0], true);
 }
 
 
-static MaybeObject* Runtime_DeleteContextSlot(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_DeleteContextSlot(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 2);
 
   CONVERT_ARG_CHECKED(Context, context, 0);
@@ -7396,12 +7775,12 @@
 
   // If the slot was not found the result is true.
   if (holder.is_null()) {
-    return Heap::true_value();
+    return isolate->heap()->true_value();
   }
 
   // If the slot was found in a context, it should be DONT_DELETE.
   if (holder->IsContext()) {
-    return Heap::false_value();
+    return isolate->heap()->false_value();
   }
 
   // The slot was found in a JSObject, either a context extension object,
@@ -7449,17 +7828,19 @@
 #endif
 
 
-static inline MaybeObject* Unhole(MaybeObject* x,
+static inline MaybeObject* Unhole(Heap* heap,
+                                  MaybeObject* x,
                                   PropertyAttributes attributes) {
   ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
   USE(attributes);
-  return x->IsTheHole() ? Heap::undefined_value() : x;
+  return x->IsTheHole() ? heap->undefined_value() : x;
 }
 
 
-static JSObject* ComputeReceiverForNonGlobal(JSObject* holder) {
+static JSObject* ComputeReceiverForNonGlobal(Isolate* isolate,
+                                             JSObject* holder) {
   ASSERT(!holder->IsGlobalObject());
-  Context* top = Top::context();
+  Context* top = isolate->context();
   // Get the context extension function.
   JSFunction* context_extension_function =
       top->global_context()->context_extension_function();
@@ -7476,12 +7857,14 @@
 }
 
 
-static ObjectPair LoadContextSlotHelper(Arguments args, bool throw_error) {
-  HandleScope scope;
+static ObjectPair LoadContextSlotHelper(Arguments args,
+                                        Isolate* isolate,
+                                        bool throw_error) {
+  HandleScope scope(isolate);
   ASSERT_EQ(2, args.length());
 
   if (!args[0]->IsContext() || !args[1]->IsString()) {
-    return MakePair(Top::ThrowIllegalOperation(), NULL);
+    return MakePair(isolate->ThrowIllegalOperation(), NULL);
   }
   Handle<Context> context = args.at<Context>(0);
   Handle<String> name = args.at<String>(1);
@@ -7498,11 +7881,12 @@
     // 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();
+    JSObject* receiver =
+        isolate->context()->global()->global_receiver();
     MaybeObject* value = (holder->IsContext())
         ? Context::cast(*holder)->get(index)
         : JSObject::cast(*holder)->GetElement(index);
-    return MakePair(Unhole(value, attributes), receiver);
+    return MakePair(Unhole(isolate->heap(), value, attributes), receiver);
   }
 
   // If the holder is found, we read the property from it.
@@ -7513,9 +7897,9 @@
     if (object->IsGlobalObject()) {
       receiver = GlobalObject::cast(object)->global_receiver();
     } else if (context->is_exception_holder(*holder)) {
-      receiver = Top::context()->global()->global_receiver();
+      receiver = isolate->context()->global()->global_receiver();
     } else {
-      receiver = ComputeReceiverForNonGlobal(object);
+      receiver = ComputeReceiverForNonGlobal(isolate, object);
     }
     // No need to unhole the value here. This is taken care of by the
     // GetProperty function.
@@ -7526,30 +7910,36 @@
   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);
+        isolate->factory()->NewReferenceError("not_defined",
+                                              HandleVector(&name, 1));
+    return MakePair(isolate->Throw(*reference_error), NULL);
   } else {
     // The property doesn't exist - return undefined
-    return MakePair(Heap::undefined_value(), Heap::undefined_value());
+    return MakePair(isolate->heap()->undefined_value(),
+                    isolate->heap()->undefined_value());
   }
 }
 
 
-static ObjectPair Runtime_LoadContextSlot(Arguments args) {
-  return LoadContextSlotHelper(args, true);
+static ObjectPair Runtime_LoadContextSlot(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  return LoadContextSlotHelper(args, isolate, true);
 }
 
 
-static ObjectPair Runtime_LoadContextSlotNoReferenceError(Arguments args) {
-  return LoadContextSlotHelper(args, false);
+static ObjectPair Runtime_LoadContextSlotNoReferenceError(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  return LoadContextSlotHelper(args, isolate, false);
 }
 
 
-static MaybeObject* Runtime_StoreContextSlot(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_StoreContextSlot(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 4);
 
-  Handle<Object> value(args[0]);
+  Handle<Object> value(args[0], isolate);
   CONVERT_ARG_CHECKED(Context, context, 1);
   CONVERT_ARG_CHECKED(String, name, 2);
   CONVERT_SMI_CHECKED(strict_unchecked, args[3]);
@@ -7571,16 +7961,16 @@
       } else if (strict_mode == kStrictMode) {
         // Setting read only property in strict mode.
         Handle<Object> error =
-            Factory::NewTypeError("strict_cannot_assign",
-                                  HandleVector(&name, 1));
-        return Top::Throw(*error);
+            isolate->factory()->NewTypeError("strict_cannot_assign",
+                                             HandleVector(&name, 1));
+        return isolate->Throw(*error);
       }
     } else {
       ASSERT((attributes & READ_ONLY) == 0);
       Handle<Object> result =
           SetElement(Handle<JSObject>::cast(holder), index, value, strict_mode);
       if (result.is_null()) {
-        ASSERT(Top::has_pending_exception());
+        ASSERT(isolate->has_pending_exception());
         return Failure::Exception();
       }
     }
@@ -7598,7 +7988,7 @@
     // 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());
+    context_ext = Handle<JSObject>(isolate->context()->global());
   }
 
   // Set the property, but ignore if read_only variable on the context
@@ -7606,62 +7996,66 @@
   if ((attributes & READ_ONLY) == 0 ||
       (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) {
     RETURN_IF_EMPTY_HANDLE(
+        isolate,
         SetProperty(context_ext, name, value, NONE, strict_mode));
   } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) {
     // Setting read only property in strict mode.
     Handle<Object> error =
-        Factory::NewTypeError("strict_cannot_assign", HandleVector(&name, 1));
-    return Top::Throw(*error);
+      isolate->factory()->NewTypeError(
+          "strict_cannot_assign", HandleVector(&name, 1));
+    return isolate->Throw(*error);
   }
   return *value;
 }
 
 
-static MaybeObject* Runtime_Throw(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_Throw(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
 
-  return Top::Throw(args[0]);
+  return isolate->Throw(args[0]);
 }
 
 
-static MaybeObject* Runtime_ReThrow(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_ReThrow(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
 
-  return Top::ReThrow(args[0]);
+  return isolate->ReThrow(args[0]);
 }
 
 
-static MaybeObject* Runtime_PromoteScheduledException(Arguments args) {
+static MaybeObject* Runtime_PromoteScheduledException(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT_EQ(0, args.length());
-  return Top::PromoteScheduledException();
+  return isolate->PromoteScheduledException();
 }
 
 
-static MaybeObject* Runtime_ThrowReferenceError(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_ThrowReferenceError(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
 
-  Handle<Object> name(args[0]);
+  Handle<Object> name(args[0], isolate);
   Handle<Object> reference_error =
-    Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
-  return Top::Throw(*reference_error);
+    isolate->factory()->NewReferenceError("not_defined",
+                                          HandleVector(&name, 1));
+  return isolate->Throw(*reference_error);
 }
 
 
-static MaybeObject* Runtime_StackOverflow(Arguments args) {
-  NoHandleAllocation na;
-  return Top::StackOverflow();
-}
-
-
-static MaybeObject* Runtime_StackGuard(Arguments args) {
+static MaybeObject* Runtime_StackGuard(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 0);
 
   // First check if this is a real stack overflow.
-  if (StackGuard::IsStackOverflow()) {
-    return Runtime_StackOverflow(args);
+  if (isolate->stack_guard()->IsStackOverflow()) {
+    NoHandleAllocation na;
+    return isolate->StackOverflow();
   }
 
   return Execution::HandleStackGuardInterrupt();
@@ -7738,7 +8132,7 @@
     // supplied parameters, not all parameters required)
     PrintF("(this=");
     PrintObject(frame->receiver());
-    const int length = frame->GetProvidedParametersCount();
+    const int length = frame->ComputeParametersCount();
     for (int i = 0; i < length; i++) {
       PrintF(", ");
       PrintObject(frame->GetParameter(i));
@@ -7754,22 +8148,25 @@
 }
 
 
-static MaybeObject* Runtime_TraceEnter(Arguments args) {
+static MaybeObject* Runtime_TraceEnter(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 0);
   NoHandleAllocation ha;
   PrintTransition(NULL);
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_TraceExit(Arguments args) {
+static MaybeObject* Runtime_TraceExit(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   PrintTransition(args[0]);
   return args[0];  // return TOS
 }
 
 
-static MaybeObject* Runtime_DebugPrint(Arguments args) {
+static MaybeObject* Runtime_DebugPrint(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
@@ -7800,15 +8197,17 @@
 }
 
 
-static MaybeObject* Runtime_DebugTrace(Arguments args) {
+static MaybeObject* Runtime_DebugTrace(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 0);
   NoHandleAllocation ha;
-  Top::PrintStack();
-  return Heap::undefined_value();
+  isolate->PrintStack();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_DateCurrentTime(Arguments args) {
+static MaybeObject* Runtime_DateCurrentTime(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 0);
 
@@ -7817,12 +8216,13 @@
   // time is milliseconds. Therefore, we floor the result of getting
   // the OS time.
   double millis = floor(OS::TimeCurrentMillis());
-  return Heap::NumberFromDouble(millis);
+  return isolate->heap()->NumberFromDouble(millis);
 }
 
 
-static MaybeObject* Runtime_DateParseString(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_DateParseString(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 2);
 
   CONVERT_ARG_CHECKED(String, str, 0);
@@ -7846,109 +8246,119 @@
   if (result) {
     return *output;
   } else {
-    return Heap::null_value();
+    return isolate->heap()->null_value();
   }
 }
 
 
-static MaybeObject* Runtime_DateLocalTimezone(Arguments args) {
+static MaybeObject* Runtime_DateLocalTimezone(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
   const char* zone = OS::LocalTimezone(x);
-  return Heap::AllocateStringFromUtf8(CStrVector(zone));
+  return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
 }
 
 
-static MaybeObject* Runtime_DateLocalTimeOffset(Arguments args) {
+static MaybeObject* Runtime_DateLocalTimeOffset(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 0);
 
-  return Heap::NumberFromDouble(OS::LocalTimeOffset());
+  return isolate->heap()->NumberFromDouble(OS::LocalTimeOffset());
 }
 
 
-static MaybeObject* Runtime_DateDaylightSavingsOffset(Arguments args) {
+static MaybeObject* Runtime_DateDaylightSavingsOffset(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
   CONVERT_DOUBLE_CHECKED(x, args[0]);
-  return Heap::NumberFromDouble(OS::DaylightSavingsOffset(x));
+  return isolate->heap()->NumberFromDouble(OS::DaylightSavingsOffset(x));
 }
 
 
-static MaybeObject* Runtime_GlobalReceiver(Arguments args) {
+static MaybeObject* Runtime_GlobalReceiver(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 1);
   Object* global = args[0];
-  if (!global->IsJSGlobalObject()) return Heap::null_value();
+  if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
   return JSGlobalObject::cast(global)->global_receiver();
 }
 
 
-static MaybeObject* Runtime_ParseJson(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_ParseJson(RUNTIME_CALLING_CONVENTION) {
+  HandleScope scope(isolate);
   ASSERT_EQ(1, args.length());
   CONVERT_ARG_CHECKED(String, source, 0);
 
   Handle<Object> result = JsonParser::Parse(source);
   if (result.is_null()) {
     // Syntax error or stack overflow in scanner.
-    ASSERT(Top::has_pending_exception());
+    ASSERT(isolate->has_pending_exception());
     return Failure::Exception();
   }
   return *result;
 }
 
 
-static MaybeObject* Runtime_CompileString(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_CompileString(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT_EQ(1, args.length());
   CONVERT_ARG_CHECKED(String, source, 0);
 
   // Compile source string in the global context.
-  Handle<Context> context(Top::context()->global_context());
+  Handle<Context> context(isolate->context()->global_context());
   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source,
                                                             context,
                                                             true,
                                                             kNonStrictMode);
   if (shared.is_null()) return Failure::Exception();
   Handle<JSFunction> fun =
-      Factory::NewFunctionFromSharedFunctionInfo(shared, context, NOT_TENURED);
+      isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
+                                                            context,
+                                                            NOT_TENURED);
   return *fun;
 }
 
 
-static ObjectPair CompileGlobalEval(Handle<String> source,
+static ObjectPair CompileGlobalEval(Isolate* isolate,
+                                    Handle<String> source,
                                     Handle<Object> receiver,
-                                    StrictModeFlag mode) {
+                                    StrictModeFlag strict_mode) {
   // Deal with a normal eval call with a string argument. Compile it
   // and return the compiled function bound in the local context.
   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
       source,
-      Handle<Context>(Top::context()),
-      Top::context()->IsGlobalContext(),
-      mode);
+      Handle<Context>(isolate->context()),
+      isolate->context()->IsGlobalContext(),
+      strict_mode);
   if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
-  Handle<JSFunction> compiled = Factory::NewFunctionFromSharedFunctionInfo(
-      shared,
-      Handle<Context>(Top::context()),
-      NOT_TENURED);
+  Handle<JSFunction> compiled =
+      isolate->factory()->NewFunctionFromSharedFunctionInfo(
+          shared, Handle<Context>(isolate->context()), NOT_TENURED);
   return MakePair(*compiled, *receiver);
 }
 
 
-static ObjectPair Runtime_ResolvePossiblyDirectEval(Arguments args) {
+static ObjectPair Runtime_ResolvePossiblyDirectEval(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 4);
 
-  HandleScope scope;
+  HandleScope scope(isolate);
   Handle<Object> callee = args.at<Object>(0);
   Handle<Object> receiver;  // Will be overwritten.
 
   // Compute the calling context.
-  Handle<Context> context = Handle<Context>(Top::context());
+  Handle<Context> context = Handle<Context>(isolate->context(), isolate);
 #ifdef DEBUG
-  // Make sure Top::context() agrees with the old code that traversed
+  // Make sure Isolate::context() agrees with the old code that traversed
   // the stack frames to compute the context.
   StackFrameLocator locator;
   JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
@@ -7960,25 +8370,28 @@
   int index = -1;
   PropertyAttributes attributes = ABSENT;
   while (true) {
-    receiver = context->Lookup(Factory::eval_symbol(), FOLLOW_PROTOTYPE_CHAIN,
+    receiver = context->Lookup(isolate->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()));
+      context = Handle<Context>(Context::cast(context->closure()->context()),
+                                isolate);
     } else {
-      context = Handle<Context>(context->previous());
+      context = Handle<Context>(context->previous(), isolate);
     }
   }
 
   // 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> name = isolate->factory()->eval_symbol();
     Handle<Object> reference_error =
-        Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
-    return MakePair(Top::Throw(*reference_error), NULL);
+        isolate->factory()->NewReferenceError("not_defined",
+                                              HandleVector(&name, 1));
+    return MakePair(isolate->Throw(*reference_error), NULL);
   }
 
   if (!context->IsGlobalContext()) {
@@ -7986,67 +8399,80 @@
     // 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));
+      receiver = Handle<Object>(context->get(index), isolate);
     } else if (receiver->IsJSContextExtensionObject()) {
-      receiver = Handle<JSObject>(Top::context()->global()->global_receiver());
+      receiver = Handle<JSObject>(
+          isolate->context()->global()->global_receiver(), isolate);
     }
     return MakePair(*callee, *receiver);
   }
 
   // 'eval' is bound in the global context, but it may have been overwritten.
   // Compare it to the builtin 'GlobalEval' function to make sure.
-  if (*callee != Top::global_context()->global_eval_fun() ||
+  if (*callee != isolate->global_context()->global_eval_fun() ||
       !args[1]->IsString()) {
-    return MakePair(*callee, Top::context()->global()->global_receiver());
+    return MakePair(*callee,
+                    isolate->context()->global()->global_receiver());
   }
 
   ASSERT(args[3]->IsSmi());
-  return CompileGlobalEval(args.at<String>(1),
+  return CompileGlobalEval(isolate,
+                           args.at<String>(1),
                            args.at<Object>(2),
                            static_cast<StrictModeFlag>(
                                 Smi::cast(args[3])->value()));
 }
 
 
-static ObjectPair Runtime_ResolvePossiblyDirectEvalNoLookup(Arguments args) {
+static ObjectPair Runtime_ResolvePossiblyDirectEvalNoLookup(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 4);
 
-  HandleScope scope;
+  HandleScope scope(isolate);
   Handle<Object> callee = args.at<Object>(0);
 
   // 'eval' is bound in the global context, but it may have been overwritten.
   // Compare it to the builtin 'GlobalEval' function to make sure.
-  if (*callee != Top::global_context()->global_eval_fun() ||
+  if (*callee != isolate->global_context()->global_eval_fun() ||
       !args[1]->IsString()) {
-    return MakePair(*callee, Top::context()->global()->global_receiver());
+    return MakePair(*callee,
+                    isolate->context()->global()->global_receiver());
   }
 
   ASSERT(args[3]->IsSmi());
-  return CompileGlobalEval(args.at<String>(1),
+  return CompileGlobalEval(isolate,
+                           args.at<String>(1),
                            args.at<Object>(2),
                            static_cast<StrictModeFlag>(
                                 Smi::cast(args[3])->value()));
 }
 
 
-static MaybeObject* Runtime_SetNewFunctionAttributes(Arguments args) {
+static MaybeObject* Runtime_SetNewFunctionAttributes(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   // 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;
+  HandleScope scope(isolate);
   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());
+
+  Handle<Map> map = func->shared()->strict_mode()
+                        ? isolate->strict_mode_function_instance_map()
+                        : isolate->function_instance_map();
+
+  ASSERT(func->map()->instance_type() == map->instance_type());
+  ASSERT(func->map()->instance_size() == map->instance_size());
+  func->set_map(*map);
   return *func;
 }
 
 
-static MaybeObject* Runtime_AllocateInNewSpace(Arguments args) {
+static MaybeObject* Runtime_AllocateInNewSpace(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   // Allocate a block of memory in NewSpace (filled with a filler).
   // Use as fallback for allocation in generated code when NewSpace
   // is full.
@@ -8055,13 +8481,13 @@
   int size = size_smi->value();
   RUNTIME_ASSERT(IsAligned(size, kPointerSize));
   RUNTIME_ASSERT(size > 0);
-  static const int kMinFreeNewSpaceAfterGC =
-      Heap::InitialSemiSpaceSize() * 3/4;
+  Heap* heap = isolate->heap();
+  const int kMinFreeNewSpaceAfterGC = heap->InitialSemiSpaceSize() * 3/4;
   RUNTIME_ASSERT(size <= kMinFreeNewSpaceAfterGC);
   Object* allocation;
-  { MaybeObject* maybe_allocation = Heap::new_space()->AllocateRaw(size);
+  { MaybeObject* maybe_allocation = heap->new_space()->AllocateRaw(size);
     if (maybe_allocation->ToObject(&allocation)) {
-      Heap::CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size);
+      heap->CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size);
     }
     return maybe_allocation;
   }
@@ -8071,7 +8497,8 @@
 // Push an object unto an array of objects if it is not already in the
 // array.  Returns true if the element was pushed on the stack and
 // false otherwise.
-static MaybeObject* Runtime_PushIfAbsent(Arguments args) {
+static MaybeObject* Runtime_PushIfAbsent(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
   CONVERT_CHECKED(JSArray, array, args[0]);
   CONVERT_CHECKED(JSObject, element, args[1]);
@@ -8079,7 +8506,7 @@
   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();
+    if (elements->get(i) == element) return isolate->heap()->false_value();
   }
   Object* obj;
   // Strict not needed. Used for cycle detection in Array join implementation.
@@ -8087,7 +8514,7 @@
                                                    kNonStrictMode);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
-  return Heap::true_value();
+  return isolate->heap()->true_value();
 }
 
 
@@ -8104,9 +8531,12 @@
  */
 class ArrayConcatVisitor {
  public:
-  ArrayConcatVisitor(Handle<FixedArray> storage,
+  ArrayConcatVisitor(Isolate* isolate,
+                     Handle<FixedArray> storage,
                      bool fast_elements) :
-    storage_(Handle<FixedArray>::cast(GlobalHandles::Create(*storage))),
+      isolate_(isolate),
+      storage_(Handle<FixedArray>::cast(
+          isolate->global_handles()->Create(*storage))),
       index_offset_(0u),
       fast_elements_(fast_elements) { }
 
@@ -8133,7 +8563,7 @@
     ASSERT(!fast_elements_);
     Handle<NumberDictionary> dict(NumberDictionary::cast(*storage_));
     Handle<NumberDictionary> result =
-        Factory::DictionaryAtNumberPut(dict, index, elm);
+        isolate_->factory()->DictionaryAtNumberPut(dict, index, elm);
     if (!result.is_identical_to(dict)) {
       // Dictionary needed to grow.
       clear_storage();
@@ -8150,14 +8580,14 @@
   }
 
   Handle<JSArray> ToArray() {
-    Handle<JSArray> array = Factory::NewJSArray(0);
+    Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
     Handle<Object> length =
-        Factory::NewNumber(static_cast<double>(index_offset_));
+        isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
     Handle<Map> map;
     if (fast_elements_) {
-      map = Factory::GetFastElementsMap(Handle<Map>(array->map()));
+      map = isolate_->factory()->GetFastElementsMap(Handle<Map>(array->map()));
     } else {
-      map = Factory::GetSlowElementsMap(Handle<Map>(array->map()));
+      map = isolate_->factory()->GetSlowElementsMap(Handle<Map>(array->map()));
     }
     array->set_map(*map);
     array->set_length(*length);
@@ -8171,14 +8601,14 @@
     ASSERT(fast_elements_);
     Handle<FixedArray> current_storage(*storage_);
     Handle<NumberDictionary> slow_storage(
-        Factory::NewNumberDictionary(current_storage->length()));
+        isolate_->factory()->NewNumberDictionary(current_storage->length()));
     uint32_t current_length = static_cast<uint32_t>(current_storage->length());
     for (uint32_t i = 0; i < current_length; i++) {
       HandleScope loop_scope;
       Handle<Object> element(current_storage->get(i));
       if (!element->IsTheHole()) {
         Handle<NumberDictionary> new_storage =
-          Factory::DictionaryAtNumberPut(slow_storage, i, element);
+          isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element);
         if (!new_storage.is_identical_to(slow_storage)) {
           slow_storage = loop_scope.CloseAndEscape(new_storage);
         }
@@ -8190,13 +8620,16 @@
   }
 
   inline void clear_storage() {
-    GlobalHandles::Destroy(Handle<Object>::cast(storage_).location());
+    isolate_->global_handles()->Destroy(
+        Handle<Object>::cast(storage_).location());
   }
 
   inline void set_storage(FixedArray* storage) {
-    storage_ = Handle<FixedArray>::cast(GlobalHandles::Create(storage));
+    storage_ = Handle<FixedArray>::cast(
+        isolate_->global_handles()->Create(storage));
   }
 
+  Isolate* isolate_;
   Handle<FixedArray> storage_;  // Always a global handle.
   // Index after last seen index. Always less than or equal to
   // JSObject::kMaxElementCount.
@@ -8244,7 +8677,8 @@
 
 
 template<class ExternalArrayClass, class ElementType>
-static void IterateExternalArrayElements(Handle<JSObject> receiver,
+static void IterateExternalArrayElements(Isolate* isolate,
+                                         Handle<JSObject> receiver,
                                          bool elements_are_ints,
                                          bool elements_are_guaranteed_smis,
                                          ArrayConcatVisitor* visitor) {
@@ -8269,15 +8703,15 @@
           visitor->visit(j, e);
         } else {
           Handle<Object> e =
-              Factory::NewNumber(static_cast<ElementType>(val));
+              isolate->factory()->NewNumber(static_cast<ElementType>(val));
           visitor->visit(j, e);
         }
       }
     }
   } else {
     for (uint32_t j = 0; j < len; j++) {
-      HandleScope loop_scope;
-      Handle<Object> e = Factory::NewNumber(array->get(j));
+      HandleScope loop_scope(isolate);
+      Handle<Object> e = isolate->factory()->NewNumber(array->get(j));
       visitor->visit(j, e);
     }
   }
@@ -8327,9 +8761,9 @@
     default: {
       int dense_elements_length;
       switch (kind) {
-        case JSObject::PIXEL_ELEMENTS: {
+        case JSObject::EXTERNAL_PIXEL_ELEMENTS: {
         dense_elements_length =
-            PixelArray::cast(object->elements())->length();
+            ExternalPixelArray::cast(object->elements())->length();
           break;
         }
         case JSObject::EXTERNAL_BYTE_ELEMENTS: {
@@ -8406,7 +8840,8 @@
  * length.
  * Returns false if any access threw an exception, otherwise true.
  */
-static bool IterateElements(Handle<JSArray> receiver,
+static bool IterateElements(Isolate* isolate,
+                            Handle<JSArray> receiver,
                             ArrayConcatVisitor* visitor) {
   uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
   switch (receiver->GetElementsKind()) {
@@ -8417,8 +8852,8 @@
       int fast_length = static_cast<int>(length);
       ASSERT(fast_length <= elements->length());
       for (int j = 0; j < fast_length; j++) {
-        HandleScope loop_scope;
-        Handle<Object> element_value(elements->get(j));
+        HandleScope loop_scope(isolate);
+        Handle<Object> element_value(elements->get(j), isolate);
         if (!element_value->IsTheHole()) {
           visitor->visit(j, element_value);
         } else if (receiver->HasElement(j)) {
@@ -8453,8 +8888,9 @@
       }
       break;
     }
-    case JSObject::PIXEL_ELEMENTS: {
-      Handle<PixelArray> pixels(PixelArray::cast(receiver->elements()));
+    case JSObject::EXTERNAL_PIXEL_ELEMENTS: {
+      Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast(
+          receiver->elements()));
       for (uint32_t j = 0; j < length; j++) {
         Handle<Smi> e(Smi::FromInt(pixels->get(j)));
         visitor->visit(j, e);
@@ -8463,37 +8899,37 @@
     }
     case JSObject::EXTERNAL_BYTE_ELEMENTS: {
       IterateExternalArrayElements<ExternalByteArray, int8_t>(
-          receiver, true, true, visitor);
+          isolate, receiver, true, true, visitor);
       break;
     }
     case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
       IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
-          receiver, true, true, visitor);
+          isolate, receiver, true, true, visitor);
       break;
     }
     case JSObject::EXTERNAL_SHORT_ELEMENTS: {
       IterateExternalArrayElements<ExternalShortArray, int16_t>(
-          receiver, true, true, visitor);
+          isolate, receiver, true, true, visitor);
       break;
     }
     case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
       IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
-          receiver, true, true, visitor);
+          isolate, receiver, true, true, visitor);
       break;
     }
     case JSObject::EXTERNAL_INT_ELEMENTS: {
       IterateExternalArrayElements<ExternalIntArray, int32_t>(
-          receiver, true, false, visitor);
+          isolate, receiver, true, false, visitor);
       break;
     }
     case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
       IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
-          receiver, true, false, visitor);
+          isolate, receiver, true, false, visitor);
       break;
     }
     case JSObject::EXTERNAL_FLOAT_ELEMENTS: {
       IterateExternalArrayElements<ExternalFloatArray, float>(
-          receiver, false, false, visitor);
+          isolate, receiver, false, false, visitor);
       break;
     }
     default:
@@ -8511,9 +8947,10 @@
  * TODO(581): Fix non-compliance for very large concatenations and update to
  * following the ECMAScript 5 specification.
  */
-static MaybeObject* Runtime_ArrayConcat(Arguments args) {
+static MaybeObject* Runtime_ArrayConcat(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 1);
-  HandleScope handle_scope;
+  HandleScope handle_scope(isolate);
 
   CONVERT_ARG_CHECKED(JSArray, arguments, 0);
   int argument_count = static_cast<int>(arguments->length()->Number());
@@ -8568,22 +9005,23 @@
   if (fast_case) {
     // The backing storage array must have non-existing elements to
     // preserve holes across concat operations.
-    storage = Factory::NewFixedArrayWithHoles(estimate_result_length);
+    storage = isolate->factory()->NewFixedArrayWithHoles(
+        estimate_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::NewNumberDictionary(at_least_space_for));
+        isolate->factory()->NewNumberDictionary(at_least_space_for));
   }
 
-  ArrayConcatVisitor visitor(storage, fast_case);
+  ArrayConcatVisitor visitor(isolate, storage, fast_case);
 
   for (int i = 0; i < argument_count; i++) {
     Handle<Object> obj(elements->get(i));
     if (obj->IsJSArray()) {
       Handle<JSArray> array = Handle<JSArray>::cast(obj);
-      if (!IterateElements(array, &visitor)) {
+      if (!IterateElements(isolate, array, &visitor)) {
         return Failure::Exception();
       }
     } else {
@@ -8598,7 +9036,8 @@
 
 // This will not allocate (flatten the string), but it may run
 // very slowly for very deeply nested ConsStrings.  For debugging use only.
-static MaybeObject* Runtime_GlobalPrint(Arguments args) {
+static MaybeObject* Runtime_GlobalPrint(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
@@ -8616,7 +9055,8 @@
 // and are followed by non-existing element. Does not change the length
 // property.
 // Returns the number of non-undefined elements collected.
-static MaybeObject* Runtime_RemoveArrayHoles(Arguments args) {
+static MaybeObject* Runtime_RemoveArrayHoles(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
   CONVERT_CHECKED(JSObject, object, args[0]);
   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
@@ -8625,14 +9065,15 @@
 
 
 // Move contents of argument 0 (an array) to argument 1 (an array)
-static MaybeObject* Runtime_MoveArrayContents(Arguments args) {
+static MaybeObject* Runtime_MoveArrayContents(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
   CONVERT_CHECKED(JSArray, from, args[0]);
   CONVERT_CHECKED(JSArray, to, args[1]);
   HeapObject* new_elements = from->elements();
   MaybeObject* maybe_new_map;
-  if (new_elements->map() == Heap::fixed_array_map() ||
-      new_elements->map() == Heap::fixed_cow_array_map()) {
+  if (new_elements->map() == isolate->heap()->fixed_array_map() ||
+      new_elements->map() == isolate->heap()->fixed_cow_array_map()) {
     maybe_new_map = to->map()->GetFastElementsMap();
   } else {
     maybe_new_map = to->map()->GetSlowElementsMap();
@@ -8652,7 +9093,9 @@
 
 
 // How many elements does this object/array have?
-static MaybeObject* Runtime_EstimateNumberOfElements(Arguments args) {
+static MaybeObject* Runtime_EstimateNumberOfElements(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 1);
   CONVERT_CHECKED(JSObject, object, args[0]);
   HeapObject* elements = object->elements();
@@ -8666,8 +9109,9 @@
 }
 
 
-static MaybeObject* Runtime_SwapElements(Arguments args) {
-  HandleScope handle_scope;
+static MaybeObject* Runtime_SwapElements(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope handle_scope(isolate);
 
   ASSERT_EQ(3, args.length());
 
@@ -8678,19 +9122,21 @@
   uint32_t index1, index2;
   if (!key1->ToArrayIndex(&index1)
       || !key2->ToArrayIndex(&index2)) {
-    return Top::ThrowIllegalOperation();
+    return isolate->ThrowIllegalOperation();
   }
 
   Handle<JSObject> jsobject = Handle<JSObject>::cast(object);
   Handle<Object> tmp1 = GetElement(jsobject, index1);
-  RETURN_IF_EMPTY_HANDLE(tmp1);
+  RETURN_IF_EMPTY_HANDLE(isolate, tmp1);
   Handle<Object> tmp2 = GetElement(jsobject, index2);
-  RETURN_IF_EMPTY_HANDLE(tmp2);
+  RETURN_IF_EMPTY_HANDLE(isolate, tmp2);
 
-  RETURN_IF_EMPTY_HANDLE(SetElement(jsobject, index1, tmp2, kStrictMode));
-  RETURN_IF_EMPTY_HANDLE(SetElement(jsobject, index2, tmp1, kStrictMode));
+  RETURN_IF_EMPTY_HANDLE(isolate,
+                         SetElement(jsobject, index1, tmp2, kStrictMode));
+  RETURN_IF_EMPTY_HANDLE(isolate,
+                         SetElement(jsobject, index2, tmp1, kStrictMode));
 
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
@@ -8699,9 +9145,10 @@
 // intervals (pair of a negative integer (-start-1) followed by a
 // positive (length)) or undefined values.
 // Intervals can span over some keys that are not in the object.
-static MaybeObject* Runtime_GetArrayKeys(Arguments args) {
+static MaybeObject* Runtime_GetArrayKeys(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
-  HandleScope scope;
+  HandleScope scope(isolate);
   CONVERT_ARG_CHECKED(JSObject, array, 0);
   CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
   if (array->elements()->IsDictionary()) {
@@ -8717,19 +9164,19 @@
         keys->set_undefined(i);
       }
     }
-    return *Factory::NewJSArrayWithElements(keys);
+    return *isolate->factory()->NewJSArrayWithElements(keys);
   } else {
     ASSERT(array->HasFastElements());
-    Handle<FixedArray> single_interval = Factory::NewFixedArray(2);
+    Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2);
     // -1 means start of array.
     single_interval->set(0, Smi::FromInt(-1));
     uint32_t actual_length =
         static_cast<uint32_t>(FixedArray::cast(array->elements())->length());
     uint32_t min_length = actual_length < length ? actual_length : length;
     Handle<Object> length_object =
-        Factory::NewNumber(static_cast<double>(min_length));
+        isolate->factory()->NewNumber(static_cast<double>(min_length));
     single_interval->set(1, *length_object);
-    return *Factory::NewJSArrayWithElements(single_interval);
+    return *isolate->factory()->NewJSArrayWithElements(single_interval);
   }
 }
 
@@ -8739,7 +9186,8 @@
 // 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 MaybeObject* Runtime_DefineAccessor(Arguments args) {
+static MaybeObject* Runtime_DefineAccessor(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
   // Compute attributes.
   PropertyAttributes attributes = NONE;
@@ -8759,7 +9207,8 @@
 }
 
 
-static MaybeObject* Runtime_LookupAccessor(Arguments args) {
+static MaybeObject* Runtime_LookupAccessor(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 3);
   CONVERT_CHECKED(JSObject, obj, args[0]);
   CONVERT_CHECKED(String, name, args[1]);
@@ -8769,7 +9218,8 @@
 
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
-static MaybeObject* Runtime_DebugBreak(Arguments args) {
+static MaybeObject* Runtime_DebugBreak(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 0);
   return Execution::DebugBreakHelper();
 }
@@ -8791,27 +9241,31 @@
 // 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 MaybeObject* Runtime_SetDebugEventListener(Arguments args) {
+static MaybeObject* Runtime_SetDebugEventListener(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   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);
+  isolate->debugger()->SetEventListener(callback, data);
 
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_Break(Arguments args) {
+static MaybeObject* Runtime_Break(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 0);
-  StackGuard::DebugBreak();
-  return Heap::undefined_value();
+  isolate->stack_guard()->DebugBreak();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* DebugLookupResultValue(Object* receiver, String* name,
+static MaybeObject* DebugLookupResultValue(Heap* heap,
+                                           Object* receiver,
+                                           String* name,
                                            LookupResult* result,
                                            bool* caught_exception) {
   Object* value;
@@ -8819,7 +9273,7 @@
     case NORMAL:
       value = result->holder()->GetNormalizedProperty(result);
       if (value->IsTheHole()) {
-        return Heap::undefined_value();
+        return heap->undefined_value();
       }
       return value;
     case FIELD:
@@ -8827,7 +9281,7 @@
           JSObject::cast(
               result->holder())->FastPropertyAt(result->GetFieldIndex());
       if (value->IsTheHole()) {
-        return Heap::undefined_value();
+        return heap->undefined_value();
       }
       return value;
     case CONSTANT_FUNCTION:
@@ -8840,8 +9294,8 @@
         if (!maybe_value->ToObject(&value)) {
           if (maybe_value->IsRetryAfterGC()) return maybe_value;
           ASSERT(maybe_value->IsException());
-          maybe_value = Top::pending_exception();
-          Top::clear_pending_exception();
+          maybe_value = heap->isolate()->pending_exception();
+          heap->isolate()->clear_pending_exception();
           if (caught_exception != NULL) {
             *caught_exception = true;
           }
@@ -8849,19 +9303,20 @@
         }
         return value;
       } else {
-        return Heap::undefined_value();
+        return heap->undefined_value();
       }
     }
     case INTERCEPTOR:
     case MAP_TRANSITION:
+    case EXTERNAL_ARRAY_TRANSITION:
     case CONSTANT_TRANSITION:
     case NULL_DESCRIPTOR:
-      return Heap::undefined_value();
+      return heap->undefined_value();
     default:
       UNREACHABLE();
   }
   UNREACHABLE();
-  return Heap::undefined_value();
+  return heap->undefined_value();
 }
 
 
@@ -8877,8 +9332,10 @@
 // 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 MaybeObject* Runtime_DebugGetPropertyDetails(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_DebugGetPropertyDetails(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
 
   ASSERT(args.length() == 2);
 
@@ -8891,9 +9348,9 @@
   // into the embedding application can occour, and the embedding application
   // could have the assumption that its own global context is the current
   // context and not some internal debugger context.
-  SaveContext save;
-  if (Debug::InDebugger()) {
-    Top::set_context(*Debug::debugger_entry()->GetContext());
+  SaveContext save(isolate);
+  if (isolate->debug()->InDebugger()) {
+    isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
   }
 
   // Skip the global proxy as it has no properties and always delegates to the
@@ -8907,17 +9364,17 @@
   // if so.
   uint32_t index;
   if (name->AsArrayIndex(&index)) {
-    Handle<FixedArray> details = Factory::NewFixedArray(2);
+    Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
     Object* element_or_char;
     { MaybeObject* maybe_element_or_char =
-          Runtime::GetElementOrCharAt(obj, index);
+          Runtime::GetElementOrCharAt(isolate, obj, index);
       if (!maybe_element_or_char->ToObject(&element_or_char)) {
         return maybe_element_or_char;
       }
     }
     details->set(0, element_or_char);
     details->set(1, PropertyDetails(NONE, NORMAL).AsSmi());
-    return *Factory::NewJSArrayWithElements(details);
+    return *isolate->factory()->NewJSArrayWithElements(details);
   }
 
   // Find the number of objects making up this.
@@ -8935,7 +9392,8 @@
       PropertyType result_type = result.type();
       Handle<Object> result_callback_obj;
       if (result_type == CALLBACKS) {
-        result_callback_obj = Handle<Object>(result.GetCallbackObject());
+        result_callback_obj = Handle<Object>(result.GetCallbackObject(),
+                                             isolate);
       }
       Smi* property_details = result.GetPropertyDetails().AsSmi();
       // DebugLookupResultValue can cause GC so details from LookupResult needs
@@ -8943,40 +9401,42 @@
       bool caught_exception = false;
       Object* raw_value;
       { MaybeObject* maybe_raw_value =
-            DebugLookupResultValue(*obj, *name, &result, &caught_exception);
+            DebugLookupResultValue(isolate->heap(), *obj, *name,
+                                   &result, &caught_exception);
         if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value;
       }
-      Handle<Object> value(raw_value);
+      Handle<Object> value(raw_value, isolate);
 
       // If the callback object is a fixed array then it contains JavaScript
       // getter and/or setter.
       bool hasJavaScriptAccessors = result_type == CALLBACKS &&
                                     result_callback_obj->IsFixedArray();
       Handle<FixedArray> details =
-          Factory::NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
+          isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
       details->set(0, *value);
       details->set(1, property_details);
       if (hasJavaScriptAccessors) {
         details->set(2,
-                     caught_exception ? Heap::true_value()
-                                      : Heap::false_value());
+                     caught_exception ? isolate->heap()->true_value()
+                                      : isolate->heap()->false_value());
         details->set(3, FixedArray::cast(*result_callback_obj)->get(0));
         details->set(4, FixedArray::cast(*result_callback_obj)->get(1));
       }
 
-      return *Factory::NewJSArrayWithElements(details);
+      return *isolate->factory()->NewJSArrayWithElements(details);
     }
     if (i < length - 1) {
       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
     }
   }
 
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_DebugGetProperty(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_DebugGetProperty(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
 
   ASSERT(args.length() == 2);
 
@@ -8986,15 +9446,17 @@
   LookupResult result;
   obj->Lookup(*name, &result);
   if (result.IsProperty()) {
-    return DebugLookupResultValue(*obj, *name, &result, NULL);
+    return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
   }
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
 // Return the property type calculated from the property details.
 // args[0]: smi with property details.
-static MaybeObject* Runtime_DebugPropertyTypeFromDetails(Arguments args) {
+static MaybeObject* Runtime_DebugPropertyTypeFromDetails(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 1);
   CONVERT_CHECKED(Smi, details, args[0]);
   PropertyType type = PropertyDetails(details).type();
@@ -9004,7 +9466,9 @@
 
 // Return the property attribute calculated from the property details.
 // args[0]: smi with property details.
-static MaybeObject* Runtime_DebugPropertyAttributesFromDetails(Arguments args) {
+static MaybeObject* Runtime_DebugPropertyAttributesFromDetails(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 1);
   CONVERT_CHECKED(Smi, details, args[0]);
   PropertyAttributes attributes = PropertyDetails(details).attributes();
@@ -9014,7 +9478,9 @@
 
 // Return the property insertion index calculated from the property details.
 // args[0]: smi with property details.
-static MaybeObject* Runtime_DebugPropertyIndexFromDetails(Arguments args) {
+static MaybeObject* Runtime_DebugPropertyIndexFromDetails(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 1);
   CONVERT_CHECKED(Smi, details, args[0]);
   int index = PropertyDetails(details).index();
@@ -9025,8 +9491,10 @@
 // Return property value from named interceptor.
 // args[0]: object
 // args[1]: property name
-static MaybeObject* Runtime_DebugNamedInterceptorPropertyValue(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_DebugNamedInterceptorPropertyValue(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 2);
   CONVERT_ARG_CHECKED(JSObject, obj, 0);
   RUNTIME_ASSERT(obj->HasNamedInterceptor());
@@ -9041,8 +9509,9 @@
 // args[0]: object
 // args[1]: index
 static MaybeObject* Runtime_DebugIndexedInterceptorElementValue(
-    Arguments args) {
-  HandleScope scope;
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 2);
   CONVERT_ARG_CHECKED(JSObject, obj, 0);
   RUNTIME_ASSERT(obj->HasIndexedInterceptor());
@@ -9052,31 +9521,35 @@
 }
 
 
-static MaybeObject* Runtime_CheckExecutionState(Arguments args) {
+static MaybeObject* Runtime_CheckExecutionState(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   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());
+  if (isolate->debug()->break_id() == 0 ||
+      break_id != isolate->debug()->break_id()) {
+    return isolate->Throw(
+        isolate->heap()->illegal_execution_state_symbol());
   }
 
-  return Heap::true_value();
+  return isolate->heap()->true_value();
 }
 
 
-static MaybeObject* Runtime_GetFrameCount(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetFrameCount(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
 
   // Check arguments.
   Object* result;
-  { MaybeObject* maybe_result = Runtime_CheckExecutionState(args);
+  { MaybeObject* maybe_result = Runtime_CheckExecutionState(args, isolate);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
 
   // Count all frames which are relevant to debugging stack trace.
   int n = 0;
-  StackFrame::Id id = Debug::break_frame_id();
+  StackFrame::Id id = isolate->debug()->break_frame_id();
   if (id == StackFrame::NO_ID) {
     // If there is no JavaScript stack frame count is 0.
     return Smi::FromInt(0);
@@ -9114,22 +9587,24 @@
 // Arguments name, value
 // Locals name, value
 // Return value if any
-static MaybeObject* Runtime_GetFrameDetails(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetFrameDetails(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 2);
 
   // Check arguments.
   Object* check;
-  { MaybeObject* maybe_check = Runtime_CheckExecutionState(args);
+  { MaybeObject* maybe_check = Runtime_CheckExecutionState(args, isolate);
     if (!maybe_check->ToObject(&check)) return maybe_check;
   }
   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
+  Heap* heap = isolate->heap();
 
   // Find the relevant frame with the requested index.
-  StackFrame::Id id = Debug::break_frame_id();
+  StackFrame::Id id = isolate->debug()->break_frame_id();
   if (id == StackFrame::NO_ID) {
     // If there are no JavaScript stack frames return undefined.
-    return Heap::undefined_value();
+    return heap->undefined_value();
   }
   int count = 0;
   JavaScriptFrameIterator it(id);
@@ -9137,24 +9612,25 @@
     if (count == index) break;
     count++;
   }
-  if (it.done()) return Heap::undefined_value();
+  if (it.done()) return heap->undefined_value();
 
   bool is_optimized_frame =
-      it.frame()->code()->kind() == Code::OPTIMIZED_FUNCTION;
+      it.frame()->LookupCode(isolate)->kind() == Code::OPTIMIZED_FUNCTION;
 
   // Traverse the saved contexts chain to find the active context for the
   // selected frame.
-  SaveContext* save = Top::save_context();
+  SaveContext* save = isolate->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()));
+  Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
 
   // Find source position.
-  int position = it.frame()->code()->SourcePosition(it.frame()->pc());
+  int position =
+      it.frame()->LookupCode(isolate)->SourcePosition(it.frame()->pc());
 
   // Check for constructor frame.
   bool constructor = it.frame()->IsConstructor();
@@ -9172,7 +9648,8 @@
   // 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);
+  Handle<FixedArray> locals =
+      isolate->factory()->NewFixedArray(info.NumberOfLocals() * 2);
 
   // Fill in the names of the locals.
   for (int i = 0; i < info.NumberOfLocals(); i++) {
@@ -9187,7 +9664,7 @@
       //
       // TODO(1140): We should be able to get the correct values
       // for locals in optimized frames.
-      locals->set(i * 2 + 1, Heap::undefined_value());
+      locals->set(i * 2 + 1, isolate->heap()->undefined_value());
     } else if (i < info.number_of_stack_slots()) {
       // Get the value from the stack.
       locals->set(i * 2 + 1, it.frame()->GetExpression(i));
@@ -9208,12 +9685,12 @@
   // frame or if the frame is optimized it cannot be at a return.
   bool at_return = false;
   if (!is_optimized_frame && index == 0) {
-    at_return = Debug::IsBreakAtReturn(it.frame());
+    at_return = isolate->debug()->IsBreakAtReturn(it.frame());
   }
 
   // If positioned just before return find the value to be returned and add it
   // to the frame information.
-  Handle<Object> return_value = Factory::undefined_value();
+  Handle<Object> return_value = isolate->factory()->undefined_value();
   if (at_return) {
     StackFrameIterator it2;
     Address internal_frame_sp = NULL;
@@ -9229,7 +9706,8 @@
             // entering the debug break exit frame.
             if (internal_frame_sp != NULL) {
               return_value =
-                  Handle<Object>(Memory::Object_at(internal_frame_sp));
+                  Handle<Object>(Memory::Object_at(internal_frame_sp),
+                                 isolate);
               break;
             }
           }
@@ -9251,15 +9729,15 @@
   // 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();
+  if (argument_count < it.frame()->ComputeParametersCount()) {
+    argument_count = it.frame()->ComputeParametersCount();
   }
 
   // Calculate the size of the result.
   int details_size = kFrameDetailsFirstDynamicIndex +
                      2 * (argument_count + info.NumberOfLocals()) +
                      (at_return ? 1 : 0);
-  Handle<FixedArray> details = Factory::NewFixedArray(details_size);
+  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
 
   // Add the frame id.
   details->set(kFrameDetailsFrameIdIndex, *frame_id);
@@ -9278,18 +9756,19 @@
   if (position != RelocInfo::kNoPosition) {
     details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
   } else {
-    details->set(kFrameDetailsSourcePositionIndex, Heap::undefined_value());
+    details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
   }
 
   // Add the constructor information.
-  details->set(kFrameDetailsConstructCallIndex, Heap::ToBoolean(constructor));
+  details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
 
   // Add the at return information.
-  details->set(kFrameDetailsAtReturnIndex, Heap::ToBoolean(at_return));
+  details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
 
   // Add information on whether this frame is invoked in the debugger context.
   details->set(kFrameDetailsDebuggerFrameIndex,
-               Heap::ToBoolean(*save->context() == *Debug::debug_context()));
+               heap->ToBoolean(*save->context() ==
+                   *isolate->debug()->debug_context()));
 
   // Fill the dynamic part.
   int details_index = kFrameDetailsFirstDynamicIndex;
@@ -9300,7 +9779,7 @@
     if (i < info.number_of_parameters()) {
       details->set(details_index++, *info.parameter_name(i));
     } else {
-      details->set(details_index++, Heap::undefined_value());
+      details->set(details_index++, heap->undefined_value());
     }
 
     // Parameter value. If we are inspecting an optimized frame, use
@@ -9309,10 +9788,10 @@
     // TODO(3141533): We should be able to get the actual parameter
     // value for optimized frames.
     if (!is_optimized_frame &&
-        (i < it.frame()->GetProvidedParametersCount())) {
+        (i < it.frame()->ComputeParametersCount())) {
       details->set(details_index++, it.frame()->GetParameter(i));
     } else {
-      details->set(details_index++, Heap::undefined_value());
+      details->set(details_index++, heap->undefined_value());
     }
   }
 
@@ -9329,7 +9808,7 @@
   // 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());
+  Handle<Object> receiver(it.frame()->receiver(), isolate);
   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.
@@ -9339,17 +9818,19 @@
     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);
+    receiver =
+        isolate->factory()->ToObject(receiver, calling_frames_global_context);
   }
   details->set(kFrameDetailsReceiverIndex, *receiver);
 
   ASSERT_EQ(details_size, details_index);
-  return *Factory::NewJSArrayWithElements(details);
+  return *isolate->factory()->NewJSArrayWithElements(details);
 }
 
 
 // Copy all the context locals into an object used to materialize a scope.
 static bool CopyContextLocalsToScopeObject(
+    Isolate* isolate,
     Handle<SerializedScopeInfo> serialized_scope_info,
     ScopeInfo<>& scope_info,
     Handle<Context> context,
@@ -9362,11 +9843,13 @@
         *scope_info.context_slot_name(i), NULL);
 
     // Don't include the arguments shadow (.arguments) context variable.
-    if (*scope_info.context_slot_name(i) != Heap::arguments_shadow_symbol()) {
+    if (*scope_info.context_slot_name(i) !=
+        isolate->heap()->arguments_shadow_symbol()) {
       RETURN_IF_EMPTY_HANDLE_VALUE(
+          isolate,
           SetProperty(scope_object,
                       scope_info.context_slot_name(i),
-                      Handle<Object>(context->get(context_index)),
+                      Handle<Object>(context->get(context_index), isolate),
                       NONE,
                       kNonStrictMode),
           false);
@@ -9379,7 +9862,8 @@
 
 // Create a plain JSObject which materializes the local scope for the specified
 // frame.
-static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) {
+static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
+                                              JavaScriptFrame* frame) {
   Handle<JSFunction> function(JSFunction::cast(frame->function()));
   Handle<SharedFunctionInfo> shared(function->shared());
   Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
@@ -9387,14 +9871,16 @@
 
   // Allocate and initialize a JSObject with all the arguments, stack locals
   // heap locals and extension properties of the debugged function.
-  Handle<JSObject> local_scope = Factory::NewJSObject(Top::object_function());
+  Handle<JSObject> local_scope =
+      isolate->factory()->NewJSObject(isolate->object_function());
 
   // First fill all parameters.
   for (int i = 0; i < scope_info.number_of_parameters(); ++i) {
     RETURN_IF_EMPTY_HANDLE_VALUE(
+        isolate,
         SetProperty(local_scope,
                     scope_info.parameter_name(i),
-                    Handle<Object>(frame->GetParameter(i)),
+                    Handle<Object>(frame->GetParameter(i), isolate),
                     NONE,
                     kNonStrictMode),
         Handle<JSObject>());
@@ -9403,9 +9889,10 @@
   // Second fill all stack locals.
   for (int i = 0; i < scope_info.number_of_stack_slots(); i++) {
     RETURN_IF_EMPTY_HANDLE_VALUE(
+        isolate,
         SetProperty(local_scope,
                     scope_info.stack_slot_name(i),
-                    Handle<Object>(frame->GetExpression(i)),
+                    Handle<Object>(frame->GetExpression(i), isolate),
                     NONE,
                     kNonStrictMode),
         Handle<JSObject>());
@@ -9414,7 +9901,8 @@
   // Third fill all context locals.
   Handle<Context> frame_context(Context::cast(frame->context()));
   Handle<Context> function_context(frame_context->fcontext());
-  if (!CopyContextLocalsToScopeObject(serialized_scope_info, scope_info,
+  if (!CopyContextLocalsToScopeObject(isolate,
+                                      serialized_scope_info, scope_info,
                                       function_context, local_scope)) {
     return Handle<JSObject>();
   }
@@ -9431,6 +9919,7 @@
         ASSERT(keys->get(i)->IsString());
         Handle<String> key(String::cast(keys->get(i)));
         RETURN_IF_EMPTY_HANDLE_VALUE(
+            isolate,
             SetProperty(local_scope,
                         key,
                         GetProperty(ext, key),
@@ -9446,7 +9935,8 @@
 
 // Create a plain JSObject which materializes the closure content for the
 // context.
-static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
+static Handle<JSObject> MaterializeClosure(Isolate* isolate,
+                                           Handle<Context> context) {
   ASSERT(context->is_function_context());
 
   Handle<SharedFunctionInfo> shared(context->closure()->shared());
@@ -9455,12 +9945,13 @@
 
   // Allocate and initialize a JSObject with all the content of theis function
   // closure.
-  Handle<JSObject> closure_scope = Factory::NewJSObject(Top::object_function());
+  Handle<JSObject> closure_scope =
+      isolate->factory()->NewJSObject(isolate->object_function());
 
   // Check whether the arguments shadow object exists.
   int arguments_shadow_index =
-      shared->scope_info()->ContextSlotIndex(Heap::arguments_shadow_symbol(),
-                                             NULL);
+      shared->scope_info()->ContextSlotIndex(
+          isolate->heap()->arguments_shadow_symbol(), NULL);
   if (arguments_shadow_index >= 0) {
     // In this case all the arguments are available in the arguments shadow
     // object.
@@ -9470,9 +9961,10 @@
       // We don't expect exception-throwing getters on the arguments shadow.
       Object* element = arguments_shadow->GetElement(i)->ToObjectUnchecked();
       RETURN_IF_EMPTY_HANDLE_VALUE(
+          isolate,
           SetProperty(closure_scope,
                       scope_info.parameter_name(i),
-                      Handle<Object>(element),
+                      Handle<Object>(element, isolate),
                       NONE,
                       kNonStrictMode),
           Handle<JSObject>());
@@ -9480,7 +9972,8 @@
   }
 
   // Fill all context locals to the context extension.
-  if (!CopyContextLocalsToScopeObject(serialized_scope_info, scope_info,
+  if (!CopyContextLocalsToScopeObject(isolate,
+                                      serialized_scope_info, scope_info,
                                       context, closure_scope)) {
     return Handle<JSObject>();
   }
@@ -9494,7 +9987,8 @@
       // Names of variables introduced by eval are strings.
       ASSERT(keys->get(i)->IsString());
       Handle<String> key(String::cast(keys->get(i)));
-      RETURN_IF_EMPTY_HANDLE_VALUE(
+       RETURN_IF_EMPTY_HANDLE_VALUE(
+          isolate,
           SetProperty(closure_scope,
                       key,
                       GetProperty(ext, key),
@@ -9525,8 +10019,9 @@
     ScopeTypeCatch
   };
 
-  explicit ScopeIterator(JavaScriptFrame* frame)
-    : frame_(frame),
+  ScopeIterator(Isolate* isolate, JavaScriptFrame* frame)
+    : isolate_(isolate),
+      frame_(frame),
       function_(JSFunction::cast(frame->function())),
       context_(Context::cast(frame->context())),
       local_done_(false),
@@ -9539,7 +10034,7 @@
       // Checking for the existence of .result seems fragile, but the scope info
       // saved with the code object does not otherwise have that information.
       int index = function_->shared()->scope_info()->
-          StackSlotIndex(Heap::result_symbol());
+          StackSlotIndex(isolate_->heap()->result_symbol());
       at_local_ = index < 0;
     } else if (context_->is_function_context()) {
       at_local_ = true;
@@ -9617,7 +10112,7 @@
         break;
       case ScopeIterator::ScopeTypeLocal:
         // Materialize the content of the local scope into a JSObject.
-        return MaterializeLocalScope(frame_);
+        return MaterializeLocalScope(isolate_, frame_);
         break;
       case ScopeIterator::ScopeTypeWith:
       case ScopeIterator::ScopeTypeCatch:
@@ -9626,7 +10121,7 @@
         break;
       case ScopeIterator::ScopeTypeClosure:
         // Materialize the content of the closure scope into a JSObject.
-        return MaterializeClosure(CurrentContext());
+        return MaterializeClosure(isolate_, CurrentContext());
         break;
     }
     UNREACHABLE();
@@ -9705,6 +10200,7 @@
 #endif
 
  private:
+  Isolate* isolate_;
   JavaScriptFrame* frame_;
   Handle<JSFunction> function_;
   Handle<Context> context_;
@@ -9715,13 +10211,14 @@
 };
 
 
-static MaybeObject* Runtime_GetScopeCount(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetScopeCount(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 2);
 
   // Check arguments.
   Object* check;
-  { MaybeObject* maybe_check = Runtime_CheckExecutionState(args);
+  { MaybeObject* maybe_check = Runtime_CheckExecutionState(args, isolate);
     if (!maybe_check->ToObject(&check)) return maybe_check;
   }
   CONVERT_CHECKED(Smi, wrapped_id, args[1]);
@@ -9733,7 +10230,7 @@
 
   // Count the visible scopes.
   int n = 0;
-  for (ScopeIterator it(frame); !it.Done(); it.Next()) {
+  for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
     n++;
   }
 
@@ -9753,13 +10250,14 @@
 // The array returned contains the following information:
 // 0: Scope type
 // 1: Scope object
-static MaybeObject* Runtime_GetScopeDetails(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetScopeDetails(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 3);
 
   // Check arguments.
   Object* check;
-  { MaybeObject* maybe_check = Runtime_CheckExecutionState(args);
+  { MaybeObject* maybe_check = Runtime_CheckExecutionState(args, isolate);
     if (!maybe_check->ToObject(&check)) return maybe_check;
   }
   CONVERT_CHECKED(Smi, wrapped_id, args[1]);
@@ -9772,57 +10270,60 @@
 
   // Find the requested scope.
   int n = 0;
-  ScopeIterator it(frame);
+  ScopeIterator it(isolate, frame);
   for (; !it.Done() && n < index; it.Next()) {
     n++;
   }
   if (it.Done()) {
-    return Heap::undefined_value();
+    return isolate->heap()->undefined_value();
   }
 
   // Calculate the size of the result.
   int details_size = kScopeDetailsSize;
-  Handle<FixedArray> details = Factory::NewFixedArray(details_size);
+  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
 
   // Fill in scope details.
   details->set(kScopeDetailsTypeIndex, Smi::FromInt(it.Type()));
   Handle<JSObject> scope_object = it.ScopeObject();
-  RETURN_IF_EMPTY_HANDLE(scope_object);
+  RETURN_IF_EMPTY_HANDLE(isolate, scope_object);
   details->set(kScopeDetailsObjectIndex, *scope_object);
 
-  return *Factory::NewJSArrayWithElements(details);
+  return *isolate->factory()->NewJSArrayWithElements(details);
 }
 
 
-static MaybeObject* Runtime_DebugPrintScopes(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_DebugPrintScopes(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 0);
 
 #ifdef DEBUG
   // Print the scopes for the top frame.
   StackFrameLocator locator;
   JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
-  for (ScopeIterator it(frame); !it.Done(); it.Next()) {
+  for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
     it.DebugPrint();
   }
 #endif
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_GetThreadCount(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetThreadCount(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
 
   // Check arguments.
   Object* result;
-  { MaybeObject* maybe_result = Runtime_CheckExecutionState(args);
+  { MaybeObject* maybe_result = Runtime_CheckExecutionState(args, isolate);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
 
   // Count all archived V8 threads.
   int n = 0;
-  for (ThreadState* thread = ThreadState::FirstInUse();
+  for (ThreadState* thread =
+          isolate->thread_manager()->FirstThreadStateInUse();
        thread != NULL;
        thread = thread->Next()) {
     n++;
@@ -9844,70 +10345,78 @@
 // The array returned contains the following information:
 // 0: Is current thread?
 // 1: Thread id
-static MaybeObject* Runtime_GetThreadDetails(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetThreadDetails(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 2);
 
   // Check arguments.
   Object* check;
-  { MaybeObject* maybe_check = Runtime_CheckExecutionState(args);
+  { MaybeObject* maybe_check = Runtime_CheckExecutionState(args, isolate);
     if (!maybe_check->ToObject(&check)) return maybe_check;
   }
   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
 
   // Allocate array for result.
-  Handle<FixedArray> details = Factory::NewFixedArray(kThreadDetailsSize);
+  Handle<FixedArray> details =
+      isolate->factory()->NewFixedArray(kThreadDetailsSize);
 
   // Thread index 0 is current thread.
   if (index == 0) {
     // Fill the details.
-    details->set(kThreadDetailsCurrentThreadIndex, Heap::true_value());
+    details->set(kThreadDetailsCurrentThreadIndex,
+                 isolate->heap()->true_value());
     details->set(kThreadDetailsThreadIdIndex,
-                 Smi::FromInt(ThreadManager::CurrentId()));
+                 Smi::FromInt(
+                     isolate->thread_manager()->CurrentId()));
   } else {
     // Find the thread with the requested index.
     int n = 1;
-    ThreadState* thread = ThreadState::FirstInUse();
+    ThreadState* thread =
+        isolate->thread_manager()->FirstThreadStateInUse();
     while (index != n && thread != NULL) {
       thread = thread->Next();
       n++;
     }
     if (thread == NULL) {
-      return Heap::undefined_value();
+      return isolate->heap()->undefined_value();
     }
 
     // Fill the details.
-    details->set(kThreadDetailsCurrentThreadIndex, Heap::false_value());
+    details->set(kThreadDetailsCurrentThreadIndex,
+                 isolate->heap()->false_value());
     details->set(kThreadDetailsThreadIdIndex, Smi::FromInt(thread->id()));
   }
 
   // Convert to JS array and return.
-  return *Factory::NewJSArrayWithElements(details);
+  return *isolate->factory()->NewJSArrayWithElements(details);
 }
 
 
 // Sets the disable break state
 // args[0]: disable break state
-static MaybeObject* Runtime_SetDisableBreak(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_SetDisableBreak(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   CONVERT_BOOLEAN_CHECKED(disable_break, args[0]);
-  Debug::set_disable_break(disable_break);
-  return  Heap::undefined_value();
+  isolate->debug()->set_disable_break(disable_break);
+  return  isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_GetBreakLocations(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetBreakLocations(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
 
   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
   Handle<SharedFunctionInfo> shared(fun->shared());
   // Find the number of break points
   Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
-  if (break_locations->IsUndefined()) return Heap::undefined_value();
+  if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
   // Return array as JS array
-  return *Factory::NewJSArrayWithElements(
+  return *isolate->factory()->NewJSArrayWithElements(
       Handle<FixedArray>::cast(break_locations));
 }
 
@@ -9916,8 +10425,9 @@
 // args[0]: function
 // args[1]: number: break source position (within the function source)
 // args[2]: number: break point object
-static MaybeObject* Runtime_SetFunctionBreakPoint(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_SetFunctionBreakPoint(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 3);
   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
   Handle<SharedFunctionInfo> shared(fun->shared());
@@ -9926,13 +10436,15 @@
   Handle<Object> break_point_object_arg = args.at<Object>(2);
 
   // Set break point.
-  Debug::SetBreakPoint(shared, break_point_object_arg, &source_position);
+  isolate->debug()->SetBreakPoint(shared, break_point_object_arg,
+                                  &source_position);
 
   return Smi::FromInt(source_position);
 }
 
 
-Object* Runtime::FindSharedFunctionInfoInScript(Handle<Script> script,
+Object* Runtime::FindSharedFunctionInfoInScript(Isolate* isolate,
+                                                Handle<Script> script,
                                                 int position) {
   // Iterate the heap looking for SharedFunctionInfo generated from the
   // script. The inner most SharedFunctionInfo containing the source position
@@ -9991,7 +10503,7 @@
     }
 
     if (target.is_null()) {
-      return Heap::undefined_value();
+      return isolate->heap()->undefined_value();
     }
 
     // If the candidate found is compiled we are done. NOTE: when lazy
@@ -10015,8 +10527,9 @@
 // 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 MaybeObject* Runtime_SetScriptBreakPoint(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_SetScriptBreakPoint(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 3);
   CONVERT_ARG_CHECKED(JSValue, wrapper, 0);
   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
@@ -10028,7 +10541,7 @@
   Handle<Script> script(Script::cast(wrapper->value()));
 
   Object* result = Runtime::FindSharedFunctionInfoInScript(
-      script, source_position);
+      isolate, script, source_position);
   if (!result->IsUndefined()) {
     Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
     // Find position within function. The script position might be before the
@@ -10039,33 +10552,35 @@
     } else {
       position = source_position - shared->start_position();
     }
-    Debug::SetBreakPoint(shared, break_point_object_arg, &position);
+    isolate->debug()->SetBreakPoint(shared, break_point_object_arg, &position);
     position += shared->start_position();
     return Smi::FromInt(position);
   }
-  return  Heap::undefined_value();
+  return  isolate->heap()->undefined_value();
 }
 
 
 // Clear a break point
 // args[0]: number: break point object
-static MaybeObject* Runtime_ClearBreakPoint(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_ClearBreakPoint(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   Handle<Object> break_point_object_arg = args.at<Object>(0);
 
   // Clear break point.
-  Debug::ClearBreakPoint(break_point_object_arg);
+  isolate->debug()->ClearBreakPoint(break_point_object_arg);
 
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
 // Change the state of break on exceptions.
 // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
 // args[1]: Boolean indicating on/off.
-static MaybeObject* Runtime_ChangeBreakOnException(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_ChangeBreakOnException(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 2);
   RUNTIME_ASSERT(args[0]->IsNumber());
   CONVERT_BOOLEAN_CHECKED(enable, args[1]);
@@ -10075,21 +10590,22 @@
   ExceptionBreakType type =
       static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
   // Update break point state.
-  Debug::ChangeBreakOnException(type, enable);
-  return Heap::undefined_value();
+  isolate->debug()->ChangeBreakOnException(type, enable);
+  return isolate->heap()->undefined_value();
 }
 
 
 // Returns the state of break on exceptions
 // args[0]: boolean indicating uncaught exceptions
-static MaybeObject* Runtime_IsBreakOnException(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_IsBreakOnException(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   RUNTIME_ASSERT(args[0]->IsNumber());
 
   ExceptionBreakType type =
       static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
-  bool result = Debug::IsBreakOnException(type);
+  bool result = isolate->debug()->IsBreakOnException(type);
   return Smi::FromInt(result);
 }
 
@@ -10099,16 +10615,17 @@
 // args[1]: step action from the enumeration StepAction
 // args[2]: number of times to perform the step, for step out it is the number
 //          of frames to step down.
-static MaybeObject* Runtime_PrepareStep(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_PrepareStep(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 3);
   // Check arguments.
   Object* check;
-  { MaybeObject* maybe_check = Runtime_CheckExecutionState(args);
+  { MaybeObject* maybe_check = Runtime_CheckExecutionState(args, isolate);
     if (!maybe_check->ToObject(&check)) return maybe_check;
   }
   if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
-    return Top::Throw(Heap::illegal_argument_symbol());
+    return isolate->Throw(isolate->heap()->illegal_argument_symbol());
   }
 
   // Get the step action and check validity.
@@ -10118,30 +10635,32 @@
       step_action != StepOut &&
       step_action != StepInMin &&
       step_action != StepMin) {
-    return Top::Throw(Heap::illegal_argument_symbol());
+    return isolate->Throw(isolate->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());
+    return isolate->Throw(isolate->heap()->illegal_argument_symbol());
   }
 
   // Clear all current stepping setup.
-  Debug::ClearStepping();
+  isolate->debug()->ClearStepping();
 
   // Prepare step.
-  Debug::PrepareStep(static_cast<StepAction>(step_action), step_count);
-  return Heap::undefined_value();
+  isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
+                                step_count);
+  return isolate->heap()->undefined_value();
 }
 
 
 // Clear all stepping set by PrepareStep.
-static MaybeObject* Runtime_ClearStepping(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_ClearStepping(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 0);
-  Debug::ClearStepping();
-  return Heap::undefined_value();
+  isolate->debug()->ClearStepping();
+  return isolate->heap()->undefined_value();
 }
 
 
@@ -10158,15 +10677,15 @@
   Handle<Context> previous(context_chain->previous());
   Handle<JSObject> extension(JSObject::cast(context_chain->extension()));
   Handle<Context> context = CopyWithContextChain(function_context, previous);
-  return Factory::NewWithContext(context,
-                                 extension,
-                                 context_chain->IsCatchContext());
+  return context->GetIsolate()->factory()->NewWithContext(
+      context, extension, context_chain->IsCatchContext());
 }
 
 
 // Helper function to find or create the arguments object for
 // Runtime_DebugEvaluate.
-static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
+static Handle<Object> GetArgumentsObject(Isolate* isolate,
+                                         JavaScriptFrame* frame,
                                          Handle<JSFunction> function,
                                          Handle<SerializedScopeInfo> scope_info,
                                          const ScopeInfo<>* sinfo,
@@ -10176,22 +10695,24 @@
   // does not support eval) then create an 'arguments' object.
   int index;
   if (sinfo->number_of_stack_slots() > 0) {
-    index = scope_info->StackSlotIndex(Heap::arguments_symbol());
+    index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol());
     if (index != -1) {
-      return Handle<Object>(frame->GetExpression(index));
+      return Handle<Object>(frame->GetExpression(index), isolate);
     }
   }
 
   if (sinfo->number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
-    index = scope_info->ContextSlotIndex(Heap::arguments_symbol(), NULL);
+    index = scope_info->ContextSlotIndex(isolate->heap()->arguments_symbol(),
+                                         NULL);
     if (index != -1) {
-      return Handle<Object>(function_context->get(index));
+      return Handle<Object>(function_context->get(index), isolate);
     }
   }
 
-  const int length = frame->GetProvidedParametersCount();
-  Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length);
-  Handle<FixedArray> array = Factory::NewFixedArray(length);
+  const int length = frame->ComputeParametersCount();
+  Handle<JSObject> arguments =
+      isolate->factory()->NewArgumentsObject(function, length);
+  Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
 
   AssertNoAllocation no_gc;
   WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
@@ -10203,6 +10724,10 @@
 }
 
 
+static const char kSourceStr[] =
+    "(function(arguments,__source__){return eval(__source__);})";
+
+
 // 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
@@ -10214,14 +10739,16 @@
 // 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 MaybeObject* Runtime_DebugEvaluate(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_DebugEvaluate(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
 
   // Check the execution state and decode arguments frame and source to be
   // evaluated.
   ASSERT(args.length() == 5);
   Object* check_result;
-  { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(args);
+  { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(args,
+                                                                  isolate);
     if (!maybe_check_result->ToObject(&check_result)) {
       return maybe_check_result;
     }
@@ -10244,13 +10771,13 @@
 
   // Traverse the saved contexts chain to find the active context for the
   // selected frame.
-  SaveContext* save = Top::save_context();
+  SaveContext* save = isolate->save_context();
   while (save != NULL && !save->below(frame)) {
     save = save->prev();
   }
   ASSERT(save != NULL);
-  SaveContext savex;
-  Top::set_context(*(save->context()));
+  SaveContext savex(isolate);
+  isolate->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
@@ -10259,7 +10786,8 @@
   // 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());
+      isolate->factory()->NewFunction(isolate->factory()->empty_string(),
+                                      isolate->factory()->undefined_value());
   go_between->set_context(function->context());
 #ifdef DEBUG
   ScopeInfo<> go_between_sinfo(go_between->shared()->scope_info());
@@ -10268,13 +10796,14 @@
 #endif
 
   // Materialize the content of the local scope into a JSObject.
-  Handle<JSObject> local_scope = MaterializeLocalScope(frame);
-  RETURN_IF_EMPTY_HANDLE(local_scope);
+  Handle<JSObject> local_scope = MaterializeLocalScope(isolate, frame);
+  RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
 
   // 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);
+      isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS,
+                                             go_between);
   context->set_extension(*local_scope);
   // Copy any with contexts present and chain them in front of this context.
   Handle<Context> frame_context(Context::cast(frame->context()));
@@ -10282,7 +10811,7 @@
   context = CopyWithContextChain(frame_context, context);
 
   if (additional_context->IsJSObject()) {
-    context = Factory::NewWithContext(context,
+    context = isolate->factory()->NewWithContext(context,
         Handle<JSObject>::cast(additional_context), false);
   }
 
@@ -10291,12 +10820,10 @@
   // '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 = StrLength(source_str);
+
   Handle<String> function_source =
-      Factory::NewStringFromAscii(Vector<const char>(source_str,
-                                                     source_str_length));
+      isolate->factory()->NewStringFromAscii(
+          Vector<const char>(kSourceStr, sizeof(kSourceStr) - 1));
 
   // Currently, the eval code will be executed in non-strict mode,
   // even in the strict code context.
@@ -10307,17 +10834,18 @@
                             kNonStrictMode);
   if (shared.is_null()) return Failure::Exception();
   Handle<JSFunction> compiled_function =
-      Factory::NewFunctionFromSharedFunctionInfo(shared, context);
+      isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
 
   // Invoke the result of the compilation to get the evaluation function.
   bool has_pending_exception;
-  Handle<Object> receiver(frame->receiver());
+  Handle<Object> receiver(frame->receiver(), isolate);
   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, scope_info,
+  Handle<Object> arguments = GetArgumentsObject(isolate, frame,
+                                                function, scope_info,
                                                 &sinfo, function_context);
 
   // Invoke the evaluation function and return the result.
@@ -10339,14 +10867,16 @@
 }
 
 
-static MaybeObject* Runtime_DebugEvaluateGlobal(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_DebugEvaluateGlobal(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
 
   // Check the execution state and decode arguments frame and source to be
   // evaluated.
   ASSERT(args.length() == 4);
   Object* check_result;
-  { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(args);
+  { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(args,
+                                                                  isolate);
     if (!maybe_check_result->ToObject(&check_result)) {
       return maybe_check_result;
     }
@@ -10359,28 +10889,30 @@
   DisableBreak disable_break_save(disable_break);
 
   // Enter the top context from before the debugger was invoked.
-  SaveContext save;
+  SaveContext save(isolate);
   SaveContext* top = &save;
-  while (top != NULL && *top->context() == *Debug::debug_context()) {
+  while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
     top = top->prev();
   }
   if (top != NULL) {
-    Top::set_context(*top->context());
+    isolate->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();
+  Handle<Context> context = isolate->global_context();
 
   bool is_global = true;
 
   if (additional_context->IsJSObject()) {
     // Create a function context first, than put 'with' context on top of it.
-    Handle<JSFunction> go_between = Factory::NewFunction(
-        Factory::empty_string(), Factory::undefined_value());
+    Handle<JSFunction> go_between = isolate->factory()->NewFunction(
+        isolate->factory()->empty_string(),
+        isolate->factory()->undefined_value());
     go_between->set_context(*context);
     context =
-        Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, go_between);
+        isolate->factory()->NewFunctionContext(
+            Context::MIN_CONTEXT_SLOTS, go_between);
     context->set_extension(JSObject::cast(*additional_context));
     is_global = false;
   }
@@ -10392,12 +10924,13 @@
       Compiler::CompileEval(source, context, is_global, kNonStrictMode);
   if (shared.is_null()) return Failure::Exception();
   Handle<JSFunction> compiled_function =
-      Handle<JSFunction>(Factory::NewFunctionFromSharedFunctionInfo(shared,
-                                                                    context));
+      Handle<JSFunction>(
+          isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
+                                                                context));
 
   // Invoke the result of the compilation to get the evaluation function.
   bool has_pending_exception;
-  Handle<Object> receiver = Top::global();
+  Handle<Object> receiver = isolate->global();
   Handle<Object> result =
     Execution::Call(compiled_function, receiver, 0, NULL,
                     &has_pending_exception);
@@ -10406,12 +10939,13 @@
 }
 
 
-static MaybeObject* Runtime_DebugGetLoadedScripts(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_DebugGetLoadedScripts(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 0);
 
   // Fill the script objects.
-  Handle<FixedArray> instances = Debug::GetLoadedScripts();
+  Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
 
   // Convert the script objects to proper JS objects.
   for (int i = 0; i < instances->length(); i++) {
@@ -10426,7 +10960,8 @@
   }
 
   // Return result as a JS array.
-  Handle<JSObject> result = Factory::NewJSObject(Top::array_function());
+  Handle<JSObject> result =
+      isolate->factory()->NewJSObject(isolate->array_function());
   Handle<JSArray>::cast(result)->SetContent(*instances);
   return *result;
 }
@@ -10506,11 +11041,12 @@
 // 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 MaybeObject* Runtime_DebugReferencedBy(Arguments args) {
+static MaybeObject* Runtime_DebugReferencedBy(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 3);
 
   // First perform a full GC in order to avoid references from dead objects.
-  Heap::CollectAllGarbage(false);
+  isolate->heap()->CollectAllGarbage(false);
 
   // Check parameters.
   CONVERT_CHECKED(JSObject, target, args[0]);
@@ -10522,7 +11058,7 @@
 
   // Get the constructor function for context extension and arguments array.
   JSObject* arguments_boilerplate =
-      Top::context()->global_context()->arguments_boilerplate();
+      isolate->context()->global_context()->arguments_boilerplate();
   JSFunction* arguments_function =
       JSFunction::cast(arguments_boilerplate->map()->constructor());
 
@@ -10533,7 +11069,7 @@
 
   // Allocate an array to hold the result.
   Object* object;
-  { MaybeObject* maybe_object = Heap::AllocateFixedArray(count);
+  { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count);
     if (!maybe_object->ToObject(&object)) return maybe_object;
   }
   FixedArray* instances = FixedArray::cast(object);
@@ -10544,8 +11080,8 @@
 
   // Return result as JS array.
   Object* result;
-  { MaybeObject* maybe_result = Heap::AllocateJSObject(
-        Top::context()->global_context()->array_function());
+  { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
+      isolate->context()->global_context()->array_function());
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   JSArray::cast(result)->SetContent(instances);
@@ -10586,11 +11122,12 @@
 // 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 MaybeObject* Runtime_DebugConstructedBy(Arguments args) {
+static MaybeObject* Runtime_DebugConstructedBy(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
 
   // First perform a full GC in order to avoid dead objects.
-  Heap::CollectAllGarbage(false);
+  isolate->heap()->CollectAllGarbage(false);
 
   // Check parameters.
   CONVERT_CHECKED(JSFunction, constructor, args[0]);
@@ -10603,7 +11140,7 @@
 
   // Allocate an array to hold the result.
   Object* object;
-  { MaybeObject* maybe_object = Heap::AllocateFixedArray(count);
+  { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count);
     if (!maybe_object->ToObject(&object)) return maybe_object;
   }
   FixedArray* instances = FixedArray::cast(object);
@@ -10613,8 +11150,8 @@
 
   // Return result as JS array.
   Object* result;
-  { MaybeObject* maybe_result = Heap::AllocateJSObject(
-        Top::context()->global_context()->array_function());
+  { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
+          isolate->context()->global_context()->array_function());
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   JSArray::cast(result)->SetContent(instances);
@@ -10624,7 +11161,8 @@
 
 // Find the effective prototype object as returned by __proto__.
 // args[0]: the object to find the prototype for.
-static MaybeObject* Runtime_DebugGetPrototype(Arguments args) {
+static MaybeObject* Runtime_DebugGetPrototype(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 1);
 
   CONVERT_CHECKED(JSObject, obj, args[0]);
@@ -10634,16 +11172,19 @@
 }
 
 
-static MaybeObject* Runtime_SystemBreak(Arguments args) {
+static MaybeObject* Runtime_SystemBreak(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 0);
   CPU::DebugBreak();
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_DebugDisassembleFunction(Arguments args) {
+static MaybeObject* Runtime_DebugDisassembleFunction(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
 #ifdef DEBUG
-  HandleScope scope;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   // Get the function and make sure it is compiled.
   CONVERT_ARG_CHECKED(JSFunction, func, 0);
@@ -10653,13 +11194,15 @@
   }
   func->code()->PrintLn();
 #endif  // DEBUG
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_DebugDisassembleConstructor(Arguments args) {
+static MaybeObject* Runtime_DebugDisassembleConstructor(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
 #ifdef DEBUG
-  HandleScope scope;
+  HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   // Get the function and make sure it is compiled.
   CONVERT_ARG_CHECKED(JSFunction, func, 0);
@@ -10669,11 +11212,13 @@
   }
   shared->construct_stub()->PrintLn();
 #endif  // DEBUG
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_FunctionGetInferredName(Arguments args) {
+static MaybeObject* Runtime_FunctionGetInferredName(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
 
@@ -10683,7 +11228,7 @@
 
 
 static int FindSharedFunctionInfosForScript(Script* script,
-                                     FixedArray* buffer) {
+                                            FixedArray* buffer) {
   AssertNoAllocation no_allocations;
 
   int counter = 0;
@@ -10710,9 +11255,10 @@
 // to this script. Returns JSArray of SharedFunctionInfo wrapped
 // in OpaqueReferences.
 static MaybeObject* Runtime_LiveEditFindSharedFunctionInfosForScript(
-    Arguments args) {
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 1);
-  HandleScope scope;
+  HandleScope scope(isolate);
   CONVERT_CHECKED(JSValue, script_value, args[0]);
 
   Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
@@ -10720,14 +11266,14 @@
   const int kBufferSize = 32;
 
   Handle<FixedArray> array;
-  array = Factory::NewFixedArray(kBufferSize);
+  array = isolate->factory()->NewFixedArray(kBufferSize);
   int number = FindSharedFunctionInfosForScript(*script, *array);
   if (number > kBufferSize) {
-    array = Factory::NewFixedArray(number);
+    array = isolate->factory()->NewFixedArray(number);
     FindSharedFunctionInfosForScript(*script, *array);
   }
 
-  Handle<JSArray> result = Factory::NewJSArrayWithElements(array);
+  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
   result->set_length(Smi::FromInt(number));
 
   LiveEdit::WrapSharedFunctionInfos(result);
@@ -10742,16 +11288,18 @@
 // Returns a JSArray of compilation infos. The array is ordered so that
 // each function with all its descendant is always stored in a continues range
 // with the function itself going first. The root function is a script function.
-static MaybeObject* Runtime_LiveEditGatherCompileInfo(Arguments args) {
+static MaybeObject* Runtime_LiveEditGatherCompileInfo(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
-  HandleScope scope;
+  HandleScope scope(isolate);
   CONVERT_CHECKED(JSValue, script, args[0]);
   CONVERT_ARG_CHECKED(String, source, 1);
   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
 
   JSArray* result =  LiveEdit::GatherCompileInfo(script_handle, source);
 
-  if (Top::has_pending_exception()) {
+  if (isolate->has_pending_exception()) {
     return Failure::Exception();
   }
 
@@ -10761,12 +11309,13 @@
 // Changes the source of the script to a new_source.
 // If old_script_name is provided (i.e. is a String), also creates a copy of
 // the script with its original source and sends notification to debugger.
-static MaybeObject* Runtime_LiveEditReplaceScript(Arguments args) {
+static MaybeObject* Runtime_LiveEditReplaceScript(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 3);
-  HandleScope scope;
+  HandleScope scope(isolate);
   CONVERT_CHECKED(JSValue, original_script_value, args[0]);
   CONVERT_ARG_CHECKED(String, new_source, 1);
-  Handle<Object> old_script_name(args[2]);
+  Handle<Object> old_script_name(args[2], isolate);
 
   CONVERT_CHECKED(Script, original_script_pointer,
                   original_script_value->value());
@@ -10780,23 +11329,27 @@
     Handle<Script> script_handle(Script::cast(old_script));
     return *(GetScriptWrapper(script_handle));
   } else {
-    return Heap::null_value();
+    return isolate->heap()->null_value();
   }
 }
 
 
-static MaybeObject* Runtime_LiveEditFunctionSourceUpdated(Arguments args) {
+static MaybeObject* Runtime_LiveEditFunctionSourceUpdated(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 1);
-  HandleScope scope;
+  HandleScope scope(isolate);
   CONVERT_ARG_CHECKED(JSArray, shared_info, 0);
   return LiveEdit::FunctionSourceUpdated(shared_info);
 }
 
 
 // Replaces code of SharedFunctionInfo with a new one.
-static MaybeObject* Runtime_LiveEditReplaceFunctionCode(Arguments args) {
+static MaybeObject* Runtime_LiveEditReplaceFunctionCode(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
-  HandleScope scope;
+  HandleScope scope(isolate);
   CONVERT_ARG_CHECKED(JSArray, new_compile_info, 0);
   CONVERT_ARG_CHECKED(JSArray, shared_info, 1);
 
@@ -10804,17 +11357,19 @@
 }
 
 // Connects SharedFunctionInfo to another script.
-static MaybeObject* Runtime_LiveEditFunctionSetScript(Arguments args) {
+static MaybeObject* Runtime_LiveEditFunctionSetScript(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
-  HandleScope scope;
-  Handle<Object> function_object(args[0]);
-  Handle<Object> script_object(args[1]);
+  HandleScope scope(isolate);
+  Handle<Object> function_object(args[0], isolate);
+  Handle<Object> script_object(args[1], isolate);
 
   if (function_object->IsJSValue()) {
     Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
     if (script_object->IsJSValue()) {
       CONVERT_CHECKED(Script, script, JSValue::cast(*script_object)->value());
-      script_object = Handle<Object>(script);
+      script_object = Handle<Object>(script, isolate);
     }
 
     LiveEdit::SetFunctionScript(function_wrapper, script_object);
@@ -10823,15 +11378,17 @@
     // and we check it in this function.
   }
 
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
 // In a code of a parent function replaces original function as embedded object
 // with a substitution one.
-static MaybeObject* Runtime_LiveEditReplaceRefToNestedFunction(Arguments args) {
+static MaybeObject* Runtime_LiveEditReplaceRefToNestedFunction(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 3);
-  HandleScope scope;
+  HandleScope scope(isolate);
 
   CONVERT_ARG_CHECKED(JSValue, parent_wrapper, 0);
   CONVERT_ARG_CHECKED(JSValue, orig_wrapper, 1);
@@ -10840,7 +11397,7 @@
   LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
                                        subst_wrapper);
 
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
@@ -10849,9 +11406,11 @@
 // array of groups of 3 numbers:
 // (change_begin, change_end, change_end_new_position).
 // Each group describes a change in text; groups are sorted by change_begin.
-static MaybeObject* Runtime_LiveEditPatchFunctionPositions(Arguments args) {
+static MaybeObject* Runtime_LiveEditPatchFunctionPositions(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
-  HandleScope scope;
+  HandleScope scope(isolate);
   CONVERT_ARG_CHECKED(JSArray, shared_array, 0);
   CONVERT_ARG_CHECKED(JSArray, position_change_array, 1);
 
@@ -10863,9 +11422,11 @@
 // checks that none of them have activations on stacks (of any thread).
 // Returns array of the same length with corresponding results of
 // LiveEdit::FunctionPatchabilityStatus type.
-static MaybeObject* Runtime_LiveEditCheckAndDropActivations(Arguments args) {
+static MaybeObject* Runtime_LiveEditCheckAndDropActivations(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
-  HandleScope scope;
+  HandleScope scope(isolate);
   CONVERT_ARG_CHECKED(JSArray, shared_array, 0);
   CONVERT_BOOLEAN_CHECKED(do_drop, args[1]);
 
@@ -10875,9 +11436,10 @@
 // Compares 2 strings line-by-line, then token-wise and returns diff in form
 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
 // of diff chunks.
-static MaybeObject* Runtime_LiveEditCompareStrings(Arguments args) {
+static MaybeObject* Runtime_LiveEditCompareStrings(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
-  HandleScope scope;
+  HandleScope scope(isolate);
   CONVERT_ARG_CHECKED(String, s1, 0);
   CONVERT_ARG_CHECKED(String, s2, 1);
 
@@ -10885,20 +11447,21 @@
 }
 
 
-
 // A testing entry. Returns statement position which is the closest to
 // source_position.
-static MaybeObject* Runtime_GetFunctionCodePositionFromSource(Arguments args) {
+static MaybeObject* Runtime_GetFunctionCodePositionFromSource(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
-  HandleScope scope;
+  HandleScope scope(isolate);
   CONVERT_ARG_CHECKED(JSFunction, function, 0);
   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
 
-  Handle<Code> code(function->code());
+  Handle<Code> code(function->code(), isolate);
 
   if (code->kind() != Code::FUNCTION &&
       code->kind() != Code::OPTIMIZED_FUNCTION) {
-    return Heap::undefined_value();
+    return isolate->heap()->undefined_value();
   }
 
   RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
@@ -10925,9 +11488,10 @@
 // Calls specified function with or without entering the debugger.
 // This is used in unit tests to run code as if debugger is entered or simply
 // to have a stack with C++ frame in the middle.
-static MaybeObject* Runtime_ExecuteInDebugContext(Arguments args) {
+static MaybeObject* Runtime_ExecuteInDebugContext(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
-  HandleScope scope;
+  HandleScope scope(isolate);
   CONVERT_ARG_CHECKED(JSFunction, function, 0);
   CONVERT_BOOLEAN_CHECKED(without_debugger, args[1]);
 
@@ -10935,11 +11499,11 @@
   bool pending_exception;
   {
     if (without_debugger) {
-      result = Execution::Call(function, Top::global(), 0, NULL,
+      result = Execution::Call(function, isolate->global(), 0, NULL,
                                &pending_exception);
     } else {
       EnterDebugger enter_debugger;
-      result = Execution::Call(function, Top::global(), 0, NULL,
+      result = Execution::Call(function, isolate->global(), 0, NULL,
                                &pending_exception);
     }
   }
@@ -10952,61 +11516,68 @@
 
 
 // Sets a v8 flag.
-static MaybeObject* Runtime_SetFlags(Arguments args) {
+static MaybeObject* Runtime_SetFlags(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   CONVERT_CHECKED(String, arg, args[0]);
   SmartPointer<char> flags =
       arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
   FlagList::SetFlagsFromString(*flags, StrLength(*flags));
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
 // Performs a GC.
 // Presently, it only does a full GC.
-static MaybeObject* Runtime_CollectGarbage(Arguments args) {
-  Heap::CollectAllGarbage(true);
-  return Heap::undefined_value();
+static MaybeObject* Runtime_CollectGarbage(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  isolate->heap()->CollectAllGarbage(true);
+  return isolate->heap()->undefined_value();
 }
 
 
 // Gets the current heap usage.
-static MaybeObject* Runtime_GetHeapUsage(Arguments args) {
-  int usage = static_cast<int>(Heap::SizeOfObjects());
+static MaybeObject* Runtime_GetHeapUsage(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
   if (!Smi::IsValid(usage)) {
-    return *Factory::NewNumberFromInt(usage);
+    return *isolate->factory()->NewNumberFromInt(usage);
   }
   return Smi::FromInt(usage);
 }
 
 
 // Captures a live object list from the present heap.
-static MaybeObject* Runtime_HasLOLEnabled(Arguments args) {
+static MaybeObject* Runtime_HasLOLEnabled(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
 #ifdef LIVE_OBJECT_LIST
-  return Heap::true_value();
+  return isolate->heap()->true_value();
 #else
-  return Heap::false_value();
+  return isolate->heap()->false_value();
 #endif
 }
 
 
 // Captures a live object list from the present heap.
-static MaybeObject* Runtime_CaptureLOL(Arguments args) {
+static MaybeObject* Runtime_CaptureLOL(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
 #ifdef LIVE_OBJECT_LIST
   return LiveObjectList::Capture();
 #else
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 #endif
 }
 
 
 // Deletes the specified live object list.
-static MaybeObject* Runtime_DeleteLOL(Arguments args) {
+static MaybeObject* Runtime_DeleteLOL(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
 #ifdef LIVE_OBJECT_LIST
   CONVERT_SMI_CHECKED(id, args[0]);
   bool success = LiveObjectList::Delete(id);
-  return success ? Heap::true_value() : Heap::false_value();
+  return success ? isolate->heap()->true_value() :
+                   isolate->heap()->false_value();
 #else
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 #endif
 }
 
@@ -11016,7 +11587,8 @@
 // specified by id1 and id2.
 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
 // dumped.
-static MaybeObject* Runtime_DumpLOL(Arguments args) {
+static MaybeObject* Runtime_DumpLOL(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
 #ifdef LIVE_OBJECT_LIST
   HandleScope scope;
   CONVERT_SMI_CHECKED(id1, args[0]);
@@ -11027,40 +11599,43 @@
   EnterDebugger enter_debugger;
   return LiveObjectList::Dump(id1, id2, start, count, filter_obj);
 #else
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 #endif
 }
 
 
 // Gets the specified object as requested by the debugger.
 // This is only used for obj ids shown in live object lists.
-static MaybeObject* Runtime_GetLOLObj(Arguments args) {
+static MaybeObject* Runtime_GetLOLObj(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
 #ifdef LIVE_OBJECT_LIST
   CONVERT_SMI_CHECKED(obj_id, args[0]);
   Object* result = LiveObjectList::GetObj(obj_id);
   return result;
 #else
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 #endif
 }
 
 
 // Gets the obj id for the specified address if valid.
 // This is only used for obj ids shown in live object lists.
-static MaybeObject* Runtime_GetLOLObjId(Arguments args) {
+static MaybeObject* Runtime_GetLOLObjId(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
 #ifdef LIVE_OBJECT_LIST
   HandleScope scope;
   CONVERT_ARG_CHECKED(String, address, 0);
   Object* result = LiveObjectList::GetObjId(address);
   return result;
 #else
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 #endif
 }
 
 
 // Gets the retainers that references the specified object alive.
-static MaybeObject* Runtime_GetLOLObjRetainers(Arguments args) {
+static MaybeObject* Runtime_GetLOLObjRetainers(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
 #ifdef LIVE_OBJECT_LIST
   HandleScope scope;
   CONVERT_SMI_CHECKED(obj_id, args[0]);
@@ -11094,13 +11669,14 @@
                                          limit,
                                          filter_obj);
 #else
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 #endif
 }
 
 
 // Gets the reference path between 2 objects.
-static MaybeObject* Runtime_GetLOLPath(Arguments args) {
+static MaybeObject* Runtime_GetLOLPath(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
 #ifdef LIVE_OBJECT_LIST
   HandleScope scope;
   CONVERT_SMI_CHECKED(obj_id1, args[0]);
@@ -11116,45 +11692,48 @@
       LiveObjectList::GetPath(obj_id1, obj_id2, instance_filter);
   return result;
 #else
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 #endif
 }
 
 
 // Generates the response to a debugger request for a list of all
 // previously captured live object lists.
-static MaybeObject* Runtime_InfoLOL(Arguments args) {
+static MaybeObject* Runtime_InfoLOL(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
 #ifdef LIVE_OBJECT_LIST
   CONVERT_SMI_CHECKED(start, args[0]);
   CONVERT_SMI_CHECKED(count, args[1]);
   return LiveObjectList::Info(start, count);
 #else
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 #endif
 }
 
 
 // Gets a dump of the specified object as requested by the debugger.
 // This is only used for obj ids shown in live object lists.
-static MaybeObject* Runtime_PrintLOLObj(Arguments args) {
+static MaybeObject* Runtime_PrintLOLObj(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
 #ifdef LIVE_OBJECT_LIST
   HandleScope scope;
   CONVERT_SMI_CHECKED(obj_id, args[0]);
   Object* result = LiveObjectList::PrintObj(obj_id);
   return result;
 #else
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 #endif
 }
 
 
 // Resets and releases all previously captured live object lists.
-static MaybeObject* Runtime_ResetLOL(Arguments args) {
+static MaybeObject* Runtime_ResetLOL(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
 #ifdef LIVE_OBJECT_LIST
   LiveObjectList::Reset();
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 #else
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 #endif
 }
 
@@ -11164,7 +11743,8 @@
 // specified by id1 and id2.
 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
 // summarized.
-static MaybeObject* Runtime_SummarizeLOL(Arguments args) {
+static MaybeObject* Runtime_SummarizeLOL(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
 #ifdef LIVE_OBJECT_LIST
   HandleScope scope;
   CONVERT_SMI_CHECKED(id1, args[0]);
@@ -11174,7 +11754,7 @@
   EnterDebugger enter_debugger;
   return LiveObjectList::Summarize(id1, id2, filter_obj);
 #else
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 #endif
 }
 
@@ -11182,25 +11762,27 @@
 
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
-static MaybeObject* Runtime_ProfilerResume(Arguments args) {
+static MaybeObject* Runtime_ProfilerResume(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
   CONVERT_CHECKED(Smi, smi_modules, args[0]);
   CONVERT_CHECKED(Smi, smi_tag, args[1]);
   v8::V8::ResumeProfilerEx(smi_modules->value(), smi_tag->value());
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_ProfilerPause(Arguments args) {
+static MaybeObject* Runtime_ProfilerPause(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
 
   CONVERT_CHECKED(Smi, smi_modules, args[0]);
   CONVERT_CHECKED(Smi, smi_tag, args[1]);
   v8::V8::PauseProfilerEx(smi_modules->value(), smi_tag->value());
-  return Heap::undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 #endif  // ENABLE_LOGGING_AND_PROFILING
@@ -11230,7 +11812,7 @@
   }
 
   // If no script with the requested script data is found return undefined.
-  if (script.is_null()) return Factory::undefined_value();
+  if (script.is_null()) return FACTORY->undefined_value();
 
   // Return the script found.
   return GetScriptWrapper(script);
@@ -11240,8 +11822,9 @@
 // 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 MaybeObject* Runtime_GetScript(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_GetScript(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
 
   ASSERT(args.length() == 1);
 
@@ -11285,17 +11868,19 @@
 // Collect the raw data for a stack trace.  Returns an array of 4
 // element segments each containing a receiver, function, code and
 // native code offset.
-static MaybeObject* Runtime_CollectStackTrace(Arguments args) {
+static MaybeObject* Runtime_CollectStackTrace(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT_EQ(args.length(), 2);
   Handle<Object> caller = args.at<Object>(0);
   CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[1]);
 
-  HandleScope scope;
+  HandleScope scope(isolate);
+  Factory* factory = isolate->factory();
 
   limit = Max(limit, 0);  // Ensure that limit is not negative.
   int initial_size = Min(limit, 10);
   Handle<FixedArray> elements =
-      Factory::NewFixedArrayWithHoles(initial_size * 4);
+      factory->NewFixedArrayWithHoles(initial_size * 4);
 
   StackFrameIterator iter;
   // If the caller parameter is a function we skip frames until we're
@@ -11314,7 +11899,7 @@
         if (cursor + 4 > elements->length()) {
           int new_capacity = JSObject::NewElementsCapacity(elements->length());
           Handle<FixedArray> new_elements =
-              Factory::NewFixedArrayWithHoles(new_capacity);
+              factory->NewFixedArrayWithHoles(new_capacity);
           for (int i = 0; i < cursor; i++) {
             new_elements->set(i, elements->get(i));
           }
@@ -11334,36 +11919,40 @@
     }
     iter.Advance();
   }
-  Handle<JSArray> result = Factory::NewJSArrayWithElements(elements);
+  Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
   result->set_length(Smi::FromInt(cursor));
   return *result;
 }
 
 
 // Returns V8 version as a string.
-static MaybeObject* Runtime_GetV8Version(Arguments args) {
+static MaybeObject* Runtime_GetV8Version(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT_EQ(args.length(), 0);
 
   NoHandleAllocation ha;
 
   const char* version_string = v8::V8::GetVersion();
 
-  return Heap::AllocateStringFromAscii(CStrVector(version_string), NOT_TENURED);
+  return isolate->heap()->AllocateStringFromAscii(CStrVector(version_string),
+                                                  NOT_TENURED);
 }
 
 
-static MaybeObject* Runtime_Abort(Arguments args) {
+static MaybeObject* Runtime_Abort(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 2);
   OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) +
                                     Smi::cast(args[1])->value());
-  Top::PrintStack();
+  isolate->PrintStack();
   OS::Abort();
   UNREACHABLE();
   return NULL;
 }
 
 
-static MaybeObject* Runtime_GetFromCache(Arguments args) {
+static MaybeObject* Runtime_GetFromCache(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   // This is only called from codegen, so checks might be more lax.
   CONVERT_CHECKED(JSFunctionResultCache, cache, args[0]);
   Object* key = args[1];
@@ -11397,7 +11986,7 @@
   }
 
   // There is no value in the cache.  Invoke the function and cache result.
-  HandleScope scope;
+  HandleScope scope(isolate);
 
   Handle<JSFunctionResultCache> cache_handle(cache);
   Handle<Object> key_handle(key);
@@ -11406,7 +11995,7 @@
     Handle<JSFunction> factory(JSFunction::cast(
           cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
     // TODO(antonm): consider passing a receiver when constructing a cache.
-    Handle<Object> receiver(Top::global_context()->global());
+    Handle<Object> receiver(isolate->global_context()->global());
     // This handle is nor shared, nor used later, so it's safe.
     Object** argv[] = { key_handle.location() };
     bool pending_exception = false;
@@ -11455,39 +12044,46 @@
 }
 
 
-static MaybeObject* Runtime_NewMessageObject(Arguments args) {
-  HandleScope scope;
+static MaybeObject* Runtime_NewMessageObject(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
+  HandleScope scope(isolate);
   CONVERT_ARG_CHECKED(String, type, 0);
   CONVERT_ARG_CHECKED(JSArray, arguments, 1);
-  return *Factory::NewJSMessageObject(type,
-                                      arguments,
-                                      0,
-                                      0,
-                                      Factory::undefined_value(),
-                                      Factory::undefined_value(),
-                                      Factory::undefined_value());
+  return *isolate->factory()->NewJSMessageObject(
+      type,
+      arguments,
+      0,
+      0,
+      isolate->factory()->undefined_value(),
+      isolate->factory()->undefined_value(),
+      isolate->factory()->undefined_value());
 }
 
 
-static MaybeObject* Runtime_MessageGetType(Arguments args) {
+static MaybeObject* Runtime_MessageGetType(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   CONVERT_CHECKED(JSMessageObject, message, args[0]);
   return message->type();
 }
 
 
-static MaybeObject* Runtime_MessageGetArguments(Arguments args) {
+static MaybeObject* Runtime_MessageGetArguments(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   CONVERT_CHECKED(JSMessageObject, message, args[0]);
   return message->arguments();
 }
 
 
-static MaybeObject* Runtime_MessageGetStartPosition(Arguments args) {
+static MaybeObject* Runtime_MessageGetStartPosition(
+    RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   CONVERT_CHECKED(JSMessageObject, message, args[0]);
   return Smi::FromInt(message->start_position());
 }
 
 
-static MaybeObject* Runtime_MessageGetScript(Arguments args) {
+static MaybeObject* Runtime_MessageGetScript(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   CONVERT_CHECKED(JSMessageObject, message, args[0]);
   return message->script();
 }
@@ -11496,7 +12092,8 @@
 #ifdef DEBUG
 // ListNatives is ONLY used by the fuzz-natives.js in debug mode
 // Exclude the code in release mode.
-static MaybeObject* Runtime_ListNatives(Arguments args) {
+static MaybeObject* Runtime_ListNatives(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 0);
   HandleScope scope;
 #define COUNT_ENTRY(Name, argc, ressize) + 1
@@ -11505,7 +12102,8 @@
       INLINE_FUNCTION_LIST(COUNT_ENTRY)
       INLINE_RUNTIME_FUNCTION_LIST(COUNT_ENTRY);
 #undef COUNT_ENTRY
-  Handle<FixedArray> elements = Factory::NewFixedArray(entry_count);
+  Factory* factory = isolate->factory();
+  Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
   int index = 0;
   bool inline_runtime_functions = false;
 #define ADD_ENTRY(Name, argc, ressize)                                       \
@@ -11514,16 +12112,16 @@
     Handle<String> name;                                                     \
     /* Inline runtime functions have an underscore in front of the name. */  \
     if (inline_runtime_functions) {                                          \
-      name = Factory::NewStringFromAscii(                                    \
+      name = factory->NewStringFromAscii(                                    \
           Vector<const char>("_" #Name, StrLength("_" #Name)));              \
     } else {                                                                 \
-      name = Factory::NewStringFromAscii(                                    \
+      name = factory->NewStringFromAscii(                                    \
           Vector<const char>(#Name, StrLength(#Name)));                      \
     }                                                                        \
-    Handle<FixedArray> pair_elements = Factory::NewFixedArray(2);            \
+    Handle<FixedArray> pair_elements = factory->NewFixedArray(2);            \
     pair_elements->set(0, *name);                                            \
     pair_elements->set(1, Smi::FromInt(argc));                               \
-    Handle<JSArray> pair = Factory::NewJSArrayWithElements(pair_elements);   \
+    Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements);   \
     elements->set(index++, *pair);                                           \
   }
   inline_runtime_functions = false;
@@ -11533,23 +12131,24 @@
   INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
 #undef ADD_ENTRY
   ASSERT_EQ(index, entry_count);
-  Handle<JSArray> result = Factory::NewJSArrayWithElements(elements);
+  Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
   return *result;
 }
 #endif
 
 
-static MaybeObject* Runtime_Log(Arguments args) {
+static MaybeObject* Runtime_Log(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   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();
+  LOGGER->LogRuntime(chars, elms);
+  return isolate->heap()->undefined_value();
 }
 
 
-static MaybeObject* Runtime_IS_VAR(Arguments args) {
+static MaybeObject* Runtime_IS_VAR(RUNTIME_CALLING_CONVENTION) {
   UNREACHABLE();  // implemented as macro in the parser
   return NULL;
 }
@@ -11567,20 +12166,22 @@
   { Runtime::kInline##name, Runtime::INLINE,     \
     "_" #name, NULL, number_of_args, result_size },
 
-Runtime::Function kIntrinsicFunctions[] = {
+static const Runtime::Function kIntrinsicFunctions[] = {
   RUNTIME_FUNCTION_LIST(F)
   INLINE_FUNCTION_LIST(I)
   INLINE_RUNTIME_FUNCTION_LIST(I)
 };
 
 
-MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Object* dictionary) {
+MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Heap* heap,
+                                                       Object* dictionary) {
+  ASSERT(Isolate::Current()->heap() == heap);
   ASSERT(dictionary != NULL);
   ASSERT(StringDictionary::cast(dictionary)->NumberOfElements() == 0);
   for (int i = 0; i < kNumFunctions; ++i) {
     Object* name_symbol;
     { MaybeObject* maybe_name_symbol =
-          Heap::LookupAsciiSymbol(kIntrinsicFunctions[i].name);
+          heap->LookupAsciiSymbol(kIntrinsicFunctions[i].name);
       if (!maybe_name_symbol->ToObject(&name_symbol)) return maybe_name_symbol;
     }
     StringDictionary* string_dictionary = StringDictionary::cast(dictionary);
@@ -11599,10 +12200,11 @@
 }
 
 
-Runtime::Function* Runtime::FunctionForSymbol(Handle<String> name) {
-  int entry = Heap::intrinsic_function_names()->FindEntry(*name);
+const Runtime::Function* Runtime::FunctionForSymbol(Handle<String> name) {
+  Heap* heap = name->GetHeap();
+  int entry = heap->intrinsic_function_names()->FindEntry(*name);
   if (entry != kNotFound) {
-    Object* smi_index = Heap::intrinsic_function_names()->ValueAt(entry);
+    Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
     int function_index = Smi::cast(smi_index)->value();
     return &(kIntrinsicFunctions[function_index]);
   }
@@ -11610,22 +12212,23 @@
 }
 
 
-Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
+const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
   return &(kIntrinsicFunctions[static_cast<int>(id)]);
 }
 
 
 void Runtime::PerformGC(Object* result) {
+  Isolate* isolate = Isolate::Current();
   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->allocation_space());
+    isolate->heap()->CollectGarbage(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(false);
+    isolate->counters()->gc_last_resort_from_js()->Increment();
+    isolate->heap()->CollectAllGarbage(false);
   }
 }
 
diff --git a/src/runtime.h b/src/runtime.h
index 8e73d5c..58062ca 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -28,6 +28,8 @@
 #ifndef V8_RUNTIME_H_
 #define V8_RUNTIME_H_
 
+#include "zone.h"
+
 namespace v8 {
 namespace internal {
 
@@ -412,7 +414,6 @@
 #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
@@ -482,6 +483,57 @@
 //---------------------------------------------------------------------------
 // Runtime provides access to all C++ runtime functions.
 
+class RuntimeState {
+ public:
+
+  StaticResource<StringInputBuffer>* string_input_buffer() {
+    return &string_input_buffer_;
+  }
+  unibrow::Mapping<unibrow::ToUppercase, 128>* to_upper_mapping() {
+    return &to_upper_mapping_;
+  }
+  unibrow::Mapping<unibrow::ToLowercase, 128>* to_lower_mapping() {
+    return &to_lower_mapping_;
+  }
+  StringInputBuffer* string_input_buffer_compare_bufx() {
+    return &string_input_buffer_compare_bufx_;
+  }
+  StringInputBuffer* string_input_buffer_compare_bufy() {
+    return &string_input_buffer_compare_bufy_;
+  }
+  StringInputBuffer* string_locale_compare_buf1() {
+    return &string_locale_compare_buf1_;
+  }
+  StringInputBuffer* string_locale_compare_buf2() {
+    return &string_locale_compare_buf2_;
+  }
+  int* smi_lexicographic_compare_x_elms() {
+    return smi_lexicographic_compare_x_elms_;
+  }
+  int* smi_lexicographic_compare_y_elms() {
+    return smi_lexicographic_compare_y_elms_;
+  }
+
+ private:
+  RuntimeState() {}
+  // Non-reentrant string buffer for efficient general use in the runtime.
+  StaticResource<StringInputBuffer> string_input_buffer_;
+  unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping_;
+  unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping_;
+  StringInputBuffer string_input_buffer_compare_bufx_;
+  StringInputBuffer string_input_buffer_compare_bufy_;
+  StringInputBuffer string_locale_compare_buf1_;
+  StringInputBuffer string_locale_compare_buf2_;
+  int smi_lexicographic_compare_x_elms_[10];
+  int smi_lexicographic_compare_y_elms_[10];
+
+  friend class Isolate;
+  friend class Runtime;
+
+  DISALLOW_COPY_AND_ASSIGN(RuntimeState);
+};
+
+
 class Runtime : public AllStatic {
  public:
   enum FunctionId {
@@ -525,30 +577,35 @@
   // retried with a new, empty StringDictionary, not with the same one.
   // Alternatively, heap initialization can be completely restarted.
   MUST_USE_RESULT static MaybeObject* InitializeIntrinsicFunctionNames(
-      Object* dictionary);
+      Heap* heap, Object* dictionary);
 
   // Get the intrinsic function with the given name, which must be a symbol.
-  static Function* FunctionForSymbol(Handle<String> name);
+  static const Function* FunctionForSymbol(Handle<String> name);
 
   // Get the intrinsic function with the given FunctionId.
-  static Function* FunctionForId(FunctionId id);
+  static const Function* FunctionForId(FunctionId id);
 
   // General-purpose helper functions for runtime system.
-  static int StringMatch(Handle<String> sub, Handle<String> pat, int index);
+  static int StringMatch(Isolate* isolate,
+                         Handle<String> sub,
+                         Handle<String> pat,
+                         int index);
 
-  static bool IsUpperCaseChar(uint16_t ch);
+  static bool IsUpperCaseChar(RuntimeState* runtime_state, 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.
-  MUST_USE_RESULT static MaybeObject* GetElementOrCharAt(Handle<Object> object,
+  MUST_USE_RESULT static MaybeObject* GetElementOrCharAt(Isolate* isolate,
+                                                         Handle<Object> object,
                                                          uint32_t index);
   MUST_USE_RESULT static MaybeObject* GetElement(Handle<Object> object,
                                                  uint32_t index);
 
   MUST_USE_RESULT static MaybeObject* SetObjectProperty(
+      Isolate* isolate,
       Handle<Object> object,
       Handle<Object> key,
       Handle<Object> value,
@@ -556,27 +613,31 @@
       StrictModeFlag strict_mode);
 
   MUST_USE_RESULT static MaybeObject* ForceSetObjectProperty(
+      Isolate* isolate,
       Handle<JSObject> object,
       Handle<Object> key,
       Handle<Object> value,
       PropertyAttributes attr);
 
   MUST_USE_RESULT static MaybeObject* ForceDeleteObjectProperty(
+      Isolate* isolate,
       Handle<JSObject> object,
       Handle<Object> key);
 
-  MUST_USE_RESULT static MaybeObject* GetObjectProperty(Handle<Object> object,
-                                                        Handle<Object> key);
+  MUST_USE_RESULT static MaybeObject* GetObjectProperty(
+      Isolate* isolate,
+      Handle<Object> object,
+      Handle<Object> key);
 
   // This function is used in FunctionNameUsing* tests.
-  static Object* FindSharedFunctionInfoInScript(Handle<Script> script,
+  static Object* FindSharedFunctionInfoInScript(Isolate* isolate,
+                                                Handle<Script> script,
                                                 int position);
 
   // Helper functions used stubs.
   static void PerformGC(Object* result);
 };
 
-
 } }  // namespace v8::internal
 
 #endif  // V8_RUNTIME_H_
diff --git a/src/safepoint-table.cc b/src/safepoint-table.cc
index d2ec54c..28cf6e6 100644
--- a/src/safepoint-table.cc
+++ b/src/safepoint-table.cc
@@ -25,11 +25,14 @@
 // (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 "safepoint-table.h"
 
 #include "deoptimizer.h"
 #include "disasm.h"
 #include "macro-assembler.h"
+#include "zone-inl.h"
 
 namespace v8 {
 namespace internal {
diff --git a/src/safepoint-table.h b/src/safepoint-table.h
index 8803d06..084a0b4 100644
--- a/src/safepoint-table.h
+++ b/src/safepoint-table.h
@@ -28,11 +28,9 @@
 #ifndef V8_SAFEPOINT_TABLE_H_
 #define V8_SAFEPOINT_TABLE_H_
 
-#include "v8.h"
-
 #include "heap.h"
+#include "v8memory.h"
 #include "zone.h"
-#include "zone-inl.h"
 
 namespace v8 {
 namespace internal {
@@ -228,6 +226,14 @@
     deoptimization_info_[index].pc_after_gap = pc;
   }
 
+  // Get the end pc offset of the last safepoint, including the code generated
+  // until the end of the gap following it.
+  unsigned GetPcAfterGap() {
+    int index = deoptimization_info_.length();
+    if (index == 0) return 0;
+    return deoptimization_info_[index - 1].pc_after_gap;
+  }
+
   // Emit the safepoint table after the body. The number of bits per
   // entry must be enough to hold all the pointer indexes.
   void Emit(Assembler* assembler, int bits_per_entry);
diff --git a/src/scanner-base.cc b/src/scanner-base.cc
index 80bca4e..2066b5a 100644
--- a/src/scanner-base.cc
+++ b/src/scanner-base.cc
@@ -35,16 +35,6 @@
 namespace internal {
 
 // ----------------------------------------------------------------------------
-// Character predicates
-
-unibrow::Predicate<IdentifierStart, 128> ScannerConstants::kIsIdentifierStart;
-unibrow::Predicate<IdentifierPart, 128> ScannerConstants::kIsIdentifierPart;
-unibrow::Predicate<unibrow::WhiteSpace, 128> ScannerConstants::kIsWhiteSpace;
-unibrow::Predicate<unibrow::LineTerminator, 128>
-  ScannerConstants::kIsLineTerminator;
-
-StaticResource<ScannerConstants::Utf8Decoder> ScannerConstants::utf8_decoder_;
-
 // Compound predicates.
 
 bool ScannerConstants::IsIdentifier(unibrow::CharacterStream* buffer) {
@@ -64,8 +54,10 @@
 // ----------------------------------------------------------------------------
 // Scanner
 
-Scanner::Scanner()
-  : octal_pos_(kNoOctalLocation) { }
+Scanner::Scanner(ScannerConstants* scanner_constants)
+    : scanner_constants_(scanner_constants),
+      octal_pos_(kNoOctalLocation) {
+}
 
 
 uc32 Scanner::ScanHexEscape(uc32 c, int length) {
@@ -122,7 +114,8 @@
 // ----------------------------------------------------------------------------
 // JavaScriptScanner
 
-JavaScriptScanner::JavaScriptScanner() : Scanner() {}
+JavaScriptScanner::JavaScriptScanner(ScannerConstants* scanner_contants)
+    : Scanner(scanner_contants) { }
 
 
 Token::Value JavaScriptScanner::Next() {
@@ -151,9 +144,9 @@
   while (true) {
     // We treat byte-order marks (BOMs) as whitespace for better
     // compatibility with Spidermonkey and other JavaScript engines.
-    while (ScannerConstants::kIsWhiteSpace.get(c0_) || IsByteOrderMark(c0_)) {
+    while (scanner_constants_->IsWhiteSpace(c0_) || IsByteOrderMark(c0_)) {
       // IsWhiteSpace() includes line terminators!
-      if (ScannerConstants::kIsLineTerminator.get(c0_)) {
+      if (scanner_constants_->IsLineTerminator(c0_)) {
         // Ignore line terminators, but remember them. This is necessary
         // for automatic semicolon insertion.
         has_line_terminator_before_next_ = true;
@@ -193,7 +186,7 @@
   // separately by the lexical grammar and becomes part of the
   // stream of input elements for the syntactic grammar (see
   // ECMA-262, section 7.4, page 12).
-  while (c0_ >= 0 && !ScannerConstants::kIsLineTerminator.get(c0_)) {
+  while (c0_ >= 0 && !scanner_constants_->IsLineTerminator(c0_)) {
     Advance();
   }
 
@@ -458,7 +451,7 @@
         break;
 
       default:
-        if (ScannerConstants::kIsIdentifierStart.get(c0_)) {
+        if (scanner_constants_->IsIdentifierStart(c0_)) {
           token = ScanIdentifierOrKeyword();
         } else if (IsDecimalDigit(c0_)) {
           token = ScanNumber(false);
@@ -506,7 +499,7 @@
   Advance();
 
   // Skip escaped newlines.
-  if (ScannerConstants::kIsLineTerminator.get(c)) {
+  if (scanner_constants_->IsLineTerminator(c)) {
     // Allow CR+LF newlines in multiline string literals.
     if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance();
     // Allow LF+CR newlines in multiline string literals.
@@ -549,7 +542,7 @@
 
   LiteralScope literal(this);
   while (c0_ != quote && c0_ >= 0
-         && !ScannerConstants::kIsLineTerminator.get(c0_)) {
+         && !scanner_constants_->IsLineTerminator(c0_)) {
     uc32 c = c0_;
     Advance();
     if (c == '\\') {
@@ -648,7 +641,7 @@
   // not be an identifier start or a decimal digit; see ECMA-262
   // section 7.8.3, page 17 (note that we read only one decimal digit
   // if the value is 0).
-  if (IsDecimalDigit(c0_) || ScannerConstants::kIsIdentifierStart.get(c0_))
+  if (IsDecimalDigit(c0_) || scanner_constants_->IsIdentifierStart(c0_))
     return Token::ILLEGAL;
 
   literal.Complete();
@@ -670,14 +663,14 @@
 
 
 Token::Value JavaScriptScanner::ScanIdentifierOrKeyword() {
-  ASSERT(ScannerConstants::kIsIdentifierStart.get(c0_));
+  ASSERT(scanner_constants_->IsIdentifierStart(c0_));
   LiteralScope literal(this);
   KeywordMatcher keyword_match;
   // Scan identifier start character.
   if (c0_ == '\\') {
     uc32 c = ScanIdentifierUnicodeEscape();
     // Only allow legal identifier start characters.
-    if (!ScannerConstants::kIsIdentifierStart.get(c)) return Token::ILLEGAL;
+    if (!scanner_constants_->IsIdentifierStart(c)) return Token::ILLEGAL;
     AddLiteralChar(c);
     return ScanIdentifierSuffix(&literal);
   }
@@ -690,7 +683,7 @@
   }
 
   // Scan the rest of the identifier characters.
-  while (ScannerConstants::kIsIdentifierPart.get(c0_)) {
+  while (scanner_constants_->IsIdentifierPart(c0_)) {
     if (c0_ != '\\') {
       uc32 next_char = c0_;
       Advance();
@@ -708,11 +701,11 @@
 
 Token::Value JavaScriptScanner::ScanIdentifierSuffix(LiteralScope* literal) {
   // Scan the rest of the identifier characters.
-  while (ScannerConstants::kIsIdentifierPart.get(c0_)) {
+  while (scanner_constants_->IsIdentifierPart(c0_)) {
     if (c0_ == '\\') {
       uc32 c = ScanIdentifierUnicodeEscape();
       // Only allow legal identifier part characters.
-      if (!ScannerConstants::kIsIdentifierPart.get(c)) return Token::ILLEGAL;
+      if (!scanner_constants_->IsIdentifierPart(c)) return Token::ILLEGAL;
       AddLiteralChar(c);
     } else {
       AddLiteralChar(c0_);
@@ -742,10 +735,10 @@
     AddLiteralChar('=');
 
   while (c0_ != '/' || in_character_class) {
-    if (ScannerConstants::kIsLineTerminator.get(c0_) || c0_ < 0) return false;
+    if (scanner_constants_->IsLineTerminator(c0_) || c0_ < 0) return false;
     if (c0_ == '\\') {  // Escape sequence.
       AddLiteralCharAdvance();
-      if (ScannerConstants::kIsLineTerminator.get(c0_) || c0_ < 0) return false;
+      if (scanner_constants_->IsLineTerminator(c0_) || c0_ < 0) return false;
       AddLiteralCharAdvance();
       // If the escape allows more characters, i.e., \x??, \u????, or \c?,
       // only "safe" characters are allowed (letters, digits, underscore),
@@ -771,7 +764,7 @@
 bool JavaScriptScanner::ScanRegExpFlags() {
   // Scan regular expression flags.
   LiteralScope literal(this);
-  while (ScannerConstants::kIsIdentifierPart.get(c0_)) {
+  while (scanner_constants_->IsIdentifierPart(c0_)) {
     if (c0_ == '\\') {
       uc32 c = ScanIdentifierUnicodeEscape();
       if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) {
diff --git a/src/scanner-base.h b/src/scanner-base.h
index f5fe7f7..552f387 100644
--- a/src/scanner-base.h
+++ b/src/scanner-base.h
@@ -119,26 +119,33 @@
 };
 
 
+class ScannerConstants {
 // ---------------------------------------------------------------------
 // Constants used by scanners.
-
-class ScannerConstants : AllStatic {
  public:
+  ScannerConstants() {}
   typedef unibrow::Utf8InputBuffer<1024> Utf8Decoder;
 
-  static StaticResource<Utf8Decoder>* utf8_decoder() {
+  StaticResource<Utf8Decoder>* utf8_decoder() {
     return &utf8_decoder_;
   }
 
-  static unibrow::Predicate<IdentifierStart, 128> kIsIdentifierStart;
-  static unibrow::Predicate<IdentifierPart, 128> kIsIdentifierPart;
-  static unibrow::Predicate<unibrow::LineTerminator, 128> kIsLineTerminator;
-  static unibrow::Predicate<unibrow::WhiteSpace, 128> kIsWhiteSpace;
+  bool IsIdentifierStart(unibrow::uchar c) { return kIsIdentifierStart.get(c); }
+  bool IsIdentifierPart(unibrow::uchar c) { return kIsIdentifierPart.get(c); }
+  bool IsLineTerminator(unibrow::uchar c) { return kIsLineTerminator.get(c); }
+  bool IsWhiteSpace(unibrow::uchar c) { return kIsWhiteSpace.get(c); }
 
-  static bool IsIdentifier(unibrow::CharacterStream* buffer);
+  bool IsIdentifier(unibrow::CharacterStream* buffer);
 
  private:
-  static StaticResource<Utf8Decoder> utf8_decoder_;
+
+  unibrow::Predicate<IdentifierStart, 128> kIsIdentifierStart;
+  unibrow::Predicate<IdentifierPart, 128> kIsIdentifierPart;
+  unibrow::Predicate<unibrow::LineTerminator, 128> kIsLineTerminator;
+  unibrow::Predicate<unibrow::WhiteSpace, 128> kIsWhiteSpace;
+  StaticResource<Utf8Decoder> utf8_decoder_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScannerConstants);
 };
 
 // ----------------------------------------------------------------------------
@@ -238,6 +245,8 @@
   bool is_ascii_;
   int position_;
   Vector<byte> backing_store_;
+
+  DISALLOW_COPY_AND_ASSIGN(LiteralBuffer);
 };
 
 
@@ -263,7 +272,7 @@
     bool complete_;
   };
 
-  Scanner();
+  explicit Scanner(ScannerConstants* scanner_contants);
 
   // Returns the current token again.
   Token::Value current_token() { return current_.token; }
@@ -418,6 +427,8 @@
     return source_->pos() - kCharacterLookaheadBufferSize;
   }
 
+  ScannerConstants* scanner_constants_;
+
   // Buffers collecting literal strings, numbers, etc.
   LiteralBuffer literal_buffer1_;
   LiteralBuffer literal_buffer2_;
@@ -462,7 +473,7 @@
     bool complete_;
   };
 
-  JavaScriptScanner();
+  explicit JavaScriptScanner(ScannerConstants* scanner_contants);
 
   // Returns the next token.
   Token::Value Next();
diff --git a/src/scanner.cc b/src/scanner.cc
index d54d9f9..d9c2188 100755
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -328,8 +328,6 @@
 // ----------------------------------------------------------------------------
 // V8JavaScriptScanner
 
-V8JavaScriptScanner::V8JavaScriptScanner() : JavaScriptScanner() { }
-
 
 void V8JavaScriptScanner::Initialize(UC16CharacterStream* source) {
   source_ = source;
@@ -347,7 +345,8 @@
 // ----------------------------------------------------------------------------
 // JsonScanner
 
-JsonScanner::JsonScanner() : Scanner() { }
+JsonScanner::JsonScanner(ScannerConstants* scanner_constants)
+    : Scanner(scanner_constants) { }
 
 
 void JsonScanner::Initialize(UC16CharacterStream* source) {
@@ -576,11 +575,10 @@
     Advance();
     text++;
   }
-  if (ScannerConstants::kIsIdentifierPart.get(c0_)) return Token::ILLEGAL;
+  if (scanner_constants_->IsIdentifierPart(c0_)) return Token::ILLEGAL;
   literal.Complete();
   return token;
 }
 
 
-
 } }  // namespace v8::internal
diff --git a/src/scanner.h b/src/scanner.h
index cf2084f..776ba53 100644
--- a/src/scanner.h
+++ b/src/scanner.h
@@ -134,14 +134,16 @@
 
 class V8JavaScriptScanner : public JavaScriptScanner {
  public:
-  V8JavaScriptScanner();
+  explicit V8JavaScriptScanner(ScannerConstants* scanner_constants)
+      : JavaScriptScanner(scanner_constants) {}
+
   void Initialize(UC16CharacterStream* source);
 };
 
 
 class JsonScanner : public Scanner {
  public:
-  JsonScanner();
+  explicit JsonScanner(ScannerConstants* scanner_constants);
 
   void Initialize(UC16CharacterStream* source);
 
diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc
index e06235a..58e2ad2 100644
--- a/src/scopeinfo.cc
+++ b/src/scopeinfo.cc
@@ -50,7 +50,7 @@
 
 template<class Allocator>
 ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
-    : function_name_(Factory::empty_symbol()),
+    : function_name_(FACTORY->empty_symbol()),
       calls_eval_(scope->calls_eval()),
       parameters_(scope->num_parameters()),
       stack_slots_(scope->num_stack_slots()),
@@ -141,7 +141,7 @@
              context_slots_.length());
       ASSERT(var->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS ==
              context_modes_.length());
-      context_slots_.Add(Factory::empty_symbol());
+      context_slots_.Add(FACTORY->empty_symbol());
       context_modes_.Add(Variable::INTERNAL);
     }
   }
@@ -238,7 +238,7 @@
 
 template<class Allocator>
 ScopeInfo<Allocator>::ScopeInfo(SerializedScopeInfo* data)
-  : function_name_(Factory::empty_symbol()),
+  : function_name_(FACTORY->empty_symbol()),
     parameters_(4),
     stack_slots_(8),
     context_slots_(8),
@@ -309,7 +309,7 @@
                stack_slots_.length();
 
   Handle<SerializedScopeInfo> data(
-      SerializedScopeInfo::cast(*Factory::NewFixedArray(length, TENURED)));
+      SerializedScopeInfo::cast(*FACTORY->NewFixedArray(length, TENURED)));
   AssertNoAllocation nogc;
 
   Object** p0 = data->data_start();
@@ -357,7 +357,7 @@
 
 
 SerializedScopeInfo* SerializedScopeInfo::Empty() {
-  return reinterpret_cast<SerializedScopeInfo*>(Heap::empty_fixed_array());
+  return reinterpret_cast<SerializedScopeInfo*>(HEAP->empty_fixed_array());
 }
 
 
@@ -448,7 +448,8 @@
 
 int SerializedScopeInfo::ContextSlotIndex(String* name, Variable::Mode* mode) {
   ASSERT(name->IsSymbol());
-  int result = ContextSlotCache::Lookup(this, name, mode);
+  Isolate* isolate = GetIsolate();
+  int result = isolate->context_slot_cache()->Lookup(this, name, mode);
   if (result != ContextSlotCache::kNotFound) return result;
   if (length() > 0) {
     // Slots start after length entry.
@@ -465,13 +466,13 @@
         Variable::Mode mode_value = static_cast<Variable::Mode>(v);
         if (mode != NULL) *mode = mode_value;
         result = static_cast<int>((p - p0) >> 1) + Context::MIN_CONTEXT_SLOTS;
-        ContextSlotCache::Update(this, name, mode_value, result);
+        isolate->context_slot_cache()->Update(this, name, mode_value, result);
         return result;
       }
       p += 2;
     }
   }
-  ContextSlotCache::Update(this, name, Variable::INTERNAL, -1);
+  isolate->context_slot_cache()->Update(this, name, Variable::INTERNAL, -1);
   return -1;
 }
 
@@ -547,7 +548,7 @@
                               int slot_index) {
   String* symbol;
   ASSERT(slot_index > kNotFound);
-  if (Heap::LookupSymbolIfExists(name, &symbol)) {
+  if (HEAP->LookupSymbolIfExists(name, &symbol)) {
     int index = Hash(data, symbol);
     Key& key = keys_[index];
     key.data = data;
@@ -566,12 +567,6 @@
 }
 
 
-ContextSlotCache::Key ContextSlotCache::keys_[ContextSlotCache::kLength];
-
-
-uint32_t ContextSlotCache::values_[ContextSlotCache::kLength];
-
-
 #ifdef DEBUG
 
 void ContextSlotCache::ValidateEntry(Object* data,
@@ -579,7 +574,7 @@
                                      Variable::Mode mode,
                                      int slot_index) {
   String* symbol;
-  if (Heap::LookupSymbolIfExists(name, &symbol)) {
+  if (HEAP->LookupSymbolIfExists(name, &symbol)) {
     int index = Hash(data, name);
     Key& key = keys_[index];
     ASSERT(key.data == data);
diff --git a/src/scopeinfo.h b/src/scopeinfo.h
index dd49a4e..cc9f816 100644
--- a/src/scopeinfo.h
+++ b/src/scopeinfo.h
@@ -114,7 +114,7 @@
 
   // Does this scope have an arguments shadow?
   bool HasArgumentsShadow() {
-    return StackSlotIndex(Heap::arguments_shadow_symbol()) >= 0;
+    return StackSlotIndex(GetHeap()->arguments_shadow_symbol()) >= 0;
   }
 
   // Return the number of stack slots for code.
@@ -173,28 +173,36 @@
  public:
   // Lookup context slot index for (data, name).
   // If absent, kNotFound is returned.
-  static int Lookup(Object* data,
-                    String* name,
-                    Variable::Mode* mode);
+  int Lookup(Object* data,
+             String* name,
+             Variable::Mode* mode);
 
   // Update an element in the cache.
-  static void Update(Object* data,
-                     String* name,
-                     Variable::Mode mode,
-                     int slot_index);
+  void Update(Object* data,
+              String* name,
+              Variable::Mode mode,
+              int slot_index);
 
   // Clear the cache.
-  static void Clear();
+  void Clear();
 
   static const int kNotFound = -2;
  private:
+  ContextSlotCache() {
+    for (int i = 0; i < kLength; ++i) {
+      keys_[i].data = NULL;
+      keys_[i].name = NULL;
+      values_[i] = kNotFound;
+    }
+  }
+
   inline static int Hash(Object* data, String* name);
 
 #ifdef DEBUG
-  static void ValidateEntry(Object* data,
-                            String* name,
-                            Variable::Mode mode,
-                            int slot_index);
+  void ValidateEntry(Object* data,
+                     String* name,
+                     Variable::Mode mode,
+                     int slot_index);
 #endif
 
   static const int kLength = 256;
@@ -228,8 +236,11 @@
     uint32_t value_;
   };
 
-  static Key keys_[kLength];
-  static uint32_t values_[kLength];
+  Key keys_[kLength];
+  uint32_t values_[kLength];
+
+  friend class Isolate;
+  DISALLOW_COPY_AND_ASSIGN(ContextSlotCache);
 };
 
 
diff --git a/src/scopes.cc b/src/scopes.cc
index fd573b0..f4bcaa8 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -40,12 +40,14 @@
 // ----------------------------------------------------------------------------
 // A Zone allocator for use with LocalsMap.
 
+// TODO(isolates): It is probably worth it to change the Allocator class to
+//                 take a pointer to an isolate.
 class ZoneAllocator: public Allocator {
  public:
   /* nothing to do */
   virtual ~ZoneAllocator()  {}
 
-  virtual void* New(size_t size)  { return Zone::New(static_cast<int>(size)); }
+  virtual void* New(size_t size)  { return ZONE->New(static_cast<int>(size)); }
 
   /* ignored - Zone is freed in one fell swoop */
   virtual void Delete(void* p)  {}
@@ -148,26 +150,30 @@
     unresolved_(16),
     decls_(4) {
   ASSERT(scope_info != NULL);
-  SetDefaults(FUNCTION_SCOPE, inner_scope->outer_scope(), scope_info);
+  SetDefaults(FUNCTION_SCOPE, NULL, scope_info);
   ASSERT(resolved());
-  InsertAfterScope(inner_scope);
   if (scope_info->HasHeapAllocatedLocals()) {
     num_heap_slots_ = scope_info_->NumberOfContextSlots();
   }
 
+  AddInnerScope(inner_scope);
+
   // This scope's arguments shadow (if present) is context-allocated if an inner
   // scope accesses this one's parameters.  Allocate the arguments_shadow_
   // variable if necessary.
+  Isolate* isolate = Isolate::Current();
   Variable::Mode mode;
   int arguments_shadow_index =
-      scope_info_->ContextSlotIndex(Heap::arguments_shadow_symbol(), &mode);
+      scope_info_->ContextSlotIndex(
+          isolate->heap()->arguments_shadow_symbol(), &mode);
   if (arguments_shadow_index >= 0) {
     ASSERT(mode == Variable::INTERNAL);
-    arguments_shadow_ = new Variable(this,
-                                     Factory::arguments_shadow_symbol(),
-                                     Variable::INTERNAL,
-                                     true,
-                                     Variable::ARGUMENTS);
+    arguments_shadow_ = new Variable(
+        this,
+        isolate->factory()->arguments_shadow_symbol(),
+        Variable::INTERNAL,
+        true,
+        Variable::ARGUMENTS);
     arguments_shadow_->set_rewrite(
         new Slot(arguments_shadow_, Slot::CONTEXT, arguments_shadow_index));
     arguments_shadow_->set_is_used(true);
@@ -175,34 +181,44 @@
 }
 
 
+Scope* Scope::DeserializeScopeChain(CompilationInfo* info,
+                                    Scope* global_scope) {
+  ASSERT(!info->closure().is_null());
+  // If we have a serialized scope info, reuse it.
+  Scope* innermost_scope = NULL;
+  Scope* scope = NULL;
+
+  SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info();
+  if (scope_info != SerializedScopeInfo::Empty()) {
+    JSFunction* current = *info->closure();
+    do {
+      current = current->context()->closure();
+      SerializedScopeInfo* scope_info = current->shared()->scope_info();
+      if (scope_info != SerializedScopeInfo::Empty()) {
+        scope = new Scope(scope, scope_info);
+        if (innermost_scope == NULL) innermost_scope = scope;
+      } else {
+        ASSERT(current->context()->IsGlobalContext());
+      }
+    } while (!current->context()->IsGlobalContext());
+  }
+
+  global_scope->AddInnerScope(scope);
+  if (innermost_scope == NULL) innermost_scope = global_scope;
+
+  return innermost_scope;
+}
+
 
 bool Scope::Analyze(CompilationInfo* info) {
   ASSERT(info->function() != NULL);
   Scope* top = info->function()->scope();
 
-  // If we have a serialized scope info, reuse it.
-  if (!info->closure().is_null()) {
-    SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info();
-    if (scope_info != SerializedScopeInfo::Empty()) {
-      Scope* scope = top;
-      JSFunction* current = *info->closure();
-      do {
-        current = current->context()->closure();
-        SerializedScopeInfo* scope_info = current->shared()->scope_info();
-        if (scope_info != SerializedScopeInfo::Empty()) {
-          scope = new Scope(scope, scope_info);
-        } else {
-          ASSERT(current->context()->IsGlobalContext());
-        }
-      } while (!current->context()->IsGlobalContext());
-    }
-  }
-
   while (top->outer_scope() != NULL) top = top->outer_scope();
   top->AllocateVariables(info->calling_context());
 
 #ifdef DEBUG
-  if (Bootstrapper::IsActive()
+  if (info->isolate()->bootstrapper()->IsActive()
           ? FLAG_print_builtin_scopes
           : FLAG_print_scopes) {
     info->function()->scope()->Print();
@@ -234,7 +250,7 @@
   // such parameter is 'this' which is passed on the stack when
   // invoking scripts
   Variable* var =
-      variables_.Declare(this, Factory::this_symbol(), Variable::VAR,
+      variables_.Declare(this, FACTORY->this_symbol(), Variable::VAR,
                          false, Variable::THIS);
   var->set_rewrite(new Slot(var, Slot::PARAMETER, -1));
   receiver_ = var;
@@ -243,7 +259,7 @@
     // Declare 'arguments' variable which exists in all functions.
     // Note that it might never be accessed, in which case it won't be
     // allocated during variable allocation.
-    variables_.Declare(this, Factory::arguments_symbol(), Variable::VAR,
+    variables_.Declare(this, FACTORY->arguments_symbol(), Variable::VAR,
                        true, Variable::ARGUMENTS);
   }
 }
@@ -258,7 +274,7 @@
 
   // We should never lookup 'arguments' in this scope
   // as it is implicitly present in any scope.
-  ASSERT(*name != *Factory::arguments_symbol());
+  ASSERT(*name != *FACTORY->arguments_symbol());
 
   // Assert that there is no local slot with the given name.
   ASSERT(scope_info_->StackSlotIndex(*name) < 0);
@@ -857,7 +873,7 @@
 
 bool Scope::HasArgumentsParameter() {
   for (int i = 0; i < params_.length(); i++) {
-    if (params_[i]->name().is_identical_to(Factory::arguments_symbol()))
+    if (params_[i]->name().is_identical_to(FACTORY->arguments_symbol()))
       return true;
   }
   return false;
@@ -876,8 +892,13 @@
 
 void Scope::AllocateParameterLocals() {
   ASSERT(is_function_scope());
-  Variable* arguments = LocalLookup(Factory::arguments_symbol());
+  Variable* arguments = LocalLookup(FACTORY->arguments_symbol());
   ASSERT(arguments != NULL);  // functions have 'arguments' declared implicitly
+
+  // Parameters are rewritten to arguments[i] if 'arguments' is used in
+  // a non-strict mode function. Strict mode code doesn't alias arguments.
+  bool rewrite_parameters = false;
+
   if (MustAllocate(arguments) && !HasArgumentsParameter()) {
     // 'arguments' is used. Unless there is also a parameter called
     // 'arguments', we must be conservative and access all parameters via
@@ -909,6 +930,13 @@
     // allocate the arguments object by setting 'arguments_'.
     arguments_ = arguments;
 
+    // In strict mode 'arguments' does not alias formal parameters.
+    // Therefore in strict mode we allocate parameters as if 'arguments'
+    // were not used.
+    rewrite_parameters = !is_strict_mode();
+  }
+
+  if (rewrite_parameters) {
     // 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
@@ -919,7 +947,7 @@
     // variable may be allocated in the heap-allocated context (temporaries
     // are never allocated in the context).
     arguments_shadow_ = new Variable(this,
-                                     Factory::arguments_shadow_symbol(),
+                                     FACTORY->arguments_shadow_symbol(),
                                      Variable::INTERNAL,
                                      true,
                                      Variable::ARGUMENTS);
@@ -985,7 +1013,7 @@
 void Scope::AllocateNonParameterLocal(Variable* var) {
   ASSERT(var->scope() == this);
   ASSERT(var->rewrite() == NULL ||
-         (!var->IsVariable(Factory::result_symbol())) ||
+         (!var->IsVariable(FACTORY->result_symbol())) ||
          (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL));
   if (var->rewrite() == NULL && MustAllocate(var)) {
     if (MustAllocateInContext(var)) {
diff --git a/src/scopes.h b/src/scopes.h
index a9220eb..24622b4 100644
--- a/src/scopes.h
+++ b/src/scopes.h
@@ -104,6 +104,9 @@
   // doesn't re-allocate variables repeatedly.
   static bool Analyze(CompilationInfo* info);
 
+  static Scope* DeserializeScopeChain(CompilationInfo* info,
+                                      Scope* innermost_scope);
+
   // The scope name is only used for printing/debugging.
   void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; }
 
@@ -193,6 +196,10 @@
   // Inform the scope that the corresponding code contains an eval call.
   void RecordEvalCall() { scope_calls_eval_ = true; }
 
+  // Enable strict mode for the scope (unless disabled by a global flag).
+  void EnableStrictMode() {
+    strict_mode_ = FLAG_strict_mode;
+  }
 
   // ---------------------------------------------------------------------------
   // Predicates.
@@ -201,6 +208,7 @@
   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; }
+  bool is_strict_mode() const { return strict_mode_; }
 
   // Information about which scopes calls eval.
   bool calls_eval() const { return scope_calls_eval_; }
@@ -220,7 +228,7 @@
   // A new variable proxy corresponding to the (function) receiver.
   VariableProxy* receiver() const {
     VariableProxy* proxy =
-        new VariableProxy(Factory::this_symbol(), true, false);
+        new VariableProxy(FACTORY->this_symbol(), true, false);
     proxy->BindTo(receiver_);
     return proxy;
   }
@@ -313,14 +321,6 @@
 
   explicit Scope(Type type);
 
-  void InsertAfterScope(Scope* scope) {
-    inner_scopes_.Add(scope);
-    outer_scope_ = scope->outer_scope_;
-    outer_scope_->inner_scopes_.RemoveElement(scope);
-    outer_scope_->inner_scopes_.Add(this);
-    scope->outer_scope_ = this;
-  }
-
   // Scope tree.
   Scope* outer_scope_;  // the immediately enclosing outer scope, or NULL
   ZoneList<Scope*> inner_scopes_;  // the immediately enclosed inner scopes
@@ -363,6 +363,7 @@
   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
+  bool strict_mode_;  // this scope is a strict mode scope
 
   // Computed via PropagateScopeInfo.
   bool outer_scope_calls_eval_;
@@ -413,12 +414,19 @@
  private:
   Scope(Scope* inner_scope, SerializedScopeInfo* scope_info);
 
+  void AddInnerScope(Scope* inner_scope) {
+    if (inner_scope != NULL) {
+      inner_scopes_.Add(inner_scope);
+      inner_scope->outer_scope_ = this;
+    }
+  }
+
   void SetDefaults(Type type,
                    Scope* outer_scope,
                    SerializedScopeInfo* scope_info) {
     outer_scope_ = outer_scope;
     type_ = type;
-    scope_name_ = Factory::empty_symbol();
+    scope_name_ = FACTORY->empty_symbol();
     dynamics_ = NULL;
     receiver_ = NULL;
     function_ = NULL;
@@ -428,6 +436,8 @@
     scope_inside_with_ = false;
     scope_contains_with_ = false;
     scope_calls_eval_ = false;
+    // Inherit the strict mode from the parent scope.
+    strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_;
     outer_scope_calls_eval_ = false;
     inner_scope_calls_eval_ = false;
     outer_scope_is_eval_scope_ = false;
diff --git a/src/serialize.cc b/src/serialize.cc
index f8e98d3..12e9613 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -38,7 +38,6 @@
 #include "serialize.h"
 #include "stub-cache.h"
 #include "v8threads.h"
-#include "top.h"
 #include "bootstrapper.h"
 
 namespace v8 {
@@ -68,9 +67,14 @@
 // hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder.
 class ExternalReferenceTable {
  public:
-  static ExternalReferenceTable* instance() {
-    if (!instance_) instance_ = new ExternalReferenceTable();
-    return instance_;
+  static ExternalReferenceTable* instance(Isolate* isolate) {
+    ExternalReferenceTable* external_reference_table =
+        isolate->external_reference_table();
+    if (external_reference_table == NULL) {
+      external_reference_table = new ExternalReferenceTable(isolate);
+      isolate->set_external_reference_table(external_reference_table);
+    }
+    return external_reference_table;
   }
 
   int size() const { return refs_.length(); }
@@ -84,9 +88,9 @@
   int max_id(int code) { return max_id_[code]; }
 
  private:
-  static ExternalReferenceTable* instance_;
-
-  ExternalReferenceTable() : refs_(64) { PopulateTable(); }
+  explicit ExternalReferenceTable(Isolate* isolate) : refs_(64) {
+      PopulateTable(isolate);
+  }
   ~ExternalReferenceTable() { }
 
   struct ExternalReferenceEntry {
@@ -95,10 +99,13 @@
     const char* name;
   };
 
-  void PopulateTable();
+  void PopulateTable(Isolate* isolate);
 
   // For a few types of references, we can get their address from their id.
-  void AddFromId(TypeCode type, uint16_t id, const char* name);
+  void AddFromId(TypeCode type,
+                 uint16_t id,
+                 const char* name,
+                 Isolate* isolate);
 
   // For other types of references, the caller will figure out the address.
   void Add(Address address, TypeCode type, uint16_t id, const char* name);
@@ -108,31 +115,30 @@
 };
 
 
-ExternalReferenceTable* ExternalReferenceTable::instance_ = NULL;
-
-
 void ExternalReferenceTable::AddFromId(TypeCode type,
                                        uint16_t id,
-                                       const char* name) {
+                                       const char* name,
+                                       Isolate* isolate) {
   Address address;
   switch (type) {
     case C_BUILTIN: {
-      ExternalReference ref(static_cast<Builtins::CFunctionId>(id));
+      ExternalReference ref(static_cast<Builtins::CFunctionId>(id), isolate);
       address = ref.address();
       break;
     }
     case BUILTIN: {
-      ExternalReference ref(static_cast<Builtins::Name>(id));
+      ExternalReference ref(static_cast<Builtins::Name>(id), isolate);
       address = ref.address();
       break;
     }
     case RUNTIME_FUNCTION: {
-      ExternalReference ref(static_cast<Runtime::FunctionId>(id));
+      ExternalReference ref(static_cast<Runtime::FunctionId>(id), isolate);
       address = ref.address();
       break;
     }
     case IC_UTILITY: {
-      ExternalReference ref(IC_Utility(static_cast<IC::UtilityId>(id)));
+      ExternalReference ref(IC_Utility(static_cast<IC::UtilityId>(id)),
+                            isolate);
       address = ref.address();
       break;
     }
@@ -159,7 +165,7 @@
 }
 
 
-void ExternalReferenceTable::PopulateTable() {
+void ExternalReferenceTable::PopulateTable(Isolate* isolate) {
   for (int type_code = 0; type_code < kTypeCodeCount; type_code++) {
     max_id_[type_code] = 0;
   }
@@ -190,7 +196,7 @@
 
 #define DEF_ENTRY_C(name, ignored) \
   { BUILTIN, \
-    Builtins::name, \
+    Builtins::k##name, \
     "Builtins::" #name },
 #define DEF_ENTRY_A(name, kind, state, extra) DEF_ENTRY_C(name, ignored)
 
@@ -220,24 +226,27 @@
   };  // 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);
+    AddFromId(ref_table[i].type,
+              ref_table[i].id,
+              ref_table[i].name,
+              isolate);
   }
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Debug addresses
-  Add(Debug_Address(Debug::k_after_break_target_address).address(),
+  Add(Debug_Address(Debug::k_after_break_target_address).address(isolate),
       DEBUG_ADDRESS,
       Debug::k_after_break_target_address << kDebugIdShift,
       "Debug::after_break_target_address()");
-  Add(Debug_Address(Debug::k_debug_break_slot_address).address(),
+  Add(Debug_Address(Debug::k_debug_break_slot_address).address(isolate),
       DEBUG_ADDRESS,
       Debug::k_debug_break_slot_address << kDebugIdShift,
       "Debug::debug_break_slot_address()");
-  Add(Debug_Address(Debug::k_debug_break_return_address).address(),
+  Add(Debug_Address(Debug::k_debug_break_return_address).address(isolate),
       DEBUG_ADDRESS,
       Debug::k_debug_break_return_address << kDebugIdShift,
       "Debug::debug_break_return_address()");
-  Add(Debug_Address(Debug::k_restarter_frame_function_pointer).address(),
+  Add(Debug_Address(Debug::k_restarter_frame_function_pointer).address(isolate),
       DEBUG_ADDRESS,
       Debug::k_restarter_frame_function_pointer << kDebugIdShift,
       "Debug::restarter_frame_function_pointer_address()");
@@ -245,14 +254,14 @@
 
   // Stat counters
   struct StatsRefTableEntry {
-    StatsCounter* counter;
+    StatsCounter* (Counters::*counter)();
     uint16_t id;
     const char* name;
   };
 
-  static const StatsRefTableEntry stats_ref_table[] = {
+  const StatsRefTableEntry stats_ref_table[] = {
 #define COUNTER_ENTRY(name, caption) \
-  { &Counters::name, \
+  { &Counters::name,    \
     Counters::k_##name, \
     "Counters::" #name },
 
@@ -261,33 +270,28 @@
 #undef COUNTER_ENTRY
   };  // end of stats_ref_table[].
 
+  Counters* counters = isolate->counters();
   for (size_t i = 0; i < ARRAY_SIZE(stats_ref_table); ++i) {
-    Add(reinterpret_cast<Address>(
-            GetInternalPointer(stats_ref_table[i].counter)),
+    Add(reinterpret_cast<Address>(GetInternalPointer(
+            (counters->*(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::%s";
 
   const char* AddressNames[] = {
-#define C(name) #name,
-    TOP_ADDRESS_LIST(C)
-    TOP_ADDRESS_LIST_PROF(C)
+#define C(name) "Isolate::" #name,
+    ISOLATE_ADDRESS_LIST(C)
+    ISOLATE_ADDRESS_LIST_PROF(C)
     NULL
 #undef C
   };
 
-  int top_format_length = StrLength(top_address_format) - 2;
-  for (uint16_t i = 0; i < Top::k_top_address_count; ++i) {
-    const char* address_name = AddressNames[i];
-    Vector<char> name =
-        Vector<char>::New(top_format_length + StrLength(address_name) + 1);
-    const char* chars = name.start();
-    OS::SNPrintF(name, top_address_format, address_name);
-    Add(Top::get_address_from_id((Top::AddressId)i), TOP_ADDRESS, i, chars);
+  for (uint16_t i = 0; i < Isolate::k_isolate_address_count; ++i) {
+    Add(isolate->get_address_from_id((Isolate::AddressId)i),
+        TOP_ADDRESS, i, AddressNames[i]);
   }
 
   // Accessors
@@ -300,143 +304,145 @@
   ACCESSOR_DESCRIPTOR_LIST(ACCESSOR_DESCRIPTOR_DECLARATION)
 #undef ACCESSOR_DESCRIPTOR_DECLARATION
 
+  StubCache* stub_cache = isolate->stub_cache();
+
   // Stub cache tables
-  Add(SCTableReference::keyReference(StubCache::kPrimary).address(),
+  Add(stub_cache->key_reference(StubCache::kPrimary).address(),
       STUB_CACHE_TABLE,
       1,
       "StubCache::primary_->key");
-  Add(SCTableReference::valueReference(StubCache::kPrimary).address(),
+  Add(stub_cache->value_reference(StubCache::kPrimary).address(),
       STUB_CACHE_TABLE,
       2,
       "StubCache::primary_->value");
-  Add(SCTableReference::keyReference(StubCache::kSecondary).address(),
+  Add(stub_cache->key_reference(StubCache::kSecondary).address(),
       STUB_CACHE_TABLE,
       3,
       "StubCache::secondary_->key");
-  Add(SCTableReference::valueReference(StubCache::kSecondary).address(),
+  Add(stub_cache->value_reference(StubCache::kSecondary).address(),
       STUB_CACHE_TABLE,
       4,
       "StubCache::secondary_->value");
 
   // Runtime entries
-  Add(ExternalReference::perform_gc_function().address(),
+  Add(ExternalReference::perform_gc_function(isolate).address(),
       RUNTIME_ENTRY,
       1,
       "Runtime::PerformGC");
-  Add(ExternalReference::fill_heap_number_with_random_function().address(),
+  Add(ExternalReference::fill_heap_number_with_random_function(
+          isolate).address(),
       RUNTIME_ENTRY,
       2,
       "V8::FillHeapNumberWithRandom");
-
-  Add(ExternalReference::random_uint32_function().address(),
+  Add(ExternalReference::random_uint32_function(isolate).address(),
       RUNTIME_ENTRY,
       3,
       "V8::Random");
-
-  Add(ExternalReference::delete_handle_scope_extensions().address(),
+  Add(ExternalReference::delete_handle_scope_extensions(isolate).address(),
       RUNTIME_ENTRY,
       4,
       "HandleScope::DeleteExtensions");
 
   // Miscellaneous
-  Add(ExternalReference::the_hole_value_location().address(),
+  Add(ExternalReference::the_hole_value_location(isolate).address(),
       UNCLASSIFIED,
       2,
       "Factory::the_hole_value().location()");
-  Add(ExternalReference::roots_address().address(),
+  Add(ExternalReference::roots_address(isolate).address(),
       UNCLASSIFIED,
       3,
       "Heap::roots_address()");
-  Add(ExternalReference::address_of_stack_limit().address(),
+  Add(ExternalReference::address_of_stack_limit(isolate).address(),
       UNCLASSIFIED,
       4,
       "StackGuard::address_of_jslimit()");
-  Add(ExternalReference::address_of_real_stack_limit().address(),
+  Add(ExternalReference::address_of_real_stack_limit(isolate).address(),
       UNCLASSIFIED,
       5,
       "StackGuard::address_of_real_jslimit()");
 #ifndef V8_INTERPRETED_REGEXP
-  Add(ExternalReference::address_of_regexp_stack_limit().address(),
+  Add(ExternalReference::address_of_regexp_stack_limit(isolate).address(),
       UNCLASSIFIED,
       6,
       "RegExpStack::limit_address()");
-  Add(ExternalReference::address_of_regexp_stack_memory_address().address(),
+  Add(ExternalReference::address_of_regexp_stack_memory_address(
+          isolate).address(),
       UNCLASSIFIED,
       7,
       "RegExpStack::memory_address()");
-  Add(ExternalReference::address_of_regexp_stack_memory_size().address(),
+  Add(ExternalReference::address_of_regexp_stack_memory_size(isolate).address(),
       UNCLASSIFIED,
       8,
       "RegExpStack::memory_size()");
-  Add(ExternalReference::address_of_static_offsets_vector().address(),
+  Add(ExternalReference::address_of_static_offsets_vector(isolate).address(),
       UNCLASSIFIED,
       9,
       "OffsetsVector::static_offsets_vector");
 #endif  // V8_INTERPRETED_REGEXP
-  Add(ExternalReference::new_space_start().address(),
+  Add(ExternalReference::new_space_start(isolate).address(),
       UNCLASSIFIED,
       10,
       "Heap::NewSpaceStart()");
-  Add(ExternalReference::new_space_mask().address(),
+  Add(ExternalReference::new_space_mask(isolate).address(),
       UNCLASSIFIED,
       11,
       "Heap::NewSpaceMask()");
-  Add(ExternalReference::heap_always_allocate_scope_depth().address(),
+  Add(ExternalReference::heap_always_allocate_scope_depth(isolate).address(),
       UNCLASSIFIED,
       12,
       "Heap::always_allocate_scope_depth()");
-  Add(ExternalReference::new_space_allocation_limit_address().address(),
+  Add(ExternalReference::new_space_allocation_limit_address(isolate).address(),
       UNCLASSIFIED,
       13,
       "Heap::NewSpaceAllocationLimitAddress()");
-  Add(ExternalReference::new_space_allocation_top_address().address(),
+  Add(ExternalReference::new_space_allocation_top_address(isolate).address(),
       UNCLASSIFIED,
       14,
       "Heap::NewSpaceAllocationTopAddress()");
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  Add(ExternalReference::debug_break().address(),
+  Add(ExternalReference::debug_break(isolate).address(),
       UNCLASSIFIED,
       15,
       "Debug::Break()");
-  Add(ExternalReference::debug_step_in_fp_address().address(),
+  Add(ExternalReference::debug_step_in_fp_address(isolate).address(),
       UNCLASSIFIED,
       16,
       "Debug::step_in_fp_addr()");
 #endif
-  Add(ExternalReference::double_fp_operation(Token::ADD).address(),
+  Add(ExternalReference::double_fp_operation(Token::ADD, isolate).address(),
       UNCLASSIFIED,
       17,
       "add_two_doubles");
-  Add(ExternalReference::double_fp_operation(Token::SUB).address(),
+  Add(ExternalReference::double_fp_operation(Token::SUB, isolate).address(),
       UNCLASSIFIED,
       18,
       "sub_two_doubles");
-  Add(ExternalReference::double_fp_operation(Token::MUL).address(),
+  Add(ExternalReference::double_fp_operation(Token::MUL, isolate).address(),
       UNCLASSIFIED,
       19,
       "mul_two_doubles");
-  Add(ExternalReference::double_fp_operation(Token::DIV).address(),
+  Add(ExternalReference::double_fp_operation(Token::DIV, isolate).address(),
       UNCLASSIFIED,
       20,
       "div_two_doubles");
-  Add(ExternalReference::double_fp_operation(Token::MOD).address(),
+  Add(ExternalReference::double_fp_operation(Token::MOD, isolate).address(),
       UNCLASSIFIED,
       21,
       "mod_two_doubles");
-  Add(ExternalReference::compare_doubles().address(),
+  Add(ExternalReference::compare_doubles(isolate).address(),
       UNCLASSIFIED,
       22,
       "compare_doubles");
 #ifndef V8_INTERPRETED_REGEXP
-  Add(ExternalReference::re_case_insensitive_compare_uc16().address(),
+  Add(ExternalReference::re_case_insensitive_compare_uc16(isolate).address(),
       UNCLASSIFIED,
       23,
       "NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()");
-  Add(ExternalReference::re_check_stack_guard_state().address(),
+  Add(ExternalReference::re_check_stack_guard_state(isolate).address(),
       UNCLASSIFIED,
       24,
       "RegExpMacroAssembler*::CheckStackGuardState()");
-  Add(ExternalReference::re_grow_stack().address(),
+  Add(ExternalReference::re_grow_stack(isolate).address(),
       UNCLASSIFIED,
       25,
       "NativeRegExpMacroAssembler::GrowStack()");
@@ -446,15 +452,15 @@
       "NativeRegExpMacroAssembler::word_character_map");
 #endif  // V8_INTERPRETED_REGEXP
   // Keyed lookup cache.
-  Add(ExternalReference::keyed_lookup_cache_keys().address(),
+  Add(ExternalReference::keyed_lookup_cache_keys(isolate).address(),
       UNCLASSIFIED,
       27,
       "KeyedLookupCache::keys()");
-  Add(ExternalReference::keyed_lookup_cache_field_offsets().address(),
+  Add(ExternalReference::keyed_lookup_cache_field_offsets(isolate).address(),
       UNCLASSIFIED,
       28,
       "KeyedLookupCache::field_offsets()");
-  Add(ExternalReference::transcendental_cache_array_address().address(),
+  Add(ExternalReference::transcendental_cache_array_address(isolate).address(),
       UNCLASSIFIED,
       29,
       "TranscendentalCache::caches()");
@@ -470,11 +476,11 @@
       UNCLASSIFIED,
       32,
       "HandleScope::level");
-  Add(ExternalReference::new_deoptimizer_function().address(),
+  Add(ExternalReference::new_deoptimizer_function(isolate).address(),
       UNCLASSIFIED,
       33,
       "Deoptimizer::New()");
-  Add(ExternalReference::compute_output_frames_function().address(),
+  Add(ExternalReference::compute_output_frames_function(isolate).address(),
       UNCLASSIFIED,
       34,
       "Deoptimizer::ComputeOutputFrames()");
@@ -486,33 +492,38 @@
       UNCLASSIFIED,
       36,
       "LDoubleConstant::one_half");
-  Add(ExternalReference::address_of_minus_zero().address(),
+  Add(ExternalReference::isolate_address().address(),
       UNCLASSIFIED,
       37,
+      "isolate");
+  Add(ExternalReference::address_of_minus_zero().address(),
+      UNCLASSIFIED,
+      38,
       "LDoubleConstant::minus_zero");
   Add(ExternalReference::address_of_negative_infinity().address(),
       UNCLASSIFIED,
-      38,
-      "LDoubleConstant::negative_infinity");
-  Add(ExternalReference::power_double_double_function().address(),
-      UNCLASSIFIED,
       39,
-      "power_double_double_function");
-  Add(ExternalReference::power_double_int_function().address(),
+      "LDoubleConstant::negative_infinity");
+  Add(ExternalReference::power_double_double_function(isolate).address(),
       UNCLASSIFIED,
       40,
-      "power_double_int_function");
-  Add(ExternalReference::arguments_marker_location().address(),
+      "power_double_double_function");
+  Add(ExternalReference::power_double_int_function(isolate).address(),
       UNCLASSIFIED,
       41,
+      "power_double_int_function");
+  Add(ExternalReference::arguments_marker_location(isolate).address(),
+      UNCLASSIFIED,
+      42,
       "Factory::arguments_marker().location()");
 }
 
 
 ExternalReferenceEncoder::ExternalReferenceEncoder()
-    : encodings_(Match) {
+    : encodings_(Match),
+      isolate_(Isolate::Current()) {
   ExternalReferenceTable* external_references =
-      ExternalReferenceTable::instance();
+      ExternalReferenceTable::instance(isolate_);
   for (int i = 0; i < external_references->size(); ++i) {
     Put(external_references->address(i), i);
   }
@@ -522,20 +533,22 @@
 uint32_t ExternalReferenceEncoder::Encode(Address key) const {
   int index = IndexOf(key);
   ASSERT(key == NULL || index >= 0);
-  return index >=0 ? ExternalReferenceTable::instance()->code(index) : 0;
+  return index >=0 ?
+         ExternalReferenceTable::instance(isolate_)->code(index) : 0;
 }
 
 
 const char* ExternalReferenceEncoder::NameOfAddress(Address key) const {
   int index = IndexOf(key);
-  return index >=0 ? ExternalReferenceTable::instance()->name(index) : NULL;
+  return index >= 0 ?
+      ExternalReferenceTable::instance(isolate_)->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);
+      const_cast<HashMap&>(encodings_).Lookup(key, Hash(key), false);
   return entry == NULL
       ? -1
       : static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
@@ -549,9 +562,10 @@
 
 
 ExternalReferenceDecoder::ExternalReferenceDecoder()
-    : encodings_(NewArray<Address*>(kTypeCodeCount)) {
+    : encodings_(NewArray<Address*>(kTypeCodeCount)),
+      isolate_(Isolate::Current()) {
   ExternalReferenceTable* external_references =
-      ExternalReferenceTable::instance();
+      ExternalReferenceTable::instance(isolate_);
   for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
     int max = external_references->max_id(type) + 1;
     encodings_[type] = NewArray<Address>(max + 1);
@@ -572,10 +586,12 @@
 
 bool Serializer::serialization_enabled_ = false;
 bool Serializer::too_late_to_enable_now_ = false;
-ExternalReferenceDecoder* Deserializer::external_reference_decoder_ = NULL;
 
 
-Deserializer::Deserializer(SnapshotByteSource* source) : source_(source) {
+Deserializer::Deserializer(SnapshotByteSource* source)
+    : isolate_(NULL),
+      source_(source),
+      external_reference_decoder_(NULL) {
 }
 
 
@@ -601,7 +617,6 @@
     high_water_[space_index] = address + size;
   } else {
     ASSERT(SpaceIsLarge(space_index));
-    ASSERT(size > Page::kPageSize - Page::kObjectStartOffset);
     LargeObjectSpace* lo_space = reinterpret_cast<LargeObjectSpace*>(space);
     Object* new_allocation;
     if (space_index == kLargeData) {
@@ -655,27 +670,31 @@
 
 
 void Deserializer::Deserialize() {
+  isolate_ = Isolate::Current();
   // Don't GC while deserializing - just expand the heap.
   AlwaysAllocateScope always_allocate;
   // Don't use the free lists while deserializing.
   LinearAllocationScope allocate_linearly;
   // No active threads.
-  ASSERT_EQ(NULL, ThreadState::FirstInUse());
+  ASSERT_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse());
   // No active handles.
-  ASSERT(HandleScopeImplementer::instance()->blocks()->is_empty());
+  ASSERT(isolate_->handle_scope_implementer()->blocks()->is_empty());
   // Make sure the entire partial snapshot cache is traversed, filling it with
   // valid object pointers.
-  partial_snapshot_cache_length_ = kPartialSnapshotCacheCapacity;
+  isolate_->set_serialize_partial_snapshot_cache_length(
+      Isolate::kPartialSnapshotCacheCapacity);
   ASSERT_EQ(NULL, external_reference_decoder_);
   external_reference_decoder_ = new ExternalReferenceDecoder();
-  Heap::IterateStrongRoots(this, VISIT_ONLY_STRONG);
-  Heap::IterateWeakRoots(this, VISIT_ALL);
+  isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
+  isolate_->heap()->IterateWeakRoots(this, VISIT_ALL);
 
-  Heap::set_global_contexts_list(Heap::undefined_value());
+  isolate_->heap()->set_global_contexts_list(
+      isolate_->heap()->undefined_value());
 }
 
 
 void Deserializer::DeserializePartial(Object** root) {
+  isolate_ = Isolate::Current();
   // Don't GC while deserializing - just expand the heap.
   AlwaysAllocateScope always_allocate;
   // Don't use the free lists while deserializing.
@@ -689,7 +708,7 @@
 
 Deserializer::~Deserializer() {
   ASSERT(source_->AtEOF());
-  if (external_reference_decoder_ != NULL) {
+  if (external_reference_decoder_) {
     delete external_reference_decoder_;
     external_reference_decoder_ = NULL;
   }
@@ -720,9 +739,14 @@
   Object** current = reinterpret_cast<Object**>(address);
   Object** limit = current + (size >> kPointerSizeLog2);
   if (FLAG_log_snapshot_positions) {
-    LOG(SnapshotPositionEvent(address, source_->position()));
+    LOG(isolate_, SnapshotPositionEvent(address, source_->position()));
   }
   ReadChunk(current, limit, space_number, address);
+#ifdef DEBUG
+  bool is_codespace = (space == HEAP->code_space()) ||
+      ((space == HEAP->lo_space()) && (space_number == kLargeCode));
+  ASSERT(HeapObject::FromAddress(address)->IsCode() == is_codespace);
+#endif
 }
 
 
@@ -732,20 +756,20 @@
 #define ASSIGN_DEST_SPACE(space_number)                                        \
   Space* dest_space;                                                           \
   if (space_number == NEW_SPACE) {                                             \
-    dest_space = Heap::new_space();                                            \
+    dest_space = isolate->heap()->new_space();                                \
   } else if (space_number == OLD_POINTER_SPACE) {                              \
-    dest_space = Heap::old_pointer_space();                                    \
+    dest_space = isolate->heap()->old_pointer_space();                         \
   } else if (space_number == OLD_DATA_SPACE) {                                 \
-    dest_space = Heap::old_data_space();                                       \
+    dest_space = isolate->heap()->old_data_space();                            \
   } else if (space_number == CODE_SPACE) {                                     \
-    dest_space = Heap::code_space();                                           \
+    dest_space = isolate->heap()->code_space();                                \
   } else if (space_number == MAP_SPACE) {                                      \
-    dest_space = Heap::map_space();                                            \
+    dest_space = isolate->heap()->map_space();                                 \
   } else if (space_number == CELL_SPACE) {                                     \
-    dest_space = Heap::cell_space();                                           \
+    dest_space = isolate->heap()->cell_space();                                \
   } else {                                                                     \
     ASSERT(space_number >= LO_SPACE);                                          \
-    dest_space = Heap::lo_space();                                             \
+    dest_space = isolate->heap()->lo_space();                                  \
   }
 
 
@@ -756,6 +780,7 @@
                              Object** limit,
                              int source_space,
                              Address address) {
+  Isolate* const isolate = isolate_;
   while (current < limit) {
     int data = source_->Get();
     switch (data) {
@@ -784,14 +809,15 @@
             ReadObject(space_number, dest_space, &new_object);                 \
           } else if (where == kRootArray) {                                    \
             int root_id = source_->GetInt();                                   \
-            new_object = Heap::roots_address()[root_id];                       \
+            new_object = isolate->heap()->roots_address()[root_id];            \
           } else if (where == kPartialSnapshotCache) {                         \
             int cache_index = source_->GetInt();                               \
-            new_object = partial_snapshot_cache_[cache_index];                 \
+            new_object = isolate->serialize_partial_snapshot_cache()           \
+                [cache_index];                                                 \
           } else if (where == kExternalReference) {                            \
             int reference_id = source_->GetInt();                              \
-            Address address =                                                  \
-                external_reference_decoder_->Decode(reference_id);             \
+            Address address = external_reference_decoder_->                    \
+                Decode(reference_id);                                          \
             new_object = reinterpret_cast<Object*>(address);                   \
           } else if (where == kBackref) {                                      \
             emit_write_barrier =                                               \
@@ -829,7 +855,7 @@
           }                                                                    \
         }                                                                      \
         if (emit_write_barrier) {                                              \
-          Heap::RecordWrite(address, static_cast<int>(                         \
+          isolate->heap()->RecordWrite(address, static_cast<int>(              \
               reinterpret_cast<Address>(current) - address));                  \
         }                                                                      \
         if (!current_was_incremented) {                                        \
@@ -878,7 +904,7 @@
   CASE_STATEMENT(where, how, within, CODE_SPACE)                               \
   CASE_BODY(where, how, within, CODE_SPACE, kUnknownOffsetFromStart)           \
   CASE_STATEMENT(where, how, within, kLargeCode)                               \
-  CASE_BODY(where, how, within, LO_SPACE, kUnknownOffsetFromStart)
+  CASE_BODY(where, how, within, kLargeCode, kUnknownOffsetFromStart)
 
 #define EMIT_COMMON_REFERENCE_PATTERNS(pseudo_space_number,                    \
                                        space_number,                           \
@@ -993,7 +1019,8 @@
         int index = source_->Get();
         Vector<const char> source_vector = Natives::GetScriptSource(index);
         NativesExternalStringResource* resource =
-            new NativesExternalStringResource(source_vector.start());
+            new NativesExternalStringResource(
+                isolate->bootstrapper(), source_vector.start());
         *current++ = reinterpret_cast<Object*>(resource);
         break;
       }
@@ -1058,6 +1085,9 @@
       current_root_index_(0),
       external_reference_encoder_(new ExternalReferenceEncoder),
       large_object_total_(0) {
+  // The serializer is meant to be used only to generate initial heap images
+  // from a context in which there is only one isolate.
+  ASSERT(Isolate::Current()->IsDefaultIsolate());
   for (int i = 0; i <= LAST_SPACE; i++) {
     fullness_[i] = 0;
   }
@@ -1070,35 +1100,40 @@
 
 
 void StartupSerializer::SerializeStrongReferences() {
+  Isolate* isolate = Isolate::Current();
   // No active threads.
-  CHECK_EQ(NULL, ThreadState::FirstInUse());
+  CHECK_EQ(NULL, Isolate::Current()->thread_manager()->FirstThreadStateInUse());
   // No active or weak handles.
-  CHECK(HandleScopeImplementer::instance()->blocks()->is_empty());
-  CHECK_EQ(0, GlobalHandles::NumberOfWeakHandles());
+  CHECK(isolate->handle_scope_implementer()->blocks()->is_empty());
+  CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles());
   // We don't support serializing installed extensions.
-  for (RegisteredExtension* ext = RegisteredExtension::first_extension();
+  for (RegisteredExtension* ext = v8::RegisteredExtension::first_extension();
        ext != NULL;
        ext = ext->next()) {
     CHECK_NE(v8::INSTALLED, ext->state());
   }
-  Heap::IterateStrongRoots(this, VISIT_ONLY_STRONG);
+  HEAP->IterateStrongRoots(this, VISIT_ONLY_STRONG);
 }
 
 
 void PartialSerializer::Serialize(Object** object) {
   this->VisitPointer(object);
+  Isolate* isolate = Isolate::Current();
 
   // After we have done the partial serialization the partial snapshot cache
   // will contain some references needed to decode the partial snapshot.  We
   // fill it up with undefineds so it has a predictable length so the
   // deserialization code doesn't need to know the length.
-  for (int index = partial_snapshot_cache_length_;
-       index < kPartialSnapshotCacheCapacity;
+  for (int index = isolate->serialize_partial_snapshot_cache_length();
+       index < Isolate::kPartialSnapshotCacheCapacity;
        index++) {
-    partial_snapshot_cache_[index] = Heap::undefined_value();
-    startup_serializer_->VisitPointer(&partial_snapshot_cache_[index]);
+    isolate->serialize_partial_snapshot_cache()[index] =
+        isolate->heap()->undefined_value();
+    startup_serializer_->VisitPointer(
+        &isolate->serialize_partial_snapshot_cache()[index]);
   }
-  partial_snapshot_cache_length_ = kPartialSnapshotCacheCapacity;
+  isolate->set_serialize_partial_snapshot_cache_length(
+      Isolate::kPartialSnapshotCacheCapacity);
 }
 
 
@@ -1117,11 +1152,6 @@
 }
 
 
-Object* SerializerDeserializer::partial_snapshot_cache_[
-    kPartialSnapshotCacheCapacity];
-int SerializerDeserializer::partial_snapshot_cache_length_ = 0;
-
-
 // This ensures that the partial snapshot cache keeps things alive during GC and
 // tracks their movement.  When it is called during serialization of the startup
 // snapshot the partial snapshot is empty, so nothing happens.  When the partial
@@ -1131,9 +1161,11 @@
 // deserialization we therefore need to visit the cache array.  This fills it up
 // with pointers to deserialized objects.
 void SerializerDeserializer::Iterate(ObjectVisitor* visitor) {
+  Isolate* isolate = Isolate::Current();
   visitor->VisitPointers(
-      &partial_snapshot_cache_[0],
-      &partial_snapshot_cache_[partial_snapshot_cache_length_]);
+      isolate->serialize_partial_snapshot_cache(),
+      &isolate->serialize_partial_snapshot_cache()[
+          isolate->serialize_partial_snapshot_cache_length()]);
 }
 
 
@@ -1141,33 +1173,39 @@
 // the root iteration code (above) will iterate over array elements, writing the
 // references to deserialized objects in them.
 void SerializerDeserializer::SetSnapshotCacheSize(int size) {
-  partial_snapshot_cache_length_ = size;
+  Isolate::Current()->set_serialize_partial_snapshot_cache_length(size);
 }
 
 
 int PartialSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) {
-  for (int i = 0; i < partial_snapshot_cache_length_; i++) {
-    Object* entry = partial_snapshot_cache_[i];
+  Isolate* isolate = Isolate::Current();
+
+  for (int i = 0;
+       i < isolate->serialize_partial_snapshot_cache_length();
+       i++) {
+    Object* entry = isolate->serialize_partial_snapshot_cache()[i];
     if (entry == heap_object) return i;
   }
 
   // We didn't find the object in the cache.  So we add it to the cache and
   // then visit the pointer so that it becomes part of the startup snapshot
   // and we can refer to it from the partial snapshot.
-  int length = partial_snapshot_cache_length_;
-  CHECK(length < kPartialSnapshotCacheCapacity);
-  partial_snapshot_cache_[length] = heap_object;
-  startup_serializer_->VisitPointer(&partial_snapshot_cache_[length]);
+  int length = isolate->serialize_partial_snapshot_cache_length();
+  CHECK(length < Isolate::kPartialSnapshotCacheCapacity);
+  isolate->serialize_partial_snapshot_cache()[length] = heap_object;
+  startup_serializer_->VisitPointer(
+      &isolate->serialize_partial_snapshot_cache()[length]);
   // We don't recurse from the startup snapshot generator into the partial
   // snapshot generator.
-  ASSERT(length == partial_snapshot_cache_length_);
-  return partial_snapshot_cache_length_++;
+  ASSERT(length == isolate->serialize_partial_snapshot_cache_length());
+  isolate->set_serialize_partial_snapshot_cache_length(length + 1);
+  return length;
 }
 
 
 int PartialSerializer::RootIndex(HeapObject* heap_object) {
   for (int i = 0; i < Heap::kRootListLength; i++) {
-    Object* root = Heap::roots_address()[i];
+    Object* root = HEAP->roots_address()[i];
     if (root == heap_object) return i;
   }
   return kInvalidRootIndex;
@@ -1250,13 +1288,13 @@
 
 
 void StartupSerializer::SerializeWeakReferences() {
-  for (int i = partial_snapshot_cache_length_;
-       i < kPartialSnapshotCacheCapacity;
+  for (int i = Isolate::Current()->serialize_partial_snapshot_cache_length();
+       i < Isolate::kPartialSnapshotCacheCapacity;
        i++) {
     sink_->Put(kRootArray + kPlain + kStartOfObject, "RootSerialization");
     sink_->PutInt(Heap::kUndefinedValueRootIndex, "root_index");
   }
-  Heap::IterateWeakRoots(this, VISIT_ALL);
+  HEAP->IterateWeakRoots(this, VISIT_ALL);
 }
 
 
@@ -1317,7 +1355,8 @@
              "ObjectSerialization");
   sink_->PutInt(size >> kObjectAlignmentBits, "Size in words");
 
-  LOG(SnapshotPositionEvent(object_->address(), sink_->Position()));
+  LOG(i::Isolate::Current(),
+      SnapshotPositionEvent(object_->address(), sink_->Position()));
 
   // Mark this object as already serialized.
   bool start_new_page;
@@ -1418,7 +1457,7 @@
   Address references_start = reinterpret_cast<Address>(resource_pointer);
   OutputRawData(references_start);
   for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
-    Object* source = Heap::natives_source_cache()->get(i);
+    Object* source = HEAP->natives_source_cache()->get(i);
     if (!source->IsUndefined()) {
       ExternalAsciiString* string = ExternalAsciiString::cast(source);
       typedef v8::String::ExternalAsciiStringResource Resource;
@@ -1468,7 +1507,7 @@
 int Serializer::SpaceOfObject(HeapObject* object) {
   for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) {
     AllocationSpace s = static_cast<AllocationSpace>(i);
-    if (Heap::InSpace(object, s)) {
+    if (HEAP->InSpace(object, s)) {
       if (i == LO_SPACE) {
         if (object->IsCode()) {
           return kLargeCode;
@@ -1489,7 +1528,7 @@
 int Serializer::SpaceOfAlreadySerializedObject(HeapObject* object) {
   for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) {
     AllocationSpace s = static_cast<AllocationSpace>(i);
-    if (Heap::InSpace(object, s)) {
+    if (HEAP->InSpace(object, s)) {
       return i;
     }
   }
diff --git a/src/serialize.h b/src/serialize.h
index e80c302..07c0a25 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -79,6 +79,8 @@
   static bool Match(void* key1, void* key2) { return key1 == key2; }
 
   void Put(Address key, int index);
+
+  Isolate* isolate_;
 };
 
 
@@ -105,6 +107,8 @@
   void Put(uint32_t key, Address value) {
     *Lookup(key) = value;
   }
+
+  Isolate* isolate_;
 };
 
 
@@ -144,7 +148,7 @@
 // This only works for objects in the first page of a space.  Don't use this for
 // things in newspace since it bypasses the write barrier.
 
-static const int k64 = (sizeof(uintptr_t) - 4) / 4;
+RLYSTC const int k64 = (sizeof(uintptr_t) - 4) / 4;
 
 #define COMMON_REFERENCE_PATTERNS(f)                               \
   f(kNumberOfSpaces, 2, (11 - k64))                                \
@@ -177,8 +181,8 @@
 // both.
 class SerializerDeserializer: public ObjectVisitor {
  public:
-  static void Iterate(ObjectVisitor* visitor);
-  static void SetSnapshotCacheSize(int size);
+  RLYSTC void Iterate(ObjectVisitor* visitor);
+  RLYSTC void SetSnapshotCacheSize(int size);
 
  protected:
   // Where the pointed-to object can be found:
@@ -216,40 +220,36 @@
 
   // Misc.
   // Raw data to be copied from the snapshot.
-  static const int kRawData = 0x30;
+  RLYSTC const int kRawData = 0x30;
   // Some common raw lengths: 0x31-0x3f
   // A tag emitted at strategic points in the snapshot to delineate sections.
   // If the deserializer does not find these at the expected moments then it
   // is an indication that the snapshot and the VM do not fit together.
   // Examine the build process for architecture, version or configuration
   // mismatches.
-  static const int kSynchronize = 0x70;
+  RLYSTC const int kSynchronize = 0x70;
   // Used for the source code of the natives, which is in the executable, but
   // is referred to from external strings in the snapshot.
-  static const int kNativesStringResource = 0x71;
-  static const int kNewPage = 0x72;
+  RLYSTC const int kNativesStringResource = 0x71;
+  RLYSTC const int kNewPage = 0x72;
   // 0x73-0x7f                            Free.
   // 0xb0-0xbf                            Free.
   // 0xf0-0xff                            Free.
 
 
-  static const int kLargeData = LAST_SPACE;
-  static const int kLargeCode = kLargeData + 1;
-  static const int kLargeFixedArray = kLargeCode + 1;
-  static const int kNumberOfSpaces = kLargeFixedArray + 1;
-  static const int kAnyOldSpace = -1;
+  RLYSTC const int kLargeData = LAST_SPACE;
+  RLYSTC const int kLargeCode = kLargeData + 1;
+  RLYSTC const int kLargeFixedArray = kLargeCode + 1;
+  RLYSTC const int kNumberOfSpaces = kLargeFixedArray + 1;
+  RLYSTC const int kAnyOldSpace = -1;
 
   // A bitmask for getting the space out of an instruction.
-  static const int kSpaceMask = 15;
+  RLYSTC const int kSpaceMask = 15;
 
-  static inline bool SpaceIsLarge(int space) { return space >= kLargeData; }
-  static inline bool SpaceIsPaged(int space) {
+  RLYSTC inline bool SpaceIsLarge(int space) { return space >= kLargeData; }
+  RLYSTC inline bool SpaceIsPaged(int space) {
     return space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE;
   }
-
-  static int partial_snapshot_cache_length_;
-  static const int kPartialSnapshotCacheCapacity = 1400;
-  static Object* partial_snapshot_cache_[];
 };
 
 
@@ -313,6 +313,9 @@
   Address Allocate(int space_number, Space* space, int size);
   void ReadObject(int space_number, Space* space, Object** write_back);
 
+  // Cached current isolate.
+  Isolate* isolate_;
+
   // Keep track of the pages in the paged spaces.
   // (In large object space we are keeping track of individual objects
   // rather than pages.)  In new space we just need the address of the
@@ -320,7 +323,6 @@
   List<Address> pages_[SerializerDeserializer::kNumberOfSpaces];
 
   SnapshotByteSource* source_;
-  static ExternalReferenceDecoder* external_reference_decoder_;
   // This is the address of the next object that will be allocated in each
   // space.  It is used to calculate the addresses of back-references.
   Address high_water_[LAST_SPACE + 1];
@@ -329,6 +331,8 @@
   // START_NEW_PAGE_SERIALIZATION tag.
   Address last_object_address_;
 
+  ExternalReferenceDecoder* external_reference_decoder_;
+
   DISALLOW_COPY_AND_ASSIGN(Deserializer);
 };
 
@@ -376,19 +380,19 @@
   }
 
  private:
-  static bool SerializationMatchFun(void* key1, void* key2) {
+  RLYSTC bool SerializationMatchFun(void* key1, void* key2) {
     return key1 == key2;
   }
 
-  static uint32_t Hash(HeapObject* obj) {
+  RLYSTC uint32_t Hash(HeapObject* obj) {
     return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
   }
 
-  static void* Key(HeapObject* obj) {
+  RLYSTC void* Key(HeapObject* obj) {
     return reinterpret_cast<void*>(obj->address());
   }
 
-  static void* Value(int v) {
+  RLYSTC void* Value(int v) {
     return reinterpret_cast<void*>(v);
   }
 
@@ -398,7 +402,8 @@
 };
 
 
-class Serializer : public SerializerDeserializer {
+// There can be only one serializer per V8 process.
+STATIC_CLASS Serializer : public SerializerDeserializer {
  public:
   explicit Serializer(SnapshotByteSink* sink);
   ~Serializer();
@@ -410,25 +415,25 @@
     return fullness_[space];
   }
 
-  static void Enable() {
+  RLYSTC void Enable() {
     if (!serialization_enabled_) {
       ASSERT(!too_late_to_enable_now_);
     }
     serialization_enabled_ = true;
   }
 
-  static void Disable() { serialization_enabled_ = false; }
+  RLYSTC void Disable() { serialization_enabled_ = false; }
   // Call this when you have made use of the fact that there is no serialization
   // going on.
-  static void TooLateToEnableNow() { too_late_to_enable_now_ = true; }
-  static bool enabled() { return serialization_enabled_; }
+  RLYSTC void TooLateToEnableNow() { too_late_to_enable_now_ = true; }
+  RLYSTC bool enabled() { return serialization_enabled_; }
   SerializationAddressMapper* address_mapper() { return &address_mapper_; }
 #ifdef DEBUG
   virtual void Synchronize(const char* tag);
 #endif
 
  protected:
-  static const int kInvalidRootIndex = -1;
+  RLYSTC const int kInvalidRootIndex = -1;
   virtual int RootIndex(HeapObject* heap_object) = 0;
   virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) = 0;
 
@@ -483,11 +488,11 @@
   // object space it may return kLargeCode or kLargeFixedArray in order
   // to indicate to the deserializer what kind of large object allocation
   // to make.
-  static int SpaceOfObject(HeapObject* object);
+  RLYSTC int SpaceOfObject(HeapObject* object);
   // This just returns the space of the object.  It will return LO_SPACE
   // for all large objects since you can't check the type of the object
   // once the map has been used for the serialization address.
-  static int SpaceOfAlreadySerializedObject(HeapObject* object);
+  RLYSTC int SpaceOfAlreadySerializedObject(HeapObject* object);
   int Allocate(int space, int size, bool* new_page_started);
   int EncodeExternalReference(Address addr) {
     return external_reference_encoder_->Encode(addr);
@@ -501,9 +506,9 @@
   SnapshotByteSink* sink_;
   int current_root_index_;
   ExternalReferenceEncoder* external_reference_encoder_;
-  static bool serialization_enabled_;
+  RLYSTC bool serialization_enabled_;
   // Did we already make use of the fact that serialization was not enabled?
-  static bool too_late_to_enable_now_;
+  RLYSTC bool too_late_to_enable_now_;
   int large_object_total_;
   SerializationAddressMapper address_mapper_;
 
@@ -539,7 +544,7 @@
     ASSERT(!o->IsScript());
     return o->IsString() || o->IsSharedFunctionInfo() ||
            o->IsHeapNumber() || o->IsCode() ||
-           o->map() == Heap::fixed_cow_array_map();
+           o->map() == HEAP->fixed_cow_array_map();
   }
 
  private:
@@ -555,7 +560,7 @@
     // strong roots have been serialized we can create a partial snapshot
     // which will repopulate the cache with objects neede by that partial
     // snapshot.
-    partial_snapshot_cache_length_ = 0;
+    Isolate::Current()->set_serialize_partial_snapshot_cache_length(0);
   }
   // Serialize the current state of the heap.  The order is:
   // 1) Strong references.
diff --git a/src/small-pointer-list.h b/src/small-pointer-list.h
new file mode 100644
index 0000000..6291d9e
--- /dev/null
+++ b/src/small-pointer-list.h
@@ -0,0 +1,163 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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_SMALL_POINTER_LIST_H_
+#define V8_SMALL_POINTER_LIST_H_
+
+#include "checks.h"
+#include "v8globals.h"
+#include "zone.h"
+
+namespace v8 {
+namespace internal {
+
+// SmallPointerList is a list optimized for storing no or just a
+// single value. When more values are given it falls back to ZoneList.
+//
+// The interface tries to be as close to List from list.h as possible.
+template <typename T>
+class SmallPointerList {
+ public:
+  SmallPointerList() : data_(kEmptyTag) {}
+
+  bool is_empty() const { return length() == 0; }
+
+  int length() const {
+    if ((data_ & kTagMask) == kEmptyTag) return 0;
+    if ((data_ & kTagMask) == kSingletonTag) return 1;
+    return list()->length();
+  }
+
+  void Add(T* pointer) {
+    ASSERT(IsAligned(reinterpret_cast<intptr_t>(pointer), kPointerAlignment));
+    if ((data_ & kTagMask) == kEmptyTag) {
+      data_ = reinterpret_cast<intptr_t>(pointer) | kSingletonTag;
+      return;
+    }
+    if ((data_ & kTagMask) == kSingletonTag) {
+      PointerList* list = new PointerList(2);
+      list->Add(single_value());
+      list->Add(pointer);
+      ASSERT(IsAligned(reinterpret_cast<intptr_t>(list), kPointerAlignment));
+      data_ = reinterpret_cast<intptr_t>(list) | kListTag;
+      return;
+    }
+    list()->Add(pointer);
+  }
+
+  // Note: returns T* and not T*& (unlike List from list.h).
+  // This makes the implementation simpler and more const correct.
+  T* at(int i) const {
+    ASSERT((data_ & kTagMask) != kEmptyTag);
+    if ((data_ & kTagMask) == kSingletonTag) {
+      ASSERT(i == 0);
+      return single_value();
+    }
+    return list()->at(i);
+  }
+
+  // See the note above.
+  T* operator[](int i) const { return at(i); }
+
+  // Remove the given element from the list (if present).
+  void RemoveElement(T* pointer) {
+    if ((data_ & kTagMask) == kEmptyTag) return;
+    if ((data_ & kTagMask) == kSingletonTag) {
+      if (pointer == single_value()) {
+        data_ = kEmptyTag;
+      }
+      return;
+    }
+    list()->RemoveElement(pointer);
+  }
+
+  T* RemoveLast() {
+    ASSERT((data_ & kTagMask) != kEmptyTag);
+    if ((data_ & kTagMask) == kSingletonTag) {
+      T* result = single_value();
+      data_ = kEmptyTag;
+      return result;
+    }
+    return list()->RemoveLast();
+  }
+
+  void Rewind(int pos) {
+    if ((data_ & kTagMask) == kEmptyTag) {
+      ASSERT(pos == 0);
+      return;
+    }
+    if ((data_ & kTagMask) == kSingletonTag) {
+      ASSERT(pos == 0 || pos == 1);
+      if (pos == 0) {
+        data_ = kEmptyTag;
+      }
+      return;
+    }
+    list()->Rewind(pos);
+  }
+
+  int CountOccurrences(T* pointer, int start, int end) const {
+    if ((data_ & kTagMask) == kEmptyTag) return 0;
+    if ((data_ & kTagMask) == kSingletonTag) {
+      if (start == 0 && end >= 0) {
+        return (single_value() == pointer) ? 1 : 0;
+      }
+      return 0;
+    }
+    return list()->CountOccurrences(pointer, start, end);
+  }
+
+ private:
+  typedef ZoneList<T*> PointerList;
+
+  static const intptr_t kEmptyTag = 1;
+  static const intptr_t kSingletonTag = 0;
+  static const intptr_t kListTag = 2;
+  static const intptr_t kTagMask = 3;
+  static const intptr_t kValueMask = ~kTagMask;
+
+  STATIC_ASSERT(kTagMask + 1 <= kPointerAlignment);
+
+  T* single_value() const {
+    ASSERT((data_ & kTagMask) == kSingletonTag);
+    STATIC_ASSERT(kSingletonTag == 0);
+    return reinterpret_cast<T*>(data_);
+  }
+
+  PointerList* list() const {
+    ASSERT((data_ & kTagMask) == kListTag);
+    return reinterpret_cast<PointerList*>(data_ & kValueMask);
+  }
+
+  intptr_t data_;
+
+  DISALLOW_COPY_AND_ASSIGN(SmallPointerList);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_SMALL_POINTER_LIST_H_
diff --git a/src/snapshot-common.cc b/src/snapshot-common.cc
index f1106e1..7f82895 100644
--- a/src/snapshot-common.cc
+++ b/src/snapshot-common.cc
@@ -64,7 +64,7 @@
   if (context_size_ == 0) {
     return Handle<Context>();
   }
-  Heap::ReserveSpace(new_space_used_,
+  HEAP->ReserveSpace(new_space_used_,
                      pointer_space_used_,
                      data_space_used_,
                      code_space_used_,
diff --git a/src/snapshot.h b/src/snapshot.h
index 9f77c20..bedd186 100644
--- a/src/snapshot.h
+++ b/src/snapshot.h
@@ -25,13 +25,15 @@
 // (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 "isolate.h"
+
 #ifndef V8_SNAPSHOT_H_
 #define V8_SNAPSHOT_H_
 
 namespace v8 {
 namespace internal {
 
-class Snapshot {
+STATIC_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
diff --git a/src/spaces-inl.h b/src/spaces-inl.h
index b5ee1e4..070f970 100644
--- a/src/spaces-inl.h
+++ b/src/spaces-inl.h
@@ -28,8 +28,9 @@
 #ifndef V8_SPACES_INL_H_
 #define V8_SPACES_INL_H_
 
-#include "memory.h"
+#include "isolate.h"
 #include "spaces.h"
+#include "v8memory.h"
 
 namespace v8 {
 namespace internal {
@@ -56,18 +57,18 @@
 // Page
 
 Page* Page::next_page() {
-  return MemoryAllocator::GetNextPage(this);
+  return heap_->isolate()->memory_allocator()->GetNextPage(this);
 }
 
 
 Address Page::AllocationTop() {
-  PagedSpace* owner = MemoryAllocator::PageOwner(this);
+  PagedSpace* owner = heap_->isolate()->memory_allocator()->PageOwner(this);
   return owner->PageAllocationTop(this);
 }
 
 
 Address Page::AllocationWatermark() {
-  PagedSpace* owner = MemoryAllocator::PageOwner(this);
+  PagedSpace* owner = heap_->isolate()->memory_allocator()->PageOwner(this);
   if (this == owner->AllocationTopPage()) {
     return owner->top();
   }
@@ -82,7 +83,7 @@
 
 
 void Page::SetAllocationWatermark(Address allocation_watermark) {
-  if ((Heap::gc_state() == Heap::SCAVENGE) && IsWatermarkValid()) {
+  if ((heap_->gc_state() == Heap::SCAVENGE) && IsWatermarkValid()) {
     // When iterating intergenerational references during scavenge
     // we might decide to promote an encountered young object.
     // We will allocate a space for such an object and put it
@@ -219,23 +220,26 @@
 }
 
 
-void Page::FlipMeaningOfInvalidatedWatermarkFlag() {
-  watermark_invalidated_mark_ ^= 1 << WATERMARK_INVALIDATED;
+void Page::FlipMeaningOfInvalidatedWatermarkFlag(Heap* heap) {
+  heap->page_watermark_invalidated_mark_ ^= 1 << WATERMARK_INVALIDATED;
 }
 
 
 bool Page::IsWatermarkValid() {
-  return (flags_ & (1 << WATERMARK_INVALIDATED)) != watermark_invalidated_mark_;
+  return (flags_ & (1 << WATERMARK_INVALIDATED)) !=
+      heap_->page_watermark_invalidated_mark_;
 }
 
 
 void Page::InvalidateWatermark(bool value) {
   if (value) {
     flags_ = (flags_ & ~(1 << WATERMARK_INVALIDATED)) |
-             watermark_invalidated_mark_;
+             heap_->page_watermark_invalidated_mark_;
   } else {
-    flags_ = (flags_ & ~(1 << WATERMARK_INVALIDATED)) |
-             (watermark_invalidated_mark_ ^ (1 << WATERMARK_INVALIDATED));
+    flags_ =
+        (flags_ & ~(1 << WATERMARK_INVALIDATED)) |
+        (heap_->page_watermark_invalidated_mark_ ^
+         (1 << WATERMARK_INVALIDATED));
   }
 
   ASSERT(IsWatermarkValid() == !value);
@@ -264,7 +268,7 @@
 void Page::ClearGCFields() {
   InvalidateWatermark(true);
   SetAllocationWatermark(ObjectAreaStart());
-  if (Heap::gc_state() == Heap::SCAVENGE) {
+  if (heap_->gc_state() == Heap::SCAVENGE) {
     SetCachedAllocationWatermark(ObjectAreaStart());
   }
   SetRegionMarks(kAllRegionsCleanMarks);
@@ -308,6 +312,7 @@
   size_ = s;
   owner_ = o;
   executable_ = (o == NULL) ? NOT_EXECUTABLE : o->executable();
+  owner_identity_ = (o == NULL) ? FIRST_SPACE : o->identity();
 }
 
 
@@ -408,15 +413,7 @@
 bool PagedSpace::Contains(Address addr) {
   Page* p = Page::FromAddress(addr);
   if (!p->is_valid()) return false;
-  return MemoryAllocator::IsPageInSpace(p, this);
-}
-
-
-bool PagedSpace::SafeContains(Address addr) {
-  if (!MemoryAllocator::SafeIsInAPageChunk(addr)) return false;
-  Page* p = Page::FromAddress(addr);
-  if (!p->is_valid()) return false;
-  return MemoryAllocator::IsPageInSpace(p, this);
+  return heap()->isolate()->memory_allocator()->IsPageInSpace(p, this);
 }
 
 
@@ -477,7 +474,9 @@
 
 
 void LargeObjectChunk::Free(Executability executable) {
-  MemoryAllocator::FreeRawMemory(address(), size(), executable);
+  Isolate* isolate =
+      Page::FromAddress(RoundUp(address(), Page::kPageSize))->heap_->isolate();
+  isolate->memory_allocator()->FreeRawMemory(address(), size(), executable);
 }
 
 // -----------------------------------------------------------------------------
@@ -501,6 +500,12 @@
 }
 
 
+intptr_t LargeObjectSpace::Available() {
+  return LargeObjectChunk::ObjectSizeFor(
+      heap()->isolate()->memory_allocator()->Available());
+}
+
+
 template <typename StringType>
 void NewSpace::ShrinkStringAtAllocationBoundary(String* string, int length) {
   ASSERT(length <= string->length());
@@ -514,9 +519,9 @@
 
 
 bool FreeListNode::IsFreeListNode(HeapObject* object) {
-  return object->map() == Heap::raw_unchecked_byte_array_map()
-      || object->map() == Heap::raw_unchecked_one_pointer_filler_map()
-      || object->map() == Heap::raw_unchecked_two_pointer_filler_map();
+  return object->map() == HEAP->raw_unchecked_byte_array_map()
+      || object->map() == HEAP->raw_unchecked_one_pointer_filler_map()
+      || object->map() == HEAP->raw_unchecked_two_pointer_filler_map();
 }
 
 } }  // namespace v8::internal
diff --git a/src/spaces.cc b/src/spaces.cc
index a586fbf..20700e1 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -42,8 +42,6 @@
          && (info).top <= (space).high()              \
          && (info).limit == (space).high())
 
-intptr_t Page::watermark_invalidated_mark_ = 1 << Page::WATERMARK_INVALIDATED;
-
 // ----------------------------------------------------------------------------
 // HeapObjectIterator
 
@@ -149,10 +147,14 @@
 // -----------------------------------------------------------------------------
 // CodeRange
 
-List<CodeRange::FreeBlock> CodeRange::free_list_(0);
-List<CodeRange::FreeBlock> CodeRange::allocation_list_(0);
-int CodeRange::current_allocation_block_index_ = 0;
-VirtualMemory* CodeRange::code_range_ = NULL;
+
+CodeRange::CodeRange()
+    : code_range_(NULL),
+      free_list_(0),
+      allocation_list_(0),
+      current_allocation_block_index_(0),
+      isolate_(NULL) {
+}
 
 
 bool CodeRange::Setup(const size_t requested) {
@@ -168,7 +170,7 @@
 
   // We are sure that we have mapped a block of requested addresses.
   ASSERT(code_range_->size() == requested);
-  LOG(NewEvent("CodeRange", code_range_->address(), requested));
+  LOG(isolate_, NewEvent("CodeRange", code_range_->address(), requested));
   allocation_list_.Add(FreeBlock(code_range_->address(), code_range_->size()));
   current_allocation_block_index_ = 0;
   return true;
@@ -271,24 +273,24 @@
 // -----------------------------------------------------------------------------
 // MemoryAllocator
 //
-intptr_t MemoryAllocator::capacity_ = 0;
-intptr_t MemoryAllocator::capacity_executable_ = 0;
-intptr_t MemoryAllocator::size_ = 0;
-intptr_t MemoryAllocator::size_executable_ = 0;
-
-List<MemoryAllocator::MemoryAllocationCallbackRegistration>
-  MemoryAllocator::memory_allocation_callbacks_;
-
-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;
+
+
+MemoryAllocator::MemoryAllocator()
+    : capacity_(0),
+      capacity_executable_(0),
+      size_(0),
+      size_executable_(0),
+      initial_chunk_(NULL),
+      chunks_(kEstimatedNumberOfChunks),
+      free_chunk_ids_(kEstimatedNumberOfChunks),
+      max_nof_chunks_(0),
+      top_(0),
+      isolate_(NULL) {
+}
 
 
 void MemoryAllocator::Push(int free_chunk_id) {
@@ -334,11 +336,6 @@
 }
 
 
-bool MemoryAllocator::SafeIsInAPageChunk(Address addr) {
-  return InInitialChunk(addr) || InAllocatedChunks(addr);
-}
-
-
 void MemoryAllocator::TearDown() {
   for (int i = 0; i < max_nof_chunks_; i++) {
     if (chunks_[i].address() != NULL) DeleteChunk(i);
@@ -347,15 +344,11 @@
   free_chunk_ids_.Clear();
 
   if (initial_chunk_ != NULL) {
-    LOG(DeleteEvent("InitialChunk", initial_chunk_->address()));
+    LOG(isolate_, DeleteEvent("InitialChunk", initial_chunk_->address()));
     delete initial_chunk_;
     initial_chunk_ = NULL;
   }
 
-  FreeChunkTables(&chunk_table_[0],
-                  kChunkTableTopLevelEntries,
-                  kChunkTableLevels);
-
   ASSERT(top_ == max_nof_chunks_);  // all chunks are free
   top_ = 0;
   capacity_ = 0;
@@ -365,22 +358,6 @@
 }
 
 
-void MemoryAllocator::FreeChunkTables(uintptr_t* array, int len, int level) {
-  for (int i = 0; i < len; i++) {
-    if (array[i] != kUnusedChunkTableEntry) {
-      uintptr_t* subarray = reinterpret_cast<uintptr_t*>(array[i]);
-      if (level > 1) {
-        array[i] = kUnusedChunkTableEntry;
-        FreeChunkTables(subarray, 1 << kChunkTableBitsPerLevel, level - 1);
-      } else {
-        array[i] = kUnusedChunkTableEntry;
-      }
-      delete[] subarray;
-    }
-  }
-}
-
-
 void* MemoryAllocator::AllocateRawMemory(const size_t requested,
                                          size_t* allocated,
                                          Executability executable) {
@@ -393,14 +370,15 @@
     // Check executable memory limit.
     if (size_executable_ + requested >
         static_cast<size_t>(capacity_executable_)) {
-      LOG(StringEvent("MemoryAllocator::AllocateRawMemory",
+      LOG(isolate_,
+          StringEvent("MemoryAllocator::AllocateRawMemory",
                       "V8 Executable Allocation capacity exceeded"));
       return NULL;
     }
     // Allocate executable memory either from code range or from the
     // OS.
-    if (CodeRange::exists()) {
-      mem = CodeRange::AllocateRawMemory(requested, allocated);
+    if (isolate_->code_range()->exists()) {
+      mem = isolate_->code_range()->AllocateRawMemory(requested, allocated);
     } else {
       mem = OS::Allocate(requested, allocated, true);
     }
@@ -415,7 +393,7 @@
 #ifdef DEBUG
   ZapBlock(reinterpret_cast<Address>(mem), alloced);
 #endif
-  Counters::memory_allocated.Increment(alloced);
+  isolate_->counters()->memory_allocated()->Increment(alloced);
   return mem;
 }
 
@@ -426,12 +404,12 @@
 #ifdef DEBUG
   ZapBlock(reinterpret_cast<Address>(mem), length);
 #endif
-  if (CodeRange::contains(static_cast<Address>(mem))) {
-    CodeRange::FreeRawMemory(mem, length);
+  if (isolate_->code_range()->contains(static_cast<Address>(mem))) {
+    isolate_->code_range()->FreeRawMemory(mem, length);
   } else {
     OS::Free(mem, length);
   }
-  Counters::memory_allocated.Decrement(static_cast<int>(length));
+  isolate_->counters()->memory_allocated()->Decrement(static_cast<int>(length));
   size_ -= static_cast<int>(length);
   if (executable == EXECUTABLE) size_executable_ -= static_cast<int>(length);
 
@@ -498,7 +476,8 @@
 
   // We are sure that we have mapped a block of requested addresses.
   ASSERT(initial_chunk_->size() == requested);
-  LOG(NewEvent("InitialChunk", initial_chunk_->address(), requested));
+  LOG(isolate_,
+      NewEvent("InitialChunk", initial_chunk_->address(), requested));
   size_ += static_cast<int>(requested);
   return initial_chunk_->address();
 }
@@ -522,14 +501,14 @@
 
   void* chunk = AllocateRawMemory(chunk_size, &chunk_size, owner->executable());
   if (chunk == NULL) return Page::FromAddress(NULL);
-  LOG(NewEvent("PagedChunk", chunk, chunk_size));
+  LOG(isolate_, NewEvent("PagedChunk", chunk, chunk_size));
 
   *allocated_pages = PagesInChunk(static_cast<Address>(chunk), chunk_size);
   // We may 'lose' a page due to alignment.
   ASSERT(*allocated_pages >= kPagesPerChunk - 1);
   if (*allocated_pages == 0) {
     FreeRawMemory(chunk, chunk_size, owner->executable());
-    LOG(DeleteEvent("PagedChunk", chunk));
+    LOG(isolate_, DeleteEvent("PagedChunk", chunk));
     return Page::FromAddress(NULL);
   }
 
@@ -540,8 +519,6 @@
   PerformAllocationCallback(space, kAllocationActionAllocate, chunk_size);
   Page* new_pages = InitializePagesInChunk(chunk_id, *allocated_pages, owner);
 
-  AddToAllocatedChunks(static_cast<Address>(chunk), chunk_size);
-
   return new_pages;
 }
 
@@ -560,7 +537,7 @@
 #ifdef DEBUG
   ZapBlock(start, size);
 #endif
-  Counters::memory_allocated.Increment(static_cast<int>(size));
+  isolate_->counters()->memory_allocated()->Increment(static_cast<int>(size));
 
   // So long as we correctly overestimated the number of chunks we should not
   // run out of chunk ids.
@@ -584,7 +561,7 @@
 #ifdef DEBUG
   ZapBlock(start, size);
 #endif
-  Counters::memory_allocated.Increment(static_cast<int>(size));
+  isolate_->counters()->memory_allocated()->Increment(static_cast<int>(size));
   return true;
 }
 
@@ -597,7 +574,7 @@
   ASSERT(InInitialChunk(start + size - 1));
 
   if (!initial_chunk_->Uncommit(start, size)) return false;
-  Counters::memory_allocated.Decrement(static_cast<int>(size));
+  isolate_->counters()->memory_allocated()->Decrement(static_cast<int>(size));
   return true;
 }
 
@@ -628,6 +605,7 @@
   Address page_addr = low;
   for (int i = 0; i < pages_in_chunk; i++) {
     Page* p = Page::FromAddress(page_addr);
+    p->heap_ = owner->heap();
     p->opaque_header = OffsetFrom(page_addr + Page::kPageSize) | chunk_id;
     p->InvalidateWatermark(true);
     p->SetIsLargeObjectPage(false);
@@ -697,11 +675,11 @@
     // TODO(1240712): VirtualMemory::Uncommit has a return value which
     // is ignored here.
     initial_chunk_->Uncommit(c.address(), c.size());
-    Counters::memory_allocated.Decrement(static_cast<int>(c.size()));
+    Counters* counters = isolate_->counters();
+    counters->memory_allocated()->Decrement(static_cast<int>(c.size()));
   } else {
-    RemoveFromAllocatedChunks(c.address(), c.size());
-    LOG(DeleteEvent("PagedChunk", c.address()));
-    ObjectSpace space = static_cast<ObjectSpace>(1 << c.owner()->identity());
+    LOG(isolate_, DeleteEvent("PagedChunk", c.address()));
+    ObjectSpace space = static_cast<ObjectSpace>(1 << c.owner_identity());
     size_t size = c.size();
     FreeRawMemory(c.address(), size, c.executable());
     PerformAllocationCallback(space, kAllocationActionFree, size);
@@ -813,131 +791,14 @@
 }
 
 
-void MemoryAllocator::AddToAllocatedChunks(Address addr, intptr_t size) {
-  ASSERT(size == kChunkSize);
-  uintptr_t int_address = reinterpret_cast<uintptr_t>(addr);
-  AddChunkUsingAddress(int_address, int_address);
-  AddChunkUsingAddress(int_address, int_address + size - 1);
-}
-
-
-void MemoryAllocator::AddChunkUsingAddress(uintptr_t chunk_start,
-                                           uintptr_t chunk_index_base) {
-  uintptr_t* fine_grained = AllocatedChunksFinder(
-      chunk_table_,
-      chunk_index_base,
-      kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel,
-      kCreateTablesAsNeeded);
-  int index = FineGrainedIndexForAddress(chunk_index_base);
-  if (fine_grained[index] != kUnusedChunkTableEntry) index++;
-  ASSERT(fine_grained[index] == kUnusedChunkTableEntry);
-  fine_grained[index] = chunk_start;
-}
-
-
-void MemoryAllocator::RemoveFromAllocatedChunks(Address addr, intptr_t size) {
-  ASSERT(size == kChunkSize);
-  uintptr_t int_address = reinterpret_cast<uintptr_t>(addr);
-  RemoveChunkFoundUsingAddress(int_address, int_address);
-  RemoveChunkFoundUsingAddress(int_address, int_address + size - 1);
-}
-
-
-void MemoryAllocator::RemoveChunkFoundUsingAddress(
-    uintptr_t chunk_start,
-    uintptr_t chunk_index_base) {
-  uintptr_t* fine_grained = AllocatedChunksFinder(
-      chunk_table_,
-      chunk_index_base,
-      kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel,
-      kDontCreateTables);
-  // Can't remove an entry that's not there.
-  ASSERT(fine_grained != kUnusedChunkTableEntry);
-  int index = FineGrainedIndexForAddress(chunk_index_base);
-  ASSERT(fine_grained[index] != kUnusedChunkTableEntry);
-  if (fine_grained[index] != chunk_start) {
-    index++;
-    ASSERT(fine_grained[index] == chunk_start);
-    fine_grained[index] = kUnusedChunkTableEntry;
-  } else {
-    // If only one of the entries is used it must be the first, since
-    // InAllocatedChunks relies on that.  Move things around so that this is
-    // the case.
-    fine_grained[index] = fine_grained[index + 1];
-    fine_grained[index + 1] = kUnusedChunkTableEntry;
-  }
-}
-
-
-bool MemoryAllocator::InAllocatedChunks(Address addr) {
-  uintptr_t int_address = reinterpret_cast<uintptr_t>(addr);
-  uintptr_t* fine_grained = AllocatedChunksFinder(
-      chunk_table_,
-      int_address,
-      kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel,
-      kDontCreateTables);
-  if (fine_grained == NULL) return false;
-  int index = FineGrainedIndexForAddress(int_address);
-  if (fine_grained[index] == kUnusedChunkTableEntry) return false;
-  uintptr_t entry = fine_grained[index];
-  if (entry <= int_address && entry + kChunkSize > int_address) return true;
-  index++;
-  if (fine_grained[index] == kUnusedChunkTableEntry) return false;
-  entry = fine_grained[index];
-  if (entry <= int_address && entry + kChunkSize > int_address) return true;
-  return false;
-}
-
-
-uintptr_t* MemoryAllocator::AllocatedChunksFinder(
-    uintptr_t* table,
-    uintptr_t address,
-    int bit_position,
-    CreateTables create_as_needed) {
-  if (bit_position == kChunkSizeLog2) {
-    return table;
-  }
-  ASSERT(bit_position >= kChunkSizeLog2 + kChunkTableBitsPerLevel);
-  int index =
-      ((address >> bit_position) &
-       ((V8_INTPTR_C(1) << kChunkTableBitsPerLevel) - 1));
-  uintptr_t more_fine_grained_address =
-      address & ((V8_INTPTR_C(1) << bit_position) - 1);
-  ASSERT((table == chunk_table_ && index < kChunkTableTopLevelEntries) ||
-         (table != chunk_table_ && index < 1 << kChunkTableBitsPerLevel));
-  uintptr_t* more_fine_grained_table =
-      reinterpret_cast<uintptr_t*>(table[index]);
-  if (more_fine_grained_table == kUnusedChunkTableEntry) {
-    if (create_as_needed == kDontCreateTables) return NULL;
-    int words_needed = 1 << kChunkTableBitsPerLevel;
-    if (bit_position == kChunkTableBitsPerLevel + kChunkSizeLog2) {
-      words_needed =
-          (1 << kChunkTableBitsPerLevel) * kChunkTableFineGrainedWordsPerEntry;
-    }
-    more_fine_grained_table = new uintptr_t[words_needed];
-    for (int i = 0; i < words_needed; i++) {
-      more_fine_grained_table[i] = kUnusedChunkTableEntry;
-    }
-    table[index] = reinterpret_cast<uintptr_t>(more_fine_grained_table);
-  }
-  return AllocatedChunksFinder(
-      more_fine_grained_table,
-      more_fine_grained_address,
-      bit_position - kChunkTableBitsPerLevel,
-      create_as_needed);
-}
-
-
-uintptr_t MemoryAllocator::chunk_table_[kChunkTableTopLevelEntries];
-
-
 // -----------------------------------------------------------------------------
 // PagedSpace implementation
 
-PagedSpace::PagedSpace(intptr_t max_capacity,
+PagedSpace::PagedSpace(Heap* heap,
+                       intptr_t max_capacity,
                        AllocationSpace id,
                        Executability executable)
-    : Space(id, executable) {
+    : Space(heap, id, executable) {
   max_capacity_ = (RoundDown(max_capacity, Page::kPageSize) / Page::kPageSize)
                   * Page::kObjectAreaSize;
   accounting_stats_.Clear();
@@ -958,15 +819,17 @@
   // 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);
+    first_page_ = Isolate::Current()->memory_allocator()->CommitPages(
+        RoundUp(start, Page::kPageSize),
+        Page::kPageSize * pages_in_chunk,
+        this, &num_pages);
   } else {
     int requested_pages =
         Min(MemoryAllocator::kPagesPerChunk,
             static_cast<int>(max_capacity_ / Page::kObjectAreaSize));
     first_page_ =
-        MemoryAllocator::AllocatePages(requested_pages, &num_pages, this);
+        Isolate::Current()->memory_allocator()->AllocatePages(
+            requested_pages, &num_pages, this);
     if (!first_page_->is_valid()) return false;
   }
 
@@ -999,7 +862,7 @@
 
 
 void PagedSpace::TearDown() {
-  MemoryAllocator::FreeAllPages(this);
+  Isolate::Current()->memory_allocator()->FreeAllPages(this);
   first_page_ = NULL;
   accounting_stats_.Clear();
 }
@@ -1010,8 +873,9 @@
 void PagedSpace::Protect() {
   Page* page = first_page_;
   while (page->is_valid()) {
-    MemoryAllocator::ProtectChunkFromPage(page);
-    page = MemoryAllocator::FindLastPageInSameChunk(page)->next_page();
+    Isolate::Current()->memory_allocator()->ProtectChunkFromPage(page);
+    page = Isolate::Current()->memory_allocator()->
+        FindLastPageInSameChunk(page)->next_page();
   }
 }
 
@@ -1019,8 +883,9 @@
 void PagedSpace::Unprotect() {
   Page* page = first_page_;
   while (page->is_valid()) {
-    MemoryAllocator::UnprotectChunkFromPage(page);
-    page = MemoryAllocator::FindLastPageInSameChunk(page)->next_page();
+    Isolate::Current()->memory_allocator()->UnprotectChunkFromPage(page);
+    page = Isolate::Current()->memory_allocator()->
+        FindLastPageInSameChunk(page)->next_page();
   }
 }
 
@@ -1038,7 +903,7 @@
 MaybeObject* 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());
+  ASSERT(!heap()->mark_compact_collector()->in_use());
 
   if (!Contains(addr)) return Failure::Exception();
 
@@ -1158,13 +1023,14 @@
   if (available_pages < MemoryAllocator::kPagesPerChunk) return false;
 
   int desired_pages = Min(available_pages, MemoryAllocator::kPagesPerChunk);
-  Page* p = MemoryAllocator::AllocatePages(desired_pages, &desired_pages, this);
+  Page* p = heap()->isolate()->memory_allocator()->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);
+  heap()->isolate()->memory_allocator()->SetNextPage(last_page, p);
 
   // Sequentially clear region marks of new pages and and cache the
   // new last page in the space.
@@ -1207,8 +1073,9 @@
   }
 
   // Free pages after top_page.
-  Page* p = MemoryAllocator::FreePages(top_page->next_page());
-  MemoryAllocator::SetNextPage(top_page, p);
+  Page* p = heap()->isolate()->memory_allocator()->
+      FreePages(top_page->next_page());
+  heap()->isolate()->memory_allocator()->SetNextPage(top_page, p);
 
   // Find out how many pages we failed to free and update last_page_.
   // Please note pages can only be freed in whole chunks.
@@ -1230,7 +1097,8 @@
   Page* last_page = AllocationTopPage();
   Page* next_page = last_page->next_page();
   while (next_page->is_valid()) {
-    last_page = MemoryAllocator::FindLastPageInSameChunk(next_page);
+    last_page = heap()->isolate()->memory_allocator()->
+        FindLastPageInSameChunk(next_page);
     next_page = last_page->next_page();
   }
 
@@ -1239,7 +1107,8 @@
     if (!Expand(last_page)) return false;
     ASSERT(last_page->next_page()->is_valid());
     last_page =
-        MemoryAllocator::FindLastPageInSameChunk(last_page->next_page());
+        heap()->isolate()->memory_allocator()->FindLastPageInSameChunk(
+            last_page->next_page());
   } while (Capacity() < capacity);
 
   return true;
@@ -1259,7 +1128,7 @@
   // space.
   ASSERT(allocation_info_.VerifyPagedAllocation());
   Page* top_page = Page::FromAllocationTop(allocation_info_.top);
-  ASSERT(MemoryAllocator::IsPageInSpace(top_page, this));
+  ASSERT(heap()->isolate()->memory_allocator()->IsPageInSpace(top_page, this));
 
   // Loop over all the pages.
   bool above_allocation_top = false;
@@ -1284,7 +1153,7 @@
         // be in map space.
         Map* map = object->map();
         ASSERT(map->IsMap());
-        ASSERT(Heap::map_space()->Contains(map));
+        ASSERT(heap()->map_space()->Contains(map));
 
         // Perform space-specific object verification.
         VerifyObject(object);
@@ -1320,8 +1189,8 @@
   // 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::MaxSemiSpaceSize();
+  int initial_semispace_capacity = heap()->InitialSemiSpaceSize();
+  int maximum_semispace_capacity = heap()->MaxSemiSpaceSize();
 
   ASSERT(initial_semispace_capacity <= maximum_semispace_capacity);
   ASSERT(IsPowerOf2(maximum_semispace_capacity));
@@ -1337,7 +1206,7 @@
 #undef SET_NAME
 #endif
 
-  ASSERT(size == 2 * Heap::ReservedSemiSpaceSize());
+  ASSERT(size == 2 * heap()->ReservedSemiSpaceSize());
   ASSERT(IsAddressAligned(start, size, 0));
 
   if (!to_space_.Setup(start,
@@ -1392,16 +1261,16 @@
 #ifdef ENABLE_HEAP_PROTECTION
 
 void NewSpace::Protect() {
-  MemoryAllocator::Protect(ToSpaceLow(), Capacity());
-  MemoryAllocator::Protect(FromSpaceLow(), Capacity());
+  heap()->isolate()->memory_allocator()->Protect(ToSpaceLow(), Capacity());
+  heap()->isolate()->memory_allocator()->Protect(FromSpaceLow(), Capacity());
 }
 
 
 void NewSpace::Unprotect() {
-  MemoryAllocator::Unprotect(ToSpaceLow(), Capacity(),
-                             to_space_.executable());
-  MemoryAllocator::Unprotect(FromSpaceLow(), Capacity(),
-                             from_space_.executable());
+  heap()->isolate()->memory_allocator()->Unprotect(ToSpaceLow(), Capacity(),
+                                                   to_space_.executable());
+  heap()->isolate()->memory_allocator()->Unprotect(FromSpaceLow(), Capacity(),
+                                                   from_space_.executable());
 }
 
 #endif
@@ -1495,7 +1364,7 @@
     // be in map space.
     Map* map = object->map();
     ASSERT(map->IsMap());
-    ASSERT(Heap::map_space()->Contains(map));
+    ASSERT(heap()->map_space()->Contains(map));
 
     // The object should not be code or a map.
     ASSERT(!object->IsMap());
@@ -1520,7 +1389,8 @@
 
 bool SemiSpace::Commit() {
   ASSERT(!is_committed());
-  if (!MemoryAllocator::CommitBlock(start_, capacity_, executable())) {
+  if (!heap()->isolate()->memory_allocator()->CommitBlock(
+      start_, capacity_, executable())) {
     return false;
   }
   committed_ = true;
@@ -1530,7 +1400,8 @@
 
 bool SemiSpace::Uncommit() {
   ASSERT(is_committed());
-  if (!MemoryAllocator::UncommitBlock(start_, capacity_)) {
+  if (!heap()->isolate()->memory_allocator()->UncommitBlock(
+      start_, capacity_)) {
     return false;
   }
   committed_ = false;
@@ -1576,7 +1447,8 @@
   int maximum_extra = maximum_capacity_ - capacity_;
   int extra = Min(RoundUp(capacity_, static_cast<int>(OS::AllocateAlignment())),
                   maximum_extra);
-  if (!MemoryAllocator::CommitBlock(high(), extra, executable())) {
+  if (!heap()->isolate()->memory_allocator()->CommitBlock(
+      high(), extra, executable())) {
     return false;
   }
   capacity_ += extra;
@@ -1589,7 +1461,8 @@
   ASSERT(new_capacity > capacity_);
   size_t delta = new_capacity - capacity_;
   ASSERT(IsAligned(delta, OS::AllocateAlignment()));
-  if (!MemoryAllocator::CommitBlock(high(), delta, executable())) {
+  if (!heap()->isolate()->memory_allocator()->CommitBlock(
+      high(), delta, executable())) {
     return false;
   }
   capacity_ = new_capacity;
@@ -1602,7 +1475,8 @@
   ASSERT(new_capacity < capacity_);
   size_t delta = capacity_ - new_capacity;
   ASSERT(IsAligned(delta, OS::AllocateAlignment()));
-  if (!MemoryAllocator::UncommitBlock(high() - delta, delta)) {
+  if (!heap()->isolate()->memory_allocator()->UncommitBlock(
+      high() - delta, delta)) {
     return false;
   }
   capacity_ = new_capacity;
@@ -1650,36 +1524,32 @@
 
 
 #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() {
+  Isolate* isolate = Isolate::Current();
   // We reset the name each time, though it hasn't changed.
-#define DEF_TYPE_NAME(name) heap_histograms[name].set_name(#name);
+#define DEF_TYPE_NAME(name) isolate->heap_histograms()[name].set_name(#name);
   INSTANCE_TYPE_LIST(DEF_TYPE_NAME)
 #undef DEF_TYPE_NAME
 
-#define CLEAR_HISTOGRAM(name) heap_histograms[name].clear();
+#define CLEAR_HISTOGRAM(name) isolate->heap_histograms()[name].clear();
   INSTANCE_TYPE_LIST(CLEAR_HISTOGRAM)
 #undef CLEAR_HISTOGRAM
 
-  js_spill_information.Clear();
+  isolate->js_spill_information()->Clear();
 }
 
 
-static int code_kind_statistics[Code::NUMBER_OF_KINDS];
-
-
 static void ClearCodeKindStatistics() {
+  Isolate* isolate = Isolate::Current();
   for (int i = 0; i < Code::NUMBER_OF_KINDS; i++) {
-    code_kind_statistics[i] = 0;
+    isolate->code_kind_statistics()[i] = 0;
   }
 }
 
 
 static void ReportCodeKindStatistics() {
+  Isolate* isolate = Isolate::Current();
   const char* table[Code::NUMBER_OF_KINDS] = { NULL };
 
 #define CASE(name)                            \
@@ -1694,8 +1564,10 @@
       CASE(BUILTIN);
       CASE(LOAD_IC);
       CASE(KEYED_LOAD_IC);
+      CASE(KEYED_EXTERNAL_ARRAY_LOAD_IC);
       CASE(STORE_IC);
       CASE(KEYED_STORE_IC);
+      CASE(KEYED_EXTERNAL_ARRAY_STORE_IC);
       CASE(CALL_IC);
       CASE(KEYED_CALL_IC);
       CASE(BINARY_OP_IC);
@@ -1708,8 +1580,9 @@
 
   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]);
+    if (isolate->code_kind_statistics()[i] > 0) {
+      PrintF("     %-20s: %10d bytes\n", table[i],
+          isolate->code_kind_statistics()[i]);
     }
   }
   PrintF("\n");
@@ -1717,14 +1590,16 @@
 
 
 static int CollectHistogramInfo(HeapObject* obj) {
+  Isolate* isolate = Isolate::Current();
   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());
+  ASSERT(isolate->heap_histograms()[type].name() != NULL);
+  isolate->heap_histograms()[type].increment_number(1);
+  isolate->heap_histograms()[type].increment_bytes(obj->Size());
 
   if (FLAG_collect_heap_spill_statistics && obj->IsJSObject()) {
-    JSObject::cast(obj)->IncrementSpillStatistics(&js_spill_information);
+    JSObject::cast(obj)->IncrementSpillStatistics(
+        isolate->js_spill_information());
   }
 
   return obj->Size();
@@ -1732,13 +1607,14 @@
 
 
 static void ReportHistogram(bool print_spill) {
+  Isolate* isolate = Isolate::Current();
   PrintF("\n  Object Histogram:\n");
   for (int i = 0; i <= LAST_TYPE; i++) {
-    if (heap_histograms[i].number() > 0) {
+    if (isolate->heap_histograms()[i].number() > 0) {
       PrintF("    %-34s%10d (%10d bytes)\n",
-             heap_histograms[i].name(),
-             heap_histograms[i].number(),
-             heap_histograms[i].bytes());
+             isolate->heap_histograms()[i].name(),
+             isolate->heap_histograms()[i].number(),
+             isolate->heap_histograms()[i].bytes());
     }
   }
   PrintF("\n");
@@ -1747,8 +1623,8 @@
   int string_number = 0;
   int string_bytes = 0;
 #define INCREMENT(type, size, name, camel_name)      \
-    string_number += heap_histograms[type].number(); \
-    string_bytes += heap_histograms[type].bytes();
+    string_number += isolate->heap_histograms()[type].number(); \
+    string_bytes += isolate->heap_histograms()[type].bytes();
   STRING_TYPE_LIST(INCREMENT)
 #undef INCREMENT
   if (string_number > 0) {
@@ -1757,7 +1633,7 @@
   }
 
   if (FLAG_collect_heap_spill_statistics && print_spill) {
-    js_spill_information.Print();
+    isolate->js_spill_information()->Print();
   }
 }
 #endif  // DEBUG
@@ -1786,8 +1662,9 @@
 
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
-static void DoReportStatistics(HistogramInfo* info, const char* description) {
-  LOG(HeapSampleBeginEvent("NewSpace", description));
+static void DoReportStatistics(Isolate* isolate,
+                               HistogramInfo* info, const char* description) {
+  LOG(isolate, HeapSampleBeginEvent("NewSpace", description));
   // Lump all the string types together.
   int string_number = 0;
   int string_bytes = 0;
@@ -1797,17 +1674,19 @@
   STRING_TYPE_LIST(INCREMENT)
 #undef INCREMENT
   if (string_number > 0) {
-    LOG(HeapSampleItemEvent("STRING_TYPE", string_number, string_bytes));
+    LOG(isolate,
+        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(),
+      LOG(isolate,
+          HeapSampleItemEvent(info[i].name(), info[i].number(),
                               info[i].bytes()));
     }
   }
-  LOG(HeapSampleEndEvent("NewSpace", description));
+  LOG(isolate, HeapSampleEndEvent("NewSpace", description));
 }
 #endif  // ENABLE_LOGGING_AND_PROFILING
 
@@ -1834,8 +1713,9 @@
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
   if (FLAG_log_gc) {
-    DoReportStatistics(allocated_histogram_, "allocated");
-    DoReportStatistics(promoted_histogram_, "promoted");
+    Isolate* isolate = ISOLATE;
+    DoReportStatistics(isolate, allocated_histogram_, "allocated");
+    DoReportStatistics(isolate, promoted_histogram_, "promoted");
   }
 #endif  // ENABLE_LOGGING_AND_PROFILING
 }
@@ -1861,7 +1741,7 @@
 // -----------------------------------------------------------------------------
 // Free lists for old object spaces implementation
 
-void FreeListNode::set_size(int size_in_bytes) {
+void FreeListNode::set_size(Heap* heap, int size_in_bytes) {
   ASSERT(size_in_bytes > 0);
   ASSERT(IsAligned(size_in_bytes, kPointerSize));
 
@@ -1873,14 +1753,14 @@
   // field and a next pointer, we give it a filler map that gives it the
   // correct size.
   if (size_in_bytes > ByteArray::kHeaderSize) {
-    set_map(Heap::raw_unchecked_byte_array_map());
+    set_map(heap->raw_unchecked_byte_array_map());
     // Can't use ByteArray::cast because it fails during deserialization.
     ByteArray* this_as_byte_array = reinterpret_cast<ByteArray*>(this);
     this_as_byte_array->set_length(ByteArray::LengthFor(size_in_bytes));
   } else if (size_in_bytes == kPointerSize) {
-    set_map(Heap::raw_unchecked_one_pointer_filler_map());
+    set_map(heap->raw_unchecked_one_pointer_filler_map());
   } else if (size_in_bytes == 2 * kPointerSize) {
-    set_map(Heap::raw_unchecked_two_pointer_filler_map());
+    set_map(heap->raw_unchecked_two_pointer_filler_map());
   } else {
     UNREACHABLE();
   }
@@ -1889,9 +1769,9 @@
 }
 
 
-Address FreeListNode::next() {
+Address FreeListNode::next(Heap* heap) {
   ASSERT(IsFreeListNode(this));
-  if (map() == Heap::raw_unchecked_byte_array_map()) {
+  if (map() == heap->raw_unchecked_byte_array_map()) {
     ASSERT(Size() >= kNextOffset + kPointerSize);
     return Memory::Address_at(address() + kNextOffset);
   } else {
@@ -1900,9 +1780,9 @@
 }
 
 
-void FreeListNode::set_next(Address next) {
+void FreeListNode::set_next(Heap* heap, Address next) {
   ASSERT(IsFreeListNode(this));
-  if (map() == Heap::raw_unchecked_byte_array_map()) {
+  if (map() == heap->raw_unchecked_byte_array_map()) {
     ASSERT(Size() >= kNextOffset + kPointerSize);
     Memory::Address_at(address() + kNextOffset) = next;
   } else {
@@ -1911,7 +1791,9 @@
 }
 
 
-OldSpaceFreeList::OldSpaceFreeList(AllocationSpace owner) : owner_(owner) {
+OldSpaceFreeList::OldSpaceFreeList(Heap* heap, AllocationSpace owner)
+  : heap_(heap),
+    owner_(owner) {
   Reset();
 }
 
@@ -1943,10 +1825,10 @@
 
 int OldSpaceFreeList::Free(Address start, int size_in_bytes) {
 #ifdef DEBUG
-  MemoryAllocator::ZapBlock(start, size_in_bytes);
+  Isolate::Current()->memory_allocator()->ZapBlock(start, size_in_bytes);
 #endif
   FreeListNode* node = FreeListNode::FromAddress(start);
-  node->set_size(size_in_bytes);
+  node->set_size(heap_, size_in_bytes);
 
   // We don't use the freelists in compacting mode.  This makes it more like a
   // GC that only has mark-sweep-compact and doesn't have a mark-sweep
@@ -1964,7 +1846,7 @@
 
   // Insert other blocks at the head of an exact free list.
   int index = size_in_bytes >> kPointerSizeLog2;
-  node->set_next(free_[index].head_node_);
+  node->set_next(heap_, free_[index].head_node_);
   free_[index].head_node_ = node->address();
   available_ += size_in_bytes;
   needs_rebuild_ = true;
@@ -1983,7 +1865,8 @@
   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);
+    if ((free_[index].head_node_ = node->next(heap_)) == NULL)
+      RemoveSize(index);
     available_ -= size_in_bytes;
     *wasted_bytes = 0;
     ASSERT(!FLAG_always_compact);  // We only use the freelists with mark-sweep.
@@ -2012,33 +1895,33 @@
     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) {
+    if ((free_[cur].head_node_ = cur_node->next(heap_)) == 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_);
+    rem_node->set_size(heap_, rem_bytes);
+    rem_node->set_next(heap_, 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) {
+    if ((free_[cur].head_node_ = cur_node->next(heap_)) == 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);
+      rem_node->set_size(heap_, 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_);
+    rem_node->set_size(heap_, rem_bytes);
+    rem_node->set_next(heap_, free_[rem].head_node_);
     free_[rem].head_node_ = rem_node->address();
-    if (rem_node->next() == NULL) InsertSize(rem);
+    if (rem_node->next(heap_) == NULL) InsertSize(rem);
   }
   available_ -= size_in_bytes;
   *wasted_bytes = 0;
@@ -2051,7 +1934,7 @@
     Address cur_addr = free_[i].head_node_;
     while (cur_addr != NULL) {
       FreeListNode* cur_node = FreeListNode::FromAddress(cur_addr);
-      cur_addr = cur_node->next();
+      cur_addr = cur_node->next(heap_);
       cur_node->SetMark();
     }
   }
@@ -2065,7 +1948,7 @@
     while (cur_addr != NULL) {
       FreeListNode* cur_node = FreeListNode::FromAddress(cur_addr);
       if (cur_node == node) return true;
-      cur_addr = cur_node->next();
+      cur_addr = cur_node->next(heap_);
     }
   }
   return false;
@@ -2073,8 +1956,10 @@
 #endif
 
 
-FixedSizeFreeList::FixedSizeFreeList(AllocationSpace owner, int object_size)
-    : owner_(owner), object_size_(object_size) {
+FixedSizeFreeList::FixedSizeFreeList(Heap* heap,
+                                     AllocationSpace owner,
+                                     int object_size)
+    : heap_(heap), owner_(owner), object_size_(object_size) {
   Reset();
 }
 
@@ -2087,17 +1972,17 @@
 
 void FixedSizeFreeList::Free(Address start) {
 #ifdef DEBUG
-  MemoryAllocator::ZapBlock(start, object_size_);
+  Isolate::Current()->memory_allocator()->ZapBlock(start, object_size_);
 #endif
   // We only use the freelists with mark-sweep.
-  ASSERT(!MarkCompactCollector::IsCompacting());
+  ASSERT(!HEAP->mark_compact_collector()->IsCompacting());
   FreeListNode* node = FreeListNode::FromAddress(start);
-  node->set_size(object_size_);
-  node->set_next(NULL);
+  node->set_size(heap_, object_size_);
+  node->set_next(heap_, NULL);
   if (head_ == NULL) {
     tail_ = head_ = node->address();
   } else {
-    FreeListNode::FromAddress(tail_)->set_next(node->address());
+    FreeListNode::FromAddress(tail_)->set_next(heap_, node->address());
     tail_ = node->address();
   }
   available_ += object_size_;
@@ -2111,7 +1996,7 @@
 
   ASSERT(!FLAG_always_compact);  // We only use the freelists with mark-sweep.
   FreeListNode* node = FreeListNode::FromAddress(head_);
-  head_ = node->next();
+  head_ = node->next(heap_);
   available_ -= object_size_;
   return node;
 }
@@ -2121,7 +2006,7 @@
   Address cur_addr = head_;
   while (cur_addr != NULL && cur_addr != tail_) {
     FreeListNode* cur_node = FreeListNode::FromAddress(cur_addr);
-    cur_addr = cur_node->next();
+    cur_addr = cur_node->next(heap_);
     cur_node->SetMark();
   }
 }
@@ -2217,13 +2102,14 @@
     first_page_ = last->next_page();
   } else {
     first = prev->next_page();
-    MemoryAllocator::SetNextPage(prev, last->next_page());
+    heap()->isolate()->memory_allocator()->SetNextPage(
+        prev, last->next_page());
   }
 
   // Attach it after the last page.
-  MemoryAllocator::SetNextPage(last_page_, first);
+  heap()->isolate()->memory_allocator()->SetNextPage(last_page_, first);
   last_page_ = last;
-  MemoryAllocator::SetNextPage(last, NULL);
+  heap()->isolate()->memory_allocator()->SetNextPage(last, NULL);
 
   // Clean them up.
   do {
@@ -2262,10 +2148,8 @@
   if (page_list_is_chunk_ordered_) return;
 
   Page* new_last_in_use = Page::FromAddress(NULL);
-  MemoryAllocator::RelinkPageListInChunkOrder(this,
-                                              &first_page_,
-                                              &last_page_,
-                                              &new_last_in_use);
+  heap()->isolate()->memory_allocator()->RelinkPageListInChunkOrder(
+      this, &first_page_, &last_page_, &new_last_in_use);
   ASSERT(new_last_in_use->is_valid());
 
   if (new_last_in_use != last_in_use) {
@@ -2282,7 +2166,7 @@
         accounting_stats_.AllocateBytes(size_in_bytes);
         DeallocateBlock(start, size_in_bytes, add_to_freelist);
       } else {
-        Heap::CreateFillerObjectAt(start, size_in_bytes);
+        heap()->CreateFillerObjectAt(start, size_in_bytes);
       }
     }
 
@@ -2309,7 +2193,7 @@
         accounting_stats_.AllocateBytes(size_in_bytes);
         DeallocateBlock(start, size_in_bytes, add_to_freelist);
       } else {
-        Heap::CreateFillerObjectAt(start, size_in_bytes);
+        heap()->CreateFillerObjectAt(start, size_in_bytes);
       }
     }
   }
@@ -2338,7 +2222,7 @@
   int bytes_left_to_reserve = bytes;
   while (bytes_left_to_reserve > 0) {
     if (!reserved_page->next_page()->is_valid()) {
-      if (Heap::OldGenerationAllocationLimitReached()) return false;
+      if (heap()->OldGenerationAllocationLimitReached()) return false;
       Expand(reserved_page);
     }
     bytes_left_to_reserve -= Page::kPageSize;
@@ -2356,7 +2240,7 @@
 // You have to call this last, since the implementation from PagedSpace
 // doesn't know that memory was 'promised' to large object space.
 bool LargeObjectSpace::ReserveSpace(int bytes) {
-  return Heap::OldGenerationSpaceAvailable() >= bytes;
+  return heap()->OldGenerationSpaceAvailable() >= bytes;
 }
 
 
@@ -2375,7 +2259,7 @@
 
   // There is no next page in this space.  Try free list allocation unless that
   // is currently forbidden.
-  if (!Heap::linear_allocation()) {
+  if (!heap()->linear_allocation()) {
     int wasted_bytes;
     Object* result;
     MaybeObject* maybe = free_list_.Allocate(size_in_bytes, &wasted_bytes);
@@ -2402,7 +2286,8 @@
   // 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()) {
+  if (!heap()->always_allocate() &&
+      heap()->OldGenerationAllocationLimitReached()) {
     return NULL;
   }
 
@@ -2465,28 +2350,14 @@
 
 
 #ifdef DEBUG
-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() {
+  Isolate* isolate = Isolate::Current();
+  CommentStatistic* comments_statistics =
+      isolate->paged_space_comments_statistics();
   ReportCodeKindStatistics();
   PrintF("Code comment statistics (\"   [ comment-txt   :    size/   "
          "count  (average)\"):\n");
-  for (int i = 0; i <= kMaxComments; i++) {
+  for (int i = 0; i <= CommentStatistic::kMaxComments; i++) {
     const CommentStatistic& cs = comments_statistics[i];
     if (cs.size > 0) {
       PrintF("   %-30s: %10d/%6d     (%d)\n", cs.comment, cs.size, cs.count,
@@ -2498,23 +2369,30 @@
 
 
 void PagedSpace::ResetCodeStatistics() {
+  Isolate* isolate = Isolate::Current();
+  CommentStatistic* comments_statistics =
+      isolate->paged_space_comments_statistics();
   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;
+  for (int i = 0; i < CommentStatistic::kMaxComments; i++) {
+    comments_statistics[i].Clear();
+  }
+  comments_statistics[CommentStatistic::kMaxComments].comment = "Unknown";
+  comments_statistics[CommentStatistic::kMaxComments].size = 0;
+  comments_statistics[CommentStatistic::kMaxComments].count = 0;
 }
 
 
-// Adds comment to 'comment_statistics' table. Performance OK sa long as
+// Adds comment to 'comment_statistics' table. Performance OK as long as
 // 'kMaxComments' is small
-static void EnterComment(const char* comment, int delta) {
+static void EnterComment(Isolate* isolate, const char* comment, int delta) {
+  CommentStatistic* comments_statistics =
+      isolate->paged_space_comments_statistics();
   // Do not count empty comments
   if (delta <= 0) return;
-  CommentStatistic* cs = &comments_statistics[kMaxComments];
+  CommentStatistic* cs = &comments_statistics[CommentStatistic::kMaxComments];
   // Search for a free or matching entry in 'comments_statistics': 'cs'
   // points to result.
-  for (int i = 0; i < kMaxComments; i++) {
+  for (int i = 0; i < CommentStatistic::kMaxComments; i++) {
     if (comments_statistics[i].comment == NULL) {
       cs = &comments_statistics[i];
       cs->comment = comment;
@@ -2532,7 +2410,7 @@
 
 // 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) {
+static void CollectCommentStatistics(Isolate* isolate, RelocIterator* it) {
   ASSERT(!it->done());
   ASSERT(it->rinfo()->rmode() == RelocInfo::COMMENT);
   const char* tmp = reinterpret_cast<const char*>(it->rinfo()->data());
@@ -2557,13 +2435,13 @@
       flat_delta += static_cast<int>(it->rinfo()->pc() - prev_pc);
       if (txt[0] == ']') break;  // End of nested  comment
       // A new comment
-      CollectCommentStatistics(it);
+      CollectCommentStatistics(isolate, it);
       // Skip code that was covered with previous comment
       prev_pc = it->rinfo()->pc();
     }
     it->next();
   }
-  EnterComment(comment_txt, flat_delta);
+  EnterComment(isolate, comment_txt, flat_delta);
 }
 
 
@@ -2571,18 +2449,19 @@
 // - by code kind
 // - by code comment
 void PagedSpace::CollectCodeStatistics() {
+  Isolate* isolate = heap()->isolate();
   HeapObjectIterator obj_it(this);
   for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next()) {
     if (obj->IsCode()) {
       Code* code = Code::cast(obj);
-      code_kind_statistics[code->kind()] += code->Size();
+      isolate->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 += static_cast<int>(it.rinfo()->pc() - prev_pc);
-          CollectCommentStatistics(&it);
+          CollectCommentStatistics(isolate, &it);
           prev_pc = it.rinfo()->pc();
         }
         it.next();
@@ -2591,7 +2470,7 @@
       ASSERT(code->instruction_start() <= prev_pc &&
              prev_pc <= code->instruction_end());
       delta += static_cast<int>(code->instruction_end() - prev_pc);
-      EnterComment("NoComment", delta);
+      EnterComment(isolate, "NoComment", delta);
     }
   }
 }
@@ -2685,7 +2564,7 @@
   // There is no next page in this space.  Try free list allocation unless
   // that is currently forbidden.  The fixed space free list implicitly assumes
   // that all free blocks are of the fixed size.
-  if (!Heap::linear_allocation()) {
+  if (!heap()->linear_allocation()) {
     Object* result;
     MaybeObject* maybe = free_list_.Allocate();
     if (maybe->ToObject(&result)) {
@@ -2709,7 +2588,8 @@
   // 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()) {
+  if (!heap()->always_allocate() &&
+      heap()->OldGenerationAllocationLimitReached()) {
     return NULL;
   }
 
@@ -2811,7 +2691,7 @@
 void CellSpace::VerifyObject(HeapObject* object) {
   // The object should be a global object property cell or a free-list node.
   ASSERT(object->IsJSGlobalPropertyCell() ||
-         object->map() == Heap::two_pointer_filler_map());
+         object->map() == heap()->two_pointer_filler_map());
 }
 #endif
 
@@ -2848,28 +2728,33 @@
                                         Executability executable) {
   size_t requested = ChunkSizeFor(size_in_bytes);
   size_t size;
-  void* mem = MemoryAllocator::AllocateRawMemory(requested, &size, executable);
+  Isolate* isolate = Isolate::Current();
+  void* mem = isolate->memory_allocator()->AllocateRawMemory(
+      requested, &size, executable);
   if (mem == NULL) return NULL;
 
   // The start of the chunk may be overlayed with a page so we have to
   // make sure that the page flags fit in the size field.
   ASSERT((size & Page::kPageFlagMask) == 0);
 
-  LOG(NewEvent("LargeObjectChunk", mem, size));
+  LOG(isolate, NewEvent("LargeObjectChunk", mem, size));
   if (size < requested) {
-    MemoryAllocator::FreeRawMemory(mem, size, executable);
-    LOG(DeleteEvent("LargeObjectChunk", mem));
+    isolate->memory_allocator()->FreeRawMemory(
+        mem, size, executable);
+    LOG(isolate, DeleteEvent("LargeObjectChunk", mem));
     return NULL;
   }
 
   ObjectSpace space = (executable == EXECUTABLE)
       ? kObjectSpaceCodeSpace
       : kObjectSpaceLoSpace;
-  MemoryAllocator::PerformAllocationCallback(
+  isolate->memory_allocator()->PerformAllocationCallback(
       space, kAllocationActionAllocate, size);
 
   LargeObjectChunk* chunk = reinterpret_cast<LargeObjectChunk*>(mem);
   chunk->size_ = size;
+  Page* page = Page::FromAddress(RoundUp(chunk->address(), Page::kPageSize));
+  page->heap_ = isolate->heap();
   return chunk;
 }
 
@@ -2885,8 +2770,8 @@
 // -----------------------------------------------------------------------------
 // LargeObjectSpace
 
-LargeObjectSpace::LargeObjectSpace(AllocationSpace id)
-    : Space(id, NOT_EXECUTABLE),  // Managed on a per-allocation basis
+LargeObjectSpace::LargeObjectSpace(Heap* heap, AllocationSpace id)
+    : Space(heap, id, NOT_EXECUTABLE),  // Managed on a per-allocation basis
       first_chunk_(NULL),
       size_(0),
       page_count_(0),
@@ -2906,15 +2791,17 @@
   while (first_chunk_ != NULL) {
     LargeObjectChunk* chunk = first_chunk_;
     first_chunk_ = first_chunk_->next();
-    LOG(DeleteEvent("LargeObjectChunk", chunk->address()));
+    LOG(heap()->isolate(), DeleteEvent("LargeObjectChunk", chunk->address()));
     Page* page = Page::FromAddress(RoundUp(chunk->address(), Page::kPageSize));
     Executability executable =
         page->IsPageExecutable() ? EXECUTABLE : NOT_EXECUTABLE;
     ObjectSpace space = kObjectSpaceLoSpace;
     if (executable == EXECUTABLE) space = kObjectSpaceCodeSpace;
     size_t size = chunk->size();
-    MemoryAllocator::FreeRawMemory(chunk->address(), size, executable);
-    MemoryAllocator::PerformAllocationCallback(
+    heap()->isolate()->memory_allocator()->FreeRawMemory(chunk->address(),
+                                                         size,
+                                                         executable);
+    heap()->isolate()->memory_allocator()->PerformAllocationCallback(
         space, kAllocationActionFree, size);
   }
 
@@ -2929,7 +2816,8 @@
 void LargeObjectSpace::Protect() {
   LargeObjectChunk* chunk = first_chunk_;
   while (chunk != NULL) {
-    MemoryAllocator::Protect(chunk->address(), chunk->size());
+    heap()->isolate()->memory_allocator()->Protect(chunk->address(),
+                                                   chunk->size());
     chunk = chunk->next();
   }
 }
@@ -2939,8 +2827,8 @@
   LargeObjectChunk* chunk = first_chunk_;
   while (chunk != NULL) {
     bool is_code = chunk->GetObject()->IsCode();
-    MemoryAllocator::Unprotect(chunk->address(), chunk->size(),
-                               is_code ? EXECUTABLE : NOT_EXECUTABLE);
+    heap()->isolate()->memory_allocator()->Unprotect(chunk->address(),
+        chunk->size(), is_code ? EXECUTABLE : NOT_EXECUTABLE);
     chunk = chunk->next();
   }
 }
@@ -2955,7 +2843,8 @@
 
   // 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()) {
+  if (!heap()->always_allocate() &&
+      heap()->OldGenerationAllocationLimitReached()) {
     return Failure::RetryAfterGC(identity());
   }
 
@@ -3060,22 +2949,22 @@
         // Iterate regions of the first normal page covering object.
         uint32_t first_region_number = page->GetRegionNumberForAddress(start);
         newmarks |=
-            Heap::IterateDirtyRegions(marks >> first_region_number,
-                                      start,
-                                      end,
-                                      &Heap::IteratePointersInDirtyRegion,
-                                      copy_object) << first_region_number;
+            heap()->IterateDirtyRegions(marks >> first_region_number,
+                                        start,
+                                        end,
+                                        &Heap::IteratePointersInDirtyRegion,
+                                        copy_object) << first_region_number;
 
         start = end;
         end = start + Page::kPageSize;
         while (end <= object_end) {
           // Iterate next 32 regions.
           newmarks |=
-              Heap::IterateDirtyRegions(marks,
-                                        start,
-                                        end,
-                                        &Heap::IteratePointersInDirtyRegion,
-                                        copy_object);
+              heap()->IterateDirtyRegions(marks,
+                                          start,
+                                          end,
+                                          &Heap::IteratePointersInDirtyRegion,
+                                          copy_object);
           start = end;
           end = start + Page::kPageSize;
         }
@@ -3084,11 +2973,11 @@
           // Iterate the last piece of an object which is less than
           // Page::kPageSize.
           newmarks |=
-              Heap::IterateDirtyRegions(marks,
-                                        start,
-                                        object_end,
-                                        &Heap::IteratePointersInDirtyRegion,
-                                        copy_object);
+              heap()->IterateDirtyRegions(marks,
+                                          start,
+                                          object_end,
+                                          &Heap::IteratePointersInDirtyRegion,
+                                          copy_object);
         }
 
         page->SetRegionMarks(newmarks);
@@ -3105,7 +2994,7 @@
     HeapObject* object = current->GetObject();
     if (object->IsMarked()) {
       object->ClearMark();
-      MarkCompactCollector::tracer()->decrement_marked_count();
+      heap()->mark_compact_collector()->tracer()->decrement_marked_count();
       previous = current;
       current = current->next();
     } else {
@@ -3125,7 +3014,7 @@
       }
 
       // Free the chunk.
-      MarkCompactCollector::ReportDeleteIfNeeded(object);
+      heap()->mark_compact_collector()->ReportDeleteIfNeeded(object);
       LiveObjectList::ProcessNonLive(object);
 
       size_ -= static_cast<int>(chunk_size);
@@ -3133,10 +3022,12 @@
       page_count_--;
       ObjectSpace space = kObjectSpaceLoSpace;
       if (executable == EXECUTABLE) space = kObjectSpaceCodeSpace;
-      MemoryAllocator::FreeRawMemory(chunk_address, chunk_size, executable);
-      MemoryAllocator::PerformAllocationCallback(space, kAllocationActionFree,
-                                                 size_);
-      LOG(DeleteEvent("LargeObjectChunk", chunk_address));
+      heap()->isolate()->memory_allocator()->FreeRawMemory(chunk_address,
+                                                           chunk_size,
+                                                           executable);
+      heap()->isolate()->memory_allocator()->PerformAllocationCallback(
+          space, kAllocationActionFree, size_);
+      LOG(heap()->isolate(), DeleteEvent("LargeObjectChunk", chunk_address));
     }
   }
 }
@@ -3144,7 +3035,7 @@
 
 bool LargeObjectSpace::Contains(HeapObject* object) {
   Address address = object->address();
-  if (Heap::new_space()->Contains(address)) {
+  if (heap()->new_space()->Contains(address)) {
     return false;
   }
   Page* page = Page::FromAddress(address);
@@ -3173,7 +3064,7 @@
     // in map space.
     Map* map = object->map();
     ASSERT(map->IsMap());
-    ASSERT(Heap::map_space()->Contains(map));
+    ASSERT(heap()->map_space()->Contains(map));
 
     // We have only code, sequential strings, external strings
     // (sequential strings that have been morphed into external
@@ -3200,9 +3091,9 @@
         Object* element = array->get(j);
         if (element->IsHeapObject()) {
           HeapObject* element_object = HeapObject::cast(element);
-          ASSERT(Heap::Contains(element_object));
+          ASSERT(heap()->Contains(element_object));
           ASSERT(element_object->map()->IsMap());
-          if (Heap::InNewSpace(element_object)) {
+          if (heap()->InNewSpace(element_object)) {
             Address array_addr = object->address();
             Address element_addr = array_addr + FixedArray::kHeaderSize +
                 j * kPointerSize;
@@ -3241,11 +3132,12 @@
 
 
 void LargeObjectSpace::CollectCodeStatistics() {
+  Isolate* isolate = heap()->isolate();
   LargeObjectIterator obj_it(this);
   for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next()) {
     if (obj->IsCode()) {
       Code* code = Code::cast(obj);
-      code_kind_statistics[code->kind()] += code->Size();
+      isolate->code_kind_statistics()[code->kind()] += code->Size();
     }
   }
 }
diff --git a/src/spaces.h b/src/spaces.h
index 6165255..bd939d1 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -34,6 +34,8 @@
 namespace v8 {
 namespace internal {
 
+class Isolate;
+
 // -----------------------------------------------------------------------------
 // Heap structures:
 //
@@ -241,7 +243,7 @@
   static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1;
 
   static const int kPageHeaderSize = kPointerSize + kPointerSize + kIntSize +
-    kIntSize + kPointerSize;
+    kIntSize + kPointerSize + kPointerSize;
 
   // The start offset of the object area in a page. Aligned to both maps and
   // code alignment to be suitable for both.
@@ -286,7 +288,7 @@
   // This invariant guarantees that after flipping flag meaning at the
   // beginning of scavenge all pages in use will be marked as having valid
   // watermark.
-  static inline void FlipMeaningOfInvalidatedWatermarkFlag();
+  static inline void FlipMeaningOfInvalidatedWatermarkFlag(Heap* heap);
 
   // Returns true if the page allocation watermark was not altered during
   // scavenge.
@@ -312,11 +314,6 @@
   STATIC_CHECK(kBitsPerInt - kAllocationWatermarkOffsetShift >=
                kAllocationWatermarkOffsetBits);
 
-  // This field contains the meaning of the WATERMARK_INVALIDATED flag.
-  // Instead of clearing this flag from all pages we just flip
-  // its meaning at the beginning of a scavenge.
-  static intptr_t watermark_invalidated_mark_;
-
   //---------------------------------------------------------------------------
   // Page header description.
   //
@@ -353,6 +350,8 @@
   // During scavenge collection this field is used to store allocation watermark
   // if it is altered during scavenge.
   Address mc_first_forwarded;
+
+  Heap* heap_;
 };
 
 
@@ -360,11 +359,13 @@
 // Space is the abstract superclass for all allocation spaces.
 class Space : public Malloced {
  public:
-  Space(AllocationSpace id, Executability executable)
-      : id_(id), executable_(executable) {}
+  Space(Heap* heap, AllocationSpace id, Executability executable)
+      : heap_(heap), id_(id), executable_(executable) {}
 
   virtual ~Space() {}
 
+  Heap* heap() const { return heap_; }
+
   // Does the space need executable memory?
   Executability executable() { return executable_; }
 
@@ -397,6 +398,7 @@
   virtual bool ReserveSpace(int bytes) = 0;
 
  private:
+  Heap* heap_;
   AllocationSpace id_;
   Executability executable_;
 };
@@ -409,19 +411,19 @@
 // displacements cover the entire 4GB virtual address space.  On 64-bit
 // platforms, we support this using the CodeRange object, which reserves and
 // manages a range of virtual memory.
-class CodeRange : public AllStatic {
+class CodeRange {
  public:
   // Reserves a range of virtual memory, but does not commit any of it.
   // Can only be called once, at heap initialization time.
   // Returns false on failure.
-  static bool Setup(const size_t requested_size);
+  bool Setup(const size_t requested_size);
 
   // Frees the range of virtual memory, and frees the data structures used to
   // manage it.
-  static void TearDown();
+  void TearDown();
 
-  static bool exists() { return code_range_ != NULL; }
-  static bool contains(Address address) {
+  bool exists() { return code_range_ != NULL; }
+  bool contains(Address address) {
     if (code_range_ == NULL) return false;
     Address start = static_cast<Address>(code_range_->address());
     return start <= address && address < start + code_range_->size();
@@ -430,13 +432,15 @@
   // Allocates a chunk of memory from the large-object portion of
   // the code range.  On platforms with no separate code range, should
   // not be called.
-  MUST_USE_RESULT static void* AllocateRawMemory(const size_t requested,
-                                                 size_t* allocated);
-  static void FreeRawMemory(void* buf, size_t length);
+  MUST_USE_RESULT void* AllocateRawMemory(const size_t requested,
+                                          size_t* allocated);
+  void FreeRawMemory(void* buf, size_t length);
 
  private:
+  CodeRange();
+
   // The reserved range of virtual memory that all code objects are put in.
-  static VirtualMemory* code_range_;
+  VirtualMemory* code_range_;
   // Plain old data class, just a struct plus a constructor.
   class FreeBlock {
    public:
@@ -452,20 +456,26 @@
   // Freed blocks of memory are added to the free list.  When the allocation
   // list is exhausted, the free list is sorted and merged to make the new
   // allocation list.
-  static List<FreeBlock> free_list_;
+  List<FreeBlock> free_list_;
   // Memory is allocated from the free blocks on the allocation list.
   // The block at current_allocation_block_index_ is the current block.
-  static List<FreeBlock> allocation_list_;
-  static int current_allocation_block_index_;
+  List<FreeBlock> allocation_list_;
+  int current_allocation_block_index_;
 
   // Finds a block on the allocation list that contains at least the
   // requested amount of memory.  If none is found, sorts and merges
   // the existing free memory blocks, and searches again.
   // If none can be found, terminates V8 with FatalProcessOutOfMemory.
-  static void GetNextAllocationBlock(size_t requested);
+  void GetNextAllocationBlock(size_t requested);
   // Compares the start addresses of two free blocks.
   static int CompareFreeBlockAddress(const FreeBlock* left,
                                      const FreeBlock* right);
+
+  friend class Isolate;
+
+  Isolate* isolate_;
+
+  DISALLOW_COPY_AND_ASSIGN(CodeRange);
 };
 
 
@@ -493,14 +503,14 @@
 //
 
 
-class MemoryAllocator : public AllStatic {
+class MemoryAllocator {
  public:
   // Initializes its internal bookkeeping structures.
   // Max capacity of the total space and executable memory limit.
-  static bool Setup(intptr_t max_capacity, intptr_t capacity_executable);
+  bool Setup(intptr_t max_capacity, intptr_t capacity_executable);
 
   // Deletes valid chunks.
-  static void TearDown();
+  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
@@ -511,7 +521,7 @@
   // 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);
+  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
@@ -520,24 +530,24 @@
   // 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);
+  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);
+  bool CommitBlock(Address start, size_t size, Executability executable);
 
   // Uncommit a contiguous block of memory [start..(start+size)[.
   // start is not NULL, the size is greater than zero, and the
   // block is contained in the initial chunk.  Returns true if it succeeded
   // and false otherwise.
-  static bool UncommitBlock(Address start, size_t size);
+  bool UncommitBlock(Address start, size_t size);
 
   // Zaps a contiguous block of memory [start..(start+size)[ thus
   // filling it up with a recognizable non-NULL bit pattern.
-  static void ZapBlock(Address start, size_t size);
+  void ZapBlock(Address start, size_t size);
 
   // Attempts to allocate the requested (non-zero) number of pages from the
   // OS.  Fewer pages might be allocated than requested. If it fails to
@@ -548,8 +558,8 @@
   // number of allocated pages is returned in the output parameter
   // allocated_pages.  If the PagedSpace owner is executable and there is
   // a code range, the pages are allocated from the code range.
-  static Page* AllocatePages(int requested_pages, int* allocated_pages,
-                             PagedSpace* owner);
+  Page* AllocatePages(int requested_pages, int* allocated_pages,
+                      PagedSpace* owner);
 
   // Frees pages from a given page and after. Requires pages to be
   // linked in chunk-order (see comment for class).
@@ -558,10 +568,10 @@
   // 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);
+  Page* FreePages(Page* p);
 
   // Frees all pages owned by given space.
-  static void FreeAllPages(PagedSpace* space);
+  void FreeAllPages(PagedSpace* space);
 
   // Allocates and frees raw memory of certain size.
   // These are just thin wrappers around OS::Allocate and OS::Free,
@@ -569,96 +579,83 @@
   // If the flag is EXECUTABLE and a code range exists, the requested
   // memory is allocated from the code range.  If a code range exists
   // and the freed memory is in it, the code range manages the freed memory.
-  MUST_USE_RESULT static void* AllocateRawMemory(const size_t requested,
-                                                 size_t* allocated,
-                                                 Executability executable);
-  static void FreeRawMemory(void* buf,
-                            size_t length,
-                            Executability executable);
-  static void PerformAllocationCallback(ObjectSpace space,
-                                        AllocationAction action,
-                                        size_t size);
+  MUST_USE_RESULT void* AllocateRawMemory(const size_t requested,
+                                          size_t* allocated,
+                                          Executability executable);
+  void FreeRawMemory(void* buf,
+                     size_t length,
+                     Executability executable);
+  void PerformAllocationCallback(ObjectSpace space,
+                                 AllocationAction action,
+                                 size_t size);
 
-  static void AddMemoryAllocationCallback(MemoryAllocationCallback callback,
-                                          ObjectSpace space,
-                                          AllocationAction action);
-  static void RemoveMemoryAllocationCallback(
-      MemoryAllocationCallback callback);
-  static bool MemoryAllocationCallbackRegistered(
-      MemoryAllocationCallback callback);
+  void AddMemoryAllocationCallback(MemoryAllocationCallback callback,
+                                   ObjectSpace space,
+                                   AllocationAction action);
+  void RemoveMemoryAllocationCallback(MemoryAllocationCallback callback);
+  bool MemoryAllocationCallbackRegistered(MemoryAllocationCallback callback);
 
   // Returns the maximum available bytes of heaps.
-  static intptr_t Available() {
-    return capacity_ < size_ ? 0 : capacity_ - size_;
-  }
+  intptr_t Available() { return capacity_ < size_ ? 0 : capacity_ - size_; }
 
   // Returns allocated spaces in bytes.
-  static intptr_t Size() { return size_; }
+  intptr_t Size() { return size_; }
 
   // Returns the maximum available executable bytes of heaps.
-  static intptr_t AvailableExecutable() {
+  intptr_t AvailableExecutable() {
     if (capacity_executable_ < size_executable_) return 0;
     return capacity_executable_ - size_executable_;
   }
 
   // Returns allocated executable spaces in bytes.
-  static intptr_t SizeExecutable() { return size_executable_; }
+  intptr_t SizeExecutable() { return size_executable_; }
 
   // Returns maximum available bytes that the old space can have.
-  static intptr_t MaxAvailable() {
+  intptr_t MaxAvailable() {
     return (Available() / Page::kPageSize) * Page::kObjectAreaSize;
   }
 
-  // Sanity check on a pointer.
-  static bool SafeIsInAPageChunk(Address addr);
-
   // Links two pages.
-  static inline void SetNextPage(Page* prev, Page* next);
+  inline void SetNextPage(Page* prev, Page* next);
 
   // Returns the next page of a given page.
-  static inline Page* GetNextPage(Page* p);
+  inline Page* GetNextPage(Page* p);
 
   // Checks whether a page belongs to a space.
-  static inline bool IsPageInSpace(Page* p, PagedSpace* space);
+  inline bool IsPageInSpace(Page* p, PagedSpace* space);
 
   // Returns the space that owns the given page.
-  static inline PagedSpace* PageOwner(Page* page);
+  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);
+  Page* FindFirstPageInSameChunk(Page* p);
+  Page* FindLastPageInSameChunk(Page* p);
 
   // Relinks list of pages owned by space to make it chunk-ordered.
   // Returns new first and last pages of space.
   // Also returns last page in relinked list which has WasInUsedBeforeMC
   // flag set.
-  static void RelinkPageListInChunkOrder(PagedSpace* space,
-                                         Page** first_page,
-                                         Page** last_page,
-                                         Page** last_page_in_use);
+  void RelinkPageListInChunkOrder(PagedSpace* space,
+                                  Page** first_page,
+                                  Page** last_page,
+                                  Page** last_page_in_use);
 
 #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);
+  inline void Protect(Address start, size_t size);
+  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);
+  inline void ProtectChunkFromPage(Page* page);
+  inline void UnprotectChunkFromPage(Page* page);
 #endif
 
 #ifdef DEBUG
   // Reports statistic info of the space.
-  static void ReportStatistics();
+  void ReportStatistics();
 #endif
 
-  static void AddToAllocatedChunks(Address addr, intptr_t size);
-  static void RemoveFromAllocatedChunks(Address addr, intptr_t size);
-  // Note: This only checks the regular chunks, not the odd-sized initial
-  // chunk.
-  static bool InAllocatedChunks(Address addr);
-
   // Due to encoding limitation, we can only have 8K chunks.
   static const int kMaxNofChunks = 1 << kPageSizeBits;
   // If a chunk has at least 16 pages, the maximum heap size is about
@@ -678,29 +675,21 @@
 #endif
 
  private:
+  MemoryAllocator();
+
   static const int kChunkSize = kPagesPerChunk * Page::kPageSize;
   static const int kChunkSizeLog2 = kPagesPerChunkLog2 + kPageSizeBits;
-  static const int kChunkTableTopLevelEntries =
-      1 << (sizeof(intptr_t) * kBitsPerByte - kChunkSizeLog2 -
-          (kChunkTableLevels - 1) * kChunkTableBitsPerLevel);
-
-  // The chunks are not chunk-size aligned so for a given chunk-sized area of
-  // memory there can be two chunks that cover it.
-  static const int kChunkTableFineGrainedWordsPerEntry = 2;
-  static const uintptr_t kUnusedChunkTableEntry = 0;
 
   // Maximum space size in bytes.
-  static intptr_t capacity_;
+  intptr_t capacity_;
   // Maximum subset of capacity_ that can be executable
-  static intptr_t capacity_executable_;
-
-  // Top level table to track whether memory is part of a chunk or not.
-  static uintptr_t chunk_table_[kChunkTableTopLevelEntries];
+  intptr_t capacity_executable_;
 
   // Allocated space size in bytes.
-  static intptr_t size_;
+  intptr_t size_;
+
   // Allocated executable space size in bytes.
-  static intptr_t size_executable_;
+  intptr_t size_executable_;
 
   struct MemoryAllocationCallbackRegistration {
     MemoryAllocationCallbackRegistration(MemoryAllocationCallback callback,
@@ -713,11 +702,11 @@
     AllocationAction action;
   };
   // A List of callback that are triggered when memory is allocated or free'd
-  static List<MemoryAllocationCallbackRegistration>
+  List<MemoryAllocationCallbackRegistration>
       memory_allocation_callbacks_;
 
   // The initial chunk of virtual memory.
-  static VirtualMemory* initial_chunk_;
+  VirtualMemory* initial_chunk_;
 
   // Allocated chunk info: chunk start address, chunk size, and owning space.
   class ChunkInfo BASE_EMBEDDED {
@@ -725,7 +714,8 @@
     ChunkInfo() : address_(NULL),
                   size_(0),
                   owner_(NULL),
-                  executable_(NOT_EXECUTABLE) {}
+                  executable_(NOT_EXECUTABLE),
+                  owner_identity_(FIRST_SPACE) {}
     inline void init(Address a, size_t s, PagedSpace* o);
     Address address() { return address_; }
     size_t size() { return size_; }
@@ -733,74 +723,60 @@
     // We save executability of the owner to allow using it
     // when collecting stats after the owner has been destroyed.
     Executability executable() const { return executable_; }
+    AllocationSpace owner_identity() const { return owner_identity_; }
 
    private:
     Address address_;
     size_t size_;
     PagedSpace* owner_;
     Executability executable_;
+    AllocationSpace owner_identity_;
   };
 
   // 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_;
+  List<ChunkInfo> chunks_;
+  List<int> free_chunk_ids_;
+  int max_nof_chunks_;
+  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; }
+  void Push(int free_chunk_id);
+  int Pop();
+  bool OutOfChunkIds() { return top_ == 0; }
 
   // Frees a chunk.
-  static void DeleteChunk(int chunk_id);
-
-  // Helpers to maintain and query the chunk tables.
-  static void AddChunkUsingAddress(
-      uintptr_t chunk_start,        // Where the chunk starts.
-      uintptr_t chunk_index_base);  // Used to place the chunk in the tables.
-  static void RemoveChunkFoundUsingAddress(
-      uintptr_t chunk_start,        // Where the chunk starts.
-      uintptr_t chunk_index_base);  // Used to locate the entry in the tables.
-  // Controls whether the lookup creates intermediate levels of tables as
-  // needed.
-  enum CreateTables { kDontCreateTables, kCreateTablesAsNeeded };
-  static uintptr_t* AllocatedChunksFinder(uintptr_t* table,
-                                          uintptr_t address,
-                                          int bit_position,
-                                          CreateTables create_as_needed);
-  static void FreeChunkTables(uintptr_t* array, int length, int level);
-  static int FineGrainedIndexForAddress(uintptr_t address) {
-    int index = ((address >> kChunkSizeLog2) &
-        ((1 << kChunkTableBitsPerLevel) - 1));
-    return index * kChunkTableFineGrainedWordsPerEntry;
-  }
-
+  void DeleteChunk(int chunk_id);
 
   // Basic check whether a chunk id is in the valid range.
-  static inline bool IsValidChunkId(int chunk_id);
+  inline bool IsValidChunkId(int chunk_id);
 
   // Checks whether a chunk id identifies an allocated chunk.
-  static inline bool IsValidChunk(int chunk_id);
+  inline bool IsValidChunk(int chunk_id);
 
   // Returns the chunk id that a page belongs to.
-  static inline int GetChunkId(Page* p);
+  inline int GetChunkId(Page* p);
 
   // True if the address lies in the initial chunk.
-  static inline bool InInitialChunk(Address address);
+  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);
+  Page* InitializePagesInChunk(int chunk_id, int pages_in_chunk,
+                               PagedSpace* owner);
 
-  static Page* RelinkPagesInChunk(int chunk_id,
-                                  Address chunk_start,
-                                  size_t chunk_size,
-                                  Page* prev,
-                                  Page** last_page_in_use);
+  Page* RelinkPagesInChunk(int chunk_id,
+                           Address chunk_start,
+                           size_t chunk_size,
+                           Page* prev,
+                           Page** last_page_in_use);
+
+  friend class Isolate;
+
+  Isolate* isolate_;
+
+  DISALLOW_COPY_AND_ASSIGN(MemoryAllocator);
 };
 
 
@@ -1048,7 +1024,8 @@
 class PagedSpace : public Space {
  public:
   // Creates a space with a maximum capacity, and an id.
-  PagedSpace(intptr_t max_capacity,
+  PagedSpace(Heap* heap,
+             intptr_t max_capacity,
              AllocationSpace id,
              Executability executable);
 
@@ -1341,7 +1318,7 @@
 class SemiSpace : public Space {
  public:
   // Constructor.
-  SemiSpace() :Space(NEW_SPACE, NOT_EXECUTABLE) {
+  explicit SemiSpace(Heap* heap) : Space(heap, NEW_SPACE, NOT_EXECUTABLE) {
     start_ = NULL;
     age_mark_ = NULL;
   }
@@ -1508,7 +1485,10 @@
 class NewSpace : public Space {
  public:
   // Constructor.
-  NewSpace() : Space(NEW_SPACE, NOT_EXECUTABLE) {}
+  explicit NewSpace(Heap* heap)
+    : Space(heap, NEW_SPACE, NOT_EXECUTABLE),
+      to_space_(heap),
+      from_space_(heap) {}
 
   // Sets up the new space using the given chunk.
   bool Setup(Address start, int size);
@@ -1741,11 +1721,11 @@
   // 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);
+  void set_size(Heap* heap, int size_in_bytes);
 
   // Accessors for the next field.
-  inline Address next();
-  inline void set_next(Address next);
+  inline Address next(Heap* heap);
+  inline void set_next(Heap* heap, Address next);
 
  private:
   static const int kNextOffset = POINTER_SIZE_ALIGN(ByteArray::kHeaderSize);
@@ -1757,7 +1737,7 @@
 // The free list for the old space.
 class OldSpaceFreeList BASE_EMBEDDED {
  public:
-  explicit OldSpaceFreeList(AllocationSpace owner);
+  OldSpaceFreeList(Heap* heap, AllocationSpace owner);
 
   // Clear the free list.
   void Reset();
@@ -1787,6 +1767,8 @@
   static const int kMinBlockSize = 2 * kPointerSize;
   static const int kMaxBlockSize = Page::kMaxHeapObjectSize;
 
+  Heap* heap_;
+
   // The identity of the owning space, for building allocation Failure
   // objects.
   AllocationSpace owner_;
@@ -1861,7 +1843,7 @@
 // The free list for the map space.
 class FixedSizeFreeList BASE_EMBEDDED {
  public:
-  FixedSizeFreeList(AllocationSpace owner, int object_size);
+  FixedSizeFreeList(Heap* heap, AllocationSpace owner, int object_size);
 
   // Clear the free list.
   void Reset();
@@ -1882,6 +1864,9 @@
   void MarkNodes();
 
  private:
+
+  Heap* heap_;
+
   // Available bytes on the free list.
   intptr_t available_;
 
@@ -1909,10 +1894,12 @@
  public:
   // Creates an old space object with a given maximum capacity.
   // The constructor does not allocate pages from OS.
-  explicit OldSpace(intptr_t max_capacity,
-                    AllocationSpace id,
-                    Executability executable)
-      : PagedSpace(max_capacity, id, executable), free_list_(id) {
+  OldSpace(Heap* heap,
+           intptr_t max_capacity,
+           AllocationSpace id,
+           Executability executable)
+      : PagedSpace(heap, max_capacity, id, executable),
+        free_list_(heap, id) {
     page_extra_ = 0;
   }
 
@@ -1981,14 +1968,15 @@
 
 class FixedSpace : public PagedSpace {
  public:
-  FixedSpace(intptr_t max_capacity,
+  FixedSpace(Heap* heap,
+             intptr_t max_capacity,
              AllocationSpace id,
              int object_size_in_bytes,
              const char* name)
-      : PagedSpace(max_capacity, id, NOT_EXECUTABLE),
+      : PagedSpace(heap, max_capacity, id, NOT_EXECUTABLE),
         object_size_in_bytes_(object_size_in_bytes),
         name_(name),
-        free_list_(id, object_size_in_bytes) {
+        free_list_(heap, id, object_size_in_bytes) {
     page_extra_ = Page::kObjectAreaSize % object_size_in_bytes;
   }
 
@@ -2059,8 +2047,11 @@
 class MapSpace : public FixedSpace {
  public:
   // Creates a map space object with a maximum capacity.
-  MapSpace(intptr_t max_capacity, int max_map_space_pages, AllocationSpace id)
-      : FixedSpace(max_capacity, id, Map::kSize, "map"),
+  MapSpace(Heap* heap,
+           intptr_t max_capacity,
+           int max_map_space_pages,
+           AllocationSpace id)
+      : FixedSpace(heap, max_capacity, id, Map::kSize, "map"),
         max_map_space_pages_(max_map_space_pages) {
     ASSERT(max_map_space_pages < kMaxMapPageIndex);
   }
@@ -2170,8 +2161,9 @@
 class CellSpace : public FixedSpace {
  public:
   // Creates a property cell space object with a maximum capacity.
-  CellSpace(intptr_t max_capacity, AllocationSpace id)
-      : FixedSpace(max_capacity, id, JSGlobalPropertyCell::kSize, "cell") {}
+  CellSpace(Heap* heap, intptr_t max_capacity, AllocationSpace id)
+      : FixedSpace(heap, max_capacity, id, JSGlobalPropertyCell::kSize, "cell")
+  {}
 
  protected:
 #ifdef DEBUG
@@ -2246,7 +2238,7 @@
 
 class LargeObjectSpace : public Space {
  public:
-  explicit LargeObjectSpace(AllocationSpace id);
+  LargeObjectSpace(Heap* heap, AllocationSpace id);
   virtual ~LargeObjectSpace() {}
 
   // Initializes internal data structures.
@@ -2263,9 +2255,7 @@
   MUST_USE_RESULT MaybeObject* AllocateRawFixedArray(int size_in_bytes);
 
   // Available bytes for objects in this space.
-  intptr_t Available() {
-    return LargeObjectChunk::ObjectSizeFor(MemoryAllocator::Available());
-  }
+  inline intptr_t Available();
 
   virtual intptr_t Size() {
     return size_;
@@ -2357,6 +2347,22 @@
 };
 
 
+#ifdef DEBUG
+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.
+  static const int kMaxComments = 64;
+};
+#endif
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_SPACES_H_
diff --git a/src/string-search.cc b/src/string-search.cc
index 5687443..3ae68b5 100644
--- a/src/string-search.cc
+++ b/src/string-search.cc
@@ -33,8 +33,9 @@
 
 // Storage for constants used by string-search.
 
-int StringSearchBase::kBadCharShiftTable[kUC16AlphabetSize];
-int StringSearchBase::kGoodSuffixShiftTable[kBMMaxShift + 1];
-int StringSearchBase::kSuffixTable[kBMMaxShift + 1];
+// Now in Isolate:
+// bad_char_shift_table()
+// good_suffix_shift_table()
+// suffix_table()
 
 }}  // namespace v8::internal
diff --git a/src/string-search.h b/src/string-search.h
index 5de3c09..1223db0 100644
--- a/src/string-search.h
+++ b/src/string-search.h
@@ -44,7 +44,7 @@
   // limit, we can fix the size of tables. For a needle longer than this limit,
   // search will not be optimal, since we only build tables for a suffix
   // of the string, but it is a safe approximation.
-  static const int kBMMaxShift = 250;
+  static const int kBMMaxShift = Isolate::kBMMaxShift;
 
   // Reduce alphabet to this size.
   // One of the tables used by Boyer-Moore and Boyer-Moore-Horspool has size
@@ -54,7 +54,7 @@
   // For needles using only characters in the same Unicode 256-code point page,
   // there is no search speed degradation.
   static const int kAsciiAlphabetSize = 128;
-  static const int kUC16AlphabetSize = 256;
+  static const int kUC16AlphabetSize = Isolate::kUC16AlphabetSize;
 
   // Bad-char shift table stored in the state. It's length is the alphabet size.
   // For patterns below this length, the skip length of Boyer-Moore is too short
@@ -69,25 +69,16 @@
     return String::IsAscii(string.start(), string.length());
   }
 
-  // The following tables are shared by all searches.
-  // TODO(lrn): Introduce a way for a pattern to keep its tables
-  // between searches (e.g., for an Atom RegExp).
-
-  // Store for the BoyerMoore(Horspool) bad char shift table.
-  static int kBadCharShiftTable[kUC16AlphabetSize];
-  // Store for the BoyerMoore good suffix shift table.
-  static int kGoodSuffixShiftTable[kBMMaxShift + 1];
-  // Table used temporarily while building the BoyerMoore good suffix
-  // shift table.
-  static int kSuffixTable[kBMMaxShift + 1];
+  friend class Isolate;
 };
 
 
 template <typename PatternChar, typename SubjectChar>
 class StringSearch : private StringSearchBase {
  public:
-  explicit StringSearch(Vector<const PatternChar> pattern)
-      : pattern_(pattern),
+  StringSearch(Isolate* isolate, Vector<const PatternChar> pattern)
+      : isolate_(isolate),
+        pattern_(pattern),
         start_(Max(0, pattern.length() - kBMMaxShift)) {
     if (sizeof(PatternChar) > sizeof(SubjectChar)) {
       if (!IsAsciiString(pattern_)) {
@@ -175,24 +166,33 @@
     return bad_char_occurrence[equiv_class];
   }
 
+  // The following tables are shared by all searches.
+  // TODO(lrn): Introduce a way for a pattern to keep its tables
+  // between searches (e.g., for an Atom RegExp).
+
+  // Store for the BoyerMoore(Horspool) bad char shift table.
   // Return a table covering the last kBMMaxShift+1 positions of
   // pattern.
   int* bad_char_table() {
-    return kBadCharShiftTable;
+    return isolate_->bad_char_shift_table();
   }
 
+  // Store for the BoyerMoore good suffix shift table.
   int* good_suffix_shift_table() {
     // Return biased pointer that maps the range  [start_..pattern_.length()
     // to the kGoodSuffixShiftTable array.
-    return kGoodSuffixShiftTable - start_;
+    return isolate_->good_suffix_shift_table() - start_;
   }
 
+  // Table used temporarily while building the BoyerMoore good suffix
+  // shift table.
   int* suffix_table() {
     // Return biased pointer that maps the range  [start_..pattern_.length()
     // to the kSuffixTable array.
-    return kSuffixTable - start_;
+    return isolate_->suffix_table() - start_;
   }
 
+  Isolate* isolate_;
   // The pattern to search for.
   Vector<const PatternChar> pattern_;
   // Pointer to implementation of the search.
@@ -555,10 +555,11 @@
 // object should be constructed once and the Search function then called
 // for each search.
 template <typename SubjectChar, typename PatternChar>
-static int SearchString(Vector<const SubjectChar> subject,
+static int SearchString(Isolate* isolate,
+                        Vector<const SubjectChar> subject,
                         Vector<const PatternChar> pattern,
                         int start_index) {
-  StringSearch<PatternChar, SubjectChar> search(pattern);
+  StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
   return search.Search(subject, start_index);
 }
 
diff --git a/src/string-stream.cc b/src/string-stream.cc
index 7abd1bb..aea1420 100644
--- a/src/string-stream.cc
+++ b/src/string-stream.cc
@@ -34,9 +34,6 @@
 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);
@@ -195,6 +192,8 @@
     return;
   }
   if (o->IsHeapObject()) {
+    DebugObjectCache* debug_object_cache = Isolate::Current()->
+        string_stream_debug_object_cache();
     for (int i = 0; i < debug_object_cache->length(); i++) {
       if ((*debug_object_cache)[i] == o) {
         Add("#%d#", i);
@@ -260,7 +259,7 @@
 
 
 void StringStream::Log() {
-  LOG(StringEvent("StackDump", buffer_));
+  LOG(ISOLATE, StringEvent("StackDump", buffer_));
 }
 
 
@@ -281,22 +280,25 @@
 
 
 Handle<String> StringStream::ToString() {
-  return Factory::NewStringFromUtf8(Vector<const char>(buffer_, length_));
+  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);
+  Isolate* isolate = Isolate::Current();
+  isolate->set_string_stream_current_security_token(NULL);
+  if (isolate->string_stream_debug_object_cache() == NULL) {
+    isolate->set_string_stream_debug_object_cache(
+        new List<HeapObject*, PreallocatedStorage>(0));
   }
-  debug_object_cache->Clear();
+  isolate->string_stream_debug_object_cache()->Clear();
 }
 
 
 #ifdef DEBUG
 bool StringStream::IsMentionedObjectCacheClear() {
-  return (debug_object_cache->length() == 0);
+  return (
+      Isolate::Current()->string_stream_debug_object_cache()->length() == 0);
 }
 #endif
 
@@ -338,7 +340,7 @@
 
 void StringStream::PrintUsingMap(JSObject* js_object) {
   Map* map = js_object->map();
-  if (!Heap::Contains(map) ||
+  if (!HEAP->Contains(map) ||
       !map->IsHeapObject() ||
       !map->IsMap()) {
     Add("<Invalid map>\n");
@@ -375,9 +377,10 @@
 
 
 void StringStream::PrintFixedArray(FixedArray* array, unsigned int limit) {
+  Heap* heap = HEAP;
   for (unsigned int i = 0; i < 10 && i < limit; i++) {
     Object* element = array->get(i);
-    if (element != Heap::the_hole_value()) {
+    if (element != heap->the_hole_value()) {
       for (int len = 1; len < 18; len++)
         Put(' ');
       Add("%d: %o\n", i, array->get(i));
@@ -412,6 +415,8 @@
 
 
 void StringStream::PrintMentionedObjectCache() {
+  DebugObjectCache* debug_object_cache =
+      Isolate::Current()->string_stream_debug_object_cache();
   Add("==== Key         ============================================\n\n");
   for (int i = 0; i < debug_object_cache->length(); i++) {
     HeapObject* printee = (*debug_object_cache)[i];
@@ -444,12 +449,14 @@
 
 
 void StringStream::PrintSecurityTokenIfChanged(Object* f) {
-  if (!f->IsHeapObject() || !Heap::Contains(HeapObject::cast(f))) {
+  Isolate* isolate = Isolate::Current();
+  Heap* heap = isolate->heap();
+  if (!f->IsHeapObject() || !heap->Contains(HeapObject::cast(f))) {
     return;
   }
   Map* map = HeapObject::cast(f)->map();
   if (!map->IsHeapObject() ||
-      !Heap::Contains(map) ||
+      !heap->Contains(map) ||
       !map->IsMap() ||
       !f->IsJSFunction()) {
     return;
@@ -458,17 +465,17 @@
   JSFunction* fun = JSFunction::cast(f);
   Object* perhaps_context = fun->unchecked_context();
   if (perhaps_context->IsHeapObject() &&
-      Heap::Contains(HeapObject::cast(perhaps_context)) &&
+      heap->Contains(HeapObject::cast(perhaps_context)) &&
       perhaps_context->IsContext()) {
     Context* context = fun->context();
-    if (!Heap::Contains(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) {
+    if (token != isolate->string_stream_current_security_token()) {
       Add("Security context: %o\n", token);
-      current_security_token = token;
+      isolate->set_string_stream_current_security_token(token);
     }
   } else {
     Add("(Function context is corrupt)\n");
@@ -478,8 +485,8 @@
 
 void StringStream::PrintFunction(Object* f, Object* receiver, Code** code) {
   if (f->IsHeapObject() &&
-      Heap::Contains(HeapObject::cast(f)) &&
-      Heap::Contains(HeapObject::cast(f)->map()) &&
+      HEAP->Contains(HeapObject::cast(f)) &&
+      HEAP->Contains(HeapObject::cast(f)->map()) &&
       HeapObject::cast(f)->map()->IsMap()) {
     if (f->IsJSFunction()) {
       JSFunction* fun = JSFunction::cast(f);
@@ -506,11 +513,11 @@
       Add("/* warning: 'function' was not a heap object */ ");
       return;
     }
-    if (!Heap::Contains(HeapObject::cast(f))) {
+    if (!HEAP->Contains(HeapObject::cast(f))) {
       Add("/* warning: 'function' was not on the heap */ ");
       return;
     }
-    if (!Heap::Contains(HeapObject::cast(f)->map())) {
+    if (!HEAP->Contains(HeapObject::cast(f)->map())) {
       Add("/* warning: function's map was not on the heap */ ");
       return;
     }
@@ -526,10 +533,11 @@
 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()) {
+  Heap* heap = HEAP;
+  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 (key != heap->undefined_value()) {
         if (!name->IsString() ||
             !key->IsString() ||
             !String::cast(name)->Equals(String::cast(key))) {
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index f23f382..435e71d 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -41,8 +41,12 @@
 // StubCache implementation.
 
 
-StubCache::Entry StubCache::primary_[StubCache::kPrimaryTableSize];
-StubCache::Entry StubCache::secondary_[StubCache::kSecondaryTableSize];
+StubCache::StubCache(Isolate* isolate) : isolate_(isolate) {
+  ASSERT(isolate == Isolate::Current());
+  memset(primary_, 0, sizeof(primary_[0]) * StubCache::kPrimaryTableSize);
+  memset(secondary_, 0, sizeof(secondary_[0]) * StubCache::kSecondaryTableSize);
+}
+
 
 void StubCache::Initialize(bool create_heap_objects) {
   ASSERT(IsPowerOf2(kPrimaryTableSize));
@@ -60,7 +64,7 @@
 
   // 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(!heap()->InNewSpace(name));
   ASSERT(name->IsSymbol());
 
   // The state bits are not important to the hash function because
@@ -80,7 +84,7 @@
 
   // 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)) {
+  if (hit != isolate_->builtins()->builtin(Builtins::kIllegal)) {
     Code::Flags primary_flags = Code::RemoveTypeFromFlags(hit->flags());
     int secondary_offset =
         SecondaryOffset(primary->key, primary_flags, primary_offset);
@@ -104,10 +108,10 @@
   // there are global objects involved, we need to check global
   // property cells in the stub and therefore the stub will be
   // specific to the name.
-  String* cache_name = Heap::empty_string();
+  String* cache_name = heap()->empty_string();
   if (receiver->IsGlobalObject()) cache_name = name;
   JSObject* last = receiver;
-  while (last->GetPrototype() != Heap::null_value()) {
+  while (last->GetPrototype() != heap()->null_value()) {
     last = JSObject::cast(last->GetPrototype());
     if (last->IsGlobalObject()) cache_name = name;
   }
@@ -122,7 +126,8 @@
           compiler.CompileLoadNonexistent(cache_name, receiver, last);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), cache_name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), cache_name));
     GDBJIT(AddCode(GDBJITInterface::LOAD_IC, cache_name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -147,7 +152,8 @@
           compiler.CompileLoadField(receiver, holder, field_index, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -173,7 +179,8 @@
           compiler.CompileLoadCallback(name, receiver, holder, callback);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -199,7 +206,8 @@
           compiler.CompileLoadConstant(receiver, holder, value, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -223,7 +231,8 @@
           compiler.CompileLoadInterceptor(receiver, holder, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -236,7 +245,7 @@
 
 
 MaybeObject* StubCache::ComputeLoadNormal() {
-  return Builtins::builtin(Builtins::LoadIC_Normal);
+  return isolate_->builtins()->builtin(Builtins::kLoadIC_Normal);
 }
 
 
@@ -257,7 +266,8 @@
                                                            is_dont_delete);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -282,7 +292,8 @@
           compiler.CompileLoadField(name, receiver, holder, field_index);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -308,7 +319,8 @@
           compiler.CompileLoadConstant(name, receiver, holder, value);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -333,7 +345,8 @@
           compiler.CompileLoadInterceptor(receiver, holder, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -359,7 +372,8 @@
           compiler.CompileLoadCallback(name, receiver, holder, callback);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -383,7 +397,8 @@
     { MaybeObject* maybe_code = compiler.CompileLoadArrayLength(name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -406,7 +421,8 @@
     { MaybeObject* maybe_code = compiler.CompileLoadStringLength(name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result = map->UpdateCodeCache(name, Code::cast(code));
@@ -428,7 +444,8 @@
     { MaybeObject* maybe_code = compiler.CompileLoadFunctionPrototype(name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -449,41 +466,15 @@
   // keyed loads that are not array elements go through a generic builtin stub.
   Code::Flags flags =
       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, NORMAL);
-  String* name = Heap::KeyedLoadSpecialized_symbol();
+  String* name = heap()->KeyedLoadSpecialized_symbol();
   Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
     KeyedLoadStubCompiler compiler;
     { MaybeObject* maybe_code = compiler.CompileLoadSpecialized(receiver);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), 0));
-    Object* result;
-    { MaybeObject* maybe_result =
-          receiver->UpdateMapCodeCache(name, Code::cast(code));
-      if (!maybe_result->ToObject(&result)) return maybe_result;
-    }
-  }
-  return code;
-}
-
-
-MaybeObject* StubCache::ComputeKeyedLoadPixelArray(JSObject* receiver) {
-  // Using NORMAL as the PropertyType for array element loads is a misuse. The
-  // generated stub always accesses fast elements, not slow-mode fields, but
-  // some property type is required for the stub lookup. Note that overloading
-  // the NORMAL PropertyType is only safe as long as no stubs are generated for
-  // other keyed field loads. This is guaranteed to be the case since all field
-  // keyed loads that are not array elements go through a generic builtin stub.
-  Code::Flags flags =
-      Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, NORMAL);
-  String* name = Heap::KeyedLoadPixelArray_symbol();
-  Object* code = receiver->map()->FindInCodeCache(name, flags);
-  if (code->IsUndefined()) {
-    KeyedLoadStubCompiler compiler;
-    { MaybeObject* maybe_code = compiler.CompileLoadPixelArray(receiver);
-      if (!maybe_code->ToObject(&code)) return maybe_code;
-    }
-    PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), 0));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), 0));
     Object* result;
     { MaybeObject* maybe_result =
           receiver->UpdateMapCodeCache(name, Code::cast(code));
@@ -509,7 +500,8 @@
           compiler.CompileStoreField(receiver, field_index, transition, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -526,43 +518,15 @@
     StrictModeFlag strict_mode) {
   Code::Flags flags =
       Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, NORMAL, strict_mode);
-  String* name = Heap::KeyedStoreSpecialized_symbol();
+  String* name = heap()->KeyedStoreSpecialized_symbol();
   Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
     KeyedStoreStubCompiler compiler(strict_mode);
     { MaybeObject* maybe_code = compiler.CompileStoreSpecialized(receiver);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, Code::cast(code), 0));
-    Object* result;
-    { MaybeObject* maybe_result =
-          receiver->UpdateMapCodeCache(name, Code::cast(code));
-      if (!maybe_result->ToObject(&result)) return maybe_result;
-    }
-  }
-  return code;
-}
-
-
-MaybeObject* StubCache::ComputeKeyedStorePixelArray(
-    JSObject* receiver,
-    StrictModeFlag strict_mode) {
-  // Using NORMAL as the PropertyType for array element stores is a misuse. The
-  // generated stub always accesses fast elements, not slow-mode fields, but
-  // some property type is required for the stub lookup. Note that overloading
-  // the NORMAL PropertyType is only safe as long as no stubs are generated for
-  // other keyed field stores. This is guaranteed to be the case since all field
-  // keyed stores that are not array elements go through a generic builtin stub.
-  Code::Flags flags =
-      Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, NORMAL, strict_mode);
-  String* name = Heap::KeyedStorePixelArray_symbol();
-  Object* code = receiver->map()->FindInCodeCache(name, flags);
-  if (code->IsUndefined()) {
-    KeyedStoreStubCompiler compiler(strict_mode);
-    { MaybeObject* maybe_code = compiler.CompileStorePixelArray(receiver);
-      if (!maybe_code->ToObject(&code)) return maybe_code;
-    }
-    PROFILE(CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, Code::cast(code), 0));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, Code::cast(code), 0));
     Object* result;
     { MaybeObject* maybe_result =
           receiver->UpdateMapCodeCache(name, Code::cast(code));
@@ -591,12 +555,64 @@
       return kExternalUnsignedIntArray;
     case JSObject::EXTERNAL_FLOAT_ELEMENTS:
       return kExternalFloatArray;
+    case JSObject::EXTERNAL_PIXEL_ELEMENTS:
+      return kExternalPixelArray;
     default:
       UNREACHABLE();
       return static_cast<ExternalArrayType>(0);
   }
 }
 
+String* ExternalArrayTypeToStubName(Heap* heap,
+                                    ExternalArrayType array_type,
+                                    bool is_store) {
+  if (is_store) {
+    switch (array_type) {
+      case kExternalByteArray:
+        return heap->KeyedStoreExternalByteArray_symbol();
+      case kExternalUnsignedByteArray:
+        return heap->KeyedStoreExternalUnsignedByteArray_symbol();
+      case kExternalShortArray:
+        return heap->KeyedStoreExternalShortArray_symbol();
+      case kExternalUnsignedShortArray:
+        return heap->KeyedStoreExternalUnsignedShortArray_symbol();
+      case kExternalIntArray:
+        return heap->KeyedStoreExternalIntArray_symbol();
+      case kExternalUnsignedIntArray:
+        return heap->KeyedStoreExternalUnsignedIntArray_symbol();
+      case kExternalFloatArray:
+        return heap->KeyedStoreExternalFloatArray_symbol();
+      case kExternalPixelArray:
+        return heap->KeyedStoreExternalPixelArray_symbol();
+      default:
+        UNREACHABLE();
+        return NULL;
+    }
+  } else {
+    switch (array_type) {
+      case kExternalByteArray:
+        return heap->KeyedLoadExternalByteArray_symbol();
+      case kExternalUnsignedByteArray:
+        return heap->KeyedLoadExternalUnsignedByteArray_symbol();
+      case kExternalShortArray:
+        return heap->KeyedLoadExternalShortArray_symbol();
+      case kExternalUnsignedShortArray:
+        return heap->KeyedLoadExternalUnsignedShortArray_symbol();
+      case kExternalIntArray:
+        return heap->KeyedLoadExternalIntArray_symbol();
+      case kExternalUnsignedIntArray:
+        return heap->KeyedLoadExternalUnsignedIntArray_symbol();
+      case kExternalFloatArray:
+        return heap->KeyedLoadExternalFloatArray_symbol();
+      case kExternalPixelArray:
+        return heap->KeyedLoadExternalPixelArray_symbol();
+      default:
+        UNREACHABLE();
+        return NULL;
+    }
+  }
+}
+
 }  // anonymous namespace
 
 
@@ -606,36 +622,35 @@
     StrictModeFlag strict_mode) {
   Code::Flags flags =
       Code::ComputeMonomorphicFlags(
-          is_store ? Code::KEYED_STORE_IC : Code::KEYED_LOAD_IC,
+          is_store ? Code::KEYED_EXTERNAL_ARRAY_STORE_IC :
+                     Code::KEYED_EXTERNAL_ARRAY_LOAD_IC,
           NORMAL,
           strict_mode);
   ExternalArrayType array_type =
       ElementsKindToExternalArrayType(receiver->GetElementsKind());
-  String* name =
-      is_store ? Heap::KeyedStoreExternalArray_symbol()
-          : Heap::KeyedLoadExternalArray_symbol();
-  // Use the global maps for the particular external array types,
-  // rather than the receiver's map, when looking up the cached code,
-  // so that we actually canonicalize these stubs.
-  Map* map = Heap::MapForExternalArrayType(array_type);
-  Object* code = map->FindInCodeCache(name, flags);
+  String* name = ExternalArrayTypeToStubName(heap(), array_type, is_store);
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
     ExternalArrayStubCompiler compiler;
-    { MaybeObject* maybe_code = is_store
-          ? compiler.CompileKeyedStoreStub(array_type, flags)
-          : compiler.CompileKeyedLoadStub(array_type, flags);
+    { MaybeObject* maybe_code =
+          is_store ?
+              compiler.CompileKeyedStoreStub(receiver, array_type, flags) :
+              compiler.CompileKeyedLoadStub(receiver, array_type, flags);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
+    Code::cast(code)->set_external_array_type(array_type);
     if (is_store) {
-      PROFILE(
-          CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, Code::cast(code), 0));
+      PROFILE(isolate_,
+          CodeCreateEvent(Logger::KEYED_EXTERNAL_ARRAY_STORE_IC_TAG,
+                          Code::cast(code), 0));
     } else {
-      PROFILE(
-          CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), 0));
+      PROFILE(isolate_,
+          CodeCreateEvent(Logger::KEYED_EXTERNAL_ARRAY_LOAD_IC_TAG,
+                          Code::cast(code), 0));
     }
     Object* result;
     { MaybeObject* maybe_result =
-          map->UpdateCodeCache(name, Code::cast(code));
+          receiver->UpdateMapCodeCache(name, Code::cast(code));
       if (!maybe_result->ToObject(&result)) return maybe_result;
     }
   }
@@ -644,9 +659,9 @@
 
 
 MaybeObject* StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
-  return Builtins::builtin((strict_mode == kStrictMode)
-                            ? Builtins::StoreIC_Normal_Strict
-                            : Builtins::StoreIC_Normal);
+  return isolate_->builtins()->builtin((strict_mode == kStrictMode)
+                            ? Builtins::kStoreIC_Normal_Strict
+                            : Builtins::kStoreIC_Normal);
 }
 
 
@@ -663,7 +678,8 @@
           compiler.CompileStoreGlobal(receiver, cell, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -690,7 +706,8 @@
           compiler.CompileStoreCallback(receiver, callback, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -715,7 +732,8 @@
           compiler.CompileStoreInterceptor(receiver, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate_,
+            CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -742,8 +760,9 @@
           compiler.CompileStoreField(receiver, field_index, transition, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
-    PROFILE(CodeCreateEvent(
-        Logger::KEYED_STORE_IC_TAG, Code::cast(code), name));
+    PROFILE(isolate(),
+            CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
+                            Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, name, Code::cast(code)));
     Object* result;
     { MaybeObject* maybe_result =
@@ -802,7 +821,8 @@
     }
     Code::cast(code)->set_check_type(check);
     ASSERT_EQ(flags, Code::cast(code)->flags());
-    PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
+    PROFILE(isolate_,
+            CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
                             Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
     Object* result;
@@ -852,7 +872,8 @@
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
     ASSERT_EQ(flags, Code::cast(code)->flags());
-    PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
+    PROFILE(isolate_,
+            CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
                             Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
     Object* result;
@@ -897,7 +918,8 @@
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
     ASSERT_EQ(flags, Code::cast(code)->flags());
-    PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
+    PROFILE(isolate(),
+            CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
                             Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
     Object* result;
@@ -954,7 +976,8 @@
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
     ASSERT_EQ(flags, Code::cast(code)->flags());
-    PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
+    PROFILE(isolate(),
+            CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
                             Code::cast(code), name));
     GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
     Object* result;
@@ -967,45 +990,48 @@
 }
 
 
-static Object* GetProbeValue(Code::Flags flags) {
+static Object* GetProbeValue(Isolate* isolate, Code::Flags flags) {
   // Use raw_unchecked... so we don't get assert failures during GC.
-  NumberDictionary* dictionary = Heap::raw_unchecked_non_monomorphic_cache();
-  int entry = dictionary->FindEntry(flags);
+  NumberDictionary* dictionary =
+      isolate->heap()->raw_unchecked_non_monomorphic_cache();
+  int entry = dictionary->FindEntry(isolate, flags);
   if (entry != -1) return dictionary->ValueAt(entry);
-  return Heap::raw_unchecked_undefined_value();
+  return isolate->heap()->raw_unchecked_undefined_value();
 }
 
 
-MUST_USE_RESULT static MaybeObject* ProbeCache(Code::Flags flags) {
-  Object* probe = GetProbeValue(flags);
-  if (probe != Heap::undefined_value()) return probe;
+MUST_USE_RESULT static MaybeObject* ProbeCache(Isolate* isolate,
+                                               Code::Flags flags) {
+  Heap* heap = isolate->heap();
+  Object* probe = GetProbeValue(isolate, 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;
   { MaybeObject* maybe_result =
-        Heap::non_monomorphic_cache()->AtNumberPut(flags,
-                                                   Heap::undefined_value());
+        heap->non_monomorphic_cache()->AtNumberPut(flags,
+                                                   heap->undefined_value());
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
-  Heap::public_set_non_monomorphic_cache(NumberDictionary::cast(result));
+  heap->public_set_non_monomorphic_cache(NumberDictionary::cast(result));
   return probe;
 }
 
 
-static MaybeObject* FillCache(MaybeObject* maybe_code) {
+static MaybeObject* FillCache(Isolate* isolate, MaybeObject* maybe_code) {
   Object* code;
   if (maybe_code->ToObject(&code)) {
     if (code->IsCode()) {
-      int entry =
-          Heap::non_monomorphic_cache()->FindEntry(
-              Code::cast(code)->flags());
+      Heap* heap = isolate->heap();
+      int entry = heap->non_monomorphic_cache()->FindEntry(
+          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);
+      ASSERT(heap->non_monomorphic_cache()->ValueAt(entry) ==
+             heap->undefined_value());
+      heap->non_monomorphic_cache()->ValueAtPut(entry, code);
+      CHECK(GetProbeValue(isolate, Code::cast(code)->flags()) == code);
     }
   }
   return maybe_code;
@@ -1021,8 +1047,8 @@
                                          Code::kNoExtraICState,
                                          NORMAL,
                                          argc);
-  Object* result = ProbeCache(flags)->ToObjectUnchecked();
-  ASSERT(!result->IsUndefined());
+  Object* result = ProbeCache(isolate(), flags)->ToObjectUnchecked();
+  ASSERT(result != heap()->undefined_value());
   // This might be called during the marking phase of the collector
   // hence the unchecked cast.
   return reinterpret_cast<Code*>(result);
@@ -1039,12 +1065,12 @@
                                          NORMAL,
                                          argc);
   Object* probe;
-  { MaybeObject* maybe_probe = ProbeCache(flags);
+  { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
     if (!maybe_probe->ToObject(&probe)) return maybe_probe;
   }
   if (!probe->IsUndefined()) return probe;
   StubCompiler compiler;
-  return FillCache(compiler.CompileCallInitialize(flags));
+  return FillCache(isolate_, compiler.CompileCallInitialize(flags));
 }
 
 
@@ -1057,7 +1083,8 @@
     // that it needs so we need to ensure it is generated already.
     ComputeCallInitialize(argc, NOT_IN_LOOP);
   }
-  CALL_HEAP_FUNCTION(ComputeCallInitialize(argc, in_loop, Code::CALL_IC), Code);
+  CALL_HEAP_FUNCTION(isolate_,
+                     ComputeCallInitialize(argc, in_loop, Code::CALL_IC), Code);
 }
 
 
@@ -1072,6 +1099,7 @@
     ComputeKeyedCallInitialize(argc, NOT_IN_LOOP);
   }
   CALL_HEAP_FUNCTION(
+      isolate_,
       ComputeCallInitialize(argc, in_loop, Code::KEYED_CALL_IC), Code);
 }
 
@@ -1086,12 +1114,12 @@
                                          NORMAL,
                                          argc);
   Object* probe;
-  { MaybeObject* maybe_probe = ProbeCache(flags);
+  { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
     if (!maybe_probe->ToObject(&probe)) return maybe_probe;
   }
   if (!probe->IsUndefined()) return probe;
   StubCompiler compiler;
-  return FillCache(compiler.CompileCallPreMonomorphic(flags));
+  return FillCache(isolate_, compiler.CompileCallPreMonomorphic(flags));
 }
 
 
@@ -1105,12 +1133,12 @@
                                          NORMAL,
                                          argc);
   Object* probe;
-  { MaybeObject* maybe_probe = ProbeCache(flags);
+  { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
     if (!maybe_probe->ToObject(&probe)) return maybe_probe;
   }
   if (!probe->IsUndefined()) return probe;
   StubCompiler compiler;
-  return FillCache(compiler.CompileCallNormal(flags));
+  return FillCache(isolate_, compiler.CompileCallNormal(flags));
 }
 
 
@@ -1124,12 +1152,12 @@
                                          NORMAL,
                                          argc);
   Object* probe;
-  { MaybeObject* maybe_probe = ProbeCache(flags);
+  { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
     if (!maybe_probe->ToObject(&probe)) return maybe_probe;
   }
   if (!probe->IsUndefined()) return probe;
   StubCompiler compiler;
-  return FillCache(compiler.CompileCallMegamorphic(flags));
+  return FillCache(isolate_, compiler.CompileCallMegamorphic(flags));
 }
 
 
@@ -1144,12 +1172,12 @@
                                          argc,
                                          OWN_MAP);
   Object* probe;
-  { MaybeObject* maybe_probe = ProbeCache(flags);
+  { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
     if (!maybe_probe->ToObject(&probe)) return maybe_probe;
   }
   if (!probe->IsUndefined()) return probe;
   StubCompiler compiler;
-  return FillCache(compiler.CompileCallMiss(flags));
+  return FillCache(isolate_, compiler.CompileCallMiss(flags));
 }
 
 
@@ -1162,12 +1190,12 @@
                                          NORMAL,
                                          argc);
   Object* probe;
-  { MaybeObject* maybe_probe = ProbeCache(flags);
+  { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
     if (!maybe_probe->ToObject(&probe)) return maybe_probe;
   }
   if (!probe->IsUndefined()) return probe;
   StubCompiler compiler;
-  return FillCache(compiler.CompileCallDebugBreak(flags));
+  return FillCache(isolate_, compiler.CompileCallDebugBreak(flags));
 }
 
 
@@ -1180,24 +1208,26 @@
                                          NORMAL,
                                          argc);
   Object* probe;
-  { MaybeObject* maybe_probe = ProbeCache(flags);
+  { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
     if (!maybe_probe->ToObject(&probe)) return maybe_probe;
   }
   if (!probe->IsUndefined()) return probe;
   StubCompiler compiler;
-  return FillCache(compiler.CompileCallDebugPrepareStepIn(flags));
+  return FillCache(isolate_, compiler.CompileCallDebugPrepareStepIn(flags));
 }
 #endif
 
 
 void StubCache::Clear() {
   for (int i = 0; i < kPrimaryTableSize; i++) {
-    primary_[i].key = Heap::empty_string();
-    primary_[i].value = Builtins::builtin(Builtins::Illegal);
+    primary_[i].key = heap()->empty_string();
+    primary_[i].value = isolate_->builtins()->builtin(
+        Builtins::kIllegal);
   }
   for (int j = 0; j < kSecondaryTableSize; j++) {
-    secondary_[j].key = Heap::empty_string();
-    secondary_[j].value = Builtins::builtin(Builtins::Illegal);
+    secondary_[j].key = heap()->empty_string();
+    secondary_[j].value = isolate_->builtins()->builtin(
+        Builtins::kIllegal);
   }
 }
 
@@ -1248,7 +1278,8 @@
 // StubCompiler implementation.
 
 
-MaybeObject* LoadCallbackProperty(Arguments args) {
+MaybeObject* LoadCallbackProperty(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args[0]->IsJSObject());
   ASSERT(args[1]->IsJSObject());
   AccessorInfo* callback = AccessorInfo::cast(args[3]);
@@ -1256,21 +1287,22 @@
   v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
   ASSERT(fun != NULL);
   v8::AccessorInfo info(&args[0]);
-  HandleScope scope;
+  HandleScope scope(isolate);
   v8::Handle<v8::Value> result;
   {
     // Leaving JavaScript.
-    VMState state(EXTERNAL);
-    ExternalCallbackScope call_scope(getter_address);
+    VMState state(isolate, EXTERNAL);
+    ExternalCallbackScope call_scope(isolate, getter_address);
     result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
   }
-  RETURN_IF_SCHEDULED_EXCEPTION();
-  if (result.IsEmpty()) return Heap::undefined_value();
+  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
+  if (result.IsEmpty()) return HEAP->undefined_value();
   return *v8::Utils::OpenHandle(*result);
 }
 
 
-MaybeObject* StoreCallbackProperty(Arguments args) {
+MaybeObject* StoreCallbackProperty(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   JSObject* recv = JSObject::cast(args[0]);
   AccessorInfo* callback = AccessorInfo::cast(args[1]);
   Address setter_address = v8::ToCData<Address>(callback->setter());
@@ -1278,17 +1310,17 @@
   ASSERT(fun != NULL);
   Handle<String> name = args.at<String>(2);
   Handle<Object> value = args.at<Object>(3);
-  HandleScope scope;
-  LOG(ApiNamedPropertyAccess("store", recv, *name));
-  CustomArguments custom_args(callback->data(), recv, recv);
+  HandleScope scope(isolate);
+  LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
+  CustomArguments custom_args(isolate, callback->data(), recv, recv);
   v8::AccessorInfo info(custom_args.end());
   {
     // Leaving JavaScript.
-    VMState state(EXTERNAL);
-    ExternalCallbackScope call_scope(setter_address);
+    VMState state(isolate, EXTERNAL);
+    ExternalCallbackScope call_scope(isolate, setter_address);
     fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
   }
-  RETURN_IF_SCHEDULED_EXCEPTION();
+  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   return *value;
 }
 
@@ -1303,7 +1335,8 @@
  * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
  * provide any value for the given name.
  */
-MaybeObject* LoadPropertyWithInterceptorOnly(Arguments args) {
+MaybeObject* LoadPropertyWithInterceptorOnly(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   Handle<String> name_handle = args.at<String>(0);
   Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
   ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
@@ -1320,20 +1353,20 @@
     // Use the interceptor getter.
     v8::AccessorInfo info(args.arguments() -
                           kAccessorInfoOffsetInInterceptorArgs);
-    HandleScope scope;
+    HandleScope scope(isolate);
     v8::Handle<v8::Value> r;
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       r = getter(v8::Utils::ToLocal(name_handle), info);
     }
-    RETURN_IF_SCHEDULED_EXCEPTION();
+    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
     if (!r.IsEmpty()) {
       return *v8::Utils::OpenHandle(*r);
     }
   }
 
-  return Heap::no_interceptor_result_sentinel();
+  return isolate->heap()->no_interceptor_result_sentinel();
 }
 
 
@@ -1341,17 +1374,17 @@
   // 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);
+  IC ic(IC::NO_EXTRA_FRAME, Isolate::Current());
   ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
-  if (!ic.SlowIsContextual()) return Heap::undefined_value();
+  if (!ic.SlowIsContextual()) return HEAP->undefined_value();
 
   // Throw a reference error.
   HandleScope scope;
   Handle<String> name_handle(name);
   Handle<Object> error =
-      Factory::NewReferenceError("not_defined",
+      FACTORY->NewReferenceError("not_defined",
                                   HandleVector(&name_handle, 1));
-  return Top::Throw(*error);
+  return Isolate::Current()->Throw(*error);
 }
 
 
@@ -1364,6 +1397,8 @@
   Handle<JSObject> holder_handle = args->at<JSObject>(3);
   ASSERT(args->length() == 5);  // Last arg is data object.
 
+  Isolate* isolate = receiver_handle->GetIsolate();
+
   Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
   v8::NamedPropertyGetter getter =
       FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
@@ -1373,14 +1408,14 @@
     // Use the interceptor getter.
     v8::AccessorInfo info(args->arguments() -
                           kAccessorInfoOffsetInInterceptorArgs);
-    HandleScope scope;
+    HandleScope scope(isolate);
     v8::Handle<v8::Value> r;
     {
       // Leaving JavaScript.
-      VMState state(EXTERNAL);
+      VMState state(isolate, EXTERNAL);
       r = getter(v8::Utils::ToLocal(name_handle), info);
     }
-    RETURN_IF_SCHEDULED_EXCEPTION();
+    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
     if (!r.IsEmpty()) {
       *attrs = NONE;
       return *v8::Utils::OpenHandle(*r);
@@ -1391,7 +1426,7 @@
       *receiver_handle,
       *name_handle,
       attrs);
-  RETURN_IF_SCHEDULED_EXCEPTION();
+  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   return result;
 }
 
@@ -1400,7 +1435,8 @@
  * Loads a property with an interceptor performing post interceptor
  * lookup if interceptor failed.
  */
-MaybeObject* LoadPropertyWithInterceptorForLoad(Arguments args) {
+MaybeObject* LoadPropertyWithInterceptorForLoad(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   PropertyAttributes attr = NONE;
   Object* result;
   { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
@@ -1413,10 +1449,11 @@
 }
 
 
-MaybeObject* LoadPropertyWithInterceptorForCall(Arguments args) {
+MaybeObject* LoadPropertyWithInterceptorForCall(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   PropertyAttributes attr;
   MaybeObject* result = LoadWithInterceptor(&args, &attr);
-  RETURN_IF_SCHEDULED_EXCEPTION();
+  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   // This is 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.
@@ -1424,7 +1461,8 @@
 }
 
 
-MaybeObject* StoreInterceptorProperty(Arguments args) {
+MaybeObject* StoreInterceptorProperty(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   ASSERT(args.length() == 4);
   JSObject* recv = JSObject::cast(args[0]);
   String* name = String::cast(args[1]);
@@ -1440,7 +1478,8 @@
 }
 
 
-MaybeObject* KeyedLoadPropertyWithInterceptor(Arguments args) {
+MaybeObject* KeyedLoadPropertyWithInterceptor(RUNTIME_CALLING_CONVENTION) {
+  RUNTIME_GET_ISOLATE;
   JSObject* receiver = JSObject::cast(args[0]);
   ASSERT(Smi::cast(args[1])->value() >= 0);
   uint32_t index = Smi::cast(args[1])->value();
@@ -1449,7 +1488,7 @@
 
 
 MaybeObject* StubCompiler::CompileCallInitialize(Code::Flags flags) {
-  HandleScope scope;
+  HandleScope scope(isolate());
   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   Code::Kind kind = Code::ExtractKindFromFlags(flags);
   if (kind == Code::CALL_IC) {
@@ -1462,10 +1501,11 @@
         GetCodeWithFlags(flags, "CompileCallInitialize");
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
-  Counters::call_initialize_stubs.Increment();
+  isolate()->counters()->call_initialize_stubs()->Increment();
   Code* code = Code::cast(result);
   USE(code);
-  PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
+  PROFILE(isolate(),
+          CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
                           code, code->arguments_count()));
   GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, Code::cast(code)));
   return result;
@@ -1473,7 +1513,7 @@
 
 
 MaybeObject* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
-  HandleScope scope;
+  HandleScope scope(isolate());
   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   // The code of the PreMonomorphic stub is the same as the code
   // of the Initialized stub.  They just differ on the code object flags.
@@ -1488,10 +1528,11 @@
         GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
-  Counters::call_premonomorphic_stubs.Increment();
+  isolate()->counters()->call_premonomorphic_stubs()->Increment();
   Code* code = Code::cast(result);
   USE(code);
-  PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
+  PROFILE(isolate(),
+          CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
                           code, code->arguments_count()));
   GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, Code::cast(code)));
   return result;
@@ -1499,7 +1540,7 @@
 
 
 MaybeObject* StubCompiler::CompileCallNormal(Code::Flags flags) {
-  HandleScope scope;
+  HandleScope scope(isolate());
   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   Code::Kind kind = Code::ExtractKindFromFlags(flags);
   if (kind == Code::CALL_IC) {
@@ -1511,10 +1552,11 @@
   { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallNormal");
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
-  Counters::call_normal_stubs.Increment();
+  isolate()->counters()->call_normal_stubs()->Increment();
   Code* code = Code::cast(result);
   USE(code);
-  PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
+  PROFILE(isolate(),
+          CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
                           code, code->arguments_count()));
   GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, Code::cast(code)));
   return result;
@@ -1522,7 +1564,7 @@
 
 
 MaybeObject* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
-  HandleScope scope;
+  HandleScope scope(isolate());
   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   Code::Kind kind = Code::ExtractKindFromFlags(flags);
   if (kind == Code::CALL_IC) {
@@ -1530,16 +1572,16 @@
   } else {
     KeyedCallIC::GenerateMegamorphic(masm(), argc);
   }
-
   Object* result;
   { MaybeObject* maybe_result =
         GetCodeWithFlags(flags, "CompileCallMegamorphic");
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
-  Counters::call_megamorphic_stubs.Increment();
+  isolate()->counters()->call_megamorphic_stubs()->Increment();
   Code* code = Code::cast(result);
   USE(code);
-  PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
+  PROFILE(isolate(),
+          CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
                           code, code->arguments_count()));
   GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, Code::cast(code)));
   return result;
@@ -1547,7 +1589,7 @@
 
 
 MaybeObject* StubCompiler::CompileCallMiss(Code::Flags flags) {
-  HandleScope scope;
+  HandleScope scope(isolate());
   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   Code::Kind kind = Code::ExtractKindFromFlags(flags);
   if (kind == Code::CALL_IC) {
@@ -1559,10 +1601,11 @@
   { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallMiss");
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
-  Counters::call_megamorphic_stubs.Increment();
+  isolate()->counters()->call_megamorphic_stubs()->Increment();
   Code* code = Code::cast(result);
   USE(code);
-  PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
+  PROFILE(isolate(),
+          CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
                           code, code->arguments_count()));
   GDBJIT(AddCode(GDBJITInterface::CALL_MISS, Code::cast(code)));
   return result;
@@ -1571,7 +1614,7 @@
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
 MaybeObject* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
-  HandleScope scope;
+  HandleScope scope(isolate());
   Debug::GenerateCallICDebugBreak(masm());
   Object* result;
   { MaybeObject* maybe_result =
@@ -1582,14 +1625,15 @@
   USE(code);
   Code::Kind kind = Code::ExtractKindFromFlags(flags);
   USE(kind);
-  PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG),
+  PROFILE(isolate(),
+          CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG),
                           code, code->arguments_count()));
   return result;
 }
 
 
 MaybeObject* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
-  HandleScope scope;
+  HandleScope scope(isolate());
   // Use the same code for the the step in preparations as we do for
   // the miss case.
   int argc = Code::ExtractArgumentsCountFromFlags(flags);
@@ -1606,10 +1650,11 @@
   }
   Code* code = Code::cast(result);
   USE(code);
-  PROFILE(CodeCreateEvent(
-      CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
-      code,
-      code->arguments_count()));
+  PROFILE(isolate(),
+          CodeCreateEvent(
+              CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
+              code,
+              code->arguments_count()));
   return result;
 }
 #endif
@@ -1624,7 +1669,7 @@
   // Create code object in the heap.
   CodeDesc desc;
   masm_.GetCode(&desc);
-  MaybeObject* result = Heap::CreateCode(desc, flags, masm_.CodeObject());
+  MaybeObject* result = heap()->CreateCode(desc, flags, masm_.CodeObject());
 #ifdef ENABLE_DISASSEMBLER
   if (FLAG_print_code_stubs && !result->IsFailure()) {
     Code::cast(result->ToObjectUnchecked())->Disassemble(name);
@@ -1649,7 +1694,7 @@
   if (!lookup->IsProperty()) {
     lookup->NotFound();
     Object* proto = holder->GetPrototype();
-    if (proto != Heap::null_value()) {
+    if (!proto->IsNull()) {
       proto->Lookup(name, lookup);
     }
   }
@@ -1661,7 +1706,8 @@
   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
   MaybeObject* result = GetCodeWithFlags(flags, name);
   if (!result->IsFailure()) {
-    PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG,
+    PROFILE(isolate(),
+            CodeCreateEvent(Logger::LOAD_IC_TAG,
                             Code::cast(result->ToObjectUnchecked()),
                             name));
     GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
@@ -1676,7 +1722,8 @@
   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, type);
   MaybeObject* result = GetCodeWithFlags(flags, name);
   if (!result->IsFailure()) {
-    PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
+    PROFILE(isolate(),
+            CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
                             Code::cast(result->ToObjectUnchecked()),
                             name));
     GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
@@ -1692,7 +1739,8 @@
       Code::STORE_IC, type, strict_mode_);
   MaybeObject* result = GetCodeWithFlags(flags, name);
   if (!result->IsFailure()) {
-    PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG,
+    PROFILE(isolate(),
+            CodeCreateEvent(Logger::STORE_IC_TAG,
                             Code::cast(result->ToObjectUnchecked()),
                             name));
     GDBJIT(AddCode(GDBJITInterface::STORE_IC,
@@ -1708,7 +1756,8 @@
       Code::KEYED_STORE_IC, type, strict_mode_);
   MaybeObject* result = GetCodeWithFlags(flags, name);
   if (!result->IsFailure()) {
-    PROFILE(CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
+    PROFILE(isolate(),
+            CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
                             Code::cast(result->ToObjectUnchecked()),
                             name));
     GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC,
@@ -1732,32 +1781,51 @@
 }
 
 
-bool CallStubCompiler::HasCustomCallGenerator(BuiltinFunctionId id) {
+bool CallStubCompiler::HasCustomCallGenerator(JSFunction* function) {
+  SharedFunctionInfo* info = function->shared();
+  if (info->HasBuiltinFunctionId()) {
+    BuiltinFunctionId id = info->builtin_function_id();
 #define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
-  CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
+    CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
 #undef CALL_GENERATOR_CASE
+  }
+  CallOptimization optimization(function);
+  if (optimization.is_simple_api_call()) {
+    return true;
+  }
   return false;
 }
 
 
-MaybeObject* CallStubCompiler::CompileCustomCall(BuiltinFunctionId id,
-                                                 Object* object,
+MaybeObject* CallStubCompiler::CompileCustomCall(Object* object,
                                                  JSObject* holder,
                                                  JSGlobalPropertyCell* cell,
                                                  JSFunction* function,
                                                  String* fname) {
-#define CALL_GENERATOR_CASE(name)                          \
-  if (id == k##name) {                                     \
-    return CallStubCompiler::Compile##name##Call(object,   \
-                                                 holder,   \
-                                                 cell,     \
-                                                 function, \
-                                                 fname);   \
-  }
-  CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
+  ASSERT(HasCustomCallGenerator(function));
+
+  SharedFunctionInfo* info = function->shared();
+  if (info->HasBuiltinFunctionId()) {
+    BuiltinFunctionId id = info->builtin_function_id();
+#define CALL_GENERATOR_CASE(name)                           \
+    if (id == k##name) {                                    \
+      return CallStubCompiler::Compile##name##Call(object,  \
+                                                  holder,   \
+                                                  cell,     \
+                                                  function, \
+                                                  fname);   \
+    }
+    CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
 #undef CALL_GENERATOR_CASE
-  ASSERT(!HasCustomCallGenerator(id));
-  return Heap::undefined_value();
+  }
+  CallOptimization optimization(function);
+  ASSERT(optimization.is_simple_api_call());
+  return CompileFastApiCall(optimization,
+                            object,
+                            holder,
+                            cell,
+                            function,
+                            fname);
 }
 
 
@@ -1790,7 +1858,7 @@
   }
   Code* code = Code::cast(result);
   USE(code);
-  PROFILE(CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
+  PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
   GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", Code::cast(code)));
   return result;
 }
@@ -1870,7 +1938,8 @@
   }
   Code* code = Code::cast(result);
   USE(code);
-  PROFILE(CodeCreateEvent(Logger::STUB_TAG, code, "ExternalArrayStub"));
+  PROFILE(isolate(),
+          CodeCreateEvent(Logger::STUB_TAG, code, "ExternalArrayStub"));
   return result;
 }
 
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 6927076..793f581 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -28,6 +28,7 @@
 #ifndef V8_STUB_CACHE_H_
 #define V8_STUB_CACHE_H_
 
+#include "arguments.h"
 #include "macro-assembler.h"
 #include "zone-inl.h"
 
@@ -43,50 +44,62 @@
 // 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;
+
+class SCTableReference {
+ public:
+  Address address() const { return address_; }
+
+ private:
+  explicit SCTableReference(Address address) : address_(address) {}
+
+  Address address_;
+
+  friend class StubCache;
+};
 
 
-class StubCache : public AllStatic {
+class StubCache {
  public:
   struct Entry {
     String* key;
     Code* value;
   };
 
+  void Initialize(bool create_heap_objects);
 
-  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.
-  MUST_USE_RESULT static MaybeObject* ComputeLoadNonexistent(
+  MUST_USE_RESULT MaybeObject* ComputeLoadNonexistent(
       String* name,
       JSObject* receiver);
 
-  MUST_USE_RESULT static MaybeObject* ComputeLoadField(String* name,
-                                                       JSObject* receiver,
-                                                       JSObject* holder,
-                                                       int field_index);
+  MUST_USE_RESULT MaybeObject* ComputeLoadField(String* name,
+                                                JSObject* receiver,
+                                                JSObject* holder,
+                                                int field_index);
 
-  MUST_USE_RESULT static MaybeObject* ComputeLoadCallback(
+  MUST_USE_RESULT MaybeObject* ComputeLoadCallback(
       String* name,
       JSObject* receiver,
       JSObject* holder,
       AccessorInfo* callback);
 
-  MUST_USE_RESULT static MaybeObject* ComputeLoadConstant(String* name,
-                                                          JSObject* receiver,
-                                                          JSObject* holder,
-                                                          Object* value);
+  MUST_USE_RESULT MaybeObject* ComputeLoadConstant(String* name,
+                                                   JSObject* receiver,
+                                                   JSObject* holder,
+                                                   Object* value);
 
-  MUST_USE_RESULT static MaybeObject* ComputeLoadInterceptor(
+  MUST_USE_RESULT MaybeObject* ComputeLoadInterceptor(
       String* name,
       JSObject* receiver,
       JSObject* holder);
 
-  MUST_USE_RESULT static MaybeObject* ComputeLoadNormal();
+  MUST_USE_RESULT MaybeObject* ComputeLoadNormal();
 
 
-  MUST_USE_RESULT static MaybeObject* ComputeLoadGlobal(
+  MUST_USE_RESULT MaybeObject* ComputeLoadGlobal(
       String* name,
       JSObject* receiver,
       GlobalObject* holder,
@@ -96,108 +109,102 @@
 
   // ---
 
-  MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadField(String* name,
-                                                            JSObject* receiver,
-                                                            JSObject* holder,
-                                                            int field_index);
+  MUST_USE_RESULT MaybeObject* ComputeKeyedLoadField(String* name,
+                                                     JSObject* receiver,
+                                                     JSObject* holder,
+                                                     int field_index);
 
-  MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadCallback(
+  MUST_USE_RESULT MaybeObject* ComputeKeyedLoadCallback(
       String* name,
       JSObject* receiver,
       JSObject* holder,
       AccessorInfo* callback);
 
-  MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadConstant(
+  MUST_USE_RESULT MaybeObject* ComputeKeyedLoadConstant(
       String* name,
       JSObject* receiver,
       JSObject* holder,
       Object* value);
 
-  MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadInterceptor(
+  MUST_USE_RESULT MaybeObject* ComputeKeyedLoadInterceptor(
       String* name,
       JSObject* receiver,
       JSObject* holder);
 
-  MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadArrayLength(
+  MUST_USE_RESULT MaybeObject* ComputeKeyedLoadArrayLength(
       String* name,
       JSArray* receiver);
 
-  MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadStringLength(
+  MUST_USE_RESULT MaybeObject* ComputeKeyedLoadStringLength(
       String* name,
       String* receiver);
 
-  MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadFunctionPrototype(
+  MUST_USE_RESULT MaybeObject* ComputeKeyedLoadFunctionPrototype(
       String* name,
       JSFunction* receiver);
 
-  MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadSpecialized(
-      JSObject* receiver);
-
-  MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadPixelArray(
+  MUST_USE_RESULT MaybeObject* ComputeKeyedLoadSpecialized(
       JSObject* receiver);
 
   // ---
 
-  MUST_USE_RESULT static MaybeObject* ComputeStoreField(
+  MUST_USE_RESULT MaybeObject* ComputeStoreField(
       String* name,
       JSObject* receiver,
       int field_index,
       Map* transition,
       StrictModeFlag strict_mode);
 
-  MUST_USE_RESULT static MaybeObject* ComputeStoreNormal(
+  MUST_USE_RESULT MaybeObject* ComputeStoreNormal(
       StrictModeFlag strict_mode);
 
-  MUST_USE_RESULT static MaybeObject* ComputeStoreGlobal(
+  MUST_USE_RESULT MaybeObject* ComputeStoreGlobal(
       String* name,
       GlobalObject* receiver,
       JSGlobalPropertyCell* cell,
       StrictModeFlag strict_mode);
 
-  MUST_USE_RESULT static MaybeObject* ComputeStoreCallback(
+  MUST_USE_RESULT MaybeObject* ComputeStoreCallback(
       String* name,
       JSObject* receiver,
       AccessorInfo* callback,
       StrictModeFlag strict_mode);
 
-  MUST_USE_RESULT static MaybeObject* ComputeStoreInterceptor(
+  MUST_USE_RESULT MaybeObject* ComputeStoreInterceptor(
       String* name,
       JSObject* receiver,
       StrictModeFlag strict_mode);
 
   // ---
 
-  MUST_USE_RESULT static MaybeObject* ComputeKeyedStoreField(
+  MUST_USE_RESULT MaybeObject* ComputeKeyedStoreField(
       String* name,
       JSObject* receiver,
       int field_index,
       Map* transition,
       StrictModeFlag strict_mode);
 
-  MUST_USE_RESULT static MaybeObject* ComputeKeyedStoreSpecialized(
+  MUST_USE_RESULT MaybeObject* ComputeKeyedStoreSpecialized(
       JSObject* receiver,
       StrictModeFlag strict_mode);
 
-  MUST_USE_RESULT static MaybeObject* ComputeKeyedStorePixelArray(
-      JSObject* receiver,
-      StrictModeFlag strict_mode);
 
-  MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadOrStoreExternalArray(
+  MUST_USE_RESULT MaybeObject* ComputeKeyedLoadOrStoreExternalArray(
       JSObject* receiver,
       bool is_store,
       StrictModeFlag strict_mode);
 
   // ---
 
-  MUST_USE_RESULT static MaybeObject* ComputeCallField(int argc,
-                                                       InLoopFlag in_loop,
-                                                       Code::Kind,
-                                                       String* name,
-                                                       Object* object,
-                                                       JSObject* holder,
-                                                       int index);
+  MUST_USE_RESULT MaybeObject* ComputeCallField(int argc,
+                                                InLoopFlag in_loop,
+                                                Code::Kind,
+                                                String* name,
+                                                Object* object,
+                                                JSObject* holder,
+                                                int index);
 
-  MUST_USE_RESULT static MaybeObject* ComputeCallConstant(
+  MUST_USE_RESULT MaybeObject* ComputeCallConstant(
       int argc,
       InLoopFlag in_loop,
       Code::Kind,
@@ -207,19 +214,19 @@
       JSObject* holder,
       JSFunction* function);
 
-  MUST_USE_RESULT static MaybeObject* ComputeCallNormal(int argc,
-                                                        InLoopFlag in_loop,
-                                                        Code::Kind,
-                                                        String* name,
-                                                        JSObject* receiver);
+  MUST_USE_RESULT MaybeObject* ComputeCallNormal(int argc,
+                                                 InLoopFlag in_loop,
+                                                 Code::Kind,
+                                                 String* name,
+                                                 JSObject* receiver);
 
-  MUST_USE_RESULT static MaybeObject* ComputeCallInterceptor(int argc,
-                                                             Code::Kind,
-                                                             String* name,
-                                                             Object* object,
-                                                             JSObject* holder);
+  MUST_USE_RESULT MaybeObject* ComputeCallInterceptor(int argc,
+                                                      Code::Kind,
+                                                      String* name,
+                                                      Object* object,
+                                                      JSObject* holder);
 
-  MUST_USE_RESULT static MaybeObject* ComputeCallGlobal(
+  MUST_USE_RESULT MaybeObject* ComputeCallGlobal(
       int argc,
       InLoopFlag in_loop,
       Code::Kind,
@@ -231,80 +238,105 @@
 
   // ---
 
-  MUST_USE_RESULT static MaybeObject* ComputeCallInitialize(int argc,
-                                                            InLoopFlag in_loop,
-                                                            Code::Kind kind);
+  MUST_USE_RESULT MaybeObject* ComputeCallInitialize(int argc,
+                                                     InLoopFlag in_loop,
+                                                     Code::Kind kind);
 
-  static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
+  Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
 
-  static Handle<Code> ComputeKeyedCallInitialize(int argc, InLoopFlag in_loop);
+  Handle<Code> ComputeKeyedCallInitialize(int argc, InLoopFlag in_loop);
 
-  MUST_USE_RESULT static MaybeObject* ComputeCallPreMonomorphic(
+  MUST_USE_RESULT MaybeObject* ComputeCallPreMonomorphic(
       int argc,
       InLoopFlag in_loop,
       Code::Kind kind);
 
-  MUST_USE_RESULT static MaybeObject* ComputeCallNormal(int argc,
-                                                        InLoopFlag in_loop,
-                                                        Code::Kind kind);
+  MUST_USE_RESULT MaybeObject* ComputeCallNormal(int argc,
+                                                 InLoopFlag in_loop,
+                                                 Code::Kind kind);
 
-  MUST_USE_RESULT static MaybeObject* ComputeCallMegamorphic(int argc,
-                                                             InLoopFlag in_loop,
-                                                             Code::Kind kind);
-
-  MUST_USE_RESULT static MaybeObject* ComputeCallMiss(int argc,
+  MUST_USE_RESULT MaybeObject* ComputeCallMegamorphic(int argc,
+                                                      InLoopFlag in_loop,
                                                       Code::Kind kind);
 
+  MUST_USE_RESULT MaybeObject* ComputeCallMiss(int argc, Code::Kind kind);
+
   // Finds the Code object stored in the Heap::non_monomorphic_cache().
-  MUST_USE_RESULT static Code* FindCallInitialize(int argc,
-                                                  InLoopFlag in_loop,
-                                                  Code::Kind kind);
+  MUST_USE_RESULT Code* FindCallInitialize(int argc,
+                                           InLoopFlag in_loop,
+                                           Code::Kind kind);
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  MUST_USE_RESULT static MaybeObject* ComputeCallDebugBreak(int argc,
-                                                            Code::Kind kind);
+  MUST_USE_RESULT MaybeObject* ComputeCallDebugBreak(int argc, Code::Kind kind);
 
-  MUST_USE_RESULT static MaybeObject* ComputeCallDebugPrepareStepIn(
-      int argc,
-      Code::Kind kind);
+  MUST_USE_RESULT MaybeObject* ComputeCallDebugPrepareStepIn(int argc,
+                                                             Code::Kind kind);
 #endif
 
   // Update cache for entry hash(name, map).
-  static Code* Set(String* name, Map* map, Code* code);
+  Code* Set(String* name, Map* map, Code* code);
 
   // Clear the lookup table (@ mark compact collection).
-  static void Clear();
+  void Clear();
 
   // Collect all maps that match the name and flags.
-  static void CollectMatchingMaps(ZoneMapList* types,
-                                  String* name,
-                                  Code::Flags flags);
+  void CollectMatchingMaps(ZoneMapList* types,
+                           String* name,
+                           Code::Flags flags);
 
   // Generate code for probing the stub cache table.
   // Arguments extra and extra2 may be used to pass additional scratch
   // registers. Set to no_reg if not needed.
-  static void GenerateProbe(MacroAssembler* masm,
-                            Code::Flags flags,
-                            Register receiver,
-                            Register name,
-                            Register scratch,
-                            Register extra,
-                            Register extra2 = no_reg);
+  void GenerateProbe(MacroAssembler* masm,
+                     Code::Flags flags,
+                     Register receiver,
+                     Register name,
+                     Register scratch,
+                     Register extra,
+                     Register extra2 = no_reg);
 
   enum Table {
     kPrimary,
     kSecondary
   };
 
+
+  SCTableReference key_reference(StubCache::Table table) {
+    return SCTableReference(
+        reinterpret_cast<Address>(&first_entry(table)->key));
+  }
+
+
+  SCTableReference value_reference(StubCache::Table table) {
+    return SCTableReference(
+        reinterpret_cast<Address>(&first_entry(table)->value));
+  }
+
+
+  StubCache::Entry* first_entry(StubCache::Table table) {
+    switch (table) {
+      case StubCache::kPrimary: return StubCache::primary_;
+      case StubCache::kSecondary: return StubCache::secondary_;
+    }
+    UNREACHABLE();
+    return NULL;
+  }
+
+  Isolate* isolate() { return isolate_; }
+  Heap* heap() { return isolate()->heap(); }
+
  private:
+  explicit StubCache(Isolate* isolate);
+
+  friend class Isolate;
   friend class SCTableReference;
   static const int kPrimaryTableSize = 2048;
   static const int kSecondaryTableSize = 512;
-  static Entry primary_[];
-  static Entry secondary_[];
+  Entry primary_[kPrimaryTableSize];
+  Entry secondary_[kSecondaryTableSize];
 
   // Computes the hashed offsets for primary and secondary caches.
-  static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
+  RLYSTC 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
@@ -327,7 +359,7 @@
     return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
   }
 
-  static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
+  RLYSTC int SecondaryOffset(String* name, Code::Flags flags, int seed) {
     // Use the seed from the primary cache in the secondary cache.
     uint32_t string_low32bits =
         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
@@ -344,59 +376,33 @@
   // ends in String::kHashShift 0s.  Then we shift it so it is a multiple
   // of sizeof(Entry).  This makes it easier to avoid making mistakes
   // in the hashed offset computations.
-  static Entry* entry(Entry* table, int offset) {
+  RLYSTC Entry* entry(Entry* table, int offset) {
     const int shift_amount = kPointerSizeLog2 + 1 - String::kHashShift;
     return reinterpret_cast<Entry*>(
         reinterpret_cast<Address>(table) + (offset << shift_amount));
   }
+
+  Isolate* isolate_;
+
+  DISALLOW_COPY_AND_ASSIGN(StubCache);
 };
 
 
-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.
-MaybeObject* LoadCallbackProperty(Arguments args);
-MaybeObject* StoreCallbackProperty(Arguments args);
+MaybeObject* LoadCallbackProperty(RUNTIME_CALLING_CONVENTION);
+MaybeObject* StoreCallbackProperty(RUNTIME_CALLING_CONVENTION);
 
 
 // Support functions for IC stubs for interceptors.
-MaybeObject* LoadPropertyWithInterceptorOnly(Arguments args);
-MaybeObject* LoadPropertyWithInterceptorForLoad(Arguments args);
-MaybeObject* LoadPropertyWithInterceptorForCall(Arguments args);
-MaybeObject* StoreInterceptorProperty(Arguments args);
-MaybeObject* CallInterceptorProperty(Arguments args);
-MaybeObject* KeyedLoadPropertyWithInterceptor(Arguments args);
+MaybeObject* LoadPropertyWithInterceptorOnly(RUNTIME_CALLING_CONVENTION);
+MaybeObject* LoadPropertyWithInterceptorForLoad(RUNTIME_CALLING_CONVENTION);
+MaybeObject* LoadPropertyWithInterceptorForCall(RUNTIME_CALLING_CONVENTION);
+MaybeObject* StoreInterceptorProperty(RUNTIME_CALLING_CONVENTION);
+MaybeObject* CallInterceptorProperty(RUNTIME_CALLING_CONVENTION);
+MaybeObject* KeyedLoadPropertyWithInterceptor(RUNTIME_CALLING_CONVENTION);
 
 
 // The stub compiler compiles stubs for the stub cache.
@@ -554,6 +560,10 @@
                                     String* name,
                                     LookupResult* lookup);
 
+  Isolate* isolate() { return scope_.isolate(); }
+  Heap* heap() { return isolate()->heap(); }
+  Factory* factory() { return isolate()->factory(); }
+
  private:
   HandleScope scope_;
   MacroAssembler masm_;
@@ -623,7 +633,6 @@
   MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
 
   MUST_USE_RESULT MaybeObject* CompileLoadSpecialized(JSObject* receiver);
-  MUST_USE_RESULT MaybeObject* CompileLoadPixelArray(JSObject* receiver);
 
  private:
   MaybeObject* GetCode(PropertyType type, String* name);
@@ -669,8 +678,6 @@
 
   MUST_USE_RESULT MaybeObject* CompileStoreSpecialized(JSObject* receiver);
 
-  MUST_USE_RESULT MaybeObject* CompileStorePixelArray(JSObject* receiver);
-
  private:
   MaybeObject* GetCode(PropertyType type, String* name);
 
@@ -690,6 +697,8 @@
   V(MathAbs)
 
 
+class CallOptimization;
+
 class CallStubCompiler: public StubCompiler {
  public:
   CallStubCompiler(int argc,
@@ -716,14 +725,13 @@
                                                  JSFunction* function,
                                                  String* name);
 
-  static bool HasCustomCallGenerator(BuiltinFunctionId id);
+  static bool HasCustomCallGenerator(JSFunction* function);
 
  private:
   // Compiles a custom call constant/global IC. For constant calls
   // cell is NULL. Returns undefined if there is no custom call code
   // for the given function or it can't be generated.
-  MUST_USE_RESULT MaybeObject* CompileCustomCall(BuiltinFunctionId id,
-                                                 Object* object,
+  MUST_USE_RESULT MaybeObject* CompileCustomCall(Object* object,
                                                  JSObject* holder,
                                                  JSGlobalPropertyCell* cell,
                                                  JSFunction* function,
@@ -738,6 +746,14 @@
   CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
 #undef DECLARE_CALL_GENERATOR
 
+  MUST_USE_RESULT MaybeObject* CompileFastApiCall(
+      const CallOptimization& optimization,
+      Object* object,
+      JSObject* holder,
+      JSGlobalPropertyCell* cell,
+      JSFunction* function,
+      String* name);
+
   const ParameterCount arguments_;
   const InLoopFlag in_loop_;
   const Code::Kind kind_;
@@ -835,10 +851,10 @@
   explicit ExternalArrayStubCompiler() {}
 
   MUST_USE_RESULT MaybeObject* CompileKeyedLoadStub(
-      ExternalArrayType array_type, Code::Flags flags);
+      JSObject* receiver, ExternalArrayType array_type, Code::Flags flags);
 
   MUST_USE_RESULT MaybeObject* CompileKeyedStoreStub(
-      ExternalArrayType array_type, Code::Flags flags);
+      JSObject* receiver, ExternalArrayType array_type, Code::Flags flags);
 
  private:
   MaybeObject* GetCode(Code::Flags flags);
diff --git a/src/token.cc b/src/token.cc
index 488e909..feca7be 100644
--- a/src/token.cc
+++ b/src/token.cc
@@ -32,21 +32,21 @@
 namespace internal {
 
 #define T(name, string, precedence) #name,
-const char* Token::name_[NUM_TOKENS] = {
+const char* const Token::name_[NUM_TOKENS] = {
   TOKEN_LIST(T, T, IGNORE_TOKEN)
 };
 #undef T
 
 
 #define T(name, string, precedence) string,
-const char* Token::string_[NUM_TOKENS] = {
+const char* const Token::string_[NUM_TOKENS] = {
   TOKEN_LIST(T, T, IGNORE_TOKEN)
 };
 #undef T
 
 
 #define T(name, string, precedence) precedence,
-int8_t Token::precedence_[NUM_TOKENS] = {
+const int8_t Token::precedence_[NUM_TOKENS] = {
   TOKEN_LIST(T, T, IGNORE_TOKEN)
 };
 #undef T
diff --git a/src/token.h b/src/token.h
index 776d9f3..a0afbc1 100644
--- a/src/token.h
+++ b/src/token.h
@@ -277,9 +277,9 @@
   }
 
  private:
-  static const char* name_[NUM_TOKENS];
-  static const char* string_[NUM_TOKENS];
-  static int8_t precedence_[NUM_TOKENS];
+  static const char* const name_[NUM_TOKENS];
+  static const char* const string_[NUM_TOKENS];
+  static const int8_t precedence_[NUM_TOKENS];
   static const char token_type[NUM_TOKENS];
 };
 
diff --git a/src/top.cc b/src/top.cc
index 78db26a..ff29cad 100644
--- a/src/top.cc
+++ b/src/top.cc
@@ -37,31 +37,12 @@
 #include "string-stream.h"
 #include "vm-state-inl.h"
 
+// TODO(isolates): move to isolate.cc. This stuff is kept here to
+// simplify merging.
+
 namespace v8 {
 namespace internal {
 
-#ifdef ENABLE_LOGGING_AND_PROFILING
-Semaphore* Top::runtime_profiler_semaphore_ = NULL;
-#endif
-ThreadLocalTop Top::thread_local_;
-Mutex* Top::break_access_ = OS::CreateMutex();
-
-NoAllocationStringAllocator* preallocated_message_space = NULL;
-
-bool capture_stack_trace_for_uncaught_exceptions = false;
-int stack_trace_for_uncaught_exceptions_frame_limit = 0;
-StackTrace::StackTraceOptions stack_trace_for_uncaught_exceptions_options =
-    StackTrace::kOverview;
-
-Address top_addresses[] = {
-#define C(name) reinterpret_cast<Address>(Top::name()),
-    TOP_ADDRESS_LIST(C)
-    TOP_ADDRESS_LIST_PROF(C)
-#undef C
-    NULL
-};
-
-
 v8::TryCatch* ThreadLocalTop::TryCatchHandler() {
   return TRY_CATCH_FROM_ADDRESS(try_catch_handler_address());
 }
@@ -72,9 +53,9 @@
   handler_ = 0;
 #ifdef USE_SIMULATOR
 #ifdef V8_TARGET_ARCH_ARM
-  simulator_ = Simulator::current();
+  simulator_ = Simulator::current(Isolate::Current());
 #elif V8_TARGET_ARCH_MIPS
-  simulator_ = assembler::mips::Simulator::current();
+  simulator_ = Simulator::current(Isolate::Current());
 #endif
 #endif
 #ifdef ENABLE_LOGGING_AND_PROFILING
@@ -83,11 +64,10 @@
 #endif
 #ifdef ENABLE_VMSTATE_TRACKING
   current_vm_state_ = EXTERNAL;
-  runtime_profiler_state_ = Top::PROF_NOT_IN_JS;
 #endif
   try_catch_handler_address_ = NULL;
   context_ = NULL;
-  int id = ThreadManager::CurrentId();
+  int id = Isolate::Current()->thread_manager()->CurrentId();
   thread_id_ = (id == 0) ? ThreadManager::kInvalidId : id;
   external_caught_exception_ = false;
   failed_access_check_callback_ = NULL;
@@ -96,32 +76,32 @@
 }
 
 
-Address Top::get_address_from_id(Top::AddressId id) {
-  return top_addresses[id];
+Address Isolate::get_address_from_id(Isolate::AddressId id) {
+  return isolate_addresses_[id];
 }
 
 
-char* Top::Iterate(ObjectVisitor* v, char* thread_storage) {
+char* Isolate::Iterate(ObjectVisitor* v, char* thread_storage) {
   ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage);
   Iterate(v, thread);
   return thread_storage + sizeof(ThreadLocalTop);
 }
 
 
-void Top::IterateThread(ThreadVisitor* v) {
-  v->VisitThread(&thread_local_);
+void Isolate::IterateThread(ThreadVisitor* v) {
+  v->VisitThread(thread_local_top());
 }
 
 
-void Top::IterateThread(ThreadVisitor* v, char* t) {
+void Isolate::IterateThread(ThreadVisitor* v, char* t) {
   ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t);
   v->VisitThread(thread);
 }
 
 
-void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
+void Isolate::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
   // Visit the roots from the top for a given thread.
-  Object *pending;
+  Object* pending;
   // The pending exception can sometimes be a failure.  We can't show
   // that to the GC, which only understands objects.
   if (thread->pending_exception_->ToObject(&pending)) {
@@ -151,176 +131,13 @@
 }
 
 
-void Top::Iterate(ObjectVisitor* v) {
-  ThreadLocalTop* current_t = &thread_local_;
+void Isolate::Iterate(ObjectVisitor* v) {
+  ThreadLocalTop* current_t = thread_local_top();
   Iterate(v, current_t);
 }
 
 
-void Top::InitializeThreadLocal() {
-  thread_local_.Initialize();
-  clear_pending_exception();
-  clear_pending_message();
-  clear_scheduled_exception();
-}
-
-
-// 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()
-    : Thread("v8:PreallocMem"),
-      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, 15 * 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.start();
-    length_ = local_buffer.length();
-    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);
-
-#ifdef ENABLE_LOGGING_AND_PROFILING
-  ASSERT(runtime_profiler_semaphore_ == NULL);
-  runtime_profiler_semaphore_ = OS::CreateSemaphore(0);
-#endif
-
-  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) {
-#ifdef ENABLE_LOGGING_AND_PROFILING
-    delete runtime_profiler_semaphore_;
-    runtime_profiler_semaphore_ = NULL;
-#endif
-
-    // 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;
-  }
-}
-
-
-void Top::RegisterTryCatchHandler(v8::TryCatch* that) {
+void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) {
   // The ARM simulator has a separate JS stack.  We therefore register
   // the C++ try catch handler with the simulator and get back an
   // address that can be used for comparisons with addresses into the
@@ -328,68 +145,64 @@
   // returned will be the address of the C++ try catch handler itself.
   Address address = reinterpret_cast<Address>(
       SimulatorStack::RegisterCTryCatch(reinterpret_cast<uintptr_t>(that)));
-  thread_local_.set_try_catch_handler_address(address);
+  thread_local_top()->set_try_catch_handler_address(address);
 }
 
 
-void Top::UnregisterTryCatchHandler(v8::TryCatch* that) {
-  ASSERT(try_catch_handler() == that);
-  thread_local_.set_try_catch_handler_address(
+void Isolate::UnregisterTryCatchHandler(v8::TryCatch* that) {
+  ASSERT(thread_local_top()->TryCatchHandler() == that);
+  thread_local_top()->set_try_catch_handler_address(
       reinterpret_cast<Address>(that->next_));
-  thread_local_.catcher_ = NULL;
+  thread_local_top()->catcher_ = NULL;
   SimulatorStack::UnregisterCTryCatch();
 }
 
 
-
-static int stack_trace_nesting_level = 0;
-static StringStream* incomplete_message = NULL;
-
-
-Handle<String> Top::StackTraceString() {
-  if (stack_trace_nesting_level == 0) {
-    stack_trace_nesting_level++;
+Handle<String> Isolate::StackTraceString() {
+  if (stack_trace_nesting_level_ == 0) {
+    stack_trace_nesting_level_++;
     HeapStringAllocator allocator;
     StringStream::ClearMentionedObjectCache();
     StringStream accumulator(&allocator);
-    incomplete_message = &accumulator;
+    incomplete_message_ = &accumulator;
     PrintStack(&accumulator);
     Handle<String> stack_trace = accumulator.ToString();
-    incomplete_message = NULL;
-    stack_trace_nesting_level = 0;
+    incomplete_message_ = NULL;
+    stack_trace_nesting_level_ = 0;
     return stack_trace;
-  } else if (stack_trace_nesting_level == 1) {
-    stack_trace_nesting_level++;
+  } 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();
+    incomplete_message_->OutputToStdOut();
+    return factory()->empty_symbol();
   } else {
     OS::Abort();
     // Unreachable
-    return Factory::empty_symbol();
+    return factory()->empty_symbol();
   }
 }
 
 
-Handle<JSArray> Top::CaptureCurrentStackTrace(
+Handle<JSArray> Isolate::CaptureCurrentStackTrace(
     int frame_limit, StackTrace::StackTraceOptions options) {
   // Ensure no negative values.
   int limit = Max(frame_limit, 0);
-  Handle<JSArray> stack_trace = Factory::NewJSArray(frame_limit);
+  Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit);
 
-  Handle<String> column_key = Factory::LookupAsciiSymbol("column");
-  Handle<String> line_key = Factory::LookupAsciiSymbol("lineNumber");
-  Handle<String> script_key = Factory::LookupAsciiSymbol("scriptName");
+  Handle<String> column_key = factory()->LookupAsciiSymbol("column");
+  Handle<String> line_key = factory()->LookupAsciiSymbol("lineNumber");
+  Handle<String> script_key = factory()->LookupAsciiSymbol("scriptName");
   Handle<String> name_or_source_url_key =
-      Factory::LookupAsciiSymbol("nameOrSourceURL");
+      factory()->LookupAsciiSymbol("nameOrSourceURL");
   Handle<String> script_name_or_source_url_key =
-      Factory::LookupAsciiSymbol("scriptNameOrSourceURL");
-  Handle<String> function_key = Factory::LookupAsciiSymbol("functionName");
-  Handle<String> eval_key = Factory::LookupAsciiSymbol("isEval");
-  Handle<String> constructor_key = Factory::LookupAsciiSymbol("isConstructor");
+      factory()->LookupAsciiSymbol("scriptNameOrSourceURL");
+  Handle<String> function_key = factory()->LookupAsciiSymbol("functionName");
+  Handle<String> eval_key = factory()->LookupAsciiSymbol("isEval");
+  Handle<String> constructor_key =
+      factory()->LookupAsciiSymbol("isConstructor");
 
   StackTraceFrameIterator it;
   int frames_seen = 0;
@@ -400,7 +213,7 @@
     frame->Summarize(&frames);
     for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) {
       // Create a JSObject to hold the information for the StackFrame.
-      Handle<JSObject> stackFrame = Factory::NewJSObject(object_function());
+      Handle<JSObject> stackFrame = factory()->NewJSObject(object_function());
 
       Handle<JSFunction> fun = frames[i].function();
       Handle<Script> script(Script::cast(fun->shared()->script()));
@@ -429,12 +242,12 @@
       }
 
       if (options & StackTrace::kScriptName) {
-        Handle<Object> script_name(script->name());
+        Handle<Object> script_name(script->name(), this);
         SetLocalPropertyNoThrow(stackFrame, script_key, script_name);
       }
 
       if (options & StackTrace::kScriptNameOrSourceURL) {
-        Handle<Object> script_name(script->name());
+        Handle<Object> script_name(script->name(), this);
         Handle<JSValue> script_wrapper = GetScriptWrapper(script);
         Handle<Object> property = GetProperty(script_wrapper,
                                               name_or_source_url_key);
@@ -444,16 +257,16 @@
         Handle<Object> result = Execution::TryCall(method, script_wrapper, 0,
                                                    NULL, &caught_exception);
         if (caught_exception) {
-          result = Factory::undefined_value();
+          result = factory()->undefined_value();
         }
         SetLocalPropertyNoThrow(stackFrame, script_name_or_source_url_key,
                                 result);
       }
 
       if (options & StackTrace::kFunctionName) {
-        Handle<Object> fun_name(fun->shared()->name());
+        Handle<Object> fun_name(fun->shared()->name(), this);
         if (fun_name->ToBoolean()->IsFalse()) {
-          fun_name = Handle<Object>(fun->shared()->inferred_name());
+          fun_name = Handle<Object>(fun->shared()->inferred_name(), this);
         }
         SetLocalPropertyNoThrow(stackFrame, function_key, fun_name);
       }
@@ -461,13 +274,13 @@
       if (options & StackTrace::kIsEval) {
         int type = Smi::cast(script->compilation_type())->value();
         Handle<Object> is_eval = (type == Script::COMPILATION_TYPE_EVAL) ?
-            Factory::true_value() : Factory::false_value();
+            factory()->true_value() : factory()->false_value();
         SetLocalPropertyNoThrow(stackFrame, eval_key, is_eval);
       }
 
       if (options & StackTrace::kIsConstructor) {
         Handle<Object> is_constructor = (frames[i].is_constructor()) ?
-            Factory::true_value() : Factory::false_value();
+            factory()->true_value() : factory()->false_value();
         SetLocalPropertyNoThrow(stackFrame, constructor_key, is_constructor);
       }
 
@@ -482,41 +295,36 @@
 }
 
 
-void Top::PrintStack() {
-  if (stack_trace_nesting_level == 0) {
-    stack_trace_nesting_level++;
+void Isolate::PrintStack() {
+  if (stack_trace_nesting_level_ == 0) {
+    stack_trace_nesting_level_++;
 
     StringAllocator* allocator;
-    if (preallocated_message_space == NULL) {
+    if (preallocated_message_space_ == NULL) {
       allocator = new HeapStringAllocator();
     } else {
-      allocator = preallocated_message_space;
+      allocator = preallocated_message_space_;
     }
 
-    NativeAllocationChecker allocation_checker(
-      !FLAG_preallocate_message_memory ?
-      NativeAllocationChecker::ALLOW :
-      NativeAllocationChecker::DISALLOW);
-
     StringStream::ClearMentionedObjectCache();
     StringStream accumulator(allocator);
-    incomplete_message = &accumulator;
+    incomplete_message_ = &accumulator;
     PrintStack(&accumulator);
     accumulator.OutputToStdOut();
     accumulator.Log();
-    incomplete_message = NULL;
-    stack_trace_nesting_level = 0;
-    if (preallocated_message_space == NULL) {
+    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++;
+  } 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();
+    incomplete_message_->OutputToStdOut();
   }
 }
 
@@ -530,13 +338,20 @@
 }
 
 
-void Top::PrintStack(StringStream* accumulator) {
+void Isolate::PrintStack(StringStream* accumulator) {
+  if (!IsInitialized()) {
+    accumulator->Add(
+        "\n==== Stack trace is not available ==========================\n\n");
+    accumulator->Add(
+        "\n==== Isolate for the thread is not initialized =============\n\n");
+    return;
+  }
   // 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;
+  if (c_entry_fp(thread_local_top()) == 0) return;
 
   accumulator->Add(
       "\n==== Stack trace ============================================\n\n");
@@ -551,28 +366,29 @@
 }
 
 
-void Top::SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback) {
-  thread_local_.failed_access_check_callback_ = callback;
+void Isolate::SetFailedAccessCheckCallback(
+    v8::FailedAccessCheckCallback callback) {
+  thread_local_top()->failed_access_check_callback_ = callback;
 }
 
 
-void Top::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) {
-  if (!thread_local_.failed_access_check_callback_) return;
+void Isolate::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) {
+  if (!thread_local_top()->failed_access_check_callback_) return;
 
   ASSERT(receiver->IsAccessCheckNeeded());
-  ASSERT(Top::context());
+  ASSERT(context());
 
   // Get the data object from access check info.
   JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
   if (!constructor->shared()->IsApiFunction()) return;
   Object* data_obj =
       constructor->shared()->get_api_func_data()->access_check_info();
-  if (data_obj == Heap::undefined_value()) return;
+  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_(
+  thread_local_top()->failed_access_check_callback_(
     v8::Utils::ToLocal(receiver_handle),
     type,
     v8::Utils::ToLocal(data));
@@ -584,18 +400,19 @@
 };
 
 
-static MayAccessDecision MayAccessPreCheck(JSObject* receiver,
+static MayAccessDecision MayAccessPreCheck(Isolate* isolate,
+                                           JSObject* receiver,
                                            v8::AccessType type) {
   // During bootstrapping, callback functions are not enabled yet.
-  if (Bootstrapper::IsActive()) return YES;
+  if (isolate->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();
+    // avoid using Isolate::global_context() because it uses Handle.
+    Context* global_context = isolate->context()->global()->global_context();
     if (receiver_context == global_context) return YES;
 
     if (Context::cast(receiver_context)->security_token() ==
@@ -607,7 +424,8 @@
 }
 
 
-bool Top::MayNamedAccess(JSObject* receiver, Object* key, v8::AccessType type) {
+bool Isolate::MayNamedAccess(JSObject* receiver, Object* key,
+                             v8::AccessType type) {
   ASSERT(receiver->IsAccessCheckNeeded());
 
   // The callers of this method are not expecting a GC.
@@ -615,13 +433,13 @@
 
   // Skip checks for hidden properties access.  Note, we do not
   // require existence of a context in this case.
-  if (key == Heap::hidden_symbol()) return true;
+  if (key == heap_.hidden_symbol()) return true;
 
   // Check for compatibility between the security tokens in the
   // current lexical context and the accessed object.
-  ASSERT(Top::context());
+  ASSERT(context());
 
-  MayAccessDecision decision = MayAccessPreCheck(receiver, type);
+  MayAccessDecision decision = MayAccessPreCheck(this, receiver, type);
   if (decision != UNKNOWN) return decision == YES;
 
   // Get named access check callback
@@ -630,7 +448,7 @@
 
   Object* data_obj =
      constructor->shared()->get_api_func_data()->access_check_info();
-  if (data_obj == Heap::undefined_value()) return false;
+  if (data_obj == heap_.undefined_value()) return false;
 
   Object* fun_obj = AccessCheckInfo::cast(data_obj)->named_callback();
   v8::NamedSecurityCallback callback =
@@ -638,15 +456,15 @@
 
   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));
+  HandleScope scope(this);
+  Handle<JSObject> receiver_handle(receiver, this);
+  Handle<Object> key_handle(key, this);
+  Handle<Object> data(AccessCheckInfo::cast(data_obj)->data(), this);
+  LOG(this, ApiNamedSecurityCheck(key));
   bool result = false;
   {
     // Leaving JavaScript.
-    VMState state(EXTERNAL);
+    VMState state(this, EXTERNAL);
     result = callback(v8::Utils::ToLocal(receiver_handle),
                       v8::Utils::ToLocal(key_handle),
                       type,
@@ -656,17 +474,15 @@
 }
 
 
-bool Top::MayIndexedAccess(JSObject* receiver,
-                           uint32_t index,
-                           v8::AccessType type) {
+bool Isolate::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;
+  ASSERT(context());
 
-  MayAccessDecision decision = MayAccessPreCheck(receiver, type);
+  MayAccessDecision decision = MayAccessPreCheck(this, receiver, type);
   if (decision != UNKNOWN) return decision == YES;
 
   // Get indexed access check callback
@@ -675,7 +491,7 @@
 
   Object* data_obj =
       constructor->shared()->get_api_func_data()->access_check_info();
-  if (data_obj == Heap::undefined_value()) return false;
+  if (data_obj == heap_.undefined_value()) return false;
 
   Object* fun_obj = AccessCheckInfo::cast(data_obj)->indexed_callback();
   v8::IndexedSecurityCallback callback =
@@ -683,14 +499,14 @@
 
   if (!callback) return false;
 
-  HandleScope scope;
-  Handle<JSObject> receiver_handle(receiver);
-  Handle<Object> data(AccessCheckInfo::cast(data_obj)->data());
-  LOG(ApiIndexedSecurityCheck(index));
+  HandleScope scope(this);
+  Handle<JSObject> receiver_handle(receiver, this);
+  Handle<Object> data(AccessCheckInfo::cast(data_obj)->data(), this);
+  LOG(this, ApiIndexedSecurityCheck(index));
   bool result = false;
   {
     // Leaving JavaScript.
-    VMState state(EXTERNAL);
+    VMState state(this, EXTERNAL);
     result = callback(v8::Utils::ToLocal(receiver_handle),
                       index,
                       type,
@@ -700,15 +516,15 @@
 }
 
 
-const char* Top::kStackOverflowMessage =
+const char* const Isolate::kStackOverflowMessage =
   "Uncaught RangeError: Maximum call stack size exceeded";
 
 
-Failure* Top::StackOverflow() {
+Failure* Isolate::StackOverflow() {
   HandleScope scope;
-  Handle<String> key = Factory::stack_overflow_symbol();
+  Handle<String> key = factory()->stack_overflow_symbol();
   Handle<JSObject> boilerplate =
-      Handle<JSObject>::cast(GetProperty(Top::builtins(), key));
+      Handle<JSObject>::cast(GetProperty(js_builtins_object(), 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
@@ -719,23 +535,23 @@
 }
 
 
-Failure* Top::TerminateExecution() {
-  DoThrow(Heap::termination_exception(), NULL, NULL);
+Failure* Isolate::TerminateExecution() {
+  DoThrow(heap_.termination_exception(), NULL, NULL);
   return Failure::Exception();
 }
 
 
-Failure* Top::Throw(Object* exception, MessageLocation* location) {
+Failure* Isolate::Throw(Object* exception, MessageLocation* location) {
   DoThrow(exception, location, NULL);
   return Failure::Exception();
 }
 
 
-Failure* Top::ReThrow(MaybeObject* exception, MessageLocation* location) {
+Failure* Isolate::ReThrow(MaybeObject* exception, MessageLocation* location) {
   bool can_be_caught_externally = false;
   ShouldReportException(&can_be_caught_externally,
                         is_catchable_by_javascript(exception));
-  thread_local_.catcher_ = can_be_caught_externally ?
+  thread_local_top()->catcher_ = can_be_caught_externally ?
       try_catch_handler() : NULL;
 
   // Set the exception being re-thrown.
@@ -744,22 +560,22 @@
 }
 
 
-Failure* Top::ThrowIllegalOperation() {
-  return Throw(Heap::illegal_access_symbol());
+Failure* Isolate::ThrowIllegalOperation() {
+  return Throw(heap_.illegal_access_symbol());
 }
 
 
-void Top::ScheduleThrow(Object* exception) {
+void Isolate::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;
+  thread_local_top()->scheduled_exception_ = pending_exception();
+  thread_local_top()->external_caught_exception_ = false;
   clear_pending_exception();
 }
 
 
-Failure* Top::PromoteScheduledException() {
+Failure* Isolate::PromoteScheduledException() {
   MaybeObject* thrown = scheduled_exception();
   clear_scheduled_exception();
   // Re-throw the exception to avoid getting repeated error reporting.
@@ -767,13 +583,13 @@
 }
 
 
-void Top::PrintCurrentStackTrace(FILE* out) {
+void Isolate::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());
+    int pos = frame->LookupCode(this)->SourcePosition(frame->pc());
     Handle<Object> pos_obj(Smi::FromInt(pos));
     // Fetch function and receiver.
     Handle<JSFunction> fun(JSFunction::cast(frame->function()));
@@ -782,8 +598,8 @@
     // current frame is the top-level frame.
     it.Advance();
     Handle<Object> is_top_level = it.done()
-        ? Factory::true_value()
-        : Factory::false_value();
+        ? factory()->true_value()
+        : factory()->false_value();
     // Generate and print stack trace line.
     Handle<String> line =
         Execution::GetStackTraceLine(recv, fun, pos_obj, is_top_level);
@@ -795,8 +611,8 @@
 }
 
 
-void Top::ComputeLocation(MessageLocation* target) {
-  *target = MessageLocation(Handle<Script>(Heap::empty_script()), -1, -1);
+void Isolate::ComputeLocation(MessageLocation* target) {
+  *target = MessageLocation(Handle<Script>(heap_.empty_script()), -1, -1);
   StackTraceFrameIterator it;
   if (!it.done()) {
     JavaScriptFrame* frame = it.frame();
@@ -804,7 +620,7 @@
     Object* script = fun->shared()->script();
     if (script->IsScript() &&
         !(Script::cast(script)->source()->IsUndefined())) {
-      int pos = frame->code()->SourcePosition(frame->pc());
+      int pos = frame->LookupCode(this)->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);
@@ -813,18 +629,19 @@
 }
 
 
-bool Top::ShouldReportException(bool* can_be_caught_externally,
-                                bool catchable_by_javascript) {
+bool Isolate::ShouldReportException(bool* can_be_caught_externally,
+                                    bool catchable_by_javascript) {
   // Find the top-most try-catch handler.
   StackHandler* handler =
-      StackHandler::FromAddress(Top::handler(Top::GetCurrentThread()));
+      StackHandler::FromAddress(Isolate::handler(thread_local_top()));
   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.
-  Address external_handler_address = thread_local_.try_catch_handler_address();
+  Address external_handler_address =
+      thread_local_top()->try_catch_handler_address();
 
   // 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
@@ -843,9 +660,9 @@
 }
 
 
-void Top::DoThrow(MaybeObject* exception,
-                  MessageLocation* location,
-                  const char* message) {
+void Isolate::DoThrow(MaybeObject* exception,
+                      MessageLocation* location,
+                      const char* message) {
   ASSERT(!has_pending_exception());
 
   HandleScope scope;
@@ -865,7 +682,7 @@
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Notify debugger of exception.
   if (catchable_by_javascript) {
-    Debugger::OnException(exception_handle, report_exception);
+    debugger_->OnException(exception_handle, report_exception);
   }
 #endif
 
@@ -881,17 +698,17 @@
       ComputeLocation(&potential_computed_location);
       location = &potential_computed_location;
     }
-    if (!Bootstrapper::IsActive()) {
+    if (!bootstrapper()->IsActive()) {
       // It's not safe to try to make message objects or collect stack
       // traces while the bootstrapper is active since the infrastructure
       // may not have been properly initialized.
       Handle<String> stack_trace;
       if (FLAG_trace_exception) stack_trace = StackTraceString();
       Handle<JSArray> stack_trace_object;
-      if (report_exception && capture_stack_trace_for_uncaught_exceptions) {
-          stack_trace_object = Top::CaptureCurrentStackTrace(
-              stack_trace_for_uncaught_exceptions_frame_limit,
-              stack_trace_for_uncaught_exceptions_options);
+      if (report_exception && capture_stack_trace_for_uncaught_exceptions_) {
+          stack_trace_object = CaptureCurrentStackTrace(
+              stack_trace_for_uncaught_exceptions_frame_limit_,
+              stack_trace_for_uncaught_exceptions_options_);
       }
       ASSERT(is_object);  // Can't use the handle unless there's a real object.
       message_obj = MessageHandler::MakeMessageObject("uncaught_exception",
@@ -901,20 +718,20 @@
   }
 
   // Save the message for reporting if the the exception remains uncaught.
-  thread_local_.has_pending_message_ = report_exception;
-  thread_local_.pending_message_ = message;
+  thread_local_top()->has_pending_message_ = report_exception;
+  thread_local_top()->pending_message_ = message;
   if (!message_obj.is_null()) {
-    thread_local_.pending_message_obj_ = *message_obj;
+    thread_local_top()->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();
+      thread_local_top()->pending_message_script_ = *location->script();
+      thread_local_top()->pending_message_start_pos_ = location->start_pos();
+      thread_local_top()->pending_message_end_pos_ = location->end_pos();
     }
   }
 
   // Do not forget to clean catcher_ if currently thrown exception cannot
   // be caught.  If necessary, ReThrow will update the catcher.
-  thread_local_.catcher_ = can_be_caught_externally ?
+  thread_local_top()->catcher_ = can_be_caught_externally ?
       try_catch_handler() : NULL;
 
   // NOTE: Notifying the debugger or generating the message
@@ -930,11 +747,11 @@
 }
 
 
-bool Top::IsExternallyCaught() {
+bool Isolate::IsExternallyCaught() {
   ASSERT(has_pending_exception());
 
-  if ((thread_local_.catcher_ == NULL) ||
-      (try_catch_handler() != thread_local_.catcher_)) {
+  if ((thread_local_top()->catcher_ == NULL) ||
+      (try_catch_handler() != thread_local_top()->catcher_)) {
     // When throwing the exception, we found no v8::TryCatch
     // which should care about this exception.
     return false;
@@ -946,7 +763,8 @@
 
   // 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.
-  Address external_handler_address = thread_local_.try_catch_handler_address();
+  Address external_handler_address =
+      thread_local_top()->try_catch_handler_address();
   ASSERT(external_handler_address != NULL);
 
   // The exception has been externally caught if and only if there is
@@ -959,7 +777,7 @@
   // aborted by jumps in control flow like return, break, etc. and we'll
   // have another chances to set proper v8::TryCatch.
   StackHandler* handler =
-      StackHandler::FromAddress(Top::handler(Top::GetCurrentThread()));
+      StackHandler::FromAddress(Isolate::handler(thread_local_top()));
   while (handler != NULL && handler->address() < external_handler_address) {
     ASSERT(!handler->is_try_catch());
     if (handler->is_try_finally()) return false;
@@ -971,46 +789,48 @@
 }
 
 
-void Top::ReportPendingMessages() {
+void Isolate::ReportPendingMessages() {
   ASSERT(has_pending_exception());
   // 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.
   bool external_caught = IsExternallyCaught();
-  thread_local_.external_caught_exception_ = external_caught;
-  HandleScope scope;
-  if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) {
+  thread_local_top()->external_caught_exception_ = external_caught;
+  HandleScope scope(this);
+  if (thread_local_top()->pending_exception_ ==
+      Failure::OutOfMemoryException()) {
     context()->mark_out_of_memory();
-  } else if (thread_local_.pending_exception_ ==
-             Heap::termination_exception()) {
+  } else if (thread_local_top()->pending_exception_ ==
+             heap_.termination_exception()) {
     if (external_caught) {
       try_catch_handler()->can_continue_ = false;
-      try_catch_handler()->exception_ = Heap::null_value();
+      try_catch_handler()->exception_ = heap_.null_value();
     }
   } else {
     // At this point all non-object (failure) exceptions have
     // been dealt with so this shouldn't fail.
     Object* pending_exception_object = pending_exception()->ToObjectUnchecked();
     Handle<Object> exception(pending_exception_object);
-    thread_local_.external_caught_exception_ = false;
+    thread_local_top()->external_caught_exception_ = false;
     if (external_caught) {
       try_catch_handler()->can_continue_ = true;
-      try_catch_handler()->exception_ = thread_local_.pending_exception_;
-      if (!thread_local_.pending_message_obj_->IsTheHole()) {
-        try_catch_handler()->message_ = thread_local_.pending_message_obj_;
+      try_catch_handler()->exception_ = thread_local_top()->pending_exception_;
+      if (!thread_local_top()->pending_message_obj_->IsTheHole()) {
+        try_catch_handler()->message_ =
+            thread_local_top()->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_;
+    if (thread_local_top()->has_pending_message_) {
+      thread_local_top()->has_pending_message_ = false;
+      if (thread_local_top()->pending_message_ != NULL) {
+        MessageHandler::ReportMessage(thread_local_top()->pending_message_);
+      } else if (!thread_local_top()->pending_message_obj_->IsTheHole()) {
+        Handle<Object> message_obj(thread_local_top()->pending_message_obj_);
+        if (thread_local_top()->pending_message_script_ != NULL) {
+          Handle<Script> script(thread_local_top()->pending_message_script_);
+          int start_pos = thread_local_top()->pending_message_start_pos_;
+          int end_pos = thread_local_top()->pending_message_end_pos_;
           MessageLocation location(script, start_pos, end_pos);
           MessageHandler::ReportMessage(&location, message_obj);
         } else {
@@ -1018,40 +838,40 @@
         }
       }
     }
-    thread_local_.external_caught_exception_ = external_caught;
+    thread_local_top()->external_caught_exception_ = external_caught;
     set_pending_exception(*exception);
   }
   clear_pending_message();
 }
 
 
-void Top::TraceException(bool flag) {
-  FLAG_trace_exception = flag;
+void Isolate::TraceException(bool flag) {
+  FLAG_trace_exception = flag;  // TODO(isolates): This is an unfortunate use.
 }
 
 
-bool Top::OptionalRescheduleException(bool is_bottom_call) {
+bool Isolate::OptionalRescheduleException(bool is_bottom_call) {
   // Allways reschedule out of memory exceptions.
   if (!is_out_of_memory()) {
     bool is_termination_exception =
-        pending_exception() == Heap::termination_exception();
+        pending_exception() == heap_.termination_exception();
 
     // Do not reschedule the exception if this is the bottom call.
     bool clear_exception = is_bottom_call;
 
     if (is_termination_exception) {
       if (is_bottom_call) {
-        thread_local_.external_caught_exception_ = false;
+        thread_local_top()->external_caught_exception_ = false;
         clear_pending_exception();
         return false;
       }
-    } else if (thread_local_.external_caught_exception_) {
+    } else if (thread_local_top()->external_caught_exception_) {
       // 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.
-      ASSERT(thread_local_.try_catch_handler_address() != NULL);
+      ASSERT(thread_local_top()->try_catch_handler_address() != NULL);
       Address external_handler_address =
-          thread_local_.try_catch_handler_address();
+          thread_local_top()->try_catch_handler_address();
       JavaScriptFrameIterator it;
       if (it.done() || (it.frame()->sp() > external_handler_address)) {
         clear_exception = true;
@@ -1060,30 +880,30 @@
 
     // Clear the exception if needed.
     if (clear_exception) {
-      thread_local_.external_caught_exception_ = false;
+      thread_local_top()->external_caught_exception_ = false;
       clear_pending_exception();
       return false;
     }
   }
 
   // Reschedule the exception.
-  thread_local_.scheduled_exception_ = pending_exception();
+  thread_local_top()->scheduled_exception_ = pending_exception();
   clear_pending_exception();
   return true;
 }
 
 
-void Top::SetCaptureStackTraceForUncaughtExceptions(
+void Isolate::SetCaptureStackTraceForUncaughtExceptions(
       bool capture,
       int frame_limit,
       StackTrace::StackTraceOptions options) {
-  capture_stack_trace_for_uncaught_exceptions = capture;
-  stack_trace_for_uncaught_exceptions_frame_limit = frame_limit;
-  stack_trace_for_uncaught_exceptions_options = options;
+  capture_stack_trace_for_uncaught_exceptions_ = capture;
+  stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit;
+  stack_trace_for_uncaught_exceptions_options_ = options;
 }
 
 
-bool Top::is_out_of_memory() {
+bool Isolate::is_out_of_memory() {
   if (has_pending_exception()) {
     MaybeObject* e = pending_exception();
     if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) {
@@ -1100,20 +920,20 @@
 }
 
 
-Handle<Context> Top::global_context() {
-  GlobalObject* global = thread_local_.context_->global();
+Handle<Context> Isolate::global_context() {
+  GlobalObject* global = thread_local_top()->context_->global();
   return Handle<Context>(global->global_context());
 }
 
 
-Handle<Context> Top::GetCallingGlobalContext() {
+Handle<Context> Isolate::GetCallingGlobalContext() {
   JavaScriptFrameIterator it;
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  if (Debug::InDebugger()) {
+  if (debug_->InDebugger()) {
     while (!it.done()) {
       JavaScriptFrame* frame = it.frame();
       Context* context = Context::cast(frame->context());
-      if (context->global_context() == *Debug::debug_context()) {
+      if (context->global_context() == *debug_->debug_context()) {
         it.Advance();
       } else {
         break;
@@ -1128,25 +948,33 @@
 }
 
 
-char* Top::ArchiveThread(char* to) {
-  memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(thread_local_));
+char* Isolate::ArchiveThread(char* to) {
+  if (RuntimeProfiler::IsEnabled() && current_vm_state() == JS) {
+    RuntimeProfiler::IsolateExitedJS(this);
+  }
+  memcpy(to, reinterpret_cast<char*>(thread_local_top()),
+         sizeof(ThreadLocalTop));
   InitializeThreadLocal();
-  return to + sizeof(thread_local_);
+  return to + sizeof(ThreadLocalTop);
 }
 
 
-char* Top::RestoreThread(char* from) {
-  memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(thread_local_));
+char* Isolate::RestoreThread(char* from) {
+  memcpy(reinterpret_cast<char*>(thread_local_top()), from,
+         sizeof(ThreadLocalTop));
   // This might be just paranoia, but it seems to be needed in case a
   // thread_local_ is restored on a separate OS thread.
 #ifdef USE_SIMULATOR
 #ifdef V8_TARGET_ARCH_ARM
-  thread_local_.simulator_ = Simulator::current();
+  thread_local_top()->simulator_ = Simulator::current(this);
 #elif V8_TARGET_ARCH_MIPS
-  thread_local_.simulator_ = assembler::mips::Simulator::current();
+  thread_local_top()->simulator_ = Simulator::current(this);
 #endif
 #endif
-  return from + sizeof(thread_local_);
+  if (RuntimeProfiler::IsEnabled() && current_vm_state() == JS) {
+    RuntimeProfiler::IsolateEnteredJS(this);
+  }
+  return from + sizeof(ThreadLocalTop);
 }
 
 } }  // namespace v8::internal
diff --git a/src/top.h b/src/top.h
deleted file mode 100644
index 26ae542..0000000
--- a/src/top.h
+++ /dev/null
@@ -1,608 +0,0 @@
-// 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 "atomicops.h"
-#include "compilation-cache.h"
-#include "frames-inl.h"
-#include "runtime-profiler.h"
-
-namespace v8 {
-namespace internal {
-
-class Simulator;
-
-#define RETURN_IF_SCHEDULED_EXCEPTION() \
-  if (Top::has_scheduled_exception()) return Top::PromoteScheduledException()
-
-#define RETURN_IF_EMPTY_HANDLE_VALUE(call, value) \
-  if (call.is_null()) {                           \
-    ASSERT(Top::has_pending_exception());         \
-    return value;                                 \
-  }
-
-#define RETURN_IF_EMPTY_HANDLE(call)      \
-  RETURN_IF_EMPTY_HANDLE_VALUE(call, Failure::Exception())
-
-// Top has static variables used for JavaScript execution.
-
-class SaveContext;  // Forward declaration.
-class ThreadVisitor;  // Defined in v8threads.h
-class VMState;  // Defined in vm-state.h
-
-class ThreadLocalTop BASE_EMBEDDED {
- public:
-  // Initialize the thread data.
-  void Initialize();
-
-  // Get the top C++ try catch handler or NULL if none are registered.
-  //
-  // This method is not guarenteed to return an address that can be
-  // used for comparison with addresses into the JS stack.  If such an
-  // address is needed, use try_catch_handler_address.
-  v8::TryCatch* TryCatchHandler();
-
-  // Get the address of the top C++ try catch handler or NULL if
-  // none are registered.
-  //
-  // This method always returns an address that can be compared to
-  // pointers into the JavaScript stack.  When running on actual
-  // hardware, try_catch_handler_address and TryCatchHandler return
-  // the same pointer.  When running on a simulator with a separate JS
-  // stack, try_catch_handler_address returns a JS stack address that
-  // corresponds to the place on the JS stack where the C++ handler
-  // would have been if the stack were not separate.
-  inline Address try_catch_handler_address() {
-    return try_catch_handler_address_;
-  }
-
-  // Set the address of the top C++ try catch handler.
-  inline void set_try_catch_handler_address(Address address) {
-    try_catch_handler_address_ = address;
-  }
-
-  void Free() {
-    ASSERT(!has_pending_message_);
-    ASSERT(!external_caught_exception_);
-    ASSERT(try_catch_handler_address_ == NULL);
-  }
-
-  // The context where the current execution method is created and for variable
-  // lookups.
-  Context* context_;
-  int thread_id_;
-  MaybeObject* 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.
-  MaybeObject* scheduled_exception_;
-  bool external_caught_exception_;
-  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
-
-#ifdef USE_SIMULATOR
-#ifdef V8_TARGET_ARCH_ARM
-  Simulator* simulator_;
-#elif V8_TARGET_ARCH_MIPS
-  assembler::mips::Simulator* simulator_;
-#endif
-#endif  // USE_SIMULATOR
-
-#ifdef ENABLE_LOGGING_AND_PROFILING
-  Address js_entry_sp_;  // the stack pointer of the bottom js entry frame
-  Address external_callback_;  // the external callback we're currently in
-#endif
-
-#ifdef ENABLE_VMSTATE_TRACKING
-  StateTag current_vm_state_;
-
-  // Used for communication with the runtime profiler thread.
-  // Possible values are specified in RuntimeProfilerState.
-  Atomic32 runtime_profiler_state_;
-#endif
-
-  // Generated code scratch locations.
-  int32_t formal_count_;
-
-  // Call back function to report unsafe JS accesses.
-  v8::FailedAccessCheckCallback failed_access_check_callback_;
-
- private:
-  Address try_catch_handler_address_;
-};
-
-#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)
-
-#ifdef ENABLE_LOGGING_AND_PROFILING
-#define TOP_ADDRESS_LIST_PROF(C)       \
-  C(js_entry_sp_address)
-#else
-#define TOP_ADDRESS_LIST_PROF(C)
-#endif
-
-
-class Top {
- public:
-  enum AddressId {
-#define C(name) k_##name,
-    TOP_ADDRESS_LIST(C)
-    TOP_ADDRESS_LIST_PROF(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;
-  }
-
-  // Access to current thread id.
-  static int thread_id() { return thread_local_.thread_id_; }
-  static void set_thread_id(int id) { thread_local_.thread_id_ = id; }
-
-  // Interface to pending exception.
-  static MaybeObject* 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(MaybeObject* exception) {
-    thread_local_.pending_exception_ = exception;
-  }
-  static void clear_pending_exception() {
-    thread_local_.pending_exception_ = Heap::the_hole_value();
-  }
-
-  static MaybeObject** 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_.TryCatchHandler();
-  }
-  static Address try_catch_handler_address() {
-    return thread_local_.try_catch_handler_address();
-  }
-  // 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 OptionalRescheduleException(bool is_bottom_call);
-
-
-  static bool* external_caught_exception_address() {
-    return &thread_local_.external_caught_exception_;
-  }
-
-  static MaybeObject** scheduled_exception_address() {
-    return &thread_local_.scheduled_exception_;
-  }
-
-  static MaybeObject* 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 bool IsExternallyCaught();
-
-  static void SetCaptureStackTraceForUncaughtExceptions(
-      bool capture,
-      int frame_limit,
-      StackTrace::StackTraceOptions options);
-
-  // Tells whether the current context has experienced an out of memory
-  // exception.
-  static bool is_out_of_memory();
-
-  static bool is_catchable_by_javascript(MaybeObject* exception) {
-    return (exception != Failure::OutOfMemoryException()) &&
-        (exception != Heap::termination_exception());
-  }
-
-  // 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_; }
-
-#ifdef ENABLE_LOGGING_AND_PROFILING
-  // Bottom JS entry (see StackTracer::Trace in log.cc).
-  static Address js_entry_sp(ThreadLocalTop* thread) {
-    return thread->js_entry_sp_;
-  }
-  static inline Address* js_entry_sp_address() {
-    return &thread_local_.js_entry_sp_;
-  }
-
-  static Address external_callback() {
-    return thread_local_.external_callback_;
-  }
-  static void set_external_callback(Address callback) {
-    thread_local_.external_callback_ = callback;
-  }
-#endif
-
-#ifdef ENABLE_VMSTATE_TRACKING
-  static StateTag current_vm_state() {
-    return thread_local_.current_vm_state_;
-  }
-
-  static void SetCurrentVMState(StateTag state) {
-    if (RuntimeProfiler::IsEnabled()) {
-      if (state == JS) {
-        // JS or non-JS -> JS transition.
-        RuntimeProfilerState old_state = SwapRuntimeProfilerState(PROF_IN_JS);
-        if (old_state == PROF_NOT_IN_JS_WAITING_FOR_JS) {
-          // If the runtime profiler was waiting, we reset the eager
-          // optimizing data in the compilation cache to get a fresh
-          // start after not running JavaScript code for a while and
-          // signal the runtime profiler so it can resume.
-          CompilationCache::ResetEagerOptimizingData();
-          runtime_profiler_semaphore_->Signal();
-        }
-      } else if (thread_local_.current_vm_state_ == JS) {
-        // JS -> non-JS transition. Update the runtime profiler state.
-        ASSERT(IsInJSState());
-        SetRuntimeProfilerState(PROF_NOT_IN_JS);
-      }
-    }
-    thread_local_.current_vm_state_ = state;
-  }
-
-  // Called in the runtime profiler thread.
-  // Returns whether the current VM state is set to JS.
-  static bool IsInJSState() {
-    ASSERT(RuntimeProfiler::IsEnabled());
-    return static_cast<RuntimeProfilerState>(
-        NoBarrier_Load(&thread_local_.runtime_profiler_state_)) == PROF_IN_JS;
-  }
-
-  // Called in the runtime profiler thread.
-  // Waits for the VM state to transtion from non-JS to JS. Returns
-  // true when notified of the transition, false when the current
-  // state is not the expected non-JS state.
-  static bool WaitForJSState() {
-    ASSERT(RuntimeProfiler::IsEnabled());
-    // Try to switch to waiting state.
-    RuntimeProfilerState old_state = CompareAndSwapRuntimeProfilerState(
-        PROF_NOT_IN_JS, PROF_NOT_IN_JS_WAITING_FOR_JS);
-    if (old_state == PROF_NOT_IN_JS) {
-      runtime_profiler_semaphore_->Wait();
-      return true;
-    }
-    return false;
-  }
-
-  // When shutting down we join the profiler thread. Doing so while
-  // it's waiting on a semaphore will cause a deadlock, so we have to
-  // wake it up first.
-  static void WakeUpRuntimeProfilerThreadBeforeShutdown() {
-    runtime_profiler_semaphore_->Signal();
-  }
-#endif
-
-  // Generated code scratch locations.
-  static void* formal_count_address() { return &thread_local_.formal_count_; }
-
-  static void PrintCurrentStackTrace(FILE* out);
-  static void PrintStackTrace(FILE* out, char* thread_data);
-  static void PrintStack(StringStream* accumulator);
-  static void PrintStack();
-  static Handle<String> StackTraceString();
-  static Handle<JSArray> CaptureCurrentStackTrace(
-      int frame_limit,
-      StackTrace::StackTraceOptions options);
-
-  // 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(MaybeObject* exception,
-                          MessageLocation* location = NULL);
-  static void ScheduleThrow(Object* exception);
-  static void ReportPendingMessages();
-  static Failure* ThrowIllegalOperation();
-
-  // Promote a scheduled exception to pending. Asserts has_scheduled_exception.
-  static Failure* PromoteScheduledException();
-  static void DoThrow(MaybeObject* exception,
-                      MessageLocation* location,
-                      const char* message);
-  // Checks if exception should be reported and finds out if it's
-  // caught externally.
-  static bool ShouldReportException(bool* can_be_caught_externally,
-                                    bool catchable_by_javascript);
-
-  // 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();
-  static Failure* TerminateExecution();
-
-  // 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);
-  static void IterateThread(ThreadVisitor* v);
-  static void IterateThread(ThreadVisitor* 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();
-  }
-
-  // Returns the current global context.
-  static Handle<Context> global_context();
-
-  // Returns the global context of the calling JavaScript code.  That
-  // is, the global context of the top-most JavaScript frame.
-  static Handle<Context> GetCallingGlobalContext();
-
-  static Handle<JSBuiltinsObject> builtins() {
-    return Handle<JSBuiltinsObject>(thread_local_.context_->builtins());
-  }
-
-  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 void FreeThreadResources() { thread_local_.Free(); }
-
-  static const char* kStackOverflowMessage;
-
- private:
-#ifdef ENABLE_VMSTATE_TRACKING
-  // Set of states used when communicating with the runtime profiler.
-  //
-  // The set of possible transitions is divided between the VM and the
-  // profiler threads.
-  //
-  // The VM thread can perform these transitions:
-  //   o IN_JS -> NOT_IN_JS
-  //   o NOT_IN_JS -> IN_JS
-  //   o NOT_IN_JS_WAITING_FOR_JS -> IN_JS notifying the profiler thread
-  //     using the semaphore.
-  // All the above transitions are caused by VM state changes.
-  //
-  // The profiler thread can only perform a single transition
-  // NOT_IN_JS -> NOT_IN_JS_WAITING_FOR_JS before it starts waiting on
-  // the semaphore.
-  enum RuntimeProfilerState {
-    PROF_NOT_IN_JS,
-    PROF_NOT_IN_JS_WAITING_FOR_JS,
-    PROF_IN_JS
-  };
-
-  static void SetRuntimeProfilerState(RuntimeProfilerState state) {
-    NoBarrier_Store(&thread_local_.runtime_profiler_state_, state);
-  }
-
-  static RuntimeProfilerState SwapRuntimeProfilerState(
-      RuntimeProfilerState state) {
-    return static_cast<RuntimeProfilerState>(
-        NoBarrier_AtomicExchange(&thread_local_.runtime_profiler_state_,
-                                 state));
-  }
-
-  static RuntimeProfilerState CompareAndSwapRuntimeProfilerState(
-      RuntimeProfilerState old_state,
-      RuntimeProfilerState state) {
-    return static_cast<RuntimeProfilerState>(
-        NoBarrier_CompareAndSwap(&thread_local_.runtime_profiler_state_,
-                                 old_state,
-                                 state));
-  }
-
-  static Semaphore* runtime_profiler_semaphore_;
-#endif  // ENABLE_VMSTATE_TRACKING
-
-  // 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;
-  friend class ThreadLocalTop;
-
-  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() { Lock(); }
-  ~ExecutionAccess() { Unlock(); }
-
-  static void Lock() { Top::break_access_->Lock(); }
-  static void Unlock() { Top::break_access_->Unlock(); }
-
-  static bool TryLock() {
-    return Top::break_access_->TryLock();
-  }
-};
-
-} }  // namespace v8::internal
-
-#endif  // V8_TOP_H_
diff --git a/src/type-info.cc b/src/type-info.cc
index 3438ff8..78f693c 100644
--- a/src/type-info.cc
+++ b/src/type-info.cc
@@ -64,42 +64,70 @@
 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code,
                                        Handle<Context> global_context) {
   global_context_ = global_context;
-  Initialize(code);
+  PopulateMap(code);
+  ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue);
 }
 
 
-void TypeFeedbackOracle::Initialize(Handle<Code> code) {
-  ASSERT(map_.is_null());  // Only initialize once.
-  map_ = Factory::NewJSObject(Top::object_function());
-  PopulateMap(code);
+Handle<Object> TypeFeedbackOracle::GetInfo(int pos) {
+  int entry = dictionary_->FindEntry(pos);
+  return entry != NumberDictionary::kNotFound
+      ? Handle<Object>(dictionary_->ValueAt(entry))
+      : Isolate::Current()->factory()->undefined_value();
 }
 
 
 bool TypeFeedbackOracle::LoadIsMonomorphic(Property* expr) {
-  return GetElement(map_, expr->position())->IsMap();
+  Handle<Object> map_or_code(GetInfo(expr->position()));
+  if (map_or_code->IsMap()) return true;
+  if (map_or_code->IsCode()) {
+    Handle<Code> code(Code::cast(*map_or_code));
+    return code->kind() == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC &&
+        code->FindFirstMap() != NULL;
+  }
+  return false;
 }
 
 
-bool TypeFeedbackOracle:: StoreIsMonomorphic(Assignment* expr) {
-  return GetElement(map_, expr->position())->IsMap();
+bool TypeFeedbackOracle::StoreIsMonomorphic(Assignment* expr) {
+  Handle<Object> map_or_code(GetInfo(expr->position()));
+  if (map_or_code->IsMap()) return true;
+  if (map_or_code->IsCode()) {
+    Handle<Code> code(Code::cast(*map_or_code));
+    return code->kind() == Code::KEYED_EXTERNAL_ARRAY_STORE_IC &&
+        code->FindFirstMap() != NULL;
+  }
+  return false;
 }
 
 
 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) {
-  Handle<Object> value = GetElement(map_, expr->position());
+  Handle<Object> value = GetInfo(expr->position());
   return value->IsMap() || value->IsSmi();
 }
 
 
 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) {
   ASSERT(LoadIsMonomorphic(expr));
-  return Handle<Map>::cast(GetElement(map_, expr->position()));
+  Handle<Object> map_or_code(
+      Handle<HeapObject>::cast(GetInfo(expr->position())));
+  if (map_or_code->IsCode()) {
+    Handle<Code> code(Code::cast(*map_or_code));
+    return Handle<Map>(code->FindFirstMap());
+  }
+  return Handle<Map>(Map::cast(*map_or_code));
 }
 
 
 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Assignment* expr) {
   ASSERT(StoreIsMonomorphic(expr));
-  return Handle<Map>::cast(GetElement(map_, expr->position()));
+  Handle<HeapObject> map_or_code(
+      Handle<HeapObject>::cast(GetInfo(expr->position())));
+  if (map_or_code->IsCode()) {
+    Handle<Code> code(Code::cast(*map_or_code));
+    return Handle<Map>(code->FindFirstMap());
+  }
+  return Handle<Map>(Map::cast(*map_or_code));
 }
 
 
@@ -135,13 +163,26 @@
 
 
 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) {
-  Handle<Object> value = GetElement(map_, expr->position());
+  Handle<Object> value = GetInfo(expr->position());
   if (!value->IsSmi()) return RECEIVER_MAP_CHECK;
   CheckType check = static_cast<CheckType>(Smi::cast(*value)->value());
   ASSERT(check != RECEIVER_MAP_CHECK);
   return check;
 }
 
+ExternalArrayType TypeFeedbackOracle::GetKeyedLoadExternalArrayType(
+    Property* expr) {
+  Handle<Object> stub = GetInfo(expr->position());
+  ASSERT(stub->IsCode());
+  return Code::cast(*stub)->external_array_type();
+}
+
+ExternalArrayType TypeFeedbackOracle::GetKeyedStoreExternalArrayType(
+    Assignment* expr) {
+  Handle<Object> stub = GetInfo(expr->position());
+  ASSERT(stub->IsCode());
+  return Code::cast(*stub)->external_array_type();
+}
 
 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck(
     CheckType check) {
@@ -166,13 +207,13 @@
 
 
 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
-  Handle<Object> object = GetElement(map_, expr->position());
-  return *object == Builtins::builtin(id);
+  return *GetInfo(expr->position()) ==
+      Isolate::Current()->builtins()->builtin(id);
 }
 
 
 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) {
-  Handle<Object> object = GetElement(map_, expr->position());
+  Handle<Object> object = GetInfo(expr->position());
   TypeInfo unknown = TypeInfo::Unknown();
   if (!object->IsCode()) return unknown;
   Handle<Code> code = Handle<Code>::cast(object);
@@ -199,7 +240,7 @@
 
 
 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) {
-  Handle<Object> object = GetElement(map_, expr->position());
+  Handle<Object> object = GetInfo(expr->position());
   TypeInfo unknown = TypeInfo::Unknown();
   if (!object->IsCode()) return unknown;
   Handle<Code> code = Handle<Code>::cast(object);
@@ -261,7 +302,7 @@
 
 
 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) {
-  Handle<Object> object = GetElement(map_, clause->position());
+  Handle<Object> object = GetInfo(clause->position());
   TypeInfo unknown = TypeInfo::Unknown();
   if (!object->IsCode()) return unknown;
   Handle<Code> code = Handle<Code>::cast(object);
@@ -290,10 +331,11 @@
 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(int position,
                                                       Handle<String> name,
                                                       Code::Flags flags) {
-  Handle<Object> object = GetElement(map_, position);
+  Isolate* isolate = Isolate::Current();
+  Handle<Object> object = GetInfo(position);
   if (object->IsUndefined() || object->IsSmi()) return NULL;
 
-  if (*object == Builtins::builtin(Builtins::StoreIC_GlobalProxy)) {
+  if (*object == isolate->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) {
     // TODO(fschneider): We could collect the maps and signal that
     // we need a generic store (or load) here.
     ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC);
@@ -305,7 +347,7 @@
   } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) {
     ZoneMapList* types = new ZoneMapList(4);
     ASSERT(object->IsCode());
-    StubCache::CollectMatchingMaps(types, *name, flags);
+    isolate->stub_cache()->CollectMatchingMaps(types, *name, flags);
     return types->length() > 0 ? types : NULL;
   } else {
     return NULL;
@@ -314,52 +356,70 @@
 
 
 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) {
-  HandleScope scope;
+  Isolate* isolate = Isolate::Current();
+  HandleScope scope(isolate);
 
   const int kInitialCapacity = 16;
   List<int> code_positions(kInitialCapacity);
   List<int> source_positions(kInitialCapacity);
   CollectPositions(*code, &code_positions, &source_positions);
 
+  ASSERT(dictionary_.is_null());  // Only initialize once.
+  dictionary_ = isolate->factory()->NewNumberDictionary(
+      code_positions.length());
+
   int length = code_positions.length();
   ASSERT(source_positions.length() == length);
   for (int i = 0; i < length; i++) {
+    HandleScope loop_scope(isolate);
     RelocInfo info(code->instruction_start() + code_positions[i],
                    RelocInfo::CODE_TARGET, 0);
     Handle<Code> target(Code::GetCodeFromTargetAddress(info.target_address()));
     int position = source_positions[i];
     InlineCacheState state = target->ic_state();
     Code::Kind kind = target->kind();
+    Handle<Object> value;
     if (kind == Code::BINARY_OP_IC ||
         kind == Code::TYPE_RECORDING_BINARY_OP_IC ||
         kind == Code::COMPARE_IC) {
       // TODO(kasperl): Avoid having multiple ICs with the same
       // position by making sure that we have position information
       // recorded for all binary ICs.
-      if (GetElement(map_, position)->IsUndefined()) {
-        SetElement(map_, position, target, kNonStrictMode);
+      int entry = dictionary_->FindEntry(position);
+      if (entry == NumberDictionary::kNotFound) {
+        value = target;
       }
     } else if (state == MONOMORPHIC) {
-      if (target->kind() != Code::CALL_IC ||
+      if (kind == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC ||
+          kind == Code::KEYED_EXTERNAL_ARRAY_STORE_IC) {
+        value = target;
+      } else if (target->kind() != Code::CALL_IC ||
           target->check_type() == RECEIVER_MAP_CHECK) {
-        Handle<Map> map = Handle<Map>(target->FindFirstMap());
-        if (*map == NULL) {
-          SetElement(map_, position, target, kNonStrictMode);
+        Map* map = target->FindFirstMap();
+        if (map == NULL) {
+          value = target;
         } else {
-          SetElement(map_, position, map, kNonStrictMode);
+          value = Handle<Map>(map);
         }
       } else {
         ASSERT(target->kind() == Code::CALL_IC);
         CheckType check = target->check_type();
         ASSERT(check != RECEIVER_MAP_CHECK);
-        SetElement(map_, position,
-                   Handle<Object>(Smi::FromInt(check)), kNonStrictMode);
-        ASSERT(Smi::cast(*GetElement(map_, position))->value() == check);
+        value = Handle<Object>(Smi::FromInt(check));
       }
     } else if (state == MEGAMORPHIC) {
-      SetElement(map_, position, target, kNonStrictMode);
+      value = target;
+    }
+
+    if (!value.is_null()) {
+      Handle<NumberDictionary> new_dict =
+          isolate->factory()->DictionaryAtNumberPut(
+              dictionary_, position, value);
+      dictionary_ = loop_scope.CloseAndEscape(new_dict);
     }
   }
+  // Allocate handle in the parent scope.
+  dictionary_ = scope.CloseAndEscape(dictionary_);
 }
 
 
diff --git a/src/type-info.h b/src/type-info.h
index 34ff584..c068489 100644
--- a/src/type-info.h
+++ b/src/type-info.h
@@ -249,6 +249,9 @@
   ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name);
   ZoneMapList* CallReceiverTypes(Call* expr, Handle<String> name);
 
+  ExternalArrayType GetKeyedLoadExternalArrayType(Property* expr);
+  ExternalArrayType GetKeyedStoreExternalArrayType(Assignment* expr);
+
   CheckType GetCallCheckType(Call* expr);
   Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
 
@@ -260,8 +263,6 @@
   TypeInfo SwitchType(CaseClause* clause);
 
  private:
-  void Initialize(Handle<Code> code);
-
   ZoneMapList* CollectReceiverTypes(int position,
                                     Handle<String> name,
                                     Code::Flags flags);
@@ -272,8 +273,12 @@
                         List<int>* code_positions,
                         List<int>* source_positions);
 
+  // Returns an element from the backing store. Returns undefined if
+  // there is no information.
+  Handle<Object> GetInfo(int pos);
+
   Handle<Context> global_context_;
-  Handle<JSObject> map_;
+  Handle<NumberDictionary> dictionary_;
 
   DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
 };
diff --git a/src/unicode.cc b/src/unicode.cc
index 346f673..6e0ac1a 100644
--- a/src/unicode.cc
+++ b/src/unicode.cc
@@ -1572,7 +1572,7 @@
 }
 
 
-uchar UnicodeData::kMaxCodePoint = 65533;
+const uchar UnicodeData::kMaxCodePoint = 65533;
 
 int UnicodeData::GetByteCount() {
   return kUppercaseTable0Size * sizeof(int32_t)  // NOLINT
diff --git a/src/unicode.h b/src/unicode.h
index 9d1d683..39fc349 100644
--- a/src/unicode.h
+++ b/src/unicode.h
@@ -97,7 +97,7 @@
  private:
   friend class Test;
   static int GetByteCount();
-  static uchar kMaxCodePoint;
+  static const uchar kMaxCodePoint;
 };
 
 // --- U t f   8 ---
diff --git a/src/utils.h b/src/utils.h
index 219343b..b89f284 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -784,6 +784,9 @@
 };
 
 template <class Dest, class Source>
+INLINE(Dest BitCast(const Source& source));
+
+template <class Dest, class Source>
 inline Dest BitCast(const Source& source) {
   return BitCastHelper<Dest, Source>::cast(source);
 }
diff --git a/src/v8-counters.cc b/src/v8-counters.cc
index de2ce66..c6aa9cb 100644
--- a/src/v8-counters.cc
+++ b/src/v8-counters.cc
@@ -32,24 +32,31 @@
 namespace v8 {
 namespace internal {
 
+Counters::Counters() {
 #define HT(name, caption) \
-  HistogramTimer Counters::name = { #caption, NULL, false, 0, 0 }; \
-
-  HISTOGRAM_TIMER_LIST(HT)
-#undef SR
+    HistogramTimer name = { #caption, NULL, false, 0, 0 }; \
+    name##_ = name;
+    HISTOGRAM_TIMER_LIST(HT)
+#undef HT
 
 #define SC(name, caption) \
-  StatsCounter Counters::name = { "c:" #caption, NULL, false };
+    StatsCounter name = { "c:" #caption, NULL, false };\
+    name##_ = name;
 
-  STATS_COUNTER_LIST_1(SC)
-  STATS_COUNTER_LIST_2(SC)
+    STATS_COUNTER_LIST_1(SC)
+    STATS_COUNTER_LIST_2(SC)
 #undef SC
 
-StatsCounter Counters::state_counters[] = {
+  StatsCounter state_counters[] = {
 #define COUNTER_NAME(name) \
-  { "c:V8.State" #name, NULL, false },
-  STATE_TAG_LIST(COUNTER_NAME)
+    { "c:V8.State" #name, NULL, false },
+    STATE_TAG_LIST(COUNTER_NAME)
 #undef COUNTER_NAME
-};
+  };
+
+  for (int i = 0; i < kSlidingStateWindowCounterCount; ++i) {
+    state_counters_[i] = state_counters[i];
+  }
+}
 
 } }  // namespace v8::internal
diff --git a/src/v8-counters.h b/src/v8-counters.h
index 9b91ace..04482e8 100644
--- a/src/v8-counters.h
+++ b/src/v8-counters.h
@@ -128,7 +128,7 @@
   SC(gc_last_resort_from_handles, V8.GCLastResortFromHandles)         \
   SC(map_slow_to_fast_elements, V8.MapSlowToFastElements)             \
   SC(map_fast_to_slow_elements, V8.MapFastToSlowElements)             \
-  SC(map_to_pixel_array_elements, V8.MapToPixelArrayElements)         \
+  SC(map_to_external_array_elements, V8.MapToExternalArrayElements)   \
   /* How is the generic keyed-load stub used? */                      \
   SC(keyed_load_generic_smi, V8.KeyedLoadGenericSmi)                  \
   SC(keyed_load_generic_symbol, V8.KeyedLoadGenericSymbol)            \
@@ -207,8 +207,6 @@
   SC(memcopy_noxmm, V8.MemCopyNoXMM)                                  \
   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)                         \
   SC(compute_entry_frame, V8.ComputeEntryFrame)                       \
   SC(generic_binary_stub_calls, V8.GenericBinaryStubCalls)            \
@@ -254,15 +252,15 @@
 
 
 // This file contains all the v8 counters that are in use.
-class Counters : AllStatic {
+class Counters {
  public:
 #define HT(name, caption) \
-  static HistogramTimer name;
+  HistogramTimer* name() { return &name##_; }
   HISTOGRAM_TIMER_LIST(HT)
 #undef HT
 
 #define SC(name, caption) \
-  static StatsCounter name;
+  StatsCounter* name() { return &name##_; }
   STATS_COUNTER_LIST_1(SC)
   STATS_COUNTER_LIST_2(SC)
 #undef SC
@@ -272,17 +270,43 @@
     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)
+    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)
+    STATE_TAG_LIST(COUNTER_ID)
 #undef COUNTER_ID
     stats_counter_count
   };
 
+  StatsCounter* state_counters(StateTag state) {
+    return &state_counters_[state];
+  }
+
+ private:
+#define HT(name, caption) \
+  HistogramTimer name##_;
+  HISTOGRAM_TIMER_LIST(HT)
+#undef HT
+
+#define SC(name, caption) \
+  StatsCounter name##_;
+  STATS_COUNTER_LIST_1(SC)
+  STATS_COUNTER_LIST_2(SC)
+#undef SC
+
+  enum {
+#define COUNTER_ID(name) __##name,
+    STATE_TAG_LIST(COUNTER_ID)
+#undef COUNTER_ID
+    kSlidingStateWindowCounterCount
+  };
+
   // Sliding state window counters.
-  static StatsCounter state_counters[];
+  StatsCounter state_counters_[kSlidingStateWindowCounterCount];
+  friend class Isolate;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Counters);
 };
 
 } }  // namespace v8::internal
diff --git a/src/v8.cc b/src/v8.cc
index 945043d..8153372 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -27,6 +27,7 @@
 
 #include "v8.h"
 
+#include "isolate.h"
 #include "bootstrapper.h"
 #include "debug.h"
 #include "deoptimizer.h"
@@ -36,8 +37,6 @@
 #include "log.h"
 #include "runtime-profiler.h"
 #include "serialize.h"
-#include "simulator.h"
-#include "stub-cache.h"
 
 namespace v8 {
 namespace internal {
@@ -50,9 +49,24 @@
 
 
 bool V8::Initialize(Deserializer* des) {
-  bool create_heap_objects = des == NULL;
-  if (has_been_disposed_ || has_fatal_error_) return false;
-  if (IsRunning()) return true;
+  // The current thread may not yet had entered an isolate to run.
+  // Note the Isolate::Current() may be non-null because for various
+  // initialization purposes an initializing thread may be assigned an isolate
+  // but not actually enter it.
+  if (i::Isolate::CurrentPerIsolateThreadData() == NULL) {
+    i::Isolate::EnterDefaultIsolate();
+  }
+
+  ASSERT(i::Isolate::CurrentPerIsolateThreadData() != NULL);
+  ASSERT(i::Isolate::CurrentPerIsolateThreadData()->thread_id() ==
+         i::Thread::GetThreadLocalInt(i::Isolate::thread_id_key()));
+  ASSERT(i::Isolate::CurrentPerIsolateThreadData()->isolate() ==
+         i::Isolate::Current());
+
+  if (IsDead()) return false;
+
+  Isolate* isolate = Isolate::Current();
+  if (isolate->IsInitialized()) return true;
 
 #if defined(V8_TARGET_ARCH_ARM) && !defined(USE_ARM_EABI)
   use_crankshaft_ = false;
@@ -62,90 +76,13 @@
 
   // Peephole optimization might interfere with deoptimization.
   FLAG_peephole_optimization = !use_crankshaft_;
+
   is_running_ = true;
   has_been_setup_ = true;
   has_fatal_error_ = false;
   has_been_disposed_ = false;
-#ifdef DEBUG
-  // The initialization process does not handle memory exhaustion.
-  DisallowAllocationFailure disallow_allocation_failure;
-#endif
 
-  // Enable logging before setting up the heap
-  Logger::Setup();
-
-  CpuProfiler::Setup();
-  HeapProfiler::Setup();
-
-  // Setup the platform OS support.
-  OS::Setup();
-
-  // Initialize other runtime facilities
-#if defined(USE_SIMULATOR)
-#if defined(V8_TARGET_ARCH_ARM)
-  Simulator::Initialize();
-#elif defined(V8_TARGET_ARCH_MIPS)
-  ::assembler::mips::Simulator::Initialize();
-#endif
-#endif
-
-  { // NOLINT
-    // Ensure that the thread has a valid stack guard.  The v8::Locker object
-    // will ensure this too, but we don't have to use lockers if we are only
-    // using one thread.
-    ExecutionAccess lock;
-    StackGuard::InitThread(lock);
-  }
-
-  // Setup the object heap
-  ASSERT(!Heap::HasBeenSetup());
-  if (!Heap::Setup(create_heap_objects)) {
-    SetFatalError();
-    return false;
-  }
-
-  Bootstrapper::Initialize(create_heap_objects);
-  Builtins::Setup(create_heap_objects);
-  Top::Initialize();
-
-  if (FLAG_preemption) {
-    v8::Locker locker;
-    v8::Locker::StartPreemption(100);
-  }
-
-#ifdef ENABLE_DEBUGGER_SUPPORT
-  Debug::Setup(create_heap_objects);
-#endif
-  StubCache::Initialize(create_heap_objects);
-
-  // If we are deserializing, read the state into the now-empty heap.
-  if (des != NULL) {
-    des->Deserialize();
-    StubCache::Clear();
-  }
-
-  // Deserializing may put strange things in the root array's copy of the
-  // stack guard.
-  Heap::SetStackLimits();
-
-  // 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();
-
-  Deoptimizer::Setup();
-  LAllocator::Setup();
-  RuntimeProfiler::Setup();
-
-  // If we are deserializing, log non-function code objects and compiled
-  // functions found in the snapshot.
-  if (des != NULL && FLAG_log_code) {
-    HandleScope scope;
-    LOG(LogCodeObjects());
-    LOG(LogCompiledFunctions());
-  }
-
-  return true;
+  return isolate->Init(des);
 }
 
 
@@ -156,31 +93,11 @@
 
 
 void V8::TearDown() {
+  Isolate* isolate = Isolate::Current();
+  ASSERT(isolate->IsDefaultIsolate());
+
   if (!has_been_setup_ || has_been_disposed_) return;
-
-  if (FLAG_time_hydrogen) HStatistics::Instance()->Print();
-
-  // We must stop the logger before we tear down other components.
-  Logger::EnsureTickerStopped();
-
-  Deoptimizer::TearDown();
-
-  if (FLAG_preemption) {
-    v8::Locker locker;
-    v8::Locker::StopPreemption();
-  }
-
-  Builtins::TearDown();
-  Bootstrapper::TearDown();
-
-  Top::TearDown();
-
-  HeapProfiler::TearDown();
-  CpuProfiler::TearDown();
-  RuntimeProfiler::TearDown();
-
-  Logger::TearDown();
-  Heap::TearDown();
+  isolate->TearDown();
 
   is_running_ = false;
   has_been_disposed_ = true;
@@ -218,7 +135,9 @@
 
 
 // Used by JavaScript APIs
-uint32_t V8::Random() {
+uint32_t V8::Random(Isolate* isolate) {
+  ASSERT(isolate == Isolate::Current());
+  // TODO(isolates): move lo and hi to isolate
   static random_state state = {0, 0};
   return random_base(&state);
 }
@@ -227,7 +146,9 @@
 // Used internally by the JIT and memory allocator for security
 // purposes. So, we keep a different state to prevent informations
 // leaks that could be used in an exploit.
-uint32_t V8::RandomPrivate() {
+uint32_t V8::RandomPrivate(Isolate* isolate) {
+  ASSERT(isolate == Isolate::Current());
+  // TODO(isolates): move lo and hi to isolate
   static random_state state = {0, 0};
   return random_base(&state);
 }
@@ -239,7 +160,7 @@
   if (!FLAG_use_idle_notification) return true;
 
   // Tell the heap that it may want to adjust.
-  return Heap::IdleNotification();
+  return HEAP->IdleNotification();
 }
 
 
@@ -251,7 +172,7 @@
 
 
 Object* V8::FillHeapNumberWithRandom(Object* heap_number) {
-  uint64_t random_bits = Random();
+  uint64_t random_bits = Random(Isolate::Current());
   // Make a double* from address (heap_number + sizeof(double)).
   double_int_union* r = reinterpret_cast<double_int_union*>(
       reinterpret_cast<char*>(heap_number) +
diff --git a/src/v8.h b/src/v8.h
index cc1673e..e7ca0d2 100644
--- a/src/v8.h
+++ b/src/v8.h
@@ -86,6 +86,7 @@
   static bool UseCrankshaft() { return use_crankshaft_; }
   static void DisableCrankshaft() { use_crankshaft_ = false; }
   // To be dead you have to have lived
+  // TODO(isolates): move IsDead to Isolate.
   static bool IsDead() { return has_fatal_error_ || has_been_disposed_; }
   static void SetFatalError();
 
@@ -94,12 +95,12 @@
                                       bool take_snapshot = false);
 
   // Random number generation support. Not cryptographically safe.
-  static uint32_t Random();
+  static uint32_t Random(Isolate* isolate);
   // We use random numbers internally in memory allocation and in the
   // compilers for security. In order to prevent information leaks we
   // use a separate random state for internal random number
   // generation.
-  static uint32_t RandomPrivate();
+  static uint32_t RandomPrivate(Isolate* isolate);
   static Object* FillHeapNumberWithRandom(Object* heap_number);
 
   // Idle notification directly from the API.
diff --git a/src/v8globals.h b/src/v8globals.h
index d11bc38..2a01dfd 100644
--- a/src/v8globals.h
+++ b/src/v8globals.h
@@ -318,14 +318,15 @@
 // Must fit in the BitField PropertyDetails::TypeField.
 // A copy of this is in mirror-debugger.js.
 enum PropertyType {
-  NORMAL              = 0,  // only in slow mode
-  FIELD               = 1,  // only in fast mode
-  CONSTANT_FUNCTION   = 2,  // only in fast mode
-  CALLBACKS           = 3,
-  INTERCEPTOR         = 4,  // only in lookup results, not in descriptors.
-  MAP_TRANSITION      = 5,  // only in fast mode
-  CONSTANT_TRANSITION = 6,  // only in fast mode
-  NULL_DESCRIPTOR     = 7,  // only in fast mode
+  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
+  EXTERNAL_ARRAY_TRANSITION = 6,
+  CONSTANT_TRANSITION       = 7,  // only in fast mode
+  NULL_DESCRIPTOR           = 8,  // only in fast mode
   // All properties before MAP_TRANSITION are real.
   FIRST_PHANTOM_PROPERTY_TYPE = MAP_TRANSITION,
   // There are no IC stubs for NULL_DESCRIPTORS. Therefore,
@@ -443,11 +444,11 @@
 #define TRACK_MEMORY(name) \
   void* operator new(size_t size) { \
     void* result = ::operator new(size); \
-    Logger::NewEvent(name, result, size); \
+    Logger::NewEventStatic(name, result, size); \
     return result; \
   } \
   void operator delete(void* object) { \
-    Logger::DeleteEvent(name, object); \
+    Logger::DeleteEventStatic(name, object); \
     ::operator delete(object); \
   }
 #else
@@ -467,12 +468,17 @@
                   CPUID = 10,  // x86
                   VFP3 = 1,    // ARM
                   ARMv7 = 2,   // ARM
-                  SAHF = 0};   // x86
+                  SAHF = 0,    // x86
+                  FPU = 1};    // MIPS
 
 // The Strict Mode (ECMA-262 5th edition, 4.2.2).
 enum StrictModeFlag {
   kNonStrictMode,
-  kStrictMode
+  kStrictMode,
+  // This value is never used, but is needed to prevent GCC 4.5 from failing
+  // to compile when we assert that a flag is either kNonStrictMode or
+  // kStrictMode.
+  kInvalidStrictFlag
 };
 
 } }  // namespace v8::internal
diff --git a/src/memory.h b/src/v8memory.h
similarity index 100%
rename from src/memory.h
rename to src/v8memory.h
diff --git a/src/v8natives.js b/src/v8natives.js
index 563de73..4fcf0ac 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -251,7 +251,11 @@
   if (!IS_FUNCTION(fun)) {
     throw new $TypeError('Object.prototype.__defineGetter__: Expecting function');
   }
-  return %DefineAccessor(ToObject(this), ToString(name), GETTER, fun);
+  var desc = new PropertyDescriptor();
+  desc.setGet(fun);
+  desc.setEnumerable(true);
+  desc.setConfigurable(true);
+  DefineOwnProperty(ToObject(this), ToString(name), desc, false);
 }
 
 
@@ -271,7 +275,11 @@
     throw new $TypeError(
         'Object.prototype.__defineSetter__: Expecting function');
   }
-  return %DefineAccessor(ToObject(this), ToString(name), SETTER, fun);
+  var desc = new PropertyDescriptor();
+  desc.setSet(fun);
+  desc.setEnumerable(true);
+  desc.setConfigurable(true);
+  DefineOwnProperty(ToObject(this), ToString(name), desc, false);
 }
 
 
@@ -394,6 +402,10 @@
   this.hasSetter_ = false;
 }
 
+PropertyDescriptor.prototype.__proto__ = null;
+PropertyDescriptor.prototype.toString = function() {
+  return "[object PropertyDescriptor]";
+};
 
 PropertyDescriptor.prototype.setValue = function(value) {
   this.value_ = value;
@@ -495,7 +507,7 @@
 // property descriptor. For a description of the array layout please
 // see the runtime.cc file.
 function ConvertDescriptorArrayToDescriptor(desc_array) {
-  if (desc_array == false) {
+  if (desc_array === false) {
     throw 'Internal error: invalid desc_array';
   }
 
@@ -544,7 +556,7 @@
   var props = %GetOwnProperty(ToObject(obj), ToString(p));
 
   // A false value here means that access checks failed.
-  if (props == false) return void 0;
+  if (props === false) return void 0;
 
   return ConvertDescriptorArrayToDescriptor(props);
 }
@@ -554,15 +566,20 @@
 function DefineOwnProperty(obj, p, desc, should_throw) {
   var current_or_access = %GetOwnProperty(ToObject(obj), ToString(p));
   // A false value here means that access checks failed.
-  if (current_or_access == false) return void 0;
+  if (current_or_access === false) return void 0;
 
   var current = ConvertDescriptorArrayToDescriptor(current_or_access);
   var extensible = %IsExtensible(ToObject(obj));
 
   // Error handling according to spec.
   // Step 3
-  if (IS_UNDEFINED(current) && !extensible)
-    throw MakeTypeError("define_disallowed", ["defineProperty"]);
+  if (IS_UNDEFINED(current) && !extensible) {
+    if (should_throw) {
+      throw MakeTypeError("define_disallowed", ["defineProperty"]);
+    } else {
+      return;
+    }
+  }
 
   if (!IS_UNDEFINED(current)) {
     // Step 5 and 6
@@ -587,31 +604,55 @@
       if (desc.isConfigurable() ||
           (desc.hasEnumerable() &&
            desc.isEnumerable() != current.isEnumerable())) {
-        throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+        if (should_throw) {
+          throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+        } else {
+          return;
+        }
       }
       // Step 8
       if (!IsGenericDescriptor(desc)) {
         // Step 9a
         if (IsDataDescriptor(current) != IsDataDescriptor(desc)) {
-          throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+          if (should_throw) {
+            throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+          } else {
+            return;
+          }
         }
         // Step 10a
         if (IsDataDescriptor(current) && IsDataDescriptor(desc)) {
           if (!current.isWritable() && desc.isWritable()) {
-            throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+            if (should_throw) {
+              throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+            } else {
+              return;
+            }
           }
           if (!current.isWritable() && desc.hasValue() &&
               !SameValue(desc.getValue(), current.getValue())) {
-            throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+            if (should_throw) {
+              throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+            } else {
+              return;
+            }
           }
         }
         // Step 11
         if (IsAccessorDescriptor(desc) && IsAccessorDescriptor(current)) {
           if (desc.hasSetter() && !SameValue(desc.getSet(), current.getSet())) {
-            throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+            if (should_throw) {
+              throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+            } else {
+              return;
+            }
           }
           if (desc.hasGetter() && !SameValue(desc.getGet(),current.getGet())) {
-            throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+            if (should_throw) {
+              throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+            } else {
+              return;
+            }
           }
         }
       }
diff --git a/src/v8threads.cc b/src/v8threads.cc
index 8a5fe69..cecafaa 100644
--- a/src/v8threads.cc
+++ b/src/v8threads.cc
@@ -36,11 +36,6 @@
 
 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.
@@ -50,64 +45,88 @@
 // 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) {
+  // TODO(isolates): When Locker has Isolate parameter and it is provided, grab
+  // that one instead of using the current one.
+  // We pull default isolate for Locker constructor w/o p[arameter.
+  // A thread should not enter an isolate before acquiring a lock,
+  // in cases which mandate using Lockers.
+  // So getting a lock is the first thing threads do in a scenario where
+  // multple threads share an isolate. Hence, we need to access
+  // 'locking isolate' before we can actually enter into default isolate.
+  internal::Isolate* isolate = internal::Isolate::GetDefaultIsolateForLocking();
+  ASSERT(isolate != NULL);
+
   // 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();
+  if (!isolate->thread_manager()->IsLockedByCurrentThread()) {
+    isolate->thread_manager()->Lock();
     has_lock_ = true;
+
+    if (isolate->IsDefaultIsolate()) {
+      // This only enters if not yet entered.
+      internal::Isolate::EnterDefaultIsolate();
+    }
+
+    ASSERT(internal::Thread::HasThreadLocal(
+        internal::Isolate::thread_id_key()));
+
     // Make sure that V8 is initialized.  Archiving of threads interferes
     // with deserialization by adding additional root pointers, so we must
     // initialize here, before anyone can call ~Locker() or Unlocker().
-    if (!internal::V8::IsRunning()) {
+    if (!isolate->IsInitialized()) {
       V8::Initialize();
     }
     // 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()) {
+    if (isolate->thread_manager()->RestoreThread()) {
       top_level_ = false;
     } else {
-      internal::ExecutionAccess access;
-      internal::StackGuard::ClearThread(access);
-      internal::StackGuard::InitThread(access);
+      internal::ExecutionAccess access(isolate);
+      isolate->stack_guard()->ClearThread(access);
+      isolate->stack_guard()->InitThread(access);
     }
   }
-  ASSERT(internal::ThreadManager::IsLockedByCurrentThread());
-
-  // Make sure this thread is assigned a thread id.
-  internal::ThreadManager::AssignId();
+  ASSERT(isolate->thread_manager()->IsLockedByCurrentThread());
 }
 
 
 bool Locker::IsLocked() {
-  return internal::ThreadManager::IsLockedByCurrentThread();
+  return internal::Isolate::Current()->thread_manager()->
+      IsLockedByCurrentThread();
 }
 
 
 Locker::~Locker() {
-  ASSERT(internal::ThreadManager::IsLockedByCurrentThread());
+  // TODO(isolate): this should use a field storing the isolate it
+  // locked instead.
+  internal::Isolate* isolate = internal::Isolate::Current();
+  ASSERT(isolate->thread_manager()->IsLockedByCurrentThread());
   if (has_lock_) {
     if (top_level_) {
-      internal::ThreadManager::FreeThreadResources();
+      isolate->thread_manager()->FreeThreadResources();
     } else {
-      internal::ThreadManager::ArchiveThread();
+      isolate->thread_manager()->ArchiveThread();
     }
-    internal::ThreadManager::Unlock();
+    isolate->thread_manager()->Unlock();
   }
 }
 
 
 Unlocker::Unlocker() {
-  ASSERT(internal::ThreadManager::IsLockedByCurrentThread());
-  internal::ThreadManager::ArchiveThread();
-  internal::ThreadManager::Unlock();
+  internal::Isolate* isolate = internal::Isolate::Current();
+  ASSERT(isolate->thread_manager()->IsLockedByCurrentThread());
+  isolate->thread_manager()->ArchiveThread();
+  isolate->thread_manager()->Unlock();
 }
 
 
 Unlocker::~Unlocker() {
-  ASSERT(!internal::ThreadManager::IsLockedByCurrentThread());
-  internal::ThreadManager::Lock();
-  internal::ThreadManager::RestoreThread();
+  // TODO(isolates): check it's the isolate we unlocked.
+  internal::Isolate* isolate = internal::Isolate::Current();
+  ASSERT(!isolate->thread_manager()->IsLockedByCurrentThread());
+  isolate->thread_manager()->Lock();
+  isolate->thread_manager()->RestoreThread();
 }
 
 
@@ -130,44 +149,45 @@
   // 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) ==
+    ASSERT(Isolate::CurrentPerIsolateThreadData()->thread_state() ==
            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);
+    Isolate::CurrentPerIsolateThreadData()->set_thread_state(NULL);
     return true;
   }
 
   // Make sure that the preemption thread cannot modify the thread state while
   // it is being archived or restored.
-  ExecutionAccess access;
+  ExecutionAccess access(isolate_);
 
   // 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) {
+  Isolate::PerIsolateThreadData* per_thread =
+      Isolate::CurrentPerIsolateThreadData();
+  if (per_thread == NULL || per_thread->thread_state() == NULL) {
     // This is a new thread.
-    StackGuard::InitThread(access);
+    isolate_->stack_guard()->InitThread(access);
     return false;
   }
+  ThreadState* state = per_thread->thread_state();
   char* from = state->data();
-  from = HandleScopeImplementer::RestoreThread(from);
-  from = Top::RestoreThread(from);
+  from = isolate_->handle_scope_implementer()->RestoreThread(from);
+  from = isolate_->RestoreThread(from);
   from = Relocatable::RestoreState(from);
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  from = Debug::RestoreDebug(from);
+  from = isolate_->debug()->RestoreDebug(from);
 #endif
-  from = StackGuard::RestoreStackGuard(from);
-  from = RegExpStack::RestoreStack(from);
-  from = Bootstrapper::RestoreState(from);
-  Thread::SetThreadLocal(thread_state_key, NULL);
+  from = isolate_->stack_guard()->RestoreStackGuard(from);
+  from = isolate_->regexp_stack()->RestoreStack(from);
+  from = isolate_->bootstrapper()->RestoreState(from);
+  per_thread->set_thread_state(NULL);
   if (state->terminate_on_restore()) {
-    StackGuard::TerminateExecution();
+    isolate_->stack_guard()->TerminateExecution();
     state->set_terminate_on_restore(false);
   }
   state->set_id(kInvalidId);
@@ -192,7 +212,7 @@
 
 static int ArchiveSpacePerThread() {
   return HandleScopeImplementer::ArchiveSpacePerThread() +
-                            Top::ArchiveSpacePerThread() +
+                        Isolate::ArchiveSpacePerThread() +
 #ifdef ENABLE_DEBUGGER_SUPPORT
                           Debug::ArchiveSpacePerThread() +
 #endif
@@ -203,13 +223,12 @@
 }
 
 
-ThreadState* ThreadState::free_anchor_ = new ThreadState();
-ThreadState* ThreadState::in_use_anchor_ = new ThreadState();
-
-
-ThreadState::ThreadState() : id_(ThreadManager::kInvalidId),
-                             terminate_on_restore_(false),
-                             next_(this), previous_(this) {
+ThreadState::ThreadState(ThreadManager* thread_manager)
+    : id_(ThreadManager::kInvalidId),
+      terminate_on_restore_(false),
+      next_(this),
+      previous_(this),
+      thread_manager_(thread_manager) {
 }
 
 
@@ -226,7 +245,8 @@
 
 void ThreadState::LinkInto(List list) {
   ThreadState* flying_anchor =
-      list == FREE_LIST ? free_anchor_ : in_use_anchor_;
+      list == FREE_LIST ? thread_manager_->free_anchor_
+                        : thread_manager_->in_use_anchor_;
   next_ = flying_anchor->next_;
   previous_ = flying_anchor;
   flying_anchor->next_ = this;
@@ -234,10 +254,10 @@
 }
 
 
-ThreadState* ThreadState::GetFree() {
+ThreadState* ThreadManager::GetFreeThreadState() {
   ThreadState* gotten = free_anchor_->next_;
   if (gotten == free_anchor_) {
-    ThreadState* new_thread_state = new ThreadState();
+    ThreadState* new_thread_state = new ThreadState(this);
     new_thread_state->AllocateSpace();
     return new_thread_state;
   }
@@ -246,13 +266,13 @@
 
 
 // Gets the first in the list of archived threads.
-ThreadState* ThreadState::FirstInUse() {
+ThreadState* ThreadManager::FirstThreadStateInUse() {
   return in_use_anchor_->Next();
 }
 
 
 ThreadState* ThreadState::Next() {
-  if (next_ == in_use_anchor_) return NULL;
+  if (next_ == thread_manager_->in_use_anchor_) return NULL;
   return next_;
 }
 
@@ -260,19 +280,29 @@
 // Thread ids must start with 1, because in TLS having thread id 0 can't
 // be distinguished from not having a thread id at all (since NULL is
 // defined as 0.)
-int ThreadManager::last_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;
+ThreadManager::ThreadManager()
+    : mutex_(OS::CreateMutex()),
+      mutex_owner_(ThreadHandle::INVALID),
+      lazily_archived_thread_(ThreadHandle::INVALID),
+      lazily_archived_thread_state_(NULL),
+      free_anchor_(NULL),
+      in_use_anchor_(NULL) {
+  free_anchor_ = new ThreadState(this);
+  in_use_anchor_ = new ThreadState(this);
+}
+
+
+ThreadManager::~ThreadManager() {
+  // TODO(isolates): Destroy mutexes.
+}
 
 
 void ThreadManager::ArchiveThread() {
   ASSERT(!lazily_archived_thread_.IsValid());
   ASSERT(!IsArchived());
-  ThreadState* state = ThreadState::GetFree();
+  ThreadState* state = GetFreeThreadState();
   state->Unlink();
-  Thread::SetThreadLocal(thread_state_key, reinterpret_cast<void*>(state));
+  Isolate::CurrentPerIsolateThreadData()->set_thread_state(state);
   lazily_archived_thread_.Initialize(ThreadHandle::SELF);
   lazily_archived_thread_state_ = state;
   ASSERT(state->id() == kInvalidId);
@@ -287,84 +317,69 @@
   char* to = state->data();
   // Ensure that data containing GC roots are archived first, and handle them
   // in ThreadManager::Iterate(ObjectVisitor*).
-  to = HandleScopeImplementer::ArchiveThread(to);
-  to = Top::ArchiveThread(to);
+  to = isolate_->handle_scope_implementer()->ArchiveThread(to);
+  to = isolate_->ArchiveThread(to);
   to = Relocatable::ArchiveState(to);
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  to = Debug::ArchiveDebug(to);
+  to = isolate_->debug()->ArchiveDebug(to);
 #endif
-  to = StackGuard::ArchiveStackGuard(to);
-  to = RegExpStack::ArchiveStack(to);
-  to = Bootstrapper::ArchiveState(to);
+  to = isolate_->stack_guard()->ArchiveStackGuard(to);
+  to = isolate_->regexp_stack()->ArchiveStack(to);
+  to = isolate_->bootstrapper()->ArchiveState(to);
   lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
   lazily_archived_thread_state_ = NULL;
 }
 
 
 void ThreadManager::FreeThreadResources() {
-  HandleScopeImplementer::FreeThreadResources();
-  Top::FreeThreadResources();
+  isolate_->handle_scope_implementer()->FreeThreadResources();
+  isolate_->FreeThreadResources();
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  Debug::FreeThreadResources();
+  isolate_->debug()->FreeThreadResources();
 #endif
-  StackGuard::FreeThreadResources();
-  RegExpStack::FreeThreadResources();
-  Bootstrapper::FreeThreadResources();
+  isolate_->stack_guard()->FreeThreadResources();
+  isolate_->regexp_stack()->FreeThreadResources();
+  isolate_->bootstrapper()->FreeThreadResources();
 }
 
 
 bool ThreadManager::IsArchived() {
-  return Thread::HasThreadLocal(thread_state_key);
+  Isolate::PerIsolateThreadData* data = Isolate::CurrentPerIsolateThreadData();
+  return data != NULL && data->thread_state() != NULL;
 }
 
 
 void ThreadManager::Iterate(ObjectVisitor* v) {
   // Expecting no threads during serialization/deserialization
-  for (ThreadState* state = ThreadState::FirstInUse();
+  for (ThreadState* state = FirstThreadStateInUse();
        state != NULL;
        state = state->Next()) {
     char* data = state->data();
     data = HandleScopeImplementer::Iterate(v, data);
-    data = Top::Iterate(v, data);
+    data = isolate_->Iterate(v, data);
     data = Relocatable::Iterate(v, data);
   }
 }
 
 
 void ThreadManager::IterateArchivedThreads(ThreadVisitor* v) {
-  for (ThreadState* state = ThreadState::FirstInUse();
+  for (ThreadState* state = FirstThreadStateInUse();
        state != NULL;
        state = state->Next()) {
     char* data = state->data();
     data += HandleScopeImplementer::ArchiveSpacePerThread();
-    Top::IterateThread(v, data);
+    isolate_->IterateThread(v, data);
   }
 }
 
 
 int ThreadManager::CurrentId() {
-  return Thread::GetThreadLocalInt(thread_id_key);
-}
-
-
-void ThreadManager::AssignId() {
-  if (!HasId()) {
-    ASSERT(Locker::IsLocked());
-    int thread_id = ++last_id_;
-    ASSERT(thread_id > 0);  // see the comment near last_id_ definition.
-    Thread::SetThreadLocalInt(thread_id_key, thread_id);
-    Top::set_thread_id(thread_id);
-  }
-}
-
-
-bool ThreadManager::HasId() {
-  return Thread::HasThreadLocal(thread_id_key);
+  return Thread::GetThreadLocalInt(Isolate::thread_id_key());
 }
 
 
 void ThreadManager::TerminateExecution(int thread_id) {
-  for (ThreadState* state = ThreadState::FirstInUse();
+  for (ThreadState* state = FirstThreadStateInUse();
        state != NULL;
        state = state->Next()) {
     if (thread_id == state->id()) {
@@ -374,13 +389,8 @@
 }
 
 
-// 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)
-  : Thread("v8:CtxtSwitcher"),
+ContextSwitcher::ContextSwitcher(Isolate* isolate, int every_n_ms)
+  : Thread(isolate, "v8:CtxtSwitcher"),
     keep_going_(true),
     sleep_ms_(every_n_ms) {
 }
@@ -389,15 +399,16 @@
 // Set the scheduling interval of V8 threads. This function starts the
 // ContextSwitcher thread if needed.
 void ContextSwitcher::StartPreemption(int every_n_ms) {
+  Isolate* isolate = Isolate::Current();
   ASSERT(Locker::IsLocked());
-  if (singleton_ == NULL) {
+  if (isolate->context_switcher() == NULL) {
     // If the ContextSwitcher thread is not running at the moment start it now.
-    singleton_ = new ContextSwitcher(every_n_ms);
-    singleton_->Start();
+    isolate->set_context_switcher(new ContextSwitcher(isolate, every_n_ms));
+    isolate->context_switcher()->Start();
   } else {
     // ContextSwitcher thread is already running, so we just change the
     // scheduling interval.
-    singleton_->sleep_ms_ = every_n_ms;
+    isolate->context_switcher()->sleep_ms_ = every_n_ms;
   }
 }
 
@@ -405,15 +416,17 @@
 // 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() {
+  Isolate* isolate = Isolate::Current();
   ASSERT(Locker::IsLocked());
-  if (singleton_ != NULL) {
+  if (isolate->context_switcher() != 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.
+    isolate->context_switcher()->keep_going_ = false;
+    // Wait for the ContextSwitcher thread to exit.
+    isolate->context_switcher()->Join();
     // Thread has exited, now we can delete it.
-    delete(singleton_);
-    singleton_ = NULL;
+    delete(isolate->context_switcher());
+    isolate->set_context_switcher(NULL);
   }
 }
 
@@ -423,7 +436,7 @@
 void ContextSwitcher::Run() {
   while (keep_going_) {
     OS::Sleep(sleep_ms_);
-    StackGuard::Preempt();
+    isolate()->stack_guard()->Preempt();
   }
 }
 
diff --git a/src/v8threads.h b/src/v8threads.h
index da56d05..f1992ad 100644
--- a/src/v8threads.h
+++ b/src/v8threads.h
@@ -34,8 +34,6 @@
 
 class ThreadState {
  public:
-  // Iterate over in-use states.
-  static ThreadState* FirstInUse();
   // Returns NULL after the last one.
   ThreadState* Next();
 
@@ -44,8 +42,6 @@
   void LinkInto(List list);
   void Unlink();
 
-  static ThreadState* GetFree();
-
   // Id of thread.
   void set_id(int id) { id_ = id; }
   int id() { return id_; }
@@ -59,7 +55,7 @@
   // Get data area for archiving a thread.
   char* data() { return data_; }
  private:
-  ThreadState();
+  explicit ThreadState(ThreadManager* thread_manager);
 
   void AllocateSpace();
 
@@ -69,13 +65,9 @@
   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_;
+  ThreadManager* thread_manager_;
+
+  friend class ThreadManager;
 };
 
 
@@ -93,35 +85,52 @@
 };
 
 
-class ThreadManager : public AllStatic {
+class ThreadManager {
  public:
-  static void Lock();
-  static void Unlock();
+  void Lock();
+  void Unlock();
 
-  static void ArchiveThread();
-  static bool RestoreThread();
-  static void FreeThreadResources();
-  static bool IsArchived();
+  void ArchiveThread();
+  bool RestoreThread();
+  void FreeThreadResources();
+  bool IsArchived();
 
-  static void Iterate(ObjectVisitor* v);
-  static void IterateArchivedThreads(ThreadVisitor* v);
-  static bool IsLockedByCurrentThread() { return mutex_owner_.IsSelf(); }
+  void Iterate(ObjectVisitor* v);
+  void IterateArchivedThreads(ThreadVisitor* v);
+  bool IsLockedByCurrentThread() { return mutex_owner_.IsSelf(); }
 
-  static int CurrentId();
-  static void AssignId();
-  static bool HasId();
+  int CurrentId();
 
-  static void TerminateExecution(int thread_id);
+  void TerminateExecution(int thread_id);
+
+  // Iterate over in-use states.
+  ThreadState* FirstThreadStateInUse();
+  ThreadState* GetFreeThreadState();
 
   static const int kInvalidId = -1;
  private:
-  static void EagerlyArchiveThread();
+  ThreadManager();
+  ~ThreadManager();
 
-  static int last_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_;
+  void EagerlyArchiveThread();
+
+  Mutex* mutex_;
+  ThreadHandle mutex_owner_;
+  ThreadHandle lazily_archived_thread_;
+  ThreadState* lazily_archived_thread_state_;
+
+  // 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.
+  ThreadState* free_anchor_;
+  // Head of linked list of states in use.
+  ThreadState* in_use_anchor_;
+
+  Isolate* isolate_;
+
+  friend class Isolate;
+  friend class ThreadState;
 };
 
 
@@ -142,14 +151,12 @@
   static void PreemptionReceived();
 
  private:
-  explicit ContextSwitcher(int every_n_ms);
+  explicit ContextSwitcher(Isolate* isolate, int every_n_ms);
 
   void Run();
 
   bool keep_going_;
   int sleep_ms_;
-
-  static ContextSwitcher* singleton_;
 };
 
 } }  // namespace v8::internal
diff --git a/src/variables.h b/src/variables.h
index 5d27a02..67e1a18 100644
--- a/src/variables.h
+++ b/src/variables.h
@@ -165,7 +165,7 @@
 
   // True if the variable is named eval and not known to be shadowed.
   bool is_possibly_eval() const {
-    return IsVariable(Factory::eval_symbol()) &&
+    return IsVariable(FACTORY->eval_symbol()) &&
         (mode_ == DYNAMIC || mode_ == DYNAMIC_GLOBAL);
   }
 
diff --git a/src/version.cc b/src/version.cc
index ac4ab4a..6104dac 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,15 +34,36 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     2
-#define BUILD_NUMBER      0
-#define PATCH_LEVEL       1
-#define CANDIDATE_VERSION false
+#define BUILD_NUMBER      6
+#define PATCH_LEVEL       0
+// Use 1 for candidates and 0 otherwise.
+// (Boolean macro values are not supported by all preprocessors.)
+#define IS_CANDIDATE_VERSION 0
 
 // Define SONAME to have the SCons build the put a specific SONAME into the
 // shared library instead the generic SONAME generated from the V8 version
 // number. This define is mainly used by the SCons build script.
 #define SONAME            ""
 
+#if IS_CANDIDATE_VERSION
+#define CANDIDATE_STRING " (candidate)"
+#else
+#define CANDIDATE_STRING ""
+#endif
+
+#define SX(x) #x
+#define S(x) SX(x)
+
+#if PATCH_LEVEL > 0
+#define VERSION_STRING                                                         \
+    S(MAJOR_VERSION) "." S(MINOR_VERSION) "." S(BUILD_NUMBER) "."              \
+        S(PATCH_LEVEL) CANDIDATE_STRING
+#else
+#define VERSION_STRING                                                         \
+    S(MAJOR_VERSION) "." S(MINOR_VERSION) "." S(BUILD_NUMBER)                  \
+        CANDIDATE_STRING
+#endif
+
 namespace v8 {
 namespace internal {
 
@@ -50,9 +71,9 @@
 int Version::minor_ = MINOR_VERSION;
 int Version::build_ = BUILD_NUMBER;
 int Version::patch_ = PATCH_LEVEL;
-bool Version::candidate_ = CANDIDATE_VERSION;
+bool Version::candidate_ = (IS_CANDIDATE_VERSION != 0);
 const char* Version::soname_ = SONAME;
-
+const char* Version::version_string_ = VERSION_STRING;
 
 // Calculate the V8 version string.
 void Version::GetString(Vector<char> str) {
diff --git a/src/version.h b/src/version.h
index c322a2f..4b3e7e2 100644
--- a/src/version.h
+++ b/src/version.h
@@ -46,13 +46,17 @@
   // Calculate the SONAME for the V8 shared library.
   static void GetSONAME(Vector<char> str);
 
+  static const char* GetVersion() { return version_string_; }
+
  private:
+  // NOTE: can't make these really const because of test-version.cc.
   static int major_;
   static int minor_;
   static int build_;
   static int patch_;
   static bool candidate_;
   static const char* soname_;
+  static const char* version_string_;
 
   // In test-version.cc.
   friend void SetVersion(int major, int minor, int build, int patch,
diff --git a/src/virtual-frame-light-inl.h b/src/virtual-frame-light-inl.h
index 19520a6..681f93f 100644
--- a/src/virtual-frame-light-inl.h
+++ b/src/virtual-frame-light-inl.h
@@ -83,8 +83,9 @@
 VirtualFrame::RegisterAllocationScope::RegisterAllocationScope(
     CodeGenerator* cgen)
   : cgen_(cgen),
-    old_is_spilled_(SpilledScope::is_spilled_) {
-  SpilledScope::is_spilled_ = false;
+    old_is_spilled_(
+        Isolate::Current()->is_virtual_frame_in_spilled_scope()) {
+  Isolate::Current()->set_is_virtual_frame_in_spilled_scope(false);
   if (old_is_spilled_) {
     VirtualFrame* frame = cgen->frame();
     if (frame != NULL) {
@@ -95,7 +96,7 @@
 
 
 VirtualFrame::RegisterAllocationScope::~RegisterAllocationScope() {
-  SpilledScope::is_spilled_ = old_is_spilled_;
+  Isolate::Current()->set_is_virtual_frame_in_spilled_scope(old_is_spilled_);
   if (old_is_spilled_) {
     VirtualFrame* frame = cgen_->frame();
     if (frame != NULL) {
@@ -106,7 +107,7 @@
 
 
 CodeGenerator* VirtualFrame::cgen() const {
-  return CodeGeneratorScope::Current();
+  return CodeGeneratorScope::Current(Isolate::Current());
 }
 
 
diff --git a/src/vm-state-inl.h b/src/vm-state-inl.h
index da912b7..1f363de 100644
--- a/src/vm-state-inl.h
+++ b/src/vm-state-inl.h
@@ -58,25 +58,27 @@
   }
 }
 
-VMState::VMState(StateTag tag) : previous_tag_(Top::current_vm_state()) {
+
+VMState::VMState(Isolate* isolate, StateTag tag)
+    : isolate_(isolate), previous_tag_(isolate->current_vm_state()) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
   if (FLAG_log_state_changes) {
-    LOG(UncheckedStringEvent("Entering", StateToString(tag)));
-    LOG(UncheckedStringEvent("From", StateToString(previous_tag_)));
+    LOG(isolate, UncheckedStringEvent("Entering", StateToString(tag)));
+    LOG(isolate, UncheckedStringEvent("From", StateToString(previous_tag_)));
   }
 #endif
 
-  Top::SetCurrentVMState(tag);
+  isolate_->SetCurrentVMState(tag);
 
 #ifdef ENABLE_HEAP_PROTECTION
   if (FLAG_protect_heap) {
     if (tag == EXTERNAL) {
       // We are leaving V8.
       ASSERT(previous_tag_ != EXTERNAL);
-      Heap::Protect();
+      isolate_->heap()->Protect();
     } else if (previous_tag_ = EXTERNAL) {
       // We are entering V8.
-      Heap::Unprotect();
+      isolate_->heap()->Unprotect();
     }
   }
 #endif
@@ -86,27 +88,29 @@
 VMState::~VMState() {
 #ifdef ENABLE_LOGGING_AND_PROFILING
   if (FLAG_log_state_changes) {
-    LOG(UncheckedStringEvent("Leaving",
-                             StateToString(Top::current_vm_state())));
-    LOG(UncheckedStringEvent("To", StateToString(previous_tag_)));
+    LOG(isolate_,
+        UncheckedStringEvent("Leaving",
+                              StateToString(isolate_->current_vm_state())));
+    LOG(isolate_,
+        UncheckedStringEvent("To", StateToString(previous_tag_)));
   }
 #endif  // ENABLE_LOGGING_AND_PROFILING
 
 #ifdef ENABLE_HEAP_PROTECTION
-  StateTag tag = Top::current_vm_state();
+  StateTag tag = isolate_->current_vm_state();
 #endif
 
-  Top::SetCurrentVMState(previous_tag_);
+  isolate_->SetCurrentVMState(previous_tag_);
 
 #ifdef ENABLE_HEAP_PROTECTION
   if (FLAG_protect_heap) {
     if (tag == EXTERNAL) {
       // We are reentering V8.
       ASSERT(previous_tag_ != EXTERNAL);
-      Heap::Unprotect();
+      isolate_->heap()->Unprotect();
     } else if (previous_tag_ == EXTERNAL) {
       // We are leaving V8.
-      Heap::Protect();
+      isolate_->heap()->Protect();
     }
   }
 #endif  // ENABLE_HEAP_PROTECTION
@@ -117,13 +121,13 @@
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
 
-ExternalCallbackScope::ExternalCallbackScope(Address callback)
-    : previous_callback_(Top::external_callback()) {
-  Top::set_external_callback(callback);
+ExternalCallbackScope::ExternalCallbackScope(Isolate* isolate, Address callback)
+    : isolate_(isolate), previous_callback_(isolate->external_callback()) {
+  isolate_->set_external_callback(callback);
 }
 
 ExternalCallbackScope::~ExternalCallbackScope() {
-  Top::set_external_callback(previous_callback_);
+  isolate_->set_external_callback(previous_callback_);
 }
 
 #endif  // ENABLE_LOGGING_AND_PROFILING
diff --git a/src/vm-state.h b/src/vm-state.h
index df7fb30..11fc6d6 100644
--- a/src/vm-state.h
+++ b/src/vm-state.h
@@ -28,7 +28,7 @@
 #ifndef V8_VM_STATE_H_
 #define V8_VM_STATE_H_
 
-#include "top.h"
+#include "isolate.h"
 
 namespace v8 {
 namespace internal {
@@ -36,15 +36,16 @@
 class VMState BASE_EMBEDDED {
 #ifdef ENABLE_VMSTATE_TRACKING
  public:
-  inline explicit VMState(StateTag tag);
+  inline VMState(Isolate* isolate, StateTag tag);
   inline ~VMState();
 
  private:
+  Isolate* isolate_;
   StateTag previous_tag_;
 
 #else
  public:
-  explicit VMState(StateTag state) {}
+  VMState(Isolate* isolate, StateTag state) {}
 #endif
 };
 
@@ -52,13 +53,14 @@
 class ExternalCallbackScope BASE_EMBEDDED {
 #ifdef ENABLE_LOGGING_AND_PROFILING
  public:
-  inline explicit ExternalCallbackScope(Address callback);
+  inline ExternalCallbackScope(Isolate* isolate, Address callback);
   inline ~ExternalCallbackScope();
  private:
+  Isolate* isolate_;
   Address previous_callback_;
 #else
  public:
-  explicit ExternalCallbackScope(Address callback) {}
+  ExternalCallbackScope(Isolate* isolate, Address callback) {}
 #endif
 };
 
diff --git a/src/win32-headers.h b/src/win32-headers.h
index b51a38a..fca5c13 100644
--- a/src/win32-headers.h
+++ b/src/win32-headers.h
@@ -66,6 +66,7 @@
 #endif  // __MINGW32__
 #ifndef __MINGW32__
 #include <dbghelp.h>  // For SymLoadModule64 and al.
+#include <errno.h>  // For STRUNCATE
 #endif  // __MINGW32__
 #include <limits.h>  // For INT_MAX and al.
 #include <tlhelp32.h>  // For Module32First and al.
diff --git a/src/x64/assembler-x64-inl.h b/src/x64/assembler-x64-inl.h
index b082624..439236a 100644
--- a/src/x64/assembler-x64-inl.h
+++ b/src/x64/assembler-x64-inl.h
@@ -30,7 +30,7 @@
 
 #include "cpu.h"
 #include "debug.h"
-#include "memory.h"
+#include "v8memory.h"
 
 namespace v8 {
 namespace internal {
@@ -372,11 +372,12 @@
     visitor->VisitExternalReference(target_reference_address());
     CPU::FlushICache(pc_, sizeof(Address));
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  } else if (Debug::has_break_points() &&
-             ((RelocInfo::IsJSReturn(mode) &&
+  // TODO(isolates): Get a cached isolate below.
+  } else if (((RelocInfo::IsJSReturn(mode) &&
               IsPatchedReturnSequence()) ||
              (RelocInfo::IsDebugBreakSlot(mode) &&
-              IsPatchedDebugBreakSlotSequence()))) {
+              IsPatchedDebugBreakSlotSequence())) &&
+             Isolate::Current()->debug()->has_break_points()) {
     visitor->VisitDebugTarget(this);
 #endif
   } else if (mode == RelocInfo::RUNTIME_ENTRY) {
@@ -386,10 +387,10 @@
 
 
 template<typename StaticVisitor>
-void RelocInfo::Visit() {
+void RelocInfo::Visit(Heap* heap) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
-    StaticVisitor::VisitPointer(target_object_address());
+    StaticVisitor::VisitPointer(heap, target_object_address());
     CPU::FlushICache(pc_, sizeof(Address));
   } else if (RelocInfo::IsCodeTarget(mode)) {
     StaticVisitor::VisitCodeTarget(this);
@@ -399,7 +400,7 @@
     StaticVisitor::VisitExternalReference(target_reference_address());
     CPU::FlushICache(pc_, sizeof(Address));
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  } else if (Debug::has_break_points() &&
+  } else if (heap->isolate()->debug()->has_break_points() &&
              ((RelocInfo::IsJSReturn(mode) &&
               IsPatchedReturnSequence()) ||
              (RelocInfo::IsDebugBreakSlot(mode) &&
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 41111a7..0744b8a 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -38,14 +38,15 @@
 // -----------------------------------------------------------------------------
 // Implementation of CpuFeatures
 
-// The required user mode extensions in X64 are (from AMD64 ABI Table A.1):
-//   fpu, tsc, cx8, cmov, mmx, sse, sse2, fxsr, syscall
-uint64_t CpuFeatures::supported_ = kDefaultCpuFeatures;
-uint64_t CpuFeatures::enabled_ = 0;
-uint64_t CpuFeatures::found_by_runtime_probing_ = 0;
+CpuFeatures::CpuFeatures()
+    : supported_(kDefaultCpuFeatures),
+      enabled_(0),
+      found_by_runtime_probing_(0) {
+}
+
 
 void CpuFeatures::Probe(bool portable)  {
-  ASSERT(Heap::HasBeenSetup());
+  ASSERT(HEAP->HasBeenSetup());
   supported_ = kDefaultCpuFeatures;
   if (portable && Serializer::enabled()) {
     supported_ |= OS::CpuFeaturesImpliedByPlatform();
@@ -118,13 +119,16 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  MaybeObject* maybe_code = Heap::CreateCode(desc,
-                                             Code::ComputeFlags(Code::STUB),
-                                             Handle<Object>());
+  Isolate* isolate = Isolate::Current();
+  MaybeObject* maybe_code =
+      isolate->heap()->CreateCode(desc,
+                                  Code::ComputeFlags(Code::STUB),
+                                  Handle<Object>());
   Object* code;
   if (!maybe_code->ToObject(&code)) return;
   if (!code->IsCode()) return;
-  PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG,
+  PROFILE(isolate,
+          CodeCreateEvent(Logger::BUILTIN_TAG,
                           Code::cast(code), "CpuFeatures::Probe"));
   typedef uint64_t (*F0)();
   F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry());
@@ -191,12 +195,12 @@
 // Register constants.
 
 const int Register::kRegisterCodeByAllocationIndex[kNumAllocatableRegisters] = {
-  // rax, rbx, rdx, rcx, rdi, r8, r9, r11, r14, r12
-  0, 3, 2, 1, 7, 8, 9, 11, 14, 12
+  // rax, rbx, rdx, rcx, rdi, r8, r9, r11, r14, r15
+  0, 3, 2, 1, 7, 8, 9, 11, 14, 15
 };
 
 const int Register::kAllocationIndexByRegisterCode[kNumRegisters] = {
-  0, 3, 2, 1, -1, -1, -1, 4, 5, 6, -1, 7, 9, -1, 8, -1
+  0, 3, 2, 1, -1, -1, -1, 4, 5, 6, -1, 7, -1, -1, 8, 9
 };
 
 
@@ -335,18 +339,19 @@
 static void InitCoverageLog();
 #endif
 
-byte* Assembler::spare_buffer_ = NULL;
-
 Assembler::Assembler(void* buffer, int buffer_size)
-    : code_targets_(100), positions_recorder_(this) {
+    : AssemblerBase(Isolate::Current()),
+      code_targets_(100),
+      positions_recorder_(this),
+      emit_debug_code_(FLAG_debug_code) {
   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 (isolate()->assembler_spare_buffer() != NULL) {
+        buffer = isolate()->assembler_spare_buffer();
+        isolate()->set_assembler_spare_buffer(NULL);
       }
     }
     if (buffer == NULL) {
@@ -388,8 +393,9 @@
 
 Assembler::~Assembler() {
   if (own_buffer_) {
-    if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
-      spare_buffer_ = buffer_;
+    if (isolate()->assembler_spare_buffer() == NULL &&
+        buffer_size_ == kMinimalBufferSize) {
+      isolate()->set_assembler_spare_buffer(buffer_);
     } else {
       DeleteArray(buffer_);
     }
@@ -409,8 +415,6 @@
   desc->reloc_size =
       static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos());
   desc->origin = this;
-
-  Counters::reloc_info_size.Increment(desc->reloc_size);
 }
 
 
@@ -487,7 +491,7 @@
   // 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::MaxOldGenerationSize())) {
+      (desc.buffer_size > HEAP->MaxOldGenerationSize())) {
     V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
   }
 
@@ -512,8 +516,9 @@
           reloc_info_writer.pos(), desc.reloc_size);
 
   // Switch buffers.
-  if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
-    spare_buffer_ = buffer_;
+  if (isolate()->assembler_spare_buffer() == NULL &&
+      buffer_size_ == kMinimalBufferSize) {
+    isolate()->set_assembler_spare_buffer(buffer_);
   } else {
     DeleteArray(buffer_);
   }
@@ -939,6 +944,12 @@
   emit(0xF8);
 }
 
+void Assembler::cld() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0xFC);
+}
+
 void Assembler::cdq() {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
@@ -1026,7 +1037,7 @@
 
 
 void Assembler::cpuid() {
-  ASSERT(CpuFeatures::IsEnabled(CPUID));
+  ASSERT(isolate()->cpu_features()->IsEnabled(CPUID));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit(0x0F);
@@ -1673,7 +1684,7 @@
     EnsureSpace ensure_space(this);
     last_pc_ = pc_;
     ASSERT(value->IsHeapObject());
-    ASSERT(!Heap::InNewSpace(*value));
+    ASSERT(!HEAP->InNewSpace(*value));
     emit_rex_64(dst);
     emit(0xB8 | dst.low_bits());
     emitq(reinterpret_cast<uintptr_t>(value.location()), mode);
@@ -2377,7 +2388,7 @@
 
 
 void Assembler::fisttp_s(const Operand& adr) {
-  ASSERT(CpuFeatures::IsEnabled(SSE3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE3));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit_optional_rex_32(adr);
@@ -2387,7 +2398,7 @@
 
 
 void Assembler::fisttp_d(const Operand& adr) {
-  ASSERT(CpuFeatures::IsEnabled(SSE3));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE3));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit_optional_rex_32(adr);
@@ -2705,7 +2716,7 @@
 
 
 void Assembler::movdqa(const Operand& dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit(0x66);
@@ -2717,7 +2728,7 @@
 
 
 void Assembler::movdqa(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit(0x66);
@@ -3114,7 +3125,7 @@
       Serializer::TooLateToEnableNow();
     }
 #endif
-    if (!Serializer::enabled() && !FLAG_debug_code) {
+    if (!Serializer::enabled() && !emit_debug_code()) {
       return;
     }
   }
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index f6cd570..52aca63 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -93,8 +93,8 @@
   //  rbp - frame pointer
   //  rsi - context register
   //  r10 - fixed scratch register
+  //  r12 - smi constant register
   //  r13 - root register
-  //  r15 - smi constant register
   static const int kNumRegisters = 16;
   static const int kNumAllocatableRegisters = 10;
 
@@ -120,7 +120,7 @@
       "r9",
       "r11",
       "r14",
-      "r12"
+      "r15"
     };
     return names[index];
   }
@@ -395,6 +395,13 @@
   // Does not check the "reg" part of the Operand.
   bool AddressUsesRegister(Register reg) const;
 
+  // Queries related to the size of the generated instruction.
+  // Whether the generated instruction will have a REX prefix.
+  bool requires_rex() const { return rex_ != 0; }
+  // Size of the ModR/M, SIB and displacement parts of the generated
+  // instruction.
+  int operand_size() const { return len_; }
+
  private:
   byte rex_;
   byte buf_[6];
@@ -427,13 +434,14 @@
 //   } else {
 //     // Generate standard x87 or SSE2 floating point code.
 //   }
-class CpuFeatures : public AllStatic {
+class CpuFeatures {
  public:
   // Detect features of the target CPU. Set safe defaults if the serializer
   // is enabled (snapshots must be portable).
-  static void Probe(bool portable);
+  void Probe(bool portable);
+
   // Check whether a feature is supported by the target CPU.
-  static bool IsSupported(CpuFeature f) {
+  bool IsSupported(CpuFeature f) const {
     if (f == SSE2 && !FLAG_enable_sse2) return false;
     if (f == SSE3 && !FLAG_enable_sse3) return false;
     if (f == CMOV && !FLAG_enable_cmov) return false;
@@ -442,39 +450,56 @@
     return (supported_ & (V8_UINT64_C(1) << f)) != 0;
   }
   // Check whether a feature is currently enabled.
-  static bool IsEnabled(CpuFeature f) {
+  bool IsEnabled(CpuFeature f) const {
     return (enabled_ & (V8_UINT64_C(1) << f)) != 0;
   }
   // Enable a specified feature within a scope.
   class Scope BASE_EMBEDDED {
 #ifdef DEBUG
    public:
-    explicit Scope(CpuFeature f) {
+    explicit Scope(CpuFeature f)
+        : cpu_features_(Isolate::Current()->cpu_features()),
+          isolate_(Isolate::Current()) {
       uint64_t mask = (V8_UINT64_C(1) << f);
-      ASSERT(CpuFeatures::IsSupported(f));
-      ASSERT(!Serializer::enabled() || (found_by_runtime_probing_ & mask) == 0);
-      old_enabled_ = CpuFeatures::enabled_;
-      CpuFeatures::enabled_ |= mask;
+      ASSERT(cpu_features_->IsSupported(f));
+      ASSERT(!Serializer::enabled() ||
+          (cpu_features_->found_by_runtime_probing_ & mask) == 0);
+      old_enabled_ = cpu_features_->enabled_;
+      cpu_features_->enabled_ |= mask;
     }
-    ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
+    ~Scope() {
+      ASSERT_EQ(Isolate::Current(), isolate_);
+      cpu_features_->enabled_ = old_enabled_;
+    }
    private:
     uint64_t old_enabled_;
+    CpuFeatures* cpu_features_;
+    Isolate* isolate_;
 #else
    public:
     explicit Scope(CpuFeature f) {}
 #endif
   };
  private:
+  CpuFeatures();
+
   // Safe defaults include SSE2 and CMOV for X64. It is always available, if
   // anyone checks, but they shouldn't need to check.
+  // The required user mode extensions in X64 are (from AMD64 ABI Table A.1):
+  //   fpu, tsc, cx8, cmov, mmx, sse, sse2, fxsr, syscall
   static const uint64_t kDefaultCpuFeatures = (1 << SSE2 | 1 << CMOV);
-  static uint64_t supported_;
-  static uint64_t enabled_;
-  static uint64_t found_by_runtime_probing_;
+
+  uint64_t supported_;
+  uint64_t enabled_;
+  uint64_t found_by_runtime_probing_;
+
+  friend class Isolate;
+
+  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
 };
 
 
-class Assembler : public Malloced {
+class Assembler : public AssemblerBase {
  private:
   // We check before assembling an instruction that there is sufficient
   // space to write an instruction and its relocation information.
@@ -504,6 +529,9 @@
   Assembler(void* buffer, int buffer_size);
   ~Assembler();
 
+  // Overrides the default provided by FLAG_debug_code.
+  void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
+
   // 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.
@@ -649,7 +677,7 @@
 
   // Move sign extended immediate to memory location.
   void movq(const Operand& dst, Immediate value);
-  // New x64 instructions to load a 64-bit immediate into a register.
+  // Instructions to load a 64-bit immediate into a register.
   // All 64-bit immediates must have a relocation mode.
   void movq(Register dst, void* ptr, RelocInfo::Mode rmode);
   void movq(Register dst, int64_t value, RelocInfo::Mode rmode);
@@ -674,7 +702,7 @@
   void repmovsl();
   void repmovsq();
 
-  // New x64 instruction to load from an immediate 64-bit pointer into RAX.
+  // Instruction to load from an immediate 64-bit pointer into RAX.
   void load_rax(void* ptr, RelocInfo::Mode rmode);
   void load_rax(ExternalReference ext);
 
@@ -1109,6 +1137,7 @@
 
   // Miscellaneous
   void clc();
+  void cld();
   void cpuid();
   void hlt();
   void int3();
@@ -1343,6 +1372,9 @@
   static const int kMaximalBufferSize = 512*MB;
   static const int kMinimalBufferSize = 4*KB;
 
+ protected:
+  bool emit_debug_code() const { return emit_debug_code_; }
+
  private:
   byte* addr_at(int pos)  { return buffer_ + pos; }
   byte byte_at(int pos)  { return buffer_[pos]; }
@@ -1536,8 +1568,6 @@
   int buffer_size_;
   // True if the assembler owns the buffer, false if buffer is external.
   bool own_buffer_;
-  // A previously allocated buffer of kMinimalBufferSize bytes, or NULL.
-  static byte* spare_buffer_;
 
   // code generation
   byte* pc_;  // the program counter; moves forward
@@ -1548,6 +1578,9 @@
   byte* last_pc_;
 
   PositionsRecorder positions_recorder_;
+
+  bool emit_debug_code_;
+
   friend class PositionsRecorder;
 };
 
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index b545876..21d3e54 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -69,7 +69,7 @@
   // JumpToExternalReference expects rax to contain the number of arguments
   // including the receiver and the extra arguments.
   __ addq(rax, Immediate(num_extra_args + 1));
-  __ JumpToExternalReference(ExternalReference(id), 1);
+  __ JumpToExternalReference(ExternalReference(id, masm->isolate()), 1);
 }
 
 
@@ -98,7 +98,7 @@
   // Set expected number of arguments to zero (not changing rax).
   __ movq(rbx, Immediate(0));
   __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
-  __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
+  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
           RelocInfo::CODE_TARGET);
 }
 
@@ -127,7 +127,7 @@
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
     ExternalReference debug_step_in_fp =
-        ExternalReference::debug_step_in_fp_address();
+        ExternalReference::debug_step_in_fp_address(masm->isolate());
     __ movq(kScratchRegister, debug_step_in_fp);
     __ cmpq(Operand(kScratchRegister, 0), Immediate(0));
     __ j(not_equal, &rt_call);
@@ -339,8 +339,8 @@
   // Call the function.
   if (is_api_function) {
     __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
-    Handle<Code> code = Handle<Code>(
-        Builtins::builtin(Builtins::HandleApiCallConstruct));
+    Handle<Code> code =
+        masm->isolate()->builtins()->HandleApiCallConstruct();
     ParameterCount expected(0);
     __ InvokeCode(code, expected, expected,
                   RelocInfo::CODE_TARGET, CALL_FUNCTION);
@@ -379,7 +379,8 @@
   SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2);
   __ lea(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize));
   __ push(rcx);
-  __ IncrementCounter(&Counters::constructed_objects, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->constructed_objects(), 1);
   __ ret(0);
 }
 
@@ -492,7 +493,7 @@
   // Invoke the code.
   if (is_construct) {
     // Expects rdi to hold function pointer.
-    __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
+    __ Call(masm->isolate()->builtins()->JSConstructCall(),
             RelocInfo::CODE_TARGET);
   } else {
     ParameterCount actual(rax);
@@ -630,7 +631,7 @@
     __ testq(rax, rax);
     __ j(not_zero, &done);
     __ pop(rbx);
-    __ Push(Factory::undefined_value());
+    __ Push(FACTORY->undefined_value());
     __ push(rbx);
     __ incq(rax);
     __ bind(&done);
@@ -733,7 +734,7 @@
     __ j(not_zero, &function);
     __ Set(rbx, 0);
     __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
-    __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
+    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
             RelocInfo::CODE_TARGET);
     __ bind(&function);
   }
@@ -748,7 +749,7 @@
   __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
   __ cmpq(rax, rbx);
   __ j(not_equal,
-       Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
+       masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
        RelocInfo::CODE_TARGET);
 
   ParameterCount expected(0);
@@ -863,7 +864,8 @@
   __ movq(rdx, Operand(rbp, kArgumentsOffset));  // load arguments
 
   // Use inline caching to speed up access to arguments.
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  Handle<Code> ic =
+      masm->isolate()->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
@@ -935,7 +937,7 @@
   // scratch2: start of next object
   __ movq(FieldOperand(result, JSObject::kMapOffset), scratch1);
   __ Move(FieldOperand(result, JSArray::kPropertiesOffset),
-          Factory::empty_fixed_array());
+          FACTORY->empty_fixed_array());
   // Field JSArray::kElementsOffset is initialized later.
   __ Move(FieldOperand(result, JSArray::kLengthOffset), Smi::FromInt(0));
 
@@ -943,7 +945,7 @@
   // fixed array.
   if (initial_capacity == 0) {
     __ Move(FieldOperand(result, JSArray::kElementsOffset),
-            Factory::empty_fixed_array());
+            FACTORY->empty_fixed_array());
     return;
   }
 
@@ -960,7 +962,7 @@
   // scratch1: elements array
   // scratch2: start of next object
   __ Move(FieldOperand(scratch1, HeapObject::kMapOffset),
-          Factory::fixed_array_map());
+          FACTORY->fixed_array_map());
   __ Move(FieldOperand(scratch1, FixedArray::kLengthOffset),
           Smi::FromInt(initial_capacity));
 
@@ -968,7 +970,7 @@
   // Reconsider loop unfolding if kPreallocatedArrayElements gets changed.
   static const int kLoopUnfoldLimit = 4;
   ASSERT(kPreallocatedArrayElements <= kLoopUnfoldLimit);
-  __ Move(scratch3, Factory::the_hole_value());
+  __ Move(scratch3, FACTORY->the_hole_value());
   if (initial_capacity <= kLoopUnfoldLimit) {
     // Use a scratch register here to have only one reloc info when unfolding
     // the loop.
@@ -1052,7 +1054,7 @@
   // array_size: size of array (smi)
   __ bind(&allocated);
   __ movq(FieldOperand(result, JSObject::kMapOffset), elements_array);
-  __ Move(elements_array, Factory::empty_fixed_array());
+  __ Move(elements_array, FACTORY->empty_fixed_array());
   __ movq(FieldOperand(result, JSArray::kPropertiesOffset), elements_array);
   // Field JSArray::kElementsOffset is initialized later.
   __ movq(FieldOperand(result, JSArray::kLengthOffset), array_size);
@@ -1071,7 +1073,7 @@
   // elements_array_end: start of next object
   // array_size: size of array (smi)
   __ Move(FieldOperand(elements_array, JSObject::kMapOffset),
-          Factory::fixed_array_map());
+          FACTORY->fixed_array_map());
   Label not_empty_2, fill_array;
   __ SmiTest(array_size);
   __ j(not_zero, &not_empty_2);
@@ -1092,7 +1094,7 @@
   __ bind(&fill_array);
   if (fill_with_hole) {
     Label loop, entry;
-    __ Move(scratch, Factory::the_hole_value());
+    __ Move(scratch, FACTORY->the_hole_value());
     __ lea(elements_array, Operand(elements_array,
                                    FixedArray::kHeaderSize - kHeapObjectTag));
     __ jmp(&entry);
@@ -1137,7 +1139,8 @@
                        r8,
                        kPreallocatedArrayElements,
                        call_generic_code);
-  __ IncrementCounter(&Counters::array_function_native, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->array_function_native(), 1);
   __ movq(rax, rbx);
   __ ret(kPointerSize);
 
@@ -1168,7 +1171,7 @@
                   r9,
                   true,
                   call_generic_code);
-  __ IncrementCounter(&Counters::array_function_native, 1);
+  __ IncrementCounter(counters->array_function_native(), 1);
   __ movq(rax, rbx);
   __ ret(2 * kPointerSize);
 
@@ -1190,7 +1193,7 @@
                   r9,
                   false,
                   call_generic_code);
-  __ IncrementCounter(&Counters::array_function_native, 1);
+  __ IncrementCounter(counters->array_function_native(), 1);
 
   // rax: argc
   // rbx: JSArray
@@ -1264,8 +1267,8 @@
   // Jump to the generic array code in case the specialized code cannot handle
   // the construction.
   __ bind(&generic_array_code);
-  Code* code = Builtins::builtin(Builtins::ArrayCodeGeneric);
-  Handle<Code> array_code(code);
+  Handle<Code> array_code =
+      masm->isolate()->builtins()->ArrayCodeGeneric();
   __ Jump(array_code, RelocInfo::CODE_TARGET);
 }
 
@@ -1298,8 +1301,8 @@
   // Jump to the generic construct code in case the specialized code cannot
   // handle the construction.
   __ bind(&generic_constructor);
-  Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
-  Handle<Code> generic_construct_stub(code);
+  Handle<Code> generic_construct_stub =
+      masm->isolate()->builtins()->JSConstructStubGeneric();
   __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
 }
 
@@ -1353,7 +1356,8 @@
   // -----------------------------------
 
   Label invoke, dont_adapt_arguments;
-  __ IncrementCounter(&Counters::arguments_adaptors, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->arguments_adaptors(), 1);
 
   Label enough, too_few;
   __ cmpq(rax, rbx);
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index eb92978..0fb827b 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -46,8 +46,8 @@
   __ Ret();
 
   __ bind(&check_heap_number);
-  __ Move(rbx, Factory::heap_number_map());
-  __ cmpq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
+  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
+                 Heap::kHeapNumberMapRootIndex);
   __ j(not_equal, &call_builtin);
   __ Ret();
 
@@ -68,11 +68,15 @@
   // Get the function info from the stack.
   __ movq(rdx, Operand(rsp, 1 * kPointerSize));
 
+  int map_index = strict_mode_ == kStrictMode
+      ? Context::STRICT_MODE_FUNCTION_MAP_INDEX
+      : Context::FUNCTION_MAP_INDEX;
+
   // Compute the function map in the current global context and set that
   // as the map of the allocated object.
   __ movq(rcx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset));
-  __ movq(rcx, Operand(rcx, Context::SlotOffset(Context::FUNCTION_MAP_INDEX)));
+  __ movq(rcx, Operand(rcx, Context::SlotOffset(map_index)));
   __ movq(FieldOperand(rax, JSObject::kMapOffset), rcx);
 
   // Initialize the rest of the function. We don't have to update the
@@ -104,7 +108,7 @@
   __ pop(rdx);
   __ push(rsi);
   __ push(rdx);
-  __ Push(Factory::false_value());
+  __ PushRoot(Heap::kFalseValueRootIndex);
   __ push(rcx);  // Restore return address.
   __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
 }
@@ -280,7 +284,8 @@
 const char* GenericBinaryOpStub::GetName() {
   if (name_ != NULL) return name_;
   const int kMaxNameLength = 100;
-  name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
+  name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
+      kMaxNameLength);
   if (name_ == NULL) return "OOM";
   const char* op_name = Token::Name(op_);
   const char* overwrite_name;
@@ -354,7 +359,8 @@
 
     // Update flags to indicate that arguments are in registers.
     SetArgsInRegisters();
-    __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1);
+    Counters* counters = masm->isolate()->counters();
+    __ IncrementCounter(counters->generic_binary_stub_calls_regs(), 1);
   }
 
   // Call the stub.
@@ -390,7 +396,8 @@
 
     // Update flags to indicate that arguments are in registers.
     SetArgsInRegisters();
-    __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1);
+  Counters* counters = masm->isolate()->counters();
+    __ IncrementCounter(counters->generic_binary_stub_calls_regs(), 1);
   }
 
   // Call the stub.
@@ -425,7 +432,8 @@
     }
     // Update flags to indicate that arguments are in registers.
     SetArgsInRegisters();
-    __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1);
+  Counters* counters = masm->isolate()->counters();
+    __ IncrementCounter(counters->generic_binary_stub_calls_regs(), 1);
   }
 
   // Call the stub.
@@ -995,7 +1003,7 @@
 
   // Perform patching to an appropriate fast case and return the result.
   __ TailCallExternalReference(
-      ExternalReference(IC_Utility(IC::kBinaryOp_Patch)),
+      ExternalReference(IC_Utility(IC::kBinaryOp_Patch), masm->isolate()),
       5,
       1);
 }
@@ -1031,7 +1039,8 @@
   // Patch the caller to an appropriate specialized stub and return the
   // operation result to the caller of the stub.
   __ TailCallExternalReference(
-      ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch)),
+      ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch),
+                        masm->isolate()),
       5,
       1);
 }
@@ -1053,6 +1062,9 @@
     case TRBinaryOpIC::HEAP_NUMBER:
       GenerateHeapNumberStub(masm);
       break;
+    case TRBinaryOpIC::ODDBALL:
+      GenerateOddballStub(masm);
+      break;
     case TRBinaryOpIC::STRING:
       GenerateStringStub(masm);
       break;
@@ -1068,7 +1080,8 @@
 const char* TypeRecordingBinaryOpStub::GetName() {
   if (name_ != NULL) return name_;
   const int kMaxNameLength = 100;
-  name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
+  name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
+      kMaxNameLength);
   if (name_ == NULL) return "OOM";
   const char* op_name = Token::Name(op_);
   const char* overwrite_name;
@@ -1428,6 +1441,39 @@
 }
 
 
+void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
+  Label call_runtime;
+
+  if (op_ == Token::ADD) {
+    // Handle string addition here, because it is the only operation
+    // that does not do a ToNumber conversion on the operands.
+    GenerateStringAddCode(masm);
+  }
+
+  // Convert oddball arguments to numbers.
+  NearLabel check, done;
+  __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
+  __ j(not_equal, &check);
+  if (Token::IsBitOp(op_)) {
+    __ xor_(rdx, rdx);
+  } else {
+    __ LoadRoot(rdx, Heap::kNanValueRootIndex);
+  }
+  __ jmp(&done);
+  __ bind(&check);
+  __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
+  __ j(not_equal, &done);
+  if (Token::IsBitOp(op_)) {
+    __ xor_(rax, rax);
+  } else {
+    __ LoadRoot(rax, Heap::kNanValueRootIndex);
+  }
+  __ bind(&done);
+
+  GenerateHeapNumberStub(masm);
+}
+
+
 void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
   Label gc_required, not_number;
   GenerateFloatingPointCode(masm, &gc_required, &not_number);
@@ -1578,15 +1624,18 @@
   __ xorl(rcx, rdx);
   __ xorl(rax, rdi);
   __ xorl(rcx, rax);
-  ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
-  __ andl(rcx, Immediate(TranscendentalCache::kCacheSize - 1));
+  ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize));
+  __ andl(rcx, Immediate(TranscendentalCache::SubCache::kCacheSize - 1));
 
   // ST[0] == double value.
   // rbx = bits of double value.
   // rcx = TranscendentalCache::hash(double value).
-  __ movq(rax, ExternalReference::transcendental_cache_array_address());
-  // rax points to cache array.
-  __ movq(rax, Operand(rax, type_ * sizeof(TranscendentalCache::caches_[0])));
+  ExternalReference cache_array =
+      ExternalReference::transcendental_cache_array_address(masm->isolate());
+  __ movq(rax, cache_array);
+  int cache_array_index =
+      type_ * sizeof(Isolate::Current()->transcendental_cache()->caches_[0]);
+  __ movq(rax, Operand(rax, cache_array_index));
   // rax points to the cache for the type type_.
   // If NULL, the cache hasn't been initialized yet, so go through runtime.
   __ testq(rax, rax);
@@ -1594,7 +1643,7 @@
 #ifdef DEBUG
   // Check that the layout of cache elements match expectations.
   {  // NOLINT - doesn't like a single brace on a line.
-    TranscendentalCache::Element test_elem[2];
+    TranscendentalCache::SubCache::Element test_elem[2];
     char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
     char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
     char* elem_in0  = reinterpret_cast<char*>(&(test_elem[0].in[0]));
@@ -1667,7 +1716,8 @@
     __ bind(&runtime_call_clear_stack);
     __ fstp(0);
     __ bind(&runtime_call);
-    __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
+    __ TailCallExternalReference(
+        ExternalReference(RuntimeFunction(), masm->isolate()), 1, 1);
   } else {  // UNTAGGED.
     __ bind(&runtime_call_clear_stack);
     __ bind(&runtime_call);
@@ -2244,11 +2294,14 @@
   Label slow;
   __ JumpIfNotSmi(rdx, &slow);
 
-  // Check if the calling frame is an arguments adaptor frame.
+  // Check if the calling frame is an arguments adaptor frame.  We look at the
+  // context offset, and if the frame is not a regular one, then we find a
+  // Smi instead of the context.  We can't use SmiCompare here, because that
+  // only works for comparing two smis.
   Label adaptor;
   __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
-  __ SmiCompare(Operand(rbx, StandardFrameConstants::kContextOffset),
-                Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+  __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
+         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
   __ j(equal, &adaptor);
 
   // Check index against formal parameters count limit passed in
@@ -2303,8 +2356,8 @@
   // Check if the calling frame is an arguments adaptor frame.
   Label adaptor_frame, try_allocate, runtime;
   __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
-  __ SmiCompare(Operand(rdx, StandardFrameConstants::kContextOffset),
-                Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+  __ Cmp(Operand(rdx, StandardFrameConstants::kContextOffset),
+         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
   __ j(equal, &adaptor_frame);
 
   // Get the length from the frame.
@@ -2331,16 +2384,16 @@
   __ j(zero, &add_arguments_object);
   __ leal(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize));
   __ bind(&add_arguments_object);
-  __ addl(rcx, Immediate(Heap::kArgumentsObjectSize));
+  __ addl(rcx, Immediate(GetArgumentsObjectSize()));
 
   // Do the allocation of both objects in one go.
   __ AllocateInNewSpace(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT);
 
   // Get the arguments boilerplate from the current (global) context.
-  int offset = Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX);
   __ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ movq(rdi, FieldOperand(rdi, GlobalObject::kGlobalContextOffset));
-  __ movq(rdi, Operand(rdi, offset));
+  __ movq(rdi, Operand(rdi,
+                       Context::SlotOffset(GetArgumentsBoilerplateIndex())));
 
   // Copy the JS object part.
   STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize);
@@ -2351,15 +2404,21 @@
   __ movq(FieldOperand(rax, 1 * kPointerSize), rdx);
   __ movq(FieldOperand(rax, 2 * kPointerSize), rbx);
 
-  // Setup the callee in-object property.
-  ASSERT(Heap::arguments_callee_index == 0);
-  __ movq(kScratchRegister, Operand(rsp, 3 * kPointerSize));
-  __ movq(FieldOperand(rax, JSObject::kHeaderSize), kScratchRegister);
+  if (type_ == NEW_NON_STRICT) {
+    // Setup the callee in-object property.
+    ASSERT(Heap::kArgumentsCalleeIndex == 1);
+    __ movq(kScratchRegister, Operand(rsp, 3 * kPointerSize));
+    __ movq(FieldOperand(rax, JSObject::kHeaderSize +
+                              Heap::kArgumentsCalleeIndex * kPointerSize),
+            kScratchRegister);
+  }
 
   // Get the length (smi tagged) and set that as an in-object property too.
-  ASSERT(Heap::arguments_length_index == 1);
+  ASSERT(Heap::kArgumentsLengthIndex == 0);
   __ movq(rcx, Operand(rsp, 1 * kPointerSize));
-  __ movq(FieldOperand(rax, JSObject::kHeaderSize + kPointerSize), rcx);
+  __ movq(FieldOperand(rax, JSObject::kHeaderSize +
+                            Heap::kArgumentsLengthIndex * kPointerSize),
+          rcx);
 
   // If there are no actual arguments, we're done.
   Label done;
@@ -2371,7 +2430,7 @@
 
   // Setup the elements pointer in the allocated arguments object and
   // initialize the header in the elements fixed array.
-  __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSize));
+  __ lea(rdi, Operand(rax, GetArgumentsObjectSize()));
   __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi);
   __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex);
   __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister);
@@ -2423,14 +2482,13 @@
   static const int kJSRegExpOffset = 4 * kPointerSize;
 
   Label runtime;
-
   // Ensure that a RegExp stack is allocated.
+  Isolate* isolate = masm->isolate();
   ExternalReference address_of_regexp_stack_memory_address =
-      ExternalReference::address_of_regexp_stack_memory_address();
+      ExternalReference::address_of_regexp_stack_memory_address(isolate);
   ExternalReference address_of_regexp_stack_memory_size =
-      ExternalReference::address_of_regexp_stack_memory_size();
-  __ movq(kScratchRegister, address_of_regexp_stack_memory_size);
-  __ movq(kScratchRegister, Operand(kScratchRegister, 0));
+      ExternalReference::address_of_regexp_stack_memory_size(isolate);
+  __ Load(kScratchRegister, address_of_regexp_stack_memory_size);
   __ testq(kScratchRegister, kScratchRegister);
   __ j(zero, &runtime);
 
@@ -2441,32 +2499,32 @@
   __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister);
   __ j(not_equal, &runtime);
   // Check that the RegExp has been compiled (data contains a fixed array).
-  __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset));
+  __ movq(rax, FieldOperand(rax, JSRegExp::kDataOffset));
   if (FLAG_debug_code) {
-    Condition is_smi = masm->CheckSmi(rcx);
+    Condition is_smi = masm->CheckSmi(rax);
     __ Check(NegateCondition(is_smi),
         "Unexpected type for RegExp data, FixedArray expected");
-    __ CmpObjectType(rcx, FIXED_ARRAY_TYPE, kScratchRegister);
+    __ CmpObjectType(rax, FIXED_ARRAY_TYPE, kScratchRegister);
     __ Check(equal, "Unexpected type for RegExp data, FixedArray expected");
   }
 
-  // rcx: RegExp data (FixedArray)
+  // rax: RegExp data (FixedArray)
   // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
-  __ SmiToInteger32(rbx, FieldOperand(rcx, JSRegExp::kDataTagOffset));
+  __ SmiToInteger32(rbx, FieldOperand(rax, JSRegExp::kDataTagOffset));
   __ cmpl(rbx, Immediate(JSRegExp::IRREGEXP));
   __ j(not_equal, &runtime);
 
-  // rcx: RegExp data (FixedArray)
+  // rax: RegExp data (FixedArray)
   // Check that the number of captures fit in the static offsets vector buffer.
   __ SmiToInteger32(rdx,
-                    FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset));
+                    FieldOperand(rax, JSRegExp::kIrregexpCaptureCountOffset));
   // Calculate number of capture registers (number_of_captures + 1) * 2.
   __ leal(rdx, Operand(rdx, rdx, times_1, 2));
   // Check that the static offsets vector buffer is large enough.
   __ cmpl(rdx, Immediate(OffsetsVector::kStaticOffsetsVectorSize));
   __ j(above, &runtime);
 
-  // rcx: RegExp data (FixedArray)
+  // rax: RegExp data (FixedArray)
   // rdx: Number of capture registers
   // Check that the second argument is a string.
   __ movq(rdi, Operand(rsp, kSubjectOffset));
@@ -2494,7 +2552,8 @@
   // Check that the JSArray is in fast case.
   __ movq(rbx, FieldOperand(rdi, JSArray::kElementsOffset));
   __ movq(rdi, FieldOperand(rbx, HeapObject::kMapOffset));
-  __ Cmp(rdi, Factory::fixed_array_map());
+  __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
+                 Heap::kFixedArrayMapRootIndex);
   __ j(not_equal, &runtime);
   // Check that the last match info has space for the capture registers and the
   // additional information. Ensure no overflow in add.
@@ -2529,8 +2588,8 @@
   __ testb(rbx, Immediate(kIsNotStringMask | kExternalStringTag));
   __ j(not_zero, &runtime);
   // String is a cons string.
-  __ movq(rdx, FieldOperand(rdi, ConsString::kSecondOffset));
-  __ Cmp(rdx, Factory::empty_string());
+  __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset),
+                 Heap::kEmptyStringRootIndex);
   __ j(not_equal, &runtime);
   __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset));
   __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
@@ -2579,15 +2638,24 @@
   // rcx: encoding of subject string (1 if ascii 0 if two_byte);
   // r11: code
   // All checks done. Now push arguments for native regexp code.
-  __ IncrementCounter(&Counters::regexp_entry_native, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->regexp_entry_native(), 1);
 
-  static const int kRegExpExecuteArguments = 7;
+  // Isolates: note we add an additional parameter here (isolate pointer).
+  static const int kRegExpExecuteArguments = 8;
   int argument_slots_on_stack =
       masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments);
-  __ EnterApiExitFrame(argument_slots_on_stack);  // Clobbers rax!
+  __ EnterApiExitFrame(argument_slots_on_stack);
+
+  // Argument 8: Pass current isolate address.
+  // __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize),
+  //     Immediate(ExternalReference::isolate_address()));
+  __ LoadAddress(kScratchRegister, ExternalReference::isolate_address());
+  __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize),
+          kScratchRegister);
 
   // Argument 7: Indicate that this is a direct call from JavaScript.
-  __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize),
+  __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kPointerSize),
           Immediate(1));
 
   // Argument 6: Start (high end) of backtracking stack memory area.
@@ -2597,14 +2665,15 @@
   __ addq(r9, Operand(kScratchRegister, 0));
   // Argument 6 passed in r9 on Linux and on the stack on Windows.
 #ifdef _WIN64
-  __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kPointerSize), r9);
+  __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kPointerSize), r9);
 #endif
 
   // Argument 5: static offsets vector buffer.
-  __ movq(r8, ExternalReference::address_of_static_offsets_vector());
+  __ LoadAddress(r8,
+                 ExternalReference::address_of_static_offsets_vector(isolate));
   // Argument 5 passed in r8 on Linux and on the stack on Windows.
 #ifdef _WIN64
-  __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kPointerSize), r8);
+  __ movq(Operand(rsp, (argument_slots_on_stack - 4) * kPointerSize), r8);
 #endif
 
   // First four arguments are passed in registers on both Linux and Windows.
@@ -2705,7 +2774,8 @@
   __ RecordWrite(rcx, RegExpImpl::kLastInputOffset, rax, rdi);
 
   // Get the static offsets vector filled by the native regexp code.
-  __ movq(rcx, ExternalReference::address_of_static_offsets_vector());
+  __ LoadAddress(rcx,
+                 ExternalReference::address_of_static_offsets_vector(isolate));
 
   // rbx: last_match_info backing store (FixedArray)
   // rcx: offsets vector
@@ -2737,13 +2807,15 @@
   // stack overflow (on the backtrack stack) was detected in RegExp code but
   // haven't created the exception yet. Handle that in the runtime system.
   // TODO(592): Rerunning the RegExp to get the stack overflow exception.
-  ExternalReference pending_exception_address(Top::k_pending_exception_address);
-  __ movq(rbx, pending_exception_address);
-  __ movq(rax, Operand(rbx, 0));
+  ExternalReference pending_exception_address(
+      Isolate::k_pending_exception_address, isolate);
+  Operand pending_exception_operand =
+      masm->ExternalOperand(pending_exception_address, rbx);
+  __ movq(rax, pending_exception_operand);
   __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
   __ cmpq(rax, rdx);
   __ j(equal, &runtime);
-  __ movq(Operand(rbx, 0), rdx);
+  __ movq(pending_exception_operand, rdx);
 
   __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex);
   NearLabel termination_exception;
@@ -2794,8 +2866,8 @@
   __ movq(FieldOperand(rax, HeapObject::kMapOffset), rdx);
 
   // Set empty properties FixedArray.
-  __ Move(FieldOperand(rax, JSObject::kPropertiesOffset),
-          Factory::empty_fixed_array());
+  __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex);
+  __ movq(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister);
 
   // Set elements to point to FixedArray allocated right after the JSArray.
   __ lea(rcx, Operand(rax, JSRegExpResult::kSize));
@@ -2815,13 +2887,13 @@
   // rbx: Number of elements in array as int32.
 
   // Set map.
-  __ Move(FieldOperand(rcx, HeapObject::kMapOffset),
-          Factory::fixed_array_map());
+  __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex);
+  __ movq(FieldOperand(rcx, HeapObject::kMapOffset), kScratchRegister);
   // Set length.
   __ Integer32ToSmi(rdx, rbx);
   __ movq(FieldOperand(rcx, FixedArray::kLengthOffset), rdx);
   // Fill contents of fixed-array with the-hole.
-  __ Move(rdx, Factory::the_hole_value());
+  __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
   __ lea(rcx, FieldOperand(rcx, FixedArray::kHeaderSize));
   // Fill fixed array elements with hole.
   // rax: JSArray.
@@ -2874,7 +2946,7 @@
   Label load_result_from_cache;
   if (!object_is_smi) {
     __ JumpIfSmi(object, &is_smi);
-    __ CheckMap(object, Factory::heap_number_map(), not_found, true);
+    __ CheckMap(object, FACTORY->heap_number_map(), not_found, true);
 
     STATIC_ASSERT(8 == kDoubleSize);
     __ movl(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4));
@@ -2889,7 +2961,7 @@
                          times_1,
                          FixedArray::kHeaderSize));
     __ JumpIfSmi(probe, not_found);
-    ASSERT(CpuFeatures::IsSupported(SSE2));
+    ASSERT(Isolate::Current()->cpu_features()->IsSupported(SSE2));
     CpuFeatures::Scope fscope(SSE2);
     __ movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
     __ movsd(xmm1, FieldOperand(probe, HeapNumber::kValueOffset));
@@ -2919,7 +2991,8 @@
                        index,
                        times_1,
                        FixedArray::kHeaderSize + kPointerSize));
-  __ IncrementCounter(&Counters::number_to_string_native, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->number_to_string_native(), 1);
 }
 
 
@@ -3004,7 +3077,7 @@
       __ bind(&check_for_nan);
     }
 
-    // Test for NaN. Sadly, we can't just compare to Factory::nan_value(),
+    // Test for NaN. Sadly, we can't just compare to FACTORY->nan_value(),
     // so we do the second best thing - test it ourselves.
     // Note: if cc_ != equal, never_nan_nan_ is not used.
     // We cannot set rax to EQUAL until just before return because
@@ -3017,7 +3090,7 @@
       NearLabel heap_number;
       // If it's not a heap number, then return equal for (in)equality operator.
       __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
-             Factory::heap_number_map());
+             FACTORY->heap_number_map());
       __ j(equal, &heap_number);
       if (cc_ != equal) {
         // Call runtime on identical JSObjects.  Otherwise return equal.
@@ -3062,7 +3135,7 @@
 
         // Check if the non-smi operand is a heap number.
         __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
-               Factory::heap_number_map());
+               FACTORY->heap_number_map());
         // If heap number, handle it in the slow case.
         __ j(equal, &slow);
         // Return non-equal.  ebx (the lower half of rbx) is not zero.
@@ -3295,11 +3368,17 @@
   __ Set(rax, argc_);
   __ Set(rbx, 0);
   __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
-  Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
+  Handle<Code> adaptor =
+      Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline();
   __ Jump(adaptor, RelocInfo::CODE_TARGET);
 }
 
 
+bool CEntryStub::NeedsImmovableCode() {
+  return false;
+}
+
+
 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
   // Throw exception in eax.
   __ Throw(rax);
@@ -3317,7 +3396,7 @@
   // rbp: frame pointer  (restored after C call).
   // rsp: stack pointer  (restored after C call).
   // r14: number of arguments including receiver (C callee-saved).
-  // r12: pointer to the first argument (C callee-saved).
+  // r15: pointer to the first argument (C callee-saved).
   //      This pointer is reused in LeaveExitFrame(), so it is stored in a
   //      callee-saved register.
 
@@ -3347,10 +3426,10 @@
   }
 
   ExternalReference scope_depth =
-      ExternalReference::heap_always_allocate_scope_depth();
+      ExternalReference::heap_always_allocate_scope_depth(masm->isolate());
   if (always_allocate_scope) {
-    __ movq(kScratchRegister, scope_depth);
-    __ incl(Operand(kScratchRegister, 0));
+    Operand scope_depth_operand = masm->ExternalOperand(scope_depth);
+    __ incl(scope_depth_operand);
   }
 
   // Call C function.
@@ -3358,30 +3437,33 @@
   // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9
   // Store Arguments object on stack, below the 4 WIN64 ABI parameter slots.
   __ movq(StackSpaceOperand(0), r14);  // argc.
-  __ movq(StackSpaceOperand(1), r12);  // argv.
+  __ movq(StackSpaceOperand(1), r15);  // argv.
   if (result_size_ < 2) {
     // Pass a pointer to the Arguments object as the first argument.
     // Return result in single register (rax).
     __ lea(rcx, StackSpaceOperand(0));
+    __ LoadAddress(rdx, ExternalReference::isolate_address());
   } else {
     ASSERT_EQ(2, result_size_);
     // Pass a pointer to the result location as the first argument.
     __ lea(rcx, StackSpaceOperand(2));
     // Pass a pointer to the Arguments object as the second argument.
     __ lea(rdx, StackSpaceOperand(0));
+    __ LoadAddress(r8, ExternalReference::isolate_address());
   }
 
 #else  // _WIN64
   // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9.
   __ movq(rdi, r14);  // argc.
-  __ movq(rsi, r12);  // argv.
+  __ movq(rsi, r15);  // argv.
+  __ movq(rdx, ExternalReference::isolate_address());
 #endif
   __ call(rbx);
   // Result is in rax - do not destroy this register!
 
   if (always_allocate_scope) {
-    __ movq(kScratchRegister, scope_depth);
-    __ decl(Operand(kScratchRegister, 0));
+    Operand scope_depth_operand = masm->ExternalOperand(scope_depth);
+    __ decl(scope_depth_operand);
   }
 
   // Check for failure result.
@@ -3422,12 +3504,13 @@
   __ j(equal, throw_out_of_memory_exception);
 
   // Retrieve the pending exception and clear the variable.
-  ExternalReference pending_exception_address(Top::k_pending_exception_address);
-  __ movq(kScratchRegister, pending_exception_address);
-  __ movq(rax, Operand(kScratchRegister, 0));
-  __ movq(rdx, ExternalReference::the_hole_value_location());
-  __ movq(rdx, Operand(rdx, 0));
-  __ movq(Operand(kScratchRegister, 0), rdx);
+  ExternalReference pending_exception_address(
+      Isolate::k_pending_exception_address, masm->isolate());
+  Operand pending_exception_operand =
+      masm->ExternalOperand(pending_exception_address);
+  __ movq(rax, pending_exception_operand);
+  __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
+  __ movq(pending_exception_operand, rdx);
 
   // Special handling of termination exceptions which are uncatchable
   // by javascript code.
@@ -3478,7 +3561,7 @@
   // rbp: frame pointer of exit frame  (restored after C call).
   // rsp: stack pointer (restored after C call).
   // r14: number of arguments including receiver (C callee-saved).
-  // r12: argv pointer (C callee-saved).
+  // r15: argv pointer (C callee-saved).
 
   Label throw_normal_exception;
   Label throw_termination_exception;
@@ -3526,52 +3609,58 @@
 #ifdef ENABLE_LOGGING_AND_PROFILING
   Label not_outermost_js, not_outermost_js_2;
 #endif
+  {  // NOLINT. Scope block confuses linter.
+    MacroAssembler::NoRootArrayScope uninitialized_root_register(masm);
+    // Setup frame.
+    __ push(rbp);
+    __ movq(rbp, rsp);
 
-  // Setup frame.
-  __ push(rbp);
-  __ movq(rbp, rsp);
-
-  // Push the stack frame type marker twice.
-  int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
-  // Scratch register is neither callee-save, nor an argument register on any
-  // platform. It's free to use at this point.
-  // Cannot use smi-register for loading yet.
-  __ movq(kScratchRegister,
-          reinterpret_cast<uint64_t>(Smi::FromInt(marker)),
-          RelocInfo::NONE);
-  __ push(kScratchRegister);  // context slot
-  __ push(kScratchRegister);  // function slot
-  // Save callee-saved registers (X64/Win64 calling conventions).
-  __ push(r12);
-  __ push(r13);
-  __ push(r14);
-  __ push(r15);
+    // Push the stack frame type marker twice.
+    int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
+    // Scratch register is neither callee-save, nor an argument register on any
+    // platform. It's free to use at this point.
+    // Cannot use smi-register for loading yet.
+    __ movq(kScratchRegister,
+            reinterpret_cast<uint64_t>(Smi::FromInt(marker)),
+            RelocInfo::NONE);
+    __ push(kScratchRegister);  // context slot
+    __ push(kScratchRegister);  // function slot
+    // Save callee-saved registers (X64/Win64 calling conventions).
+    __ push(r12);
+    __ push(r13);
+    __ push(r14);
+    __ push(r15);
 #ifdef _WIN64
-  __ push(rdi);  // Only callee save in Win64 ABI, argument in AMD64 ABI.
-  __ push(rsi);  // Only callee save in Win64 ABI, argument in AMD64 ABI.
+    __ push(rdi);  // Only callee save in Win64 ABI, argument in AMD64 ABI.
+    __ push(rsi);  // Only callee save in Win64 ABI, argument in AMD64 ABI.
 #endif
-  __ push(rbx);
-  // TODO(X64): On Win64, if we ever use XMM6-XMM15, the low low 64 bits are
-  // callee save as well.
+    __ push(rbx);
+    // TODO(X64): On Win64, if we ever use XMM6-XMM15, the low low 64 bits are
+    // callee save as well.
+
+    // Set up the roots and smi constant registers.
+    // Needs to be done before any further smi loads.
+    __ InitializeSmiConstantRegister();
+    __ InitializeRootRegister();
+  }
+
+  Isolate* isolate = masm->isolate();
 
   // Save copies of the top frame descriptor on the stack.
-  ExternalReference c_entry_fp(Top::k_c_entry_fp_address);
-  __ load_rax(c_entry_fp);
-  __ push(rax);
-
-  // Set up the roots and smi constant registers.
-  // Needs to be done before any further smi loads.
-  __ InitializeRootRegister();
-  __ InitializeSmiConstantRegister();
+  ExternalReference c_entry_fp(Isolate::k_c_entry_fp_address, isolate);
+  {
+    Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp);
+    __ push(c_entry_fp_operand);
+  }
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
   // If this is the outermost JS call, set js_entry_sp value.
-  ExternalReference js_entry_sp(Top::k_js_entry_sp_address);
-  __ load_rax(js_entry_sp);
+  ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address, isolate);
+  __ Load(rax, js_entry_sp);
   __ testq(rax, rax);
   __ j(not_zero, &not_outermost_js);
   __ movq(rax, rbp);
-  __ store_rax(js_entry_sp);
+  __ Store(js_entry_sp, rax);
   __ bind(&not_outermost_js);
 #endif
 
@@ -3580,8 +3669,9 @@
 
   // 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);
-  __ store_rax(pending_exception);
+  ExternalReference pending_exception(Isolate::k_pending_exception_address,
+                                      isolate);
+  __ Store(pending_exception, rax);
   __ movq(rax, Failure::Exception(), RelocInfo::NONE);
   __ jmp(&exit);
 
@@ -3590,8 +3680,8 @@
   __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER);
 
   // Clear any pending exceptions.
-  __ load_rax(ExternalReference::the_hole_value_location());
-  __ store_rax(pending_exception);
+  __ LoadRoot(rax, Heap::kTheHoleValueRootIndex);
+  __ Store(pending_exception, rax);
 
   // Fake a receiver (NULL).
   __ push(Immediate(0));  // receiver
@@ -3602,18 +3692,21 @@
   // directly in the code, because the builtin stubs may not have been
   // generated yet at the time this code is generated.
   if (is_construct) {
-    ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline);
-    __ load_rax(construct_entry);
+    ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline,
+                                      isolate);
+    __ Load(rax, construct_entry);
   } else {
-    ExternalReference entry(Builtins::JSEntryTrampoline);
-    __ load_rax(entry);
+    ExternalReference entry(Builtins::kJSEntryTrampoline, isolate);
+    __ Load(rax, entry);
   }
   __ lea(kScratchRegister, FieldOperand(rax, Code::kHeaderSize));
   __ call(kScratchRegister);
 
   // Unlink this frame from the handler chain.
-  __ movq(kScratchRegister, ExternalReference(Top::k_handler_address));
-  __ pop(Operand(kScratchRegister, 0));
+  Operand handler_operand =
+      masm->ExternalOperand(ExternalReference(Isolate::k_handler_address,
+                                              isolate));
+  __ pop(handler_operand);
   // Pop next_sp.
   __ addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize));
 
@@ -3629,8 +3722,10 @@
 
   // Restore the top frame descriptor from the stack.
   __ bind(&exit);
-  __ movq(kScratchRegister, ExternalReference(Top::k_c_entry_fp_address));
-  __ pop(Operand(kScratchRegister, 0));
+  {
+    Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp);
+    __ pop(c_entry_fp_operand);
+  }
 
   // Restore callee-saved registers (X64 conventions).
   __ pop(rbx);
@@ -3653,20 +3748,39 @@
 
 void InstanceofStub::Generate(MacroAssembler* masm) {
   // Implements "value instanceof function" operator.
-  // Expected input state:
+  // Expected input state with no inline cache:
   //   rsp[0] : return address
   //   rsp[1] : function pointer
   //   rsp[2] : value
+  // Expected input state with an inline one-element cache:
+  //   rsp[0] : return address
+  //   rsp[1] : offset from return address to location of inline cache
+  //   rsp[2] : function pointer
+  //   rsp[3] : value
   // Returns a bitwise zero to indicate that the value
   // is and instance of the function and anything else to
   // indicate that the value is not an instance.
 
-  // None of the flags are supported on X64.
-  ASSERT(flags_ == kNoFlags);
+  static const int kOffsetToMapCheckValue = 5;
+  static const int kOffsetToResultValue = 21;
+  // The last 4 bytes of the instruction sequence
+  //   movq(rax, FieldOperand(rdi, HeapObject::kMapOffset)
+  //   Move(kScratchRegister, FACTORY->the_hole_value())
+  // in front of the hole value address.
+  static const unsigned int kWordBeforeMapCheckValue = 0xBA49FF78;
+  // The last 4 bytes of the instruction sequence
+  //   __ j(not_equal, &cache_miss);
+  //   __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex);
+  // before the offset of the hole value in the root array.
+  static const unsigned int kWordBeforeResultValue = 0x458B4909;
+  // Only the inline check flag is supported on X64.
+  ASSERT(flags_ == kNoFlags || HasCallSiteInlineCheck());
+  int extra_stack_space = HasCallSiteInlineCheck() ? kPointerSize : 0;
 
   // Get the object - go slow case if it's a smi.
   Label slow;
-  __ movq(rax, Operand(rsp, 2 * kPointerSize));
+
+  __ movq(rax, Operand(rsp, 2 * kPointerSize + extra_stack_space));
   __ JumpIfSmi(rax, &slow);
 
   // Check that the left hand is a JS object. Leave its map in rax.
@@ -3676,19 +3790,23 @@
   __ j(above, &slow);
 
   // Get the prototype of the function.
-  __ movq(rdx, Operand(rsp, 1 * kPointerSize));
+  __ movq(rdx, Operand(rsp, 1 * kPointerSize + extra_stack_space));
   // rdx is function, rax is map.
 
-  // Look up the function and the map in the instanceof cache.
-  NearLabel miss;
-  __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
-  __ j(not_equal, &miss);
-  __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex);
-  __ j(not_equal, &miss);
-  __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
-  __ ret(2 * kPointerSize);
+  // If there is a call site cache don't look in the global cache, but do the
+  // real lookup and update the call site cache.
+  if (!HasCallSiteInlineCheck()) {
+    // Look up the function and the map in the instanceof cache.
+    NearLabel miss;
+    __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
+    __ j(not_equal, &miss);
+    __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex);
+    __ j(not_equal, &miss);
+    __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
+    __ ret(2 * kPointerSize);
+    __ bind(&miss);
+  }
 
-  __ bind(&miss);
   __ TryGetFunctionPrototype(rdx, rbx, &slow);
 
   // Check that the function prototype is a JS object.
@@ -3702,8 +3820,19 @@
   //   rax is object map.
   //   rdx is function.
   //   rbx is function prototype.
-  __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
-  __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex);
+  if (!HasCallSiteInlineCheck()) {
+    __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
+    __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex);
+  } else {
+    __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize));
+    __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize));
+    __ movq(Operand(kScratchRegister, kOffsetToMapCheckValue), rax);
+    if (FLAG_debug_code) {
+      __ movl(rdi, Immediate(kWordBeforeMapCheckValue));
+      __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi);
+      __ Assert(equal, "InstanceofStub unexpected call site cache.");
+    }
+  }
 
   __ movq(rcx, FieldOperand(rax, Map::kPrototypeOffset));
 
@@ -3722,19 +3851,56 @@
   __ jmp(&loop);
 
   __ bind(&is_instance);
-  __ xorl(rax, rax);
-  // Store bitwise zero in the cache.  This is a Smi in GC terms.
-  STATIC_ASSERT(kSmiTag == 0);
-  __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
-  __ ret(2 * kPointerSize);
+  if (!HasCallSiteInlineCheck()) {
+    __ xorl(rax, rax);
+    // Store bitwise zero in the cache.  This is a Smi in GC terms.
+    STATIC_ASSERT(kSmiTag == 0);
+    __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
+  } else {
+    // Store offset of true in the root array at the inline check site.
+    ASSERT((Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias
+        == 0xB0 - 0x100);
+    __ movl(rax, Immediate(0xB0));  // TrueValue is at -10 * kPointerSize.
+    __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize));
+    __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize));
+    __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax);
+    if (FLAG_debug_code) {
+      __ movl(rax, Immediate(kWordBeforeResultValue));
+      __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
+      __ Assert(equal, "InstanceofStub unexpected call site cache.");
+    }
+    __ xorl(rax, rax);
+  }
+  __ ret(2 * kPointerSize + extra_stack_space);
 
   __ bind(&is_not_instance);
-  // We have to store a non-zero value in the cache.
-  __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex);
-  __ ret(2 * kPointerSize);
+  if (!HasCallSiteInlineCheck()) {
+    // We have to store a non-zero value in the cache.
+    __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex);
+  } else {
+    // Store offset of false in the root array at the inline check site.
+    ASSERT((Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias
+        == 0xB8 - 0x100);
+    __ movl(rax, Immediate(0xB8));  // FalseValue is at -9 * kPointerSize.
+    __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize));
+    __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize));
+    __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax);
+    if (FLAG_debug_code) {
+      __ movl(rax, Immediate(kWordBeforeResultValue));
+      __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
+      __ Assert(equal, "InstanceofStub unexpected call site cache (mov)");
+    }
+  }
+  __ ret(2 * kPointerSize + extra_stack_space);
 
   // Slow-case: Go through the JavaScript implementation.
   __ bind(&slow);
+  if (HasCallSiteInlineCheck()) {
+    // Remove extra value from the stack.
+    __ pop(rcx);
+    __ pop(rax);
+    __ push(rcx);
+  }
   __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
 }
 
@@ -3768,7 +3934,8 @@
 
   if (name_ != NULL) return name_;
   const int kMaxNameLength = 100;
-  name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
+  name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
+      kMaxNameLength);
   if (name_ == NULL) return "OOM";
 
   const char* cc_name;
@@ -3902,7 +4069,7 @@
   // Index is not a smi.
   __ bind(&index_not_smi_);
   // If index is a heap number, try converting it to an integer.
-  __ CheckMap(index_, Factory::heap_number_map(), index_not_number_, true);
+  __ CheckMap(index_, FACTORY->heap_number_map(), index_not_number_, true);
   call_helper.BeforeCall(masm);
   __ push(object_);
   __ push(index_);
@@ -4047,7 +4214,8 @@
   __ SmiTest(rcx);
   __ j(not_zero, &second_not_zero_length);
   // Second string is empty, result is first string which is already in rax.
-  __ IncrementCounter(&Counters::string_add_native, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->string_add_native(), 1);
   __ ret(2 * kPointerSize);
   __ bind(&second_not_zero_length);
   __ movq(rbx, FieldOperand(rax, String::kLengthOffset));
@@ -4055,7 +4223,7 @@
   __ j(not_zero, &both_not_zero_length);
   // First string is empty, result is second string which is in rdx.
   __ movq(rax, rdx);
-  __ IncrementCounter(&Counters::string_add_native, 1);
+  __ IncrementCounter(counters->string_add_native(), 1);
   __ ret(2 * kPointerSize);
 
   // Both strings are non-empty.
@@ -4081,8 +4249,8 @@
   // Look at the length of the result of adding the two strings.
   STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue / 2);
   __ SmiAdd(rbx, rbx, rcx);
-  // Use the runtime system when adding two one character strings, as it
-  // contains optimizations for this specific case using the symbol table.
+  // Use the symbol table when adding two one character strings, as it
+  // helps later optimizations to return a symbol here.
   __ SmiCompare(rbx, Smi::FromInt(2));
   __ j(not_equal, &longer_than_two);
 
@@ -4098,8 +4266,8 @@
   // just allocate a new one.
   Label make_two_character_string, make_flat_ascii_string;
   StringHelper::GenerateTwoCharacterSymbolTableProbe(
-      masm, rbx, rcx, r14, r11, rdi, r12, &make_two_character_string);
-  __ IncrementCounter(&Counters::string_add_native, 1);
+      masm, rbx, rcx, r14, r11, rdi, r15, &make_two_character_string);
+  __ IncrementCounter(counters->string_add_native(), 1);
   __ ret(2 * kPointerSize);
 
   __ bind(&make_two_character_string);
@@ -4139,7 +4307,7 @@
   __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax);
   __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx);
   __ movq(rax, rcx);
-  __ IncrementCounter(&Counters::string_add_native, 1);
+  __ IncrementCounter(counters->string_add_native(), 1);
   __ ret(2 * kPointerSize);
   __ bind(&non_ascii);
   // At least one of the strings is two-byte. Check whether it happens
@@ -4213,7 +4381,7 @@
   // rdi: length of second argument
   StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, true);
   __ movq(rax, rbx);
-  __ IncrementCounter(&Counters::string_add_native, 1);
+  __ IncrementCounter(counters->string_add_native(), 1);
   __ ret(2 * kPointerSize);
 
   // Handle creating a flat two byte result.
@@ -4250,7 +4418,7 @@
   // rdi: length of second argument
   StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, false);
   __ movq(rax, rbx);
-  __ IncrementCounter(&Counters::string_add_native, 1);
+  __ IncrementCounter(counters->string_add_native(), 1);
   __ ret(2 * kPointerSize);
 
   // Just jump to runtime to add the two strings.
@@ -4434,15 +4602,14 @@
                     FieldOperand(symbol_table, SymbolTable::kCapacityOffset));
   __ decl(mask);
 
-  Register undefined = scratch4;
-  __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
+  Register map = scratch4;
 
   // Registers
   // chars:        two character string, char 1 in byte 0 and char 2 in byte 1.
   // hash:         hash of two character string (32-bit int)
   // symbol_table: symbol table
   // mask:         capacity mask (32-bit int)
-  // undefined:    undefined value
+  // map:          -
   // scratch:      -
 
   // Perform a number of probes in the symbol table.
@@ -4457,7 +4624,7 @@
     }
     __ andl(scratch, mask);
 
-    // Load the entry from the symble table.
+    // Load the entry from the symbol table.
     Register candidate = scratch;  // Scratch register contains candidate.
     STATIC_ASSERT(SymbolTable::kEntrySize == 1);
     __ movq(candidate,
@@ -4467,8 +4634,16 @@
                          SymbolTable::kElementsStartOffset));
 
     // If entry is undefined no string with this hash can be found.
-    __ cmpq(candidate, undefined);
+    NearLabel is_string;
+    __ CmpObjectType(candidate, ODDBALL_TYPE, map);
+    __ j(not_equal, &is_string);
+
+    __ CompareRoot(candidate, Heap::kUndefinedValueRootIndex);
     __ j(equal, not_found);
+    // Must be null (deleted entry).
+    __ jmp(&next_probe[i]);
+
+    __ bind(&is_string);
 
     // If length is not 2 the string is not a candidate.
     __ SmiCompare(FieldOperand(candidate, String::kLengthOffset),
@@ -4480,8 +4655,7 @@
     Register temp = kScratchRegister;
 
     // Check that the candidate is a non-external ascii string.
-    __ movq(temp, FieldOperand(candidate, HeapObject::kMapOffset));
-    __ movzxbl(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
+    __ movzxbl(temp, FieldOperand(map, Map::kInstanceTypeOffset));
     __ JumpIfInstanceTypeIsNotSequentialAscii(
         temp, temp, &next_probe[i]);
 
@@ -4659,7 +4833,8 @@
   // rsi: character of sub string start
   StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true);
   __ movq(rsi, rdx);  // Restore rsi.
-  __ IncrementCounter(&Counters::sub_string_native, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->sub_string_native(), 1);
   __ ret(kArgumentsSize);
 
   __ bind(&non_ascii_flat);
@@ -4696,7 +4871,7 @@
   __ movq(rsi, rdx);  // Restore esi.
 
   __ bind(&return_rax);
-  __ IncrementCounter(&Counters::sub_string_native, 1);
+  __ IncrementCounter(counters->sub_string_native(), 1);
   __ ret(kArgumentsSize);
 
   // Just jump to runtime to create the sub string.
@@ -4810,7 +4985,8 @@
   __ cmpq(rdx, rax);
   __ j(not_equal, &not_same);
   __ Move(rax, Smi::FromInt(EQUAL));
-  __ IncrementCounter(&Counters::string_compare_native, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->string_compare_native(), 1);
   __ ret(2 * kPointerSize);
 
   __ bind(&not_same);
@@ -4819,7 +4995,7 @@
   __ JumpIfNotBothSequentialAsciiStrings(rdx, rax, rcx, rbx, &runtime);
 
   // Inline comparison of ascii strings.
-  __ IncrementCounter(&Counters::string_compare_native, 1);
+  __ IncrementCounter(counters->string_compare_native(), 1);
   // Drop arguments from the stack
   __ pop(rcx);
   __ addq(rsp, Immediate(2 * kPointerSize));
@@ -4833,60 +5009,6 @@
 }
 
 
-void StringCharAtStub::Generate(MacroAssembler* masm) {
-  // Expects two arguments (object, index) on the stack:
-
-  // Stack frame on entry.
-  //  rsp[0]: return address
-  //  rsp[8]: index
-  //  rsp[16]: object
-
-  Register object = rbx;
-  Register index = rax;
-  Register scratch1 = rcx;
-  Register scratch2 = rdx;
-  Register result = rax;
-
-  __ pop(scratch1);  // Return address.
-  __ pop(index);
-  __ pop(object);
-  __ push(scratch1);
-
-  Label need_conversion;
-  Label index_out_of_range;
-  Label done;
-  StringCharAtGenerator generator(object,
-                                  index,
-                                  scratch1,
-                                  scratch2,
-                                  result,
-                                  &need_conversion,
-                                  &need_conversion,
-                                  &index_out_of_range,
-                                  STRING_INDEX_IS_NUMBER);
-  generator.GenerateFast(masm);
-  __ jmp(&done);
-
-  __ bind(&index_out_of_range);
-  // When the index is out of range, the spec requires us to return
-  // the empty string.
-  __ Move(result, Factory::empty_string());
-  __ jmp(&done);
-
-  __ bind(&need_conversion);
-  // Move smi zero into the result register, which will trigger
-  // conversion.
-  __ Move(result, Smi::FromInt(0));
-  __ jmp(&done);
-
-  StubRuntimeCallHelper call_helper;
-  generator.GenerateSlow(masm, call_helper);
-
-  __ bind(&done);
-  __ ret(0);
-}
-
-
 void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
   ASSERT(state_ == CompareIC::SMIS);
   NearLabel miss;
@@ -4982,7 +5104,8 @@
   __ push(rcx);
 
   // Call the runtime system in a fresh internal frame.
-  ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss));
+  ExternalReference miss =
+      ExternalReference(IC_Utility(IC::kCompareIC_Miss), masm->isolate());
   __ EnterInternalFrame();
   __ push(rdx);
   __ push(rax);
@@ -5004,144 +5127,6 @@
 }
 
 
-void GenerateFastPixelArrayLoad(MacroAssembler* masm,
-                                Register receiver,
-                                Register key,
-                                Register elements,
-                                Register untagged_key,
-                                Register result,
-                                Label* not_pixel_array,
-                                Label* key_not_smi,
-                                Label* out_of_range) {
-  // Register use:
-  //   receiver - holds the receiver and is unchanged.
-  //   key - holds the key and is unchanged (must be a smi).
-  //   elements - is set to the the receiver's element if
-  //       the receiver doesn't have a pixel array or the
-  //       key is not a smi, otherwise it's the elements'
-  //       external pointer.
-  //   untagged_key - is set to the untagged key
-
-  // Some callers already have verified that the key is a smi.  key_not_smi is
-  // set to NULL as a sentinel for that case.  Otherwise, add an explicit check
-  // to ensure the key is a smi must be added.
-  if (key_not_smi != NULL) {
-    __ JumpIfNotSmi(key, key_not_smi);
-  } else {
-    if (FLAG_debug_code) {
-      __ AbortIfNotSmi(key);
-    }
-  }
-  __ SmiToInteger32(untagged_key, key);
-
-  __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset));
-  // By passing NULL as not_pixel_array, callers signal that they have already
-  // verified that the receiver has pixel array elements.
-  if (not_pixel_array != NULL) {
-    __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true);
-  } else {
-    if (FLAG_debug_code) {
-      // Map check should have already made sure that elements is a pixel array.
-      __  Cmp(FieldOperand(elements, HeapObject::kMapOffset),
-              Factory::pixel_array_map());
-      __ Assert(equal, "Elements isn't a pixel array");
-    }
-  }
-
-  // Check that the smi is in range.
-  __ cmpl(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset));
-  __ j(above_equal, out_of_range);  // unsigned check handles negative keys.
-
-  // Load and tag the element as a smi.
-  __ movq(elements, FieldOperand(elements, PixelArray::kExternalPointerOffset));
-  __ movzxbq(result, Operand(elements, untagged_key, times_1, 0));
-  __ Integer32ToSmi(result, result);
-  __ ret(0);
-}
-
-
-// Stores an indexed element into a pixel array, clamping the stored value.
-void GenerateFastPixelArrayStore(MacroAssembler* masm,
-                                 Register receiver,
-                                 Register key,
-                                 Register value,
-                                 Register elements,
-                                 Register scratch1,
-                                 bool load_elements_from_receiver,
-                                 bool key_is_untagged,
-                                 Label* key_not_smi,
-                                 Label* value_not_smi,
-                                 Label* not_pixel_array,
-                                 Label* out_of_range) {
-  // Register use:
-  //   receiver - holds the receiver and is unchanged.
-  //   key - holds the key (must be a smi) and is unchanged.
-  //   value - holds the value (must be a smi) and is unchanged.
-  //   elements - holds the element object of the receiver on entry if
-  //              load_elements_from_receiver is false, otherwise used
-  //              internally to store the pixel arrays elements and
-  //              external array pointer.
-  //
-  Register external_pointer = elements;
-  Register untagged_key = scratch1;
-  Register untagged_value = receiver;  // Only set once success guaranteed.
-
-  // Fetch the receiver's elements if the caller hasn't already done so.
-  if (load_elements_from_receiver) {
-    __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset));
-  }
-
-  // By passing NULL as not_pixel_array, callers signal that they have already
-  // verified that the receiver has pixel array elements.
-  if (not_pixel_array != NULL) {
-    __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true);
-  } else {
-    if (FLAG_debug_code) {
-      // Map check should have already made sure that elements is a pixel array.
-      __  Cmp(FieldOperand(elements, HeapObject::kMapOffset),
-              Factory::pixel_array_map());
-      __ Assert(equal, "Elements isn't a pixel array");
-    }
-  }
-
-  // Key must be a smi and it must be in range.
-  if (key_is_untagged) {
-    untagged_key = key;
-  } else {
-    // Some callers already have verified that the key is a smi.  key_not_smi is
-    // set to NULL as a sentinel for that case.  Otherwise, add an explicit
-    // check to ensure the key is a smi.
-    if (key_not_smi != NULL) {
-      __ JumpIfNotSmi(key, key_not_smi);
-    } else {
-      if (FLAG_debug_code) {
-        __ AbortIfNotSmi(key);
-      }
-    }
-    __ SmiToInteger32(untagged_key, key);
-  }
-  __ cmpl(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset));
-  __ j(above_equal, out_of_range);  // unsigned check handles negative keys.
-
-  // Value must be a smi.
-  __ JumpIfNotSmi(value, value_not_smi);
-  __ SmiToInteger32(untagged_value, value);
-
-  {  // Clamp the value to [0..255].
-    NearLabel done;
-    __ testl(untagged_value, Immediate(0xFFFFFF00));
-    __ j(zero, &done);
-    __ setcc(negative, untagged_value);  // 1 if negative, 0 if positive.
-    __ decb(untagged_value);  // 0 if negative, 255 if positive.
-    __ bind(&done);
-  }
-
-  __ movq(external_pointer,
-          FieldOperand(elements, PixelArray::kExternalPointerOffset));
-  __ movb(Operand(external_pointer, untagged_key, times_1, 0), untagged_value);
-  __ ret(0);  // Return value in eax.
-}
-
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h
index 32a37b2..246650a 100644
--- a/src/x64/code-stubs-x64.h
+++ b/src/x64/code-stubs-x64.h
@@ -289,6 +289,7 @@
   void GenerateSmiStub(MacroAssembler* masm);
   void GenerateInt32Stub(MacroAssembler* masm);
   void GenerateHeapNumberStub(MacroAssembler* masm);
+  void GenerateOddballStub(MacroAssembler* masm);
   void GenerateStringStub(MacroAssembler* masm);
   void GenerateGenericStub(MacroAssembler* masm);
 
@@ -471,49 +472,6 @@
 };
 
 
-// Generate code to load an element from a pixel array. The receiver is assumed
-// to not be a smi and to have elements, the caller must guarantee this
-// precondition. If key is not a smi, then the generated code branches to
-// key_not_smi. Callers can specify NULL for key_not_smi to signal that a smi
-// check has already been performed on key so that the smi check is not
-// generated. If key is not a valid index within the bounds of the pixel array,
-// the generated code jumps to out_of_range. receiver, key and elements are
-// unchanged throughout the generated code sequence.
-void GenerateFastPixelArrayLoad(MacroAssembler* masm,
-                                Register receiver,
-                                Register key,
-                                Register elements,
-                                Register untagged_key,
-                                Register result,
-                                Label* not_pixel_array,
-                                Label* key_not_smi,
-                                Label* out_of_range);
-
-// Generate code to store an element into a pixel array, clamping values between
-// [0..255]. The receiver is assumed to not be a smi and to have elements, the
-// caller must guarantee this precondition. If key is not a smi, then the
-// generated code branches to key_not_smi. Callers can specify NULL for
-// key_not_smi to signal that a smi check has already been performed on key so
-// that the smi check is not generated. If the value is not a smi, the
-// generated code will branch to value_not_smi.  If the receiver
-// doesn't have pixel array elements, the generated code will branch to
-// not_pixel_array, unless not_pixel_array is NULL, in which case the caller
-// must ensure that the receiver has pixel array elements.  If key is not a
-// valid index within the bounds of the pixel array, the generated code jumps to
-// out_of_range.
-void GenerateFastPixelArrayStore(MacroAssembler* masm,
-                                 Register receiver,
-                                 Register key,
-                                 Register value,
-                                 Register elements,
-                                 Register scratch1,
-                                 bool load_elements_from_receiver,
-                                 bool key_is_untagged,
-                                 Label* key_not_smi,
-                                 Label* value_not_smi,
-                                 Label* not_pixel_array,
-                                 Label* out_of_range);
-
 } }  // namespace v8::internal
 
 #endif  // V8_X64_CODE_STUBS_X64_H_
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index fc4bc04..8c338fe 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -180,7 +180,7 @@
   ASSERT_EQ(0, loop_nesting_);
   loop_nesting_ = info->is_in_loop() ? 1 : 0;
 
-  JumpTarget::set_compiling_deferred_code(false);
+  Isolate::Current()->set_jump_target_compiling_deferred_code(false);
 
   {
     CodeGenState state(this);
@@ -281,7 +281,7 @@
 
     // Initialize ThisFunction reference if present.
     if (scope()->is_function_scope() && scope()->function() != NULL) {
-      frame_->Push(Factory::the_hole_value());
+      frame_->Push(FACTORY->the_hole_value());
       StoreToSlot(scope()->function()->AsSlot(), NOT_CONST_INIT);
     }
 
@@ -316,7 +316,7 @@
     if (!scope()->HasIllegalRedeclaration()) {
       Comment cmnt(masm_, "[ function body");
 #ifdef DEBUG
-      bool is_builtin = Bootstrapper::IsActive();
+      bool is_builtin = Isolate::Current()->bootstrapper()->IsActive();
       bool should_trace =
           is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;
       if (should_trace) {
@@ -333,7 +333,7 @@
         ASSERT(!function_return_is_shadowed_);
         CodeForReturnPosition(info->function());
         frame_->PrepareForReturn();
-        Result undefined(Factory::undefined_value());
+        Result undefined(FACTORY->undefined_value());
         if (function_return_.is_bound()) {
           function_return_.Jump(&undefined);
         } else {
@@ -365,9 +365,9 @@
 
   // Process any deferred code using the register allocator.
   if (!HasStackOverflow()) {
-    JumpTarget::set_compiling_deferred_code(true);
+    info->isolate()->set_jump_target_compiling_deferred_code(true);
     ProcessDeferred();
-    JumpTarget::set_compiling_deferred_code(false);
+    info->isolate()->set_jump_target_compiling_deferred_code(false);
   }
 
   // There is no need to delete the register allocator, it is a
@@ -516,12 +516,12 @@
   if (dest.false_was_fall_through()) {
     // The false target was just bound.
     JumpTarget loaded;
-    frame_->Push(Factory::false_value());
+    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());
+      frame_->Push(FACTORY->true_value());
       loaded.Bind();
     }
 
@@ -529,11 +529,11 @@
     // There is true, and possibly false, control flow (with true as
     // the fall through).
     JumpTarget loaded;
-    frame_->Push(Factory::true_value());
+    frame_->Push(FACTORY->true_value());
     if (false_target.is_linked()) {
       loaded.Jump();
       false_target.Bind();
-      frame_->Push(Factory::false_value());
+      frame_->Push(FACTORY->false_value());
       loaded.Bind();
     }
 
@@ -548,14 +548,14 @@
       loaded.Jump();  // Don't lose the current TOS.
       if (true_target.is_linked()) {
         true_target.Bind();
-        frame_->Push(Factory::true_value());
+        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());
+        frame_->Push(FACTORY->false_value());
       }
       loaded.Bind();
     }
@@ -611,11 +611,13 @@
 
 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() {
   if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION;
-  ASSERT(scope()->arguments_shadow() != NULL);
+
+  // In strict mode there is no need for shadow arguments.
+  ASSERT(scope()->arguments_shadow() != NULL || scope()->is_strict_mode());
   // We don't want to do lazy arguments allocation for functions that
   // have heap-allocated contexts, because it interfers with the
   // uninitialized const tracking in the context objects.
-  return (scope()->num_heap_slots() > 0)
+  return (scope()->num_heap_slots() > 0 || scope()->is_strict_mode())
       ? EAGER_ARGUMENTS_ALLOCATION
       : LAZY_ARGUMENTS_ALLOCATION;
 }
@@ -630,9 +632,11 @@
     // When using lazy arguments allocation, we store the arguments marker value
     // as a sentinel indicating that the arguments object hasn't been
     // allocated yet.
-    frame_->Push(Factory::arguments_marker());
+    frame_->Push(FACTORY->arguments_marker());
   } else {
-    ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
+    ArgumentsAccessStub stub(is_strict_mode()
+        ? ArgumentsAccessStub::NEW_STRICT
+        : ArgumentsAccessStub::NEW_NON_STRICT);
     frame_->PushFunction();
     frame_->PushReceiverSlotAddress();
     frame_->Push(Smi::FromInt(scope()->num_parameters()));
@@ -643,7 +647,9 @@
   Variable* arguments = scope()->arguments();
   Variable* shadow = scope()->arguments_shadow();
   ASSERT(arguments != NULL && arguments->AsSlot() != NULL);
-  ASSERT(shadow != NULL && shadow->AsSlot() != NULL);
+  ASSERT((shadow != NULL && shadow->AsSlot() != NULL) ||
+         scope()->is_strict_mode());
+
   JumpTarget done;
   bool skip_arguments = false;
   if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) {
@@ -666,7 +672,9 @@
     StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT);
     if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind();
   }
-  StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
+  if (shadow != NULL) {
+    StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
+  }
   return frame_->Pop();
 }
 
@@ -760,7 +768,7 @@
       __ AbortIfNotNumber(value.reg());
     }
     // Smi => false iff zero.
-    __ SmiCompare(value.reg(), Smi::FromInt(0));
+    __ Cmp(value.reg(), Smi::FromInt(0));
     if (value.is_smi()) {
       value.Unuse();
       dest->Split(not_zero);
@@ -788,7 +796,7 @@
     dest->false_target()->Branch(equal);
 
     // Smi => false iff zero.
-    __ SmiCompare(value.reg(), Smi::FromInt(0));
+    __ Cmp(value.reg(), Smi::FromInt(0));
     dest->false_target()->Branch(equal);
     Condition is_smi = masm_->CheckSmi(value.reg());
     dest->true_target()->Branch(is_smi);
@@ -1030,7 +1038,7 @@
                                         true, overwrite_mode);
   } else {
     // Set the flags based on the operation, type and loop nesting level.
-    // Bit operations always assume they likely operate on Smis. Still only
+    // 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.
     // For all other operations only inline the Smi check code for likely smis
     // if the operation is part of a loop.
@@ -1054,7 +1062,7 @@
 
 
 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) {
-  Object* answer_object = Heap::undefined_value();
+  Object* answer_object = HEAP->undefined_value();
   switch (op) {
     case Token::ADD:
       // Use intptr_t to detect overflow of 32-bit int.
@@ -1128,7 +1136,7 @@
       UNREACHABLE();
       break;
   }
-  if (answer_object == Heap::undefined_value()) {
+  if (answer_object->IsUndefined()) {
     return false;
   }
   frame_->Push(Handle<Object>(answer_object));
@@ -1363,7 +1371,7 @@
         if (!left_type_info.IsNumber()) {
           // Branch if not a heapnumber.
           __ Cmp(FieldOperand(answer.reg(), HeapObject::kMapOffset),
-                 Factory::heap_number_map());
+                 FACTORY->heap_number_map());
           deferred->Branch(not_equal);
         }
         // Load integer value into answer register using truncation.
@@ -2102,7 +2110,7 @@
       if (cc == equal) {
         Label comparison_done;
         __ SmiCompare(FieldOperand(left_side.reg(), String::kLengthOffset),
-                Smi::FromInt(1));
+                      Smi::FromInt(1));
         __ j(not_equal, &comparison_done);
         uint8_t char_value =
             static_cast<uint8_t>(String::cast(*right_val)->Get(0));
@@ -2288,7 +2296,7 @@
       // 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.
+    // where both sides are smis.
     left_side->ToRegister();
     Register left_reg = left_side->reg();
     Smi* constant_smi = Smi::cast(*right_side->handle());
@@ -2298,7 +2306,6 @@
         __ AbortIfNotSmi(left_reg);
       }
       // Test smi equality and comparison by signed int comparison.
-      // Both sides are smis, so we can use an Immediate.
       __ SmiCompare(left_reg, constant_smi);
       left_side->Unuse();
       right_side->Unuse();
@@ -2308,7 +2315,7 @@
       JumpTarget is_smi;
       if (cc == equal) {
         // We can do the equality comparison before the smi check.
-        __ SmiCompare(left_reg, constant_smi);
+        __ Cmp(left_reg, constant_smi);
         dest->true_target()->Branch(equal);
         Condition left_is_smi = masm_->CheckSmi(left_reg);
         dest->false_target()->Branch(left_is_smi);
@@ -2326,7 +2333,7 @@
         // not to be a smi.
         JumpTarget not_number;
         __ Cmp(FieldOperand(left_reg, HeapObject::kMapOffset),
-               Factory::heap_number_map());
+               FACTORY->heap_number_map());
         not_number.Branch(not_equal, left_side);
         __ movsd(xmm1,
                  FieldOperand(left_reg, HeapNumber::kValueOffset));
@@ -2486,7 +2493,7 @@
   // give us a megamorphic load site. Not super, but it works.
   Load(applicand);
   frame()->Dup();
-  Handle<String> name = Factory::LookupAsciiSymbol("apply");
+  Handle<String> name = FACTORY->LookupAsciiSymbol("apply");
   frame()->Push(name);
   Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET);
   __ nop();
@@ -2554,7 +2561,7 @@
       __ j(not_equal, &build_args);
       __ movq(rcx, FieldOperand(rax, JSFunction::kCodeEntryOffset));
       __ subq(rcx, Immediate(Code::kHeaderSize - kHeapObjectTag));
-      Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
+      Handle<Code> apply_code = Isolate::Current()->builtins()->FunctionApply();
       __ Cmp(rcx, apply_code);
       __ j(not_equal, &build_args);
 
@@ -2569,8 +2576,8 @@
       // adaptor frame below it.
       Label invoke, adapted;
       __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
-      __ SmiCompare(Operand(rdx, StandardFrameConstants::kContextOffset),
-                    Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+      __ Cmp(Operand(rdx, StandardFrameConstants::kContextOffset),
+             Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
       __ j(equal, &adapted);
 
       // No arguments adaptor frame. Copy fixed number of arguments.
@@ -2797,7 +2804,7 @@
   // 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());
+    val = new Literal(FACTORY->the_hole_value());
   } else {
     val = node->fun();  // NULL if we don't have a function
   }
@@ -3851,7 +3858,7 @@
   __ movq(rbx, rax);
 
   // If the property has been removed while iterating, we just skip it.
-  __ SmiCompare(rbx, Smi::FromInt(0));
+  __ Cmp(rbx, Smi::FromInt(0));
   node->continue_target()->Branch(equal);
 
   end_del_check.Bind();
@@ -3973,7 +3980,7 @@
   function_return_is_shadowed_ = function_return_was_shadowed;
 
   // Get an external reference to the handler address.
-  ExternalReference handler_address(Top::k_handler_address);
+  ExternalReference handler_address(Isolate::k_handler_address, isolate());
 
   // Make sure that there's nothing left on the stack above the
   // handler structure.
@@ -4102,7 +4109,7 @@
   function_return_is_shadowed_ = function_return_was_shadowed;
 
   // Get an external reference to the handler address.
-  ExternalReference handler_address(Top::k_handler_address);
+  ExternalReference handler_address(Isolate::k_handler_address, isolate());
 
   // 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.
@@ -4255,10 +4262,11 @@
 
   // Use the fast case closure allocation code that allocates in new
   // space for nested functions that don't need literals cloning.
-  if (scope()->is_function_scope() &&
-      function_info->num_literals() == 0 &&
-      !pretenure) {
-    FastNewClosureStub stub;
+  if (!pretenure &&
+      scope()->is_function_scope() &&
+      function_info->num_literals() == 0) {
+    FastNewClosureStub stub(
+        function_info->strict_mode() ? kStrictMode : kNonStrictMode);
     frame_->Push(function_info);
     Result answer = frame_->CallStub(&stub, 1);
     frame_->Push(&answer);
@@ -4268,8 +4276,8 @@
     frame_->EmitPush(rsi);
     frame_->EmitPush(function_info);
     frame_->EmitPush(pretenure
-                     ? Factory::true_value()
-                     : Factory::false_value());
+                     ? FACTORY->true_value()
+                     : FACTORY->false_value());
     Result result = frame_->CallRuntime(Runtime::kNewClosure, 3);
     frame_->Push(&result);
   }
@@ -4754,7 +4762,7 @@
                              Register target,
                              int registers_to_save = 0)
     : size_(size), target_(target), registers_to_save_(registers_to_save) {
-    ASSERT(size >= kPointerSize && size <= Heap::MaxObjectSizeInNewSpace());
+    ASSERT(size >= kPointerSize && size <= HEAP->MaxObjectSizeInNewSpace());
     set_comment("[ DeferredAllocateInNewSpace");
   }
   void Generate();
@@ -4969,11 +4977,12 @@
   frame_->Push(node->constant_elements());
   int length = node->values()->length();
   Result clone;
-  if (node->constant_elements()->map() == Heap::fixed_cow_array_map()) {
+  if (node->constant_elements()->map() == HEAP->fixed_cow_array_map()) {
     FastCloneShallowArrayStub stub(
         FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
     clone = frame_->CallStub(&stub, 3);
-    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1);
+    Counters* counters = masm()->isolate()->counters();
+    __ IncrementCounter(counters->cow_arrays_created_stub(), 1);
   } else if (node->depth() > 1) {
     clone = frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3);
   } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
@@ -5371,7 +5380,7 @@
     Load(function);
 
     // Allocate a frame slot for the receiver.
-    frame_->Push(Factory::undefined_value());
+    frame_->Push(FACTORY->undefined_value());
 
     // Load the arguments.
     int arg_count = args->length();
@@ -5403,7 +5412,7 @@
       if (arg_count > 0) {
         frame_->PushElementAt(arg_count);
       } else {
-        frame_->Push(Factory::undefined_value());
+        frame_->Push(FACTORY->undefined_value());
       }
       frame_->PushParameterAt(-1);
 
@@ -5425,7 +5434,7 @@
     if (arg_count > 0) {
       frame_->PushElementAt(arg_count);
     } else {
-      frame_->Push(Factory::undefined_value());
+      frame_->Push(FACTORY->undefined_value());
     }
     frame_->PushParameterAt(-1);
 
@@ -5714,7 +5723,7 @@
   }
 #endif
   // Finally, we're expected to leave a value on the top of the stack.
-  frame_->Push(Factory::undefined_value());
+  frame_->Push(FACTORY->undefined_value());
 }
 
 
@@ -5977,7 +5986,7 @@
   Condition is_smi = masm_->CheckSmi(obj.reg());
   destination()->false_target()->Branch(is_smi);
 
-  __ Move(kScratchRegister, Factory::null_value());
+  __ Move(kScratchRegister, FACTORY->null_value());
   __ cmpq(obj.reg(), kScratchRegister);
   destination()->true_target()->Branch(equal);
 
@@ -6069,7 +6078,7 @@
     __ jmp(&entry);
     __ bind(&loop);
     __ movq(scratch2_, FieldOperand(map_result_, 0));
-    __ Cmp(scratch2_, Factory::value_of_symbol());
+    __ Cmp(scratch2_, FACTORY->value_of_symbol());
     __ j(equal, &false_result);
     __ addq(map_result_, Immediate(kPointerSize));
     __ bind(&entry);
@@ -6192,15 +6201,15 @@
 
   // Skip the arguments adaptor frame if it exists.
   Label check_frame_marker;
-  __ SmiCompare(Operand(fp.reg(), StandardFrameConstants::kContextOffset),
-                Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+  __ Cmp(Operand(fp.reg(), StandardFrameConstants::kContextOffset),
+         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
   __ j(not_equal, &check_frame_marker);
   __ movq(fp.reg(), Operand(fp.reg(), StandardFrameConstants::kCallerFPOffset));
 
   // Check the marker in the calling frame.
   __ bind(&check_frame_marker);
-  __ SmiCompare(Operand(fp.reg(), StandardFrameConstants::kMarkerOffset),
-                Smi::FromInt(StackFrame::CONSTRUCT));
+  __ Cmp(Operand(fp.reg(), StandardFrameConstants::kMarkerOffset),
+         Smi::FromInt(StackFrame::CONSTRUCT));
   fp.Unuse();
   destination()->Split(equal);
 }
@@ -6220,8 +6229,8 @@
 
   // Check if the calling frame is an arguments adaptor frame.
   __ movq(fp.reg(), Operand(rbp, StandardFrameConstants::kCallerFPOffset));
-  __ SmiCompare(Operand(fp.reg(), StandardFrameConstants::kContextOffset),
-                Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+  __ Cmp(Operand(fp.reg(), StandardFrameConstants::kContextOffset),
+         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
   __ j(not_equal, &exit);
 
   // Arguments adaptor case: Read the arguments length from the
@@ -6281,17 +6290,17 @@
 
   // Functions have class 'Function'.
   function.Bind();
-  frame_->Push(Factory::function_class_symbol());
+  frame_->Push(FACTORY->function_class_symbol());
   leave.Jump();
 
   // Objects with a non-function constructor have class 'Object'.
   non_function_constructor.Bind();
-  frame_->Push(Factory::Object_symbol());
+  frame_->Push(FACTORY->Object_symbol());
   leave.Jump();
 
   // Non-JS objects have class null.
   null.Bind();
-  frame_->Push(Factory::null_value());
+  frame_->Push(FACTORY->null_value());
 
   // All done.
   leave.Bind();
@@ -6430,7 +6439,7 @@
   // Return a random uint32 number in rax.
   // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs.
   __ PrepareCallCFunction(0);
-  __ CallCFunction(ExternalReference::random_uint32_function(), 0);
+  __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 0);
 
   // Convert 32 random bits in rax to 0.(32 random bits) in a double
   // by computing:
@@ -6660,10 +6669,10 @@
   int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
 
   Handle<FixedArray> jsfunction_result_caches(
-      Top::global_context()->jsfunction_result_caches());
+      Isolate::Current()->global_context()->jsfunction_result_caches());
   if (jsfunction_result_caches->length() <= cache_id) {
     __ Abort("Attempt to use undefined cache.");
-    frame_->Push(Factory::undefined_value());
+    frame_->Push(FACTORY->undefined_value());
     return;
   }
 
@@ -6777,8 +6786,8 @@
   // Fetch the map and check if array is in fast case.
   // Check that object doesn't require security checks and
   // has no indexed interceptor.
-  __ CmpObjectType(object.reg(), FIRST_JS_OBJECT_TYPE, tmp1.reg());
-  deferred->Branch(below);
+  __ CmpObjectType(object.reg(), JS_ARRAY_TYPE, tmp1.reg());
+  deferred->Branch(not_equal);
   __ testb(FieldOperand(tmp1.reg(), Map::kBitFieldOffset),
            Immediate(KeyedLoadIC::kSlowCaseBitFieldMask));
   deferred->Branch(not_zero);
@@ -6820,7 +6829,7 @@
 
   Label done;
   __ InNewSpace(tmp1.reg(), tmp2.reg(), equal, &done);
-  // Possible optimization: do a check that both values are Smis
+  // Possible optimization: do a check that both values are smis
   // (or them and test against Smi mask.)
 
   __ movq(tmp2.reg(), tmp1.reg());
@@ -6829,7 +6838,7 @@
   __ bind(&done);
 
   deferred->BindExit();
-  frame_->Push(Factory::undefined_value());
+  frame_->Push(FACTORY->undefined_value());
 }
 
 
@@ -7173,7 +7182,7 @@
 
 
 void CodeGenerator::GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args) {
-  frame_->Push(Factory::undefined_value());
+  frame_->Push(FACTORY->undefined_value());
 }
 
 
@@ -7184,7 +7193,7 @@
 
   ZoneList<Expression*>* args = node->arguments();
   Comment cmnt(masm_, "[ CallRuntime");
-  Runtime::Function* function = node->function();
+  const Runtime::Function* function = node->function();
 
   if (function == NULL) {
     // Push the builtins object found in the current global object.
@@ -7268,12 +7277,12 @@
       } else {
         // Default: Result of deleting non-global, not dynamically
         // introduced variables is false.
-        frame_->Push(Factory::false_value());
+        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());
+      frame_->SetElementAt(0, FACTORY->true_value());
     }
 
   } else if (op == Token::TYPEOF) {
@@ -7294,10 +7303,10 @@
         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());
+      frame_->Push(FACTORY->undefined_value());
     } else {
       Load(node->expression());
-      frame_->SetElementAt(0, Factory::undefined_value());
+      frame_->SetElementAt(0, FACTORY->undefined_value());
     }
 
   } else {
@@ -7769,7 +7778,7 @@
     Result answer = frame_->Pop();
     answer.ToRegister();
 
-    if (check->Equals(Heap::number_symbol())) {
+    if (check->Equals(HEAP->number_symbol())) {
       Condition is_smi = masm_->CheckSmi(answer.reg());
       destination()->true_target()->Branch(is_smi);
       frame_->Spill(answer.reg());
@@ -7778,7 +7787,7 @@
       answer.Unuse();
       destination()->Split(equal);
 
-    } else if (check->Equals(Heap::string_symbol())) {
+    } else if (check->Equals(HEAP->string_symbol())) {
       Condition is_smi = masm_->CheckSmi(answer.reg());
       destination()->false_target()->Branch(is_smi);
 
@@ -7792,14 +7801,14 @@
       answer.Unuse();
       destination()->Split(below);  // Unsigned byte comparison needed.
 
-    } else if (check->Equals(Heap::boolean_symbol())) {
+    } else if (check->Equals(HEAP->boolean_symbol())) {
       __ CompareRoot(answer.reg(), Heap::kTrueValueRootIndex);
       destination()->true_target()->Branch(equal);
       __ CompareRoot(answer.reg(), Heap::kFalseValueRootIndex);
       answer.Unuse();
       destination()->Split(equal);
 
-    } else if (check->Equals(Heap::undefined_symbol())) {
+    } else if (check->Equals(HEAP->undefined_symbol())) {
       __ CompareRoot(answer.reg(), Heap::kUndefinedValueRootIndex);
       destination()->true_target()->Branch(equal);
 
@@ -7814,7 +7823,7 @@
       answer.Unuse();
       destination()->Split(not_zero);
 
-    } else if (check->Equals(Heap::function_symbol())) {
+    } else if (check->Equals(HEAP->function_symbol())) {
       Condition is_smi = masm_->CheckSmi(answer.reg());
       destination()->false_target()->Branch(is_smi);
       frame_->Spill(answer.reg());
@@ -7825,7 +7834,7 @@
       answer.Unuse();
       destination()->Split(equal);
 
-    } else if (check->Equals(Heap::object_symbol())) {
+    } else if (check->Equals(HEAP->object_symbol())) {
       Condition is_smi = masm_->CheckSmi(answer.reg());
       destination()->false_target()->Branch(is_smi);
       __ CompareRoot(answer.reg(), Heap::kNullValueRootIndex);
@@ -7955,7 +7964,7 @@
       && (allocator()->count(r9) == (frame()->is_used(r9) ? 1 : 0))
       && (allocator()->count(r11) == (frame()->is_used(r11) ? 1 : 0))
       && (allocator()->count(r14) == (frame()->is_used(r14) ? 1 : 0))
-      && (allocator()->count(r12) == (frame()->is_used(r12) ? 1 : 0));
+      && (allocator()->count(r15) == (frame()->is_used(r15) ? 1 : 0));
 }
 #endif
 
@@ -7989,7 +7998,7 @@
     __ movq(rax, receiver_);
   }
   __ Move(rcx, name_);
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Handle<Code> ic = Isolate::Current()->builtins()->LoadIC_Initialize();
   __ Call(ic, RelocInfo::CODE_TARGET);
   // The call must be followed by a test rax instruction to indicate
   // that the inobject property case was inlined.
@@ -8001,7 +8010,8 @@
   // Here we use masm_-> instead of the __ macro because this is the
   // instruction that gets patched and coverage code gets in the way.
   masm_->testl(rax, Immediate(-delta_to_patch_site));
-  __ IncrementCounter(&Counters::named_load_inline_miss, 1);
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->named_load_inline_miss(), 1);
 
   if (!dst_.is(rax)) __ movq(dst_, rax);
 }
@@ -8054,7 +8064,7 @@
   // it in the IC initialization code and patch the movq instruction.
   // This means that we cannot allow test instructions after calls to
   // KeyedLoadIC stubs in other places.
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  Handle<Code> ic = Isolate::Current()->builtins()->KeyedLoadIC_Initialize();
   __ Call(ic, RelocInfo::CODE_TARGET);
   // The delta from the start of the map-compare instruction to the
   // test instruction.  We use masm_-> directly here instead of the __
@@ -8068,7 +8078,8 @@
   // 7-byte NOP with non-zero immediate (0f 1f 80 xxxxxxxx) which won't
   // be generated normally.
   masm_->testl(rax, Immediate(-delta_to_patch_site));
-  __ IncrementCounter(&Counters::keyed_load_inline_miss, 1);
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_inline_miss(), 1);
 
   if (!dst_.is(rax)) __ movq(dst_, rax);
 }
@@ -8101,7 +8112,8 @@
 
 
 void DeferredReferenceSetKeyedValue::Generate() {
-  __ IncrementCounter(&Counters::keyed_store_inline_miss, 1);
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->keyed_store_inline_miss(), 1);
   // Move value, receiver, and key to registers rax, rdx, and rcx, as
   // the IC stub expects.
   // Move value to rax, using xchg if the receiver or key is in rax.
@@ -8148,9 +8160,9 @@
   }
 
   // Call the IC stub.
-  Handle<Code> ic(Builtins::builtin(
-      (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
-                                    : Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      (strict_mode_ == kStrictMode) ? Builtins::kKeyedStoreIC_Initialize_Strict
+                                    : Builtins::kKeyedStoreIC_Initialize));
   __ Call(ic, RelocInfo::CODE_TARGET);
   // The delta from the start of the map-compare instructions (initial movq)
   // to the test instruction.  We use masm_-> directly here instead of the
@@ -8195,17 +8207,9 @@
     result = allocator()->Allocate();
     ASSERT(result.is_valid());
 
-    // Cannot use r12 for receiver, because that changes
-    // the distance between a call and a fixup location,
-    // due to a special encoding of r12 as r/m in a ModR/M byte.
-    if (receiver.reg().is(r12)) {
-      frame()->Spill(receiver.reg());  // It will be overwritten with result.
-      // Swap receiver and value.
-      __ movq(result.reg(), receiver.reg());
-      Result temp = receiver;
-      receiver = result;
-      result = temp;
-    }
+    // r12 is now a reserved register, so it cannot be the receiver.
+    // If it was, the distance to the fixup location would not be constant.
+    ASSERT(!receiver.reg().is(r12));
 
     DeferredReferenceGetNamedValue* deferred =
         new DeferredReferenceGetNamedValue(result.reg(), receiver.reg(), name);
@@ -8217,7 +8221,7 @@
     // This is the map check instruction that will be patched (so we can't
     // use the double underscore macro that may insert instructions).
     // Initially use an invalid map to force a failure.
-    masm()->movq(kScratchRegister, Factory::null_value(),
+    masm()->movq(kScratchRegister, FACTORY->null_value(),
                  RelocInfo::EMBEDDED_OBJECT);
     masm()->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
                  kScratchRegister);
@@ -8236,7 +8240,8 @@
     int offset = kMaxInt;
     masm()->movq(result.reg(), FieldOperand(receiver.reg(), offset));
 
-    __ IncrementCounter(&Counters::named_load_inline, 1);
+    Counters* counters = masm()->isolate()->counters();
+    __ IncrementCounter(counters->named_load_inline(), 1);
     deferred->BindExit();
   }
   ASSERT(frame()->height() == original_height - 1);
@@ -8294,7 +8299,7 @@
     // the __ macro for the following two instructions because it
     // might introduce extra instructions.
     __ bind(&patch_site);
-    masm()->movq(kScratchRegister, Factory::null_value(),
+    masm()->movq(kScratchRegister, FACTORY->null_value(),
                  RelocInfo::EMBEDDED_OBJECT);
     masm()->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
                  kScratchRegister);
@@ -8408,7 +8413,7 @@
     // coverage code can interfere with the patching.  Do not use a load
     // from the root array to load null_value, since the load must be patched
     // with the expected receiver map, which is not in the root array.
-    masm_->movq(kScratchRegister, Factory::null_value(),
+    masm_->movq(kScratchRegister, FACTORY->null_value(),
                 RelocInfo::EMBEDDED_OBJECT);
     masm_->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
                 kScratchRegister);
@@ -8443,7 +8448,8 @@
     result = elements;
     __ CompareRoot(result.reg(), Heap::kTheHoleValueRootIndex);
     deferred->Branch(equal);
-    __ IncrementCounter(&Counters::keyed_load_inline, 1);
+    Counters* counters = masm()->isolate()->counters();
+    __ IncrementCounter(counters->keyed_load_inline(), 1);
 
     deferred->BindExit();
   } else {
@@ -8510,12 +8516,6 @@
     __ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, kScratchRegister);
     deferred->Branch(not_equal);
 
-    // Check that the key is within bounds.  Both the key and the length of
-    // the JSArray are smis. Use unsigned comparison to handle negative keys.
-    __ SmiCompare(FieldOperand(receiver.reg(), JSArray::kLengthOffset),
-                  key.reg());
-    deferred->Branch(below_equal);
-
     // Get the elements array from the receiver and check that it is not a
     // dictionary.
     __ movq(tmp.reg(),
@@ -8538,12 +8538,20 @@
     __ bind(deferred->patch_site());
     // Avoid using __ to ensure the distance from patch_site
     // to the map address is always the same.
-    masm()->movq(kScratchRegister, Factory::fixed_array_map(),
+    masm()->movq(kScratchRegister, FACTORY->fixed_array_map(),
                RelocInfo::EMBEDDED_OBJECT);
     __ cmpq(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
             kScratchRegister);
     deferred->Branch(not_equal);
 
+    // Check that the key is within bounds.  Both the key and the length of
+    // the JSArray are smis (because the fixed array check above ensures the
+    // elements are in fast case). Use unsigned comparison to handle negative
+    // keys.
+    __ SmiCompare(FieldOperand(receiver.reg(), JSArray::kLengthOffset),
+                  key.reg());
+    deferred->Branch(below_equal);
+
     // Store the value.
     SmiIndex index =
         masm()->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2);
@@ -8552,7 +8560,8 @@
                          index.scale,
                          FixedArray::kHeaderSize),
             result.reg());
-    __ IncrementCounter(&Counters::keyed_store_inline, 1);
+    Counters* counters = masm()->isolate()->counters();
+    __ IncrementCounter(counters->keyed_store_inline(), 1);
 
     deferred->BindExit();
   } else {
diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h
index 4392829..9a70907 100644
--- a/src/x64/codegen-x64.h
+++ b/src/x64/codegen-x64.h
@@ -357,6 +357,7 @@
   // Accessors
   inline bool is_eval();
   inline Scope* scope();
+  inline bool is_strict_mode();
   inline StrictModeFlag strict_mode_flag();
 
   // Generating deferred code.
@@ -732,6 +733,7 @@
   bool in_spilled_code_;
 
   friend class VirtualFrame;
+  friend class Isolate;
   friend class JumpTarget;
   friend class Reference;
   friend class Result;
@@ -740,6 +742,7 @@
   friend class FullCodeGenSyntaxChecker;
 
   friend class CodeGeneratorPatcher;  // Used in test-log-stack-tracer.cc
+  friend class InlineRuntimeFunctionsTable;
 
   DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
 };
diff --git a/src/x64/cpu-x64.cc b/src/x64/cpu-x64.cc
index 3ff292e..b49fb1c 100644
--- a/src/x64/cpu-x64.cc
+++ b/src/x64/cpu-x64.cc
@@ -42,7 +42,7 @@
 namespace internal {
 
 void CPU::Setup() {
-  CpuFeatures::Probe(true);
+  Isolate::Current()->cpu_features()->Probe(true);
   if (Serializer::enabled()) {
     V8::DisableCrankshaft();
   }
diff --git a/src/x64/debug-x64.cc b/src/x64/debug-x64.cc
index 2c50ddd..0398465 100644
--- a/src/x64/debug-x64.cc
+++ b/src/x64/debug-x64.cc
@@ -49,7 +49,8 @@
 void BreakLocationIterator::SetDebugBreakAtReturn()  {
   ASSERT(Assembler::kJSReturnSequenceLength >=
          Assembler::kCallInstructionLength);
-  rinfo()->PatchCodeWithCall(Debug::debug_break_return()->entry(),
+  rinfo()->PatchCodeWithCall(
+      Isolate::Current()->debug()->debug_break_return()->entry(),
       Assembler::kJSReturnSequenceLength - Assembler::kCallInstructionLength);
 }
 
@@ -79,7 +80,7 @@
 void BreakLocationIterator::SetDebugBreakAtSlot() {
   ASSERT(IsDebugBreakSlot());
   rinfo()->PatchCodeWithCall(
-      Debug::debug_break_slot()->entry(),
+      Isolate::Current()->debug()->debug_break_slot()->entry(),
       Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength);
 }
 
@@ -128,7 +129,7 @@
   __ RecordComment("// Calling from debug break to runtime - come in - over");
 #endif
   __ Set(rax, 0);  // No arguments (argc == 0).
-  __ movq(rbx, ExternalReference::debug_break());
+  __ movq(rbx, ExternalReference::debug_break(masm->isolate()));
 
   CEntryStub ceb(1);
   __ CallStub(&ceb);
@@ -167,7 +168,7 @@
   // 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());
+      ExternalReference(Debug_Address::AfterBreakTarget(), masm->isolate());
   __ movq(kScratchRegister, after_break_target);
   __ jmp(Operand(kScratchRegister, 0));
 }
@@ -283,7 +284,8 @@
 
 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
   ExternalReference restarter_frame_function_slot =
-      ExternalReference(Debug_Address::RestarterFrameFunctionPointer());
+      ExternalReference(Debug_Address::RestarterFrameFunctionPointer(),
+                        masm->isolate());
   __ movq(rax, restarter_frame_function_slot);
   __ movq(Operand(rax, 0), Immediate(0));
 
diff --git a/src/x64/deoptimizer-x64.cc b/src/x64/deoptimizer-x64.cc
index daa9128..2080c61 100644
--- a/src/x64/deoptimizer-x64.cc
+++ b/src/x64/deoptimizer-x64.cc
@@ -101,7 +101,13 @@
 };
 
 
+void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
+  // TODO(1276): Implement.
+}
+
+
 void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
+  HandleScope scope;
   AssertNoAllocation no_allocation;
 
   if (!function->IsOptimized()) return;
@@ -186,8 +192,9 @@
 
   // Add the deoptimizing code to the list.
   DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code);
-  node->set_next(deoptimizing_code_list_);
-  deoptimizing_code_list_ = node;
+  DeoptimizerData* data = code->GetIsolate()->deoptimizer_data();
+  node->set_next(data->deoptimizing_code_list_);
+  data->deoptimizing_code_list_ = node;
 
   // Set the code for the function to non-optimized version.
   function->ReplaceCode(function->shared()->code());
@@ -196,6 +203,11 @@
     PrintF("[forced deoptimization: ");
     function->PrintName();
     PrintF(" / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function));
+#ifdef DEBUG
+    if (FLAG_print_code) {
+      code->PrintLn();
+    }
+#endif
   }
 }
 
@@ -349,13 +361,32 @@
 
   // There are no translation commands for the caller's pc and fp, the
   // context, and the function.  Set them up explicitly.
-  for (int i = 0; ok && i < 4; i++) {
+  for (int i = StandardFrameConstants::kCallerPCOffset;
+       ok && i >=  StandardFrameConstants::kMarkerOffset;
+       i -= kPointerSize) {
     intptr_t input_value = input_->GetFrameSlot(input_offset);
     if (FLAG_trace_osr) {
-      PrintF("    [esp + %d] <- 0x%08" V8PRIxPTR " ; [esp + %d] (fixed part)\n",
+      const char* name = "UNKNOWN";
+      switch (i) {
+        case StandardFrameConstants::kCallerPCOffset:
+          name = "caller's pc";
+          break;
+        case StandardFrameConstants::kCallerFPOffset:
+          name = "fp";
+          break;
+        case StandardFrameConstants::kContextOffset:
+          name = "context";
+          break;
+        case StandardFrameConstants::kMarkerOffset:
+          name = "function";
+          break;
+      }
+      PrintF("    [rsp + %d] <- 0x%08" V8PRIxPTR " ; [rsp + %d] "
+             "(fixed part - %s)\n",
              output_offset,
              input_value,
-             input_offset);
+             input_offset,
+             name);
     }
     output_[0]->SetFrameSlot(output_offset, input_->GetFrameSlot(input_offset));
     input_offset -= kPointerSize;
@@ -382,7 +413,8 @@
         optimized_code_->entry() + pc_offset);
     output_[0]->SetPc(pc);
   }
-  Code* continuation = Builtins::builtin(Builtins::NotifyOSR);
+  Code* continuation =
+      function->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR);
   output_[0]->SetContinuation(
       reinterpret_cast<intptr_t>(continuation->entry()));
 
@@ -554,8 +586,8 @@
   // Set the continuation for the topmost frame.
   if (is_topmost) {
     Code* continuation = (bailout_type_ == EAGER)
-        ? Builtins::builtin(Builtins::NotifyDeoptimized)
-        : Builtins::builtin(Builtins::NotifyLazyDeoptimized);
+        ? isolate_->builtins()->builtin(Builtins::kNotifyDeoptimized)
+        : isolate_->builtins()->builtin(Builtins::kNotifyLazyDeoptimized);
     output_frame->SetContinuation(
         reinterpret_cast<intptr_t>(continuation->entry()));
   }
@@ -645,7 +677,9 @@
   __ movq(r8, arg5);
 #endif
 
-  __ CallCFunction(ExternalReference::new_deoptimizer_function(), 5);
+  Isolate* isolate = masm()->isolate();
+
+  __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate), 5);
   // Preserve deoptimizer object in register rax and get the input
   // frame descriptor pointer.
   __ movq(rbx, Operand(rax, Deoptimizer::input_offset()));
@@ -690,7 +724,8 @@
   __ push(rax);
   __ PrepareCallCFunction(1);
   __ movq(arg1, rax);
-  __ CallCFunction(ExternalReference::compute_output_frames_function(), 1);
+  __ CallCFunction(
+      ExternalReference::compute_output_frames_function(isolate), 1);
   __ pop(rax);
 
   // Replace the current frame with the output frames.
@@ -748,7 +783,6 @@
   }
 
   // Set up the roots register.
-  ExternalReference roots_address = ExternalReference::roots_address();
   __ InitializeRootRegister();
   __ InitializeSmiConstantRegister();
 
diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc
index 21a100f..189ee42 100644
--- a/src/x64/disasm-x64.cc
+++ b/src/x64/disasm-x64.cc
@@ -269,6 +269,7 @@
 
 static InstructionTable instruction_table;
 
+
 static InstructionDesc cmov_instructions[16] = {
   {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
   {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
@@ -451,9 +452,11 @@
 
 int DisassemblerX64::PrintRightOperandHelper(
     byte* modrmp,
-    RegisterNameMapping register_name) {
+    RegisterNameMapping direct_register_name) {
   int mod, regop, rm;
   get_modrm(*modrmp, &mod, &regop, &rm);
+  RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
+      &DisassemblerX64::NameOfCPURegister;
   switch (mod) {
     case 0:
       if ((rm & 7) == 5) {
@@ -1028,7 +1031,7 @@
       } else if (opcode == 0x6F) {
         AppendToBuffer("movdqa %s,",
                        NameOfXMMRegister(regop));
-        current += PrintRightOperand(current);
+        current += PrintRightXMMOperand(current);
       } else if (opcode == 0x7E) {
         AppendToBuffer("mov%c ",
                        rex_w() ? 'q' : 'd');
@@ -1036,7 +1039,7 @@
         AppendToBuffer(", %s", NameOfXMMRegister(regop));
       } else if (opcode == 0x7F) {
         AppendToBuffer("movdqa ");
-        current += PrintRightOperand(current);
+        current += PrintRightXMMOperand(current);
         AppendToBuffer(", %s", NameOfXMMRegister(regop));
       } else {
         const char* mnemonic = "?";
@@ -1068,11 +1071,11 @@
       int mod, regop, rm;
       get_modrm(*current, &mod, &regop, &rm);
       if (opcode == 0x11) {
-        current += PrintRightOperand(current);
+        current += PrintRightXMMOperand(current);
         AppendToBuffer(",%s", NameOfXMMRegister(regop));
       } else {
         AppendToBuffer("%s,", NameOfXMMRegister(regop));
-        current += PrintRightOperand(current);
+        current += PrintRightXMMOperand(current);
       }
     } else if (opcode == 0x2A) {
       // CVTSI2SD: integer to XMM double conversion.
@@ -1435,19 +1438,26 @@
       {
         bool is_byte = *data == 0xC6;
         data++;
-
-        AppendToBuffer("mov%c ", is_byte ? 'b' : operand_size_code());
-        data += PrintRightOperand(data);
-        int32_t imm = is_byte ? *data : *reinterpret_cast<int32_t*>(data);
-        AppendToBuffer(",0x%x", imm);
-        data += is_byte ? 1 : 4;
+        if (is_byte) {
+          AppendToBuffer("movb ");
+          data += PrintRightByteOperand(data);
+          int32_t imm = *data;
+          AppendToBuffer(",0x%x", imm);
+          data++;
+        } else {
+          AppendToBuffer("mov%c ", operand_size_code());
+          data += PrintRightOperand(data);
+          int32_t imm = *reinterpret_cast<int32_t*>(data);
+          AppendToBuffer(",0x%x", imm);
+          data += 4;
+        }
       }
         break;
 
       case 0x80: {
         data++;
         AppendToBuffer("cmpb ");
-        data += PrintRightOperand(data);
+        data += PrintRightByteOperand(data);
         int32_t imm = *data;
         AppendToBuffer(",0x%x", imm);
         data++;
@@ -1461,9 +1471,15 @@
         int mod, regop, rm;
         data++;
         get_modrm(*data, &mod, &regop, &rm);
-        AppendToBuffer("mov%c ", is_byte ? 'b' : operand_size_code());
-        data += PrintRightOperand(data);
-        AppendToBuffer(",%s", NameOfCPURegister(regop));
+        if (is_byte) {
+          AppendToBuffer("movb ");
+          data += PrintRightByteOperand(data);
+          AppendToBuffer(",%s", NameOfByteCPURegister(regop));
+        } else {
+          AppendToBuffer("mov%c ", operand_size_code());
+          data += PrintRightOperand(data);
+          AppendToBuffer(",%s", NameOfCPURegister(regop));
+        }
       }
         break;
 
@@ -1493,7 +1509,7 @@
         get_modrm(*data, &mod, &regop, &rm);
         if (regop == 1) {
           AppendToBuffer("decb ");
-          data += PrintRightOperand(data);
+          data += PrintRightByteOperand(data);
         } else {
           UnimplementedInstruction();
         }
@@ -1652,9 +1668,8 @@
 
 
 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();
+  v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
+  return tmp_buffer_.start();
 }
 
 
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 780f4b0..90afd85 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -198,13 +198,18 @@
     //   function, receiver address, parameter count.
     // The stub will rewrite receiver and parameter count if the previous
     // stack frame was an arguments adapter frame.
-    ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
+    ArgumentsAccessStub stub(
+        is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT
+                         : ArgumentsAccessStub::NEW_NON_STRICT);
     __ CallStub(&stub);
-    // Store new arguments object in both "arguments" and ".arguments" slots.
-    __ movq(rcx, rax);
+
+    Variable* arguments_shadow = scope()->arguments_shadow();
+    if (arguments_shadow != NULL) {
+      // Store new arguments object in both "arguments" and ".arguments" slots.
+      __ movq(rcx, rax);
+      Move(arguments_shadow->AsSlot(), rcx, rbx, rdx);
+    }
     Move(arguments->AsSlot(), rax, rbx, rdx);
-    Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot();
-    Move(dot_arguments_slot, rcx, rbx, rdx);
   }
 
   if (FLAG_trace) {
@@ -476,10 +481,10 @@
     Label* materialize_false) const {
   NearLabel done;
   __ bind(materialize_true);
-  __ Move(result_register(), Factory::true_value());
+  __ Move(result_register(), isolate()->factory()->true_value());
   __ jmp(&done);
   __ bind(materialize_false);
-  __ Move(result_register(), Factory::false_value());
+  __ Move(result_register(), isolate()->factory()->false_value());
   __ bind(&done);
 }
 
@@ -489,10 +494,10 @@
     Label* materialize_false) const {
   NearLabel done;
   __ bind(materialize_true);
-  __ Push(Factory::true_value());
+  __ Push(isolate()->factory()->true_value());
   __ jmp(&done);
   __ bind(materialize_false);
-  __ Push(Factory::false_value());
+  __ Push(isolate()->factory()->false_value());
   __ bind(&done);
 }
 
@@ -546,7 +551,7 @@
   __ CompareRoot(result_register(), Heap::kFalseValueRootIndex);
   __ j(equal, if_false);
   STATIC_ASSERT(kSmiTag == 0);
-  __ SmiCompare(result_register(), Smi::FromInt(0));
+  __ Cmp(result_register(), Smi::FromInt(0));
   __ j(equal, if_false);
   Condition is_smi = masm_->CheckSmi(result_register());
   __ j(is_smi, if_true);
@@ -735,9 +740,9 @@
              prop->key()->AsLiteral()->handle()->IsSmi());
       __ Move(rcx, prop->key()->AsLiteral()->handle());
 
-      Handle<Code> ic(Builtins::builtin(is_strict()
-          ? Builtins::KeyedStoreIC_Initialize_Strict
-          : Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic = is_strict_mode()
+          ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+          : isolate()->builtins()->KeyedStoreIC_Initialize();
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
     }
   }
@@ -834,6 +839,7 @@
     Comment cmnt(masm_, "[ Case body");
     CaseClause* clause = clauses->at(i);
     __ bind(clause->body_target()->entry_label());
+    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
     VisitStatements(clause->statements());
   }
 
@@ -991,7 +997,7 @@
   __ push(rcx);  // Enumerable.
   __ push(rbx);  // Current entry.
   __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
-  __ SmiCompare(rax, Smi::FromInt(0));
+  __ Cmp(rax, Smi::FromInt(0));
   __ j(equal, loop_statement.continue_target());
   __ movq(rbx, rax);
 
@@ -1035,16 +1041,18 @@
   // doesn't just get a copy of the existing unoptimized code.
   if (!FLAG_always_opt &&
       !FLAG_prepare_always_opt &&
+      !pretenure &&
       scope()->is_function_scope() &&
-      info->num_literals() == 0 &&
-      !pretenure) {
-    FastNewClosureStub stub;
+      info->num_literals() == 0) {
+    FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode);
     __ Push(info);
     __ CallStub(&stub);
   } else {
     __ push(rsi);
     __ Push(info);
-    __ Push(pretenure ? Factory::true_value() : Factory::false_value());
+    __ Push(pretenure
+            ? isolate()->factory()->true_value()
+            : isolate()->factory()->false_value());
     __ CallRuntime(Runtime::kNewClosure, 3);
   }
   context()->Plug(rax);
@@ -1113,7 +1121,7 @@
   // load IC call.
   __ movq(rax, GlobalObjectOperand());
   __ Move(rcx, slot->var()->name());
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
       ? RelocInfo::CODE_TARGET
       : RelocInfo::CODE_TARGET_CONTEXT;
@@ -1196,7 +1204,8 @@
                   ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
                                                     slow));
           __ Move(rax, key_literal->handle());
-          Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+          Handle<Code> ic =
+              isolate()->builtins()->KeyedLoadIC_Initialize();
           EmitCallIC(ic, RelocInfo::CODE_TARGET);
           __ jmp(done);
         }
@@ -1219,7 +1228,7 @@
     // object on the stack.
     __ Move(rcx, var->name());
     __ movq(rax, GlobalObjectOperand());
-    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
     EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
     context()->Plug(rax);
 
@@ -1282,7 +1291,7 @@
     __ Move(rax, key_literal->handle());
 
     // Do a keyed property load.
-    Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+    Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
     EmitCallIC(ic, RelocInfo::CODE_TARGET);
     context()->Plug(rax);
   }
@@ -1349,7 +1358,13 @@
   __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
   __ Push(Smi::FromInt(expr->literal_index()));
   __ Push(expr->constant_properties());
-  __ Push(Smi::FromInt(expr->fast_elements() ? 1 : 0));
+  int flags = expr->fast_elements()
+      ? ObjectLiteral::kFastElements
+      : ObjectLiteral::kNoFlags;
+  flags |= expr->has_function()
+      ? ObjectLiteral::kHasFunction
+      : ObjectLiteral::kNoFlags;
+  __ Push(Smi::FromInt(flags));
   if (expr->depth() > 1) {
     __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
   } else {
@@ -1387,7 +1402,7 @@
           __ Move(rcx, key->handle());
           __ movq(rdx, Operand(rsp, 0));
           if (property->emit_store()) {
-            Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+            Handle<Code> ic = isolate()->builtins()->StoreIC_Initialize();
             EmitCallIC(ic, RelocInfo::CODE_TARGET);
             PrepareForBailoutForId(key->id(), NO_REGISTERS);
           }
@@ -1418,6 +1433,12 @@
     }
   }
 
+  if (expr->has_function()) {
+    ASSERT(result_saved);
+    __ push(Operand(rsp, 0));
+    __ CallRuntime(Runtime::kToFastProperties, 1);
+  }
+
   if (result_saved) {
     context()->PlugTOS();
   } else {
@@ -1436,11 +1457,12 @@
   __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
   __ Push(Smi::FromInt(expr->literal_index()));
   __ Push(expr->constant_elements());
-  if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) {
+  if (expr->constant_elements()->map() ==
+      isolate()->heap()->fixed_cow_array_map()) {
     FastCloneShallowArrayStub stub(
         FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
     __ CallStub(&stub);
-    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1);
+    __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), 1);
   } else if (expr->depth() > 1) {
     __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
   } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
@@ -1624,14 +1646,14 @@
   SetSourcePosition(prop->position());
   Literal* key = prop->key()->AsLiteral();
   __ Move(rcx, key->handle());
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 }
 
 
 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
   SetSourcePosition(prop->position());
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 }
 
@@ -1737,9 +1759,9 @@
       __ movq(rdx, rax);
       __ pop(rax);  // Restore value.
       __ Move(rcx, prop->key()->AsLiteral()->handle());
-      Handle<Code> ic(Builtins::builtin(
-          is_strict() ? Builtins::StoreIC_Initialize_Strict
-                      : Builtins::StoreIC_Initialize));
+      Handle<Code> ic = is_strict_mode()
+          ? isolate()->builtins()->StoreIC_Initialize_Strict()
+          : isolate()->builtins()->StoreIC_Initialize();
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
@@ -1760,9 +1782,9 @@
         __ pop(rdx);
       }
       __ pop(rax);  // Restore value.
-      Handle<Code> ic(Builtins::builtin(
-          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
-                      : Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic = is_strict_mode()
+          ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+          : isolate()->builtins()->KeyedStoreIC_Initialize();
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
@@ -1786,9 +1808,9 @@
     // rcx, and the global object on the stack.
     __ Move(rcx, var->name());
     __ movq(rdx, GlobalObjectOperand());
-    Handle<Code> ic(Builtins::builtin(is_strict()
-        ? Builtins::StoreIC_Initialize_Strict
-        : Builtins::StoreIC_Initialize));
+    Handle<Code> ic = is_strict_mode()
+        ? isolate()->builtins()->StoreIC_Initialize_Strict()
+        : isolate()->builtins()->StoreIC_Initialize();
     EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
 
   } else if (op == Token::INIT_CONST) {
@@ -1889,9 +1911,9 @@
   } else {
     __ pop(rdx);
   }
-  Handle<Code> ic(Builtins::builtin(
-      is_strict() ? Builtins::StoreIC_Initialize_Strict
-                  : Builtins::StoreIC_Initialize));
+  Handle<Code> ic = is_strict_mode()
+      ? isolate()->builtins()->StoreIC_Initialize_Strict()
+      : isolate()->builtins()->StoreIC_Initialize();
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -1929,9 +1951,9 @@
   }
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
-  Handle<Code> ic(Builtins::builtin(
-      is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
-                  : Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic = is_strict_mode()
+      ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+      : isolate()->builtins()->KeyedStoreIC_Initialize();
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -1982,7 +2004,8 @@
   SetSourcePosition(expr->position());
   // Call the IC initialization code.
   InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
+  Handle<Code> ic =
+      ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop);
   EmitCallIC(ic, mode);
   RecordJSReturnSite(expr);
   // Restore context register.
@@ -2015,7 +2038,8 @@
   SetSourcePosition(expr->position());
   // Call the IC initialization code.
   InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
+  Handle<Code> ic =
+      ISOLATE->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop);
   __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize));  // Key.
   EmitCallIC(ic, mode);
   RecordJSReturnSite(expr);
@@ -2208,7 +2232,7 @@
         // Record source code position for IC call.
         SetSourcePosition(prop->position());
 
-        Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+        Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
         EmitCallIC(ic, RelocInfo::CODE_TARGET);
         // Push result (function).
         __ push(rax);
@@ -2229,7 +2253,7 @@
     // also use the full code generator.
     FunctionLiteral* lit = fun->AsFunctionLiteral();
     if (lit != NULL &&
-        lit->name()->Equals(Heap::empty_string()) &&
+        lit->name()->Equals(isolate()->heap()->empty_string()) &&
         loop_depth() == 0) {
       lit->set_try_full_codegen(true);
     }
@@ -2276,7 +2300,8 @@
   __ Set(rax, arg_count);
   __ movq(rdi, Operand(rsp, arg_count * kPointerSize));
 
-  Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
+  Handle<Code> construct_builtin =
+      isolate()->builtins()->JSConstructCall();
   __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
   context()->Plug(rax);
 }
@@ -2498,15 +2523,15 @@
 
   // Skip the arguments adaptor frame if it exists.
   Label check_frame_marker;
-  __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset),
-                Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+  __ Cmp(Operand(rax, StandardFrameConstants::kContextOffset),
+         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
   __ j(not_equal, &check_frame_marker);
   __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
 
   // Check the marker in the calling frame.
   __ bind(&check_frame_marker);
-  __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset),
-                Smi::FromInt(StackFrame::CONSTRUCT));
+  __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset),
+         Smi::FromInt(StackFrame::CONSTRUCT));
   PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
   Split(equal, if_true, if_false, fall_through);
 
@@ -2560,8 +2585,8 @@
 
   // Check if the calling frame is an arguments adaptor frame.
   __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
-  __ SmiCompare(Operand(rbx, StandardFrameConstants::kContextOffset),
-                Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+  __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
+         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
   __ j(not_equal, &exit);
 
   // Arguments adaptor case: Read the arguments length from the
@@ -2609,12 +2634,12 @@
 
   // Functions have class 'Function'.
   __ bind(&function);
-  __ Move(rax, Factory::function_class_symbol());
+  __ Move(rax, isolate()->factory()->function_class_symbol());
   __ jmp(&done);
 
   // Objects with a non-function constructor have class 'Object'.
   __ bind(&non_function_constructor);
-  __ Move(rax, Factory::Object_symbol());
+  __ Move(rax, isolate()->factory()->Object_symbol());
   __ jmp(&done);
 
   // Non-JS objects have class null.
@@ -2669,7 +2694,7 @@
   // Return a random uint32 number in rax.
   // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs.
   __ PrepareCallCFunction(0);
-  __ CallCFunction(ExternalReference::random_uint32_function(), 0);
+  __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 0);
 
   // Convert 32 random bits in rax to 0.(32 random bits) in a double
   // by computing:
@@ -3006,8 +3031,8 @@
   // Fetch the map and check if array is in fast case.
   // Check that object doesn't require security checks and
   // has no indexed interceptor.
-  __ CmpObjectType(object, FIRST_JS_OBJECT_TYPE, temp);
-  __ j(below, &slow_case);
+  __ CmpObjectType(object, JS_ARRAY_TYPE, temp);
+  __ j(not_equal, &slow_case);
   __ testb(FieldOperand(temp, Map::kBitFieldOffset),
            Immediate(KeyedLoadIC::kSlowCaseBitFieldMask));
   __ j(not_zero, &slow_case);
@@ -3073,7 +3098,7 @@
   int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
 
   Handle<FixedArray> jsfunction_result_caches(
-      Top::global_context()->jsfunction_result_caches());
+      isolate()->global_context()->jsfunction_result_caches());
   if (jsfunction_result_caches->length() <= cache_id) {
     __ Abort("Attempt to use undefined cache.");
     __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
@@ -3150,10 +3175,10 @@
   __ cmpq(tmp, FieldOperand(right, JSRegExp::kDataOffset));
   __ j(equal, &ok);
   __ bind(&fail);
-  __ Move(rax, Factory::false_value());
+  __ Move(rax, isolate()->factory()->false_value());
   __ jmp(&done);
   __ bind(&ok);
-  __ Move(rax, Factory::true_value());
+  __ Move(rax, isolate()->factory()->true_value());
   __ bind(&done);
 
   context()->Plug(rax);
@@ -3199,7 +3224,288 @@
 
 
 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
-  context()->Plug(Heap::kUndefinedValueRootIndex);
+  Label bailout, return_result, done, one_char_separator, long_separator,
+      non_trivial_array, not_size_one_array, loop,
+      loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
+  ASSERT(args->length() == 2);
+  // We will leave the separator on the stack until the end of the function.
+  VisitForStackValue(args->at(1));
+  // Load this to rax (= array)
+  VisitForAccumulatorValue(args->at(0));
+  // All aliases of the same register have disjoint lifetimes.
+  Register array = rax;
+  Register elements = no_reg;  // Will be rax.
+
+  Register index = rdx;
+
+  Register string_length = rcx;
+
+  Register string = rsi;
+
+  Register scratch = rbx;
+
+  Register array_length = rdi;
+  Register result_pos = no_reg;  // Will be rdi.
+
+  Operand separator_operand =    Operand(rsp, 2 * kPointerSize);
+  Operand result_operand =       Operand(rsp, 1 * kPointerSize);
+  Operand array_length_operand = Operand(rsp, 0 * kPointerSize);
+  // Separator operand is already pushed. Make room for the two
+  // other stack fields, and clear the direction flag in anticipation
+  // of calling CopyBytes.
+  __ subq(rsp, Immediate(2 * kPointerSize));
+  __ cld();
+  // Check that the array is a JSArray
+  __ JumpIfSmi(array, &bailout);
+  __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
+  __ j(not_equal, &bailout);
+
+  // Check that the array has fast elements.
+  __ testb(FieldOperand(scratch, Map::kBitField2Offset),
+           Immediate(1 << Map::kHasFastElements));
+  __ j(zero, &bailout);
+
+  // Array has fast elements, so its length must be a smi.
+  // If the array has length zero, return the empty string.
+  __ movq(array_length, FieldOperand(array, JSArray::kLengthOffset));
+  __ SmiCompare(array_length, Smi::FromInt(0));
+  __ j(not_zero, &non_trivial_array);
+  __ LoadRoot(rax, Heap::kEmptyStringRootIndex);
+  __ jmp(&return_result);
+
+  // Save the array length on the stack.
+  __ bind(&non_trivial_array);
+  __ SmiToInteger32(array_length, array_length);
+  __ movl(array_length_operand, array_length);
+
+  // Save the FixedArray containing array's elements.
+  // End of array's live range.
+  elements = array;
+  __ movq(elements, FieldOperand(array, JSArray::kElementsOffset));
+  array = no_reg;
+
+
+  // Check that all array elements are sequential ASCII strings, and
+  // accumulate the sum of their lengths, as a smi-encoded value.
+  __ Set(index, 0);
+  __ Set(string_length, 0);
+  // Loop condition: while (index < array_length).
+  // Live loop registers: index(int32), array_length(int32), string(String*),
+  //                      scratch, string_length(int32), elements(FixedArray*).
+  if (FLAG_debug_code) {
+    __ cmpq(index, array_length);
+    __ Assert(below, "No empty arrays here in EmitFastAsciiArrayJoin");
+  }
+  __ bind(&loop);
+  __ movq(string, FieldOperand(elements,
+                               index,
+                               times_pointer_size,
+                               FixedArray::kHeaderSize));
+  __ JumpIfSmi(string, &bailout);
+  __ movq(scratch, FieldOperand(string, HeapObject::kMapOffset));
+  __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
+  __ andb(scratch, Immediate(
+      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
+  __ cmpb(scratch, Immediate(kStringTag | kAsciiStringTag | kSeqStringTag));
+  __ j(not_equal, &bailout);
+  __ AddSmiField(string_length,
+                 FieldOperand(string, SeqAsciiString::kLengthOffset));
+  __ j(overflow, &bailout);
+  __ incl(index);
+  __ cmpl(index, array_length);
+  __ j(less, &loop);
+
+  // Live registers:
+  // string_length: Sum of string lengths.
+  // elements: FixedArray of strings.
+  // index: Array length.
+  // array_length: Array length.
+
+  // If array_length is 1, return elements[0], a string.
+  __ cmpl(array_length, Immediate(1));
+  __ j(not_equal, &not_size_one_array);
+  __ movq(rax, FieldOperand(elements, FixedArray::kHeaderSize));
+  __ jmp(&return_result);
+
+  __ bind(&not_size_one_array);
+
+  // End of array_length live range.
+  result_pos = array_length;
+  array_length = no_reg;
+
+  // Live registers:
+  // string_length: Sum of string lengths.
+  // elements: FixedArray of strings.
+  // index: Array length.
+
+  // Check that the separator is a sequential ASCII string.
+  __ movq(string, separator_operand);
+  __ JumpIfSmi(string, &bailout);
+  __ movq(scratch, FieldOperand(string, HeapObject::kMapOffset));
+  __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
+  __ andb(scratch, Immediate(
+      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
+  __ cmpb(scratch, Immediate(kStringTag | kAsciiStringTag | kSeqStringTag));
+  __ j(not_equal, &bailout);
+
+  // Live registers:
+  // string_length: Sum of string lengths.
+  // elements: FixedArray of strings.
+  // index: Array length.
+  // string: Separator string.
+
+  // Add (separator length times (array_length - 1)) to string_length.
+  __ SmiToInteger32(scratch,
+                    FieldOperand(string, SeqAsciiString::kLengthOffset));
+  __ decl(index);
+  __ imull(scratch, index);
+  __ j(overflow, &bailout);
+  __ addl(string_length, scratch);
+  __ j(overflow, &bailout);
+
+  // Live registers and stack values:
+  //   string_length: Total length of result string.
+  //   elements: FixedArray of strings.
+  __ AllocateAsciiString(result_pos, string_length, scratch,
+                         index, string, &bailout);
+  __ movq(result_operand, result_pos);
+  __ lea(result_pos, FieldOperand(result_pos, SeqAsciiString::kHeaderSize));
+
+  __ movq(string, separator_operand);
+  __ SmiCompare(FieldOperand(string, SeqAsciiString::kLengthOffset),
+                Smi::FromInt(1));
+  __ j(equal, &one_char_separator);
+  __ j(greater, &long_separator);
+
+
+  // Empty separator case:
+  __ Set(index, 0);
+  __ movl(scratch, array_length_operand);
+  __ jmp(&loop_1_condition);
+  // Loop condition: while (index < array_length).
+  __ bind(&loop_1);
+  // Each iteration of the loop concatenates one string to the result.
+  // Live values in registers:
+  //   index: which element of the elements array we are adding to the result.
+  //   result_pos: the position to which we are currently copying characters.
+  //   elements: the FixedArray of strings we are joining.
+  //   scratch: array length.
+
+  // Get string = array[index].
+  __ movq(string, FieldOperand(elements, index,
+                               times_pointer_size,
+                               FixedArray::kHeaderSize));
+  __ SmiToInteger32(string_length,
+                    FieldOperand(string, String::kLengthOffset));
+  __ lea(string,
+         FieldOperand(string, SeqAsciiString::kHeaderSize));
+  __ CopyBytes(result_pos, string, string_length);
+  __ incl(index);
+  __ bind(&loop_1_condition);
+  __ cmpl(index, scratch);
+  __ j(less, &loop_1);  // Loop while (index < array_length).
+  __ jmp(&done);
+
+  // Generic bailout code used from several places.
+  __ bind(&bailout);
+  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
+  __ jmp(&return_result);
+
+
+  // One-character separator case
+  __ bind(&one_char_separator);
+  // Get the separator ascii character value.
+  // Register "string" holds the separator.
+  __ movzxbl(scratch, FieldOperand(string, SeqAsciiString::kHeaderSize));
+  __ Set(index, 0);
+  // Jump into the loop after the code that copies the separator, so the first
+  // element is not preceded by a separator
+  __ jmp(&loop_2_entry);
+  // Loop condition: while (index < length).
+  __ bind(&loop_2);
+  // Each iteration of the loop concatenates one string to the result.
+  // Live values in registers:
+  //   elements: The FixedArray of strings we are joining.
+  //   index: which element of the elements array we are adding to the result.
+  //   result_pos: the position to which we are currently copying characters.
+  //   scratch: Separator character.
+
+  // Copy the separator character to the result.
+  __ movb(Operand(result_pos, 0), scratch);
+  __ incq(result_pos);
+
+  __ bind(&loop_2_entry);
+  // Get string = array[index].
+  __ movq(string, FieldOperand(elements, index,
+                               times_pointer_size,
+                               FixedArray::kHeaderSize));
+  __ SmiToInteger32(string_length,
+                    FieldOperand(string, String::kLengthOffset));
+  __ lea(string,
+         FieldOperand(string, SeqAsciiString::kHeaderSize));
+  __ CopyBytes(result_pos, string, string_length);
+  __ incl(index);
+  __ cmpl(index, array_length_operand);
+  __ j(less, &loop_2);  // End while (index < length).
+  __ jmp(&done);
+
+
+  // Long separator case (separator is more than one character).
+  __ bind(&long_separator);
+
+  // Make elements point to end of elements array, and index
+  // count from -array_length to zero, so we don't need to maintain
+  // a loop limit.
+  __ movl(index, array_length_operand);
+  __ lea(elements, FieldOperand(elements, index, times_pointer_size,
+                                FixedArray::kHeaderSize));
+  __ neg(index);
+
+  // Replace separator string with pointer to its first character, and
+  // make scratch be its length.
+  __ movq(string, separator_operand);
+  __ SmiToInteger32(scratch,
+                    FieldOperand(string, String::kLengthOffset));
+  __ lea(string,
+         FieldOperand(string, SeqAsciiString::kHeaderSize));
+  __ movq(separator_operand, string);
+
+  // Jump into the loop after the code that copies the separator, so the first
+  // element is not preceded by a separator
+  __ jmp(&loop_3_entry);
+  // Loop condition: while (index < length).
+  __ bind(&loop_3);
+  // Each iteration of the loop concatenates one string to the result.
+  // Live values in registers:
+  //   index: which element of the elements array we are adding to the result.
+  //   result_pos: the position to which we are currently copying characters.
+  //   scratch: Separator length.
+  //   separator_operand (rsp[0x10]): Address of first char of separator.
+
+  // Copy the separator to the result.
+  __ movq(string, separator_operand);
+  __ movl(string_length, scratch);
+  __ CopyBytes(result_pos, string, string_length, 2);
+
+  __ bind(&loop_3_entry);
+  // Get string = array[index].
+  __ movq(string, Operand(elements, index, times_pointer_size, 0));
+  __ SmiToInteger32(string_length,
+                    FieldOperand(string, String::kLengthOffset));
+  __ lea(string,
+         FieldOperand(string, SeqAsciiString::kHeaderSize));
+  __ CopyBytes(result_pos, string, string_length);
+  __ incq(index);
+  __ j(not_equal, &loop_3);  // Loop while (index < 0).
+
+  __ bind(&done);
+  __ movq(rax, result_operand);
+
+  __ bind(&return_result);
+  // Drop temp values from the stack, and restore context register.
+  __ addq(rsp, Immediate(3 * kPointerSize));
+  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+  context()->Plug(rax);
 }
 
 
@@ -3230,7 +3536,8 @@
     // Call the JS runtime function using a call IC.
     __ Move(rcx, expr->name());
     InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-    Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
+    Handle<Code> ic =
+        ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop);
     EmitCallIC(ic, RelocInfo::CODE_TARGET);
     // Restore context register.
     __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
@@ -3542,9 +3849,9 @@
     case NAMED_PROPERTY: {
       __ Move(rcx, prop->key()->AsLiteral()->handle());
       __ pop(rdx);
-      Handle<Code> ic(Builtins::builtin(
-          is_strict() ? Builtins::StoreIC_Initialize_Strict
-                      : Builtins::StoreIC_Initialize));
+      Handle<Code> ic = is_strict_mode()
+          ? isolate()->builtins()->StoreIC_Initialize_Strict()
+          : isolate()->builtins()->StoreIC_Initialize();
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -3559,9 +3866,9 @@
     case KEYED_PROPERTY: {
       __ pop(rcx);
       __ pop(rdx);
-      Handle<Code> ic(Builtins::builtin(
-          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
-                      : Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic = is_strict_mode()
+          ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+          : isolate()->builtins()->KeyedStoreIC_Initialize();
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -3586,7 +3893,7 @@
     Comment cmnt(masm_, "Global variable");
     __ Move(rcx, proxy->name());
     __ movq(rax, GlobalObjectOperand());
-    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
     // Use a regular load, not a contextual load, to avoid a reference
     // error.
     EmitCallIC(ic, RelocInfo::CODE_TARGET);
@@ -3639,12 +3946,12 @@
   }
   PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
 
-  if (check->Equals(Heap::number_symbol())) {
+  if (check->Equals(isolate()->heap()->number_symbol())) {
     __ JumpIfSmi(rax, if_true);
     __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
     __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
     Split(equal, if_true, if_false, fall_through);
-  } else if (check->Equals(Heap::string_symbol())) {
+  } else if (check->Equals(isolate()->heap()->string_symbol())) {
     __ JumpIfSmi(rax, if_false);
     // Check for undetectable objects => false.
     __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
@@ -3652,12 +3959,12 @@
     __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
              Immediate(1 << Map::kIsUndetectable));
     Split(zero, if_true, if_false, fall_through);
-  } else if (check->Equals(Heap::boolean_symbol())) {
+  } else if (check->Equals(isolate()->heap()->boolean_symbol())) {
     __ CompareRoot(rax, Heap::kTrueValueRootIndex);
     __ j(equal, if_true);
     __ CompareRoot(rax, Heap::kFalseValueRootIndex);
     Split(equal, if_true, if_false, fall_through);
-  } else if (check->Equals(Heap::undefined_symbol())) {
+  } else if (check->Equals(isolate()->heap()->undefined_symbol())) {
     __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
     __ j(equal, if_true);
     __ JumpIfSmi(rax, if_false);
@@ -3666,11 +3973,11 @@
     __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
              Immediate(1 << Map::kIsUndetectable));
     Split(not_zero, if_true, if_false, fall_through);
-  } else if (check->Equals(Heap::function_symbol())) {
+  } else if (check->Equals(isolate()->heap()->function_symbol())) {
     __ JumpIfSmi(rax, if_false);
     __ CmpObjectType(rax, FIRST_FUNCTION_CLASS_TYPE, rdx);
     Split(above_equal, if_true, if_false, fall_through);
-  } else if (check->Equals(Heap::object_symbol())) {
+  } else if (check->Equals(isolate()->heap()->object_symbol())) {
     __ JumpIfSmi(rax, if_false);
     __ CompareRoot(rax, Heap::kNullValueRootIndex);
     __ j(equal, if_true);
@@ -3850,18 +4157,19 @@
 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) {
   ASSERT(mode == RelocInfo::CODE_TARGET ||
          mode == RelocInfo::CODE_TARGET_CONTEXT);
+  Counters* counters = isolate()->counters();
   switch (ic->kind()) {
     case Code::LOAD_IC:
-      __ IncrementCounter(&Counters::named_load_full, 1);
+      __ IncrementCounter(counters->named_load_full(), 1);
       break;
     case Code::KEYED_LOAD_IC:
-      __ IncrementCounter(&Counters::keyed_load_full, 1);
+      __ IncrementCounter(counters->keyed_load_full(), 1);
       break;
     case Code::STORE_IC:
-      __ IncrementCounter(&Counters::named_store_full, 1);
+      __ IncrementCounter(counters->named_store_full(), 1);
       break;
     case Code::KEYED_STORE_IC:
-      __ IncrementCounter(&Counters::keyed_store_full, 1);
+      __ IncrementCounter(counters->keyed_store_full(), 1);
     default:
       break;
   }
@@ -3893,18 +4201,19 @@
 
 
 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) {
+  Counters* counters = isolate()->counters();
   switch (ic->kind()) {
     case Code::LOAD_IC:
-      __ IncrementCounter(&Counters::named_load_full, 1);
+      __ IncrementCounter(counters->named_load_full(), 1);
       break;
     case Code::KEYED_LOAD_IC:
-      __ IncrementCounter(&Counters::keyed_load_full, 1);
+      __ IncrementCounter(counters->keyed_load_full(), 1);
       break;
     case Code::STORE_IC:
-      __ IncrementCounter(&Counters::named_store_full, 1);
+      __ IncrementCounter(counters->named_store_full(), 1);
       break;
     case Code::KEYED_STORE_IC:
-      __ IncrementCounter(&Counters::keyed_store_full, 1);
+      __ IncrementCounter(counters->keyed_store_full(), 1);
     default:
       break;
   }
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index b3243cf..9180465 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -554,7 +554,7 @@
   //  -- rsp[0] : return address
   // -----------------------------------
   Label slow, check_string, index_smi, index_string, property_array_property;
-  Label check_pixel_array, probe_dictionary, check_number_dictionary;
+  Label probe_dictionary, check_number_dictionary;
 
   // Check that the key is a smi.
   __ JumpIfNotSmi(rax, &check_string);
@@ -569,7 +569,7 @@
   // now in rcx.
   __ testb(FieldOperand(rcx, Map::kBitField2Offset),
            Immediate(1 << Map::kHasFastElements));
-  __ j(zero, &check_pixel_array);
+  __ j(zero, &check_number_dictionary);
 
   GenerateFastArrayLoad(masm,
                         rdx,
@@ -579,21 +579,14 @@
                         rax,
                         NULL,
                         &slow);
-  __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_generic_smi(), 1);
   __ ret(0);
 
-  __ bind(&check_pixel_array);
-  GenerateFastPixelArrayLoad(masm,
-                             rdx,
-                             rax,
-                             rcx,
-                             rbx,
-                             rax,
-                             &check_number_dictionary,
-                             NULL,
-                             &slow);
-
   __ bind(&check_number_dictionary);
+  __ SmiToInteger32(rbx, rax);
+  __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
+
   // Check whether the elements is a number dictionary.
   // rdx: receiver
   // rax: key
@@ -609,7 +602,7 @@
   // Slow case: Jump to runtime.
   // rdx: receiver
   // rax: key
-  __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
+  __ IncrementCounter(counters->keyed_load_generic_slow(), 1);
   GenerateRuntimeGetProperty(masm);
 
   __ bind(&check_string);
@@ -638,10 +631,10 @@
   // Load the key (consisting of map and symbol) from the cache and
   // check for match.
   ExternalReference cache_keys
-      = ExternalReference::keyed_lookup_cache_keys();
+      = ExternalReference::keyed_lookup_cache_keys(masm->isolate());
   __ movq(rdi, rcx);
   __ shl(rdi, Immediate(kPointerSizeLog2 + 1));
-  __ movq(kScratchRegister, cache_keys);
+  __ LoadAddress(kScratchRegister, cache_keys);
   __ cmpq(rbx, Operand(kScratchRegister, rdi, times_1, 0));
   __ j(not_equal, &slow);
   __ cmpq(rax, Operand(kScratchRegister, rdi, times_1, kPointerSize));
@@ -649,8 +642,8 @@
 
   // Get field offset, which is a 32-bit integer.
   ExternalReference cache_field_offsets
-      = ExternalReference::keyed_lookup_cache_field_offsets();
-  __ movq(kScratchRegister, cache_field_offsets);
+      = ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
+  __ LoadAddress(kScratchRegister, cache_field_offsets);
   __ movl(rdi, Operand(kScratchRegister, rcx, times_4, 0));
   __ movzxbq(rcx, FieldOperand(rbx, Map::kInObjectPropertiesOffset));
   __ subq(rdi, rcx);
@@ -660,7 +653,7 @@
   __ movzxbq(rcx, FieldOperand(rbx, Map::kInstanceSizeOffset));
   __ addq(rcx, rdi);
   __ movq(rax, FieldOperand(rdx, rcx, times_pointer_size, 0));
-  __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1);
+  __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
   __ ret(0);
 
   // Load property array property.
@@ -668,7 +661,7 @@
   __ movq(rax, FieldOperand(rdx, JSObject::kPropertiesOffset));
   __ movq(rax, FieldOperand(rax, rdi, times_pointer_size,
                             FixedArray::kHeaderSize));
-  __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1);
+  __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
   __ ret(0);
 
   // Do a quick inline probe of the receiver's dictionary, if it
@@ -683,7 +676,7 @@
   GenerateGlobalInstanceTypeCheck(masm, rcx, &slow);
 
   GenerateDictionaryLoad(masm, &slow, rbx, rax, rcx, rdi, rax);
-  __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
+  __ IncrementCounter(counters->keyed_load_generic_symbol(), 1);
   __ ret(0);
 
   __ bind(&index_string);
@@ -758,8 +751,11 @@
   __ push(rcx);  // return address
 
   // Perform tail call to the entry.
-  __ TailCallExternalReference(ExternalReference(
-        IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1);
+  __ TailCallExternalReference(
+      ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor),
+                        masm->isolate()),
+      2,
+      1);
 
   __ bind(&slow);
   GenerateMiss(masm);
@@ -774,7 +770,7 @@
   //  -- rdx     : receiver
   //  -- rsp[0]  : return address
   // -----------------------------------
-  Label slow, slow_with_tagged_index, fast, array, extra, check_pixel_array;
+  Label slow, slow_with_tagged_index, fast, array, extra;
 
   // Check that the object isn't a smi.
   __ JumpIfSmi(rdx, &slow_with_tagged_index);
@@ -803,7 +799,7 @@
   // Check that the object is in fast mode and writable.
   __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
                  Heap::kFixedArrayMapRootIndex);
-  __ j(not_equal, &check_pixel_array);
+  __ j(not_equal, &slow);
   __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx);
   // rax: value
   // rbx: FixedArray
@@ -817,25 +813,6 @@
   GenerateRuntimeSetProperty(masm, strict_mode);
   // Never returns to here.
 
-  // Check whether the elements is a pixel array.
-  // rax: value
-  // rdx: receiver
-  // rbx: receiver's elements array
-  // rcx: index, zero-extended.
-  __ bind(&check_pixel_array);
-  GenerateFastPixelArrayStore(masm,
-                              rdx,
-                              rcx,
-                              rax,
-                              rbx,
-                              rdi,
-                              false,
-                              true,
-                              NULL,
-                              &slow,
-                              &slow,
-                              &slow);
-
   // 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].
@@ -907,7 +884,8 @@
                                          Code::kNoExtraICState,
                                          NORMAL,
                                          argc);
-  StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, rax);
+  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx,
+                                                  rax);
 
   // If the stub cache probing failed, the receiver might be a value.
   // For value objects, we use the map of the prototype objects for
@@ -943,7 +921,8 @@
 
   // Probe the stub cache for the value object.
   __ bind(&probe);
-  StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg);
+  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx,
+                                                  no_reg);
 
   __ bind(&miss);
 }
@@ -1012,10 +991,11 @@
   // rsp[(argc + 1) * 8]      : argument 0 = receiver
   // -----------------------------------
 
+  Counters* counters = masm->isolate()->counters();
   if (id == IC::kCallIC_Miss) {
-    __ IncrementCounter(&Counters::call_miss, 1);
+    __ IncrementCounter(counters->call_miss(), 1);
   } else {
-    __ IncrementCounter(&Counters::keyed_call_miss, 1);
+    __ IncrementCounter(counters->keyed_call_miss(), 1);
   }
 
   // Get the receiver of the function from the stack; 1 ~ return address.
@@ -1031,7 +1011,7 @@
   // Call the entry.
   CEntryStub stub(1);
   __ movq(rax, Immediate(2));
-  __ movq(rbx, ExternalReference(IC_Utility(id)));
+  __ LoadAddress(rbx, ExternalReference(IC_Utility(id), masm->isolate()));
   __ CallStub(&stub);
 
   // Move result to rdi and exit the internal frame.
@@ -1141,7 +1121,8 @@
 
   GenerateFastArrayLoad(
       masm, rdx, rcx, rax, rbx, rdi, &check_number_dictionary, &slow_load);
-  __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->keyed_call_generic_smi_fast(), 1);
 
   __ bind(&do_call);
   // receiver in rdx is not used after this point.
@@ -1159,13 +1140,13 @@
   __ SmiToInteger32(rbx, rcx);
   // ebx: untagged index
   GenerateNumberDictionaryLoad(masm, &slow_load, rax, rcx, rbx, r9, rdi, rdi);
-  __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1);
+  __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1);
   __ jmp(&do_call);
 
   __ bind(&slow_load);
   // This branch is taken when calling KeyedCallIC_Miss is neither required
   // nor beneficial.
-  __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1);
+  __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1);
   __ EnterInternalFrame();
   __ push(rcx);  // save the key
   __ push(rdx);  // pass the receiver
@@ -1192,11 +1173,11 @@
   __ j(not_equal, &lookup_monomorphic_cache);
 
   GenerateDictionaryLoad(masm, &slow_load, rbx, rcx, rax, rdi, rdi);
-  __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1);
+  __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1);
   __ jmp(&do_call);
 
   __ bind(&lookup_monomorphic_cache);
-  __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1);
+  __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1);
   GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC);
   // Fall through on miss.
 
@@ -1207,7 +1188,7 @@
   // - the value loaded is not a function,
   // - there is hope that the runtime will create a monomorphic call stub
   //   that will get fetched next time.
-  __ IncrementCounter(&Counters::keyed_call_generic_slow, 1);
+  __ IncrementCounter(counters->keyed_call_generic_slow(), 1);
   GenerateMiss(masm, argc);
 
   __ bind(&index_string);
@@ -1265,7 +1246,8 @@
   Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
                                          NOT_IN_LOOP,
                                          MONOMORPHIC);
-  StubCache::GenerateProbe(masm, flags, rax, rcx, rbx, rdx);
+  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rax, rcx, rbx,
+                                                  rdx);
 
   // Cache miss: Jump to runtime.
   StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
@@ -1300,7 +1282,8 @@
   //  -- rsp[0] : return address
   // -----------------------------------
 
-  __ IncrementCounter(&Counters::load_miss, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->load_miss(), 1);
 
   __ pop(rbx);
   __ push(rax);  // receiver
@@ -1308,7 +1291,8 @@
   __ push(rbx);  // return address
 
   // Perform tail call to the entry.
-  ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss));
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate());
   __ TailCallExternalReference(ref, 2, 1);
 }
 
@@ -1383,7 +1367,7 @@
   // (-1) or we should be clearing the inlined version.
   ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt - 1 ||
          *reinterpret_cast<int*>(offset_address) == -1 ||
-         (offset == 0 && map == Heap::null_value()));
+         (offset == 0 && map == HEAP->null_value()));
   *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag;
 
   // Patch the offset in the write-barrier code. The offset is the
@@ -1393,7 +1377,7 @@
   // (-1) or we should be clearing the inlined version.
   ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt ||
          *reinterpret_cast<int*>(offset_address) == -1 ||
-         (offset == 0 && map == Heap::null_value()));
+         (offset == 0 && map == HEAP->null_value()));
   *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag;
 
   return true;
@@ -1444,7 +1428,8 @@
   //  -- rsp[0]  : return address
   // -----------------------------------
 
-  __ IncrementCounter(&Counters::keyed_load_miss, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_miss(), 1);
 
   __ pop(rbx);
   __ push(rdx);  // receiver
@@ -1452,7 +1437,8 @@
   __ push(rbx);  // return address
 
   // Perform tail call to the entry.
-  ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss));
+  ExternalReference ref
+      = ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate());
   __ TailCallExternalReference(ref, 2, 1);
 }
 
@@ -1488,7 +1474,8 @@
                                          NOT_IN_LOOP,
                                          MONOMORPHIC,
                                          strict_mode);
-  StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg);
+  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx,
+                                                  no_reg);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
@@ -1510,7 +1497,8 @@
   __ push(rbx);  // return address
 
   // Perform tail call to the entry.
-  ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss));
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate());
   __ TailCallExternalReference(ref, 3, 1);
 }
 
@@ -1563,7 +1551,8 @@
   __ push(value);
   __ push(scratch);  // return address
 
-  ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength));
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate());
   __ TailCallExternalReference(ref, 2, 1);
 
   __ bind(&miss);
@@ -1585,11 +1574,12 @@
   GenerateStringDictionaryReceiverCheck(masm, rdx, rbx, rdi, &miss);
 
   GenerateDictionaryStore(masm, &miss, rbx, rcx, rax, r8, r9);
-  __ IncrementCounter(&Counters::store_normal_hit, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->store_normal_hit(), 1);
   __ ret(0);
 
   __ bind(&miss);
-  __ IncrementCounter(&Counters::store_normal_miss, 1);
+  __ IncrementCounter(counters->store_normal_miss(), 1);
   GenerateMiss(masm);
 }
 
@@ -1652,7 +1642,8 @@
   __ push(rbx);  // return address
 
   // Do tail-call to runtime routine.
-  ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss));
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate());
   __ TailCallExternalReference(ref, 3, 1);
 }
 
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index bd968b9..86a7e83 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -39,38 +39,31 @@
 
 // When invoking builtins, we need to record the safepoint in the middle of
 // the invoke instruction sequence generated by the macro assembler.
-class SafepointGenerator : public PostCallGenerator {
+class SafepointGenerator : public CallWrapper {
  public:
   SafepointGenerator(LCodeGen* codegen,
                      LPointerMap* pointers,
-                     int deoptimization_index,
-                     bool ensure_reloc_space = false)
+                     int deoptimization_index)
       : codegen_(codegen),
         pointers_(pointers),
-        deoptimization_index_(deoptimization_index),
-        ensure_reloc_space_(ensure_reloc_space),
-        previous_safepoint_position_(-kMinSafepointSize) { }
+        deoptimization_index_(deoptimization_index) { }
   virtual ~SafepointGenerator() { }
 
-  virtual void Generate() {
+  virtual void BeforeCall(int call_size) {
+    ASSERT(call_size >= 0);
     // Ensure that we have enough space after the previous safepoint position
-    // for the generated code there.
-    int position = codegen_->masm()->pc_offset();
-    ASSERT(position > previous_safepoint_position_);
-    if (position < previous_safepoint_position_ + kMinSafepointSize) {
-      int padding_size =
-          previous_safepoint_position_ + kMinSafepointSize - position;
+    // for the jump generated there.
+    int call_end = codegen_->masm()->pc_offset() + call_size;
+    int prev_jump_end = codegen_->LastSafepointEnd() + kMinSafepointSize;
+    if (call_end < prev_jump_end) {
+      int padding_size = prev_jump_end - call_end;
       STATIC_ASSERT(kMinSafepointSize <= 9);  // One multibyte nop is enough.
       codegen_->masm()->nop(padding_size);
-      position += padding_size;
     }
-    // Ensure that we have enough space in the reloc info to patch
-    // this with calls when doing deoptimization.
-    if (ensure_reloc_space_) {
-      codegen_->masm()->RecordComment(RelocInfo::kFillerCommentString, true);
-    }
+  }
+
+  virtual void AfterCall() {
     codegen_->RecordSafepoint(pointers_, deoptimization_index_);
-    previous_safepoint_position_ = position;
   }
 
  private:
@@ -79,8 +72,6 @@
   LCodeGen* codegen_;
   LPointerMap* pointers_;
   int deoptimization_index_;
-  bool ensure_reloc_space_;
-  int previous_safepoint_position_;
 };
 
 
@@ -103,6 +94,7 @@
   code->set_stack_slots(StackSlotCount());
   code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
   PopulateDeoptimizationData(code);
+  Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
 }
 
 
@@ -259,9 +251,8 @@
 
 bool LCodeGen::GenerateJumpTable() {
   for (int i = 0; i < jump_table_.length(); i++) {
-    JumpTableEntry* info = jump_table_[i];
-    __ bind(&(info->label_));
-    __ Jump(info->address_, RelocInfo::RUNTIME_ENTRY);
+    __ bind(&jump_table_[i].label);
+    __ Jump(jump_table_[i].address, RelocInfo::RUNTIME_ENTRY);
   }
   return !is_aborted();
 }
@@ -467,7 +458,7 @@
 }
 
 
-void LCodeGen::CallRuntime(Runtime::Function* function,
+void LCodeGen::CallRuntime(const Runtime::Function* function,
                            int num_arguments,
                            LInstruction* instr) {
   ASSERT(instr != NULL);
@@ -539,17 +530,13 @@
   if (cc == no_condition) {
     __ Jump(entry, RelocInfo::RUNTIME_ENTRY);
   } else {
-    JumpTableEntry* jump_info = NULL;
     // We often have several deopts to the same entry, reuse the last
     // jump entry if this is the case.
-    if (jump_table_.length() > 0 &&
-        jump_table_[jump_table_.length() - 1]->address_ == entry) {
-      jump_info = jump_table_[jump_table_.length() - 1];
-    } else {
-      jump_info = new JumpTableEntry(entry);
-      jump_table_.Add(jump_info);
+    if (jump_table_.is_empty() ||
+        jump_table_.last().address != entry) {
+      jump_table_.Add(entry);
     }
-    __ j(cc, &jump_info->label_);
+    __ j(cc, &jump_table_.last().label);
   }
 }
 
@@ -559,14 +546,14 @@
   if (length == 0) return;
   ASSERT(FLAG_deopt);
   Handle<DeoptimizationInputData> data =
-      Factory::NewDeoptimizationInputData(length, TENURED);
+      factory()->NewDeoptimizationInputData(length, TENURED);
 
   Handle<ByteArray> translations = translations_.CreateByteArray();
   data->SetTranslationByteArray(*translations);
   data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
 
   Handle<FixedArray> literals =
-      Factory::NewFixedArray(deoptimization_literals_.length(), TENURED);
+      factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
   for (int i = 0; i < deoptimization_literals_.length(); i++) {
     literals->set(i, *deoptimization_literals_[i]);
   }
@@ -720,16 +707,6 @@
       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
       break;
     }
-    case CodeStub::StringCharAt: {
-      StringCharAtStub stub;
-      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
-      break;
-    }
-    case CodeStub::MathPow: {
-      MathPowStub stub;
-      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
-      break;
-    }
     case CodeStub::NumberToString: {
       NumberToStringStub stub;
       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
@@ -763,41 +740,65 @@
 
 
 void LCodeGen::DoModI(LModI* instr) {
-  LOperand* right = instr->InputAt(1);
-  ASSERT(ToRegister(instr->result()).is(rdx));
-  ASSERT(ToRegister(instr->InputAt(0)).is(rax));
-  ASSERT(!ToRegister(instr->InputAt(1)).is(rax));
-  ASSERT(!ToRegister(instr->InputAt(1)).is(rdx));
+  if (instr->hydrogen()->HasPowerOf2Divisor()) {
+    Register dividend = ToRegister(instr->InputAt(0));
 
-  Register right_reg = ToRegister(right);
+    int32_t divisor =
+        HConstant::cast(instr->hydrogen()->right())->Integer32Value();
 
-  // Check for x % 0.
-  if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
-    __ testl(right_reg, right_reg);
-    DeoptimizeIf(zero, instr->environment());
-  }
+    if (divisor < 0) divisor = -divisor;
 
-  // Sign extend eax to edx. (We are using only the low 32 bits of the values.)
-  __ cdq();
-
-  // Check for (0 % -x) that will produce negative zero.
-  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
-    NearLabel positive_left;
-    NearLabel done;
-    __ testl(rax, rax);
-    __ j(not_sign, &positive_left);
-    __ idivl(right_reg);
-
-    // Test the remainder for 0, because then the result would be -0.
-    __ testl(rdx, rdx);
-    __ j(not_zero, &done);
-
-    DeoptimizeIf(no_condition, instr->environment());
-    __ bind(&positive_left);
-    __ idivl(right_reg);
+    NearLabel positive_dividend, done;
+    __ testl(dividend, dividend);
+    __ j(not_sign, &positive_dividend);
+    __ negl(dividend);
+    __ andl(dividend, Immediate(divisor - 1));
+    __ negl(dividend);
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      __ j(not_zero, &done);
+      DeoptimizeIf(no_condition, instr->environment());
+    }
+    __ bind(&positive_dividend);
+    __ andl(dividend, Immediate(divisor - 1));
     __ bind(&done);
   } else {
-    __ idivl(right_reg);
+    LOperand* right = instr->InputAt(1);
+    Register right_reg = ToRegister(right);
+
+    ASSERT(ToRegister(instr->result()).is(rdx));
+    ASSERT(ToRegister(instr->InputAt(0)).is(rax));
+    ASSERT(!right_reg.is(rax));
+    ASSERT(!right_reg.is(rdx));
+
+    // Check for x % 0.
+    if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
+      __ testl(right_reg, right_reg);
+      DeoptimizeIf(zero, instr->environment());
+    }
+
+    // Sign extend eax to edx.
+    // (We are using only the low 32 bits of the values.)
+    __ cdq();
+
+    // Check for (0 % -x) that will produce negative zero.
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      NearLabel positive_left;
+      NearLabel done;
+      __ testl(rax, rax);
+      __ j(not_sign, &positive_left);
+      __ idivl(right_reg);
+
+      // Test the remainder for 0, because then the result would be -0.
+      __ testl(rdx, rdx);
+      __ j(not_zero, &done);
+
+      DeoptimizeIf(no_condition, instr->environment());
+      __ bind(&positive_left);
+      __ idivl(right_reg);
+      __ bind(&done);
+    } else {
+      __ idivl(right_reg);
+    }
   }
 }
 
@@ -856,16 +857,56 @@
     __ movl(kScratchRegister, left);
   }
 
+  bool can_overflow =
+      instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
   if (right->IsConstantOperand()) {
     int right_value = ToInteger32(LConstantOperand::cast(right));
-    __ imull(left, left, Immediate(right_value));
+    if (right_value == -1) {
+      __ negl(left);
+    } else if (right_value == 0) {
+      __ xorl(left, left);
+    } else if (right_value == 2) {
+      __ addl(left, left);
+    } else if (!can_overflow) {
+      // If the multiplication is known to not overflow, we
+      // can use operations that don't set the overflow flag
+      // correctly.
+      switch (right_value) {
+        case 1:
+          // Do nothing.
+          break;
+        case 3:
+          __ leal(left, Operand(left, left, times_2, 0));
+          break;
+        case 4:
+          __ shll(left, Immediate(2));
+          break;
+        case 5:
+          __ leal(left, Operand(left, left, times_4, 0));
+          break;
+        case 8:
+          __ shll(left, Immediate(3));
+          break;
+        case 9:
+          __ leal(left, Operand(left, left, times_8, 0));
+          break;
+        case 16:
+          __ shll(left, Immediate(4));
+          break;
+        default:
+          __ imull(left, left, Immediate(right_value));
+          break;
+      }
+    } else {
+      __ imull(left, left, Immediate(right_value));
+    }
   } else if (right->IsStackSlot()) {
     __ imull(left, ToOperand(right));
   } else {
     __ imull(left, ToRegister(right));
   }
 
-  if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+  if (can_overflow) {
     DeoptimizeIf(overflow, instr->environment());
   }
 
@@ -1067,10 +1108,10 @@
 }
 
 
-void LCodeGen::DoPixelArrayLength(LPixelArrayLength* instr) {
+void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) {
   Register result = ToRegister(instr->result());
   Register array = ToRegister(instr->InputAt(0));
-  __ movq(result, FieldOperand(array, PixelArray::kLengthOffset));
+  __ movl(result, FieldOperand(array, ExternalPixelArray::kLengthOffset));
 }
 
 
@@ -1152,7 +1193,8 @@
       __ PrepareCallCFunction(2);
       __ movsd(xmm0, left);
       ASSERT(right.is(xmm1));
-      __ CallCFunction(ExternalReference::double_fp_operation(Token::MOD), 2);
+      __ CallCFunction(
+          ExternalReference::double_fp_operation(Token::MOD, isolate()), 2);
       __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
       __ movsd(result, xmm0);
       break;
@@ -1221,7 +1263,7 @@
     Register reg = ToRegister(instr->InputAt(0));
     HType type = instr->hydrogen()->type();
     if (type.IsBoolean()) {
-      __ Cmp(reg, Factory::true_value());
+      __ CompareRoot(reg, Heap::kTrueValueRootIndex);
       EmitBranch(true_block, false_block, equal);
     } else if (type.IsSmi()) {
       __ SmiCompare(reg, Smi::FromInt(0));
@@ -1236,7 +1278,7 @@
       __ j(equal, true_label);
       __ CompareRoot(reg, Heap::kFalseValueRootIndex);
       __ j(equal, false_label);
-      __ SmiCompare(reg, Smi::FromInt(0));
+      __ Cmp(reg, Smi::FromInt(0));
       __ j(equal, false_label);
       __ JumpIfSmi(reg, true_label);
 
@@ -1488,14 +1530,14 @@
 
   int true_block = chunk_->LookupDestination(instr->true_block_id());
 
-  __ Cmp(reg, Factory::null_value());
+  __ CompareRoot(reg, Heap::kNullValueRootIndex);
   if (instr->is_strict()) {
     EmitBranch(true_block, false_block, equal);
   } else {
     Label* true_label = chunk_->GetAssemblyLabel(true_block);
     Label* false_label = chunk_->GetAssemblyLabel(false_block);
     __ j(equal, true_label);
-    __ Cmp(reg, Factory::undefined_value());
+    __ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
     __ j(equal, true_label);
     __ JumpIfSmi(reg, false_label);
     // Check for undetectable objects by looking in the bit field in
@@ -1834,24 +1876,51 @@
                                   LInstanceOfKnownGlobal* instr)
         : LDeferredCode(codegen), instr_(instr) { }
     virtual void Generate() {
-      codegen()->DoDeferredLInstanceOfKnownGlobal(instr_);
+      codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_);
     }
 
+    Label* map_check() { return &map_check_; }
+
    private:
     LInstanceOfKnownGlobal* instr_;
+    Label map_check_;
   };
 
 
   DeferredInstanceOfKnownGlobal* deferred;
   deferred = new DeferredInstanceOfKnownGlobal(this, instr);
 
-  Label false_result;
+  Label done, false_result;
   Register object = ToRegister(instr->InputAt(0));
 
   // A Smi is not an instance of anything.
   __ JumpIfSmi(object, &false_result);
 
-  // Null is not an instance of anything.
+  // This is the inlined call site instanceof cache. The two occurences of the
+  // hole value will be patched to the last map/result pair generated by the
+  // instanceof stub.
+  NearLabel cache_miss;
+  // Use a temp register to avoid memory operands with variable lengths.
+  Register map = ToRegister(instr->TempAt(0));
+  __ movq(map, FieldOperand(object, HeapObject::kMapOffset));
+  __ bind(deferred->map_check());  // Label for calculating code patching.
+  __ movq(kScratchRegister, factory()->the_hole_value(),
+          RelocInfo::EMBEDDED_OBJECT);
+  __ cmpq(map, kScratchRegister);  // Patched to cached map.
+  __ j(not_equal, &cache_miss);
+  // Patched to load either true or false.
+  __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex);
+#ifdef DEBUG
+  // Check that the code size between patch label and patch sites is invariant.
+  Label end_of_patched_code;
+  __ bind(&end_of_patched_code);
+  ASSERT(true);
+#endif
+  __ jmp(&done);
+
+  // The inlined call site cache did not match. Check for null and string
+  // before calling the deferred code.
+  __ bind(&cache_miss);  // Null is not an instance of anything.
   __ CompareRoot(object, Heap::kNullValueRootIndex);
   __ j(equal, &false_result);
 
@@ -1862,17 +1931,26 @@
   __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
 
   __ bind(deferred->exit());
+  __ bind(&done);
 }
 
 
-void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
+void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
+                                                Label* map_check) {
   __ PushSafepointRegisters();
-
-  InstanceofStub stub(InstanceofStub::kNoFlags);
+  InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>(
+      InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck);
+  InstanceofStub stub(flags);
 
   __ push(ToRegister(instr->InputAt(0)));
   __ Push(instr->function());
-  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+  Register temp = ToRegister(instr->TempAt(0));
+  ASSERT(temp.is(rdi));
+  static const int kAdditionalDelta = 16;
+  int delta =
+      masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
+  __ movq(temp, Immediate(delta));
+  __ push(temp);
   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   __ movq(kScratchRegister, rax);
   __ PopSafepointRegisters();
@@ -2011,12 +2089,76 @@
 }
 
 
+void LCodeGen::EmitLoadField(Register result,
+                             Register object,
+                             Handle<Map> type,
+                             Handle<String> name) {
+  LookupResult lookup;
+  type->LookupInDescriptors(NULL, *name, &lookup);
+  ASSERT(lookup.IsProperty() && lookup.type() == FIELD);
+  int index = lookup.GetLocalFieldIndexFromMap(*type);
+  int offset = index * kPointerSize;
+  if (index < 0) {
+    // Negative property indices are in-object properties, indexed
+    // from the end of the fixed part of the object.
+    __ movq(result, FieldOperand(object, offset + type->instance_size()));
+  } else {
+    // Non-negative property indices are in the properties array.
+    __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset));
+    __ movq(result, FieldOperand(result, offset + FixedArray::kHeaderSize));
+  }
+}
+
+
+void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
+  Register object = ToRegister(instr->object());
+  Register result = ToRegister(instr->result());
+
+  int map_count = instr->hydrogen()->types()->length();
+  Handle<String> name = instr->hydrogen()->name();
+
+  if (map_count == 0) {
+    ASSERT(instr->hydrogen()->need_generic());
+    __ Move(rcx, instr->hydrogen()->name());
+    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+    CallCode(ic, RelocInfo::CODE_TARGET, instr);
+  } else {
+    NearLabel done;
+    for (int i = 0; i < map_count - 1; ++i) {
+      Handle<Map> map = instr->hydrogen()->types()->at(i);
+      NearLabel next;
+      __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map);
+      __ j(not_equal, &next);
+      EmitLoadField(result, object, map, name);
+      __ jmp(&done);
+      __ bind(&next);
+    }
+    Handle<Map> map = instr->hydrogen()->types()->last();
+    __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map);
+    if (instr->hydrogen()->need_generic()) {
+      NearLabel generic;
+      __ j(not_equal, &generic);
+      EmitLoadField(result, object, map, name);
+      __ jmp(&done);
+      __ bind(&generic);
+      __ Move(rcx, instr->hydrogen()->name());
+      Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+      CallCode(ic, RelocInfo::CODE_TARGET, instr);
+    } else {
+      DeoptimizeIf(not_equal, instr->environment());
+      EmitLoadField(result, object, map, name);
+    }
+    __ bind(&done);
+  }
+}
+
+
 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
   ASSERT(ToRegister(instr->object()).is(rax));
   ASSERT(ToRegister(instr->result()).is(rax));
 
   __ Move(rcx, instr->name());
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2068,25 +2210,31 @@
   __ movq(result, FieldOperand(input, JSObject::kElementsOffset));
   if (FLAG_debug_code) {
     NearLabel done;
-    __ Cmp(FieldOperand(result, HeapObject::kMapOffset),
-           Factory::fixed_array_map());
+    __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset),
+                   Heap::kFixedArrayMapRootIndex);
     __ j(equal, &done);
-    __ Cmp(FieldOperand(result, HeapObject::kMapOffset),
-           Factory::pixel_array_map());
+    __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset),
+                   Heap::kFixedCOWArrayMapRootIndex);
     __ j(equal, &done);
-    __ Cmp(FieldOperand(result, HeapObject::kMapOffset),
-           Factory::fixed_cow_array_map());
-    __ Check(equal, "Check for fast elements failed.");
+    Register temp((result.is(rax)) ? rbx : rax);
+    __ push(temp);
+    __ movq(temp, FieldOperand(result, HeapObject::kMapOffset));
+    __ movzxbq(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
+    __ subq(temp, Immediate(FIRST_EXTERNAL_ARRAY_TYPE));
+    __ cmpq(temp, Immediate(kExternalArrayTypeCount));
+    __ pop(temp);
+    __ Check(below, "Check for fast elements failed.");
     __ bind(&done);
   }
 }
 
 
-void LCodeGen::DoLoadPixelArrayExternalPointer(
-    LLoadPixelArrayExternalPointer* instr) {
+void LCodeGen::DoLoadExternalArrayPointer(
+    LLoadExternalArrayPointer* instr) {
   Register result = ToRegister(instr->result());
   Register input = ToRegister(instr->InputAt(0));
-  __ movq(result, FieldOperand(input, PixelArray::kExternalPointerOffset));
+  __ movq(result, FieldOperand(input,
+                               ExternalPixelArray::kExternalPointerOffset));
 }
 
 
@@ -2121,19 +2269,52 @@
                                FixedArray::kHeaderSize));
 
   // Check for the hole value.
-  __ Cmp(result, Factory::the_hole_value());
+  __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
   DeoptimizeIf(equal, instr->environment());
 }
 
 
-void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) {
-  Register external_elements = ToRegister(instr->external_pointer());
+void LCodeGen::DoLoadKeyedSpecializedArrayElement(
+    LLoadKeyedSpecializedArrayElement* instr) {
+  Register external_pointer = ToRegister(instr->external_pointer());
   Register key = ToRegister(instr->key());
-  Register result = ToRegister(instr->result());
-  ASSERT(result.is(external_elements));
-
-  // Load the result.
-  __ movzxbq(result, Operand(external_elements, key, times_1, 0));
+  ExternalArrayType array_type = instr->array_type();
+  if (array_type == kExternalFloatArray) {
+    XMMRegister result(ToDoubleRegister(instr->result()));
+    __ movss(result, Operand(external_pointer, key, times_4, 0));
+    __ cvtss2sd(result, result);
+  } else {
+    Register result(ToRegister(instr->result()));
+    switch (array_type) {
+      case kExternalByteArray:
+        __ movsxbq(result, Operand(external_pointer, key, times_1, 0));
+        break;
+      case kExternalUnsignedByteArray:
+      case kExternalPixelArray:
+        __ movzxbq(result, Operand(external_pointer, key, times_1, 0));
+        break;
+      case kExternalShortArray:
+        __ movsxwq(result, Operand(external_pointer, key, times_2, 0));
+        break;
+      case kExternalUnsignedShortArray:
+        __ movzxwq(result, Operand(external_pointer, key, times_2, 0));
+        break;
+      case kExternalIntArray:
+        __ movsxlq(result, Operand(external_pointer, key, times_4, 0));
+        break;
+      case kExternalUnsignedIntArray:
+        __ movl(result, Operand(external_pointer, key, times_4, 0));
+        __ testl(result, result);
+        // TODO(danno): we could be more clever here, perhaps having a special
+        // version of the stub that detects if the overflow case actually
+        // happens, and generate code that returns a double rather than int.
+        DeoptimizeIf(negative, instr->environment());
+        break;
+      case kExternalFloatArray:
+        UNREACHABLE();
+        break;
+    }
+  }
 }
 
 
@@ -2141,7 +2322,7 @@
   ASSERT(ToRegister(instr->object()).is(rdx));
   ASSERT(ToRegister(instr->key()).is(rax));
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2152,8 +2333,8 @@
   // Check for arguments adapter frame.
   NearLabel done, adapted;
   __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
-  __ SmiCompare(Operand(result, StandardFrameConstants::kContextOffset),
-                Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+  __ Cmp(Operand(result, StandardFrameConstants::kContextOffset),
+         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
   __ j(equal, &adapted);
 
   // No arguments adaptor frame.
@@ -2256,8 +2437,7 @@
   RegisterEnvironmentForDeoptimization(env);
   SafepointGenerator safepoint_generator(this,
                                          pointers,
-                                         env->deoptimization_index(),
-                                         true);
+                                         env->deoptimization_index());
   v8::internal::ParameterCount actual(rax);
   __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
 }
@@ -2298,9 +2478,9 @@
 
 
 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
+  Register global = ToRegister(instr->global());
   Register result = ToRegister(instr->result());
-  __ movq(result, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
-  __ movq(result, FieldOperand(result, GlobalObject::kGlobalReceiverOffset));
+  __ movq(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset));
 }
 
 
@@ -2536,7 +2716,8 @@
     // Move arguments to correct registers
     __ movsd(xmm0, left_reg);
     ASSERT(ToDoubleRegister(right).is(xmm1));
-    __ CallCFunction(ExternalReference::power_double_double_function(), 2);
+    __ CallCFunction(
+        ExternalReference::power_double_double_function(isolate()), 2);
   } else if (exponent_type.IsInteger32()) {
     __ PrepareCallCFunction(2);
     // Move arguments to correct registers: xmm0 and edi (not rdi).
@@ -2547,7 +2728,8 @@
 #else
     ASSERT(ToRegister(right).is(rdi));
 #endif
-    __ CallCFunction(ExternalReference::power_double_int_function(), 2);
+    __ CallCFunction(
+        ExternalReference::power_double_int_function(isolate()), 2);
   } else {
     ASSERT(exponent_type.IsTagged());
     CpuFeatures::Scope scope(SSE2);
@@ -2569,10 +2751,13 @@
     // Move arguments to correct registers xmm0 and xmm1.
     __ movsd(xmm0, left_reg);
     // Right argument is already in xmm1.
-    __ CallCFunction(ExternalReference::power_double_double_function(), 2);
+    __ CallCFunction(
+        ExternalReference::power_double_double_function(isolate()), 2);
   }
   // Return value is in xmm0.
   __ movsd(result_reg, xmm0);
+  // Restore context register.
+  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
 }
 
 
@@ -2586,7 +2771,7 @@
 
 void LCodeGen::DoMathCos(LUnaryMathOperation* instr) {
   ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
-  TranscendentalCacheStub stub(TranscendentalCache::LOG,
+  TranscendentalCacheStub stub(TranscendentalCache::COS,
                                TranscendentalCacheStub::UNTAGGED);
   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
 }
@@ -2594,7 +2779,7 @@
 
 void LCodeGen::DoMathSin(LUnaryMathOperation* instr) {
   ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
-  TranscendentalCacheStub stub(TranscendentalCache::LOG,
+  TranscendentalCacheStub stub(TranscendentalCache::SIN,
                                TranscendentalCacheStub::UNTAGGED);
   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
 }
@@ -2638,7 +2823,8 @@
   ASSERT(ToRegister(instr->result()).is(rax));
 
   int arity = instr->arity();
-  Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arity, NOT_IN_LOOP);
+  Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(
+    arity, NOT_IN_LOOP);
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
   __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
 }
@@ -2648,7 +2834,8 @@
   ASSERT(ToRegister(instr->result()).is(rax));
 
   int arity = instr->arity();
-  Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP);
+  Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(
+      arity, NOT_IN_LOOP);
   __ Move(rcx, instr->name());
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
   __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
@@ -2669,7 +2856,8 @@
 void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
   ASSERT(ToRegister(instr->result()).is(rax));
   int arity = instr->arity();
-  Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP);
+  Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(
+      arity, NOT_IN_LOOP);
   __ Move(rcx, instr->name());
   CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
   __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
@@ -2687,7 +2875,7 @@
   ASSERT(ToRegister(instr->InputAt(0)).is(rdi));
   ASSERT(ToRegister(instr->result()).is(rax));
 
-  Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall));
+  Handle<Code> builtin = isolate()->builtins()->JSConstructCall();
   __ Set(rax, instr->arity());
   CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr);
 }
@@ -2733,28 +2921,53 @@
   ASSERT(ToRegister(instr->value()).is(rax));
 
   __ Move(rcx, instr->hydrogen()->name());
-  Handle<Code> ic(Builtins::builtin(
-      info_->is_strict() ? Builtins::StoreIC_Initialize_Strict
-                         : Builtins::StoreIC_Initialize));
+  Handle<Code> ic = info_->is_strict()
+      ? isolate()->builtins()->StoreIC_Initialize_Strict()
+      : isolate()->builtins()->StoreIC_Initialize();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
 
-void LCodeGen::DoStorePixelArrayElement(LStorePixelArrayElement* instr) {
+void LCodeGen::DoStoreKeyedSpecializedArrayElement(
+    LStoreKeyedSpecializedArrayElement* instr) {
   Register external_pointer = ToRegister(instr->external_pointer());
   Register key = ToRegister(instr->key());
-  Register value = ToRegister(instr->value());
-
-  {  // Clamp the value to [0..255].
-    NearLabel done;
-    __ testl(value, Immediate(0xFFFFFF00));
-    __ j(zero, &done);
-    __ setcc(negative, value);  // 1 if negative, 0 if positive.
-    __ decb(value);  // 0 if negative, 255 if positive.
-    __ bind(&done);
+  ExternalArrayType array_type = instr->array_type();
+  if (array_type == kExternalFloatArray) {
+    XMMRegister value(ToDoubleRegister(instr->value()));
+    __ cvtsd2ss(value, value);
+    __ movss(Operand(external_pointer, key, times_4, 0), value);
+  } else {
+    Register value(ToRegister(instr->value()));
+    switch (array_type) {
+      case kExternalPixelArray:
+        {  // Clamp the value to [0..255].
+          NearLabel done;
+          __ testl(value, Immediate(0xFFFFFF00));
+          __ j(zero, &done);
+          __ setcc(negative, value);  // 1 if negative, 0 if positive.
+          __ decb(value);  // 0 if negative, 255 if positive.
+          __ bind(&done);
+          __ movb(Operand(external_pointer, key, times_1, 0), value);
+        }
+        break;
+      case kExternalByteArray:
+      case kExternalUnsignedByteArray:
+        __ movb(Operand(external_pointer, key, times_1, 0), value);
+        break;
+      case kExternalShortArray:
+      case kExternalUnsignedShortArray:
+        __ movw(Operand(external_pointer, key, times_2, 0), value);
+        break;
+      case kExternalIntArray:
+      case kExternalUnsignedIntArray:
+        __ movl(Operand(external_pointer, key, times_4, 0), value);
+        break;
+      case kExternalFloatArray:
+        UNREACHABLE();
+        break;
+    }
   }
-
-  __ movb(Operand(external_pointer, key, times_1, 0), value);
 }
 
 
@@ -2804,9 +3017,9 @@
   ASSERT(ToRegister(instr->key()).is(rcx));
   ASSERT(ToRegister(instr->value()).is(rax));
 
-  Handle<Code> ic(Builtins::builtin(
-      info_->is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
-                         : Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic = info_->is_strict()
+      ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+      : isolate()->builtins()->KeyedStoreIC_Initialize();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2951,6 +3164,56 @@
 }
 
 
+void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
+  class DeferredStringCharFromCode: public LDeferredCode {
+   public:
+    DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); }
+   private:
+    LStringCharFromCode* instr_;
+  };
+
+  DeferredStringCharFromCode* deferred =
+      new DeferredStringCharFromCode(this, instr);
+
+  ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
+  Register char_code = ToRegister(instr->char_code());
+  Register result = ToRegister(instr->result());
+  ASSERT(!char_code.is(result));
+
+  __ cmpl(char_code, Immediate(String::kMaxAsciiCharCode));
+  __ j(above, deferred->entry());
+  __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
+  __ movq(result, FieldOperand(result,
+                               char_code, times_pointer_size,
+                               FixedArray::kHeaderSize));
+  __ CompareRoot(result, Heap::kUndefinedValueRootIndex);
+  __ j(equal, deferred->entry());
+  __ bind(deferred->exit());
+}
+
+
+void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
+  Register char_code = ToRegister(instr->char_code());
+  Register result = ToRegister(instr->result());
+
+  // TODO(3095996): Get rid of this. For now, we need to make the
+  // result register contain a valid pointer because it is already
+  // contained in the register pointer map.
+  __ Set(result, 0);
+
+  __ PushSafepointRegisters();
+  __ Integer32ToSmi(char_code, char_code);
+  __ push(char_code);
+  __ CallRuntimeSaveDoubles(Runtime::kCharFromCode);
+  RecordSafepointWithRegisters(
+      instr->pointer_map(), 1, Safepoint::kNoDeoptimizationIndex);
+  __ StoreToSafepointRegisterSlot(result, rax);
+  __ PopSafepointRegisters();
+}
+
+
 void LCodeGen::DoStringLength(LStringLength* instr) {
   Register string = ToRegister(instr->string());
   Register result = ToRegister(instr->result());
@@ -3201,11 +3464,14 @@
 
 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
   LOperand* input = instr->InputAt(0);
-  ASSERT(input->IsRegister());
   Condition cc = masm()->CheckSmi(ToRegister(input));
-  if (instr->condition() != equal) {
-    cc = NegateCondition(cc);
-  }
+  DeoptimizeIf(NegateCondition(cc), instr->environment());
+}
+
+
+void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
+  LOperand* input = instr->InputAt(0);
+  Condition cc = masm()->CheckSmi(ToRegister(input));
   DeoptimizeIf(cc, instr->environment());
 }
 
@@ -3260,9 +3526,9 @@
 
 
 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) {
-  if (Heap::InNewSpace(*object)) {
+  if (heap()->InNewSpace(*object)) {
     Handle<JSGlobalPropertyCell> cell =
-        Factory::NewJSGlobalPropertyCell(object);
+        factory()->NewJSGlobalPropertyCell(object);
     __ movq(result, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
     __ movq(result, Operand(result, 0));
   } else {
@@ -3343,6 +3609,13 @@
 }
 
 
+void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
+  ASSERT(ToRegister(instr->InputAt(0)).is(rax));
+  __ push(rax);
+  CallRuntime(Runtime::kToFastProperties, 1, instr);
+}
+
+
 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
   NearLabel materialized;
   // Registers will be used as follows:
@@ -3400,14 +3673,17 @@
   // space for nested functions that don't need literals cloning.
   Handle<SharedFunctionInfo> shared_info = instr->shared_info();
   bool pretenure = instr->hydrogen()->pretenure();
-  if (shared_info->num_literals() == 0 && !pretenure) {
-    FastNewClosureStub stub;
+  if (!pretenure && shared_info->num_literals() == 0) {
+    FastNewClosureStub stub(
+        shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
     __ Push(shared_info);
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   } else {
     __ push(rsi);
     __ Push(shared_info);
-    __ Push(pretenure ? Factory::true_value() : Factory::false_value());
+    __ PushRoot(pretenure ?
+                Heap::kTrueValueRootIndex :
+                Heap::kFalseValueRootIndex);
     CallRuntime(Runtime::kNewClosure, 3, instr);
   }
 }
@@ -3488,13 +3764,14 @@
                                  Register input,
                                  Handle<String> type_name) {
   Condition final_branch_condition = no_condition;
-  if (type_name->Equals(Heap::number_symbol())) {
+  if (type_name->Equals(heap()->number_symbol())) {
     __ JumpIfSmi(input, true_label);
-    __ Cmp(FieldOperand(input, HeapObject::kMapOffset),
-           Factory::heap_number_map());
+    __ CompareRoot(FieldOperand(input, HeapObject::kMapOffset),
+                   Heap::kHeapNumberMapRootIndex);
+
     final_branch_condition = equal;
 
-  } else if (type_name->Equals(Heap::string_symbol())) {
+  } else if (type_name->Equals(heap()->string_symbol())) {
     __ JumpIfSmi(input, false_label);
     __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
     __ j(above_equal, false_label);
@@ -3502,13 +3779,13 @@
              Immediate(1 << Map::kIsUndetectable));
     final_branch_condition = zero;
 
-  } else if (type_name->Equals(Heap::boolean_symbol())) {
+  } else if (type_name->Equals(heap()->boolean_symbol())) {
     __ CompareRoot(input, Heap::kTrueValueRootIndex);
     __ j(equal, true_label);
     __ CompareRoot(input, Heap::kFalseValueRootIndex);
     final_branch_condition = equal;
 
-  } else if (type_name->Equals(Heap::undefined_symbol())) {
+  } else if (type_name->Equals(heap()->undefined_symbol())) {
     __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
     __ j(equal, true_label);
     __ JumpIfSmi(input, false_label);
@@ -3518,12 +3795,12 @@
              Immediate(1 << Map::kIsUndetectable));
     final_branch_condition = not_zero;
 
-  } else if (type_name->Equals(Heap::function_symbol())) {
+  } else if (type_name->Equals(heap()->function_symbol())) {
     __ JumpIfSmi(input, false_label);
     __ CmpObjectType(input, FIRST_FUNCTION_CLASS_TYPE, input);
     final_branch_condition = above_equal;
 
-  } else if (type_name->Equals(Heap::object_symbol())) {
+  } else if (type_name->Equals(heap()->object_symbol())) {
     __ JumpIfSmi(input, false_label);
     __ CompareRoot(input, Heap::kNullValueRootIndex);
     __ j(equal, true_label);
@@ -3581,15 +3858,15 @@
 
   // Skip the arguments adaptor frame if it exists.
   NearLabel check_frame_marker;
-  __ SmiCompare(Operand(temp, StandardFrameConstants::kContextOffset),
-                Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+  __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset),
+         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
   __ j(not_equal, &check_frame_marker);
   __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset));
 
   // Check the marker in the calling frame.
   __ bind(&check_frame_marker);
-  __ SmiCompare(Operand(temp, StandardFrameConstants::kMarkerOffset),
-                Smi::FromInt(StackFrame::CONSTRUCT));
+  __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset),
+         Smi::FromInt(StackFrame::CONSTRUCT));
 }
 
 
@@ -3631,8 +3908,7 @@
   // builtin)
   SafepointGenerator safepoint_generator(this,
                                          pointers,
-                                         env->deoptimization_index(),
-                                         true);
+                                         env->deoptimization_index());
   __ Push(Smi::FromInt(strict_mode_flag()));
   __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, &safepoint_generator);
 }
diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h
index ab0dffb..f44fdb9 100644
--- a/src/x64/lithium-codegen-x64.h
+++ b/src/x64/lithium-codegen-x64.h
@@ -67,6 +67,9 @@
   // Simple accessors.
   MacroAssembler* masm() const { return masm_; }
   CompilationInfo* info() const { return info_; }
+  Isolate* isolate() const { return info_->isolate(); }
+  Factory* factory() const { return isolate()->factory(); }
+  Heap* heap() const { return isolate()->heap(); }
 
   // Support for converting LOperands to assembler types.
   Register ToRegister(LOperand* op) const;
@@ -77,7 +80,6 @@
   Handle<Object> ToHandle(LConstantOperand* op) const;
   Operand ToOperand(LOperand* op) const;
 
-
   // Try to generate code for the entire chunk, but it may fail if the
   // chunk contains constructs we cannot handle. Returns true if the
   // code generation attempt succeeded.
@@ -93,7 +95,9 @@
   void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
   void DoDeferredStackCheck(LGoto* instr);
   void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
-  void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr);
+  void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
+  void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
+                                        Label* map_check);
 
   // Parallel move support.
   void DoParallelMove(LParallelMove* move);
@@ -155,13 +159,13 @@
   void CallCode(Handle<Code> code,
                 RelocInfo::Mode mode,
                 LInstruction* instr);
-  void CallRuntime(Runtime::Function* function,
+  void CallRuntime(const Runtime::Function* function,
                    int num_arguments,
                    LInstruction* instr);
   void CallRuntime(Runtime::FunctionId id,
                    int num_arguments,
                    LInstruction* instr) {
-    Runtime::Function* function = Runtime::FunctionForId(id);
+    const Runtime::Function* function = Runtime::FunctionForId(id);
     CallRuntime(function, num_arguments, instr);
   }
 
@@ -210,6 +214,9 @@
                                     int arguments,
                                     int deoptimization_index);
   void RecordPosition(int position);
+  int LastSafepointEnd() {
+    return static_cast<int>(safepoints_.GetPcAfterGap());
+  }
 
   static Condition TokenToCondition(Token::Value op, bool is_unsigned);
   void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL);
@@ -234,15 +241,20 @@
   // Caller should branch on equal condition.
   void EmitIsConstructCall(Register temp);
 
+  void EmitLoadField(Register result,
+                     Register object,
+                     Handle<Map> type,
+                     Handle<String> name);
+
   // Emits code for pushing a constant operand.
   void EmitPushConstantOperand(LOperand* operand);
 
   struct JumpTableEntry {
-    inline JumpTableEntry(Address address)
-        : label_(),
-          address_(address) { }
-    Label label_;
-    Address address_;
+    inline JumpTableEntry(Address entry)
+        : label(),
+          address(entry) { }
+    Label label;
+    Address address;
   };
 
   LChunk* const chunk_;
@@ -253,7 +265,7 @@
   int current_instruction_;
   const ZoneList<LInstruction*>* instructions_;
   ZoneList<LEnvironment*> deoptimizations_;
-  ZoneList<JumpTableEntry*> jump_table_;
+  ZoneList<JumpTableEntry> jump_table_;
   ZoneList<Handle<Object> > deoptimization_literals_;
   int inlined_function_count_;
   Scope* const scope_;
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index bf4d5a1..c47cd72 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -1156,7 +1156,8 @@
 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
     HInstanceOfKnownGlobal* instr) {
   LInstanceOfKnownGlobal* result =
-      new LInstanceOfKnownGlobal(UseFixed(instr->value(), rax));
+      new LInstanceOfKnownGlobal(UseFixed(instr->value(), rax),
+                                 FixedTemp(rdi));
   return MarkAsCall(DefineFixed(result, rax), instr);
 }
 
@@ -1198,7 +1199,8 @@
 
 
 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
-  return DefineAsRegister(new LGlobalReceiver);
+  LOperand* global_object = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new LGlobalReceiver(global_object));
 }
 
 
@@ -1346,13 +1348,23 @@
   if (instr->representation().IsInteger32()) {
     ASSERT(instr->left()->representation().IsInteger32());
     ASSERT(instr->right()->representation().IsInteger32());
-    // The temporary operand is necessary to ensure that right is not allocated
-    // into edx.
-    LOperand* temp = FixedTemp(rdx);
-    LOperand* value = UseFixed(instr->left(), rax);
-    LOperand* divisor = UseRegister(instr->right());
-    LModI* mod = new LModI(value, divisor, temp);
-    LInstruction* result = DefineFixed(mod, rdx);
+
+    LInstruction* result;
+    if (instr->HasPowerOf2Divisor()) {
+      ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
+      LOperand* value = UseRegisterAtStart(instr->left());
+      LModI* mod = new LModI(value, UseOrConstant(instr->right()), NULL);
+      result = DefineSameAsFirst(mod);
+    } else {
+      // The temporary operand is necessary to ensure that right is not
+      // allocated into edx.
+      LOperand* temp = FixedTemp(rdx);
+      LOperand* value = UseFixed(instr->left(), rax);
+      LOperand* divisor = UseRegister(instr->right());
+      LModI* mod = new LModI(value, divisor, temp);
+      result = DefineFixed(mod, rdx);
+    }
+
     return (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
             instr->CheckFlag(HValue::kCanBeDivByZero))
         ? AssignEnvironment(result)
@@ -1555,9 +1567,10 @@
 }
 
 
-LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) {
+LInstruction* LChunkBuilder::DoExternalArrayLength(
+    HExternalArrayLength* instr) {
   LOperand* array = UseRegisterAtStart(instr->value());
-  return DefineAsRegister(new LPixelArrayLength(array));
+  return DefineAsRegister(new LExternalArrayLength(array));
 }
 
 
@@ -1601,7 +1614,8 @@
       bool needs_check = !instr->value()->type().IsSmi();
       if (needs_check) {
         LOperand* xmm_temp =
-            (instr->CanTruncateToInt32() && CpuFeatures::IsSupported(SSE3))
+            (instr->CanTruncateToInt32() &&
+             Isolate::Current()->cpu_features()->IsSupported(SSE3))
             ? NULL
             : FixedTemp(xmm1);
         LTaggedToI* res = new LTaggedToI(value, xmm_temp);
@@ -1646,7 +1660,7 @@
 
 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
-  return AssignEnvironment(new LCheckSmi(value, zero));
+  return AssignEnvironment(new LCheckNonSmi(value));
 }
 
 
@@ -1666,7 +1680,7 @@
 
 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
-  return AssignEnvironment(new LCheckSmi(value, not_zero));
+  return AssignEnvironment(new LCheckSmi(value));
 }
 
 
@@ -1749,6 +1763,21 @@
 }
 
 
+LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
+    HLoadNamedFieldPolymorphic* instr) {
+  ASSERT(instr->representation().IsTagged());
+  if (instr->need_generic()) {
+    LOperand* obj = UseFixed(instr->object(), rax);
+    LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
+    return MarkAsCall(DefineFixed(result, rax), instr);
+  } else {
+    LOperand* obj = UseRegisterAtStart(instr->object());
+    LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
+    return AssignEnvironment(DefineAsRegister(result));
+  }
+}
+
+
 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
   LOperand* object = UseFixed(instr->object(), rax);
   LLoadNamedGeneric* result = new LLoadNamedGeneric(object);
@@ -1769,10 +1798,10 @@
 }
 
 
-LInstruction* LChunkBuilder::DoLoadPixelArrayExternalPointer(
-    HLoadPixelArrayExternalPointer* instr) {
+LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
+    HLoadExternalArrayPointer* instr) {
   LOperand* input = UseRegisterAtStart(instr->value());
-  return DefineAsRegister(new LLoadPixelArrayExternalPointer(input));
+  return DefineAsRegister(new LLoadExternalArrayPointer(input));
 }
 
 
@@ -1787,16 +1816,22 @@
 }
 
 
-LInstruction* LChunkBuilder::DoLoadPixelArrayElement(
-    HLoadPixelArrayElement* instr) {
-  ASSERT(instr->representation().IsInteger32());
+LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
+    HLoadKeyedSpecializedArrayElement* instr) {
+  ExternalArrayType array_type = instr->array_type();
+  Representation representation(instr->representation());
+  ASSERT((representation.IsInteger32() && array_type != kExternalFloatArray) ||
+         (representation.IsDouble() && array_type == kExternalFloatArray));
   ASSERT(instr->key()->representation().IsInteger32());
-  LOperand* external_pointer =
-      UseRegisterAtStart(instr->external_pointer());
-  LOperand* key = UseRegisterAtStart(instr->key());
-  LLoadPixelArrayElement* result =
-      new LLoadPixelArrayElement(external_pointer, key);
-  return DefineSameAsFirst(result);
+  LOperand* external_pointer = UseRegister(instr->external_pointer());
+  LOperand* key = UseRegister(instr->key());
+  LLoadKeyedSpecializedArrayElement* result =
+      new LLoadKeyedSpecializedArrayElement(external_pointer, key);
+  LInstruction* load_instr = DefineAsRegister(result);
+  // An unsigned int array load might overflow and cause a deopt, make sure it
+  // has an environment.
+  return (array_type == kExternalUnsignedIntArray) ?
+      AssignEnvironment(load_instr) : load_instr;
 }
 
 
@@ -1828,17 +1863,26 @@
 }
 
 
-LInstruction* LChunkBuilder::DoStorePixelArrayElement(
-    HStorePixelArrayElement* instr) {
-  ASSERT(instr->value()->representation().IsInteger32());
+LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
+    HStoreKeyedSpecializedArrayElement* instr) {
+  Representation representation(instr->value()->representation());
+  ExternalArrayType array_type = instr->array_type();
+  ASSERT((representation.IsInteger32() && array_type != kExternalFloatArray) ||
+         (representation.IsDouble() && array_type == kExternalFloatArray));
   ASSERT(instr->external_pointer()->representation().IsExternal());
   ASSERT(instr->key()->representation().IsInteger32());
 
   LOperand* external_pointer = UseRegister(instr->external_pointer());
-  LOperand* val = UseTempRegister(instr->value());
+  bool val_is_temp_register = array_type == kExternalPixelArray ||
+      array_type == kExternalFloatArray;
+  LOperand* val = val_is_temp_register
+      ? UseTempRegister(instr->value())
+      : UseRegister(instr->key());
   LOperand* key = UseRegister(instr->key());
 
-  return new LStorePixelArrayElement(external_pointer, key, val);
+  return new LStoreKeyedSpecializedArrayElement(external_pointer,
+                                                key,
+                                                val);
 }
 
 
@@ -1893,6 +1937,13 @@
 }
 
 
+LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
+  LOperand* char_code = UseRegister(instr->value());
+  LStringCharFromCode* result = new LStringCharFromCode(char_code);
+  return AssignPointerMap(DefineAsRegister(result));
+}
+
+
 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
   LOperand* string = UseRegisterAtStart(instr->value());
   return DefineAsRegister(new LStringLength(string));
@@ -1969,6 +2020,13 @@
 }
 
 
+LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
+  LOperand* object = UseFixed(instr->value(), rax);
+  LToFastProperties* result = new LToFastProperties(object);
+  return MarkAsCall(DefineFixed(result, rax), instr);
+}
+
+
 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
   LTypeof* result = new LTypeof(UseAtStart(instr->value()));
   return MarkAsCall(DefineFixed(result, rax), instr);
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index 67ec7af..e94debf 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -70,8 +70,11 @@
   V(CheckFunction)                              \
   V(CheckInstanceType)                          \
   V(CheckMap)                                   \
+  V(CheckNonSmi)                                \
   V(CheckPrototypeMaps)                         \
   V(CheckSmi)                                   \
+  V(ClassOfTest)                                \
+  V(ClassOfTestAndBranch)                       \
   V(CmpID)                                      \
   V(CmpIDAndBranch)                             \
   V(CmpJSObjectEq)                              \
@@ -87,13 +90,18 @@
   V(Deoptimize)                                 \
   V(DivI)                                       \
   V(DoubleToI)                                  \
+  V(ExternalArrayLength)                        \
+  V(FixedArrayLength)                           \
   V(FunctionLiteral)                            \
   V(Gap)                                        \
   V(GetCachedArrayIndex)                        \
   V(GlobalObject)                               \
   V(GlobalReceiver)                             \
   V(Goto)                                       \
-  V(FixedArrayLength)                           \
+  V(HasInstanceType)                            \
+  V(HasInstanceTypeAndBranch)                   \
+  V(HasCachedArrayIndex)                        \
+  V(HasCachedArrayIndexAndBranch)               \
   V(InstanceOf)                                 \
   V(InstanceOfAndBranch)                        \
   V(InstanceOfKnownGlobal)                      \
@@ -105,24 +113,19 @@
   V(IsSmi)                                      \
   V(IsSmiAndBranch)                             \
   V(JSArrayLength)                              \
-  V(HasInstanceType)                            \
-  V(HasInstanceTypeAndBranch)                   \
-  V(HasCachedArrayIndex)                        \
-  V(HasCachedArrayIndexAndBranch)               \
-  V(ClassOfTest)                                \
-  V(ClassOfTestAndBranch)                       \
   V(Label)                                      \
   V(LazyBailout)                                \
   V(LoadContextSlot)                            \
   V(LoadElements)                               \
+  V(LoadExternalArrayPointer)                   \
   V(LoadGlobal)                                 \
   V(LoadKeyedFastElement)                       \
   V(LoadKeyedGeneric)                           \
+  V(LoadKeyedSpecializedArrayElement)           \
   V(LoadNamedField)                             \
+  V(LoadNamedFieldPolymorphic)                  \
   V(LoadNamedGeneric)                           \
   V(LoadFunctionPrototype)                      \
-  V(LoadPixelArrayElement)                      \
-  V(LoadPixelArrayExternalPointer)              \
   V(ModI)                                       \
   V(MulI)                                       \
   V(NumberTagD)                                 \
@@ -132,7 +135,6 @@
   V(OsrEntry)                                   \
   V(OuterContext)                               \
   V(Parameter)                                  \
-  V(PixelArrayLength)                           \
   V(Power)                                      \
   V(PushArgument)                               \
   V(RegExpLiteral)                              \
@@ -145,13 +147,15 @@
   V(StoreGlobal)                                \
   V(StoreKeyedFastElement)                      \
   V(StoreKeyedGeneric)                          \
+  V(StoreKeyedSpecializedArrayElement)          \
   V(StoreNamedField)                            \
   V(StoreNamedGeneric)                          \
-  V(StorePixelArrayElement)                     \
   V(StringCharCodeAt)                           \
+  V(StringCharFromCode)                         \
   V(StringLength)                               \
   V(SubI)                                       \
   V(TaggedToI)                                  \
+  V(ToFastProperties)                           \
   V(Throw)                                      \
   V(Typeof)                                     \
   V(TypeofIs)                                   \
@@ -844,10 +848,11 @@
 };
 
 
-class LInstanceOfKnownGlobal: public LTemplateInstruction<1, 1, 0> {
+class LInstanceOfKnownGlobal: public LTemplateInstruction<1, 1, 1> {
  public:
-  explicit LInstanceOfKnownGlobal(LOperand* value) {
+  LInstanceOfKnownGlobal(LOperand* value, LOperand* temp) {
     inputs_[0] = value;
+    temps_[0] = temp;
   }
 
   DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
@@ -996,14 +1001,14 @@
 };
 
 
-class LPixelArrayLength: public LTemplateInstruction<1, 1, 0> {
+class LExternalArrayLength: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LPixelArrayLength(LOperand* value) {
+  explicit LExternalArrayLength(LOperand* value) {
     inputs_[0] = value;
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel-array-length")
-  DECLARE_HYDROGEN_ACCESSOR(PixelArrayLength)
+  DECLARE_CONCRETE_INSTRUCTION(ExternalArrayLength, "external-array-length")
+  DECLARE_HYDROGEN_ACCESSOR(ExternalArrayLength)
 };
 
 
@@ -1130,6 +1135,19 @@
 };
 
 
+class LLoadNamedFieldPolymorphic: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LLoadNamedFieldPolymorphic(LOperand* object) {
+    inputs_[0] = object;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field-polymorphic")
+  DECLARE_HYDROGEN_ACCESSOR(LoadNamedFieldPolymorphic)
+
+  LOperand* object() { return inputs_[0]; }
+};
+
+
 class LLoadNamedGeneric: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LLoadNamedGeneric(LOperand* object) {
@@ -1167,14 +1185,14 @@
 };
 
 
-class LLoadPixelArrayExternalPointer: public LTemplateInstruction<1, 1, 0> {
+class LLoadExternalArrayPointer: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LLoadPixelArrayExternalPointer(LOperand* object) {
+  explicit LLoadExternalArrayPointer(LOperand* object) {
     inputs_[0] = object;
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
-                               "load-pixel-array-external-pointer")
+  DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer,
+                               "load-external-array-pointer")
 };
 
 
@@ -1193,19 +1211,23 @@
 };
 
 
-class LLoadPixelArrayElement: public LTemplateInstruction<1, 2, 0> {
+class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
  public:
-  LLoadPixelArrayElement(LOperand* external_pointer, LOperand* key) {
+  LLoadKeyedSpecializedArrayElement(LOperand* external_pointer,
+                                    LOperand* key) {
     inputs_[0] = external_pointer;
     inputs_[1] = key;
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayElement,
-                               "load-pixel-array-element")
-  DECLARE_HYDROGEN_ACCESSOR(LoadPixelArrayElement)
+  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement,
+                               "load-keyed-specialized-array-element")
+  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedSpecializedArrayElement)
 
   LOperand* external_pointer() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
+  ExternalArrayType array_type() const {
+    return hydrogen()->array_type();
+  }
 };
 
 
@@ -1312,9 +1334,15 @@
 };
 
 
-class LGlobalReceiver: public LTemplateInstruction<1, 0, 0> {
+class LGlobalReceiver: public LTemplateInstruction<1, 1, 0> {
  public:
+  explicit LGlobalReceiver(LOperand* global_object) {
+    inputs_[0] = global_object;
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global-receiver")
+
+  LOperand* global() { return InputAt(0); }
 };
 
 
@@ -1414,7 +1442,7 @@
   DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
   DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
 
-  Runtime::Function* function() const { return hydrogen()->function(); }
+  const Runtime::Function* function() const { return hydrogen()->function(); }
   int arity() const { return hydrogen()->argument_count(); }
 };
 
@@ -1577,23 +1605,26 @@
 };
 
 
-class LStorePixelArrayElement: public LTemplateInstruction<0, 3, 0> {
+class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 0> {
  public:
-  LStorePixelArrayElement(LOperand* external_pointer,
-                          LOperand* key,
-                          LOperand* val) {
+  LStoreKeyedSpecializedArrayElement(LOperand* external_pointer,
+                                     LOperand* key,
+                                     LOperand* val) {
     inputs_[0] = external_pointer;
     inputs_[1] = key;
     inputs_[2] = val;
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(StorePixelArrayElement,
-                               "store-pixel-array-element")
-  DECLARE_HYDROGEN_ACCESSOR(StorePixelArrayElement)
+  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement,
+                               "store-keyed-specialized-array-element")
+  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedSpecializedArrayElement)
 
   LOperand* external_pointer() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
+  ExternalArrayType array_type() const {
+    return hydrogen()->array_type();
+  }
 };
 
 
@@ -1630,6 +1661,19 @@
 };
 
 
+class LStringCharFromCode: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LStringCharFromCode(LOperand* char_code) {
+    inputs_[0] = char_code;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
+  DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
+
+  LOperand* char_code() { return inputs_[0]; }
+};
+
+
 class LStringLength: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LStringLength(LOperand* string) {
@@ -1692,20 +1736,21 @@
 
 class LCheckSmi: public LTemplateInstruction<0, 1, 0> {
  public:
-  LCheckSmi(LOperand* value, Condition condition)
-      : condition_(condition) {
+  explicit LCheckSmi(LOperand* value) {
     inputs_[0] = value;
   }
 
-  Condition condition() const { return condition_; }
+  DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi")
+};
 
-  virtual void CompileToNative(LCodeGen* generator);
-  virtual const char* Mnemonic() const {
-    return (condition_ == zero) ? "check-non-smi" : "check-smi";
+
+class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LCheckNonSmi(LOperand* value) {
+    inputs_[0] = value;
   }
 
- private:
-  Condition condition_;
+  DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi")
 };
 
 
@@ -1739,6 +1784,17 @@
 };
 
 
+class LToFastProperties: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LToFastProperties(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to-fast-properties")
+  DECLARE_HYDROGEN_ACCESSOR(ToFastProperties)
+};
+
+
 class LTypeof: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LTypeof(LOperand* value) {
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index b468e82..654814c 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -44,11 +44,110 @@
     : Assembler(buffer, size),
       generating_stub_(false),
       allow_stub_calls_(true),
-      code_object_(Heap::undefined_value()) {
+      root_array_available_(true),
+      code_object_(isolate()->heap()->undefined_value()) {
+}
+
+
+static intptr_t RootRegisterDelta(ExternalReference other, Isolate* isolate) {
+  Address roots_register_value = kRootRegisterBias +
+      reinterpret_cast<Address>(isolate->heap()->roots_address());
+  intptr_t delta = other.address() - roots_register_value;
+  return delta;
+}
+
+
+Operand MacroAssembler::ExternalOperand(ExternalReference target,
+                                        Register scratch) {
+  if (root_array_available_ && !Serializer::enabled()) {
+    intptr_t delta = RootRegisterDelta(target, isolate());
+    if (is_int32(delta)) {
+      Serializer::TooLateToEnableNow();
+      return Operand(kRootRegister, static_cast<int32_t>(delta));
+    }
+  }
+  movq(scratch, target);
+  return Operand(scratch, 0);
+}
+
+
+void MacroAssembler::Load(Register destination, ExternalReference source) {
+  if (root_array_available_ && !Serializer::enabled()) {
+    intptr_t delta = RootRegisterDelta(source, isolate());
+    if (is_int32(delta)) {
+      Serializer::TooLateToEnableNow();
+      movq(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
+      return;
+    }
+  }
+  // Safe code.
+  if (destination.is(rax)) {
+    load_rax(source);
+  } else {
+    movq(kScratchRegister, source);
+    movq(destination, Operand(kScratchRegister, 0));
+  }
+}
+
+
+void MacroAssembler::Store(ExternalReference destination, Register source) {
+  if (root_array_available_ && !Serializer::enabled()) {
+    intptr_t delta = RootRegisterDelta(destination, isolate());
+    if (is_int32(delta)) {
+      Serializer::TooLateToEnableNow();
+      movq(Operand(kRootRegister, static_cast<int32_t>(delta)), source);
+      return;
+    }
+  }
+  // Safe code.
+  if (source.is(rax)) {
+    store_rax(destination);
+  } else {
+    movq(kScratchRegister, destination);
+    movq(Operand(kScratchRegister, 0), source);
+  }
+}
+
+
+void MacroAssembler::LoadAddress(Register destination,
+                                 ExternalReference source) {
+  if (root_array_available_ && !Serializer::enabled()) {
+    intptr_t delta = RootRegisterDelta(source, isolate());
+    if (is_int32(delta)) {
+      Serializer::TooLateToEnableNow();
+      lea(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
+      return;
+    }
+  }
+  // Safe code.
+  movq(destination, source);
+}
+
+
+int MacroAssembler::LoadAddressSize(ExternalReference source) {
+  if (root_array_available_ && !Serializer::enabled()) {
+    // This calculation depends on the internals of LoadAddress.
+    // It's correctness is ensured by the asserts in the Call
+    // instruction below.
+    intptr_t delta = RootRegisterDelta(source, isolate());
+    if (is_int32(delta)) {
+      Serializer::TooLateToEnableNow();
+      // Operand is lea(scratch, Operand(kRootRegister, delta));
+      // Opcodes : REX.W 8D ModRM Disp8/Disp32  - 4 or 7.
+      int size = 4;
+      if (!is_int8(static_cast<int32_t>(delta))) {
+        size += 3;  // Need full four-byte displacement in lea.
+      }
+      return size;
+    }
+  }
+  // Size of movq(destination, src);
+  return 10;
 }
 
 
 void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
+  ASSERT(root_array_available_);
   movq(destination, Operand(kRootRegister,
                             (index << kPointerSizeLog2) - kRootRegisterBias));
 }
@@ -57,6 +156,7 @@
 void MacroAssembler::LoadRootIndexed(Register destination,
                                      Register variable_offset,
                                      int fixed_offset) {
+  ASSERT(root_array_available_);
   movq(destination,
        Operand(kRootRegister,
                variable_offset, times_pointer_size,
@@ -65,17 +165,20 @@
 
 
 void MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) {
+  ASSERT(root_array_available_);
   movq(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias),
        source);
 }
 
 
 void MacroAssembler::PushRoot(Heap::RootListIndex index) {
+  ASSERT(root_array_available_);
   push(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias));
 }
 
 
 void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
+  ASSERT(root_array_available_);
   cmpq(with, Operand(kRootRegister,
                      (index << kPointerSizeLog2) - kRootRegisterBias));
 }
@@ -83,6 +186,7 @@
 
 void MacroAssembler::CompareRoot(const Operand& with,
                                  Heap::RootListIndex index) {
+  ASSERT(root_array_available_);
   ASSERT(!with.AddressUsesRegister(kScratchRegister));
   LoadRoot(kScratchRegister, index);
   cmpq(with, kScratchRegister);
@@ -92,7 +196,7 @@
 void MacroAssembler::RecordWriteHelper(Register object,
                                        Register addr,
                                        Register scratch) {
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     // Check that the object is not in new space.
     NearLabel not_in_new_space;
     InNewSpace(object, scratch, not_equal, &not_in_new_space);
@@ -124,7 +228,7 @@
   ASSERT(!object.is(rsi) && !value.is(rsi) && !index.is(rsi));
 
   // First, check if a write barrier is even needed. The tests below
-  // catch stores of Smis and stores into young gen.
+  // catch stores of smis and stores into the young generation.
   Label done;
   JumpIfSmi(value, &done);
 
@@ -136,7 +240,7 @@
   // clobbering done inside RecordWriteNonSmi but it's necessary to
   // avoid having the fast case for smis leave the registers
   // unchanged.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
     movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
     movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
@@ -153,7 +257,7 @@
   ASSERT(!object.is(rsi) && !value.is(rsi) && !address.is(rsi));
 
   // First, check if a write barrier is even needed. The tests below
-  // catch stores of Smis and stores into young gen.
+  // catch stores of smis and stores into the young generation.
   Label done;
   JumpIfSmi(value, &done);
 
@@ -165,7 +269,7 @@
 
   // Clobber all input registers when running with the debug-code flag
   // turned on to provoke errors.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
     movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
     movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
@@ -179,7 +283,7 @@
                                        Register index) {
   Label done;
 
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     NearLabel okay;
     JumpIfNotSmi(object, &okay);
     Abort("MacroAssembler::RecordWriteNonSmi cannot deal with smis");
@@ -223,7 +327,7 @@
 
   // Clobber all input registers when running with the debug-code flag
   // turned on to provoke errors.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
     movq(scratch, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
     movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
@@ -231,12 +335,12 @@
 }
 
 void MacroAssembler::Assert(Condition cc, const char* msg) {
-  if (FLAG_debug_code) Check(cc, msg);
+  if (emit_debug_code()) Check(cc, msg);
 }
 
 
 void MacroAssembler::AssertFastElements(Register elements) {
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     NearLabel ok;
     CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
                 Heap::kFixedArrayMapRootIndex);
@@ -391,9 +495,9 @@
 
 
 void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
-  Runtime::Function* function = Runtime::FunctionForId(id);
+  const Runtime::Function* function = Runtime::FunctionForId(id);
   Set(rax, function->nargs);
-  movq(rbx, ExternalReference(function));
+  LoadAddress(rbx, ExternalReference(function, isolate()));
   CEntryStub ces(1);
   ces.SaveDoubles();
   CallStub(&ces);
@@ -406,7 +510,8 @@
 }
 
 
-void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
+void MacroAssembler::CallRuntime(const 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.
@@ -420,19 +525,19 @@
   // should remove this need and make the runtime routine entry code
   // smarter.
   Set(rax, num_arguments);
-  movq(rbx, ExternalReference(f));
+  LoadAddress(rbx, ExternalReference(f, isolate()));
   CEntryStub ces(f->result_size);
   CallStub(&ces);
 }
 
 
-MaybeObject* MacroAssembler::TryCallRuntime(Runtime::Function* f,
+MaybeObject* MacroAssembler::TryCallRuntime(const Runtime::Function* f,
                                             int num_arguments) {
   if (f->nargs >= 0 && f->nargs != num_arguments) {
     IllegalOperation(num_arguments);
     // Since we did not call the stub, there was no allocation failure.
     // Return some non-failure object.
-    return Heap::undefined_value();
+    return HEAP->undefined_value();
   }
 
   // TODO(1236192): Most runtime routines don't need the number of
@@ -440,7 +545,7 @@
   // should remove this need and make the runtime routine entry code
   // smarter.
   Set(rax, num_arguments);
-  movq(rbx, ExternalReference(f));
+  LoadAddress(rbx, ExternalReference(f, isolate()));
   CEntryStub ces(f->result_size);
   return TryCallStub(&ces);
 }
@@ -449,7 +554,7 @@
 void MacroAssembler::CallExternalReference(const ExternalReference& ext,
                                            int num_arguments) {
   Set(rax, num_arguments);
-  movq(rbx, ext);
+  LoadAddress(rbx, ext);
 
   CEntryStub stub(1);
   CallStub(&stub);
@@ -496,14 +601,16 @@
 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
                                      int num_arguments,
                                      int result_size) {
-  TailCallExternalReference(ExternalReference(fid), num_arguments, result_size);
+  TailCallExternalReference(ExternalReference(fid, isolate()),
+                            num_arguments,
+                            result_size);
 }
 
 
 MaybeObject* MacroAssembler::TryTailCallRuntime(Runtime::FunctionId fid,
                                                 int num_arguments,
                                                 int result_size) {
-  return TryTailCallExternalReference(ExternalReference(fid),
+  return TryTailCallExternalReference(ExternalReference(fid, isolate()),
                                       num_arguments,
                                       result_size);
 }
@@ -550,12 +657,12 @@
       ExternalReference::handle_scope_level_address(),
       next_address);
   ExternalReference scheduled_exception_address =
-      ExternalReference::scheduled_exception_address();
+      ExternalReference::scheduled_exception_address(isolate());
 
   // Allocate HandleScope in callee-save registers.
   Register prev_next_address_reg = r14;
   Register prev_limit_reg = rbx;
-  Register base_reg = r12;
+  Register base_reg = r15;
   movq(base_reg, next_address);
   movq(prev_next_address_reg, Operand(base_reg, kNextOffset));
   movq(prev_limit_reg, Operand(base_reg, kLimitOffset));
@@ -587,7 +694,7 @@
 
   // Check if the function scheduled an exception.
   movq(rsi, scheduled_exception_address);
-  Cmp(Operand(rsi, 0), Factory::the_hole_value());
+  Cmp(Operand(rsi, 0), FACTORY->the_hole_value());
   j(not_equal, &promote_scheduled_exception);
 
   LeaveApiExitFrame();
@@ -602,14 +709,20 @@
 
   bind(&empty_result);
   // It was zero; the result is undefined.
-  Move(rax, Factory::undefined_value());
+  Move(rax, FACTORY->undefined_value());
   jmp(&prologue);
 
   // HandleScope limit has changed. Delete allocated extensions.
   bind(&delete_allocated_handles);
   movq(Operand(base_reg, kLimitOffset), prev_limit_reg);
   movq(prev_limit_reg, rax);
-  movq(rax, ExternalReference::delete_handle_scope_extensions());
+#ifdef _WIN64
+  LoadAddress(rcx, ExternalReference::isolate_address());
+#else
+  LoadAddress(rdi, ExternalReference::isolate_address());
+#endif
+  LoadAddress(rax,
+              ExternalReference::delete_handle_scope_extensions(isolate()));
   call(rax);
   movq(rax, prev_limit_reg);
   jmp(&leave_exit_frame);
@@ -621,7 +734,7 @@
 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
                                              int result_size) {
   // Set the entry point and jump to the C entry runtime stub.
-  movq(rbx, ext);
+  LoadAddress(rbx, ext);
   CEntryStub ces(result_size);
   jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
 }
@@ -630,7 +743,7 @@
 MaybeObject* MacroAssembler::TryJumpToExternalReference(
     const ExternalReference& ext, int result_size) {
   // Set the entry point and jump to the C entry runtime stub.
-  movq(rbx, ext);
+  LoadAddress(rbx, ext);
   CEntryStub ces(result_size);
   return TryTailCallStub(&ces);
 }
@@ -638,7 +751,7 @@
 
 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
                                    InvokeFlag flag,
-                                   PostCallGenerator* post_call_generator) {
+                                   CallWrapper* call_wrapper) {
   // Calls are not allowed in some stubs.
   ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
 
@@ -647,7 +760,7 @@
   // parameter count to avoid emitting code to do the check.
   ParameterCount expected(0);
   GetBuiltinEntry(rdx, id);
-  InvokeCode(rdx, expected, expected, flag, post_call_generator);
+  InvokeCode(rdx, expected, expected, flag, call_wrapper);
 }
 
 
@@ -707,7 +820,7 @@
 }
 
 void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     movq(dst,
          reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)),
          RelocInfo::NONE);
@@ -721,11 +834,11 @@
       bind(&ok);
     }
   }
-  if (source->value() == 0) {
+  int value = source->value();
+  if (value == 0) {
     xorl(dst, dst);
     return;
   }
-  int value = source->value();
   bool negative = value < 0;
   unsigned int uvalue = negative ? -value : value;
 
@@ -776,7 +889,7 @@
 
 
 void MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) {
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     testb(dst, Immediate(0x01));
     NearLabel ok;
     j(zero, &ok);
@@ -796,9 +909,9 @@
                                                 Register src,
                                                 int constant) {
   if (dst.is(src)) {
-    addq(dst, Immediate(constant));
+    addl(dst, Immediate(constant));
   } else {
-    lea(dst, Operand(src, constant));
+    leal(dst, Operand(src, constant));
   }
   shl(dst, Immediate(kSmiShift));
 }
@@ -837,12 +950,24 @@
 }
 
 
-void MacroAssembler::SmiCompare(Register dst, Register src) {
-  cmpq(dst, src);
+void MacroAssembler::SmiCompare(Register smi1, Register smi2) {
+  if (emit_debug_code()) {
+    AbortIfNotSmi(smi1);
+    AbortIfNotSmi(smi2);
+  }
+  cmpq(smi1, smi2);
 }
 
 
 void MacroAssembler::SmiCompare(Register dst, Smi* src) {
+  if (emit_debug_code()) {
+    AbortIfNotSmi(dst);
+  }
+  Cmp(dst, src);
+}
+
+
+void MacroAssembler::Cmp(Register dst, Smi* src) {
   ASSERT(!dst.is(kScratchRegister));
   if (src->value() == 0) {
     testq(dst, dst);
@@ -854,20 +979,39 @@
 
 
 void MacroAssembler::SmiCompare(Register dst, const Operand& src) {
+  if (emit_debug_code()) {
+    AbortIfNotSmi(dst);
+    AbortIfNotSmi(src);
+  }
   cmpq(dst, src);
 }
 
 
 void MacroAssembler::SmiCompare(const Operand& dst, Register src) {
+  if (emit_debug_code()) {
+    AbortIfNotSmi(dst);
+    AbortIfNotSmi(src);
+  }
   cmpq(dst, src);
 }
 
 
 void MacroAssembler::SmiCompare(const Operand& dst, Smi* src) {
+  if (emit_debug_code()) {
+    AbortIfNotSmi(dst);
+  }
   cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value()));
 }
 
 
+void MacroAssembler::Cmp(const Operand& dst, Smi* src) {
+  // The Operand cannot use the smi register.
+  Register smi_reg = GetSmiConstant(src);
+  ASSERT(!dst.AddressUsesRegister(smi_reg));
+  cmpq(dst, smi_reg);
+}
+
+
 void MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) {
   cmpl(Operand(dst, kSmiShift / kBitsPerByte), src);
 }
@@ -1101,12 +1245,10 @@
   // No overflow checking. Use only when it's known that
   // overflowing is impossible.
   ASSERT(!dst.is(src2));
-  if (dst.is(src1)) {
-    addq(dst, src2);
-  } else {
+  if (!dst.is(src1)) {
     movq(dst, src1);
-    addq(dst, src2);
   }
+  addq(dst, src2);
   Assert(no_overflow, "Smi addition overflow");
 }
 
@@ -1115,12 +1257,10 @@
   // No overflow checking. Use only when it's known that
   // overflowing is impossible (e.g., subtracting two positive smis).
   ASSERT(!dst.is(src2));
-  if (dst.is(src1)) {
-    subq(dst, src2);
-  } else {
+  if (!dst.is(src1)) {
     movq(dst, src1);
-    subq(dst, src2);
   }
+  subq(dst, src2);
   Assert(no_overflow, "Smi subtraction overflow");
 }
 
@@ -1130,12 +1270,10 @@
                             const Operand& src2) {
   // No overflow checking. Use only when it's known that
   // overflowing is impossible (e.g., subtracting two positive smis).
-  if (dst.is(src1)) {
-    subq(dst, src2);
-  } else {
+  if (!dst.is(src1)) {
     movq(dst, src1);
-    subq(dst, src2);
   }
+  subq(dst, src2);
   Assert(no_overflow, "Smi subtraction overflow");
 }
 
@@ -1322,6 +1460,13 @@
 }
 
 
+void MacroAssembler::AddSmiField(Register dst, const Operand& src) {
+  ASSERT_EQ(0, kSmiShift % kBitsPerByte);
+  addl(dst, Operand(src, kSmiShift / kBitsPerByte));
+}
+
+
+
 void MacroAssembler::Move(Register dst, Register src) {
   if (!dst.is(src)) {
     movq(dst, src);
@@ -1352,7 +1497,7 @@
 
 void MacroAssembler::Cmp(Register dst, Handle<Object> source) {
   if (source->IsSmi()) {
-    SmiCompare(dst, Smi::cast(*source));
+    Cmp(dst, Smi::cast(*source));
   } else {
     Move(kScratchRegister, source);
     cmpq(dst, kScratchRegister);
@@ -1362,7 +1507,7 @@
 
 void MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) {
   if (source->IsSmi()) {
-    SmiCompare(dst, Smi::cast(*source));
+    Cmp(dst, Smi::cast(*source));
   } else {
     ASSERT(source->IsHeapObject());
     movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
@@ -1406,7 +1551,7 @@
 
 
 void MacroAssembler::Jump(ExternalReference ext) {
-  movq(kScratchRegister, ext);
+  LoadAddress(kScratchRegister, ext);
   jmp(kScratchRegister);
 }
 
@@ -1423,21 +1568,46 @@
 }
 
 
+int MacroAssembler::CallSize(ExternalReference ext) {
+  // Opcode for call kScratchRegister is: Rex.B FF D4 (three bytes).
+  const int kCallInstructionSize = 3;
+  return LoadAddressSize(ext) + kCallInstructionSize;
+}
+
+
 void MacroAssembler::Call(ExternalReference ext) {
-  movq(kScratchRegister, ext);
+#ifdef DEBUG
+  int end_position = pc_offset() + CallSize(ext);
+#endif
+  LoadAddress(kScratchRegister, ext);
   call(kScratchRegister);
+#ifdef DEBUG
+  CHECK_EQ(end_position, pc_offset());
+#endif
 }
 
 
 void MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) {
+#ifdef DEBUG
+  int end_position = pc_offset() + CallSize(destination, rmode);
+#endif
   movq(kScratchRegister, destination, rmode);
   call(kScratchRegister);
+#ifdef DEBUG
+  CHECK_EQ(pc_offset(), end_position);
+#endif
 }
 
 
 void MacroAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) {
+#ifdef DEBUG
+  int end_position = pc_offset() + CallSize(code_object);
+#endif
   ASSERT(RelocInfo::IsCodeTarget(rmode));
   call(code_object, rmode);
+#ifdef DEBUG
+  CHECK_EQ(end_position, pc_offset());
+#endif
 }
 
 
@@ -1453,10 +1623,10 @@
   push(r9);
   // r10 is kScratchRegister.
   push(r11);
-  push(r12);
+  // r12 is kSmiConstantRegister.
   // r13 is kRootRegister.
   push(r14);
-  // r15 is kSmiConstantRegister
+  push(r15);
   STATIC_ASSERT(11 == kNumSafepointSavedRegisters);
   // Use lea for symmetry with Popad.
   int sp_delta =
@@ -1470,8 +1640,8 @@
   int sp_delta =
       (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize;
   lea(rsp, Operand(rsp, sp_delta));
+  pop(r15);
   pop(r14);
-  pop(r12);
   pop(r11);
   pop(r9);
   pop(r8);
@@ -1490,7 +1660,7 @@
 
 
 // Order general registers are pushed by Pushad:
-// rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r12, r14.
+// rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15.
 int MacroAssembler::kSafepointPushRegisterIndices[Register::kNumRegisters] = {
     0,
     1,
@@ -1504,10 +1674,10 @@
     7,
     -1,
     8,
-    9,
     -1,
-    10,
-    -1
+    -1,
+    9,
+    10
 };
 
 
@@ -1557,18 +1727,20 @@
     push(Immediate(0));  // NULL frame pointer.
   }
   // Save the current handler.
-  movq(kScratchRegister, ExternalReference(Top::k_handler_address));
-  push(Operand(kScratchRegister, 0));
+  Operand handler_operand =
+      ExternalOperand(ExternalReference(Isolate::k_handler_address, isolate()));
+  push(handler_operand);
   // Link this handler.
-  movq(Operand(kScratchRegister, 0), rsp);
+  movq(handler_operand, rsp);
 }
 
 
 void MacroAssembler::PopTryHandler() {
   ASSERT_EQ(0, StackHandlerConstants::kNextOffset);
   // Unlink this handler.
-  movq(kScratchRegister, ExternalReference(Top::k_handler_address));
-  pop(Operand(kScratchRegister, 0));
+  Operand handler_operand =
+      ExternalOperand(ExternalReference(Isolate::k_handler_address, isolate()));
+  pop(handler_operand);
   // Remove the remaining fields.
   addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize));
 }
@@ -1586,12 +1758,11 @@
     movq(rax, value);
   }
 
-  ExternalReference handler_address(Top::k_handler_address);
-  movq(kScratchRegister, handler_address);
-  movq(rsp, Operand(kScratchRegister, 0));
+  ExternalReference handler_address(Isolate::k_handler_address, isolate());
+  Operand handler_operand = ExternalOperand(handler_address);
+  movq(rsp, handler_operand);
   // get next in chain
-  pop(rcx);
-  movq(Operand(kScratchRegister, 0), rcx);
+  pop(handler_operand);
   pop(rbp);  // pop frame pointer
   pop(rdx);  // remove state
 
@@ -1614,9 +1785,8 @@
     movq(rax, value);
   }
   // Fetch top stack handler.
-  ExternalReference handler_address(Top::k_handler_address);
-  movq(kScratchRegister, handler_address);
-  movq(rsp, Operand(kScratchRegister, 0));
+  ExternalReference handler_address(Isolate::k_handler_address, isolate());
+  Load(rsp, handler_address);
 
   // Unwind the handlers until the ENTRY handler is found.
   NearLabel loop, done;
@@ -1632,19 +1802,21 @@
   bind(&done);
 
   // Set the top handler address to next handler past the current ENTRY handler.
-  movq(kScratchRegister, handler_address);
-  pop(Operand(kScratchRegister, 0));
+  Operand handler_operand = ExternalOperand(handler_address);
+  pop(handler_operand);
 
   if (type == OUT_OF_MEMORY) {
     // Set external caught exception to false.
-    ExternalReference external_caught(Top::k_external_caught_exception_address);
+    ExternalReference external_caught(
+        Isolate::k_external_caught_exception_address, isolate());
     movq(rax, Immediate(false));
-    store_rax(external_caught);
+    Store(external_caught, rax);
 
     // Set pending exception and rax to out of memory exception.
-    ExternalReference pending_exception(Top::k_pending_exception_address);
+    ExternalReference pending_exception(Isolate::k_pending_exception_address,
+                                        isolate());
     movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE);
-    store_rax(pending_exception);
+    Store(pending_exception, rax);
   }
 
   // Clear the context pointer.
@@ -1652,14 +1824,14 @@
 
   // Restore registers from handler.
   STATIC_ASSERT(StackHandlerConstants::kNextOffset + kPointerSize ==
-            StackHandlerConstants::kFPOffset);
+                StackHandlerConstants::kFPOffset);
   pop(rbp);  // FP
   STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize ==
-            StackHandlerConstants::kStateOffset);
+                StackHandlerConstants::kStateOffset);
   pop(rdx);  // State
 
   STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize ==
-            StackHandlerConstants::kPCOffset);
+                StackHandlerConstants::kPCOffset);
   ret(0);
 }
 
@@ -1718,7 +1890,7 @@
   Condition is_smi = CheckSmi(object);
   j(is_smi, &ok);
   Cmp(FieldOperand(object, HeapObject::kMapOffset),
-      Factory::heap_number_map());
+      FACTORY->heap_number_map());
   Assert(equal, "Operand not a number");
   bind(&ok);
 }
@@ -1732,7 +1904,12 @@
 
 
 void MacroAssembler::AbortIfNotSmi(Register object) {
-  NearLabel ok;
+  Condition is_smi = CheckSmi(object);
+  Assert(is_smi, "Operand is not a smi");
+}
+
+
+void MacroAssembler::AbortIfNotSmi(const Operand& object) {
   Condition is_smi = CheckSmi(object);
   Assert(is_smi, "Operand is not a smi");
 }
@@ -1819,8 +1996,8 @@
 
 void MacroAssembler::SetCounter(StatsCounter* counter, int value) {
   if (FLAG_native_code_counters && counter->Enabled()) {
-    movq(kScratchRegister, ExternalReference(counter));
-    movl(Operand(kScratchRegister, 0), Immediate(value));
+    Operand counter_operand = ExternalOperand(ExternalReference(counter));
+    movq(counter_operand, Immediate(value));
   }
 }
 
@@ -1828,12 +2005,11 @@
 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
   ASSERT(value > 0);
   if (FLAG_native_code_counters && counter->Enabled()) {
-    movq(kScratchRegister, ExternalReference(counter));
-    Operand operand(kScratchRegister, 0);
+    Operand counter_operand = ExternalOperand(ExternalReference(counter));
     if (value == 1) {
-      incl(operand);
+      incl(counter_operand);
     } else {
-      addl(operand, Immediate(value));
+      addl(counter_operand, Immediate(value));
     }
   }
 }
@@ -1842,12 +2018,11 @@
 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
   ASSERT(value > 0);
   if (FLAG_native_code_counters && counter->Enabled()) {
-    movq(kScratchRegister, ExternalReference(counter));
-    Operand operand(kScratchRegister, 0);
+    Operand counter_operand = ExternalOperand(ExternalReference(counter));
     if (value == 1) {
-      decl(operand);
+      decl(counter_operand);
     } else {
-      subl(operand, Immediate(value));
+      subl(counter_operand, Immediate(value));
     }
   }
 }
@@ -1857,7 +2032,7 @@
 void MacroAssembler::DebugBreak() {
   ASSERT(allow_stub_calls());
   Set(rax, 0);  // No arguments.
-  movq(rbx, ExternalReference(Runtime::kDebugBreak));
+  LoadAddress(rbx, ExternalReference(Runtime::kDebugBreak, isolate()));
   CEntryStub ces(1);
   Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
 }
@@ -1868,7 +2043,7 @@
                                 const ParameterCount& expected,
                                 const ParameterCount& actual,
                                 InvokeFlag flag,
-                                PostCallGenerator* post_call_generator) {
+                                CallWrapper* call_wrapper) {
   NearLabel done;
   InvokePrologue(expected,
                  actual,
@@ -1876,10 +2051,11 @@
                  code,
                  &done,
                  flag,
-                 post_call_generator);
+                 call_wrapper);
   if (flag == CALL_FUNCTION) {
+    if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(code));
     call(code);
-    if (post_call_generator != NULL) post_call_generator->Generate();
+    if (call_wrapper != NULL) call_wrapper->AfterCall();
   } else {
     ASSERT(flag == JUMP_FUNCTION);
     jmp(code);
@@ -1893,7 +2069,7 @@
                                 const ParameterCount& actual,
                                 RelocInfo::Mode rmode,
                                 InvokeFlag flag,
-                                PostCallGenerator* post_call_generator) {
+                                CallWrapper* call_wrapper) {
   NearLabel done;
   Register dummy = rax;
   InvokePrologue(expected,
@@ -1902,10 +2078,11 @@
                  dummy,
                  &done,
                  flag,
-                 post_call_generator);
+                 call_wrapper);
   if (flag == CALL_FUNCTION) {
+    if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(code));
     Call(code, rmode);
-    if (post_call_generator != NULL) post_call_generator->Generate();
+    if (call_wrapper != NULL) call_wrapper->AfterCall();
   } else {
     ASSERT(flag == JUMP_FUNCTION);
     Jump(code, rmode);
@@ -1917,7 +2094,7 @@
 void MacroAssembler::InvokeFunction(Register function,
                                     const ParameterCount& actual,
                                     InvokeFlag flag,
-                                    PostCallGenerator* post_call_generator) {
+                                    CallWrapper* call_wrapper) {
   ASSERT(function.is(rdi));
   movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
   movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
@@ -1928,14 +2105,14 @@
   movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
 
   ParameterCount expected(rbx);
-  InvokeCode(rdx, expected, actual, flag, post_call_generator);
+  InvokeCode(rdx, expected, actual, flag, call_wrapper);
 }
 
 
 void MacroAssembler::InvokeFunction(JSFunction* function,
                                     const ParameterCount& actual,
                                     InvokeFlag flag,
-                                    PostCallGenerator* post_call_generator) {
+                                    CallWrapper* call_wrapper) {
   ASSERT(function->is_compiled());
   // Get the function and setup the context.
   Move(rdi, Handle<JSFunction>(function));
@@ -1946,7 +2123,7 @@
     // the Code object every time we call the function.
     movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
     ParameterCount expected(function->shared()->formal_parameter_count());
-    InvokeCode(rdx, expected, actual, flag, post_call_generator);
+    InvokeCode(rdx, expected, actual, flag, call_wrapper);
   } else {
     // Invoke the cached code.
     Handle<Code> code(function->code());
@@ -1956,7 +2133,7 @@
                actual,
                RelocInfo::CODE_TARGET,
                flag,
-               post_call_generator);
+               call_wrapper);
   }
 }
 
@@ -1968,9 +2145,9 @@
   Push(Smi::FromInt(type));
   movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
   push(kScratchRegister);
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     movq(kScratchRegister,
-         Factory::undefined_value(),
+         FACTORY->undefined_value(),
          RelocInfo::EMBEDDED_OBJECT);
     cmpq(Operand(rsp, 0), kScratchRegister);
     Check(not_equal, "code object not properly patched");
@@ -1979,7 +2156,7 @@
 
 
 void MacroAssembler::LeaveFrame(StackFrame::Type type) {
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     Move(kScratchRegister, Smi::FromInt(type));
     cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister);
     Check(equal, "stack frame types must match");
@@ -2005,16 +2182,12 @@
   push(kScratchRegister);  // Accessed from EditFrame::code_slot.
 
   // 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);
   if (save_rax) {
-    movq(r14, rax);  // Backup rax before we use it.
+    movq(r14, rax);  // Backup rax in callee-save register.
   }
 
-  movq(rax, rbp);
-  store_rax(c_entry_fp_address);
-  movq(rax, rsi);
-  store_rax(context_address);
+  Store(ExternalReference(Isolate::k_c_entry_fp_address, isolate()), rbp);
+  Store(ExternalReference(Isolate::k_context_address, isolate()), rsi);
 }
 
 
@@ -2040,7 +2213,7 @@
   }
 
   // Get the required frame alignment for the OS.
-  static const int kFrameAlignment = OS::ActivationFrameAlignment();
+  const int kFrameAlignment = OS::ActivationFrameAlignment();
   if (kFrameAlignment > 0) {
     ASSERT(IsPowerOf2(kFrameAlignment));
     movq(kScratchRegister, Immediate(-kFrameAlignment));
@@ -2055,10 +2228,10 @@
 void MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) {
   EnterExitFramePrologue(true);
 
-  // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
+  // Setup argv in callee-saved register r15. It is reused in LeaveExitFrame,
   // so it must be retained across the C-call.
   int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
-  lea(r12, Operand(rbp, r14, times_pointer_size, offset));
+  lea(r15, Operand(rbp, r14, times_pointer_size, offset));
 
   EnterExitFrameEpilogue(arg_stack_space, save_doubles);
 }
@@ -2072,7 +2245,7 @@
 
 void MacroAssembler::LeaveExitFrame(bool save_doubles) {
   // Registers:
-  // r12 : argv
+  // r15 : argv
   if (save_doubles) {
     int offset = -2 * kPointerSize;
     for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; i++) {
@@ -2086,7 +2259,7 @@
 
   // Drop everything up to and including the arguments and the receiver
   // from the caller stack.
-  lea(rsp, Operand(r12, 1 * kPointerSize));
+  lea(rsp, Operand(r15, 1 * kPointerSize));
 
   // Push the return address to get ready to return.
   push(rcx);
@@ -2105,17 +2278,18 @@
 
 void MacroAssembler::LeaveExitFrameEpilogue() {
   // Restore current context from top and clear it in debug mode.
-  ExternalReference context_address(Top::k_context_address);
-  movq(kScratchRegister, context_address);
-  movq(rsi, Operand(kScratchRegister, 0));
+  ExternalReference context_address(Isolate::k_context_address, isolate());
+  Operand context_operand = ExternalOperand(context_address);
+  movq(rsi, context_operand);
 #ifdef DEBUG
-  movq(Operand(kScratchRegister, 0), Immediate(0));
+  movq(context_operand, Immediate(0));
 #endif
 
   // Clear the top frame.
-  ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
-  movq(kScratchRegister, c_entry_fp_address);
-  movq(Operand(kScratchRegister, 0), Immediate(0));
+  ExternalReference c_entry_fp_address(Isolate::k_c_entry_fp_address,
+                                       isolate());
+  Operand c_entry_fp_operand = ExternalOperand(c_entry_fp_address);
+  movq(c_entry_fp_operand, Immediate(0));
 }
 
 
@@ -2130,7 +2304,7 @@
   movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset));
 
   // When generating debug code, make sure the lexical context is set.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     cmpq(scratch, Immediate(0));
     Check(not_equal, "we should not have an empty lexical context");
   }
@@ -2140,9 +2314,9 @@
   movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset));
 
   // Check the context is a global context.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     Cmp(FieldOperand(scratch, HeapObject::kMapOffset),
-        Factory::global_context_map());
+        FACTORY->global_context_map());
     Check(equal, "JSGlobalObject::global_context should be a global context.");
   }
 
@@ -2156,7 +2330,7 @@
   // object.
 
   // Check the context is a global context.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     // Preserve original value of holder_reg.
     push(holder_reg);
     movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
@@ -2186,7 +2360,7 @@
                                              Register scratch,
                                              AllocationFlags flags) {
   ExternalReference new_space_allocation_top =
-      ExternalReference::new_space_allocation_top_address();
+      ExternalReference::new_space_allocation_top_address(isolate());
 
   // Just return if allocation top is already known.
   if ((flags & RESULT_CONTAINS_TOP) != 0) {
@@ -2194,8 +2368,8 @@
     ASSERT(!scratch.is_valid());
 #ifdef DEBUG
     // Assert that result actually contains top on entry.
-    movq(kScratchRegister, new_space_allocation_top);
-    cmpq(result, Operand(kScratchRegister, 0));
+    Operand top_operand = ExternalOperand(new_space_allocation_top);
+    cmpq(result, top_operand);
     Check(equal, "Unexpected allocation top");
 #endif
     return;
@@ -2204,39 +2378,30 @@
   // Move address of new object to result. Use scratch register if available,
   // and keep address in scratch until call to UpdateAllocationTopHelper.
   if (scratch.is_valid()) {
-    movq(scratch, new_space_allocation_top);
+    LoadAddress(scratch, new_space_allocation_top);
     movq(result, Operand(scratch, 0));
-  } else if (result.is(rax)) {
-    load_rax(new_space_allocation_top);
   } else {
-    movq(kScratchRegister, new_space_allocation_top);
-    movq(result, Operand(kScratchRegister, 0));
+    Load(result, new_space_allocation_top);
   }
 }
 
 
 void MacroAssembler::UpdateAllocationTopHelper(Register result_end,
                                                Register scratch) {
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     testq(result_end, Immediate(kObjectAlignmentMask));
     Check(zero, "Unaligned allocation in new space");
   }
 
   ExternalReference new_space_allocation_top =
-      ExternalReference::new_space_allocation_top_address();
+      ExternalReference::new_space_allocation_top_address(isolate());
 
   // Update new top.
-  if (result_end.is(rax)) {
-    // rax can be stored directly to a memory location.
-    store_rax(new_space_allocation_top);
+  if (scratch.is_valid()) {
+    // Scratch already contains address of allocation top.
+    movq(Operand(scratch, 0), result_end);
   } else {
-    // Register required - use scratch provided if available.
-    if (scratch.is_valid()) {
-      movq(Operand(scratch, 0), result_end);
-    } else {
-      movq(kScratchRegister, new_space_allocation_top);
-      movq(Operand(kScratchRegister, 0), result_end);
-    }
+    Store(new_space_allocation_top, result_end);
   }
 }
 
@@ -2248,7 +2413,7 @@
                                         Label* gc_required,
                                         AllocationFlags flags) {
   if (!FLAG_inline_new) {
-    if (FLAG_debug_code) {
+    if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
       movl(result, Immediate(0x7091));
       if (result_end.is_valid()) {
@@ -2268,7 +2433,7 @@
 
   // Calculate new top and bail out if new space is exhausted.
   ExternalReference new_space_allocation_limit =
-      ExternalReference::new_space_allocation_limit_address();
+      ExternalReference::new_space_allocation_limit_address(isolate());
 
   Register top_reg = result_end.is_valid() ? result_end : result;
 
@@ -2277,8 +2442,8 @@
   }
   addq(top_reg, Immediate(object_size));
   j(carry, gc_required);
-  movq(kScratchRegister, new_space_allocation_limit);
-  cmpq(top_reg, Operand(kScratchRegister, 0));
+  Operand limit_operand = ExternalOperand(new_space_allocation_limit);
+  cmpq(top_reg, limit_operand);
   j(above, gc_required);
 
   // Update allocation top.
@@ -2306,7 +2471,7 @@
                                         Label* gc_required,
                                         AllocationFlags flags) {
   if (!FLAG_inline_new) {
-    if (FLAG_debug_code) {
+    if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
       movl(result, Immediate(0x7091));
       movl(result_end, Immediate(0x7191));
@@ -2325,15 +2490,15 @@
 
   // Calculate new top and bail out if new space is exhausted.
   ExternalReference new_space_allocation_limit =
-      ExternalReference::new_space_allocation_limit_address();
+      ExternalReference::new_space_allocation_limit_address(isolate());
 
   // We assume that element_count*element_size + header_size does not
   // overflow.
   lea(result_end, Operand(element_count, element_size, header_size));
   addq(result_end, result);
   j(carry, gc_required);
-  movq(kScratchRegister, new_space_allocation_limit);
-  cmpq(result_end, Operand(kScratchRegister, 0));
+  Operand limit_operand = ExternalOperand(new_space_allocation_limit);
+  cmpq(result_end, limit_operand);
   j(above, gc_required);
 
   // Update allocation top.
@@ -2353,7 +2518,7 @@
                                         Label* gc_required,
                                         AllocationFlags flags) {
   if (!FLAG_inline_new) {
-    if (FLAG_debug_code) {
+    if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
       movl(result, Immediate(0x7091));
       movl(result_end, Immediate(0x7191));
@@ -2372,14 +2537,14 @@
 
   // Calculate new top and bail out if new space is exhausted.
   ExternalReference new_space_allocation_limit =
-      ExternalReference::new_space_allocation_limit_address();
+      ExternalReference::new_space_allocation_limit_address(isolate());
   if (!object_size.is(result_end)) {
     movq(result_end, object_size);
   }
   addq(result_end, result);
   j(carry, gc_required);
-  movq(kScratchRegister, new_space_allocation_limit);
-  cmpq(result_end, Operand(kScratchRegister, 0));
+  Operand limit_operand = ExternalOperand(new_space_allocation_limit);
+  cmpq(result_end, limit_operand);
   j(above, gc_required);
 
   // Update allocation top.
@@ -2394,16 +2559,16 @@
 
 void MacroAssembler::UndoAllocationInNewSpace(Register object) {
   ExternalReference new_space_allocation_top =
-      ExternalReference::new_space_allocation_top_address();
+      ExternalReference::new_space_allocation_top_address(isolate());
 
   // Make sure the object has no tag before resetting top.
   and_(object, Immediate(~kHeapObjectTagMask));
-  movq(kScratchRegister, new_space_allocation_top);
+  Operand top_operand = ExternalOperand(new_space_allocation_top);
 #ifdef DEBUG
-  cmpq(object, Operand(kScratchRegister, 0));
+  cmpq(object, top_operand);
   Check(below, "Undo allocation of non allocated memory");
 #endif
-  movq(Operand(kScratchRegister, 0), object);
+  movq(top_operand, object);
 }
 
 
@@ -2537,6 +2702,70 @@
 }
 
 
+// Copy memory, byte-by-byte, from source to destination.  Not optimized for
+// long or aligned copies.  The contents of scratch and length are destroyed.
+// Destination is incremented by length, source, length and scratch are
+// clobbered.
+// A simpler loop is faster on small copies, but slower on large ones.
+// The cld() instruction must have been emitted, to set the direction flag(),
+// before calling this function.
+void MacroAssembler::CopyBytes(Register destination,
+                               Register source,
+                               Register length,
+                               int min_length,
+                               Register scratch) {
+  ASSERT(min_length >= 0);
+  if (FLAG_debug_code) {
+    cmpl(length, Immediate(min_length));
+    Assert(greater_equal, "Invalid min_length");
+  }
+  Label loop, done, short_string, short_loop;
+
+  const int kLongStringLimit = 20;
+  if (min_length <= kLongStringLimit) {
+    cmpl(length, Immediate(kLongStringLimit));
+    j(less_equal, &short_string);
+  }
+
+  ASSERT(source.is(rsi));
+  ASSERT(destination.is(rdi));
+  ASSERT(length.is(rcx));
+
+  // Because source is 8-byte aligned in our uses of this function,
+  // we keep source aligned for the rep movs operation by copying the odd bytes
+  // at the end of the ranges.
+  movq(scratch, length);
+  shrl(length, Immediate(3));
+  repmovsq();
+  // Move remaining bytes of length.
+  andl(scratch, Immediate(0x7));
+  movq(length, Operand(source, scratch, times_1, -8));
+  movq(Operand(destination, scratch, times_1, -8), length);
+  addq(destination, scratch);
+
+  if (min_length <= kLongStringLimit) {
+    jmp(&done);
+
+    bind(&short_string);
+    if (min_length == 0) {
+      testl(length, length);
+      j(zero, &done);
+    }
+    lea(scratch, Operand(destination, length, times_1, 0));
+
+    bind(&short_loop);
+    movb(length, Operand(source, 0));
+    movb(Operand(destination, 0), length);
+    incq(source);
+    incq(destination);
+    cmpq(destination, scratch);
+    j(not_equal, &short_loop);
+
+    bind(&done);
+  }
+}
+
+
 void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
   if (context_chain_length > 0) {
     // Move up the chain of contexts to the context containing the slot.
@@ -2560,13 +2789,18 @@
   // (i.e., the static scope chain and runtime context chain do not agree).
   // A variable occurring in such a scope should have slot type LOOKUP and
   // not CONTEXT.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     cmpq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
     Check(equal, "Yo dawg, I heard you liked function contexts "
                  "so I put function contexts in all your contexts");
   }
 }
 
+#ifdef _WIN64
+static const int kRegisterPassedArguments = 4;
+#else
+static const int kRegisterPassedArguments = 6;
+#endif
 
 void MacroAssembler::LoadGlobalFunction(int index, Register function) {
   // Load the global or builtins object from the current context.
@@ -2582,9 +2816,9 @@
                                                   Register map) {
   // Load the initial map.  The global functions all have initial maps.
   movq(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     Label ok, fail;
-    CheckMap(map, Factory::meta_map(), &fail, false);
+    CheckMap(map, FACTORY->meta_map(), &fail, false);
     jmp(&ok);
     bind(&fail);
     Abort("Global functions must have initial map");
@@ -2602,11 +2836,10 @@
   // and the caller does not reserve stack slots for them.
   ASSERT(num_arguments >= 0);
 #ifdef _WIN64
-  static const int kMinimumStackSlots = 4;
+  const int kMinimumStackSlots = kRegisterPassedArguments;
   if (num_arguments < kMinimumStackSlots) return kMinimumStackSlots;
   return num_arguments;
 #else
-  static const int kRegisterPassedArguments = 6;
   if (num_arguments < kRegisterPassedArguments) return 0;
   return num_arguments - kRegisterPassedArguments;
 #endif
@@ -2617,6 +2850,10 @@
   int frame_alignment = OS::ActivationFrameAlignment();
   ASSERT(frame_alignment != 0);
   ASSERT(num_arguments >= 0);
+
+  // Reserve space for Isolate address which is always passed as last parameter
+  num_arguments += 1;
+
   // Make stack end at alignment and allocate space for arguments and old rsp.
   movq(kScratchRegister, rsp);
   ASSERT(IsPowerOf2(frame_alignment));
@@ -2630,20 +2867,41 @@
 
 void MacroAssembler::CallCFunction(ExternalReference function,
                                    int num_arguments) {
-  movq(rax, function);
+  LoadAddress(rax, function);
   CallCFunction(rax, num_arguments);
 }
 
 
 void MacroAssembler::CallCFunction(Register function, int num_arguments) {
+  // Pass current isolate address as additional parameter.
+  if (num_arguments < kRegisterPassedArguments) {
+#ifdef _WIN64
+    // First four arguments are passed in registers on Windows.
+    Register arg_to_reg[] = {rcx, rdx, r8, r9};
+#else
+    // First six arguments are passed in registers on other platforms.
+    Register arg_to_reg[] = {rdi, rsi, rdx, rcx, r8, r9};
+#endif
+    Register reg = arg_to_reg[num_arguments];
+    LoadAddress(reg, ExternalReference::isolate_address());
+  } else {
+    // Push Isolate pointer after all parameters.
+    int argument_slots_on_stack =
+        ArgumentStackSlotsForCFunctionCall(num_arguments);
+    LoadAddress(kScratchRegister, ExternalReference::isolate_address());
+    movq(Operand(rsp, argument_slots_on_stack * kPointerSize),
+         kScratchRegister);
+  }
+
   // Check stack alignment.
-  if (FLAG_debug_code) {
+  if (emit_debug_code()) {
     CheckStackAlignment();
   }
 
   call(function);
   ASSERT(OS::ActivationFrameAlignment() != 0);
   ASSERT(num_arguments >= 0);
+  num_arguments += 1;
   int argument_slots_on_stack =
       ArgumentStackSlotsForCFunctionCall(num_arguments);
   movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize));
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index 7a7f1a2..1ee0fe0 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -48,7 +48,7 @@
 // a spare register). The register isn't callee save, and not used by the
 // function calling convention.
 static const Register kScratchRegister = { 10 };      // r10.
-static const Register kSmiConstantRegister = { 15 };  // r15 (callee save).
+static const Register kSmiConstantRegister = { 12 };  // r12 (callee save).
 static const Register kRootRegister = { 13 };         // r13 (callee save).
 // Value of smi in kSmiConstantRegister.
 static const int kSmiConstantRegisterValue = 1;
@@ -61,7 +61,7 @@
 
 // Forward declaration.
 class JumpTarget;
-class PostCallGenerator;
+class CallWrapper;
 
 struct SmiIndex {
   SmiIndex(Register index_register, ScaleFactor scale)
@@ -76,7 +76,49 @@
  public:
   MacroAssembler(void* buffer, int size);
 
+  // Prevent the use of the RootArray during the lifetime of this
+  // scope object.
+  class NoRootArrayScope BASE_EMBEDDED {
+   public:
+    explicit NoRootArrayScope(MacroAssembler* assembler)
+        : variable_(&assembler->root_array_available_),
+          old_value_(assembler->root_array_available_) {
+      assembler->root_array_available_ = false;
+    }
+    ~NoRootArrayScope() {
+      *variable_ = old_value_;
+    }
+   private:
+    bool* variable_;
+    bool old_value_;
+  };
+
+  // Operand pointing to an external reference.
+  // May emit code to set up the scratch register. The operand is
+  // only guaranteed to be correct as long as the scratch register
+  // isn't changed.
+  // If the operand is used more than once, use a scratch register
+  // that is guaranteed not to be clobbered.
+  Operand ExternalOperand(ExternalReference reference,
+                          Register scratch = kScratchRegister);
+  // Loads and stores the value of an external reference.
+  // Special case code for load and store to take advantage of
+  // load_rax/store_rax if possible/necessary.
+  // For other operations, just use:
+  //   Operand operand = ExternalOperand(extref);
+  //   operation(operand, ..);
+  void Load(Register destination, ExternalReference source);
+  void Store(ExternalReference destination, Register source);
+  // Loads the address of the external reference into the destination
+  // register.
+  void LoadAddress(Register destination, ExternalReference source);
+  // Returns the size of the code generated by LoadAddress.
+  // Used by CallSize(ExternalReference) to find the size of a call.
+  int LoadAddressSize(ExternalReference source);
+
+  // Operations on roots in the root-array.
   void LoadRoot(Register destination, Heap::RootListIndex index);
+  void StoreRoot(Register source, Heap::RootListIndex index);
   // Load a root value where the index (or part of it) is variable.
   // The variable_offset register is added to the fixed_offset value
   // to get the index into the root-array.
@@ -86,7 +128,6 @@
   void CompareRoot(Register with, Heap::RootListIndex index);
   void CompareRoot(const Operand& with, Heap::RootListIndex index);
   void PushRoot(Heap::RootListIndex index);
-  void StoreRoot(Register source, Heap::RootListIndex index);
 
   // ---------------------------------------------------------------------------
   // GC Support
@@ -186,7 +227,8 @@
   void LoadFromSafepointRegisterSlot(Register dst, Register src);
 
   void InitializeRootRegister() {
-    ExternalReference roots_address = ExternalReference::roots_address();
+    ExternalReference roots_address =
+        ExternalReference::roots_address(isolate());
     movq(kRootRegister, roots_address);
     addq(kRootRegister, Immediate(kRootRegisterBias));
   }
@@ -199,32 +241,32 @@
                   const ParameterCount& expected,
                   const ParameterCount& actual,
                   InvokeFlag flag,
-                  PostCallGenerator* post_call_generator = NULL);
+                  CallWrapper* call_wrapper = NULL);
 
   void InvokeCode(Handle<Code> code,
                   const ParameterCount& expected,
                   const ParameterCount& actual,
                   RelocInfo::Mode rmode,
                   InvokeFlag flag,
-                  PostCallGenerator* post_call_generator = NULL);
+                  CallWrapper* call_wrapper = NULL);
 
   // 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,
-                      PostCallGenerator* post_call_generator = NULL);
+                      CallWrapper* call_wrapper = NULL);
 
   void InvokeFunction(JSFunction* function,
                       const ParameterCount& actual,
                       InvokeFlag flag,
-                      PostCallGenerator* post_call_generator = NULL);
+                      CallWrapper* call_wrapper = NULL);
 
   // 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,
-                     PostCallGenerator* post_call_generator = NULL);
+                     CallWrapper* call_wrapper = NULL);
 
   // Store the function for the given builtin in the target register.
   void GetBuiltinFunction(Register target, Builtins::JavaScript id);
@@ -278,8 +320,9 @@
                                            int power);
 
 
-  // Simple comparison of smis.
-  void SmiCompare(Register dst, Register src);
+  // Simple comparison of smis.  Both sides must be known smis to use these,
+  // otherwise use Cmp.
+  void SmiCompare(Register smi1, Register smi2);
   void SmiCompare(Register dst, Smi* src);
   void SmiCompare(Register dst, const Operand& src);
   void SmiCompare(const Operand& dst, Register src);
@@ -427,6 +470,11 @@
               Register src1,
               Register src2,
               LabelType* on_not_smi_result);
+  template <typename LabelType>
+  void SmiAdd(Register dst,
+              Register src1,
+              const Operand& src2,
+              LabelType* on_not_smi_result);
 
   void SmiAdd(Register dst,
               Register src1,
@@ -547,6 +595,10 @@
   // Converts a positive smi to a negative index.
   SmiIndex SmiToNegativeIndex(Register dst, Register src, int shift);
 
+  // Add the value of a smi in memory to an int32 register.
+  // Sets flags as a normal add.
+  void AddSmiField(Register dst, const Operand& src);
+
   // Basic Smi operations.
   void Move(Register dst, Smi* source) {
     LoadSmiConstant(dst, source);
@@ -609,6 +661,8 @@
   void Move(const Operand& dst, Handle<Object> source);
   void Cmp(Register dst, Handle<Object> source);
   void Cmp(const Operand& dst, Handle<Object> source);
+  void Cmp(Register dst, Smi* src);
+  void Cmp(const Operand& dst, Smi* src);
   void Push(Handle<Object> source);
 
   // Emit code to discard a non-negative number of pointer-sized elements
@@ -626,6 +680,24 @@
   void Call(ExternalReference ext);
   void Call(Handle<Code> code_object, RelocInfo::Mode rmode);
 
+  // The size of the code generated for different call instructions.
+  int CallSize(Address destination, RelocInfo::Mode rmode) {
+    return kCallInstructionLength;
+  }
+  int CallSize(ExternalReference ext);
+  int CallSize(Handle<Code> code_object) {
+    // Code calls use 32-bit relative addressing.
+    return kShortCallInstructionLength;
+  }
+  int CallSize(Register target) {
+    // Opcode: REX_opt FF /2 m64
+    return (target.high_bit() != 0) ? 3 : 2;
+  }
+  int CallSize(const Operand& target) {
+    // Opcode: REX_opt FF /2 m64
+    return (target.requires_rex() ? 2 : 1) + target.operand_size();
+  }
+
   // Emit call to the code we are currently generating.
   void CallSelf() {
     Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location()));
@@ -682,6 +754,7 @@
 
   // Abort execution if argument is not a smi. Used in debug code.
   void AbortIfNotSmi(Register object);
+  void AbortIfNotSmi(const Operand& object);
 
   // Abort execution if argument is a string. Used in debug code.
   void AbortIfNotString(Register object);
@@ -864,7 +937,7 @@
   void StubReturn(int argc);
 
   // Call a runtime routine.
-  void CallRuntime(Runtime::Function* f, int num_arguments);
+  void CallRuntime(const Runtime::Function* f, int num_arguments);
 
   // Call a runtime function and save the value of XMM registers.
   void CallRuntimeSaveDoubles(Runtime::FunctionId id);
@@ -872,7 +945,7 @@
   // Call a runtime function, returning the CodeStub object called.
   // Try to generate the stub code if necessary.  Do not perform a GC
   // but instead return a retry after GC failure.
-  MUST_USE_RESULT MaybeObject* TryCallRuntime(Runtime::Function* f,
+  MUST_USE_RESULT MaybeObject* TryCallRuntime(const Runtime::Function* f,
                                               int num_arguments);
 
   // Convenience function: Same as above, but takes the fid instead.
@@ -921,7 +994,7 @@
 
   // Calls an API function. Allocates HandleScope, extracts
   // returned value from handle and propagates exceptions.
-  // Clobbers r12, r14, rbx and caller-save registers. Restores context.
+  // Clobbers r14, r15, rbx and caller-save registers. Restores context.
   // On return removes stack_space * kPointerSize (GCed).
   MUST_USE_RESULT MaybeObject* TryCallApiFunctionAndReturn(
       ApiFunction* function, int stack_space);
@@ -958,6 +1031,18 @@
 
   Handle<Object> CodeObject() { return code_object_; }
 
+  // Copy length bytes from source to destination.
+  // Uses scratch register internally (if you have a low-eight register
+  // free, do use it, otherwise kScratchRegister will be used).
+  // The min_length is a minimum limit on the value that length will have.
+  // The algorithm has some special cases that might be omitted if the string
+  // is known to always be long.
+  void CopyBytes(Register destination,
+                 Register source,
+                 Register length,
+                 int min_length = 0,
+                 Register scratch = kScratchRegister);
+
 
   // ---------------------------------------------------------------------------
   // StatsCounter support
@@ -993,12 +1078,13 @@
 
  private:
   // Order general registers are pushed by Pushad.
-  // rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r12, r14.
+  // rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15.
   static int kSafepointPushRegisterIndices[Register::kNumRegisters];
   static const int kNumSafepointSavedRegisters = 11;
 
   bool generating_stub_;
   bool allow_stub_calls_;
+  bool root_array_available_;
 
   // Returns a register holding the smi value. The register MUST NOT be
   // modified. It may be the "smi 1 constant" register.
@@ -1018,7 +1104,7 @@
                       Register code_register,
                       LabelType* done,
                       InvokeFlag flag,
-                      PostCallGenerator* post_call_generator);
+                      CallWrapper* call_wrapper);
 
   // Activation support.
   void EnterFrame(StackFrame::Type type);
@@ -1084,13 +1170,17 @@
 
 
 // Helper class for generating code or data associated with the code
-// right after a call instruction. As an example this can be used to
+// right before or after a call instruction. As an example this can be used to
 // generate safepoint data after calls for crankshaft.
-class PostCallGenerator {
+class CallWrapper {
  public:
-  PostCallGenerator() { }
-  virtual ~PostCallGenerator() { }
-  virtual void Generate() = 0;
+  CallWrapper() { }
+  virtual ~CallWrapper() { }
+  // Called just before emitting a call. Argument is the size of the generated
+  // call code.
+  virtual void BeforeCall(int call_size) = 0;
+  // Called just after emitting a call, i.e., at the return site for the call.
+  virtual void AfterCall() = 0;
 };
 
 
@@ -1204,6 +1294,26 @@
 
 
 template <typename LabelType>
+void MacroAssembler::SmiAdd(Register dst,
+                            Register src1,
+                            const Operand& src2,
+                            LabelType* on_not_smi_result) {
+  ASSERT_NOT_NULL(on_not_smi_result);
+  if (dst.is(src1)) {
+    movq(kScratchRegister, src1);
+    addq(kScratchRegister, src2);
+    j(overflow, on_not_smi_result);
+    movq(dst, kScratchRegister);
+  } else {
+    ASSERT(!src2.AddressUsesRegister(dst));
+    movq(dst, src1);
+    addq(dst, src2);
+    j(overflow, on_not_smi_result);
+  }
+}
+
+
+template <typename LabelType>
 void MacroAssembler::SmiSub(Register dst,
                             Register src1,
                             Register src2,
@@ -1769,26 +1879,26 @@
     // case the size of the new space is different between the snapshot maker
     // and the running system.
     if (scratch.is(object)) {
-      movq(kScratchRegister, ExternalReference::new_space_mask());
+      movq(kScratchRegister, ExternalReference::new_space_mask(isolate()));
       and_(scratch, kScratchRegister);
     } else {
-      movq(scratch, ExternalReference::new_space_mask());
+      movq(scratch, ExternalReference::new_space_mask(isolate()));
       and_(scratch, object);
     }
-    movq(kScratchRegister, ExternalReference::new_space_start());
+    movq(kScratchRegister, ExternalReference::new_space_start(isolate()));
     cmpq(scratch, kScratchRegister);
     j(cc, branch);
   } else {
-    ASSERT(is_int32(static_cast<int64_t>(Heap::NewSpaceMask())));
+    ASSERT(is_int32(static_cast<int64_t>(HEAP->NewSpaceMask())));
     intptr_t new_space_start =
-        reinterpret_cast<intptr_t>(Heap::NewSpaceStart());
+        reinterpret_cast<intptr_t>(HEAP->NewSpaceStart());
     movq(kScratchRegister, -new_space_start, RelocInfo::NONE);
     if (scratch.is(object)) {
       addq(scratch, kScratchRegister);
     } else {
       lea(scratch, Operand(object, kScratchRegister, times_1, 0));
     }
-    and_(scratch, Immediate(static_cast<int32_t>(Heap::NewSpaceMask())));
+    and_(scratch, Immediate(static_cast<int32_t>(HEAP->NewSpaceMask())));
     j(cc, branch);
   }
 }
@@ -1801,7 +1911,7 @@
                                     Register code_register,
                                     LabelType* done,
                                     InvokeFlag flag,
-                                    PostCallGenerator* post_call_generator) {
+                                    CallWrapper* call_wrapper) {
   bool definitely_matches = false;
   NearLabel invoke;
   if (expected.is_immediate()) {
@@ -1841,8 +1951,7 @@
   }
 
   if (!definitely_matches) {
-    Handle<Code> adaptor =
-        Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
+    Handle<Code> adaptor = isolate()->builtins()->ArgumentsAdaptorTrampoline();
     if (!code_constant.is_null()) {
       movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT);
       addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag));
@@ -1851,8 +1960,9 @@
     }
 
     if (flag == CALL_FUNCTION) {
+      if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(adaptor));
       Call(adaptor, RelocInfo::CODE_TARGET);
-      if (post_call_generator != NULL) post_call_generator->Generate();
+      if (call_wrapper != NULL) call_wrapper->AfterCall();
       jmp(done);
     } else {
       Jump(adaptor, RelocInfo::CODE_TARGET);
diff --git a/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc
index cd3bfbd..269e7af 100644
--- a/src/x64/regexp-macro-assembler-x64.cc
+++ b/src/x64/regexp-macro-assembler-x64.cc
@@ -63,11 +63,16 @@
  *
  * The registers rax, rbx, r9 and r11 are free to use for computations.
  * If changed to use r12+, they should be saved as callee-save registers.
+ * The macro assembler special registers r12 and r13 (kSmiConstantRegister,
+ * kRootRegister) aren't special during execution of RegExp code (they don't
+ * hold the values assumed when creating JS code), so no Smi or Root related
+ * macro operations can be used.
  *
  * Each call to a C++ method should retain these registers.
  *
  * The stack will have the following content, in some order, indexable from the
  * frame pointer (see, e.g., kStackHighEnd):
+ *    - Isolate* isolate     (Address of the current isolate)
  *    - direct_call          (if 1, direct call from JavaScript code, if 0 call
  *                            through the runtime system)
  *    - stack_area_base      (High end of the memory area to use as
@@ -104,12 +109,13 @@
  *              bool direct_call)
  */
 
-#define __ ACCESS_MASM(masm_)
+#define __ ACCESS_MASM((&masm_))
 
 RegExpMacroAssemblerX64::RegExpMacroAssemblerX64(
     Mode mode,
     int registers_to_save)
-    : masm_(new MacroAssembler(NULL, kRegExpCodeSize)),
+    : masm_(NULL, kRegExpCodeSize),
+      no_root_array_scope_(&masm_),
       code_relative_fixup_positions_(4),
       mode_(mode),
       num_registers_(registers_to_save),
@@ -126,7 +132,6 @@
 
 
 RegExpMacroAssemblerX64::~RegExpMacroAssemblerX64() {
-  delete masm_;
   // Unuse labels in case we throw away the assembler without calling GetCode.
   entry_label_.Unuse();
   start_label_.Unuse();
@@ -422,11 +427,11 @@
     __ movq(rdx, rbx);
 #endif
     ExternalReference compare =
-        ExternalReference::re_case_insensitive_compare_uc16();
+        ExternalReference::re_case_insensitive_compare_uc16(masm_.isolate());
     __ CallCFunction(compare, num_arguments);
 
     // Restore original values before reacting on result value.
-    __ Move(code_object_pointer(), masm_->CodeObject());
+    __ Move(code_object_pointer(), masm_.CodeObject());
     __ pop(backtrack_stackpointer());
 #ifndef _WIN64
     __ pop(rdi);
@@ -740,7 +745,7 @@
   Label stack_ok;
 
   ExternalReference stack_limit =
-      ExternalReference::address_of_stack_limit();
+      ExternalReference::address_of_stack_limit(masm_.isolate());
   __ movq(rcx, rsp);
   __ movq(kScratchRegister, stack_limit);
   __ subq(rcx, Operand(kScratchRegister, 0));
@@ -756,7 +761,7 @@
   __ jmp(&exit_label_);
 
   __ bind(&stack_limit_hit);
-  __ Move(code_object_pointer(), masm_->CodeObject());
+  __ Move(code_object_pointer(), masm_.CodeObject());
   CallCheckStackGuardState();  // Preserves no registers beside rbp and rsp.
   __ testq(rax, rax);
   // If returned value is non-zero, we exit with the returned value as result.
@@ -811,7 +816,7 @@
   // Initialize backtrack stack pointer.
   __ movq(backtrack_stackpointer(), Operand(rbp, kStackHighEnd));
   // Initialize code object pointer.
-  __ Move(code_object_pointer(), masm_->CodeObject());
+  __ Move(code_object_pointer(), masm_.CodeObject());
   // Load previous char as initial value of current-character.
   Label at_start;
   __ cmpb(Operand(rbp, kStartIndex), Immediate(0));
@@ -892,7 +897,7 @@
     __ j(not_zero, &exit_label_);
 
     // Restore registers.
-    __ Move(code_object_pointer(), masm_->CodeObject());
+    __ Move(code_object_pointer(), masm_.CodeObject());
     __ pop(rdi);
     __ pop(backtrack_stackpointer());
     // String might have moved: Reload esi from frame.
@@ -925,7 +930,8 @@
     __ movq(rdi, backtrack_stackpointer());   // First argument.
     __ lea(rsi, Operand(rbp, kStackHighEnd));  // Second argument.
 #endif
-    ExternalReference grow_stack = ExternalReference::re_grow_stack();
+    ExternalReference grow_stack =
+        ExternalReference::re_grow_stack(masm_.isolate());
     __ CallCFunction(grow_stack, num_arguments);
     // If return NULL, we have failed to grow the stack, and
     // must exit with a stack-overflow exception.
@@ -934,7 +940,7 @@
     // Otherwise use return value as new stack pointer.
     __ movq(backtrack_stackpointer(), rax);
     // Restore saved registers and continue.
-    __ Move(code_object_pointer(), masm_->CodeObject());
+    __ Move(code_object_pointer(), masm_.CodeObject());
 #ifndef _WIN64
     __ pop(rdi);
     __ pop(rsi);
@@ -953,11 +959,12 @@
   FixupCodeRelativePositions();
 
   CodeDesc code_desc;
-  masm_->GetCode(&code_desc);
-  Handle<Code> code = Factory::NewCode(code_desc,
-                                       Code::ComputeFlags(Code::REGEXP),
-                                       masm_->CodeObject());
-  PROFILE(RegExpCodeCreateEvent(*code, *source));
+  masm_.GetCode(&code_desc);
+  Isolate* isolate = ISOLATE;
+  Handle<Code> code = isolate->factory()->NewCode(
+      code_desc, Code::ComputeFlags(Code::REGEXP),
+      masm_.CodeObject());
+  PROFILE(isolate, RegExpCodeCreateEvent(*code, *source));
   return Handle<Object>::cast(code);
 }
 
@@ -1126,7 +1133,7 @@
   __ lea(rdi, Operand(rsp, -kPointerSize));
 #endif
   ExternalReference stack_check =
-      ExternalReference::re_check_stack_guard_state();
+      ExternalReference::re_check_stack_guard_state(masm_.isolate());
   __ CallCFunction(stack_check, num_arguments);
 }
 
@@ -1141,8 +1148,10 @@
 int RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address,
                                                   Code* re_code,
                                                   Address re_frame) {
-  if (StackGuard::IsStackOverflow()) {
-    Top::StackOverflow();
+  Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
+  ASSERT(isolate == Isolate::Current());
+  if (isolate->stack_guard()->IsStackOverflow()) {
+    isolate->StackOverflow();
     return EXCEPTION;
   }
 
@@ -1289,8 +1298,8 @@
     // Patch the relative offset to be relative to the Code object pointer
     // instead.
     int patch_position = position - kIntSize;
-    int offset = masm_->long_at(patch_position);
-    masm_->long_at_put(patch_position,
+    int offset = masm_.long_at(patch_position);
+    masm_.long_at_put(patch_position,
                        offset
                        + position
                        + Code::kHeaderSize
@@ -1324,7 +1333,7 @@
   // Check for preemption.
   Label no_preempt;
   ExternalReference stack_limit =
-      ExternalReference::address_of_stack_limit();
+      ExternalReference::address_of_stack_limit(masm_.isolate());
   __ load_rax(stack_limit);
   __ cmpq(rsp, rax);
   __ j(above, &no_preempt);
@@ -1338,7 +1347,7 @@
 void RegExpMacroAssemblerX64::CheckStackLimit() {
   Label no_stack_overflow;
   ExternalReference stack_limit =
-      ExternalReference::address_of_regexp_stack_limit();
+      ExternalReference::address_of_regexp_stack_limit(masm_.isolate());
   __ load_rax(stack_limit);
   __ cmpq(backtrack_stackpointer(), rax);
   __ j(above, &no_stack_overflow);
diff --git a/src/x64/regexp-macro-assembler-x64.h b/src/x64/regexp-macro-assembler-x64.h
index 421a229..a83f8cb 100644
--- a/src/x64/regexp-macro-assembler-x64.h
+++ b/src/x64/regexp-macro-assembler-x64.h
@@ -104,7 +104,8 @@
                       Handle<String> subject,
                       int* offsets_vector,
                       int offsets_vector_length,
-                      int previous_index);
+                      int previous_index,
+                      Isolate* isolate);
 
   static Result Execute(Code* code,
                         String* input,
@@ -142,6 +143,7 @@
   static const int kStackHighEnd = kRegisterOutput + kPointerSize;
   // DirectCall is passed as 32 bit int (values 0 or 1).
   static const int kDirectCall = kStackHighEnd + kPointerSize;
+  static const int kIsolate = kDirectCall + kPointerSize;
 #else
   // In AMD64 ABI Calling Convention, the first six integer parameters
   // are passed as registers, and caller must allocate space on the stack
@@ -153,6 +155,7 @@
   static const int kRegisterOutput = kInputEnd - kPointerSize;
   static const int kStackHighEnd = kRegisterOutput - kPointerSize;
   static const int kDirectCall = kFrameAlign;
+  static const int kIsolate = kDirectCall + kPointerSize;
 #endif
 
 #ifdef _WIN64
@@ -215,7 +218,7 @@
   void BranchOrBacktrack(Condition condition, Label* to);
 
   void MarkPositionForCodeRelativeFixup() {
-    code_relative_fixup_positions_.Add(masm_->pc_offset());
+    code_relative_fixup_positions_.Add(masm_.pc_offset());
   }
 
   void FixupCodeRelativePositions();
@@ -247,7 +250,8 @@
   // Increments the stack pointer (rcx) by a word size.
   inline void Drop();
 
-  MacroAssembler* masm_;
+  MacroAssembler masm_;
+  MacroAssembler::NoRootArrayScope no_root_array_scope_;
 
   ZoneList<int> code_relative_fixup_positions_;
 
diff --git a/src/x64/register-allocator-x64-inl.h b/src/x64/register-allocator-x64-inl.h
index c6bea3a..5df3d54 100644
--- a/src/x64/register-allocator-x64-inl.h
+++ b/src/x64/register-allocator-x64-inl.h
@@ -60,10 +60,10 @@
     6,   // r9
     -1,  // r10  Scratch register.
     8,   // r11
-    9,   // r12
+    -1,  // r12  Smi constant.
     -1,  // r13  Roots array.  This is callee saved.
     7,   // r14
-    -1   // r15  Smi constant register.
+    9    // r15
   };
   return kNumbers[reg.code()];
 }
@@ -72,7 +72,7 @@
 Register RegisterAllocator::ToRegister(int num) {
   ASSERT(num >= 0 && num < kNumRegisters);
   const Register kRegisters[] =
-      { rax, rbx, rcx, rdx, rdi, r8, r9, r14, r11, r12 };
+      { rax, rbx, rcx, rdx, rdi, r8, r9, r14, r11, r15 };
   return kRegisters[num];
 }
 
diff --git a/src/x64/register-allocator-x64.cc b/src/x64/register-allocator-x64.cc
index 1f5467e..65189f5 100644
--- a/src/x64/register-allocator-x64.cc
+++ b/src/x64/register-allocator-x64.cc
@@ -42,9 +42,11 @@
 void Result::ToRegister() {
   ASSERT(is_valid());
   if (is_constant()) {
-    Result fresh = CodeGeneratorScope::Current()->allocator()->Allocate();
+    CodeGenerator* code_generator =
+        CodeGeneratorScope::Current(Isolate::Current());
+    Result fresh = code_generator->allocator()->Allocate();
     ASSERT(fresh.is_valid());
-    CodeGeneratorScope::Current()->masm()->Move(fresh.reg(), handle());
+    code_generator->masm()->Move(fresh.reg(), handle());
     // This result becomes a copy of the fresh one.
     fresh.set_type_info(type_info());
     *this = fresh;
@@ -55,21 +57,23 @@
 
 void Result::ToRegister(Register target) {
   ASSERT(is_valid());
+  CodeGenerator* code_generator =
+      CodeGeneratorScope::Current(Isolate::Current());
   if (!is_register() || !reg().is(target)) {
-    Result fresh = CodeGeneratorScope::Current()->allocator()->Allocate(target);
+    Result fresh = code_generator->allocator()->Allocate(target);
     ASSERT(fresh.is_valid());
     if (is_register()) {
-      CodeGeneratorScope::Current()->masm()->movq(fresh.reg(), reg());
+      code_generator->masm()->movq(fresh.reg(), reg());
     } else {
       ASSERT(is_constant());
-      CodeGeneratorScope::Current()->masm()->Move(fresh.reg(), handle());
+      code_generator->masm()->Move(fresh.reg(), handle());
     }
     fresh.set_type_info(type_info());
     *this = fresh;
   } else if (is_register() && reg().is(target)) {
-    ASSERT(CodeGeneratorScope::Current()->has_valid_frame());
-    CodeGeneratorScope::Current()->frame()->Spill(target);
-    ASSERT(CodeGeneratorScope::Current()->allocator()->count(target) == 1);
+    ASSERT(code_generator->has_valid_frame());
+    code_generator->frame()->Spill(target);
+    ASSERT(code_generator->allocator()->count(target) == 1);
   }
   ASSERT(is_register());
   ASSERT(reg().is(target));
diff --git a/src/x64/simulator-x64.h b/src/x64/simulator-x64.h
index aa2994f..cfaa5b8 100644
--- a/src/x64/simulator-x64.h
+++ b/src/x64/simulator-x64.h
@@ -40,12 +40,12 @@
   (entry(p0, p1, p2, p3, p4))
 
 typedef int (*regexp_matcher)(String*, int, const byte*,
-                              const byte*, int*, Address, int);
+                              const byte*, int*, Address, int, Isolate*);
 
 // Call the generated regexp code directly. The code at the entry address should
-// expect seven int/pointer sized arguments and return an int.
-#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
-  (FUNCTION_CAST<regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6))
+// expect eight int/pointer sized arguments and return an int.
+#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
+  (FUNCTION_CAST<regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7))
 
 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
   (reinterpret_cast<TryCatch*>(try_catch_address))
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 109985c..7494fe0 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -39,7 +39,8 @@
 #define __ ACCESS_MASM(masm)
 
 
-static void ProbeTable(MacroAssembler* masm,
+static void ProbeTable(Isolate* isolate,
+                       MacroAssembler* masm,
                        Code::Flags flags,
                        StubCache::Table table,
                        Register name,
@@ -48,10 +49,10 @@
   ASSERT_EQ(16, sizeof(StubCache::Entry));
   // The offset register holds the entry offset times four (due to masking
   // and shifting optimizations).
-  ExternalReference key_offset(SCTableReference::keyReference(table));
+  ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
   Label miss;
 
-  __ movq(kScratchRegister, key_offset);
+  __ LoadAddress(kScratchRegister, key_offset);
   // Check that the key in the entry matches the name.
   // Multiply entry offset by 16 to get the entry address. Since the
   // offset register already holds the entry offset times four, multiply
@@ -88,8 +89,9 @@
                                              Register r0,
                                              Register r1) {
   ASSERT(name->IsSymbol());
-  __ IncrementCounter(&Counters::negative_lookups, 1);
-  __ IncrementCounter(&Counters::negative_lookups_miss, 1);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->negative_lookups(), 1);
+  __ IncrementCounter(counters->negative_lookups_miss(), 1);
 
   Label done;
   __ movq(r0, FieldOperand(receiver, HeapObject::kMapOffset));
@@ -151,7 +153,7 @@
     ASSERT_EQ(kSmiTagSize, 1);
     __ movq(entity_name, Operand(properties, index, times_pointer_size,
                                  kElementsStartOffset - kHeapObjectTag));
-    __ Cmp(entity_name, Factory::undefined_value());
+    __ Cmp(entity_name, masm->isolate()->factory()->undefined_value());
     // __ jmp(miss_label);
     if (i != kProbes - 1) {
       __ j(equal, &done);
@@ -172,7 +174,7 @@
   }
 
   __ bind(&done);
-  __ DecrementCounter(&Counters::negative_lookups_miss, 1);
+  __ DecrementCounter(counters->negative_lookups_miss(), 1);
 }
 
 
@@ -183,6 +185,7 @@
                               Register scratch,
                               Register extra,
                               Register extra2) {
+  Isolate* isolate = masm->isolate();
   Label miss;
   USE(extra);   // The register extra is not used on the X64 platform.
   USE(extra2);  // The register extra2 is not used on the X64 platform.
@@ -212,7 +215,7 @@
   __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
 
   // Probe the primary table.
-  ProbeTable(masm, flags, kPrimary, name, scratch);
+  ProbeTable(isolate, masm, flags, kPrimary, name, scratch);
 
   // Primary miss: Compute hash for secondary probe.
   __ movl(scratch, FieldOperand(name, String::kHashFieldOffset));
@@ -224,7 +227,7 @@
   __ and_(scratch, Immediate((kSecondaryTableSize - 1) << kHeapObjectTagSize));
 
   // Probe the secondary table.
-  ProbeTable(masm, flags, kSecondary, name, scratch);
+  ProbeTable(isolate, masm, flags, kSecondary, name, scratch);
 
   // Cache miss: Fall-through and let caller handle the miss by
   // entering the runtime system.
@@ -253,13 +256,15 @@
 
 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
     MacroAssembler* masm, int index, Register prototype, Label* miss) {
+  Isolate* isolate = masm->isolate();
   // Check we're still in the same context.
-  __ Move(prototype, Top::global());
+  __ Move(prototype, isolate->global());
   __ cmpq(Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)),
           prototype);
   __ j(not_equal, miss);
   // Get the global function with the given index.
-  JSFunction* function = JSFunction::cast(Top::global_context()->get(index));
+  JSFunction* function =
+      JSFunction::cast(isolate->global_context()->get(index));
   // Load its initial map. The global functions all have initial maps.
   __ Move(prototype, Handle<Map>(function->initial_map()));
   // Load the prototype from the initial map.
@@ -375,7 +380,7 @@
                                      JSObject* holder_obj) {
   __ push(name);
   InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
-  ASSERT(!Heap::InNewSpace(interceptor));
+  ASSERT(!masm->isolate()->heap()->InNewSpace(interceptor));
   __ Move(kScratchRegister, Handle<Object>(interceptor));
   __ push(kScratchRegister);
   __ push(receiver);
@@ -392,9 +397,10 @@
   PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
 
   ExternalReference ref =
-      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly));
+      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
+                        masm->isolate());
   __ movq(rax, Immediate(5));
-  __ movq(rbx, ref);
+  __ LoadAddress(rbx, ref);
 
   CEntryStub stub(1);
   __ CallStub(&stub);
@@ -466,7 +472,7 @@
   __ movq(Operand(rsp, 2 * kPointerSize), rdi);
   Object* call_data = optimization.api_call_info()->data();
   Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info());
-  if (Heap::InNewSpace(call_data)) {
+  if (masm->isolate()->heap()->InNewSpace(call_data)) {
     __ Move(rcx, api_call_info_handle);
     __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
     __ movq(Operand(rsp, 3 * kPointerSize), rbx);
@@ -561,7 +567,7 @@
                      name,
                      holder,
                      miss);
-      return Heap::undefined_value();  // Success.
+      return masm->isolate()->heap()->undefined_value();  // Success.
     }
   }
 
@@ -597,10 +603,11 @@
                              (depth2 != kInvalidProtoDepth);
     }
 
-    __ IncrementCounter(&Counters::call_const_interceptor, 1);
+    Counters* counters = masm->isolate()->counters();
+    __ IncrementCounter(counters->call_const_interceptor(), 1);
 
     if (can_do_fast_api_call) {
-      __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1);
+      __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1);
       ReserveSpaceForFastApiCall(masm, scratch1);
     }
 
@@ -660,7 +667,7 @@
       FreeSpaceForFastApiCall(masm, scratch1);
     }
 
-    return Heap::undefined_value();  // Success.
+    return masm->isolate()->heap()->undefined_value();  // Success.
   }
 
   void CompileRegular(MacroAssembler* masm,
@@ -688,7 +695,8 @@
                              interceptor_holder);
 
     __ CallExternalReference(
-        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall)),
+        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
+                          masm->isolate()),
         5);
 
     // Restore the name_ register.
@@ -729,9 +737,9 @@
   ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
   Code* code = NULL;
   if (kind == Code::LOAD_IC) {
-    code = Builtins::builtin(Builtins::LoadIC_Miss);
+    code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss);
   } else {
-    code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
+    code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss);
   }
 
   Handle<Code> ic(code);
@@ -776,7 +784,10 @@
     __ push(rax);
     __ push(scratch);
     __ TailCallExternalReference(
-        ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage)), 3, 1);
+        ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
+                          masm->isolate()),
+        3,
+        1);
     return;
   }
 
@@ -836,7 +847,7 @@
   ASSERT(cell->value()->IsTheHole());
   __ Move(scratch, Handle<Object>(cell));
   __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
-         Factory::the_hole_value());
+         masm->isolate()->factory()->the_hole_value());
   __ j(not_equal, miss);
   return cell;
 }
@@ -885,7 +896,7 @@
         !current->IsJSGlobalObject() &&
         !current->IsJSGlobalProxy()) {
       if (!name->IsSymbol()) {
-        MaybeObject* lookup_result = Heap::LookupSymbol(name);
+        MaybeObject* lookup_result = heap()->LookupSymbol(name);
         if (lookup_result->IsFailure()) {
           set_failure(Failure::cast(lookup_result));
           return reg;
@@ -905,7 +916,7 @@
       __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
       reg = holder_reg;  // from now the object is in holder_reg
       __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
-    } else if (Heap::InNewSpace(prototype)) {
+    } else if (heap()->InNewSpace(prototype)) {
       // Get the map of the current object.
       __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
       __ Cmp(scratch1, Handle<Map>(current->map()));
@@ -956,7 +967,7 @@
   __ j(not_equal, miss);
 
   // Log the check depth.
-  LOG(IntEvent("check-maps-depth", depth + 1));
+  LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
 
   // Perform security check for access to the global object and return
   // the holder register.
@@ -1039,7 +1050,7 @@
 
   __ push(receiver);  // receiver
   __ push(reg);  // holder
-  if (Heap::InNewSpace(callback_handle->data())) {
+  if (heap()->InNewSpace(callback_handle->data())) {
     __ Move(scratch1, callback_handle);
     __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset));  // data
   } else {
@@ -1230,7 +1241,8 @@
       __ push(scratch2);  // restore return address
 
       ExternalReference ref =
-          ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
+          ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
+                            isolate());
       __ TailCallExternalReference(ref, 5, 1);
     }
   } else {  // !compile_followup_inline
@@ -1245,7 +1257,7 @@
     __ push(scratch2);  // restore old return address
 
     ExternalReference ref = ExternalReference(
-        IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
+        IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate());
     __ TailCallExternalReference(ref, 5, 1);
   }
 }
@@ -1291,7 +1303,7 @@
   __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset));
 
   // Check that the cell contains the same function.
-  if (Heap::InNewSpace(function)) {
+  if (heap()->InNewSpace(function)) {
     // We can't embed a pointer to a function in new space so we have
     // to verify that the shared function info is unchanged. This has
     // the nice side effect that multiple closures based on the same
@@ -1313,8 +1325,8 @@
 
 
 MaybeObject* CallStubCompiler::GenerateMissBranch() {
-  MaybeObject* maybe_obj = StubCache::ComputeCallMiss(arguments().immediate(),
-                                                      kind_);
+  MaybeObject* maybe_obj = isolate()->stub_cache()->ComputeCallMiss(
+      arguments().immediate(), kind_);
   Object* obj;
   if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
@@ -1369,10 +1381,8 @@
 
   // Handle call cache miss.
   __ bind(&miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(FIELD, name);
@@ -1393,7 +1403,7 @@
   // -----------------------------------
 
   // If object is not an array, bail out to regular call.
-  if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value();
+  if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value();
 
   Label miss;
 
@@ -1427,7 +1437,7 @@
 
     // Check that the elements are in fast mode and writable.
     __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
-           Factory::fixed_array_map());
+           factory()->fixed_array_map());
     __ j(not_equal, &call_builtin);
 
     if (argc == 1) {  // Otherwise fall through to call builtin.
@@ -1477,14 +1487,13 @@
       }
 
       ExternalReference new_space_allocation_top =
-          ExternalReference::new_space_allocation_top_address();
+          ExternalReference::new_space_allocation_top_address(isolate());
       ExternalReference new_space_allocation_limit =
-          ExternalReference::new_space_allocation_limit_address();
+          ExternalReference::new_space_allocation_limit_address(isolate());
 
       const int kAllocationDelta = 4;
       // Load top.
-      __ movq(rcx, new_space_allocation_top);
-      __ movq(rcx, Operand(rcx, 0));
+      __ Load(rcx, new_space_allocation_top);
 
       // Check if it's the end of elements.
       __ lea(rdx, FieldOperand(rbx,
@@ -1493,13 +1502,13 @@
       __ cmpq(rdx, rcx);
       __ j(not_equal, &call_builtin);
       __ addq(rcx, Immediate(kAllocationDelta * kPointerSize));
-      __ movq(kScratchRegister, new_space_allocation_limit);
-      __ cmpq(rcx, Operand(kScratchRegister, 0));
+      Operand limit_operand =
+          masm()->ExternalOperand(new_space_allocation_limit);
+      __ cmpq(rcx, limit_operand);
       __ j(above, &call_builtin);
 
       // We fit and could grow elements.
-      __ movq(kScratchRegister, new_space_allocation_top);
-      __ movq(Operand(kScratchRegister, 0), rcx);
+      __ Store(new_space_allocation_top, rcx);
       __ movq(rcx, Operand(rsp, argc * kPointerSize));
 
       // Push the argument...
@@ -1526,16 +1535,15 @@
     }
 
     __ bind(&call_builtin);
-    __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
+    __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush,
+                                                   isolate()),
                                  argc + 1,
                                  1);
   }
 
   __ bind(&miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(function);
@@ -1556,7 +1564,7 @@
   // -----------------------------------
 
   // If object is not an array, bail out to regular call.
-  if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value();
+  if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value();
 
   Label miss, return_undefined, call_builtin;
 
@@ -1611,15 +1619,14 @@
   __ ret((argc + 1) * kPointerSize);
 
   __ bind(&call_builtin);
-  __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop),
-                               argc + 1,
-                               1);
+  __ TailCallExternalReference(
+      ExternalReference(Builtins::c_ArrayPop, isolate()),
+      argc + 1,
+      1);
 
   __ bind(&miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(function);
@@ -1641,7 +1648,7 @@
   // -----------------------------------
 
   // If object is not a string, bail out to regular call.
-  if (!object->IsString() || cell != NULL) return Heap::undefined_value();
+  if (!object->IsString() || cell != NULL) return heap()->undefined_value();
 
   const int argc = arguments().immediate();
 
@@ -1700,10 +1707,8 @@
   // Restore function name in rcx.
   __ Move(rcx, Handle<String>(name));
   __ bind(&name_miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(function);
@@ -1725,7 +1730,7 @@
   // -----------------------------------
 
   // If object is not a string, bail out to regular call.
-  if (!object->IsString() || cell != NULL) return Heap::undefined_value();
+  if (!object->IsString() || cell != NULL) return heap()->undefined_value();
 
   const int argc = arguments().immediate();
 
@@ -1786,10 +1791,8 @@
   // Restore function name in rcx.
   __ Move(rcx, Handle<String>(name));
   __ bind(&name_miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(function);
@@ -1814,7 +1817,7 @@
 
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
-  if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
+  if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
 
   Label miss;
   GenerateNameCheck(name, &miss);
@@ -1857,10 +1860,8 @@
 
   __ bind(&miss);
   // rcx: function name.
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
@@ -1873,7 +1874,7 @@
                                                     JSFunction* function,
                                                     String* name) {
   // TODO(872): implement this.
-  return Heap::undefined_value();
+  return heap()->undefined_value();
 }
 
 
@@ -1894,7 +1895,7 @@
 
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
-  if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
+  if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
 
   Label miss;
   GenerateNameCheck(name, &miss);
@@ -1943,7 +1944,7 @@
 
   // Check if the argument is a heap number and load its value.
   __ bind(&not_smi);
-  __ CheckMap(rax, Factory::heap_number_map(), &slow, true);
+  __ CheckMap(rax, factory()->heap_number_map(), &slow, true);
   __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset));
 
   // Check the sign of the argument. If the argument is positive,
@@ -1972,16 +1973,72 @@
 
   __ bind(&miss);
   // rcx: function name.
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
 }
 
 
+MaybeObject* CallStubCompiler::CompileFastApiCall(
+    const CallOptimization& optimization,
+    Object* object,
+    JSObject* holder,
+    JSGlobalPropertyCell* cell,
+    JSFunction* function,
+    String* name) {
+  ASSERT(optimization.is_simple_api_call());
+  // Bail out if object is a global object as we don't want to
+  // repatch it to global receiver.
+  if (object->IsGlobalObject()) return heap()->undefined_value();
+  if (cell != NULL) return heap()->undefined_value();
+  int depth = optimization.GetPrototypeDepthOfExpectedType(
+            JSObject::cast(object), holder);
+  if (depth == kInvalidProtoDepth) return heap()->undefined_value();
+
+  Label miss, miss_before_stack_reserved;
+
+  GenerateNameCheck(name, &miss_before_stack_reserved);
+
+  // Get the receiver from the stack.
+  const int argc = arguments().immediate();
+  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
+
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(rdx, &miss_before_stack_reserved);
+
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->call_const(), 1);
+  __ IncrementCounter(counters->call_const_fast_api(), 1);
+
+  // Allocate space for v8::Arguments implicit values. Must be initialized
+  // before calling any runtime function.
+  __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
+
+  // Check that the maps haven't changed and find a Holder as a side effect.
+  CheckPrototypes(JSObject::cast(object), rdx, holder,
+                  rbx, rax, rdi, name, depth, &miss);
+
+  // Move the return address on top of the stack.
+  __ movq(rax, Operand(rsp, 3 * kPointerSize));
+  __ movq(Operand(rsp, 0 * kPointerSize), rax);
+
+  MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc);
+  if (result->IsFailure()) return result;
+
+  __ bind(&miss);
+  __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
+
+  __ bind(&miss_before_stack_reserved);
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
+
+  // Return the generated code.
+  return GetCode(function);
+}
+
+
 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
                                                    JSObject* holder,
                                                    JSFunction* function,
@@ -1997,20 +2054,18 @@
   // rsp[(argc + 1) * 8] : argument 0 = receiver
   // -----------------------------------
 
-  SharedFunctionInfo* function_info = function->shared();
-  if (function_info->HasBuiltinFunctionId()) {
-    BuiltinFunctionId id = function_info->builtin_function_id();
+  if (HasCustomCallGenerator(function)) {
     MaybeObject* maybe_result = CompileCustomCall(
-        id, object, holder,  NULL, function, name);
+        object, holder, NULL, function, name);
     Object* result;
     if (!maybe_result->ToObject(&result)) return maybe_result;
     // undefined means bail out to regular compiler.
     if (!result->IsUndefined()) return result;
   }
 
-  Label miss_in_smi_check;
+  Label miss;
 
-  GenerateNameCheck(name, &miss_in_smi_check);
+  GenerateNameCheck(name, &miss);
 
   // Get the receiver from the stack.
   const int argc = arguments().immediate();
@@ -2018,42 +2073,26 @@
 
   // Check that the receiver isn't a smi.
   if (check != NUMBER_CHECK) {
-    __ JumpIfSmi(rdx, &miss_in_smi_check);
+    __ JumpIfSmi(rdx, &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);
 
-  CallOptimization optimization(function);
-  int depth = kInvalidProtoDepth;
-  Label miss;
-
+  Counters* counters = isolate()->counters();
+  SharedFunctionInfo* function_info = function->shared();
   switch (check) {
     case RECEIVER_MAP_CHECK:
-      __ IncrementCounter(&Counters::call_const, 1);
-
-      if (optimization.is_simple_api_call() && !object->IsGlobalObject()) {
-        depth = optimization.GetPrototypeDepthOfExpectedType(
-            JSObject::cast(object), holder);
-      }
-
-      if (depth != kInvalidProtoDepth) {
-        __ IncrementCounter(&Counters::call_const_fast_api, 1);
-
-        // Allocate space for v8::Arguments implicit values. Must be initialized
-        // before to call any runtime function.
-        __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
-      }
+      __ IncrementCounter(counters->call_const(), 1);
 
       // Check that the maps haven't changed.
       CheckPrototypes(JSObject::cast(object), rdx, holder,
-                      rbx, rax, rdi, name, depth, &miss);
+                      rbx, rax, rdi, name, &miss);
 
       // Patch the receiver on the stack with the global proxy if
       // necessary.
       if (object->IsGlobalObject()) {
-        ASSERT(depth == kInvalidProtoDepth);
         __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
         __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
       }
@@ -2123,31 +2162,12 @@
       UNREACHABLE();
   }
 
-  if (depth != kInvalidProtoDepth) {
-    // Move the return address on top of the stack.
-    __ movq(rax, Operand(rsp, 3 * kPointerSize));
-    __ movq(Operand(rsp, 0 * kPointerSize), rax);
-
-    // rsp[2 * kPointerSize] is uninitialized, rsp[3 * kPointerSize] contains
-    // duplicate of return address and will be overwritten.
-    MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc);
-    if (result->IsFailure()) return result;
-  } else {
-    __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
-  }
+  __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
 
   // Handle call cache miss.
   __ bind(&miss);
-  if (depth != kInvalidProtoDepth) {
-    __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
-  }
-
-  // Handle call cache miss.
-  __ bind(&miss_in_smi_check);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(function);
@@ -2213,10 +2233,8 @@
 
   // Handle load cache miss.
   __ bind(&miss);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(INTERCEPTOR, name);
@@ -2238,11 +2256,9 @@
   // rsp[(argc + 1) * 8] : argument 0 = receiver
   // -----------------------------------
 
-  SharedFunctionInfo* function_info = function->shared();
-  if (function_info->HasBuiltinFunctionId()) {
-    BuiltinFunctionId id = function_info->builtin_function_id();
+  if (HasCustomCallGenerator(function)) {
     MaybeObject* maybe_result = CompileCustomCall(
-        id, object, holder, cell, function, name);
+        object, holder, cell, function, name);
     Object* result;
     if (!maybe_result->ToObject(&result)) return maybe_result;
     // undefined means bail out to regular compiler.
@@ -2270,7 +2286,8 @@
   __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
 
   // Jump to the cached code (tail call).
-  __ IncrementCounter(&Counters::call_global_inline, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->call_global_inline(), 1);
   ASSERT(function->is_compiled());
   ParameterCount expected(function->shared()->formal_parameter_count());
   if (V8::UseCrankshaft()) {
@@ -2286,11 +2303,9 @@
   }
   // Handle call cache miss.
   __ bind(&miss);
-  __ IncrementCounter(&Counters::call_global_inline_miss, 1);
-  Object* obj;
-  { MaybeObject* maybe_obj = GenerateMissBranch();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
+  __ IncrementCounter(counters->call_global_inline_miss(), 1);
+  MaybeObject* maybe_result = GenerateMissBranch();
+  if (maybe_result->IsFailure()) return maybe_result;
 
   // Return the generated code.
   return GetCode(NORMAL, name);
@@ -2319,7 +2334,7 @@
 
   // Handle store cache miss.
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2364,12 +2379,12 @@
 
   // Do tail-call to the runtime system.
   ExternalReference store_callback_property =
-      ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
+      ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
   __ TailCallExternalReference(store_callback_property, 4, 1);
 
   // Handle store cache miss.
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2413,12 +2428,12 @@
 
   // Do tail-call to the runtime system.
   ExternalReference store_ic_property =
-      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
+      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
   __ TailCallExternalReference(store_ic_property, 4, 1);
 
   // Handle store cache miss.
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2455,13 +2470,14 @@
   __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rax);
 
   // Return the value (register rax).
-  __ IncrementCounter(&Counters::named_store_global_inline, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->named_store_global_inline(), 1);
   __ ret(0);
 
   // Handle store cache miss.
   __ bind(&miss);
-  __ IncrementCounter(&Counters::named_store_global_inline_miss, 1);
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+  __ IncrementCounter(counters->named_store_global_inline_miss(), 1);
+  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2481,7 +2497,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_store_field, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_store_field(), 1);
 
   // Check that the name has not changed.
   __ Cmp(rcx, Handle<String>(name));
@@ -2497,8 +2514,8 @@
 
   // Handle store cache miss.
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_store_field, 1);
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
+  __ DecrementCounter(counters->keyed_store_field(), 1);
+  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2530,7 +2547,7 @@
   // Get the elements array and make sure it is a fast element array, not 'cow'.
   __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
   __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
-         Factory::fixed_array_map());
+         factory()->fixed_array_map());
   __ j(not_equal, &miss);
 
   // Check that the key is within bounds.
@@ -2555,44 +2572,7 @@
 
   // Handle store cache miss.
   __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
-  __ jmp(ic, RelocInfo::CODE_TARGET);
-
-  // Return the generated code.
-  return GetCode(NORMAL, NULL);
-}
-
-
-MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray(
-    JSObject* receiver) {
-  // ----------- S t a t e -------------
-  //  -- rax    : value
-  //  -- rcx    : key
-  //  -- rdx    : receiver
-  //  -- rsp[0] : return address
-  // -----------------------------------
-  Label miss;
-
-  // Check that the map matches.
-  __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, false);
-
-  // Do the load.
-  GenerateFastPixelArrayStore(masm(),
-                              rdx,
-                              rcx,
-                              rax,
-                              rdi,
-                              rbx,
-                              true,
-                              false,
-                              &miss,
-                              &miss,
-                              NULL,
-                              &miss);
-
-  // Handle store cache miss.
-  __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
+  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
   __ jmp(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
@@ -2641,7 +2621,7 @@
   GenerateLoadMiss(masm(), Code::LOAD_IC);
 
   // Return the generated code.
-  return GetCode(NONEXISTENT, Heap::empty_string());
+  return GetCode(NONEXISTENT, heap()->empty_string());
 }
 
 
@@ -2780,12 +2760,13 @@
     __ Check(not_equal, "DontDelete cells can't contain the hole");
   }
 
-  __ IncrementCounter(&Counters::named_load_global_stub, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->named_load_global_stub(), 1);
   __ movq(rax, rbx);
   __ ret(0);
 
   __ bind(&miss);
-  __ IncrementCounter(&Counters::named_load_global_stub_miss, 1);
+  __ IncrementCounter(counters->named_load_global_stub_miss(), 1);
   GenerateLoadMiss(masm(), Code::LOAD_IC);
 
   // Return the generated code.
@@ -2804,7 +2785,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_load_field, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_field(), 1);
 
   // Check that the name has not changed.
   __ Cmp(rax, Handle<String>(name));
@@ -2813,7 +2795,7 @@
   GenerateLoadField(receiver, holder, rdx, rbx, rcx, rdi, index, name, &miss);
 
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_field, 1);
+  __ DecrementCounter(counters->keyed_load_field(), 1);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
@@ -2833,7 +2815,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_load_callback, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_callback(), 1);
 
   // Check that the name has not changed.
   __ Cmp(rax, Handle<String>(name));
@@ -2848,7 +2831,7 @@
 
   __ bind(&miss);
 
-  __ DecrementCounter(&Counters::keyed_load_callback, 1);
+  __ DecrementCounter(counters->keyed_load_callback(), 1);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
@@ -2867,7 +2850,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_load_constant_function, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_constant_function(), 1);
 
   // Check that the name has not changed.
   __ Cmp(rax, Handle<String>(name));
@@ -2876,7 +2860,7 @@
   GenerateLoadConstant(receiver, holder, rdx, rbx, rcx, rdi,
                        value, name, &miss);
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_constant_function, 1);
+  __ DecrementCounter(counters->keyed_load_constant_function(), 1);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
@@ -2894,7 +2878,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_load_interceptor, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_interceptor(), 1);
 
   // Check that the name has not changed.
   __ Cmp(rax, Handle<String>(name));
@@ -2913,7 +2898,7 @@
                           name,
                           &miss);
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_interceptor, 1);
+  __ DecrementCounter(counters->keyed_load_interceptor(), 1);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
@@ -2929,7 +2914,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_load_array_length, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_array_length(), 1);
 
   // Check that the name has not changed.
   __ Cmp(rax, Handle<String>(name));
@@ -2937,7 +2923,7 @@
 
   GenerateLoadArrayLength(masm(), rdx, rcx, &miss);
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_array_length, 1);
+  __ DecrementCounter(counters->keyed_load_array_length(), 1);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
@@ -2953,7 +2939,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_load_string_length, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_string_length(), 1);
 
   // Check that the name has not changed.
   __ Cmp(rax, Handle<String>(name));
@@ -2961,7 +2948,7 @@
 
   GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss, true);
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_string_length, 1);
+  __ DecrementCounter(counters->keyed_load_string_length(), 1);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
@@ -2977,7 +2964,8 @@
   // -----------------------------------
   Label miss;
 
-  __ IncrementCounter(&Counters::keyed_load_function_prototype, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_function_prototype(), 1);
 
   // Check that the name has not changed.
   __ Cmp(rax, Handle<String>(name));
@@ -2985,7 +2973,7 @@
 
   GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss);
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_function_prototype, 1);
+  __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
@@ -2997,7 +2985,7 @@
   // ----------- S t a t e -------------
   //  -- rax    : key
   //  -- rdx    : receiver
-  //  -- esp[0] : return address
+  //  -- rsp[0] : return address
   // -----------------------------------
   Label miss;
 
@@ -3039,35 +3027,6 @@
 }
 
 
-MaybeObject* KeyedLoadStubCompiler::CompileLoadPixelArray(JSObject* receiver) {
-  // ----------- S t a t e -------------
-  //  -- rax    : key
-  //  -- rdx    : receiver
-  //  -- esp[0] : return address
-  // -----------------------------------
-  Label miss;
-
-  // Check that the map matches.
-  __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, false);
-
-  GenerateFastPixelArrayLoad(masm(),
-                             rdx,
-                             rax,
-                             rbx,
-                             rcx,
-                             rax,
-                             &miss,
-                             &miss,
-                             &miss);
-
-  __ bind(&miss);
-  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
-
-  // Return the generated code.
-  return GetCode(NORMAL, NULL);
-}
-
-
 // Specialized stub for constructing objects from functions which only have only
 // simple assignments of the form this.x = ...; in their body.
 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
@@ -3080,7 +3039,7 @@
   Label generic_stub_call;
 
   // Use r8 for holding undefined which is used in several places below.
-  __ Move(r8, Factory::undefined_value());
+  __ Move(r8, factory()->undefined_value());
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Check to see whether there are any break points in the function code. If
@@ -3124,7 +3083,7 @@
   // rbx: initial map
   // rdx: JSObject (untagged)
   __ movq(Operand(rdx, JSObject::kMapOffset), rbx);
-  __ Move(rbx, Factory::empty_fixed_array());
+  __ Move(rbx, factory()->empty_fixed_array());
   __ movq(Operand(rdx, JSObject::kPropertiesOffset), rbx);
   __ movq(Operand(rdx, JSObject::kElementsOffset), rbx);
 
@@ -3183,14 +3142,16 @@
   __ pop(rcx);
   __ lea(rsp, Operand(rsp, rbx, times_pointer_size, 1 * kPointerSize));
   __ push(rcx);
-  __ IncrementCounter(&Counters::constructed_objects, 1);
-  __ IncrementCounter(&Counters::constructed_objects_stub, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->constructed_objects(), 1);
+  __ IncrementCounter(counters->constructed_objects_stub(), 1);
   __ ret(0);
 
   // Jump to the generic stub in case the specialized code cannot handle the
   // construction.
   __ bind(&generic_stub_call);
-  Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
+  Code* code =
+      isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric);
   Handle<Code> generic_construct_stub(code);
   __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
 
@@ -3200,7 +3161,7 @@
 
 
 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
-    ExternalArrayType array_type, Code::Flags flags) {
+    JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) {
   // ----------- S t a t e -------------
   //  -- rax    : key
   //  -- rdx    : receiver
@@ -3214,24 +3175,9 @@
   // Check that the key is a smi.
   __ JumpIfNotSmi(rax, &slow);
 
-  // Check that the object is a JS object.
-  __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
-  __ j(not_equal, &slow);
-  // Check that the receiver does not require access checks.  We need
-  // to check this explicitly since this generic stub does not perform
-  // map checks.  The map is already in rdx.
-  __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
-           Immediate(1 << Map::kIsAccessCheckNeeded));
-  __ j(not_zero, &slow);
-
-  // Check that the elements array is the appropriate type of
-  // ExternalArray.
-  // rax: index (as a smi)
-  // rdx: JSObject
+  // Check that the map matches.
+  __ CheckMap(rdx, Handle<Map>(receiver->map()), &slow, false);
   __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
-  __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
-                 Heap::RootIndexForExternalArrayType(array_type));
-  __ j(not_equal, &slow);
 
   // Check that the index is in range.
   __ SmiToInteger32(rcx, rax);
@@ -3249,6 +3195,7 @@
     case kExternalByteArray:
       __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0));
       break;
+    case kExternalPixelArray:
     case kExternalUnsignedByteArray:
       __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0));
       break;
@@ -3319,7 +3266,8 @@
 
   // Slow case: Jump to runtime.
   __ bind(&slow);
-  __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
+  Counters* counters = isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
 
   // ----------- S t a t e -------------
   //  -- rax    : key
@@ -3341,7 +3289,7 @@
 
 
 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
-    ExternalArrayType array_type, Code::Flags flags) {
+    JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) {
   // ----------- S t a t e -------------
   //  -- rax     : value
   //  -- rcx     : key
@@ -3352,30 +3300,14 @@
 
   // Check that the object isn't a smi.
   __ JumpIfSmi(rdx, &slow);
-  // Get the map from the receiver.
-  __ movq(rbx, FieldOperand(rdx, 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.
-  __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
-           Immediate(1 << Map::kIsAccessCheckNeeded));
-  __ j(not_zero, &slow);
+
+  // Check that the map matches.
+  __ CheckMap(rdx, Handle<Map>(receiver->map()), &slow, false);
+  __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
+
   // Check that the key is a smi.
   __ JumpIfNotSmi(rcx, &slow);
 
-  // Check that the object is a JS object.
-  __ CmpInstanceType(rbx, JS_OBJECT_TYPE);
-  __ j(not_equal, &slow);
-
-  // Check that the elements array is the appropriate type of
-  // ExternalArray.
-  // rax: value
-  // rcx: key (a smi)
-  // rdx: receiver (a JSObject)
-  __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
-  __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
-                 Heap::RootIndexForExternalArrayType(array_type));
-  __ j(not_equal, &slow);
-
   // Check that the index is in range.
   __ SmiToInteger32(rdi, rcx);  // Untag the index.
   __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset));
@@ -3390,12 +3322,28 @@
   // rbx: elements array
   // rdi: untagged key
   NearLabel check_heap_number;
-  __ JumpIfNotSmi(rax, &check_heap_number);
+  if (array_type == kExternalPixelArray) {
+    // Float to pixel conversion is only implemented in the runtime for now.
+    __ JumpIfNotSmi(rax, &slow);
+  } else {
+    __ JumpIfNotSmi(rax, &check_heap_number);
+  }
   // No more branches to slow case on this path.  Key and receiver not needed.
   __ SmiToInteger32(rdx, rax);
   __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
   // rbx: base pointer of external storage
   switch (array_type) {
+    case kExternalPixelArray:
+      {  // Clamp the value to [0..255].
+        NearLabel done;
+        __ testl(rdx, Immediate(0xFFFFFF00));
+        __ j(zero, &done);
+        __ setcc(negative, rdx);  // 1 if negative, 0 if positive.
+        __ decb(rdx);  // 0 if negative, 255 if positive.
+        __ bind(&done);
+      }
+      __ movb(Operand(rbx, rdi, times_1, 0), rdx);
+      break;
     case kExternalByteArray:
     case kExternalUnsignedByteArray:
       __ movb(Operand(rbx, rdi, times_1, 0), rdx);
@@ -3419,62 +3367,65 @@
   }
   __ ret(0);
 
-  __ bind(&check_heap_number);
-  // rax: value
-  // rcx: key (a smi)
-  // rdx: receiver (a JSObject)
-  // rbx: elements array
-  // rdi: untagged key
-  __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister);
-  __ j(not_equal, &slow);
-  // No more branches to slow case on this path.
+  // TODO(danno): handle heap number -> pixel array conversion
+  if (array_type != kExternalPixelArray) {
+    __ bind(&check_heap_number);
+    // rax: value
+    // rcx: key (a smi)
+    // rdx: receiver (a JSObject)
+    // rbx: elements array
+    // rdi: untagged key
+    __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister);
+    __ j(not_equal, &slow);
+    // No more branches to slow case on this path.
 
-  // The WebGL specification leaves the behavior of storing NaN and
-  // +/-Infinity into integer arrays basically undefined. For more
-  // reproducible behavior, convert these to zero.
-  __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
-  __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
-  // rdi: untagged index
-  // rbx: base pointer of external storage
-  // top of FPU stack: value
-  if (array_type == kExternalFloatArray) {
-    __ cvtsd2ss(xmm0, xmm0);
-    __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
-    __ ret(0);
-  } else {
-    // Perform float-to-int conversion with truncation (round-to-zero)
-    // behavior.
-
-    // Convert to int32 and store the low byte/word.
-    // If the value is NaN or +/-infinity, the result is 0x80000000,
-    // which is automatically zero when taken mod 2^n, n < 32.
-    // rdx: value (converted to an untagged integer)
+    // The WebGL specification leaves the behavior of storing NaN and
+    // +/-Infinity into integer arrays basically undefined. For more
+    // reproducible behavior, convert these to zero.
+    __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
+    __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
     // rdi: untagged index
     // rbx: base pointer of external storage
-    switch (array_type) {
-      case kExternalByteArray:
-      case kExternalUnsignedByteArray:
-        __ cvttsd2si(rdx, xmm0);
-        __ movb(Operand(rbx, rdi, times_1, 0), rdx);
-        break;
-      case kExternalShortArray:
-      case kExternalUnsignedShortArray:
-        __ cvttsd2si(rdx, xmm0);
-        __ movw(Operand(rbx, rdi, times_2, 0), rdx);
-        break;
-      case kExternalIntArray:
-      case kExternalUnsignedIntArray: {
-        // Convert to int64, so that NaN and infinities become
-        // 0x8000000000000000, which is zero mod 2^32.
-        __ cvttsd2siq(rdx, xmm0);
-        __ movl(Operand(rbx, rdi, times_4, 0), rdx);
-        break;
+    // top of FPU stack: value
+    if (array_type == kExternalFloatArray) {
+      __ cvtsd2ss(xmm0, xmm0);
+      __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
+      __ ret(0);
+    } else {
+      // Perform float-to-int conversion with truncation (round-to-zero)
+      // behavior.
+
+      // Convert to int32 and store the low byte/word.
+      // If the value is NaN or +/-infinity, the result is 0x80000000,
+      // which is automatically zero when taken mod 2^n, n < 32.
+      // rdx: value (converted to an untagged integer)
+      // rdi: untagged index
+      // rbx: base pointer of external storage
+      switch (array_type) {
+        case kExternalByteArray:
+        case kExternalUnsignedByteArray:
+          __ cvttsd2si(rdx, xmm0);
+          __ movb(Operand(rbx, rdi, times_1, 0), rdx);
+          break;
+        case kExternalShortArray:
+        case kExternalUnsignedShortArray:
+          __ cvttsd2si(rdx, xmm0);
+          __ movw(Operand(rbx, rdi, times_2, 0), rdx);
+          break;
+        case kExternalIntArray:
+        case kExternalUnsignedIntArray: {
+          // Convert to int64, so that NaN and infinities become
+          // 0x8000000000000000, which is zero mod 2^32.
+          __ cvttsd2siq(rdx, xmm0);
+          __ movl(Operand(rbx, rdi, times_4, 0), rdx);
+          break;
+        }
+        default:
+          UNREACHABLE();
+          break;
       }
-      default:
-        UNREACHABLE();
-        break;
+      __ ret(0);
     }
-    __ ret(0);
   }
 
   // Slow case: call runtime.
diff --git a/src/x64/virtual-frame-x64.cc b/src/x64/virtual-frame-x64.cc
index c4d7e65..10c327a 100644
--- a/src/x64/virtual-frame-x64.cc
+++ b/src/x64/virtual-frame-x64.cc
@@ -113,7 +113,7 @@
     // them later.  First sync everything above the stack pointer so we can
     // use pushes to allocate and initialize the locals.
     SyncRange(stack_pointer_ + 1, element_count() - 1);
-    Handle<Object> undefined = Factory::undefined_value();
+    Handle<Object> undefined = FACTORY->undefined_value();
     FrameElement initial_value =
         FrameElement::ConstantElement(undefined, FrameElement::SYNCED);
     if (count < kLocalVarBound) {
@@ -1019,7 +1019,7 @@
 //------------------------------------------------------------------------------
 // Virtual frame stub and IC calling functions.
 
-Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
+Result VirtualFrame::CallRuntime(const Runtime::Function* f, int arg_count) {
   PrepareForCall(arg_count, arg_count);
   ASSERT(cgen()->HasValidEntryRegisters());
   __ CallRuntime(f, arg_count);
@@ -1115,7 +1115,8 @@
 Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) {
   // Name and receiver are on the top of the frame.  Both are dropped.
   // The IC expects name in rcx and receiver in rax.
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      Builtins::kLoadIC_Initialize));
   Result name = Pop();
   Result receiver = Pop();
   PrepareForCall(0, 0);
@@ -1132,7 +1133,8 @@
   PrepareForCall(0, 0);
   MoveResultsToRegisters(&key, &receiver, rax, rdx);
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      Builtins::kKeyedLoadIC_Initialize));
   return RawCallCodeObject(ic, mode);
 }
 
@@ -1142,9 +1144,9 @@
                                  StrictModeFlag strict_mode) {
   // Value and (if not contextual) receiver are on top of the frame.
   // The IC expects name in rcx, value in rax, and receiver in rdx.
-  Handle<Code> ic(Builtins::builtin(
-      (strict_mode == kStrictMode) ? Builtins::StoreIC_Initialize_Strict
-                                   : Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      (strict_mode == kStrictMode) ? Builtins::kStoreIC_Initialize_Strict
+                                   : Builtins::kStoreIC_Initialize));
   Result value = Pop();
   RelocInfo::Mode mode;
   if (is_contextual) {
@@ -1208,9 +1210,9 @@
     receiver.Unuse();
   }
 
-  Handle<Code> ic(Builtins::builtin(
-      (strict_mode == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
-                                   : Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      (strict_mode == kStrictMode) ? Builtins::kKeyedStoreIC_Initialize_Strict
+                                   : Builtins::kKeyedStoreIC_Initialize));
   return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
 }
 
@@ -1222,7 +1224,8 @@
   // and dropped by the call.  The IC expects the name in rcx and the rest
   // on the stack, and drops them all.
   InLoopFlag in_loop = loop_nesting > 0 ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
+  Handle<Code> ic =
+      ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop);
   Result name = Pop();
   // Spill args, receiver, and function.  The call will drop args and
   // receiver.
@@ -1241,7 +1244,7 @@
   // on the stack, and drops them all.
   InLoopFlag in_loop = loop_nesting > 0 ? IN_LOOP : NOT_IN_LOOP;
   Handle<Code> ic =
-      StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
+      ISOLATE->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop);
   Result name = Pop();
   // Spill args, receiver, and function.  The call will drop args and
   // receiver.
@@ -1256,7 +1259,8 @@
   // Arguments, receiver, and function are on top of the frame.  The
   // IC expects arg count in rax, function in rdi, and the arguments
   // and receiver on the stack.
-  Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      Builtins::kJSConstructCall));
   // Duplicate the function before preparing the frame.
   PushElementAt(arg_count);
   Result function = Pop();
diff --git a/src/x64/virtual-frame-x64.h b/src/x64/virtual-frame-x64.h
index 7396db1..aac9864 100644
--- a/src/x64/virtual-frame-x64.h
+++ b/src/x64/virtual-frame-x64.h
@@ -67,7 +67,9 @@
    private:
     bool previous_state_;
 
-    CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
+    CodeGenerator* cgen() {
+      return CodeGeneratorScope::Current(Isolate::Current());
+    }
   };
 
   // An illegal index into the virtual frame.
@@ -79,7 +81,10 @@
   // Construct a virtual frame as a clone of an existing one.
   explicit inline VirtualFrame(VirtualFrame* original);
 
-  CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
+  CodeGenerator* cgen() {
+    return CodeGeneratorScope::Current(Isolate::Current());
+  }
+
   MacroAssembler* masm() { return cgen()->masm(); }
 
   // Create a duplicate of an existing valid frame element.
@@ -315,7 +320,7 @@
 
   // Call runtime given the number of arguments expected on (and
   // removed from) the stack.
-  Result CallRuntime(Runtime::Function* f, int arg_count);
+  Result CallRuntime(const Runtime::Function* f, int arg_count);
   Result CallRuntime(Runtime::FunctionId id, int arg_count);
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
@@ -342,7 +347,6 @@
                      StrictModeFlag strict_mode);
 
   // Call keyed store IC.  Value, key, and receiver are found on top
-  // of the frame.  All three are dropped.
   Result CallKeyedStoreIC(StrictModeFlag strict_mode);
 
   // Call call IC.  Function name, arguments, and receiver are found on top
diff --git a/src/zone-inl.h b/src/zone-inl.h
index 4672960..516fc4a 100644
--- a/src/zone-inl.h
+++ b/src/zone-inl.h
@@ -28,6 +28,7 @@
 #ifndef V8_ZONE_INL_H_
 #define V8_ZONE_INL_H_
 
+#include "isolate.h"
 #include "zone.h"
 #include "v8-counters.h"
 
@@ -35,8 +36,19 @@
 namespace internal {
 
 
+AssertNoZoneAllocation::AssertNoZoneAllocation()
+    : prev_(Isolate::Current()->zone_allow_allocation()) {
+  Isolate::Current()->set_zone_allow_allocation(false);
+}
+
+
+AssertNoZoneAllocation::~AssertNoZoneAllocation() {
+  Isolate::Current()->set_zone_allow_allocation(prev_);
+}
+
+
 inline void* Zone::New(int size) {
-  ASSERT(AssertNoZoneAllocation::allow_allocation());
+  ASSERT(Isolate::Current()->zone_allow_allocation());
   ASSERT(ZoneScope::nesting() > 0);
   // Round up the requested size to fit the alignment.
   size = RoundUp(size, kAlignment);
@@ -54,7 +66,7 @@
 
 template <typename T>
 T* Zone::NewArray(int length) {
-  return static_cast<T*>(Zone::New(length * sizeof(T)));
+  return static_cast<T*>(New(length * sizeof(T)));
 }
 
 
@@ -65,7 +77,7 @@
 
 void Zone::adjust_segment_bytes_allocated(int delta) {
   segment_bytes_allocated_ += delta;
-  Counters::zone_segment_bytes.Set(segment_bytes_allocated_);
+  isolate_->counters()->zone_segment_bytes()->Set(segment_bytes_allocated_);
 }
 
 
@@ -78,6 +90,36 @@
 }
 
 
+// TODO(isolates): for performance reasons, this should be replaced with a new
+//                 operator that takes the zone in which the object should be
+//                 allocated.
+void* ZoneObject::operator new(size_t size) {
+  return ZONE->New(static_cast<int>(size));
+}
+
+
+inline void* ZoneListAllocationPolicy::New(int size) {
+  return ZONE->New(size);
+}
+
+
+ZoneScope::ZoneScope(ZoneScopeMode mode)
+    : isolate_(Isolate::Current()),
+      mode_(mode) {
+  isolate_->zone()->scope_nesting_++;
+}
+
+
+bool ZoneScope::ShouldDeleteOnExit() {
+  return isolate_->zone()->scope_nesting_ == 1 && mode_ == DELETE_ON_EXIT;
+}
+
+
+int ZoneScope::nesting() {
+  return Isolate::Current()->zone()->scope_nesting_;
+}
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_ZONE_INL_H_
diff --git a/src/zone.cc b/src/zone.cc
index f8dbaab..42ce8c5 100644
--- a/src/zone.cc
+++ b/src/zone.cc
@@ -34,20 +34,28 @@
 namespace internal {
 
 
-Address Zone::position_ = 0;
-Address Zone::limit_ = 0;
-int Zone::zone_excess_limit_ = 256 * MB;
-int Zone::segment_bytes_allocated_ = 0;
+Zone::Zone()
+    : zone_excess_limit_(256 * MB),
+      segment_bytes_allocated_(0),
+      position_(0),
+      limit_(0),
+      scope_nesting_(0),
+      segment_head_(NULL) {
+}
 unsigned Zone::allocation_size_ = 0;
 
-bool AssertNoZoneAllocation::allow_allocation_ = true;
 
-int ZoneScope::nesting_ = 0;
+ZoneScope::~ZoneScope() {
+  ASSERT_EQ(Isolate::Current(), isolate_);
+  if (ShouldDeleteOnExit()) isolate_->zone()->DeleteAll();
+  isolate_->zone()->scope_nesting_--;
+}
+
 
 // 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()
+// available as segment_head_. Segments are allocated using malloc()
 // and de-allocated using free().
 
 class Segment {
@@ -61,45 +69,38 @@
   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_;
+
+  friend class Zone;
 };
 
 
-Segment* Segment::head_ = NULL;
-int Segment::bytes_allocated_ = 0;
+// Creates a new segment, sets it size, and pushes it to the front
+// of the segment chain. Returns the new segment.
+Segment* Zone::NewSegment(int size) {
+  Segment* result = reinterpret_cast<Segment*>(Malloced::New(size));
+  adjust_segment_bytes_allocated(size);
+  if (result != NULL) {
+    result->next_ = segment_head_;
+    result->size_ = size;
+    segment_head_ = result;
+  }
+  return result;
+}
+
+
+// Deletes the given segment. Does not touch the segment chain.
+void Zone::DeleteSegment(Segment* segment, int size) {
+  adjust_segment_bytes_allocated(-size);
+  Malloced::Delete(segment);
+}
 
 
 void Zone::DeleteAll() {
@@ -109,14 +110,14 @@
 #endif
 
   // Find a segment with a suitable size to keep around.
-  Segment* keep = Segment::head();
+  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();
+  Segment* current = segment_head_;
   while (current != NULL) {
     Segment* next = current->next();
     if (current == keep) {
@@ -128,7 +129,7 @@
       // Zap the entire current segment (including the header).
       memset(current, kZapDeadByte, size);
 #endif
-      Segment::Delete(current, size);
+      DeleteSegment(current, size);
     }
     current = next;
   }
@@ -150,7 +151,7 @@
   }
 
   // Update the head segment to be the kept segment (if any).
-  Segment::set_head(keep);
+  segment_head_ = keep;
 }
 
 
@@ -164,7 +165,7 @@
   // 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();
+  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);
@@ -177,7 +178,7 @@
     // requested size.
     new_size = Max(kSegmentOverhead + size, kMaximumSegmentSize);
   }
-  Segment* segment = Segment::New(new_size);
+  Segment* segment = NewSegment(new_size);
   if (segment == NULL) {
     V8::FatalProcessOutOfMemory("Zone");
     return NULL;
diff --git a/src/zone.h b/src/zone.h
index e299f15..13b55c4 100644
--- a/src/zone.h
+++ b/src/zone.h
@@ -39,6 +39,7 @@
   DONT_DELETE_ON_EXIT
 };
 
+class Segment;
 
 // The Zone supports very fast allocation of small chunks of
 // memory. The chunks cannot be deallocated individually, but instead
@@ -57,23 +58,25 @@
  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);
+  inline void* New(int size);
 
   template <typename T>
-  static inline T* NewArray(int length);
+  inline T* NewArray(int length);
 
   // Delete all objects and free all memory allocated in the Zone.
-  static void DeleteAll();
+  void DeleteAll();
 
   // Returns true if more memory has been allocated in zones than
   // the limit allows.
-  static inline bool excess_allocation();
+  inline bool excess_allocation();
 
-  static inline void adjust_segment_bytes_allocated(int delta);
+  inline void adjust_segment_bytes_allocated(int delta);
 
   static unsigned allocation_size_;
 
  private:
+  friend class Isolate;
+  friend class ZoneScope;
 
   // All pointers returned from New() have this alignment.
   static const int kAlignment = kPointerSize;
@@ -88,30 +91,39 @@
   static const int kMaximumKeptSegmentSize = 64 * KB;
 
   // Report zone excess when allocation exceeds this limit.
-  static int zone_excess_limit_;
+  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_;
+  int segment_bytes_allocated_;
 
-  // The Zone is intentionally a singleton; you should not try to
-  // allocate instances of the class.
-  Zone() { UNREACHABLE(); }
-
+  // Each isolate gets its own zone.
+  Zone();
 
   // 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);
+  Address NewExpand(int size);
 
+  // Creates a new segment, sets it size, and pushes it to the front
+  // of the segment chain. Returns the new segment.
+  Segment* NewSegment(int size);
+
+  // Deletes the given segment. Does not touch the segment chain.
+  void DeleteSegment(Segment* segment, 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_;
+  Address position_;
+  Address limit_;
+
+  int scope_nesting_;
+
+  Segment* segment_head_;
+  Isolate* isolate_;
 };
 
 
@@ -120,7 +132,7 @@
 class ZoneObject {
  public:
   // Allocate a new ZoneObject of 'size' bytes in the Zone.
-  void* operator new(size_t size) { return Zone::New(static_cast<int>(size)); }
+  inline void* operator new(size_t size);
 
   // Ideally, the delete operator should be private instead of
   // public, but unfortunately the compiler sometimes synthesizes
@@ -136,14 +148,10 @@
 
 class AssertNoZoneAllocation {
  public:
-  AssertNoZoneAllocation() : prev_(allow_allocation_) {
-    allow_allocation_ = false;
-  }
-  ~AssertNoZoneAllocation() { allow_allocation_ = prev_; }
-  static bool allow_allocation() { return allow_allocation_; }
+  inline AssertNoZoneAllocation();
+  inline ~AssertNoZoneAllocation();
  private:
   bool prev_;
-  static bool allow_allocation_;
 };
 
 
@@ -153,7 +161,7 @@
 class ZoneListAllocationPolicy {
  public:
   // Allocate 'size' bytes of memory in the zone.
-  static void* New(int size) {  return Zone::New(size); }
+  static inline void* New(int size);
 
   // De-allocation attempts are silently ignored.
   static void Delete(void* p) { }
@@ -189,18 +197,12 @@
 // outer-most scope.
 class ZoneScope BASE_EMBEDDED {
  public:
-  explicit ZoneScope(ZoneScopeMode mode) : mode_(mode) {
-    nesting_++;
-  }
+  // TODO(isolates): pass isolate pointer here.
+  inline explicit ZoneScope(ZoneScopeMode mode);
 
-  virtual ~ZoneScope() {
-    if (ShouldDeleteOnExit()) Zone::DeleteAll();
-    --nesting_;
-  }
+  virtual ~ZoneScope();
 
-  bool ShouldDeleteOnExit() {
-    return nesting_ == 1 && mode_ == DELETE_ON_EXIT;
-  }
+  inline bool ShouldDeleteOnExit();
 
   // For ZoneScopes that do not delete on exit by default, call this
   // method to request deletion on exit.
@@ -208,11 +210,11 @@
     mode_ = DELETE_ON_EXIT;
   }
 
-  static int nesting() { return nesting_; }
+  inline static int nesting();
 
  private:
+  Isolate* isolate_;
   ZoneScopeMode mode_;
-  static int nesting_;
 };
 
 
diff --git a/test/benchmarks/testcfg.py b/test/benchmarks/testcfg.py
new file mode 100644
index 0000000..51d8520
--- /dev/null
+++ b/test/benchmarks/testcfg.py
@@ -0,0 +1,100 @@
+# Copyright 2011 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+#       copyright notice, this list of conditions and the following
+#       disclaimer in the documentation and/or other materials provided
+#       with the distribution.
+#     * Neither the name of Google Inc. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (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, split
+
+def IsNumber(string):
+  try:
+    float(string)
+    return True
+  except ValueError:
+    return False
+
+
+class BenchmarkTestCase(test.TestCase):
+
+  def __init__(self, path, context, mode):
+    super(BenchmarkTestCase, self).__init__(context, split(path), mode)
+    self.root = path
+
+  def GetLabel(self):
+    return '%s benchmark %s' % (self.mode, self.GetName())
+
+  def IsFailureOutput(self, output):
+    if output.exit_code != 0:
+      return True
+    lines = output.stdout.splitlines()
+    for line in lines:
+      colon_index = line.find(':')
+      if colon_index >= 0:
+        if not IsNumber(line[colon_index+1:].strip()):
+          return True
+    return False
+
+  def GetCommand(self):
+    result = self.context.GetVmCommand(self, self.mode)
+    result.append(join(self.root, 'run.js'))
+    return result
+
+  def GetName(self):
+    return 'V8'
+
+  def BeforeRun(self):
+    os.chdir(self.root)
+
+  def AfterRun(self, result):
+    os.chdir(self.context.buildspace)
+
+  def GetSource(self):
+    return open(join(self.root, 'run.js')).read()
+
+  def GetCustomFlags(self, mode):
+    return []
+
+
+class BenchmarkTestConfiguration(test.TestConfiguration):
+
+  def __init__(self, context, root):
+    super(BenchmarkTestConfiguration, self).__init__(context, root)
+
+  def ListTests(self, current_path, path, mode, variant_flags):
+    path = self.context.workspace
+    path = join(path, 'benchmarks')
+    test = BenchmarkTestCase(path, self.context, mode)
+    return [test]
+
+  def GetBuildRequirements(self):
+    return ['sample', 'sample=shell']
+
+  def GetTestStatus(self, sections, defs):
+    pass
+
+def GetConfiguration(context, root):
+  return BenchmarkTestConfiguration(context, root)
diff --git a/test/cctest/SConscript b/test/cctest/SConscript
index 7038137..f4cb4a9 100644
--- a/test/cctest/SConscript
+++ b/test/cctest/SConscript
@@ -41,8 +41,8 @@
     'test-alloc.cc',
     'test-api.cc',
     'test-ast.cc',
-    'test-bignum.cc',
     'test-bignum-dtoa.cc',
+    'test-bignum.cc',
     'test-circular-queue.cc',
     'test-compiler.cc',
     'test-conversions.cc',
@@ -59,15 +59,16 @@
     'test-flags.cc',
     'test-func-name-inference.cc',
     'test-hashmap.cc',
-    'test-heap.cc',
     'test-heap-profiler.cc',
+    'test-heap.cc',
     'test-list.cc',
     'test-liveedit.cc',
     'test-lock.cc',
-    'test-log.cc',
     'test-log-utils.cc',
+    'test-log.cc',
     'test-mark-compact.cc',
     'test-parsing.cc',
+    'test-platform-tls.cc',
     'test-profile-generator.cc',
     'test-regexp.cc',
     'test-reloc-info.cc',
@@ -95,7 +96,7 @@
   'arch:x64': ['test-assembler-x64.cc',
                'test-macro-assembler-x64.cc',
                'test-log-stack-tracer.cc'],
-  'arch:mips': ['test-assembler-mips.cc', 'test-mips.cc'],
+  'arch:mips': ['test-assembler-mips.cc'],
   'os:linux':  ['test-platform-linux.cc'],
   'os:macos':  ['test-platform-macos.cc'],
   'os:nullos': ['test-platform-nullos.cc'],
diff --git a/test/cctest/cctest.h b/test/cctest/cctest.h
index 404b692..277593c 100644
--- a/test/cctest/cctest.h
+++ b/test/cctest/cctest.h
@@ -87,8 +87,9 @@
 class ApiTestFuzzer: public v8::internal::Thread {
  public:
   void CallTest();
-  explicit ApiTestFuzzer(int num)
-      : test_number_(num),
+  explicit ApiTestFuzzer(v8::internal::Isolate* isolate, int num)
+      : Thread(isolate, "ApiTestFuzzer"),
+        test_number_(num),
         gate_(v8::internal::OS::CreateSemaphore(0)),
         active_(true) {
   }
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index e573eb2..986fb8d 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -36,11 +36,6 @@
 # BUG(382): Weird test. Can't guarantee that it never times out.
 test-api/ApplyInterruption: PASS || TIMEOUT
 
-# BUG(484): This test which we thought was originally corrected in r5236
-# is re-appearing. Disabled until bug in test is fixed. This only fails
-# when snapshot is on, so I am marking it PASS || FAIL
-test-heap-profiler/HeapSnapshotsDiff: PASS || FAIL
-
 # These tests always fail.  They are here to test test.py.  If
 # they don't fail then test.py has failed.
 test-serialize/TestThatAlwaysFails: FAIL
@@ -62,12 +57,6 @@
 test-debug/DebuggerAgentProtocolOverflowHeader: SKIP
 test-sockets/Socket: SKIP
 
-# BUG(1075): Some deserialization tests fail om ARM
-test-serialize/Deserialize: SKIP
-test-serialize/DeserializeFromSecondSerializationAndRunScript2: SKIP
-test-serialize/DeserializeAndRunScript2: SKIP
-test-serialize/DeserializeFromSecondSerialization: SKIP
-
 ##############################################################################
 [ $arch == arm && $crankshaft ]
 
@@ -85,15 +74,21 @@
 test-cpu-profiler: SKIP
 test-debug: SKIP
 test-decls: SKIP
+test-deoptimization: SKIP
 test-func-name-inference: SKIP
 test-heap: SKIP
 test-heap-profiler: SKIP
 test-log: SKIP
 test-log-utils: SKIP
 test-mark-compact: SKIP
+test-parsing: SKIP
+test-profile-generator: SKIP
 test-regexp: SKIP
 test-serialize: SKIP
 test-sockets: SKIP
 test-strings: SKIP
 test-threads: SKIP
 test-thread-termination: SKIP
+
+##############################################################################
+# Tests that time out with Isolates
diff --git a/test/cctest/test-accessors.cc b/test/cctest/test-accessors.cc
index 25f5c39..b74f166 100644
--- a/test/cctest/test-accessors.cc
+++ b/test/cctest/test-accessors.cc
@@ -243,7 +243,7 @@
   ApiTestFuzzer::Fuzz();
   CHECK(info.This() == info.Holder());
   CHECK(info.Data()->Equals(v8::String::New("data")));
-  i::Heap::CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
   CHECK(info.This() == info.Holder());
   CHECK(info.Data()->Equals(v8::String::New("data")));
   return v8::Integer::New(17);
@@ -397,9 +397,9 @@
   for (int i = 0; !iter.done(); i++) {
     i::StackFrame* frame = iter.frame();
     CHECK(i != 0 || (frame->type() == i::StackFrame::EXIT));
-    CHECK(frame->code()->IsCode());
+    i::Code* code = frame->LookupCode(i::Isolate::Current());
+    CHECK(code->IsCode());
     i::Address pc = frame->pc();
-    i::Code* code = frame->code();
     CHECK(code->contains(pc));
     iter.Advance();
   }
diff --git a/test/cctest/test-alloc.cc b/test/cctest/test-alloc.cc
index d2a28d7..3d8157d 100644
--- a/test/cctest/test-alloc.cc
+++ b/test/cctest/test-alloc.cc
@@ -27,7 +27,6 @@
 
 #include "v8.h"
 #include "accessors.h"
-#include "top.h"
 
 #include "cctest.h"
 
@@ -38,13 +37,14 @@
 static MaybeObject* AllocateAfterFailures() {
   static int attempts = 0;
   if (++attempts < 3) return Failure::RetryAfterGC();
+  Heap* heap = Isolate::Current()->heap();
 
   // New space.
-  NewSpace* new_space = Heap::new_space();
+  NewSpace* new_space = heap->new_space();
   static const int kNewSpaceFillerSize = ByteArray::SizeFor(0);
   while (new_space->Available() > kNewSpaceFillerSize) {
     int available_before = static_cast<int>(new_space->Available());
-    CHECK(!Heap::AllocateByteArray(0)->IsFailure());
+    CHECK(!heap->AllocateByteArray(0)->IsFailure());
     if (available_before == new_space->Available()) {
       // It seems that we are avoiding new space allocations when
       // allocation is forced, so no need to fill up new space
@@ -52,45 +52,46 @@
       break;
     }
   }
-  CHECK(!Heap::AllocateByteArray(100)->IsFailure());
-  CHECK(!Heap::AllocateFixedArray(100, NOT_TENURED)->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())->ToObjectChecked();
-  CHECK(!Heap::CopyJSObject(JSObject::cast(object))->IsFailure());
+  CHECK(!heap->AllocateFixedArray(100)->IsFailure());
+  CHECK(!heap->AllocateHeapNumber(0.42)->IsFailure());
+  CHECK(!heap->AllocateArgumentsObject(Smi::FromInt(87), 10)->IsFailure());
+  Object* object = heap->AllocateJSObject(
+      *Isolate::Current()->object_function())->ToObjectChecked();
+  CHECK(!heap->CopyJSObject(JSObject::cast(object))->IsFailure());
 
   // Old data space.
-  OldSpace* old_data_space = Heap::old_data_space();
+  OldSpace* old_data_space = heap->old_data_space();
   static const int kOldDataSpaceFillerSize = ByteArray::SizeFor(0);
   while (old_data_space->Available() > kOldDataSpaceFillerSize) {
-    CHECK(!Heap::AllocateByteArray(0, TENURED)->IsFailure());
+    CHECK(!heap->AllocateByteArray(0, TENURED)->IsFailure());
   }
-  CHECK(!Heap::AllocateRawAsciiString(100, TENURED)->IsFailure());
+  CHECK(!heap->AllocateRawAsciiString(100, TENURED)->IsFailure());
 
   // Large object space.
-  while (!Heap::OldGenerationAllocationLimitReached()) {
-    CHECK(!Heap::AllocateFixedArray(10000, TENURED)->IsFailure());
+  while (!heap->OldGenerationAllocationLimitReached()) {
+    CHECK(!heap->AllocateFixedArray(10000, TENURED)->IsFailure());
   }
-  CHECK(!Heap::AllocateFixedArray(10000, TENURED)->IsFailure());
+  CHECK(!heap->AllocateFixedArray(10000, TENURED)->IsFailure());
 
   // Map space.
-  MapSpace* map_space = Heap::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());
   }
-  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());
+  CHECK(!heap->AllocateFixedArray(100, TENURED)->IsFailure());
+  CHECK(!heap->CopyCode(Isolate::Current()->builtins()->builtin(
+      Builtins::kIllegal))->IsFailure());
 
   // Return success.
   return Smi::FromInt(42);
@@ -98,7 +99,7 @@
 
 
 static Handle<Object> Test() {
-  CALL_HEAP_FUNCTION(AllocateAfterFailures(), Object);
+  CALL_HEAP_FUNCTION(ISOLATE, AllocateAfterFailures(), Object);
 }
 
 
@@ -129,18 +130,19 @@
   v8::HandleScope scope;
   env->Enter();
   Handle<JSFunction> function =
-      Factory::NewFunction(Factory::function_symbol(), Factory::null_value());
+      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->ReplaceCode(Builtins::builtin(Builtins::EmptyFunction));
+  FACTORY->NewJSObject(function);
+  function->ReplaceCode(Isolate::Current()->builtins()->builtin(
+      Builtins::kEmptyFunction));
   // 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(
+  Handle<Proxy> proxy = FACTORY->NewProxy(&kDescriptor);
+  instance_descriptors = FACTORY->CopyAppendProxyDescriptor(
       instance_descriptors,
-      Factory::NewStringFromAscii(Vector<const char>("get", 3)),
+      FACTORY->NewStringFromAscii(Vector<const char>("get", 3)),
       proxy,
       static_cast<PropertyAttributes>(0));
   map->set_instance_descriptors(*instance_descriptors);
@@ -183,7 +185,8 @@
 
 TEST(CodeRange) {
   const int code_range_size = 16*MB;
-  CodeRange::Setup(code_range_size);
+  OS::Setup();
+  Isolate::Current()->code_range()->Setup(code_range_size);
   int current_allocated = 0;
   int total_allocated = 0;
   List<Block> blocks(1000);
@@ -195,14 +198,16 @@
       size_t requested = (Page::kPageSize << (Pseudorandom() % 6)) +
            Pseudorandom() % 5000 + 1;
       size_t allocated = 0;
-      void* base = CodeRange::AllocateRawMemory(requested, &allocated);
+      void* base = Isolate::Current()->code_range()->
+          AllocateRawMemory(requested, &allocated);
       blocks.Add(Block(base, static_cast<int>(allocated)));
       current_allocated += static_cast<int>(allocated);
       total_allocated += static_cast<int>(allocated);
     } else {
       // Free a block.
       int index = Pseudorandom() % blocks.length();
-      CodeRange::FreeRawMemory(blocks[index].base, blocks[index].size);
+      Isolate::Current()->code_range()->FreeRawMemory(
+          blocks[index].base, blocks[index].size);
       current_allocated -= blocks[index].size;
       if (index < blocks.length() - 1) {
         blocks[index] = blocks.RemoveLast();
@@ -212,5 +217,5 @@
     }
   }
 
-  CodeRange::TearDown();
+  Isolate::Current()->code_range()->TearDown();
 }
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index cd26412..33d505e 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -34,7 +34,6 @@
 #include "execution.h"
 #include "snapshot.h"
 #include "platform.h"
-#include "top.h"
 #include "utils.h"
 #include "cctest.h"
 #include "parser.h"
@@ -50,15 +49,19 @@
 #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::Context;
 using ::v8::Extension;
+using ::v8::Function;
+using ::v8::HandleScope;
+using ::v8::Local;
+using ::v8::Object;
+using ::v8::ObjectTemplate;
+using ::v8::Persistent;
+using ::v8::Script;
+using ::v8::String;
+using ::v8::Value;
+using ::v8::V8;
 
 namespace i = ::i;
 
@@ -394,11 +397,11 @@
     CHECK(source->IsExternal());
     CHECK_EQ(resource,
              static_cast<TestResource*>(source->GetExternalStringResource()));
-    i::Heap::CollectAllGarbage(false);
+    HEAP->CollectAllGarbage(false);
     CHECK_EQ(0, TestResource::dispose_count);
   }
-  i::CompilationCache::Clear();
-  i::Heap::CollectAllGarbage(false);
+  v8::internal::Isolate::Current()->compilation_cache()->Clear();
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(1, TestResource::dispose_count);
 }
 
@@ -415,11 +418,11 @@
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(7, value->Int32Value());
-    i::Heap::CollectAllGarbage(false);
+    HEAP->CollectAllGarbage(false);
     CHECK_EQ(0, TestAsciiResource::dispose_count);
   }
-  i::CompilationCache::Clear();
-  i::Heap::CollectAllGarbage(false);
+  i::Isolate::Current()->compilation_cache()->Clear();
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(1, TestAsciiResource::dispose_count);
 }
 
@@ -432,19 +435,19 @@
     LocalContext env;
     Local<String> source = String::New(two_byte_source);
     // Trigger GCs so that the newly allocated string moves to old gen.
-    i::Heap::CollectGarbage(i::NEW_SPACE);  // in survivor space now
-    i::Heap::CollectGarbage(i::NEW_SPACE);  // in old gen now
+    HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
+    HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
     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());
-    i::Heap::CollectAllGarbage(false);
+    HEAP->CollectAllGarbage(false);
     CHECK_EQ(0, TestResource::dispose_count);
   }
-  i::CompilationCache::Clear();
-  i::Heap::CollectAllGarbage(false);
+  i::Isolate::Current()->compilation_cache()->Clear();
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(1, TestResource::dispose_count);
 }
 
@@ -457,8 +460,8 @@
     LocalContext env;
     Local<String> source = v8_str(c_source);
     // Trigger GCs so that the newly allocated string moves to old gen.
-    i::Heap::CollectGarbage(i::NEW_SPACE);  // in survivor space now
-    i::Heap::CollectGarbage(i::NEW_SPACE);  // in old gen now
+    HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
+    HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
     bool success = source->MakeExternal(
         new TestAsciiResource(i::StrDup(c_source)));
     CHECK(success);
@@ -466,11 +469,11 @@
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(7, value->Int32Value());
-    i::Heap::CollectAllGarbage(false);
+    HEAP->CollectAllGarbage(false);
     CHECK_EQ(0, TestAsciiResource::dispose_count);
   }
-  i::CompilationCache::Clear();
-  i::Heap::CollectAllGarbage(false);
+  i::Isolate::Current()->compilation_cache()->Clear();
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(1, TestAsciiResource::dispose_count);
 }
 
@@ -480,8 +483,8 @@
   LocalContext env;
 
   // Free some space in the new space so that we can check freshness.
-  i::Heap::CollectGarbage(i::NEW_SPACE);
-  i::Heap::CollectGarbage(i::NEW_SPACE);
+  HEAP->CollectGarbage(i::NEW_SPACE);
+  HEAP->CollectGarbage(i::NEW_SPACE);
 
   uint16_t* two_byte_string = AsciiToTwoByteString("small");
   Local<String> small_string = String::New(two_byte_string);
@@ -490,8 +493,8 @@
   // We should refuse to externalize newly created small string.
   CHECK(!small_string->CanMakeExternal());
   // Trigger GCs so that the newly allocated string moves to old gen.
-  i::Heap::CollectGarbage(i::NEW_SPACE);  // in survivor space now
-  i::Heap::CollectGarbage(i::NEW_SPACE);  // in old gen now
+  HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
+  HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
   // Old space strings should be accepted.
   CHECK(small_string->CanMakeExternal());
 
@@ -526,15 +529,15 @@
   LocalContext env;
 
   // Free some space in the new space so that we can check freshness.
-  i::Heap::CollectGarbage(i::NEW_SPACE);
-  i::Heap::CollectGarbage(i::NEW_SPACE);
+  HEAP->CollectGarbage(i::NEW_SPACE);
+  HEAP->CollectGarbage(i::NEW_SPACE);
 
   Local<String> small_string = String::New("small");
   // We should refuse to externalize newly created small string.
   CHECK(!small_string->CanMakeExternal());
   // Trigger GCs so that the newly allocated string moves to old gen.
-  i::Heap::CollectGarbage(i::NEW_SPACE);  // in survivor space now
-  i::Heap::CollectGarbage(i::NEW_SPACE);  // in old gen now
+  HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
+  HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
   // Old space strings should be accepted.
   CHECK(small_string->CanMakeExternal());
 
@@ -566,13 +569,13 @@
         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(i::NEW_SPACE);  // in survivor space now
-    i::Heap::CollectGarbage(i::NEW_SPACE);  // in old gen now
-    i::Handle<i::String> isymbol = i::Factory::SymbolFromString(istring);
+    HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
+    HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
+    i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring);
     CHECK(isymbol->IsSymbol());
   }
-  i::Heap::CollectAllGarbage(false);
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 }
 
 
@@ -584,13 +587,13 @@
         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(i::NEW_SPACE);  // in survivor space now
-    i::Heap::CollectGarbage(i::NEW_SPACE);  // in old gen now
-    i::Handle<i::String> isymbol = i::Factory::SymbolFromString(istring);
+    HEAP->CollectGarbage(i::NEW_SPACE);  // in survivor space now
+    HEAP->CollectGarbage(i::NEW_SPACE);  // in old gen now
+    i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring);
     CHECK(isymbol->IsSymbol());
   }
-  i::Heap::CollectAllGarbage(false);
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 }
 
 
@@ -603,12 +606,12 @@
     Local<String> string =
         String::NewExternal(new TestResource(two_byte_string));
     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
-    i::Heap::CollectGarbage(i::NEW_SPACE);
-    in_new_space = i::Heap::InNewSpace(*istring);
-    CHECK(in_new_space || i::Heap::old_data_space()->Contains(*istring));
+    HEAP->CollectGarbage(i::NEW_SPACE);
+    in_new_space = HEAP->InNewSpace(*istring);
+    CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
     CHECK_EQ(0, TestResource::dispose_count);
   }
-  i::Heap::CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
+  HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
   CHECK_EQ(1, TestResource::dispose_count);
 }
 
@@ -622,12 +625,12 @@
     Local<String> string = String::NewExternal(
         new TestAsciiResource(i::StrDup(one_byte_string)));
     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
-    i::Heap::CollectGarbage(i::NEW_SPACE);
-    in_new_space = i::Heap::InNewSpace(*istring);
-    CHECK(in_new_space || i::Heap::old_data_space()->Contains(*istring));
+    HEAP->CollectGarbage(i::NEW_SPACE);
+    in_new_space = HEAP->InNewSpace(*istring);
+    CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
     CHECK_EQ(0, TestAsciiResource::dispose_count);
   }
-  i::Heap::CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
+  HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
   CHECK_EQ(1, TestAsciiResource::dispose_count);
 }
 
@@ -667,11 +670,11 @@
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(7, value->Int32Value());
-    i::Heap::CollectAllGarbage(false);
+    HEAP->CollectAllGarbage(false);
     CHECK_EQ(0, TestAsciiResource::dispose_count);
   }
-  i::CompilationCache::Clear();
-  i::Heap::CollectAllGarbage(false);
+  i::Isolate::Current()->compilation_cache()->Clear();
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
   CHECK_EQ(0, TestAsciiResource::dispose_count);
 
@@ -688,11 +691,11 @@
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(7, value->Int32Value());
-    i::Heap::CollectAllGarbage(false);
+    HEAP->CollectAllGarbage(false);
     CHECK_EQ(0, TestAsciiResource::dispose_count);
   }
-  i::CompilationCache::Clear();
-  i::Heap::CollectAllGarbage(false);
+  i::Isolate::Current()->compilation_cache()->Clear();
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
   CHECK_EQ(1, TestAsciiResource::dispose_count);
 }
@@ -738,9 +741,9 @@
     CHECK(value->IsNumber());
     CHECK_EQ(68, value->Int32Value());
   }
-  i::CompilationCache::Clear();
-  i::Heap::CollectAllGarbage(false);
-  i::Heap::CollectAllGarbage(false);
+  i::Isolate::Current()->compilation_cache()->Clear();
+  HEAP->CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 }
 
 
@@ -1575,12 +1578,12 @@
 
   // Check reading and writing aligned pointers.
   obj->SetPointerInInternalField(0, aligned);
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(aligned, obj->GetPointerFromInternalField(0));
 
   // Check reading and writing unaligned pointers.
   obj->SetPointerInInternalField(0, unaligned);
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0));
 
   delete[] data;
@@ -1606,19 +1609,19 @@
   CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1));
 
   obj->SetPointerInInternalField(0, aligned);
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(aligned, v8::External::Unwrap(obj->GetInternalField(0)));
 
   obj->SetPointerInInternalField(0, unaligned);
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(unaligned, v8::External::Unwrap(obj->GetInternalField(0)));
 
   obj->SetInternalField(0, v8::External::Wrap(aligned));
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(aligned, obj->GetPointerFromInternalField(0));
 
   obj->SetInternalField(0, v8::External::Wrap(unaligned));
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0));
 
   delete[] data;
@@ -1631,7 +1634,7 @@
 
   // Ensure that the test starts with an fresh heap to test whether the hash
   // code is based on the address.
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   Local<v8::Object> obj = v8::Object::New();
   int hash = obj->GetIdentityHash();
   int hash1 = obj->GetIdentityHash();
@@ -1641,7 +1644,7 @@
   // 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(false);
+  HEAP->CollectAllGarbage(false);
   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
@@ -1678,7 +1681,7 @@
   v8::Local<v8::String> empty = v8_str("");
   v8::Local<v8::String> prop_name = v8_str("prop_name");
 
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 
   // Make sure delete of a non-existent hidden value works
   CHECK(obj->DeleteHiddenValue(key));
@@ -1688,7 +1691,7 @@
   CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
 
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 
   // Make sure we do not find the hidden property.
   CHECK(!obj->Has(empty));
@@ -1699,7 +1702,7 @@
   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
   CHECK_EQ(2003, obj->Get(empty)->Int32Value());
 
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 
   // Add another property and delete it afterwards to force the object in
   // slow case.
@@ -1710,7 +1713,7 @@
   CHECK(obj->Delete(prop_name));
   CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
 
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 
   CHECK(obj->DeleteHiddenValue(key));
   CHECK(obj->GetHiddenValue(key).IsEmpty());
@@ -1789,6 +1792,180 @@
 }
 
 
+static int NumberOfWeakCalls = 0;
+static void WeakPointerCallback(Persistent<Value> handle, void* id) {
+  CHECK_EQ(reinterpret_cast<void*>(1234), id);
+  NumberOfWeakCalls++;
+  handle.Dispose();
+}
+
+THREADED_TEST(ApiObjectGroups) {
+  HandleScope scope;
+  LocalContext env;
+
+  NumberOfWeakCalls = 0;
+
+  Persistent<Object> g1s1;
+  Persistent<Object> g1s2;
+  Persistent<Object> g1c1;
+  Persistent<Object> g2s1;
+  Persistent<Object> g2s2;
+  Persistent<Object> g2c1;
+
+  {
+    HandleScope scope;
+    g1s1 = Persistent<Object>::New(Object::New());
+    g1s2 = Persistent<Object>::New(Object::New());
+    g1c1 = Persistent<Object>::New(Object::New());
+    g1s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+    g1s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+    g1c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+
+    g2s1 = Persistent<Object>::New(Object::New());
+    g2s2 = Persistent<Object>::New(Object::New());
+    g2c1 = Persistent<Object>::New(Object::New());
+    g2s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+    g2s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+    g2c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+  }
+
+  Persistent<Object> root = Persistent<Object>::New(g1s1);  // make a root.
+
+  // Connect group 1 and 2, make a cycle.
+  CHECK(g1s2->Set(0, g2s2));
+  CHECK(g2s1->Set(0, g1s1));
+
+  {
+    Persistent<Value> g1_objects[] = { g1s1, g1s2 };
+    Persistent<Value> g1_children[] = { g1c1 };
+    Persistent<Value> g2_objects[] = { g2s1, g2s2 };
+    Persistent<Value> g2_children[] = { g2c1 };
+    V8::AddObjectGroup(g1_objects, 2);
+    V8::AddImplicitReferences(g1s1, g1_children, 1);
+    V8::AddObjectGroup(g2_objects, 2);
+    V8::AddImplicitReferences(g2s2, g2_children, 1);
+  }
+  // Do a full GC
+  HEAP->CollectGarbage(i::OLD_POINTER_SPACE);
+
+  // All object should be alive.
+  CHECK_EQ(0, NumberOfWeakCalls);
+
+  // Weaken the root.
+  root.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+  // But make children strong roots---all the objects (except for children)
+  // should be collectable now.
+  g1c1.ClearWeak();
+  g2c1.ClearWeak();
+
+  // Groups are deleted, rebuild groups.
+  {
+    Persistent<Value> g1_objects[] = { g1s1, g1s2 };
+    Persistent<Value> g1_children[] = { g1c1 };
+    Persistent<Value> g2_objects[] = { g2s1, g2s2 };
+    Persistent<Value> g2_children[] = { g2c1 };
+    V8::AddObjectGroup(g1_objects, 2);
+    V8::AddImplicitReferences(g1s1, g1_children, 1);
+    V8::AddObjectGroup(g2_objects, 2);
+    V8::AddImplicitReferences(g2s2, g2_children, 1);
+  }
+
+  HEAP->CollectGarbage(i::OLD_POINTER_SPACE);
+
+  // All objects should be gone. 5 global handles in total.
+  CHECK_EQ(5, NumberOfWeakCalls);
+
+  // And now make children weak again and collect them.
+  g1c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+  g2c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+
+  HEAP->CollectGarbage(i::OLD_POINTER_SPACE);
+  CHECK_EQ(7, NumberOfWeakCalls);
+}
+
+
+THREADED_TEST(ApiObjectGroupsCycle) {
+  HandleScope scope;
+  LocalContext env;
+
+  NumberOfWeakCalls = 0;
+
+  Persistent<Object> g1s1;
+  Persistent<Object> g1s2;
+  Persistent<Object> g2s1;
+  Persistent<Object> g2s2;
+  Persistent<Object> g3s1;
+  Persistent<Object> g3s2;
+
+  {
+    HandleScope scope;
+    g1s1 = Persistent<Object>::New(Object::New());
+    g1s2 = Persistent<Object>::New(Object::New());
+    g1s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+    g1s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+
+    g2s1 = Persistent<Object>::New(Object::New());
+    g2s2 = Persistent<Object>::New(Object::New());
+    g2s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+    g2s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+
+    g3s1 = Persistent<Object>::New(Object::New());
+    g3s2 = Persistent<Object>::New(Object::New());
+    g3s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+    g3s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+  }
+
+  Persistent<Object> root = Persistent<Object>::New(g1s1);  // make a root.
+
+  // Connect groups.  We're building the following cycle:
+  // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
+  // groups.
+  {
+    Persistent<Value> g1_objects[] = { g1s1, g1s2 };
+    Persistent<Value> g1_children[] = { g2s1 };
+    Persistent<Value> g2_objects[] = { g2s1, g2s2 };
+    Persistent<Value> g2_children[] = { g3s1 };
+    Persistent<Value> g3_objects[] = { g3s1, g3s2 };
+    Persistent<Value> g3_children[] = { g1s1 };
+    V8::AddObjectGroup(g1_objects, 2);
+    V8::AddImplicitReferences(g1s1, g1_children, 1);
+    V8::AddObjectGroup(g2_objects, 2);
+    V8::AddImplicitReferences(g2s1, g2_children, 1);
+    V8::AddObjectGroup(g3_objects, 2);
+    V8::AddImplicitReferences(g3s1, g3_children, 1);
+  }
+  // Do a full GC
+  HEAP->CollectGarbage(i::OLD_POINTER_SPACE);
+
+  // All object should be alive.
+  CHECK_EQ(0, NumberOfWeakCalls);
+
+  // Weaken the root.
+  root.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
+
+  // Groups are deleted, rebuild groups.
+  {
+    Persistent<Value> g1_objects[] = { g1s1, g1s2 };
+    Persistent<Value> g1_children[] = { g2s1 };
+    Persistent<Value> g2_objects[] = { g2s1, g2s2 };
+    Persistent<Value> g2_children[] = { g3s1 };
+    Persistent<Value> g3_objects[] = { g3s1, g3s2 };
+    Persistent<Value> g3_children[] = { g1s1 };
+    V8::AddObjectGroup(g1_objects, 2);
+    V8::AddImplicitReferences(g1s1, g1_children, 1);
+    V8::AddObjectGroup(g2_objects, 2);
+    V8::AddImplicitReferences(g2s1, g2_children, 1);
+    V8::AddObjectGroup(g3_objects, 2);
+    V8::AddImplicitReferences(g3s1, g3_children, 1);
+  }
+
+  HEAP->CollectGarbage(i::OLD_POINTER_SPACE);
+
+  // All objects should be gone. 7 global handles in total.
+  CHECK_EQ(7, NumberOfWeakCalls);
+}
+
+
 THREADED_TEST(ScriptException) {
   v8::HandleScope scope;
   LocalContext env;
@@ -1900,6 +2077,10 @@
   CHECK_EQ(1, arr->Get(0)->Int32Value());
   CHECK_EQ(2, arr->Get(1)->Int32Value());
   CHECK_EQ(3, arr->Get(2)->Int32Value());
+  array = v8::Array::New(27);
+  CHECK_EQ(27, array->Length());
+  array = v8::Array::New(-27);
+  CHECK_EQ(0, array->Length());
 }
 
 
@@ -2082,8 +2263,6 @@
 TEST(HugeConsStringOutOfMemory) {
   // It's not possible to read a snapshot into a heap with different dimensions.
   if (i::Snapshot::IsEnabled()) return;
-  v8::HandleScope scope;
-  LocalContext context;
   // Set heap limits.
   static const int K = 1024;
   v8::ResourceConstraints constraints;
@@ -2094,6 +2273,9 @@
   // Execute a script that causes out of memory.
   v8::V8::IgnoreOutOfMemoryException();
 
+  v8::HandleScope scope;
+  LocalContext context;
+
   // 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();"
@@ -2513,7 +2695,7 @@
       if (try_catch.HasCaught()) {
         CHECK_EQ(expected, count);
         CHECK(result.IsEmpty());
-        CHECK(!i::Top::has_scheduled_exception());
+        CHECK(!i::Isolate::Current()->has_scheduled_exception());
       } else {
         CHECK_NE(expected, count);
       }
@@ -3688,10 +3870,8 @@
 
   source = v8_str("undetectable.y = 2000;");
   script = Script::Compile(source);
-  v8::TryCatch try_catch;
   Local<Value> result = script->Run();
-  CHECK(result.IsEmpty());
-  CHECK(try_catch.HasCaught());
+  ExpectBoolean("undetectable.y == undefined", true);
 }
 
 
@@ -4205,7 +4385,7 @@
   obj.Dispose();
   obj.Clear();
   in_scavenge = true;
-  i::Heap::PerformScavenge();
+  HEAP->PerformScavenge();
   in_scavenge = false;
   *(reinterpret_cast<bool*>(data)) = true;
 }
@@ -4242,7 +4422,7 @@
   object_b.MakeWeak(&released_in_scavenge, &CheckIsNotInvokedInScavenge);
 
   while (!object_a_disposed) {
-    i::Heap::CollectAllGarbage(false);
+    HEAP->CollectAllGarbage(false);
   }
   CHECK(!released_in_scavenge);
 }
@@ -4260,7 +4440,7 @@
   CHECK_EQ(v8::Integer::New(3), args[2]);
   CHECK_EQ(v8::Undefined(), args[3]);
   v8::HandleScope scope;
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   return v8::Undefined();
 }
 
@@ -4562,130 +4742,130 @@
 
   memset(utf8buf, 0x1, sizeof(utf8buf));
   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
-  CHECK_EQ(len, 9);
-  CHECK_EQ(charlen, 5);
-  CHECK_EQ(strcmp(utf8buf, "abc\303\260\342\230\203"), 0);
+  CHECK_EQ(9, len);
+  CHECK_EQ(5, charlen);
+  CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
 
   memset(utf8buf, 0x1, sizeof(utf8buf));
   len = str2->WriteUtf8(utf8buf, 8, &charlen);
-  CHECK_EQ(len, 8);
-  CHECK_EQ(charlen, 5);
-  CHECK_EQ(strncmp(utf8buf, "abc\303\260\342\230\203\1", 9), 0);
+  CHECK_EQ(8, len);
+  CHECK_EQ(5, charlen);
+  CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
 
   memset(utf8buf, 0x1, sizeof(utf8buf));
   len = str2->WriteUtf8(utf8buf, 7, &charlen);
-  CHECK_EQ(len, 5);
-  CHECK_EQ(charlen, 4);
-  CHECK_EQ(strncmp(utf8buf, "abc\303\260\1", 5), 0);
+  CHECK_EQ(5, len);
+  CHECK_EQ(4, charlen);
+  CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
 
   memset(utf8buf, 0x1, sizeof(utf8buf));
   len = str2->WriteUtf8(utf8buf, 6, &charlen);
-  CHECK_EQ(len, 5);
-  CHECK_EQ(charlen, 4);
-  CHECK_EQ(strncmp(utf8buf, "abc\303\260\1", 5), 0);
+  CHECK_EQ(5, len);
+  CHECK_EQ(4, charlen);
+  CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
 
   memset(utf8buf, 0x1, sizeof(utf8buf));
   len = str2->WriteUtf8(utf8buf, 5, &charlen);
-  CHECK_EQ(len, 5);
-  CHECK_EQ(charlen, 4);
-  CHECK_EQ(strncmp(utf8buf, "abc\303\260\1", 5), 0);
+  CHECK_EQ(5, len);
+  CHECK_EQ(4, charlen);
+  CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
 
   memset(utf8buf, 0x1, sizeof(utf8buf));
   len = str2->WriteUtf8(utf8buf, 4, &charlen);
-  CHECK_EQ(len, 3);
-  CHECK_EQ(charlen, 3);
-  CHECK_EQ(strncmp(utf8buf, "abc\1", 4), 0);
+  CHECK_EQ(3, len);
+  CHECK_EQ(3, charlen);
+  CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
 
   memset(utf8buf, 0x1, sizeof(utf8buf));
   len = str2->WriteUtf8(utf8buf, 3, &charlen);
-  CHECK_EQ(len, 3);
-  CHECK_EQ(charlen, 3);
-  CHECK_EQ(strncmp(utf8buf, "abc\1", 4), 0);
+  CHECK_EQ(3, len);
+  CHECK_EQ(3, charlen);
+  CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
 
   memset(utf8buf, 0x1, sizeof(utf8buf));
   len = str2->WriteUtf8(utf8buf, 2, &charlen);
-  CHECK_EQ(len, 2);
-  CHECK_EQ(charlen, 2);
-  CHECK_EQ(strncmp(utf8buf, "ab\1", 3), 0);
+  CHECK_EQ(2, len);
+  CHECK_EQ(2, charlen);
+  CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
 
   memset(buf, 0x1, sizeof(buf));
   memset(wbuf, 0x1, sizeof(wbuf));
   len = str->WriteAscii(buf);
-  CHECK_EQ(len, 5);
+  CHECK_EQ(5, len);
   len = str->Write(wbuf);
-  CHECK_EQ(len, 5);
-  CHECK_EQ(strcmp("abcde", buf), 0);
+  CHECK_EQ(5, len);
+  CHECK_EQ(0, strcmp("abcde", buf));
   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
-  CHECK_EQ(StrCmp16(answer1, wbuf), 0);
+  CHECK_EQ(0, StrCmp16(answer1, wbuf));
 
   memset(buf, 0x1, sizeof(buf));
   memset(wbuf, 0x1, sizeof(wbuf));
   len = str->WriteAscii(buf, 0, 4);
-  CHECK_EQ(len, 4);
+  CHECK_EQ(4, len);
   len = str->Write(wbuf, 0, 4);
-  CHECK_EQ(len, 4);
-  CHECK_EQ(strncmp("abcd\1", buf, 5), 0);
+  CHECK_EQ(4, len);
+  CHECK_EQ(0, strncmp("abcd\1", buf, 5));
   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
-  CHECK_EQ(StrNCmp16(answer2, wbuf, 5), 0);
+  CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
 
   memset(buf, 0x1, sizeof(buf));
   memset(wbuf, 0x1, sizeof(wbuf));
   len = str->WriteAscii(buf, 0, 5);
-  CHECK_EQ(len, 5);
+  CHECK_EQ(5, len);
   len = str->Write(wbuf, 0, 5);
-  CHECK_EQ(len, 5);
-  CHECK_EQ(strncmp("abcde\1", buf, 6), 0);
+  CHECK_EQ(5, len);
+  CHECK_EQ(0, strncmp("abcde\1", buf, 6));
   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
-  CHECK_EQ(StrNCmp16(answer3, wbuf, 6), 0);
+  CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
 
   memset(buf, 0x1, sizeof(buf));
   memset(wbuf, 0x1, sizeof(wbuf));
   len = str->WriteAscii(buf, 0, 6);
-  CHECK_EQ(len, 5);
+  CHECK_EQ(5, len);
   len = str->Write(wbuf, 0, 6);
-  CHECK_EQ(len, 5);
-  CHECK_EQ(strcmp("abcde", buf), 0);
+  CHECK_EQ(5, len);
+  CHECK_EQ(0, strcmp("abcde", buf));
   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
-  CHECK_EQ(StrCmp16(answer4, wbuf), 0);
+  CHECK_EQ(0, StrCmp16(answer4, wbuf));
 
   memset(buf, 0x1, sizeof(buf));
   memset(wbuf, 0x1, sizeof(wbuf));
   len = str->WriteAscii(buf, 4, -1);
-  CHECK_EQ(len, 1);
+  CHECK_EQ(1, len);
   len = str->Write(wbuf, 4, -1);
-  CHECK_EQ(len, 1);
-  CHECK_EQ(strcmp("e", buf), 0);
+  CHECK_EQ(1, len);
+  CHECK_EQ(0, strcmp("e", buf));
   uint16_t answer5[] = {'e', '\0'};
-  CHECK_EQ(StrCmp16(answer5, wbuf), 0);
+  CHECK_EQ(0, StrCmp16(answer5, wbuf));
 
   memset(buf, 0x1, sizeof(buf));
   memset(wbuf, 0x1, sizeof(wbuf));
   len = str->WriteAscii(buf, 4, 6);
-  CHECK_EQ(len, 1);
+  CHECK_EQ(1, len);
   len = str->Write(wbuf, 4, 6);
-  CHECK_EQ(len, 1);
-  CHECK_EQ(strcmp("e", buf), 0);
-  CHECK_EQ(StrCmp16(answer5, wbuf), 0);
+  CHECK_EQ(1, len);
+  CHECK_EQ(0, strcmp("e", buf));
+  CHECK_EQ(0, StrCmp16(answer5, wbuf));
 
   memset(buf, 0x1, sizeof(buf));
   memset(wbuf, 0x1, sizeof(wbuf));
   len = str->WriteAscii(buf, 4, 1);
-  CHECK_EQ(len, 1);
+  CHECK_EQ(1, len);
   len = str->Write(wbuf, 4, 1);
-  CHECK_EQ(len, 1);
-  CHECK_EQ(strncmp("e\1", buf, 2), 0);
+  CHECK_EQ(1, len);
+  CHECK_EQ(0, strncmp("e\1", buf, 2));
   uint16_t answer6[] = {'e', 0x101};
-  CHECK_EQ(StrNCmp16(answer6, wbuf, 2), 0);
+  CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
 
   memset(buf, 0x1, sizeof(buf));
   memset(wbuf, 0x1, sizeof(wbuf));
   len = str->WriteAscii(buf, 3, 1);
-  CHECK_EQ(len, 1);
+  CHECK_EQ(1, len);
   len = str->Write(wbuf, 3, 1);
-  CHECK_EQ(len, 1);
-  CHECK_EQ(strncmp("d\1", buf, 2), 0);
+  CHECK_EQ(1, len);
+  CHECK_EQ(0, strncmp("d\1", buf, 2));
   uint16_t answer7[] = {'d', 0x101};
-  CHECK_EQ(StrNCmp16(answer7, wbuf, 2), 0);
+  CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
 }
 
 
@@ -5659,6 +5839,14 @@
   global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
                                            IndexedAccessBlocker);
 
+  // Add accessible accessor.
+  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,
@@ -5699,6 +5887,18 @@
 
   CompileRun("Object.seal(other)");
   ExpectTrue("Object.isExtensible(other)");
+
+  // Regression test for issue 1250.
+  // Make sure that we can set the accessible accessors value using normal
+  // assignment.
+  CompileRun("other.accessible_prop = 42");
+  CHECK_EQ(42, g_echo_value);
+
+  v8::Handle<Value> value;
+  // We follow Safari in ignoring assignments to host object accessors.
+  CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
+  value = CompileRun("other.accessible_prop == 42");
+  CHECK(value->IsTrue());
 }
 
 
@@ -6481,7 +6681,7 @@
   v8::TryCatch try_catch;
   CHECK(!o1->SetPrototype(o0));
   CHECK(!try_catch.HasCaught());
-  ASSERT(!i::Top::has_pending_exception());
+  ASSERT(!i::Isolate::Current()->has_pending_exception());
 
   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
 }
@@ -6863,7 +7063,7 @@
     Local<String> name,
     const AccessorInfo& info) {
   ApiTestFuzzer::Fuzz();
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   return v8::Handle<Value>();
 }
 
@@ -7593,7 +7793,7 @@
   int* call_count = reinterpret_cast<int*>(v8::External::Unwrap(info.Data()));
   ++(*call_count);
   if ((*call_count) % 20 == 0) {
-    i::Heap::CollectAllGarbage(true);
+    HEAP->CollectAllGarbage(true);
   }
   return v8::Handle<Value>();
 }
@@ -7631,7 +7831,7 @@
 v8::Handle<v8::Value> DirectApiCallback(const v8::Arguments& args) {
   static int count = 0;
   if (count++ % 3 == 0) {
-    i::Heap::CollectAllGarbage(true);  // This should move the stub
+    HEAP->  CollectAllGarbage(true);  // This should move the stub
     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
   }
   return v8::Handle<v8::Value>();
@@ -7686,7 +7886,7 @@
 v8::Handle<v8::Value> DirectGetterCallback(Local<String> name,
                                            const v8::AccessorInfo& info) {
   if (++p_getter_count % 3 == 0) {
-    i::Heap::CollectAllGarbage(true);
+    HEAP->CollectAllGarbage(true);
     GenerateSomeGarbage();
   }
   return v8::Handle<v8::Value>();
@@ -8601,7 +8801,8 @@
       : 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);
+    RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(
+        i::Isolate::Current(), i + start);
   }
   for (int i = 0; i < active_tests_; i++) {
     RegisterThreadedTest::nth(i)->fuzzer_->Start();
@@ -8823,11 +9024,11 @@
   // 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.
-  i::Heap::CollectAllGarbage(false);
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   int count = GetGlobalObjectsCount();
 #ifdef DEBUG
-  if (count != expected) i::Heap::TracePathToGlobal();
+  if (count != expected) HEAP->TracePathToGlobal();
 #endif
   CHECK_EQ(expected, count);
 }
@@ -8893,7 +9094,7 @@
   // weak callback of the first handle would be able to 'reallocate' it.
   handle1.MakeWeak(NULL, NewPersistentHandleCallback);
   handle2.Dispose();
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 }
 
 
@@ -8901,7 +9102,7 @@
 
 void DisposeAndForceGcCallback(v8::Persistent<v8::Value> handle, void*) {
   to_be_disposed.Dispose();
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   handle.Dispose();
 }
 
@@ -8917,7 +9118,7 @@
   }
   handle1.MakeWeak(NULL, DisposeAndForceGcCallback);
   to_be_disposed = handle2;
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 }
 
 void DisposingCallback(v8::Persistent<v8::Value> handle, void*) {
@@ -8943,7 +9144,7 @@
   }
   handle2.MakeWeak(NULL, DisposingCallback);
   handle3.MakeWeak(NULL, HandleCreatingCallback);
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 }
 
 
@@ -9189,6 +9390,31 @@
   CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3);
 }
 
+THREADED_TEST(PropertyEnumeration2) {
+  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 = obj.As<v8::Array>();
+  CHECK_EQ(4, elms->Length());
+  int elmc0 = 0;
+  const char** elmv0 = NULL;
+  CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
+
+  v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(0));
+  v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
+  CHECK_EQ(0, props->Length());
+  for (uint32_t i = 0; i < props->Length(); i++) {
+    printf("p[%d]\n", i);
+  }
+}
 
 static bool NamedSetAccessBlocker(Local<v8::Object> obj,
                                   Local<Value> name,
@@ -9681,7 +9907,7 @@
     gc_during_regexp_ = 0;
     regexp_success_ = false;
     gc_success_ = false;
-    GCThread gc_thread(this);
+    GCThread gc_thread(i::Isolate::Current(), this);
     gc_thread.Start();
     v8::Locker::StartPreemption(1);
 
@@ -9700,8 +9926,8 @@
 
   class GCThread : public i::Thread {
    public:
-    explicit GCThread(RegExpInterruptTest* test)
-        : test_(test) {}
+    explicit GCThread(i::Isolate* isolate, RegExpInterruptTest* test)
+        : Thread(isolate, "GCThread"), test_(test) {}
     virtual void Run() {
       test_->CollectGarbage();
     }
@@ -9715,7 +9941,7 @@
       {
         v8::Locker lock;
         // TODO(lrn): Perhaps create some garbage before collecting.
-        i::Heap::CollectAllGarbage(false);
+        HEAP->CollectAllGarbage(false);
         gc_count_++;
       }
       i::OS::Sleep(1);
@@ -9803,7 +10029,7 @@
     gc_during_apply_ = 0;
     apply_success_ = false;
     gc_success_ = false;
-    GCThread gc_thread(this);
+    GCThread gc_thread(i::Isolate::Current(), this);
     gc_thread.Start();
     v8::Locker::StartPreemption(1);
 
@@ -9822,8 +10048,8 @@
 
   class GCThread : public i::Thread {
    public:
-    explicit GCThread(ApplyInterruptTest* test)
-        : test_(test) {}
+    explicit GCThread(i::Isolate* isolate, ApplyInterruptTest* test)
+        : Thread(isolate, "GCThread"), test_(test) {}
     virtual void Run() {
       test_->CollectGarbage();
     }
@@ -9836,7 +10062,7 @@
     while (gc_during_apply_ < kRequiredGCs) {
       {
         v8::Locker lock;
-        i::Heap::CollectAllGarbage(false);
+        HEAP->CollectAllGarbage(false);
         gc_count_++;
       }
       i::OS::Sleep(1);
@@ -9965,17 +10191,17 @@
   CHECK(i::StringShape(string).IsExternal());
   if (string->IsAsciiRepresentation()) {
     // Check old map is not symbol or long.
-    CHECK(string->map() == i::Heap::external_ascii_string_map());
+    CHECK(string->map() == HEAP->external_ascii_string_map());
     // Morph external string to be TwoByte string.
-    string->set_map(i::Heap::external_string_map());
+    string->set_map(HEAP->external_string_map());
     i::ExternalTwoByteString* morphed =
          i::ExternalTwoByteString::cast(string);
     morphed->set_resource(uc16_resource);
   } else {
     // Check old map is not symbol or long.
-    CHECK(string->map() == i::Heap::external_string_map());
+    CHECK(string->map() == HEAP->external_string_map());
     // Morph external string to be ASCII string.
-    string->set_map(i::Heap::external_ascii_string_map());
+    string->set_map(HEAP->external_ascii_string_map());
     i::ExternalAsciiString* morphed =
          i::ExternalAsciiString::cast(string);
     morphed->set_resource(ascii_resource);
@@ -9999,9 +10225,9 @@
                                   i::StrLength(c_string)));
 
     Local<String> lhs(v8::Utils::ToLocal(
-        i::Factory::NewExternalStringFromAscii(&ascii_resource)));
+        FACTORY->NewExternalStringFromAscii(&ascii_resource)));
     Local<String> rhs(v8::Utils::ToLocal(
-        i::Factory::NewExternalStringFromAscii(&ascii_resource)));
+        FACTORY->NewExternalStringFromAscii(&ascii_resource)));
 
     env->Global()->Set(v8_str("lhs"), lhs);
     env->Global()->Set(v8_str("rhs"), rhs);
@@ -10086,18 +10312,18 @@
 
     // Create the input string for the regexp - the one we are going to change
     // properties of.
-    input_ = i::Factory::NewExternalStringFromAscii(&ascii_resource_);
+    input_ = 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(
+        FACTORY->NewStringFromAscii(i::Vector<const char>("input", 5));
+    i::Isolate::Current()->global_context()->global()->SetProperty(
         *input_name,
         *input_,
         NONE,
         i::kNonStrictMode)->ToObjectChecked();
 
-    MorphThread morph_thread(this);
+    MorphThread morph_thread(i::Isolate::Current(), this);
     morph_thread.Start();
     v8::Locker::StartPreemption(1);
     LongRunningRegExp();
@@ -10117,8 +10343,9 @@
 
   class MorphThread : public i::Thread {
    public:
-    explicit MorphThread(RegExpStringModificationTest* test)
-        : test_(test) {}
+    explicit MorphThread(i::Isolate* isolate,
+                         RegExpStringModificationTest* test)
+        : Thread(isolate, "MorphThread"), test_(test) {}
     virtual void Run() {
       test_->MorphString();
     }
@@ -10549,13 +10776,16 @@
   LocalContext context;
   const int kElementCount = 260;
   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
-  i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(kElementCount,
-                                                              pixel_data);
-  i::Heap::CollectAllGarbage(false);  // Force GC to trigger verification.
+  i::Handle<i::ExternalPixelArray> pixels =
+      i::Handle<i::ExternalPixelArray>::cast(
+          FACTORY->NewExternalArray(kElementCount,
+                                       v8::kExternalPixelArray,
+                                       pixel_data));
+  HEAP->CollectAllGarbage(false);  // Force GC to trigger verification.
   for (int i = 0; i < kElementCount; i++) {
     pixels->set(i, i % 256);
   }
-  i::Heap::CollectAllGarbage(false);  // Force GC to trigger verification.
+  HEAP->CollectAllGarbage(false);  // Force GC to trigger verification.
   for (int i = 0; i < kElementCount; i++) {
     CHECK_EQ(i % 256, pixels->get(i));
     CHECK_EQ(i % 256, pixel_data[i]);
@@ -10890,7 +11120,7 @@
                       "  return sum; "
                       "}"
                       "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
-                      "for (var i = 0; i < 10000; ++i) {"
+                      "for (var i = 0; i < 5000; ++i) {"
                       "  result = pa_load(pixels);"
                       "}"
                       "result");
@@ -10907,7 +11137,7 @@
                       "  }"
                       "  return sum; "
                       "}"
-                      "for (var i = 0; i < 100000; ++i) {"
+                      "for (var i = 0; i < 5000; ++i) {"
                       "  pa_init(pixels);"
                       "}"
                       "result = pa_load(pixels);"
@@ -10955,8 +11185,11 @@
   LocalContext context;
   const int kElementCount = 260;
   uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
-  i::Handle<i::PixelArray> pixels =
-      i::Factory::NewPixelArray(kElementCount, pixel_data);
+  i::Handle<i::ExternalPixelArray> pixels =
+      i::Handle<i::ExternalPixelArray>::cast(
+          FACTORY->NewExternalArray(kElementCount,
+                                    v8::kExternalPixelArray,
+                                    pixel_data));
   for (int i = 0; i < kElementCount; i++) {
     pixels->set(i, i % 256);
   }
@@ -10984,6 +11217,7 @@
   switch (array_type) {
     case v8::kExternalByteArray:
     case v8::kExternalUnsignedByteArray:
+    case v8::kExternalPixelArray:
       return 1;
       break;
     case v8::kExternalShortArray:
@@ -11016,12 +11250,12 @@
       static_cast<ElementType*>(malloc(kElementCount * element_size));
   i::Handle<ExternalArrayClass> array =
       i::Handle<ExternalArrayClass>::cast(
-          i::Factory::NewExternalArray(kElementCount, array_type, array_data));
-  i::Heap::CollectAllGarbage(false);  // Force GC to trigger verification.
+          FACTORY->NewExternalArray(kElementCount, array_type, array_data));
+  HEAP->CollectAllGarbage(false);  // Force GC to trigger verification.
   for (int i = 0; i < kElementCount; i++) {
     array->set(i, static_cast<ElementType>(i));
   }
-  i::Heap::CollectAllGarbage(false);  // Force GC to trigger verification.
+  HEAP->CollectAllGarbage(false);  // Force GC to trigger verification.
   for (int i = 0; i < kElementCount; i++) {
     CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array->get(i)));
     CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
@@ -11138,7 +11372,7 @@
                       "  }"
                       "}"
                       "sum;");
-  i::Heap::CollectAllGarbage(false);  // Force GC to trigger verification.
+  HEAP->CollectAllGarbage(false);  // Force GC to trigger verification.
   CHECK_EQ(28, result->Int32Value());
 
   // Make sure out-of-range loads do not throw.
@@ -11205,8 +11439,10 @@
                         "  ext_array[i] = Infinity;"
                         "}"
                         "ext_array[5];");
-    CHECK_EQ(0, result->Int32Value());
-    CHECK_EQ(0,
+    int expected_value =
+        (array_type == v8::kExternalPixelArray) ? 255 : 0;
+    CHECK_EQ(expected_value, result->Int32Value());
+    CHECK_EQ(expected_value,
              i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
 
     result = CompileRun("for (var i = 0; i < 8; i++) {"
@@ -11227,10 +11463,14 @@
     const char* signed_data =
         "var source_data = [0.6, 10.6, -0.6, -10.6];"
         "var expected_results = [0, 10, 0, -10];";
+    const char* pixel_data =
+        "var source_data = [0.6, 10.6];"
+        "var expected_results = [1, 11];";
     bool is_unsigned =
         (array_type == v8::kExternalUnsignedByteArray ||
          array_type == v8::kExternalUnsignedShortArray ||
          array_type == v8::kExternalUnsignedIntArray);
+    bool is_pixel_data = array_type == v8::kExternalPixelArray;
 
     i::OS::SNPrintF(test_buf,
                     "%s"
@@ -11243,11 +11483,42 @@
                     "               (ext_array[5] == expected_results[i]);"
                     "}"
                     "all_passed;",
-                    (is_unsigned ? unsigned_data : signed_data));
+                    (is_unsigned ?
+                         unsigned_data :
+                         (is_pixel_data ? pixel_data : signed_data)));
     result = CompileRun(test_buf.start());
     CHECK_EQ(true, result->BooleanValue());
   }
 
+  // Test crankshaft external array loads
+  for (int i = 0; i < kElementCount; i++) {
+    array->set(i, static_cast<ElementType>(i));
+  }
+  result = CompileRun("function ee_load_test_func(sum) {"
+                      " for (var i=0;i<40;++i)"
+                      "   sum += ext_array[i];"
+                      " return sum;"
+                      "}"
+                      "sum=0;"
+                      "for (var i=0;i<10000;++i) {"
+                      "  sum=ee_load_test_func(sum);"
+                      "}"
+                      "sum;");
+  CHECK_EQ(7800000, result->Int32Value());
+
+  // Test crankshaft external array stores
+  result = CompileRun("function ee_store_test_func(sum) {"
+                      " for (var i=0;i<40;++i)"
+                      "   sum += ext_array[i] = i;"
+                      " return sum;"
+                      "}"
+                      "sum=0;"
+                      "for (var i=0;i<10000;++i) {"
+                      "  sum=ee_store_test_func(sum);"
+                      "}"
+                      "sum;");
+  CHECK_EQ(7800000, result->Int32Value());
+
   result = CompileRun("ext_array[3] = 33;"
                       "delete ext_array[3];"
                       "ext_array[3];");
@@ -11287,7 +11558,7 @@
         static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
     i::Handle<ExternalArrayClass> large_array =
         i::Handle<ExternalArrayClass>::cast(
-            i::Factory::NewExternalArray(kLargeElementCount,
+            FACTORY->NewExternalArray(kLargeElementCount,
                                          array_type,
                                          array_data));
     v8::Handle<v8::Object> large_obj = v8::Object::New();
@@ -11354,6 +11625,95 @@
     free(large_array_data);
   }
 
+  // The "" property descriptor is overloaded to store information about
+  // the external array. Ensure that setting and accessing the "" property
+  // works (it should overwrite the information cached about the external
+  // array in the DescriptorArray) in various situations.
+  result = CompileRun("ext_array[''] = 23; ext_array['']");
+  CHECK_EQ(23, result->Int32Value());
+
+  // Property "" set after the external array is associated with the object.
+  {
+    v8::Handle<v8::Object> obj2 = v8::Object::New();
+    obj2->Set(v8_str("ee_test_field"), v8::Int32::New(256));
+    obj2->Set(v8_str(""), v8::Int32::New(1503));
+    // Set the elements to be the external array.
+    obj2->SetIndexedPropertiesToExternalArrayData(array_data,
+                                                  array_type,
+                                                  kElementCount);
+    context->Global()->Set(v8_str("ext_array"), obj2);
+    result = CompileRun("ext_array['']");
+    CHECK_EQ(1503, result->Int32Value());
+  }
+
+  // Property "" set after the external array is associated with the object.
+  {
+    v8::Handle<v8::Object> obj2 = v8::Object::New();
+    obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
+    // Set the elements to be the external array.
+    obj2->SetIndexedPropertiesToExternalArrayData(array_data,
+                                                  array_type,
+                                                  kElementCount);
+    obj2->Set(v8_str(""), v8::Int32::New(1503));
+    context->Global()->Set(v8_str("ext_array"), obj2);
+    result = CompileRun("ext_array['']");
+    CHECK_EQ(1503, result->Int32Value());
+  }
+
+  // Should reuse the map from previous test.
+  {
+    v8::Handle<v8::Object> obj2 = v8::Object::New();
+    obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
+    // Set the elements to be the external array. Should re-use the map
+    // from previous test.
+    obj2->SetIndexedPropertiesToExternalArrayData(array_data,
+                                                  array_type,
+                                                  kElementCount);
+    context->Global()->Set(v8_str("ext_array"), obj2);
+    result = CompileRun("ext_array['']");
+  }
+
+  // Property "" is a constant function that shouldn't not be interfered with
+  // when an external array is set.
+  {
+    v8::Handle<v8::Object> obj2 = v8::Object::New();
+    // Start
+    obj2->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
+
+    // Add a constant function to an object.
+    context->Global()->Set(v8_str("ext_array"), obj2);
+    result = CompileRun("ext_array[''] = function() {return 1503;};"
+                        "ext_array['']();");
+
+    // Add an external array transition to the same map that
+    // has the constant transition.
+    v8::Handle<v8::Object> obj3 = v8::Object::New();
+    obj3->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
+    obj3->SetIndexedPropertiesToExternalArrayData(array_data,
+                                                  array_type,
+                                                  kElementCount);
+    context->Global()->Set(v8_str("ext_array"), obj3);
+  }
+
+  // If a external array transition is in the map, it should get clobbered
+  // by a constant function.
+  {
+    // Add an external array transition.
+    v8::Handle<v8::Object> obj3 = v8::Object::New();
+    obj3->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
+    obj3->SetIndexedPropertiesToExternalArrayData(array_data,
+                                                  array_type,
+                                                  kElementCount);
+
+    // Add a constant function to the same map that just got an external array
+    // transition.
+    v8::Handle<v8::Object> obj2 = v8::Object::New();
+    obj2->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
+    context->Global()->Set(v8_str("ext_array"), obj2);
+    result = CompileRun("ext_array[''] = function() {return 1503;};"
+                        "ext_array['']();");
+  }
+
   free(array_data);
 }
 
@@ -11374,6 +11734,14 @@
 }
 
 
+THREADED_TEST(ExternalPixelArray) {
+  ExternalArrayTestHelper<i::ExternalPixelArray, uint8_t>(
+      v8::kExternalPixelArray,
+      0,
+      255);
+}
+
+
 THREADED_TEST(ExternalShortArray) {
   ExternalArrayTestHelper<i::ExternalShortArray, int16_t>(
       v8::kExternalShortArray,
@@ -11451,6 +11819,7 @@
   ExternalArrayInfoTestHelper(v8::kExternalIntArray);
   ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray);
   ExternalArrayInfoTestHelper(v8::kExternalFloatArray);
+  ExternalArrayInfoTestHelper(v8::kExternalPixelArray);
 }
 
 
@@ -11714,7 +12083,8 @@
 static uint32_t* stack_limit;
 
 static v8::Handle<Value> GetStackLimitCallback(const v8::Arguments& args) {
-  stack_limit = reinterpret_cast<uint32_t*>(i::StackGuard::real_climit());
+  stack_limit = reinterpret_cast<uint32_t*>(
+      i::Isolate::Current()->stack_guard()->real_climit());
   return v8::Undefined();
 }
 
@@ -11980,7 +12350,7 @@
     other_context->Enter();
     CompileRun(source_simple);
     other_context->Exit();
-    i::Heap::CollectAllGarbage(false);
+    HEAP->CollectAllGarbage(false);
     if (GetGlobalObjectsCount() == 1) break;
   }
   CHECK_GE(2, gc_count);
@@ -12002,7 +12372,7 @@
     other_context->Enter();
     CompileRun(source_eval);
     other_context->Exit();
-    i::Heap::CollectAllGarbage(false);
+    HEAP->CollectAllGarbage(false);
     if (GetGlobalObjectsCount() == 1) break;
   }
   CHECK_GE(2, gc_count);
@@ -12029,7 +12399,7 @@
     other_context->Enter();
     CompileRun(source_exception);
     other_context->Exit();
-    i::Heap::CollectAllGarbage(false);
+    HEAP->CollectAllGarbage(false);
     if (GetGlobalObjectsCount() == 1) break;
   }
   CHECK_GE(2, gc_count);
@@ -12247,26 +12617,26 @@
   v8::V8::AddGCEpilogueCallback(EpilogueCallback);
   CHECK_EQ(0, prologue_call_count);
   CHECK_EQ(0, epilogue_call_count);
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(1, prologue_call_count);
   CHECK_EQ(1, epilogue_call_count);
   v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
   v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(2, prologue_call_count);
   CHECK_EQ(2, epilogue_call_count);
   CHECK_EQ(1, prologue_call_count_second);
   CHECK_EQ(1, epilogue_call_count_second);
   v8::V8::RemoveGCPrologueCallback(PrologueCallback);
   v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(2, prologue_call_count);
   CHECK_EQ(2, epilogue_call_count);
   CHECK_EQ(2, prologue_call_count_second);
   CHECK_EQ(2, epilogue_call_count_second);
   v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
   v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   CHECK_EQ(2, prologue_call_count);
   CHECK_EQ(2, epilogue_call_count);
   CHECK_EQ(2, prologue_call_count_second);
@@ -12294,7 +12664,7 @@
       "    return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
       "  return 'PASSED';"
       "})()";
-  i::Heap::ClearJSFunctionResultCaches();
+  HEAP->ClearJSFunctionResultCaches();
   ExpectString(code, "PASSED");
 }
 
@@ -12318,7 +12688,7 @@
       "    return 'FAILED: k0CacheSize is too small';"
       "  return 'PASSED';"
       "})()";
-  i::Heap::ClearJSFunctionResultCaches();
+  HEAP->ClearJSFunctionResultCaches();
   ExpectString(code, "PASSED");
 }
 
@@ -12343,7 +12713,7 @@
       "  };"
       "  return 'PASSED';"
       "})()";
-  i::Heap::ClearJSFunctionResultCaches();
+  HEAP->ClearJSFunctionResultCaches();
   ExpectString(code, "PASSED");
 }
 
@@ -12368,7 +12738,7 @@
       "  };"
       "  return 'PASSED';"
       "})()";
-  i::Heap::ClearJSFunctionResultCaches();
+  HEAP->ClearJSFunctionResultCaches();
   ExpectString(code, "PASSED");
 }
 
@@ -12386,7 +12756,7 @@
       "  };"
       "  return 'PASSED';"
       "})()";
-  i::Heap::ClearJSFunctionResultCaches();
+  HEAP->ClearJSFunctionResultCaches();
   ExpectString(code, "PASSED");
 }
 
@@ -12476,7 +12846,7 @@
 void FailedAccessCheckCallbackGC(Local<v8::Object> target,
                                  v8::AccessType type,
                                  Local<v8::Value> data) {
-  i::Heap::CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
 }
 
 
@@ -12557,6 +12927,374 @@
   v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
 }
 
+TEST(DefaultIsolateGetCurrent) {
+  CHECK(v8::Isolate::GetCurrent() != NULL);
+  v8::Isolate* isolate = v8::Isolate::GetCurrent();
+  CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
+  printf("*** %s\n", "DefaultIsolateGetCurrent success");
+}
+
+TEST(IsolateNewDispose) {
+  v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
+  v8::Isolate* isolate = v8::Isolate::New();
+  CHECK(isolate != NULL);
+  CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
+  CHECK(current_isolate != isolate);
+  CHECK(current_isolate == v8::Isolate::GetCurrent());
+
+  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
+  last_location = last_message = NULL;
+  isolate->Dispose();
+  CHECK_EQ(last_location, NULL);
+  CHECK_EQ(last_message, NULL);
+}
+
+TEST(IsolateEnterExitDefault) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
+  CHECK(current_isolate != NULL);  // Default isolate.
+  ExpectString("'hello'", "hello");
+  current_isolate->Enter();
+  ExpectString("'still working'", "still working");
+  current_isolate->Exit();
+  ExpectString("'still working 2'", "still working 2");
+  current_isolate->Exit();
+  // Default isolate is always, well, 'default current'.
+  CHECK_EQ(v8::Isolate::GetCurrent(), current_isolate);
+  // Still working since default isolate is auto-entering any thread
+  // that has no isolate and attempts to execute V8 APIs.
+  ExpectString("'still working 3'", "still working 3");
+}
+
+TEST(DisposeDefaultIsolate) {
+  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
+
+  // Run some V8 code to trigger default isolate to become 'current'.
+  v8::HandleScope scope;
+  LocalContext context;
+  ExpectString("'run some V8'", "run some V8");
+
+  v8::Isolate* isolate = v8::Isolate::GetCurrent();
+  CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
+  last_location = last_message = NULL;
+  isolate->Dispose();
+  // It is not possible to dispose default isolate via Isolate API.
+  CHECK_NE(last_location, NULL);
+  CHECK_NE(last_message, NULL);
+}
+
+TEST(RunDefaultAndAnotherIsolate) {
+  v8::HandleScope scope;
+  LocalContext context;
+
+  // Enter new isolate.
+  v8::Isolate* isolate = v8::Isolate::New();
+  CHECK(isolate);
+  isolate->Enter();
+  { // Need this block because subsequent Exit() will deallocate Heap,
+    // so we need all scope objects to be deconstructed when it happens.
+    v8::HandleScope scope_new;
+    LocalContext context_new;
+
+    // Run something in new isolate.
+    CompileRun("var foo = 153;");
+    ExpectTrue("function f() { return foo == 153; }; f()");
+  }
+  isolate->Exit();
+
+  // This runs automatically in default isolate.
+  // Variables in another isolate should be not available.
+  ExpectTrue("function f() {"
+             "  try {"
+             "    foo;"
+             "    return false;"
+             "  } catch(e) {"
+             "    return true;"
+             "  }"
+             "};"
+             "var bar = 371;"
+             "f()");
+
+  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
+  last_location = last_message = NULL;
+  isolate->Dispose();
+  CHECK_EQ(last_location, NULL);
+  CHECK_EQ(last_message, NULL);
+
+  // Check that default isolate still runs.
+  ExpectTrue("function f() { return bar == 371; }; f()");
+}
+
+TEST(DisposeIsolateWhenInUse) {
+  v8::Isolate* isolate = v8::Isolate::New();
+  CHECK(isolate);
+  isolate->Enter();
+  v8::HandleScope scope;
+  LocalContext context;
+  // Run something in this isolate.
+  ExpectTrue("true");
+  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
+  last_location = last_message = NULL;
+  // Still entered, should fail.
+  isolate->Dispose();
+  CHECK_NE(last_location, NULL);
+  CHECK_NE(last_message, NULL);
+}
+
+TEST(RunTwoIsolatesOnSingleThread) {
+  // Run isolate 1.
+  v8::Isolate* isolate1 = v8::Isolate::New();
+  isolate1->Enter();
+  v8::Persistent<v8::Context> context1 = v8::Context::New();
+
+  {
+    v8::Context::Scope cscope(context1);
+    v8::HandleScope scope;
+    // Run something in new isolate.
+    CompileRun("var foo = 'isolate 1';");
+    ExpectString("function f() { return foo; }; f()", "isolate 1");
+  }
+
+  // Run isolate 2.
+  v8::Isolate* isolate2 = v8::Isolate::New();
+  v8::Persistent<v8::Context> context2;
+
+  {
+    v8::Isolate::Scope iscope(isolate2);
+    context2 = v8::Context::New();
+    v8::Context::Scope cscope(context2);
+    v8::HandleScope scope;
+
+    // Run something in new isolate.
+    CompileRun("var foo = 'isolate 2';");
+    ExpectString("function f() { return foo; }; f()", "isolate 2");
+  }
+
+  {
+    v8::Context::Scope cscope(context1);
+    v8::HandleScope scope;
+    // Now again in isolate 1
+    ExpectString("function f() { return foo; }; f()", "isolate 1");
+  }
+
+  isolate1->Exit();
+
+  // Run some stuff in default isolate.
+  v8::Persistent<v8::Context> context_default = v8::Context::New();
+
+  {
+    v8::Context::Scope cscope(context_default);
+    v8::HandleScope scope;
+    // Variables in other isolates should be not available, verify there
+    // is an exception.
+    ExpectTrue("function f() {"
+               "  try {"
+               "    foo;"
+               "    return false;"
+               "  } catch(e) {"
+               "    return true;"
+               "  }"
+               "};"
+               "var isDefaultIsolate = true;"
+               "f()");
+  }
+
+  isolate1->Enter();
+
+  {
+    v8::Isolate::Scope iscope(isolate2);
+    v8::Context::Scope cscope(context2);
+    v8::HandleScope scope;
+    ExpectString("function f() { return foo; }; f()", "isolate 2");
+  }
+
+  {
+    v8::Context::Scope cscope(context1);
+    v8::HandleScope scope;
+    ExpectString("function f() { return foo; }; f()", "isolate 1");
+  }
+
+  {
+    v8::Isolate::Scope iscope(isolate2);
+    context2.Dispose();
+  }
+
+  context1.Dispose();
+  isolate1->Exit();
+
+  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
+  last_location = last_message = NULL;
+
+  isolate1->Dispose();
+  CHECK_EQ(last_location, NULL);
+  CHECK_EQ(last_message, NULL);
+
+  isolate2->Dispose();
+  CHECK_EQ(last_location, NULL);
+  CHECK_EQ(last_message, NULL);
+
+  // Check that default isolate still runs.
+  {
+    v8::Context::Scope cscope(context_default);
+    v8::HandleScope scope;
+    ExpectTrue("function f() { return isDefaultIsolate; }; f()");
+  }
+}
+
+static int CalcFibonacci(v8::Isolate* isolate, int limit) {
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::HandleScope scope;
+  LocalContext context;
+  i::ScopedVector<char> code(1024);
+  i::OS::SNPrintF(code, "function fib(n) {"
+                        "  if (n <= 2) return 1;"
+                        "  return fib(n-1) + fib(n-2);"
+                        "}"
+                        "fib(%d)", limit);
+  Local<Value> value = CompileRun(code.start());
+  CHECK(value->IsNumber());
+  return static_cast<int>(value->NumberValue());
+}
+
+class IsolateThread : public v8::internal::Thread {
+ public:
+  explicit IsolateThread(v8::Isolate* isolate, int fib_limit)
+      : Thread(NULL, "IsolateThread"),
+        isolate_(isolate),
+        fib_limit_(fib_limit),
+        result_(0) { }
+
+  void Run() {
+    result_ = CalcFibonacci(isolate_, fib_limit_);
+  }
+
+  int result() { return result_; }
+
+ private:
+  v8::Isolate* isolate_;
+  int fib_limit_;
+  int result_;
+};
+
+TEST(MultipleIsolatesOnIndividualThreads) {
+  v8::Isolate* isolate1 = v8::Isolate::New();
+  v8::Isolate* isolate2 = v8::Isolate::New();
+
+  IsolateThread thread1(isolate1, 21);
+  IsolateThread thread2(isolate2, 12);
+
+  // Compute some fibonacci numbers on 3 threads in 3 isolates.
+  thread1.Start();
+  thread2.Start();
+
+  int result1 = CalcFibonacci(v8::Isolate::GetCurrent(), 21);
+  int result2 = CalcFibonacci(v8::Isolate::GetCurrent(), 12);
+
+  thread1.Join();
+  thread2.Join();
+
+  // Compare results. The actual fibonacci numbers for 12 and 21 are taken
+  // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
+  CHECK_EQ(result1, 10946);
+  CHECK_EQ(result2, 144);
+  CHECK_EQ(result1, thread1.result());
+  CHECK_EQ(result2, thread2.result());
+
+  isolate1->Dispose();
+  isolate2->Dispose();
+}
+
+
+class InitDefaultIsolateThread : public v8::internal::Thread {
+ public:
+  enum TestCase {
+    IgnoreOOM,
+    SetResourceConstraints,
+    SetFatalHandler,
+    SetCounterFunction,
+    SetCreateHistogramFunction,
+    SetAddHistogramSampleFunction
+  };
+
+  explicit InitDefaultIsolateThread(TestCase testCase)
+      : Thread(NULL, "InitDefaultIsolateThread"),
+        testCase_(testCase),
+        result_(false) { }
+
+  void Run() {
+    switch (testCase_) {
+    case IgnoreOOM:
+      v8::V8::IgnoreOutOfMemoryException();
+      break;
+
+    case SetResourceConstraints: {
+      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);
+      break;
+    }
+
+    case SetFatalHandler:
+      v8::V8::SetFatalErrorHandler(NULL);
+      break;
+
+    case SetCounterFunction:
+      v8::V8::SetCounterFunction(NULL);
+      break;
+
+    case SetCreateHistogramFunction:
+      v8::V8::SetCreateHistogramFunction(NULL);
+      break;
+
+    case SetAddHistogramSampleFunction:
+      v8::V8::SetAddHistogramSampleFunction(NULL);
+      break;
+    }
+    result_ = true;
+  }
+
+  bool result() { return result_; }
+
+ private:
+  TestCase testCase_;
+  bool result_;
+};
+
+
+static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
+  InitDefaultIsolateThread thread(testCase);
+  thread.Start();
+  thread.Join();
+  CHECK_EQ(thread.result(), true);
+}
+
+TEST(InitializeDefaultIsolateOnSecondaryThread1) {
+  InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
+}
+
+TEST(InitializeDefaultIsolateOnSecondaryThread2) {
+  InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
+}
+
+TEST(InitializeDefaultIsolateOnSecondaryThread3) {
+  InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
+}
+
+TEST(InitializeDefaultIsolateOnSecondaryThread4) {
+  InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
+}
+
+TEST(InitializeDefaultIsolateOnSecondaryThread5) {
+  InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
+}
+
+TEST(InitializeDefaultIsolateOnSecondaryThread6) {
+  InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
+}
+
 
 TEST(StringCheckMultipleContexts) {
   const char* code =
@@ -12660,7 +13398,7 @@
                  "})()",
                  "ReferenceError: cell is not defined");
     CompileRun("cell = \"new_second\";");
-    i::Heap::CollectAllGarbage(true);
+    HEAP->CollectAllGarbage(true);
     ExpectString("readCell()", "new_second");
     ExpectString("readCell()", "new_second");
   }
diff --git a/test/cctest/test-assembler-arm.cc b/test/cctest/test-assembler-arm.cc
index 43cf580..a91886e 100644
--- a/test/cctest/test-assembler-arm.cc
+++ b/test/cctest/test-assembler-arm.cc
@@ -65,10 +65,10 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Object* code = Heap::CreateCode(
+  Object* code = HEAP->CreateCode(
       desc,
       Code::ComputeFlags(Code::STUB),
-      Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
   CHECK(code->IsCode());
 #ifdef DEBUG
   Code::cast(code)->Print();
@@ -102,10 +102,10 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Object* code = Heap::CreateCode(
+  Object* code = HEAP->CreateCode(
       desc,
       Code::ComputeFlags(Code::STUB),
-      Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
   CHECK(code->IsCode());
 #ifdef DEBUG
   Code::cast(code)->Print();
@@ -139,7 +139,7 @@
 
   // some relocated stuff here, not executed
   __ RecordComment("dead code, just testing relocations");
-  __ mov(r0, Operand(Factory::true_value()));
+  __ mov(r0, Operand(FACTORY->true_value()));
   __ RecordComment("dead code, just testing immediate operands");
   __ mov(r0, Operand(-1));
   __ mov(r0, Operand(0xFF000000));
@@ -148,10 +148,10 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Object* code = Heap::CreateCode(
+  Object* code = HEAP->CreateCode(
       desc,
       Code::ComputeFlags(Code::STUB),
-      Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
   CHECK(code->IsCode());
 #ifdef DEBUG
   Code::cast(code)->Print();
@@ -196,10 +196,10 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Object* code = Heap::CreateCode(
+  Object* code = HEAP->CreateCode(
       desc,
       Code::ComputeFlags(Code::STUB),
-      Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
   CHECK(code->IsCode());
 #ifdef DEBUG
   Code::cast(code)->Print();
@@ -232,6 +232,8 @@
     double g;
     double h;
     int i;
+    double m;
+    double n;
     float x;
     float y;
   } T;
@@ -243,7 +245,7 @@
   Label L, C;
 
 
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
 
     __ mov(ip, Operand(sp));
@@ -297,14 +299,22 @@
     __ vabs(d0, d2);
     __ vstr(d0, r4, OFFSET_OF(T, h));
 
+    // Test vneg.
+    __ vldr(d1, r4, OFFSET_OF(T, m));
+    __ vneg(d0, d1);
+    __ vstr(d0, r4, OFFSET_OF(T, m));
+    __ vldr(d1, r4, OFFSET_OF(T, n));
+    __ vneg(d0, d1);
+    __ vstr(d0, r4, OFFSET_OF(T, n));
+
     __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
 
     CodeDesc desc;
     assm.GetCode(&desc);
-    Object* code = Heap::CreateCode(
+    Object* code = HEAP->CreateCode(
         desc,
         Code::ComputeFlags(Code::STUB),
-        Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
     CHECK(code->IsCode());
 #ifdef DEBUG
     Code::cast(code)->Print();
@@ -319,12 +329,16 @@
     t.g = -2718.2818;
     t.h = 31415926.5;
     t.i = 0;
+    t.m = -2718.2818;
+    t.n = 123.456;
     t.x = 4.5;
     t.y = 9.0;
     Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
     USE(dummy);
     CHECK_EQ(4.5, t.y);
     CHECK_EQ(9.0, t.x);
+    CHECK_EQ(-123.456, t.n);
+    CHECK_EQ(2718.2818, t.m);
     CHECK_EQ(2, t.i);
     CHECK_EQ(2718.2818, t.g);
     CHECK_EQ(31415926.5, t.h);
@@ -345,7 +359,7 @@
 
   Assembler assm(NULL, 0);
 
-  if (CpuFeatures::IsSupported(ARMv7)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(ARMv7)) {
     CpuFeatures::Scope scope(ARMv7);
     // On entry, r0 = 0xAAAAAAAA = 0b10..10101010.
     __ ubfx(r0, r0, 1, 12);  // 0b00..010101010101 = 0x555
@@ -357,10 +371,10 @@
 
     CodeDesc desc;
     assm.GetCode(&desc);
-    Object* code = Heap::CreateCode(
+    Object* code = HEAP->CreateCode(
         desc,
         Code::ComputeFlags(Code::STUB),
-        Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
     CHECK(code->IsCode());
 #ifdef DEBUG
     Code::cast(code)->Print();
@@ -381,7 +395,7 @@
 
   Assembler assm(NULL, 0);
 
-  if (CpuFeatures::IsSupported(ARMv7)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(ARMv7)) {
     CpuFeatures::Scope scope(ARMv7);
     __ usat(r1, 8, Operand(r0));           // Sat 0xFFFF to 0-255 = 0xFF.
     __ usat(r2, 12, Operand(r0, ASR, 9));  // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
@@ -392,10 +406,10 @@
 
     CodeDesc desc;
     assm.GetCode(&desc);
-    Object* code = Heap::CreateCode(
+    Object* code = HEAP->CreateCode(
         desc,
         Code::ComputeFlags(Code::STUB),
-        Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
     CHECK(code->IsCode());
 #ifdef DEBUG
     Code::cast(code)->Print();
@@ -424,7 +438,7 @@
 
   Assembler assm(NULL, 0);
 
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
 
     Label wrong_exception;
@@ -468,10 +482,10 @@
 
     CodeDesc desc;
     assm.GetCode(&desc);
-    Object* code = Heap::CreateCode(
+    Object* code = HEAP->CreateCode(
         desc,
         Code::ComputeFlags(Code::STUB),
-        Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
     CHECK(code->IsCode());
 #ifdef DEBUG
     Code::cast(code)->Print();
diff --git a/test/cctest/test-assembler-ia32.cc b/test/cctest/test-assembler-ia32.cc
index 14692ff..694bd57 100644
--- a/test/cctest/test-assembler-ia32.cc
+++ b/test/cctest/test-assembler-ia32.cc
@@ -69,10 +69,10 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Object* code = Heap::CreateCode(desc,
-                                  Code::ComputeFlags(Code::STUB),
-                                  Handle<Object>(Heap::undefined_value()))->
-      ToObjectChecked();
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
   CHECK(code->IsCode());
 #ifdef OBJECT_PRINT
   Code::cast(code)->Print();
@@ -107,10 +107,10 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Object* code = Heap::CreateCode(desc,
-                                  Code::ComputeFlags(Code::STUB),
-                                  Handle<Object>(Heap::undefined_value()))->
-      ToObjectChecked();
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
   CHECK(code->IsCode());
 #ifdef OBJECT_PRINT
   Code::cast(code)->Print();
@@ -144,16 +144,15 @@
   __ ret(0);
 
   // some relocated stuff here, not executed
-  __ mov(eax, Factory::true_value());
+  __ mov(eax, FACTORY->true_value());
   __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Object* code = Heap::CreateCode(
+  Object* code = HEAP->CreateCode(
       desc,
       Code::ComputeFlags(Code::STUB),
-      Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
-
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
   CHECK(code->IsCode());
 #ifdef OBJECT_PRINT
   Code::cast(code)->Print();
@@ -168,7 +167,7 @@
 typedef int (*F3)(float x);
 
 TEST(AssemblerIa323) {
-  if (!CpuFeatures::IsSupported(SSE2)) return;
+  if (!Isolate::Current()->cpu_features()->IsSupported(SSE2)) return;
 
   InitializeVM();
   v8::HandleScope scope;
@@ -176,7 +175,7 @@
   v8::internal::byte buffer[256];
   Assembler assm(buffer, sizeof buffer);
 
-  CHECK(CpuFeatures::IsSupported(SSE2));
+  CHECK(Isolate::Current()->cpu_features()->IsSupported(SSE2));
   { CpuFeatures::Scope fscope(SSE2);
     __ cvttss2si(eax, Operand(esp, 4));
     __ ret(0);
@@ -184,10 +183,10 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Code* code = Code::cast(Heap::CreateCode(
+  Code* code = Code::cast(HEAP->CreateCode(
       desc,
       Code::ComputeFlags(Code::STUB),
-      Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
   // don't print the code - our disassembler can't handle cvttss2si
   // instead print bytes
   Disassembler::Dump(stdout,
@@ -203,7 +202,7 @@
 typedef int (*F4)(double x);
 
 TEST(AssemblerIa324) {
-  if (!CpuFeatures::IsSupported(SSE2)) return;
+  if (!Isolate::Current()->cpu_features()->IsSupported(SSE2)) return;
 
   InitializeVM();
   v8::HandleScope scope;
@@ -211,17 +210,17 @@
   v8::internal::byte buffer[256];
   Assembler assm(buffer, sizeof buffer);
 
-  CHECK(CpuFeatures::IsSupported(SSE2));
+  CHECK(Isolate::Current()->cpu_features()->IsSupported(SSE2));
   CpuFeatures::Scope fscope(SSE2);
   __ cvttsd2si(eax, Operand(esp, 4));
   __ ret(0);
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Code* code = Code::cast(Heap::CreateCode(
+  Code* code = Code::cast(HEAP->CreateCode(
       desc,
       Code::ComputeFlags(Code::STUB),
-      Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
   // don't print the code - our disassembler can't handle cvttsd2si
   // instead print bytes
   Disassembler::Dump(stdout,
@@ -247,10 +246,10 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Code* code = Code::cast(Heap::CreateCode(
+  Code* code = Code::cast(HEAP->CreateCode(
       desc,
       Code::ComputeFlags(Code::STUB),
-      Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
   F0 f = FUNCTION_CAST<F0>(code->entry());
   int res = f();
   CHECK_EQ(42, res);
@@ -260,11 +259,11 @@
 typedef double (*F5)(double x, double y);
 
 TEST(AssemblerIa326) {
-  if (!CpuFeatures::IsSupported(SSE2)) return;
+  if (!Isolate::Current()->cpu_features()->IsSupported(SSE2)) return;
 
   InitializeVM();
   v8::HandleScope scope;
-  CHECK(CpuFeatures::IsSupported(SSE2));
+  CHECK(Isolate::Current()->cpu_features()->IsSupported(SSE2));
   CpuFeatures::Scope fscope(SSE2);
   v8::internal::byte buffer[256];
   Assembler assm(buffer, sizeof buffer);
@@ -284,10 +283,10 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Code* code = Code::cast(Heap::CreateCode(
+  Code* code = Code::cast(HEAP->CreateCode(
       desc,
       Code::ComputeFlags(Code::STUB),
-      Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
 #ifdef DEBUG
   ::printf("\n---\n");
   // don't print the code - our disassembler can't handle SSE instructions
@@ -306,11 +305,11 @@
 typedef double (*F6)(int x);
 
 TEST(AssemblerIa328) {
-  if (!CpuFeatures::IsSupported(SSE2)) return;
+  if (!Isolate::Current()->cpu_features()->IsSupported(SSE2)) return;
 
   InitializeVM();
   v8::HandleScope scope;
-  CHECK(CpuFeatures::IsSupported(SSE2));
+  CHECK(Isolate::Current()->cpu_features()->IsSupported(SSE2));
   CpuFeatures::Scope fscope(SSE2);
   v8::internal::byte buffer[256];
   Assembler assm(buffer, sizeof buffer);
@@ -324,10 +323,10 @@
   __ ret(0);
   CodeDesc desc;
   assm.GetCode(&desc);
-  Code* code = Code::cast(Heap::CreateCode(
+  Code* code = Code::cast(HEAP->CreateCode(
       desc,
       Code::ComputeFlags(Code::STUB),
-      Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
   CHECK(code->IsCode());
 #ifdef OBJECT_PRINT
   Code::cast(code)->Print();
@@ -379,10 +378,10 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Code* code = Code::cast(Heap::CreateCode(
+  Code* code = Code::cast(HEAP->CreateCode(
       desc,
       Code::ComputeFlags(Code::STUB),
-      Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
   CHECK(code->IsCode());
 #ifdef OBJECT_PRINT
   Code::cast(code)->Print();
diff --git a/test/cctest/test-assembler-mips.cc b/test/cctest/test-assembler-mips.cc
index ecb42e2..8cd56f7 100644
--- a/test/cctest/test-assembler-mips.cc
+++ b/test/cctest/test-assembler-mips.cc
@@ -59,6 +59,7 @@
 
 #define __ assm.
 
+
 TEST(MIPS0) {
   InitializeVM();
   v8::HandleScope scope;
@@ -72,14 +73,11 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Object* code = Heap::CreateCode(desc,
-                                  NULL,
-                                  Code::ComputeFlags(Code::STUB),
-                                  Handle<Object>(Heap::undefined_value()));
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
   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, 0xab0, 0xc, 0, 0, 0));
   ::printf("f() = %d\n", res);
@@ -100,12 +98,12 @@
   __ nop();
 
   __ bind(&L);
-  __ add(v0, v0, a1);
+  __ addu(v0, v0, a1);
   __ addiu(a1, a1, -1);
 
   __ bind(&C);
   __ xori(v1, a1, 0);
-  __ Branch(ne, &L, v1, Operand(0, RelocInfo::NONE));
+  __ Branch(&L, ne, v1, Operand(0));
   __ nop();
 
   __ jr(ra);
@@ -113,14 +111,11 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Object* code = Heap::CreateCode(desc,
-                                  NULL,
-                                  Code::ComputeFlags(Code::STUB),
-                                  Handle<Object>(Heap::undefined_value()));
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
   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, 50, 0, 0, 0, 0));
   ::printf("f() = %d\n", res);
@@ -166,62 +161,81 @@
   __ srav(v0, v0, t0);  // 0xff234560
   __ sllv(v0, v0, t0);  // 0xf2345600
   __ srlv(v0, v0, t0);  // 0x0f234560
-  __ Branch(ne, &error, v0, Operand(0x0f234560));
+  __ Branch(&error, ne, v0, Operand(0x0f234560));
   __ nop();
 
-  __ add(v0, t0, t1);   // 0x00001238
-  __ sub(v0, v0, t0);   // 0x00001234
-  __ Branch(ne, &error, v0, Operand(0x00001234));
+  __ addu(v0, t0, t1);   // 0x00001238
+  __ subu(v0, v0, t0);  // 0x00001234
+  __ Branch(&error, ne, v0, Operand(0x00001234));
   __ nop();
   __ addu(v1, t3, t0);
-  __ Branch(ne, &error, v1, Operand(0x80000003));
+  __ Branch(&error, ne, v1, Operand(0x80000003));
   __ nop();
   __ subu(v1, t7, t0);  // 0x7ffffffc
-  __ Branch(ne, &error, v1, Operand(0x7ffffffc));
+  __ Branch(&error, ne, v1, Operand(0x7ffffffc));
   __ nop();
 
   __ and_(v0, t1, t2);  // 0x00001230
   __ or_(v0, v0, t1);   // 0x00001234
   __ xor_(v0, v0, t2);  // 0x1234444c
   __ nor(v0, v0, t2);   // 0xedcba987
-  __ Branch(ne, &error, v0, Operand(0xedcba983));
+  __ Branch(&error, ne, v0, Operand(0xedcba983));
   __ nop();
 
   __ slt(v0, t7, t3);
-  __ Branch(ne, &error, v0, Operand(0x1));
+  __ Branch(&error, ne, v0, Operand(0x1));
   __ nop();
   __ sltu(v0, t7, t3);
-  __ Branch(ne, &error, v0, Operand(0x0));
+  __ Branch(&error, ne, v0, Operand(0x0));
   __ nop();
   // End of SPECIAL class.
 
-  __ addi(v0, zero_reg, 0x7421);  // 0x00007421
-  __ addi(v0, v0, -0x1);  // 0x00007420
+  __ addiu(v0, zero_reg, 0x7421);  // 0x00007421
+  __ addiu(v0, v0, -0x1);  // 0x00007420
   __ addiu(v0, v0, -0x20);  // 0x00007400
-  __ Branch(ne, &error, v0, Operand(0x00007400));
+  __ Branch(&error, ne, v0, Operand(0x00007400));
   __ nop();
   __ addiu(v1, t3, 0x1);  // 0x80000000
-  __ Branch(ne, &error, v1, Operand(0x80000000));
+  __ Branch(&error, ne, v1, Operand(0x80000000));
   __ nop();
 
   __ slti(v0, t1, 0x00002000);  // 0x1
   __ slti(v0, v0, 0xffff8000);  // 0x0
-  __ Branch(ne, &error, v0, Operand(0x0));
+  __ Branch(&error, ne, v0, Operand(0x0));
   __ nop();
   __ sltiu(v0, t1, 0x00002000);  // 0x1
   __ sltiu(v0, v0, 0x00008000);  // 0x1
-  __ Branch(ne, &error, v0, Operand(0x1));
+  __ Branch(&error, ne, v0, Operand(0x1));
   __ nop();
 
   __ andi(v0, t1, 0xf0f0);  // 0x00001030
   __ ori(v0, v0, 0x8a00);  // 0x00009a30
   __ xori(v0, v0, 0x83cc);  // 0x000019fc
-  __ Branch(ne, &error, v0, Operand(0x000019fc));
+  __ Branch(&error, ne, v0, Operand(0x000019fc));
   __ nop();
   __ lui(v1, 0x8123);  // 0x81230000
-  __ Branch(ne, &error, v1, Operand(0x81230000));
+  __ Branch(&error, ne, v1, Operand(0x81230000));
   __ nop();
 
+  // Bit twiddling instructions & conditional moves.
+  // Uses t0-t7 as set above.
+  __ clz(v0, t0);       // 29
+  __ clz(v1, t1);       // 19
+  __ addu(v0, v0, v1);  // 48
+  __ clz(v1, t2);       // 3
+  __ addu(v0, v0, v1);  // 51
+  __ clz(v1, t7);       // 0
+  __ addu(v0, v0, v1);  // 51
+  __ Branch(&error, ne, v0, Operand(51));
+  __ movn(a0, t3, t0);  // Move a0<-t3 (t0 is NOT 0).
+  __ Ins(a0, t1, 12, 8);  // 0x7ff34fff
+  __ Branch(&error, ne, a0, Operand(0x7ff34fff));
+  __ movz(a0, t6, t7);    // a0 not updated (t7 is NOT 0).
+  __ Ext(a1, a0, 8, 12);  // 0x34f
+  __ Branch(&error, ne, a1, Operand(0x34f));
+  __ movz(a0, t6, v1);    // a0<-t6, v0 is 0, from 8 instr back.
+  __ Branch(&error, ne, a0, Operand(t6));
+
   // Everything was correctly executed. Load the expected result.
   __ li(v0, 0x31415926);
   __ b(&exit);
@@ -229,6 +243,7 @@
 
   __ bind(&error);
   // Got an error. Return a wrong result.
+  __ li(v0, 666);
 
   __ bind(&exit);
   __ jr(ra);
@@ -236,18 +251,1061 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Object* code = Heap::CreateCode(desc,
-                                  NULL,
-                                  Code::ComputeFlags(Code::STUB),
-                                  Handle<Object>(Heap::undefined_value()));
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
   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, 0xab0, 0xc, 0, 0, 0));
   ::printf("f() = %d\n", res);
   CHECK_EQ(0x31415926, res);
 }
 
+
+TEST(MIPS3) {
+  // Test floating point instructions.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    double a;
+    double b;
+    double c;
+    double d;
+    double e;
+    double f;
+    double g;
+  } T;
+  T t;
+
+  // Create a function that accepts &t, and loads, manipulates, and stores
+  // the doubles t.a ... t.f.
+  MacroAssembler assm(NULL, 0);
+  Label L, C;
+
+  if (Isolate::Current()->cpu_features()->IsSupported(FPU)) {
+    CpuFeatures::Scope scope(FPU);
+
+    __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
+    __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
+    __ add_d(f8, f4, f6);
+    __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) );  // c = a + b.
+
+    __ mov_d(f10, f8);  // c
+    __ neg_d(f12, f6);  // -b
+    __ sub_d(f10, f10, f12);
+    __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) );  // d = c - (-b).
+
+    __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) );   // b = a.
+
+    __ li(t0, 120);
+    __ mtc1(t0, f14);
+    __ cvt_d_w(f14, f14);   // f14 = 120.0.
+    __ mul_d(f10, f10, f14);
+    __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) );  // e = d * 120 = 1.8066e16.
+
+    __ div_d(f12, f10, f4);
+    __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) );  // f = e / a = 120.44.
+
+    __ sqrt_d(f14, f12);
+    __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) );
+    // g = sqrt(f) = 10.97451593465515908537
+
+    __ jr(ra);
+    __ nop();
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Object* code = HEAP->CreateCode(
+        desc,
+        Code::ComputeFlags(Code::STUB),
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+    CHECK(code->IsCode());
+    F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+    t.a = 1.5e14;
+    t.b = 2.75e11;
+    t.c = 0.0;
+    t.d = 0.0;
+    t.e = 0.0;
+    t.f = 0.0;
+    Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+    USE(dummy);
+    CHECK_EQ(1.5e14, t.a);
+    CHECK_EQ(1.5e14, t.b);
+    CHECK_EQ(1.50275e14, t.c);
+    CHECK_EQ(1.50550e14, t.d);
+    CHECK_EQ(1.8066e16, t.e);
+    CHECK_EQ(120.44, t.f);
+    CHECK_EQ(10.97451593465515908537, t.g);
+  }
+}
+
+
+TEST(MIPS4) {
+  // Test moves between floating point and integer registers.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    double a;
+    double b;
+    double c;
+  } T;
+  T t;
+
+  Assembler assm(NULL, 0);
+  Label L, C;
+
+  if (Isolate::Current()->cpu_features()->IsSupported(FPU)) {
+    CpuFeatures::Scope scope(FPU);
+
+    __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
+    __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
+
+    // Swap f4 and f6, by using four integer registers, t0-t3.
+    __ mfc1(t0, f4);
+    __ mfc1(t1, f5);
+    __ mfc1(t2, f6);
+    __ mfc1(t3, f7);
+
+    __ mtc1(t0, f6);
+    __ mtc1(t1, f7);
+    __ mtc1(t2, f4);
+    __ mtc1(t3, f5);
+
+    // Store the swapped f4 and f5 back to memory.
+    __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
+    __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, c)) );
+
+    __ jr(ra);
+    __ nop();
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Object* code = HEAP->CreateCode(
+        desc,
+        Code::ComputeFlags(Code::STUB),
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+    CHECK(code->IsCode());
+    F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+    t.a = 1.5e22;
+    t.b = 2.75e11;
+    t.c = 17.17;
+    Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+    USE(dummy);
+
+    CHECK_EQ(2.75e11, t.a);
+    CHECK_EQ(2.75e11, t.b);
+    CHECK_EQ(1.5e22, t.c);
+  }
+}
+
+
+TEST(MIPS5) {
+  // Test conversions between doubles and integers.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    double a;
+    double b;
+    int i;
+    int j;
+  } T;
+  T t;
+
+  Assembler assm(NULL, 0);
+  Label L, C;
+
+  if (Isolate::Current()->cpu_features()->IsSupported(FPU)) {
+    CpuFeatures::Scope scope(FPU);
+
+    // Load all structure elements to registers.
+    __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
+    __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
+    __ lw(t0, MemOperand(a0, OFFSET_OF(T, i)) );
+    __ lw(t1, MemOperand(a0, OFFSET_OF(T, j)) );
+
+    // Convert double in f4 to int in element i.
+    __ cvt_w_d(f8, f4);
+    __ mfc1(t2, f8);
+    __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) );
+
+    // Convert double in f6 to int in element j.
+    __ cvt_w_d(f10, f6);
+    __ mfc1(t3, f10);
+    __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) );
+
+    // Convert int in original i (t0) to double in a.
+    __ mtc1(t0, f12);
+    __ cvt_d_w(f0, f12);
+    __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) );
+
+    // Convert int in original j (t1) to double in b.
+    __ mtc1(t1, f14);
+    __ cvt_d_w(f2, f14);
+    __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) );
+
+    __ jr(ra);
+    __ nop();
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Object* code = HEAP->CreateCode(
+        desc,
+        Code::ComputeFlags(Code::STUB),
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+    CHECK(code->IsCode());
+    F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+    t.a = 1.5e4;
+    t.b = 2.75e8;
+    t.i = 12345678;
+    t.j = -100000;
+    Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+    USE(dummy);
+
+    CHECK_EQ(12345678.0, t.a);
+    CHECK_EQ(-100000.0, t.b);
+    CHECK_EQ(15000, t.i);
+    CHECK_EQ(275000000, t.j);
+  }
+}
+
+
+TEST(MIPS6) {
+  // Test simple memory loads and stores.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    uint32_t ui;
+    int32_t si;
+    int32_t r1;
+    int32_t r2;
+    int32_t r3;
+    int32_t r4;
+    int32_t r5;
+    int32_t r6;
+  } T;
+  T t;
+
+  Assembler assm(NULL, 0);
+  Label L, C;
+
+  // Basic word load/store.
+  __ lw(t0, MemOperand(a0, OFFSET_OF(T, ui)) );
+  __ sw(t0, MemOperand(a0, OFFSET_OF(T, r1)) );
+
+  // lh with positive data.
+  __ lh(t1, MemOperand(a0, OFFSET_OF(T, ui)) );
+  __ sw(t1, MemOperand(a0, OFFSET_OF(T, r2)) );
+
+  // lh with negative data.
+  __ lh(t2, MemOperand(a0, OFFSET_OF(T, si)) );
+  __ sw(t2, MemOperand(a0, OFFSET_OF(T, r3)) );
+
+  // lhu with negative data.
+  __ lhu(t3, MemOperand(a0, OFFSET_OF(T, si)) );
+  __ sw(t3, MemOperand(a0, OFFSET_OF(T, r4)) );
+
+  // lb with negative data.
+  __ lb(t4, MemOperand(a0, OFFSET_OF(T, si)) );
+  __ sw(t4, MemOperand(a0, OFFSET_OF(T, r5)) );
+
+  // sh writes only 1/2 of word.
+  __ lui(t5, 0x3333);
+  __ ori(t5, t5, 0x3333);
+  __ sw(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
+  __ lhu(t5, MemOperand(a0, OFFSET_OF(T, si)) );
+  __ sh(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
+
+  __ jr(ra);
+  __ nop();
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+  CHECK(code->IsCode());
+  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+  t.ui = 0x11223344;
+  t.si = 0x99aabbcc;
+  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+  USE(dummy);
+
+  CHECK_EQ(0x11223344, t.r1);
+  CHECK_EQ(0x3344, t.r2);
+  CHECK_EQ(0xffffbbcc, t.r3);
+  CHECK_EQ(0x0000bbcc, t.r4);
+  CHECK_EQ(0xffffffcc, t.r5);
+  CHECK_EQ(0x3333bbcc, t.r6);
+}
+
+
+TEST(MIPS7) {
+  // Test floating point compare and branch instructions.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    double a;
+    double b;
+    double c;
+    double d;
+    double e;
+    double f;
+    int32_t result;
+  } T;
+  T t;
+
+  // Create a function that accepts &t, and loads, manipulates, and stores
+  // the doubles t.a ... t.f.
+  MacroAssembler assm(NULL, 0);
+  Label neither_is_nan, less_than, outa_here;
+
+  if (Isolate::Current()->cpu_features()->IsSupported(FPU)) {
+    CpuFeatures::Scope scope(FPU);
+
+    __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
+    __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
+    __ c(UN, D, f4, f6);
+    __ bc1f(&neither_is_nan);
+    __ nop();
+    __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
+    __ Branch(&outa_here);
+
+    __ bind(&neither_is_nan);
+
+    __ c(OLT, D, f6, f4, 2);
+    __ bc1t(&less_than, 2);
+    __ nop();
+    __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
+    __ Branch(&outa_here);
+
+    __ bind(&less_than);
+    __ Addu(t0, zero_reg, Operand(1));
+    __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) );  // Set true.
+
+
+    // This test-case should have additional tests.
+
+    __ bind(&outa_here);
+
+    __ jr(ra);
+    __ nop();
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Object* code = HEAP->CreateCode(
+        desc,
+        Code::ComputeFlags(Code::STUB),
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+    CHECK(code->IsCode());
+    F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+    t.a = 1.5e14;
+    t.b = 2.75e11;
+    t.c = 2.0;
+    t.d = -4.0;
+    t.e = 0.0;
+    t.f = 0.0;
+    t.result = 0;
+    Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+    USE(dummy);
+    CHECK_EQ(1.5e14, t.a);
+    CHECK_EQ(2.75e11, t.b);
+    CHECK_EQ(1, t.result);
+  }
+}
+
+
+TEST(MIPS8) {
+  // Test ROTR and ROTRV instructions.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    int32_t input;
+    int32_t result_rotr_4;
+    int32_t result_rotr_8;
+    int32_t result_rotr_12;
+    int32_t result_rotr_16;
+    int32_t result_rotr_20;
+    int32_t result_rotr_24;
+    int32_t result_rotr_28;
+    int32_t result_rotrv_4;
+    int32_t result_rotrv_8;
+    int32_t result_rotrv_12;
+    int32_t result_rotrv_16;
+    int32_t result_rotrv_20;
+    int32_t result_rotrv_24;
+    int32_t result_rotrv_28;
+  } T;
+  T t;
+
+  MacroAssembler assm(NULL, 0);
+
+  // Basic word load.
+  __ lw(t0, MemOperand(a0, OFFSET_OF(T, input)) );
+
+  // ROTR instruction (called through the Ror macro).
+  __ Ror(t1, t0, 0x0004);
+  __ Ror(t2, t0, 0x0008);
+  __ Ror(t3, t0, 0x000c);
+  __ Ror(t4, t0, 0x0010);
+  __ Ror(t5, t0, 0x0014);
+  __ Ror(t6, t0, 0x0018);
+  __ Ror(t7, t0, 0x001c);
+
+  // Basic word store.
+  __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotr_4)) );
+  __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotr_8)) );
+  __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotr_12)) );
+  __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotr_16)) );
+  __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotr_20)) );
+  __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotr_24)) );
+  __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotr_28)) );
+
+  // ROTRV instruction (called through the Ror macro).
+  __ li(t7, 0x0004);
+  __ Ror(t1, t0, t7);
+  __ li(t7, 0x0008);
+  __ Ror(t2, t0, t7);
+  __ li(t7, 0x000C);
+  __ Ror(t3, t0, t7);
+  __ li(t7, 0x0010);
+  __ Ror(t4, t0, t7);
+  __ li(t7, 0x0014);
+  __ Ror(t5, t0, t7);
+  __ li(t7, 0x0018);
+  __ Ror(t6, t0, t7);
+  __ li(t7, 0x001C);
+  __ Ror(t7, t0, t7);
+
+  // Basic word store.
+  __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotrv_4)) );
+  __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotrv_8)) );
+  __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotrv_12)) );
+  __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotrv_16)) );
+  __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotrv_20)) );
+  __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotrv_24)) );
+  __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotrv_28)) );
+
+  __ jr(ra);
+  __ nop();
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+  CHECK(code->IsCode());
+  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+  t.input = 0x12345678;
+  Object* dummy = CALL_GENERATED_CODE(f, &t, 0x0, 0, 0, 0);
+  USE(dummy);
+  CHECK_EQ(0x81234567, t.result_rotr_4);
+  CHECK_EQ(0x78123456, t.result_rotr_8);
+  CHECK_EQ(0x67812345, t.result_rotr_12);
+  CHECK_EQ(0x56781234, t.result_rotr_16);
+  CHECK_EQ(0x45678123, t.result_rotr_20);
+  CHECK_EQ(0x34567812, t.result_rotr_24);
+  CHECK_EQ(0x23456781, t.result_rotr_28);
+
+  CHECK_EQ(0x81234567, t.result_rotrv_4);
+  CHECK_EQ(0x78123456, t.result_rotrv_8);
+  CHECK_EQ(0x67812345, t.result_rotrv_12);
+  CHECK_EQ(0x56781234, t.result_rotrv_16);
+  CHECK_EQ(0x45678123, t.result_rotrv_20);
+  CHECK_EQ(0x34567812, t.result_rotrv_24);
+  CHECK_EQ(0x23456781, t.result_rotrv_28);
+}
+
+
+TEST(MIPS9) {
+  // Test BRANCH improvements.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  MacroAssembler assm(NULL, 0);
+  Label exit, exit2, exit3;
+
+  __ Branch(&exit, ge, a0, Operand(0x00000000));
+  __ Branch(&exit2, ge, a0, Operand(0x00001FFF));
+  __ Branch(&exit3, ge, a0, Operand(0x0001FFFF));
+
+  __ bind(&exit);
+  __ bind(&exit2);
+  __ bind(&exit3);
+  __ jr(ra);
+  __ nop();
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+  CHECK(code->IsCode());
+}
+
+
+TEST(MIPS10) {
+  // Test conversions between doubles and long integers.
+  // Test hos the long ints map to FP regs pairs.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    double a;
+    double b;
+    int32_t dbl_mant;
+    int32_t dbl_exp;
+    int32_t long_hi;
+    int32_t long_lo;
+    int32_t b_long_hi;
+    int32_t b_long_lo;
+  } T;
+  T t;
+
+  Assembler assm(NULL, 0);
+  Label L, C;
+
+  if (Isolate::Current()->cpu_features()->IsSupported(FPU)) {
+    CpuFeatures::Scope scope(FPU);
+
+    // Load all structure elements to registers.
+    __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a)));
+
+    // Save the raw bits of the double.
+    __ mfc1(t0, f0);
+    __ mfc1(t1, f1);
+    __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant)));
+    __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp)));
+
+    // Convert double in f0 to long, save hi/lo parts.
+    __ cvt_l_d(f0, f0);
+    __ mfc1(t0, f0);  // f0 has LS 32 bits of long.
+    __ mfc1(t1, f1);  // f1 has MS 32 bits of long.
+    __ sw(t0, MemOperand(a0, OFFSET_OF(T, long_lo)));
+    __ sw(t1, MemOperand(a0, OFFSET_OF(T, long_hi)));
+
+    // Convert the b long integers to double b.
+    __ lw(t0, MemOperand(a0, OFFSET_OF(T, b_long_lo)));
+    __ lw(t1, MemOperand(a0, OFFSET_OF(T, b_long_hi)));
+    __ mtc1(t0, f8);  // f8 has LS 32-bits.
+    __ mtc1(t1, f9);  // f9 has MS 32-bits.
+    __ cvt_d_l(f10, f8);
+    __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b)));
+
+    __ jr(ra);
+    __ nop();
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Object* code = HEAP->CreateCode(
+        desc,
+        Code::ComputeFlags(Code::STUB),
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+    CHECK(code->IsCode());
+    F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+    t.a = 2.147483647e9;       // 0x7fffffff -> 0x41DFFFFFFFC00000 as double.
+    t.b_long_hi = 0x000000ff;  // 0xFF00FF00FF -> 0x426FE01FE01FE000 as double.
+    t.b_long_lo = 0x00ff00ff;
+    Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+    USE(dummy);
+
+    CHECK_EQ(0x41DFFFFF, t.dbl_exp);
+    CHECK_EQ(0xFFC00000, t.dbl_mant);
+    CHECK_EQ(0, t.long_hi);
+    CHECK_EQ(0x7fffffff, t.long_lo);
+    // 0xFF00FF00FF -> 1.095233372415e12.
+    CHECK_EQ(1.095233372415e12, t.b);
+  }
+}
+
+
+TEST(MIPS11) {
+  // Test LWL, LWR, SWL and SWR instructions.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    int32_t reg_init;
+    int32_t mem_init;
+    int32_t lwl_0;
+    int32_t lwl_1;
+    int32_t lwl_2;
+    int32_t lwl_3;
+    int32_t lwr_0;
+    int32_t lwr_1;
+    int32_t lwr_2;
+    int32_t lwr_3;
+    int32_t swl_0;
+    int32_t swl_1;
+    int32_t swl_2;
+    int32_t swl_3;
+    int32_t swr_0;
+    int32_t swr_1;
+    int32_t swr_2;
+    int32_t swr_3;
+  } T;
+  T t;
+
+  Assembler assm(NULL, 0);
+
+  // Test all combinations of LWL and vAddr.
+  __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ lwl(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
+  __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwl_0)) );
+
+  __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ lwl(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
+  __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwl_1)) );
+
+  __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ lwl(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
+  __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwl_2)) );
+
+  __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ lwl(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
+  __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwl_3)) );
+
+  // Test all combinations of LWR and vAddr.
+  __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ lwr(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
+  __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwr_0)) );
+
+  __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ lwr(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
+  __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwr_1)) );
+
+  __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ lwr(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
+  __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwr_2)) );
+
+  __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ lwr(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
+  __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwr_3)) );
+
+  // Test all combinations of SWL and vAddr.
+  __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
+  __ sw(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
+  __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ swl(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
+
+  __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
+  __ sw(t1, MemOperand(a0, OFFSET_OF(T, swl_1)) );
+  __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ swl(t1, MemOperand(a0, OFFSET_OF(T, swl_1) + 1) );
+
+  __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
+  __ sw(t2, MemOperand(a0, OFFSET_OF(T, swl_2)) );
+  __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ swl(t2, MemOperand(a0, OFFSET_OF(T, swl_2) + 2) );
+
+  __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
+  __ sw(t3, MemOperand(a0, OFFSET_OF(T, swl_3)) );
+  __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ swl(t3, MemOperand(a0, OFFSET_OF(T, swl_3) + 3) );
+
+  // Test all combinations of SWR and vAddr.
+  __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
+  __ sw(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
+  __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ swr(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
+
+  __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
+  __ sw(t1, MemOperand(a0, OFFSET_OF(T, swr_1)) );
+  __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ swr(t1, MemOperand(a0, OFFSET_OF(T, swr_1) + 1) );
+
+  __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
+  __ sw(t2, MemOperand(a0, OFFSET_OF(T, swr_2)) );
+  __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ swr(t2, MemOperand(a0, OFFSET_OF(T, swr_2) + 2) );
+
+  __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
+  __ sw(t3, MemOperand(a0, OFFSET_OF(T, swr_3)) );
+  __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
+  __ swr(t3, MemOperand(a0, OFFSET_OF(T, swr_3) + 3) );
+
+  __ jr(ra);
+  __ nop();
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+  CHECK(code->IsCode());
+  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+  t.reg_init = 0xaabbccdd;
+  t.mem_init = 0x11223344;
+
+  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+  USE(dummy);
+
+  CHECK_EQ(0x44bbccdd, t.lwl_0);
+  CHECK_EQ(0x3344ccdd, t.lwl_1);
+  CHECK_EQ(0x223344dd, t.lwl_2);
+  CHECK_EQ(0x11223344, t.lwl_3);
+
+  CHECK_EQ(0x11223344, t.lwr_0);
+  CHECK_EQ(0xaa112233, t.lwr_1);
+  CHECK_EQ(0xaabb1122, t.lwr_2);
+  CHECK_EQ(0xaabbcc11, t.lwr_3);
+
+  CHECK_EQ(0x112233aa, t.swl_0);
+  CHECK_EQ(0x1122aabb, t.swl_1);
+  CHECK_EQ(0x11aabbcc, t.swl_2);
+  CHECK_EQ(0xaabbccdd, t.swl_3);
+
+  CHECK_EQ(0xaabbccdd, t.swr_0);
+  CHECK_EQ(0xbbccdd44, t.swr_1);
+  CHECK_EQ(0xccdd3344, t.swr_2);
+  CHECK_EQ(0xdd223344, t.swr_3);
+}
+
+
+TEST(MIPS12) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+      int32_t  x;
+      int32_t  y;
+      int32_t  y1;
+      int32_t  y2;
+      int32_t  y3;
+      int32_t  y4;
+  } T;
+  T t;
+
+  MacroAssembler assm(NULL, 0);
+
+  __ mov(t6, fp);  // Save frame pointer.
+  __ mov(fp, a0);  // Access struct T by fp.
+  __ lw(t0, MemOperand(a0, OFFSET_OF(T, y)) );
+  __ lw(t3, MemOperand(a0, OFFSET_OF(T, y4)) );
+
+  __ addu(t1, t0, t3);
+  __ subu(t4, t0, t3);
+  __ nop();
+  __ Push(t0);  // These instructions disappear after opt.
+  __ Pop();
+  __ addu(t0, t0, t0);
+  __ nop();
+  __ Pop();     // These instructions disappear after opt.
+  __ Push(t3);
+  __ nop();
+  __ Push(t3);  // These instructions disappear after opt.
+  __ Pop(t3);
+  __ nop();
+  __ Push(t3);
+  __ Pop(t4);
+  __ nop();
+  __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
+  __ lw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
+  __ nop();
+  __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
+  __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
+  __ nop();
+  __ Push(t1);
+  __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
+  __ Pop(t1);
+  __ nop();
+  __ Push(t1);
+  __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
+  __ Pop(t1);
+  __ nop();
+  __ Push(t1);
+  __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
+  __ Pop(t2);
+  __ nop();
+  __ Push(t2);
+  __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
+  __ Pop(t1);
+  __ nop();
+  __ Push(t1);
+  __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
+  __ Pop(t3);
+  __ nop();
+
+  __ mov(fp, t6);
+  __ jr(ra);
+  __ nop();
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+  CHECK(code->IsCode());
+  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+  t.x = 1;
+  t.y = 2;
+  t.y1 = 3;
+  t.y2 = 4;
+  t.y3 = 0XBABA;
+  t.y4 = 0xDEDA;
+
+  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+  USE(dummy);
+
+  CHECK_EQ(3, t.y1);
+}
+
+
+TEST(MIPS13) {
+  // Test Cvt_d_uw and Trunc_uw_d macros.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    double cvt_big_out;
+    double cvt_small_out;
+    uint32_t trunc_big_out;
+    uint32_t trunc_small_out;
+    uint32_t cvt_big_in;
+    uint32_t cvt_small_in;
+  } T;
+  T t;
+
+  MacroAssembler assm(NULL, 0);
+
+  if (Isolate::Current()->cpu_features()->IsSupported(FPU)) {
+    CpuFeatures::Scope scope(FPU);
+
+    __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in)));
+    __ Cvt_d_uw(f10, t0);
+    __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out)));
+
+    __ Trunc_uw_d(f10, f10);
+    __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out)));
+
+    __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in)));
+    __ Cvt_d_uw(f8, t0);
+    __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out)));
+
+    __ Trunc_uw_d(f8, f8);
+    __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out)));
+
+    __ jr(ra);
+    __ nop();
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Object* code = HEAP->CreateCode(
+        desc,
+        Code::ComputeFlags(Code::STUB),
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+    CHECK(code->IsCode());
+    F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+
+    t.cvt_big_in = 0xFFFFFFFF;
+    t.cvt_small_in  = 333;
+
+    Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+    USE(dummy);
+
+    CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in));
+    CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in));
+
+    CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in));
+    CHECK_EQ(static_cast<int>(t.trunc_small_out),
+             static_cast<int>(t.cvt_small_in));
+  }
+}
+
+
+TEST(MIPS14) {
+  // Test round, floor, ceil, trunc, cvt.
+  InitializeVM();
+  v8::HandleScope scope;
+
+#define ROUND_STRUCT_ELEMENT(x) \
+  int32_t x##_up_out; \
+  int32_t x##_down_out; \
+  int32_t neg_##x##_up_out; \
+  int32_t neg_##x##_down_out; \
+  int32_t x##_err1_out; \
+  int32_t x##_err2_out; \
+  int32_t x##_err3_out; \
+  int32_t x##_err4_out; \
+  int32_t x##_invalid_result;
+
+  typedef struct {
+    double round_up_in;
+    double round_down_in;
+    double neg_round_up_in;
+    double neg_round_down_in;
+    double err1_in;
+    double err2_in;
+    double err3_in;
+    double err4_in;
+
+    ROUND_STRUCT_ELEMENT(round)
+    ROUND_STRUCT_ELEMENT(floor)
+    ROUND_STRUCT_ELEMENT(ceil)
+    ROUND_STRUCT_ELEMENT(trunc)
+    ROUND_STRUCT_ELEMENT(cvt)
+  } T;
+  T t;
+
+#undef ROUND_STRUCT_ELEMENT
+
+  MacroAssembler assm(NULL, 0);
+
+  if (Isolate::Current()->cpu_features()->IsSupported(FPU)) {
+    CpuFeatures::Scope scope(FPU);
+
+    // Save FCSR.
+    __ cfc1(a1, FCSR);
+    // Disable FPU exceptions.
+    __ ctc1(zero_reg, FCSR);
+#define RUN_ROUND_TEST(x) \
+    __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_up_in))); \
+    __ x##_w_d(f0, f0); \
+    __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_up_out))); \
+    \
+    __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_down_in))); \
+    __ x##_w_d(f0, f0); \
+    __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_down_out))); \
+    \
+    __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_up_in))); \
+    __ x##_w_d(f0, f0); \
+    __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_up_out))); \
+    \
+    __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_down_in))); \
+    __ x##_w_d(f0, f0); \
+    __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_down_out))); \
+    \
+    __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err1_in))); \
+    __ ctc1(zero_reg, FCSR); \
+    __ x##_w_d(f0, f0); \
+    __ cfc1(a2, FCSR); \
+    __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err1_out))); \
+    \
+    __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err2_in))); \
+    __ ctc1(zero_reg, FCSR); \
+    __ x##_w_d(f0, f0); \
+    __ cfc1(a2, FCSR); \
+    __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err2_out))); \
+    \
+    __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err3_in))); \
+    __ ctc1(zero_reg, FCSR); \
+    __ x##_w_d(f0, f0); \
+    __ cfc1(a2, FCSR); \
+    __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err3_out))); \
+    \
+    __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err4_in))); \
+    __ ctc1(zero_reg, FCSR); \
+    __ x##_w_d(f0, f0); \
+    __ cfc1(a2, FCSR); \
+    __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err4_out))); \
+    __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_invalid_result)));
+
+    RUN_ROUND_TEST(round)
+    RUN_ROUND_TEST(floor)
+    RUN_ROUND_TEST(ceil)
+    RUN_ROUND_TEST(trunc)
+    RUN_ROUND_TEST(cvt)
+
+    // Restore FCSR.
+    __ ctc1(a1, FCSR);
+
+#undef RUN_ROUND_TEST
+
+    __ jr(ra);
+    __ nop();
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Object* code = HEAP->CreateCode(
+        desc,
+        Code::ComputeFlags(Code::STUB),
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+    CHECK(code->IsCode());
+    F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+
+    t.round_up_in = 123.51;
+    t.round_down_in = 123.49;
+    t.neg_round_up_in = -123.5;
+    t.neg_round_down_in = -123.49;
+    t.err1_in = 123.51;
+    t.err2_in = 1;
+    t.err3_in = static_cast<double>(1) + 0xFFFFFFFF;
+    t.err4_in = NAN;
+
+    Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+    USE(dummy);
+
+#define GET_FPU_ERR(x) ((x >> 2) & (32 - 1))
+
+    CHECK_EQ(124, t.round_up_out);
+    CHECK_EQ(123, t.round_down_out);
+    CHECK_EQ(-124, t.neg_round_up_out);
+    CHECK_EQ(-123, t.neg_round_down_out);
+
+    // Inaccurate.
+    CHECK_EQ(1, GET_FPU_ERR(t.round_err1_out));
+    // No error.
+    CHECK_EQ(0, GET_FPU_ERR(t.round_err2_out));
+    // Invalid operation.
+    CHECK_EQ(16, GET_FPU_ERR(t.round_err3_out));
+    CHECK_EQ(16, GET_FPU_ERR(t.round_err4_out));
+    CHECK_EQ(kFPUInvalidResult, t.round_invalid_result);
+
+    CHECK_EQ(123, t.floor_up_out);
+    CHECK_EQ(123, t.floor_down_out);
+    CHECK_EQ(-124, t.neg_floor_up_out);
+    CHECK_EQ(-124, t.neg_floor_down_out);
+
+    // Inaccurate.
+    CHECK_EQ(1, GET_FPU_ERR(t.floor_err1_out));
+    // No error.
+    CHECK_EQ(0, GET_FPU_ERR(t.floor_err2_out));
+    // Invalid operation.
+    CHECK_EQ(16, GET_FPU_ERR(t.floor_err3_out));
+    CHECK_EQ(16, GET_FPU_ERR(t.floor_err4_out));
+    CHECK_EQ(kFPUInvalidResult, t.floor_invalid_result);
+
+    CHECK_EQ(124, t.ceil_up_out);
+    CHECK_EQ(124, t.ceil_down_out);
+    CHECK_EQ(-123, t.neg_ceil_up_out);
+    CHECK_EQ(-123, t.neg_ceil_down_out);
+
+    // Inaccurate.
+    CHECK_EQ(1, GET_FPU_ERR(t.ceil_err1_out));
+    // No error.
+    CHECK_EQ(0, GET_FPU_ERR(t.ceil_err2_out));
+    // Invalid operation.
+    CHECK_EQ(16, GET_FPU_ERR(t.ceil_err3_out));
+    CHECK_EQ(16, GET_FPU_ERR(t.ceil_err4_out));
+    CHECK_EQ(kFPUInvalidResult, t.ceil_invalid_result);
+
+    // In rounding mode 0 cvt should behave like round.
+    CHECK_EQ(t.round_up_out, t.cvt_up_out);
+    CHECK_EQ(t.round_down_out, t.cvt_down_out);
+    CHECK_EQ(t.neg_round_up_out, t.neg_cvt_up_out);
+    CHECK_EQ(t.neg_round_down_out, t.neg_cvt_down_out);
+
+    // Inaccurate.
+    CHECK_EQ(1, GET_FPU_ERR(t.cvt_err1_out));
+    // No error.
+    CHECK_EQ(0, GET_FPU_ERR(t.cvt_err2_out));
+    // Invalid operation.
+    CHECK_EQ(16, GET_FPU_ERR(t.cvt_err3_out));
+    CHECK_EQ(16, GET_FPU_ERR(t.cvt_err4_out));
+    CHECK_EQ(kFPUInvalidResult, t.cvt_invalid_result);
+  }
+}
+
+
 #undef __
diff --git a/test/cctest/test-assembler-x64.cc b/test/cctest/test-assembler-x64.cc
index 5d292df..7e2115a 100644
--- a/test/cctest/test-assembler-x64.cc
+++ b/test/cctest/test-assembler-x64.cc
@@ -50,8 +50,8 @@
 using v8::internal::rsp;
 using v8::internal::r8;
 using v8::internal::r9;
-using v8::internal::r12;
 using v8::internal::r13;
+using v8::internal::r15;
 using v8::internal::times_1;
 
 using v8::internal::FUNCTION_CAST;
@@ -86,6 +86,7 @@
 
 
 TEST(AssemblerX64ReturnOperation) {
+  OS::Setup();
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -107,6 +108,7 @@
 }
 
 TEST(AssemblerX64StackOperations) {
+  OS::Setup();
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -138,6 +140,7 @@
 }
 
 TEST(AssemblerX64ArithmeticOperations) {
+  OS::Setup();
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -159,6 +162,7 @@
 }
 
 TEST(AssemblerX64ImulOperation) {
+  OS::Setup();
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -186,6 +190,7 @@
 }
 
 TEST(AssemblerX64MemoryOperands) {
+  OS::Setup();
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -219,6 +224,7 @@
 }
 
 TEST(AssemblerX64ControlFlow) {
+  OS::Setup();
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -247,6 +253,7 @@
 }
 
 TEST(AssemblerX64LoopImmediates) {
+  OS::Setup();
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -317,7 +324,7 @@
 
     CHECK(Operand(rsp, offset).AddressUsesRegister(rsp));
     CHECK(!Operand(rsp, offset).AddressUsesRegister(rax));
-    CHECK(!Operand(rsp, offset).AddressUsesRegister(r12));
+    CHECK(!Operand(rsp, offset).AddressUsesRegister(r15));
 
     CHECK(Operand(rbp, offset).AddressUsesRegister(rbp));
     CHECK(!Operand(rbp, offset).AddressUsesRegister(rax));
@@ -333,7 +340,7 @@
     CHECK(Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rsp));
     CHECK(Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rbp));
     CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rax));
-    CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(r12));
+    CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(r15));
     CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(r13));
   }
 }
diff --git a/test/cctest/test-ast.cc b/test/cctest/test-ast.cc
index 9c292bc..6183357 100644
--- a/test/cctest/test-ast.cc
+++ b/test/cctest/test-ast.cc
@@ -35,6 +35,7 @@
 using namespace v8::internal;
 
 TEST(List) {
+  v8::internal::V8::Initialize(NULL);
   List<AstNode*>* list = new List<AstNode*>(0);
   CHECK_EQ(0, list->length());
 
diff --git a/test/cctest/test-circular-queue.cc b/test/cctest/test-circular-queue.cc
index ce9a42e..9dd4981 100644
--- a/test/cctest/test-circular-queue.cc
+++ b/test/cctest/test-circular-queue.cc
@@ -84,11 +84,13 @@
  public:
   typedef SamplingCircularQueue::Cell Record;
 
-  ProducerThread(SamplingCircularQueue* scq,
+  ProducerThread(i::Isolate* isolate,
+                 SamplingCircularQueue* scq,
                  int records_per_chunk,
                  Record value,
                  i::Semaphore* finished)
-      : scq_(scq),
+      : Thread(isolate, "producer"),
+        scq_(scq),
         records_per_chunk_(records_per_chunk),
         value_(value),
         finished_(finished) { }
@@ -131,9 +133,10 @@
   // Check that we are using non-reserved values.
   CHECK_NE(SamplingCircularQueue::kClear, 1);
   CHECK_NE(SamplingCircularQueue::kEnd, 1);
-  ProducerThread producer1(&scq, kRecordsPerChunk, 1, semaphore);
-  ProducerThread producer2(&scq, kRecordsPerChunk, 10, semaphore);
-  ProducerThread producer3(&scq, kRecordsPerChunk, 20, semaphore);
+  i::Isolate* isolate = i::Isolate::Current();
+  ProducerThread producer1(isolate, &scq, kRecordsPerChunk, 1, semaphore);
+  ProducerThread producer2(isolate, &scq, kRecordsPerChunk, 10, semaphore);
+  ProducerThread producer3(isolate, &scq, kRecordsPerChunk, 20, semaphore);
 
   CHECK_EQ(NULL, scq.StartDequeue());
   producer1.Start();
diff --git a/test/cctest/test-compiler.cc b/test/cctest/test-compiler.cc
index 9f21b78..d3dd9c6 100644
--- a/test/cctest/test-compiler.cc
+++ b/test/cctest/test-compiler.cc
@@ -34,7 +34,6 @@
 #include "execution.h"
 #include "factory.h"
 #include "platform.h"
-#include "top.h"
 #include "cctest.h"
 
 using namespace v8::internal;
@@ -99,21 +98,21 @@
 
 
 static MaybeObject* GetGlobalProperty(const char* name) {
-  Handle<String> symbol = Factory::LookupAsciiSymbol(name);
-  return Top::context()->global()->GetProperty(*symbol);
+  Handle<String> symbol = FACTORY->LookupAsciiSymbol(name);
+  return Isolate::Current()->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());
+  Handle<String> symbol = FACTORY->LookupAsciiSymbol(name);
+  Handle<JSObject> global(Isolate::Current()->context()->global());
   SetProperty(global, symbol, object, NONE, kNonStrictMode);
 }
 
 
 static Handle<JSFunction> Compile(const char* source) {
-  Handle<String> source_code(Factory::NewStringFromUtf8(CStrVector(source)));
+  Handle<String> source_code(FACTORY->NewStringFromUtf8(CStrVector(source)));
   Handle<SharedFunctionInfo> shared_function =
       Compiler::Compile(source_code,
                         Handle<String>(),
@@ -123,8 +122,8 @@
                         NULL,
                         Handle<String>::null(),
                         NOT_NATIVES_CODE);
-  return Factory::NewFunctionFromSharedFunctionInfo(shared_function,
-                                                    Top::global_context());
+  return FACTORY->NewFunctionFromSharedFunctionInfo(shared_function,
+      Isolate::Current()->global_context());
 }
 
 
@@ -137,7 +136,7 @@
   if (fun.is_null()) return -1;
 
   bool has_pending_exception;
-  Handle<JSObject> global(Top::context()->global());
+  Handle<JSObject> global(Isolate::Current()->context()->global());
   Execution::Call(fun, global, 0, NULL, &has_pending_exception);
   CHECK(!has_pending_exception);
   return GetGlobalProperty("result")->ToObjectChecked()->Number();
@@ -158,7 +157,7 @@
   SetGlobalProperty("x", Smi::FromInt(x));
   SetGlobalProperty("y", Smi::FromInt(y));
   bool has_pending_exception;
-  Handle<JSObject> global(Top::context()->global());
+  Handle<JSObject> global(Isolate::Current()->context()->global());
   Execution::Call(fun, global, 0, NULL, &has_pending_exception);
   CHECK(!has_pending_exception);
   return GetGlobalProperty("result")->ToObjectChecked()->Number();
@@ -178,7 +177,7 @@
 
   SetGlobalProperty("x", Smi::FromInt(x));
   bool has_pending_exception;
-  Handle<JSObject> global(Top::context()->global());
+  Handle<JSObject> global(Isolate::Current()->context()->global());
   Execution::Call(fun, global, 0, NULL, &has_pending_exception);
   CHECK(!has_pending_exception);
   return GetGlobalProperty("result")->ToObjectChecked()->Number();
@@ -199,7 +198,7 @@
 
   SetGlobalProperty("n", Smi::FromInt(n));
   bool has_pending_exception;
-  Handle<JSObject> global(Top::context()->global());
+  Handle<JSObject> global(Isolate::Current()->context()->global());
   Execution::Call(fun, global, 0, NULL, &has_pending_exception);
   CHECK(!has_pending_exception);
   return GetGlobalProperty("result")->ToObjectChecked()->Number();
@@ -220,7 +219,7 @@
   Handle<JSFunction> fun = Compile(source);
   if (fun.is_null()) return;
   bool has_pending_exception;
-  Handle<JSObject> global(Top::context()->global());
+  Handle<JSObject> global(Isolate::Current()->context()->global());
   Execution::Call(fun, global, 0, NULL, &has_pending_exception);
   CHECK(!has_pending_exception);
 }
@@ -253,7 +252,7 @@
   Handle<JSFunction> fun = Compile(source);
   CHECK(!fun.is_null());
   bool has_pending_exception;
-  Handle<JSObject> global(Top::context()->global());
+  Handle<JSObject> global(Isolate::Current()->context()->global());
   Execution::Call(fun, global, 0, NULL, &has_pending_exception);
   CHECK(!has_pending_exception);
   CHECK_EQ(511.0, GetGlobalProperty("r")->ToObjectChecked()->Number());
@@ -268,11 +267,12 @@
   Handle<JSFunction> fun = Compile(source);
   CHECK(!fun.is_null());
   bool has_pending_exception;
-  Handle<JSObject> global(Top::context()->global());
+  Handle<JSObject> global(Isolate::Current()->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()->ToObjectChecked()->Number());
+  CHECK_EQ(42.0, Isolate::Current()->pending_exception()->
+           ToObjectChecked()->Number());
 }
 
 
@@ -293,18 +293,18 @@
 
   // Run the generated code to populate the global object with 'foo'.
   bool has_pending_exception;
-  Handle<JSObject> global(Top::context()->global());
+  Handle<JSObject> global(Isolate::Current()->context()->global());
   Execution::Call(fun0, global, 0, NULL, &has_pending_exception);
   CHECK(!has_pending_exception);
 
-  Object* foo_symbol = Factory::LookupAsciiSymbol("foo")->ToObjectChecked();
-  MaybeObject* fun1_object =
-      Top::context()->global()->GetProperty(String::cast(foo_symbol));
+  Object* foo_symbol = FACTORY->LookupAsciiSymbol("foo")->ToObjectChecked();
+  MaybeObject* fun1_object = Isolate::Current()->context()->global()->
+      GetProperty(String::cast(foo_symbol));
   Handle<Object> fun1(fun1_object->ToObjectChecked());
   CHECK(fun1->IsJSFunction());
 
   Object** argv[1] = {
-    Handle<Object>::cast(Factory::LookupAsciiSymbol("hello")).location()
+    Handle<Object>::cast(FACTORY->LookupAsciiSymbol("hello")).location()
   };
   Execution::Call(Handle<JSFunction>::cast(fun1), global, 1, argv,
                   &has_pending_exception);
@@ -318,8 +318,8 @@
   InitializeVM();
   v8::HandleScope scope;
 
-  Handle<Script> script = Factory::NewScript(Factory::empty_string());
-  script->set_source(Heap::undefined_value());
+  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/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index 7f06bc3..749ac15 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -7,6 +7,7 @@
 #include "v8.h"
 #include "cpu-profiler-inl.h"
 #include "cctest.h"
+#include "../include/v8-profiler.h"
 
 namespace i = v8::internal;
 
@@ -23,7 +24,7 @@
 TEST(StartStop) {
   CpuProfilesCollection profiles;
   ProfileGenerator generator(&profiles);
-  ProfilerEventsProcessor processor(&generator);
+  ProfilerEventsProcessor processor(i::Isolate::Current(), &generator);
   processor.Start();
   while (!processor.running()) {
     i::Thread::YieldCPU();
@@ -87,7 +88,7 @@
   CpuProfilesCollection profiles;
   profiles.StartProfiling("", 1);
   ProfileGenerator generator(&profiles);
-  ProfilerEventsProcessor processor(&generator);
+  ProfilerEventsProcessor processor(i::Isolate::Current(), &generator);
   processor.Start();
   while (!processor.running()) {
     i::Thread::YieldCPU();
@@ -96,11 +97,11 @@
   // Enqueue code creation events.
   i::HandleScope scope;
   const char* aaa_str = "aaa";
-  i::Handle<i::String> aaa_name = i::Factory::NewStringFromAscii(
+  i::Handle<i::String> aaa_name = FACTORY->NewStringFromAscii(
       i::Vector<const char>(aaa_str, i::StrLength(aaa_str)));
   processor.CodeCreateEvent(i::Logger::FUNCTION_TAG,
                             *aaa_name,
-                            i::Heap::empty_string(),
+                            HEAP->empty_string(),
                             0,
                             ToAddress(0x1000),
                             0x100,
@@ -151,7 +152,7 @@
   CpuProfilesCollection profiles;
   profiles.StartProfiling("", 1);
   ProfileGenerator generator(&profiles);
-  ProfilerEventsProcessor processor(&generator);
+  ProfilerEventsProcessor processor(i::Isolate::Current(), &generator);
   processor.Start();
   while (!processor.running()) {
     i::Thread::YieldCPU();
@@ -236,4 +237,138 @@
   CpuProfiler::TearDown();
 }
 
+
+TEST(DeleteAllCpuProfiles) {
+  InitializeVM();
+  TestSetup test_setup;
+  CpuProfiler::Setup();
+  CHECK_EQ(0, CpuProfiler::GetProfilesCount());
+  CpuProfiler::DeleteAllProfiles();
+  CHECK_EQ(0, CpuProfiler::GetProfilesCount());
+
+  CpuProfiler::StartProfiling("1");
+  CpuProfiler::StopProfiling("1");
+  CHECK_EQ(1, CpuProfiler::GetProfilesCount());
+  CpuProfiler::DeleteAllProfiles();
+  CHECK_EQ(0, CpuProfiler::GetProfilesCount());
+  CpuProfiler::StartProfiling("1");
+  CpuProfiler::StartProfiling("2");
+  CpuProfiler::StopProfiling("2");
+  CpuProfiler::StopProfiling("1");
+  CHECK_EQ(2, CpuProfiler::GetProfilesCount());
+  CpuProfiler::DeleteAllProfiles();
+  CHECK_EQ(0, CpuProfiler::GetProfilesCount());
+
+  // Test profiling cancellation by the 'delete' command.
+  CpuProfiler::StartProfiling("1");
+  CpuProfiler::StartProfiling("2");
+  CHECK_EQ(0, CpuProfiler::GetProfilesCount());
+  CpuProfiler::DeleteAllProfiles();
+  CHECK_EQ(0, CpuProfiler::GetProfilesCount());
+
+  CpuProfiler::TearDown();
+}
+
+
+TEST(DeleteCpuProfile) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
+  v8::Local<v8::String> name1 = v8::String::New("1");
+  v8::CpuProfiler::StartProfiling(name1);
+  const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1);
+  CHECK_NE(NULL, p1);
+  CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
+  unsigned uid1 = p1->GetUid();
+  CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1));
+  const_cast<v8::CpuProfile*>(p1)->Delete();
+  CHECK_EQ(0, CpuProfiler::GetProfilesCount());
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
+
+  v8::Local<v8::String> name2 = v8::String::New("2");
+  v8::CpuProfiler::StartProfiling(name2);
+  const v8::CpuProfile* p2 = v8::CpuProfiler::StopProfiling(name2);
+  CHECK_NE(NULL, p2);
+  CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
+  unsigned uid2 = p2->GetUid();
+  CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
+  CHECK_EQ(p2, v8::CpuProfiler::FindProfile(uid2));
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
+  v8::Local<v8::String> name3 = v8::String::New("3");
+  v8::CpuProfiler::StartProfiling(name3);
+  const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3);
+  CHECK_NE(NULL, p3);
+  CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount());
+  unsigned uid3 = p3->GetUid();
+  CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
+  CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
+  const_cast<v8::CpuProfile*>(p2)->Delete();
+  CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
+  CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
+  const_cast<v8::CpuProfile*>(p3)->Delete();
+  CHECK_EQ(0, CpuProfiler::GetProfilesCount());
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3));
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
+}
+
+
+TEST(DeleteCpuProfileDifferentTokens) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
+  v8::Local<v8::String> name1 = v8::String::New("1");
+  v8::CpuProfiler::StartProfiling(name1);
+  const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1);
+  CHECK_NE(NULL, p1);
+  CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
+  unsigned uid1 = p1->GetUid();
+  CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1));
+  v8::Local<v8::String> token1 = v8::String::New("token1");
+  const v8::CpuProfile* p1_t1 = v8::CpuProfiler::FindProfile(uid1, token1);
+  CHECK_NE(NULL, p1_t1);
+  CHECK_NE(p1, p1_t1);
+  CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
+  const_cast<v8::CpuProfile*>(p1)->Delete();
+  CHECK_EQ(0, CpuProfiler::GetProfilesCount());
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1, token1));
+  const_cast<v8::CpuProfile*>(p1_t1)->Delete();
+  CHECK_EQ(0, CpuProfiler::GetProfilesCount());
+
+  v8::Local<v8::String> name2 = v8::String::New("2");
+  v8::CpuProfiler::StartProfiling(name2);
+  v8::Local<v8::String> token2 = v8::String::New("token2");
+  const v8::CpuProfile* p2_t2 = v8::CpuProfiler::StopProfiling(name2, token2);
+  CHECK_NE(NULL, p2_t2);
+  CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
+  unsigned uid2 = p2_t2->GetUid();
+  CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
+  const v8::CpuProfile* p2 = v8::CpuProfiler::FindProfile(uid2);
+  CHECK_NE(p2_t2, p2);
+  v8::Local<v8::String> name3 = v8::String::New("3");
+  v8::CpuProfiler::StartProfiling(name3);
+  const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3);
+  CHECK_NE(NULL, p3);
+  CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount());
+  unsigned uid3 = p3->GetUid();
+  CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
+  CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
+  const_cast<v8::CpuProfile*>(p2_t2)->Delete();
+  CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
+  CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
+  const_cast<v8::CpuProfile*>(p2)->Delete();
+  CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
+  CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
+  const_cast<v8::CpuProfile*>(p3)->Delete();
+  CHECK_EQ(0, CpuProfiler::GetProfilesCount());
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3));
+}
+
 #endif  // ENABLE_LOGGING_AND_PROFILING
diff --git a/test/cctest/test-dataflow.cc b/test/cctest/test-dataflow.cc
index 5894de2..feae0b0 100644
--- a/test/cctest/test-dataflow.cc
+++ b/test/cctest/test-dataflow.cc
@@ -35,6 +35,7 @@
 using namespace v8::internal;
 
 TEST(BitVector) {
+  v8::internal::V8::Initialize(NULL);
   ZoneScope zone(DELETE_ON_EXIT);
   {
     BitVector v(15);
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 7245e54..b81129e 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -143,17 +143,18 @@
   inline v8::Context* operator*() { return *context_; }
   inline bool IsReady() { return !context_.IsEmpty(); }
   void ExposeDebug() {
+    v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
     // Expose the debug context global object in the global object for testing.
-    Debug::Load();
-    Debug::debug_context()->set_security_token(
+    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");
+        FACTORY->LookupAsciiSymbol("debug");
     SetProperty(global, debug_string,
-        Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM,
+        Handle<Object>(debug->debug_context()->global_proxy()), DONT_ENUM,
         ::v8::internal::kNonStrictMode);
   }
  private:
@@ -196,7 +197,8 @@
 static int SetBreakPoint(Handle<v8::internal::JSFunction> fun, int position) {
   static int break_point = 0;
   Handle<v8::internal::SharedFunctionInfo> shared(fun->shared());
-  Debug::SetBreakPoint(
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
+  debug->SetBreakPoint(
       shared,
       Handle<Object>(v8::internal::Smi::FromInt(++break_point)),
       &position);
@@ -279,7 +281,8 @@
 
 // Clear a break point.
 static void ClearBreakPoint(int break_point) {
-  Debug::ClearBreakPoint(
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
+  debug->ClearBreakPoint(
       Handle<Object>(v8::internal::Smi::FromInt(break_point)));
 }
 
@@ -339,8 +342,9 @@
 
 // Change break on exception.
 static void ChangeBreakOnException(bool caught, bool uncaught) {
-  Debug::ChangeBreakOnException(v8::internal::BreakException, caught);
-  Debug::ChangeBreakOnException(v8::internal::BreakUncaughtException, uncaught);
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
+  debug->ChangeBreakOnException(v8::internal::BreakException, caught);
+  debug->ChangeBreakOnException(v8::internal::BreakUncaughtException, uncaught);
 }
 
 
@@ -365,7 +369,8 @@
 
 // Prepare to step to next break location.
 static void PrepareStep(StepAction step_action) {
-  Debug::PrepareStep(step_action, 1);
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
+  debug->PrepareStep(step_action, 1);
 }
 
 
@@ -376,7 +381,9 @@
 
 // Collect the currently debugged functions.
 Handle<FixedArray> GetDebuggedFunctions() {
-  v8::internal::DebugInfoListNode* node = Debug::debug_info_list_;
+  Debug* debug = Isolate::Current()->debug();
+
+  v8::internal::DebugInfoListNode* node = debug->debug_info_list_;
 
   // Find the number of debugged functions.
   int count = 0;
@@ -387,7 +394,7 @@
 
   // Allocate array for the debugged functions
   Handle<FixedArray> debugged_functions =
-      v8::internal::Factory::NewFixedArray(count);
+      FACTORY->NewFixedArray(count);
 
   // Run through the debug info objects and collect all functions.
   count = 0;
@@ -402,7 +409,9 @@
 
 static Handle<Code> ComputeCallDebugBreak(int argc) {
   CALL_HEAP_FUNCTION(
-      v8::internal::StubCache::ComputeCallDebugBreak(argc, Code::CALL_IC),
+      v8::internal::Isolate::Current(),
+      v8::internal::Isolate::Current()->stub_cache()->ComputeCallDebugBreak(
+          argc, Code::CALL_IC),
       Code);
 }
 
@@ -411,12 +420,12 @@
 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_);
+  CHECK(Isolate::Current()->debug()->debug_context().is_null());
+  CHECK_EQ(NULL, Isolate::Current()->debug()->debug_info_list_);
 
   // Collect garbage to ensure weak handles are cleared.
-  Heap::CollectAllGarbage(false);
-  Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 
   // Iterate the head and check that there are no debugger related objects left.
   HeapIterator iterator;
@@ -444,8 +453,8 @@
 
 
 void ForceUnloadDebugger() {
-  Debugger::never_unload_debugger_ = false;
-  Debugger::UnloadDebugger();
+  Isolate::Current()->debugger()->never_unload_debugger_ = false;
+  Isolate::Current()->debugger()->UnloadDebugger();
 }
 
 
@@ -480,6 +489,8 @@
                              const char* source, const char* name,
                              int position, v8::internal::RelocInfo::Mode mode,
                              Code* debug_break) {
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
+
   // Create function and set the break point.
   Handle<v8::internal::JSFunction> fun = v8::Utils::OpenHandle(
       *CompileFunction(env, source, name));
@@ -501,8 +512,8 @@
   // 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));
+  CHECK(!debug->HasDebugInfo(shared));
+  CHECK(debug->EnsureDebugInfo(shared));
   TestBreakLocationIterator it2(Debug::GetDebugInfo(shared));
   it2.FindBreakLocationFromPosition(position);
   CHECK_EQ(mode, it2.it()->rinfo()->rmode());
@@ -634,8 +645,9 @@
                                          v8::Handle<v8::Object> exec_state,
                                          v8::Handle<v8::Object> event_data,
                                          v8::Handle<v8::Value> data) {
+  Debug* debug = v8::internal::Isolate::Current()->debug();
   // When hitting a debug event listener there must be a break set.
-  CHECK_NE(v8::internal::Debug::break_id(), 0);
+  CHECK_NE(debug->break_id(), 0);
 
   // Count the number of breaks.
   if (event == v8::Break) {
@@ -738,8 +750,10 @@
                               v8::Handle<v8::Object> exec_state,
                               v8::Handle<v8::Object> event_data,
                               v8::Handle<v8::Value> data) {
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
+
   // When hitting a debug event listener there must be a break set.
-  CHECK_NE(v8::internal::Debug::break_id(), 0);
+  CHECK_NE(debug->break_id(), 0);
 
   // Count the number of breaks.
   if (event == v8::Break) {
@@ -796,8 +810,9 @@
                                v8::Handle<v8::Object> exec_state,
                                v8::Handle<v8::Object> event_data,
                                v8::Handle<v8::Value> data) {
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
   // When hitting a debug event listener there must be a break set.
-  CHECK_NE(v8::internal::Debug::break_id(), 0);
+  CHECK_NE(debug->break_id(), 0);
 
   if (event == v8::Break) {
     for (int i = 0; checks[i].expr != NULL; i++) {
@@ -822,8 +837,9 @@
                                        v8::Handle<v8::Object> exec_state,
                                        v8::Handle<v8::Object> event_data,
                                        v8::Handle<v8::Value> data) {
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
   // When hitting a debug event listener there must be a break set.
-  CHECK_NE(v8::internal::Debug::break_id(), 0);
+  CHECK_NE(debug->break_id(), 0);
 
   if (event == v8::Break) {
     break_point_hit_count++;
@@ -840,8 +856,9 @@
                            v8::Handle<v8::Object> exec_state,
                            v8::Handle<v8::Object> event_data,
                            v8::Handle<v8::Value> data) {
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
   // When hitting a debug event listener there must be a break set.
-  CHECK_NE(v8::internal::Debug::break_id(), 0);
+  CHECK_NE(debug->break_id(), 0);
 
   if (event == v8::Break) {
     break_point_hit_count++;
@@ -866,8 +883,9 @@
                                    v8::Handle<v8::Object> exec_state,
                                    v8::Handle<v8::Object> event_data,
                                    v8::Handle<v8::Value> data) {
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
   // When hitting a debug event listener there must be a break set.
-  CHECK_NE(v8::internal::Debug::break_id(), 0);
+  CHECK_NE(debug->break_id(), 0);
 
   if (event == v8::Break || event == v8::Exception) {
     // Check that the current function is the expected.
@@ -896,8 +914,9 @@
     v8::Handle<v8::Object> exec_state,
     v8::Handle<v8::Object> event_data,
     v8::Handle<v8::Value> data) {
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
   // When hitting a debug event listener there must be a break set.
-  CHECK_NE(v8::internal::Debug::break_id(), 0);
+  CHECK_NE(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
@@ -906,10 +925,10 @@
     break_point_hit_count++;
     if (break_point_hit_count % 2 == 0) {
       // Scavenge.
-      Heap::CollectGarbage(v8::internal::NEW_SPACE);
+      HEAP->CollectGarbage(v8::internal::NEW_SPACE);
     } else {
       // Mark sweep compact.
-      Heap::CollectAllGarbage(true);
+      HEAP->CollectAllGarbage(true);
     }
   }
 }
@@ -921,8 +940,9 @@
                             v8::Handle<v8::Object> exec_state,
                             v8::Handle<v8::Object> event_data,
                             v8::Handle<v8::Value> data) {
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
   // When hitting a debug event listener there must be a break set.
-  CHECK_NE(v8::internal::Debug::break_id(), 0);
+  CHECK_NE(debug->break_id(), 0);
 
   if (event == v8::Break) {
     // Count the number of breaks.
@@ -930,7 +950,7 @@
 
     // Run the garbage collector to enforce heap verification if option
     // --verify-heap is set.
-    Heap::CollectGarbage(v8::internal::NEW_SPACE);
+    HEAP->CollectGarbage(v8::internal::NEW_SPACE);
 
     // Set the break flag again to come back here as soon as possible.
     v8::Debug::DebugBreak();
@@ -946,8 +966,9 @@
                                v8::Handle<v8::Object> exec_state,
                                v8::Handle<v8::Object> event_data,
                                v8::Handle<v8::Value> data) {
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
   // When hitting a debug event listener there must be a break set.
-  CHECK_NE(v8::internal::Debug::break_id(), 0);
+  CHECK_NE(debug->break_id(), 0);
 
   if (event == v8::Break) {
     if (break_point_hit_count < max_break_point_hit_count) {
@@ -987,6 +1008,7 @@
 // of break locations.
 TEST(DebugStub) {
   using ::v8::internal::Builtins;
+  using ::v8::internal::Isolate;
   v8::HandleScope scope;
   DebugLocalContext env;
 
@@ -999,12 +1021,14 @@
                           "function f2(){x=1;}", "f2",
                           0,
                           v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
-                          Builtins::builtin(Builtins::StoreIC_DebugBreak));
+                          Isolate::Current()->builtins()->builtin(
+                              Builtins::kStoreIC_DebugBreak));
   CheckDebugBreakFunction(&env,
                           "function f3(){var a=x;}", "f3",
                           0,
                           v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
-                          Builtins::builtin(Builtins::LoadIC_DebugBreak));
+                          Isolate::Current()->builtins()->builtin(
+                              Builtins::kLoadIC_DebugBreak));
 
 // TODO(1240753): Make the test architecture independent or split
 // parts of the debugger into architecture dependent files. This
@@ -1017,14 +1041,16 @@
       "f4",
       0,
       v8::internal::RelocInfo::CODE_TARGET,
-      Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak));
+      Isolate::Current()->builtins()->builtin(
+          Builtins::kKeyedStoreIC_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));
+      Isolate::Current()->builtins()->builtin(
+          Builtins::kKeyedLoadIC_DebugBreak));
 #endif
 
   // Check the debug break code stubs for call ICs with different number of
@@ -1139,7 +1165,7 @@
   foo->Call(env->Global(), 0, NULL);
   CHECK_EQ(0, break_point_hit_count);
 
-  // Run with breakpoint
+  // Run with breakpoint.
   int bp = SetBreakPoint(foo, 0);
   foo->Call(env->Global(), 0, NULL);
   CHECK_EQ(1, break_point_hit_count);
@@ -1172,7 +1198,7 @@
   foo->Call(env->Global(), 0, NULL);
   CHECK_EQ(0, break_point_hit_count);
 
-  // Run with breakpoint.
+  // Run with breakpoint
   int bp = SetBreakPoint(foo, 0);
   foo->Call(env->Global(), 0, NULL);
   CHECK_EQ(1, break_point_hit_count);
@@ -1367,12 +1393,12 @@
     CHECK_EQ(1 + i * 3, break_point_hit_count);
 
     // Scavenge and call function.
-    Heap::CollectGarbage(v8::internal::NEW_SPACE);
+    HEAP->CollectGarbage(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(force_compaction);
+    HEAP->CollectAllGarbage(force_compaction);
     f->Call(recv, 0, NULL);
     CHECK_EQ(3 + i * 3, break_point_hit_count);
   }
@@ -2199,7 +2225,7 @@
   }
   f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
 
-  Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 
   SetScriptBreakPointByNameFromJS("test.html", 3, -1);
 
@@ -3698,7 +3724,7 @@
   DebugLocalContext env;
   env.ExposeDebug();
 
-  v8::internal::Top::TraceException(false);
+  v8::internal::Isolate::Current()->TraceException(false);
 
   // Create functions for testing break on exception.
   v8::Local<v8::Function> throws =
@@ -3845,7 +3871,7 @@
   // For this test, we want to break on uncaught exceptions:
   ChangeBreakOnException(false, true);
 
-  v8::internal::Top::TraceException(false);
+  v8::internal::Isolate::Current()->TraceException(false);
 
   // Create a function for checking the function when hitting a break point.
   frame_count = CompileFunction(&env, frame_count_source, "frame_count");
@@ -4694,6 +4720,8 @@
 // placing JSON debugger commands in the queue.
 class MessageQueueDebuggerThread : public v8::internal::Thread {
  public:
+  explicit MessageQueueDebuggerThread(v8::internal::Isolate* isolate)
+      : Thread(isolate, "MessageQueueDebuggerThread") { }
   void Run();
 };
 
@@ -4793,10 +4821,12 @@
   // 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) {
+  MessageQueueDebuggerThread message_queue_debugger_thread(
+      i::Isolate::Current());
+
   // Create a V8 environment
   v8::HandleScope scope;
   DebugLocalContext env;
@@ -4942,11 +4972,15 @@
 
 class V8Thread : public v8::internal::Thread {
  public:
+  explicit V8Thread(v8::internal::Isolate* isolate)
+      : Thread(isolate, "V8Thread") { }
   void Run();
 };
 
 class DebuggerThread : public v8::internal::Thread {
  public:
+  explicit DebuggerThread(v8::internal::Isolate* isolate)
+      : Thread(isolate, "DebuggerThread") { }
   void Run();
 };
 
@@ -5021,10 +5055,11 @@
   v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer));
 }
 
-DebuggerThread debugger_thread;
-V8Thread v8_thread;
 
 TEST(ThreadedDebugging) {
+  DebuggerThread debugger_thread(i::Isolate::Current());
+  V8Thread v8_thread(i::Isolate::Current());
+
   // Create a V8 environment
   threaded_debugging_barriers.Initialize();
 
@@ -5044,13 +5079,17 @@
 
 class BreakpointsV8Thread : public v8::internal::Thread {
  public:
+  explicit BreakpointsV8Thread(v8::internal::Isolate* isolate)
+      : Thread(isolate, "BreakpointsV8Thread") { }
   void Run();
 };
 
 class BreakpointsDebuggerThread : public v8::internal::Thread {
  public:
-  explicit BreakpointsDebuggerThread(bool global_evaluate)
-      : global_evaluate_(global_evaluate) {}
+  explicit BreakpointsDebuggerThread(v8::internal::Isolate* isolate,
+                                     bool global_evaluate)
+      : Thread(isolate, "BreakpointsDebuggerThread"),
+        global_evaluate_(global_evaluate) {}
   void Run();
 
  private:
@@ -5226,8 +5265,9 @@
 void TestRecursiveBreakpointsGeneric(bool global_evaluate) {
   i::FLAG_debugger_auto_break = true;
 
-  BreakpointsDebuggerThread breakpoints_debugger_thread(global_evaluate);
-  BreakpointsV8Thread breakpoints_v8_thread;
+  BreakpointsDebuggerThread breakpoints_debugger_thread(i::Isolate::Current(),
+      global_evaluate);
+  BreakpointsV8Thread breakpoints_v8_thread(i::Isolate::Current());
 
   // Create a V8 environment
   Barriers stack_allocated_breakpoints_barriers;
@@ -5609,11 +5649,15 @@
 
 class HostDispatchV8Thread : public v8::internal::Thread {
  public:
+  explicit HostDispatchV8Thread(v8::internal::Isolate* isolate)
+      : Thread(isolate, "HostDispatchV8Thread") { }
   void Run();
 };
 
 class HostDispatchDebuggerThread : public v8::internal::Thread {
  public:
+  explicit HostDispatchDebuggerThread(v8::internal::Isolate* isolate)
+      : Thread(isolate, "HostDispatchDebuggerThread") { }
   void Run();
 };
 
@@ -5683,11 +5727,11 @@
   v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer));
 }
 
-HostDispatchDebuggerThread host_dispatch_debugger_thread;
-HostDispatchV8Thread host_dispatch_v8_thread;
-
 
 TEST(DebuggerHostDispatch) {
+  HostDispatchDebuggerThread host_dispatch_debugger_thread(
+      i::Isolate::Current());
+  HostDispatchV8Thread host_dispatch_v8_thread(i::Isolate::Current());
   i::FLAG_debugger_auto_break = true;
 
   // Create a V8 environment
@@ -5711,11 +5755,15 @@
 
 class DebugMessageDispatchV8Thread : public v8::internal::Thread {
  public:
+  explicit DebugMessageDispatchV8Thread(v8::internal::Isolate* isolate)
+      : Thread(isolate, "DebugMessageDispatchV8Thread") { }
   void Run();
 };
 
 class DebugMessageDispatchDebuggerThread : public v8::internal::Thread {
  public:
+  explicit DebugMessageDispatchDebuggerThread(v8::internal::Isolate* isolate)
+      : Thread(isolate, "DebugMessageDispatchDebuggerThread") { }
   void Run();
 };
 
@@ -5747,11 +5795,13 @@
   debug_message_dispatch_barriers->barrier_2.Wait();
 }
 
-DebugMessageDispatchDebuggerThread debug_message_dispatch_debugger_thread;
-DebugMessageDispatchV8Thread debug_message_dispatch_v8_thread;
-
 
 TEST(DebuggerDebugMessageDispatch) {
+  DebugMessageDispatchDebuggerThread debug_message_dispatch_debugger_thread(
+      i::Isolate::Current());
+  DebugMessageDispatchV8Thread debug_message_dispatch_v8_thread(
+      i::Isolate::Current());
+
   i::FLAG_debugger_auto_break = true;
 
   // Create a V8 environment
@@ -5769,6 +5819,7 @@
 
 
 TEST(DebuggerAgent) {
+  i::Debugger* debugger = i::Isolate::Current()->debugger();
   // Make sure these ports is not used by other tests to allow tests to run in
   // parallel.
   const int kPort1 = 5858;
@@ -5786,18 +5837,18 @@
   i::Socket::Setup();
 
   // Test starting and stopping the agent without any client connection.
-  i::Debugger::StartAgent("test", kPort1);
-  i::Debugger::StopAgent();
+  debugger->StartAgent("test", kPort1);
+  debugger->StopAgent();
 
   // Test starting the agent, connecting a client and shutting down the agent
   // with the client connected.
-  ok = i::Debugger::StartAgent("test", kPort2);
+  ok = debugger->StartAgent("test", kPort2);
   CHECK(ok);
-  i::Debugger::WaitForAgent();
+  debugger->WaitForAgent();
   i::Socket* client = i::OS::CreateSocket();
   ok = client->Connect("localhost", port2_str);
   CHECK(ok);
-  i::Debugger::StopAgent();
+  debugger->StopAgent();
   delete client;
 
   // Test starting and stopping the agent with the required port already
@@ -5805,8 +5856,8 @@
   i::Socket* server = i::OS::CreateSocket();
   server->Bind(kPort3);
 
-  i::Debugger::StartAgent("test", kPort3);
-  i::Debugger::StopAgent();
+  debugger->StartAgent("test", kPort3);
+  debugger->StopAgent();
 
   delete server;
 }
@@ -5814,8 +5865,11 @@
 
 class DebuggerAgentProtocolServerThread : public i::Thread {
  public:
-  explicit DebuggerAgentProtocolServerThread(int port)
-      : port_(port), server_(NULL), client_(NULL),
+  explicit DebuggerAgentProtocolServerThread(i::Isolate* isolate, int port)
+      : Thread(isolate, "DebuggerAgentProtocolServerThread"),
+        port_(port),
+        server_(NULL),
+        client_(NULL),
         listening_(OS::CreateSemaphore(0)) {
   }
   ~DebuggerAgentProtocolServerThread() {
@@ -5877,7 +5931,7 @@
 
   // Create a socket server to receive a debugger agent message.
   DebuggerAgentProtocolServerThread* server =
-      new DebuggerAgentProtocolServerThread(kPort);
+      new DebuggerAgentProtocolServerThread(i::Isolate::Current(), kPort);
   server->Start();
   server->WaitForListening();
 
@@ -6376,17 +6430,18 @@
 
 // Test that scripts collected are reported through the debug event listener.
 TEST(ScriptCollectedEvent) {
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
   break_point_hit_count = 0;
   script_collected_count = 0;
   v8::HandleScope scope;
   DebugLocalContext env;
 
   // Request the loaded scripts to initialize the debugger script cache.
-  Debug::GetLoadedScripts();
+  debug->GetLoadedScripts();
 
   // Do garbage collection to ensure that only the script in this test will be
   // collected afterwards.
-  Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 
   script_collected_count = 0;
   v8::Debug::SetDebugEventListener(DebugEventScriptCollectedEvent,
@@ -6398,7 +6453,7 @@
 
   // Do garbage collection to collect the script above which is no longer
   // referenced.
-  Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 
   CHECK_EQ(2, script_collected_count);
 
@@ -6422,6 +6477,7 @@
 // Test that GetEventContext doesn't fail and return empty handle for
 // ScriptCollected events.
 TEST(ScriptCollectedEventContext) {
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
   script_collected_message_count = 0;
   v8::HandleScope scope;
 
@@ -6429,11 +6485,11 @@
     DebugLocalContext env;
 
     // Request the loaded scripts to initialize the debugger script cache.
-    Debug::GetLoadedScripts();
+    debug->GetLoadedScripts();
 
     // Do garbage collection to ensure that only the script in this test will be
     // collected afterwards.
-    Heap::CollectAllGarbage(false);
+    HEAP->CollectAllGarbage(false);
 
     v8::Debug::SetMessageHandler2(ScriptCollectedMessageHandler);
     {
@@ -6444,7 +6500,7 @@
 
   // Do garbage collection to collect the script above which is no longer
   // referenced.
-  Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 
   CHECK_EQ(2, script_collected_message_count);
 
@@ -6592,6 +6648,7 @@
 
 
 static void BreakMessageHandler(const v8::Debug::Message& message) {
+  i::Isolate* isolate = i::Isolate::Current();
   if (message.IsEvent() && message.GetEvent() == v8::Break) {
     // Count the number of breaks.
     break_point_hit_count++;
@@ -6603,18 +6660,18 @@
   } else if (message.IsEvent() && message.GetEvent() == v8::AfterCompile) {
     v8::HandleScope scope;
 
-    bool is_debug_break = i::StackGuard::IsDebugBreak();
+    bool is_debug_break = isolate->stack_guard()->IsDebugBreak();
     // Force DebugBreak flag while serializer is working.
-    i::StackGuard::DebugBreak();
+    isolate->stack_guard()->DebugBreak();
 
     // Force serialization to trigger some internal JS execution.
     v8::Handle<v8::String> json = message.GetJSON();
 
     // Restore previous state.
     if (is_debug_break) {
-      i::StackGuard::DebugBreak();
+      isolate->stack_guard()->DebugBreak();
     } else {
-      i::StackGuard::Continue(i::DEBUGBREAK);
+      isolate->stack_guard()->Continue(i::DEBUGBREAK);
     }
   }
 }
@@ -6843,6 +6900,7 @@
 
 
 TEST(CallingContextIsNotDebugContext) {
+  v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
   // Create and enter a debugee context.
   v8::HandleScope scope;
   DebugLocalContext env;
@@ -6851,7 +6909,7 @@
   // Save handles to the debugger and debugee contexts to be used in
   // NamedGetterWithCallingContextCheck.
   debugee_context = v8::Local<v8::Context>(*env);
-  debugger_context = v8::Utils::ToLocal(Debug::debug_context());
+  debugger_context = v8::Utils::ToLocal(debug->debug_context());
 
   // Create object with 'a' property accessor.
   v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New();
diff --git a/test/cctest/test-decls.cc b/test/cctest/test-decls.cc
index 6ea4c84..6198391 100644
--- a/test/cctest/test-decls.cc
+++ b/test/cctest/test-decls.cc
@@ -130,7 +130,7 @@
   InitializeIfNeeded();
   // A retry after a GC may pollute the counts, so perform gc now
   // to avoid that.
-  v8::internal::Heap::CollectGarbage(v8::internal::NEW_SPACE);
+  HEAP->CollectGarbage(v8::internal::NEW_SPACE);
   HandleScope scope;
   TryCatch catcher;
   catcher.SetVerbose(true);
diff --git a/test/cctest/test-deoptimization.cc b/test/cctest/test-deoptimization.cc
index 1745355..5ab84f9 100644
--- a/test/cctest/test-deoptimization.cc
+++ b/test/cctest/test-deoptimization.cc
@@ -30,20 +30,21 @@
 #include "v8.h"
 
 #include "api.h"
+#include "cctest.h"
 #include "compilation-cache.h"
 #include "debug.h"
 #include "deoptimizer.h"
+#include "isolate.h"
 #include "platform.h"
 #include "stub-cache.h"
-#include "cctest.h"
 
-
-using ::v8::internal::Handle;
-using ::v8::internal::Object;
-using ::v8::internal::JSFunction;
 using ::v8::internal::Deoptimizer;
 using ::v8::internal::EmbeddedVector;
+using ::v8::internal::Handle;
+using ::v8::internal::Isolate;
+using ::v8::internal::JSFunction;
 using ::v8::internal::OS;
+using ::v8::internal::Object;
 
 // Size of temp buffer for formatting small strings.
 #define SMALL_STRING_BUFFER_SIZE 80
@@ -124,7 +125,7 @@
 
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 
   // Test lazy deoptimization of a simple function. Call the function after the
   // deoptimization while it is still activated further down the stack.
@@ -140,7 +141,7 @@
 
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 }
 
 
@@ -164,7 +165,7 @@
 
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 
   // Test lazy deoptimization of a simple function with some arguments. Call the
   // function after the deoptimization while it is still activated further down
@@ -181,7 +182,7 @@
 
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 }
 
 
@@ -207,7 +208,7 @@
     CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
     CHECK_EQ(6, env->Global()->Get(v8_str("result"))->Int32Value());
     CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized());
-    CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+    CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
   }
 }
 
@@ -232,7 +233,7 @@
 
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK_EQ(11, env->Global()->Get(v8_str("calls"))->Int32Value());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 
   v8::Local<v8::Function> fun =
       v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
@@ -266,7 +267,7 @@
 
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK_EQ(14, env->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 }
 
 
@@ -289,7 +290,7 @@
 
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK(env->Global()->Get(v8_str("result"))->IsTrue());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 
   {
     AlwaysOptimizeAllowNativesSyntaxNoInlining options;
@@ -306,7 +307,7 @@
 
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK_EQ(3, env->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 }
 
 
@@ -337,7 +338,7 @@
 
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK_EQ(14, env->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 }
 
 
@@ -385,7 +386,7 @@
   CHECK(result->IsString());
   v8::String::AsciiValue ascii(result);
   CHECK_EQ("a+an X", *ascii);
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 }
 
 
@@ -444,7 +445,7 @@
 
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK_EQ(15, env->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 }
 
 
@@ -458,7 +459,7 @@
 
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK_EQ(-1, env->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 }
 
 
@@ -472,7 +473,7 @@
 
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK_EQ(56, env->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 }
 
 
@@ -486,7 +487,7 @@
 
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK_EQ(0, env->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 }
 
 
@@ -500,7 +501,7 @@
 
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK_EQ(7, env->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 }
 
 
@@ -545,7 +546,7 @@
   CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized());
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK_EQ(true, env->Global()->Get(v8_str("result"))->BooleanValue());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 }
 
 
@@ -627,7 +628,7 @@
   CHECK(!GetJSFunction(env->Global(), "g2")->IsOptimized());
   CHECK_EQ(4, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK_EQ(13, env->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 }
 
 
@@ -710,5 +711,5 @@
   CHECK(!GetJSFunction(env->Global(), "g2")->IsOptimized());
   CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
   CHECK_EQ(13, env->Global()->Get(v8_str("result"))->Int32Value());
-  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount());
+  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
 }
diff --git a/test/cctest/test-disasm-arm.cc b/test/cctest/test-disasm-arm.cc
index dea0db9..3221614 100644
--- a/test/cctest/test-disasm-arm.cc
+++ b/test/cctest/test-disasm-arm.cc
@@ -270,7 +270,7 @@
           "13a06000       movne r6, #0");
 
   // mov -> movw.
-  if (CpuFeatures::IsSupported(ARMv7)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(ARMv7)) {
     COMPARE(mov(r5, Operand(0x01234), LeaveCC, ne),
             "13015234       movwne r5, #4660");
     // We only disassemble one instruction so the eor instruction is not here.
@@ -360,7 +360,7 @@
 TEST(Type3) {
   SETUP();
 
-  if (CpuFeatures::IsSupported(ARMv7)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(ARMv7)) {
     COMPARE(ubfx(r0, r1, 5, 10),
             "e7e902d1       ubfx r0, r1, #5, #10");
     COMPARE(ubfx(r1, r0, 5, 10),
@@ -415,7 +415,7 @@
 TEST(Vfp) {
   SETUP();
 
-  if (CpuFeatures::IsSupported(VFP3)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
     COMPARE(vmov(d0, d1),
             "eeb00b41       vmov.f64 d0, d1");
@@ -440,6 +440,11 @@
     COMPARE(vabs(d3, d4, mi),
             "4eb03bc4       vabsmi d3, d4");
 
+    COMPARE(vneg(d0, d1),
+            "eeb10b41       vneg d0, d1");
+    COMPARE(vneg(d3, d4, mi),
+            "4eb13b44       vnegmi d3, d4");
+
     COMPARE(vadd(d0, d1, d2),
             "ee310b02       vadd.f64 d0, d1, d2");
     COMPARE(vadd(d3, d4, d5, mi),
diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index c995aa8..26da5c9 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -68,7 +68,7 @@
   __ sub(Operand(eax), Immediate(12345678));
   __ xor_(eax, 12345678);
   __ and_(eax, 12345678);
-  Handle<FixedArray> foo = Factory::NewFixedArray(10, TENURED);
+  Handle<FixedArray> foo = FACTORY->NewFixedArray(10, TENURED);
   __ cmp(eax, foo);
 
   // ---- This one caused crash
@@ -99,7 +99,7 @@
   __ cmp(edx, 3);
   __ cmp(edx, Operand(esp, 4));
   __ cmp(Operand(ebp, ecx, times_4, 0), Immediate(1000));
-  Handle<FixedArray> foo2 = Factory::NewFixedArray(10, TENURED);
+  Handle<FixedArray> foo2 = FACTORY->NewFixedArray(10, TENURED);
   __ cmp(ebx, foo2);
   __ cmpb(ebx, Operand(ebp, ecx, times_2, 0));
   __ cmpb(Operand(ebp, ecx, times_2, 0), ebx);
@@ -107,12 +107,12 @@
   __ xor_(edx, 3);
   __ nop();
   {
-    CHECK(CpuFeatures::IsSupported(CPUID));
+    CHECK(Isolate::Current()->cpu_features()->IsSupported(CPUID));
     CpuFeatures::Scope fscope(CPUID);
     __ cpuid();
   }
   {
-    CHECK(CpuFeatures::IsSupported(RDTSC));
+    CHECK(Isolate::Current()->cpu_features()->IsSupported(RDTSC));
     CpuFeatures::Scope fscope(RDTSC);
     __ rdtsc();
   }
@@ -272,7 +272,8 @@
   __ bind(&L2);
   __ call(Operand(ebx, ecx, times_4, 10000));
   __ nop();
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      Builtins::kLoadIC_Initialize));
   __ call(ic, RelocInfo::CODE_TARGET);
   __ nop();
   __ call(FUNCTION_ADDR(DummyStaticFunction), RelocInfo::RUNTIME_ENTRY);
@@ -282,7 +283,8 @@
   __ jmp(Operand(ebx, ecx, times_4, 10000));
 #ifdef ENABLE_DEBUGGER_SUPPORT
   ExternalReference after_break_target =
-      ExternalReference(Debug_Address::AfterBreakTarget());
+      ExternalReference(Debug_Address::AfterBreakTarget(),
+                        assm.isolate());
   __ jmp(Operand::StaticVariable(after_break_target));
 #endif  // ENABLE_DEBUGGER_SUPPORT
   __ jmp(ic, RelocInfo::CODE_TARGET);
@@ -332,7 +334,7 @@
   __ j(zero, &Ljcc, taken);
   __ j(zero, &Ljcc, not_taken);
 
-  // __ mov(Operand::StaticVariable(Top::handler_address()), eax);
+  // __ mov(Operand::StaticVariable(Isolate::handler_address()), eax);
   // 0xD9 instructions
   __ nop();
 
@@ -373,7 +375,7 @@
   __ fwait();
   __ nop();
   {
-    if (CpuFeatures::IsSupported(SSE2)) {
+    if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
       CpuFeatures::Scope fscope(SSE2);
       __ cvttss2si(edx, Operand(ebx, ecx, times_4, 10000));
       __ cvtsi2sd(xmm1, Operand(ebx, ecx, times_4, 10000));
@@ -395,7 +397,7 @@
 
   // cmov.
   {
-    if (CpuFeatures::IsSupported(CMOV)) {
+    if (Isolate::Current()->cpu_features()->IsSupported(CMOV)) {
       CpuFeatures::Scope use_cmov(CMOV);
       __ cmov(overflow, eax, Operand(eax, 0));
       __ cmov(no_overflow, eax, Operand(eax, 1));
@@ -418,7 +420,7 @@
 
   // andpd, cmpltsd, movaps, psllq, psrlq, por.
   {
-    if (CpuFeatures::IsSupported(SSE2)) {
+    if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) {
       CpuFeatures::Scope fscope(SSE2);
       __ andpd(xmm0, xmm1);
       __ andpd(xmm1, xmm2);
@@ -447,7 +449,7 @@
   }
 
   {
-    if (CpuFeatures::IsSupported(SSE4_1)) {
+    if (Isolate::Current()->cpu_features()->IsSupported(SSE4_1)) {
       CpuFeatures::Scope scope(SSE4_1);
       __ pextrd(Operand(eax), xmm0, 1);
       __ pinsrd(xmm1, Operand(eax), 0);
@@ -458,10 +460,10 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Object* code = Heap::CreateCode(
+  Object* code = HEAP->CreateCode(
       desc,
       Code::ComputeFlags(Code::STUB),
-      Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
   CHECK(code->IsCode());
 #ifdef OBJECT_PRINT
   Code::cast(code)->Print();
diff --git a/test/cctest/test-func-name-inference.cc b/test/cctest/test-func-name-inference.cc
index 563cc4b..dea5c47 100644
--- a/test/cctest/test-func-name-inference.cc
+++ b/test/cctest/test-func-name-inference.cc
@@ -36,6 +36,7 @@
 using ::v8::internal::Factory;
 using ::v8::internal::Handle;
 using ::v8::internal::Heap;
+using ::v8::internal::Isolate;
 using ::v8::internal::JSFunction;
 using ::v8::internal::Object;
 using ::v8::internal::Runtime;
@@ -77,15 +78,20 @@
 
   // Find the position of a given func source substring in the source.
   Handle<String> func_pos_str =
-      Factory::NewStringFromAscii(CStrVector(func_pos_src));
-  int func_pos = Runtime::StringMatch(script_src, func_pos_str, 0);
+      FACTORY->NewStringFromAscii(CStrVector(func_pos_src));
+  int func_pos = Runtime::StringMatch(Isolate::Current(),
+                                      script_src,
+                                      func_pos_str,
+                                      0);
   CHECK_NE(0, func_pos);
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Obtain SharedFunctionInfo for the function.
   Object* shared_func_info_ptr =
-      Runtime::FindSharedFunctionInfoInScript(i_script, func_pos);
-  CHECK(shared_func_info_ptr != Heap::undefined_value());
+      Runtime::FindSharedFunctionInfoInScript(Isolate::Current(),
+                                              i_script,
+                                              func_pos);
+  CHECK(shared_func_info_ptr != HEAP->undefined_value());
   Handle<SharedFunctionInfo> shared_func_info(
       SharedFunctionInfo::cast(shared_func_info_ptr));
 
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index ad242fe..141b42f 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -26,7 +26,7 @@
  public:
   ConstructorHeapProfileTestHelper()
     : i::ConstructorHeapProfile(),
-      f_name_(i::Factory::NewStringFromAscii(i::CStrVector("F"))),
+      f_name_(FACTORY->NewStringFromAscii(i::CStrVector("F"))),
       f_count_(0) {
   }
 
@@ -143,25 +143,25 @@
   i::ZoneScope zn_scope(i::DELETE_ON_EXIT);
 
   JSObjectsRetainerTree tree;
-  JSObjectsCluster function(i::Heap::function_class_symbol());
-  JSObjectsCluster a(*i::Factory::NewStringFromAscii(i::CStrVector("A")));
-  JSObjectsCluster b(*i::Factory::NewStringFromAscii(i::CStrVector("B")));
+  JSObjectsCluster function(HEAP->function_class_symbol());
+  JSObjectsCluster a(*FACTORY->NewStringFromAscii(i::CStrVector("A")));
+  JSObjectsCluster b(*FACTORY->NewStringFromAscii(i::CStrVector("B")));
 
   // o1 <- Function
   JSObjectsCluster o1 =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100, &function);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x100, &function);
   // o2 <- Function
   JSObjectsCluster o2 =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x200, &function);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x200, &function);
   // o3 <- A, B
   JSObjectsCluster o3 =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x300, &a, &b);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x300, &a, &b);
   // o4 <- B, A
   JSObjectsCluster o4 =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x400, &b, &a);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x400, &b, &a);
   // o5 <- A, B, Function
   JSObjectsCluster o5 =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x500,
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x500,
                           &a, &b, &function);
 
   ClustersCoarser coarser;
@@ -181,20 +181,20 @@
   i::ZoneScope zn_scope(i::DELETE_ON_EXIT);
 
   JSObjectsRetainerTree tree;
-  JSObjectsCluster function(i::Heap::function_class_symbol());
+  JSObjectsCluster function(HEAP->function_class_symbol());
 
   // o1 <- Function
   JSObjectsCluster o1 =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100, &function);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x100, &function);
   // a1 <- Function
   JSObjectsCluster a1 =
-      AddHeapObjectToTree(&tree, i::Heap::Array_symbol(), 0x1000, &function);
+      AddHeapObjectToTree(&tree, HEAP->Array_symbol(), 0x1000, &function);
   // o2 <- Function
   JSObjectsCluster o2 =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x200, &function);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x200, &function);
   // a2 <- Function
   JSObjectsCluster a2 =
-      AddHeapObjectToTree(&tree, i::Heap::Array_symbol(), 0x2000, &function);
+      AddHeapObjectToTree(&tree, HEAP->Array_symbol(), 0x2000, &function);
 
   ClustersCoarser coarser;
   coarser.Process(&tree);
@@ -224,21 +224,21 @@
   // o21 ~ o22, and o11 ~ o12.
 
   JSObjectsCluster o =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x100);
   JSObjectsCluster o11 =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x110, &o);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x110, &o);
   JSObjectsCluster o12 =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x120, &o);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x120, &o);
   JSObjectsCluster o21 =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x210, &o11);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x210, &o11);
   JSObjectsCluster o22 =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x220, &o12);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x220, &o12);
   JSObjectsCluster p =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x300, &o21);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x300, &o21);
   JSObjectsCluster q =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x310, &o21, &o22);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x310, &o21, &o22);
   JSObjectsCluster r =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x320, &o22);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x320, &o22);
 
   ClustersCoarser coarser;
   coarser.Process(&tree);
@@ -275,19 +275,19 @@
   // we expect that coarser will deduce equivalences: p ~ q ~ r, o1 ~ o2;
 
   JSObjectsCluster o =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x100);
   JSObjectsCluster o1 =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x110, &o);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x110, &o);
   JSObjectsCluster o2 =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x120, &o);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x120, &o);
   JSObjectsCluster p =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x300, &o1);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x300, &o1);
   AddSelfReferenceToTree(&tree, &p);
   JSObjectsCluster q =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x310, &o1, &o2);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x310, &o1, &o2);
   AddSelfReferenceToTree(&tree, &q);
   JSObjectsCluster r =
-      AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x320, &o2);
+      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x320, &o2);
   AddSelfReferenceToTree(&tree, &r);
 
   ClustersCoarser coarser;
@@ -433,19 +433,6 @@
 }
 
 
-static bool IsNodeRetainedAs(const v8::HeapGraphNode* node,
-                             v8::HeapGraphEdge::Type type,
-                             const char* name) {
-  for (int i = 0, count = node->GetRetainersCount(); i < count; ++i) {
-    const v8::HeapGraphEdge* prop = node->GetRetainer(i);
-    v8::String::AsciiValue prop_name(prop->GetName());
-    if (prop->GetType() == type && strcmp(name, *prop_name) == 0)
-      return true;
-  }
-  return false;
-}
-
-
 static bool HasString(const v8::HeapGraphNode* node, const char* contents) {
   for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
     const v8::HeapGraphEdge* prop = node->GetChild(i);
@@ -496,56 +483,6 @@
   CHECK(det.has_A2);
   CHECK(det.has_B2);
   CHECK(det.has_C2);
-
-  /*
-    // Currently disabled. Too many retaining paths emerge, need to
-    // reduce the amount.
-
-  // Verify 'a2' object retainers. They are:
-  //  - (global object).a2
-  //  - c2.x1, c2.x2, c2[1]
-  //  - b2_1 and b2_2 closures: via 'x' variable
-  CHECK_EQ(6, a2_node->GetRetainingPathsCount());
-  bool has_global_obj_a2_ref = false;
-  bool has_c2_x1_ref = false, has_c2_x2_ref = false, has_c2_1_ref = false;
-  bool has_b2_1_x_ref = false, has_b2_2_x_ref = false;
-  for (int i = 0; i < a2_node->GetRetainingPathsCount(); ++i) {
-    const v8::HeapGraphPath* path = a2_node->GetRetainingPath(i);
-    const int edges_count = path->GetEdgesCount();
-    CHECK_GT(edges_count, 0);
-    const v8::HeapGraphEdge* last_edge = path->GetEdge(edges_count - 1);
-    v8::String::AsciiValue last_edge_name(last_edge->GetName());
-    if (strcmp("a2", *last_edge_name) == 0
-        && last_edge->GetType() == v8::HeapGraphEdge::kProperty) {
-      has_global_obj_a2_ref = true;
-      continue;
-    }
-    CHECK_GT(edges_count, 1);
-    const v8::HeapGraphEdge* prev_edge = path->GetEdge(edges_count - 2);
-    v8::String::AsciiValue prev_edge_name(prev_edge->GetName());
-    if (strcmp("x1", *last_edge_name) == 0
-        && last_edge->GetType() == v8::HeapGraphEdge::kProperty
-        && strcmp("c2", *prev_edge_name) == 0) has_c2_x1_ref = true;
-    if (strcmp("x2", *last_edge_name) == 0
-        && last_edge->GetType() == v8::HeapGraphEdge::kProperty
-        && strcmp("c2", *prev_edge_name) == 0) has_c2_x2_ref = true;
-    if (strcmp("1", *last_edge_name) == 0
-        && last_edge->GetType() == v8::HeapGraphEdge::kElement
-        && strcmp("c2", *prev_edge_name) == 0) has_c2_1_ref = true;
-    if (strcmp("x", *last_edge_name) == 0
-        && last_edge->GetType() == v8::HeapGraphEdge::kContextVariable
-        && strcmp("b2_1", *prev_edge_name) == 0) has_b2_1_x_ref = true;
-    if (strcmp("x", *last_edge_name) == 0
-        && last_edge->GetType() == v8::HeapGraphEdge::kContextVariable
-        && strcmp("b2_2", *prev_edge_name) == 0) has_b2_2_x_ref = true;
-  }
-  CHECK(has_global_obj_a2_ref);
-  CHECK(has_c2_x1_ref);
-  CHECK(has_c2_x2_ref);
-  CHECK(has_c2_1_ref);
-  CHECK(has_b2_1_x_ref);
-  CHECK(has_b2_2_x_ref);
-  */
 }
 
 
@@ -730,7 +667,7 @@
   const v8::HeapSnapshot* snapshot1 =
       v8::HeapProfiler::TakeSnapshot(v8::String::New("s1"));
 
-  i::Heap::CollectAllGarbage(true);  // Enforce compaction.
+  HEAP->CollectAllGarbage(true);  // Enforce compaction.
 
   const v8::HeapSnapshot* snapshot2 =
       v8::HeapProfiler::TakeSnapshot(v8::String::New("s2"));
@@ -774,76 +711,6 @@
 }
 
 
-TEST(HeapSnapshotsDiff) {
-  v8::HandleScope scope;
-  LocalContext env;
-
-  CompileRun(
-      "function A() {}\n"
-      "function B(x) { this.x = x; }\n"
-      "function A2(a) { for (var i = 0; i < a; ++i) this[i] = i; }\n"
-      "var a = new A();\n"
-      "var b = new B(a);");
-  const v8::HeapSnapshot* snapshot1 =
-      v8::HeapProfiler::TakeSnapshot(v8::String::New("s1"));
-
-  CompileRun(
-      "delete a;\n"
-      "b.x = null;\n"
-      "var a = new A2(20);\n"
-      "var b2 = new B(a);");
-  const v8::HeapSnapshot* snapshot2 =
-      v8::HeapProfiler::TakeSnapshot(v8::String::New("s2"));
-
-  const v8::HeapSnapshotsDiff* diff = snapshot1->CompareWith(snapshot2);
-
-  // Verify additions: ensure that addition of A and B was detected.
-  const v8::HeapGraphNode* additions_root = diff->GetAdditionsRoot();
-  bool found_A = false, found_B = false;
-  uint64_t s1_A_id = 0;
-  for (int i = 0, count = additions_root->GetChildrenCount(); i < count; ++i) {
-    const v8::HeapGraphEdge* prop = additions_root->GetChild(i);
-    const v8::HeapGraphNode* node = prop->GetToNode();
-    if (node->GetType() == v8::HeapGraphNode::kObject) {
-      v8::String::AsciiValue node_name(node->GetName());
-      if (strcmp(*node_name, "A2") == 0) {
-        CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "a"));
-        CHECK(!found_A);
-        found_A = true;
-        s1_A_id = node->GetId();
-      } else if (strcmp(*node_name, "B") == 0) {
-        CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "b2"));
-        CHECK(!found_B);
-        found_B = true;
-      }
-    }
-  }
-  CHECK(found_A);
-  CHECK(found_B);
-
-  // Verify deletions: ensure that deletion of A was detected.
-  const v8::HeapGraphNode* deletions_root = diff->GetDeletionsRoot();
-  bool found_A_del = false;
-  uint64_t s2_A_id = 0;
-  for (int i = 0, count = deletions_root->GetChildrenCount(); i < count; ++i) {
-    const v8::HeapGraphEdge* prop = deletions_root->GetChild(i);
-    const v8::HeapGraphNode* node = prop->GetToNode();
-    if (node->GetType() == v8::HeapGraphNode::kObject) {
-      v8::String::AsciiValue node_name(node->GetName());
-      if (strcmp(*node_name, "A") == 0) {
-        CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "a"));
-        CHECK(!found_A_del);
-        found_A_del = true;
-        s2_A_id = node->GetId();
-      }
-    }
-  }
-  CHECK(found_A_del);
-  CHECK_NE_UINT64_T(0, s1_A_id);
-  CHECK(s1_A_id != s2_A_id);
-}
-
-
 TEST(HeapSnapshotRootPreservedAfterSorting) {
   v8::HandleScope scope;
   LocalContext env;
@@ -1258,4 +1125,199 @@
   CHECK_GT(control.total(), 0);
 }
 
+
+namespace {
+
+class TestRetainedObjectInfo : public v8::RetainedObjectInfo {
+ public:
+  TestRetainedObjectInfo(int hash,
+                         const char* label,
+                         intptr_t element_count = -1,
+                         intptr_t size = -1)
+      : disposed_(false),
+        hash_(hash),
+        label_(label),
+        element_count_(element_count),
+        size_(size) {
+    instances.Add(this);
+  }
+  virtual ~TestRetainedObjectInfo() {}
+  virtual void Dispose() {
+    CHECK(!disposed_);
+    disposed_ = true;
+  }
+  virtual bool IsEquivalent(RetainedObjectInfo* other) {
+    return GetHash() == other->GetHash();
+  }
+  virtual intptr_t GetHash() { return hash_; }
+  virtual const char* GetLabel() { return label_; }
+  virtual intptr_t GetElementCount() { return element_count_; }
+  virtual intptr_t GetSizeInBytes() { return size_; }
+  bool disposed() { return disposed_; }
+
+  static v8::RetainedObjectInfo* WrapperInfoCallback(
+      uint16_t class_id, v8::Handle<v8::Value> wrapper) {
+    if (class_id == 1) {
+      if (wrapper->IsString()) {
+        v8::String::AsciiValue ascii(wrapper);
+        if (strcmp(*ascii, "AAA") == 0)
+          return new TestRetainedObjectInfo(1, "aaa", 100);
+        else if (strcmp(*ascii, "BBB") == 0)
+          return new TestRetainedObjectInfo(1, "aaa", 100);
+      }
+    } else if (class_id == 2) {
+      if (wrapper->IsString()) {
+        v8::String::AsciiValue ascii(wrapper);
+        if (strcmp(*ascii, "CCC") == 0)
+          return new TestRetainedObjectInfo(2, "ccc");
+      }
+    }
+    CHECK(false);
+    return NULL;
+  }
+
+  static i::List<TestRetainedObjectInfo*> instances;
+
+ private:
+  bool disposed_;
+  int category_;
+  int hash_;
+  const char* label_;
+  intptr_t element_count_;
+  intptr_t size_;
+};
+
+
+i::List<TestRetainedObjectInfo*> TestRetainedObjectInfo::instances;
+}
+
+
+static const v8::HeapGraphNode* GetNode(const v8::HeapGraphNode* parent,
+                                        v8::HeapGraphNode::Type type,
+                                        const char* name) {
+  for (int i = 0, count = parent->GetChildrenCount(); i < count; ++i) {
+    const v8::HeapGraphNode* node = parent->GetChild(i)->GetToNode();
+    if (node->GetType() == type && strcmp(name,
+               const_cast<i::HeapEntry*>(
+                   reinterpret_cast<const i::HeapEntry*>(node))->name()) == 0) {
+      return node;
+    }
+  }
+  return NULL;
+}
+
+
+TEST(HeapSnapshotRetainedObjectInfo) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  v8::HeapProfiler::DefineWrapperClass(
+      1, TestRetainedObjectInfo::WrapperInfoCallback);
+  v8::HeapProfiler::DefineWrapperClass(
+      2, TestRetainedObjectInfo::WrapperInfoCallback);
+  v8::Persistent<v8::String> p_AAA =
+      v8::Persistent<v8::String>::New(v8_str("AAA"));
+  p_AAA.SetWrapperClassId(1);
+  v8::Persistent<v8::String> p_BBB =
+      v8::Persistent<v8::String>::New(v8_str("BBB"));
+  p_BBB.SetWrapperClassId(1);
+  v8::Persistent<v8::String> p_CCC =
+      v8::Persistent<v8::String>::New(v8_str("CCC"));
+  p_CCC.SetWrapperClassId(2);
+  CHECK_EQ(0, TestRetainedObjectInfo::instances.length());
+  const v8::HeapSnapshot* snapshot =
+      v8::HeapProfiler::TakeSnapshot(v8::String::New("retained"));
+
+  CHECK_EQ(3, TestRetainedObjectInfo::instances.length());
+  for (int i = 0; i < TestRetainedObjectInfo::instances.length(); ++i) {
+    CHECK(TestRetainedObjectInfo::instances[i]->disposed());
+    delete TestRetainedObjectInfo::instances[i];
+  }
+
+  const v8::HeapGraphNode* natives = GetNode(
+      snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(Native objects)");
+  CHECK_NE(NULL, natives);
+  CHECK_EQ(2, natives->GetChildrenCount());
+  const v8::HeapGraphNode* aaa = GetNode(
+      natives, v8::HeapGraphNode::kNative, "aaa / 100 entries");
+  CHECK_NE(NULL, aaa);
+  const v8::HeapGraphNode* ccc = GetNode(
+      natives, v8::HeapGraphNode::kNative, "ccc");
+  CHECK_NE(NULL, ccc);
+
+  CHECK_EQ(2, aaa->GetChildrenCount());
+  const v8::HeapGraphNode* n_AAA = GetNode(
+      aaa, v8::HeapGraphNode::kString, "AAA");
+  CHECK_NE(NULL, n_AAA);
+  const v8::HeapGraphNode* n_BBB = GetNode(
+      aaa, v8::HeapGraphNode::kString, "BBB");
+  CHECK_NE(NULL, n_BBB);
+  CHECK_EQ(1, ccc->GetChildrenCount());
+  const v8::HeapGraphNode* n_CCC = GetNode(
+      ccc, v8::HeapGraphNode::kString, "CCC");
+  CHECK_NE(NULL, n_CCC);
+
+  CHECK_EQ(aaa, GetProperty(n_AAA, v8::HeapGraphEdge::kInternal, "Native"));
+  CHECK_EQ(aaa, GetProperty(n_BBB, v8::HeapGraphEdge::kInternal, "Native"));
+  CHECK_EQ(ccc, GetProperty(n_CCC, v8::HeapGraphEdge::kInternal, "Native"));
+}
+
+
+TEST(DeleteAllHeapSnapshots) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
+  v8::HeapProfiler::DeleteAllSnapshots();
+  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
+  CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8::String::New("1")));
+  CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
+  v8::HeapProfiler::DeleteAllSnapshots();
+  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
+  CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8::String::New("1")));
+  CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8::String::New("2")));
+  CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount());
+  v8::HeapProfiler::DeleteAllSnapshots();
+  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
+}
+
+
+TEST(DeleteHeapSnapshot) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
+  const v8::HeapSnapshot* s1 =
+      v8::HeapProfiler::TakeSnapshot(v8::String::New("1"));
+  CHECK_NE(NULL, s1);
+  CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
+  unsigned uid1 = s1->GetUid();
+  CHECK_EQ(s1, v8::HeapProfiler::FindSnapshot(uid1));
+  const_cast<v8::HeapSnapshot*>(s1)->Delete();
+  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
+  CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid1));
+
+  const v8::HeapSnapshot* s2 =
+      v8::HeapProfiler::TakeSnapshot(v8::String::New("2"));
+  CHECK_NE(NULL, s2);
+  CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
+  unsigned uid2 = s2->GetUid();
+  CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
+  CHECK_EQ(s2, v8::HeapProfiler::FindSnapshot(uid2));
+  const v8::HeapSnapshot* s3 =
+      v8::HeapProfiler::TakeSnapshot(v8::String::New("3"));
+  CHECK_NE(NULL, s3);
+  CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount());
+  unsigned uid3 = s3->GetUid();
+  CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
+  CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3));
+  const_cast<v8::HeapSnapshot*>(s2)->Delete();
+  CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
+  CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid2));
+  CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3));
+  const_cast<v8::HeapSnapshot*>(s3)->Delete();
+  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
+  CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid3));
+}
+
 #endif  // ENABLE_LOGGING_AND_PROFILING
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index 4cc7f8b..86860ce 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -24,9 +24,9 @@
 static void CheckMap(Map* map, int type, int instance_size) {
   CHECK(map->IsHeapObject());
 #ifdef DEBUG
-  CHECK(Heap::Contains(map));
+  CHECK(HEAP->Contains(map));
 #endif
-  CHECK_EQ(Heap::meta_map(), map->map());
+  CHECK_EQ(HEAP->meta_map(), map->map());
   CHECK_EQ(type, map->instance_type());
   CHECK_EQ(instance_size, map->instance_size());
 }
@@ -34,10 +34,10 @@
 
 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, kVariableSizeSentinel);
-  CheckMap(Heap::string_map(), STRING_TYPE, kVariableSizeSentinel);
+  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, kVariableSizeSentinel);
+  CheckMap(HEAP->string_map(), STRING_TYPE, kVariableSizeSentinel);
 }
 
 
@@ -58,7 +58,7 @@
 
 
 static void CheckNumber(double value, const char* string) {
-  Object* obj = Heap::NumberFromDouble(value)->ToObjectChecked();
+  Object* obj = HEAP->NumberFromDouble(value)->ToObjectChecked();
   CHECK(obj->IsNumber());
   bool exc;
   Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
@@ -76,27 +76,27 @@
 
   CodeDesc desc;
   assm.GetCode(&desc);
-  Object* code = Heap::CreateCode(
+  Object* code = HEAP->CreateCode(
       desc,
       Code::ComputeFlags(Code::STUB),
-      Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
   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);
+    Object* found = HEAP->FindCodeObject(obj_addr + i);
     CHECK_EQ(code, found);
   }
 
-  Object* copy = Heap::CreateCode(
+  Object* copy = HEAP->CreateCode(
       desc,
       Code::ComputeFlags(Code::STUB),
-      Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
   CHECK(copy->IsCode());
   HeapObject* obj_copy = HeapObject::cast(copy);
-  Object* not_right = Heap::FindCodeObject(obj_copy->address() +
+  Object* not_right = HEAP->FindCodeObject(obj_copy->address() +
                                            obj_copy->Size() / 2);
   CHECK(not_right != code);
 }
@@ -106,41 +106,41 @@
   InitializeVM();
 
   v8::HandleScope sc;
-  Object* value = Heap::NumberFromDouble(1.000123)->ToObjectChecked();
+  Object* value = HEAP->NumberFromDouble(1.000123)->ToObjectChecked();
   CHECK(value->IsHeapNumber());
   CHECK(value->IsNumber());
   CHECK_EQ(1.000123, value->Number());
 
-  value = Heap::NumberFromDouble(1.0)->ToObjectChecked();
+  value = HEAP->NumberFromDouble(1.0)->ToObjectChecked();
   CHECK(value->IsSmi());
   CHECK(value->IsNumber());
   CHECK_EQ(1.0, value->Number());
 
-  value = Heap::NumberFromInt32(1024)->ToObjectChecked();
+  value = HEAP->NumberFromInt32(1024)->ToObjectChecked();
   CHECK(value->IsSmi());
   CHECK(value->IsNumber());
   CHECK_EQ(1024.0, value->Number());
 
-  value = Heap::NumberFromInt32(Smi::kMinValue)->ToObjectChecked();
+  value = HEAP->NumberFromInt32(Smi::kMinValue)->ToObjectChecked();
   CHECK(value->IsSmi());
   CHECK(value->IsNumber());
   CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value());
 
-  value = Heap::NumberFromInt32(Smi::kMaxValue)->ToObjectChecked();
+  value = HEAP->NumberFromInt32(Smi::kMaxValue)->ToObjectChecked();
   CHECK(value->IsSmi());
   CHECK(value->IsNumber());
   CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value());
 
 #ifndef V8_TARGET_ARCH_X64
   // TODO(lrn): We need a NumberFromIntptr function in order to test this.
-  value = Heap::NumberFromInt32(Smi::kMinValue - 1)->ToObjectChecked();
+  value = HEAP->NumberFromInt32(Smi::kMinValue - 1)->ToObjectChecked();
   CHECK(value->IsHeapNumber());
   CHECK(value->IsNumber());
   CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number());
 #endif
 
   MaybeObject* maybe_value =
-      Heap::NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1);
+      HEAP->NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1);
   value = maybe_value->ToObjectChecked();
   CHECK(value->IsHeapNumber());
   CHECK(value->IsNumber());
@@ -148,21 +148,22 @@
            value->Number());
 
   // nan oddball checks
-  CHECK(Heap::nan_value()->IsNumber());
-  CHECK(isnan(Heap::nan_value()->Number()));
+  CHECK(HEAP->nan_value()->IsNumber());
+  CHECK(isnan(HEAP->nan_value()->Number()));
 
-  Handle<String> s = Factory::NewStringFromAscii(CStrVector("fisk hest "));
+  Handle<String> s = FACTORY->NewStringFromAscii(CStrVector("fisk hest "));
   CHECK(s->IsString());
   CHECK_EQ(10, s->length());
 
-  String* object_symbol = String::cast(Heap::Object_symbol());
-  CHECK(Top::context()->global()->HasLocalProperty(object_symbol));
+  String* object_symbol = String::cast(HEAP->Object_symbol());
+  CHECK(
+      Isolate::Current()->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");
+  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");
@@ -197,25 +198,25 @@
 
   v8::HandleScope sc;
   // Check GC.
-  Heap::CollectGarbage(NEW_SPACE);
+  HEAP->CollectGarbage(NEW_SPACE);
 
-  Handle<String> name = Factory::LookupAsciiSymbol("theFunction");
-  Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot");
-  Handle<String> prop_namex = Factory::LookupAsciiSymbol("theSlotx");
-  Handle<String> obj_name = Factory::LookupAsciiSymbol("theObject");
+  Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction");
+  Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot");
+  Handle<String> prop_namex = FACTORY->LookupAsciiSymbol("theSlotx");
+  Handle<String> obj_name = FACTORY->LookupAsciiSymbol("theObject");
 
   {
     v8::HandleScope inner_scope;
     // Allocate a function and keep it in global object's property.
     Handle<JSFunction> function =
-        Factory::NewFunction(name, Factory::undefined_value());
+        FACTORY->NewFunction(name, FACTORY->undefined_value());
     Handle<Map> initial_map =
-        Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+        FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     function->set_initial_map(*initial_map);
-    Top::context()->global()->SetProperty(
+    Isolate::Current()->context()->global()->SetProperty(
         *name, *function, NONE, kNonStrictMode)->ToObjectChecked();
     // Allocate an object.  Unrooted after leaving the scope.
-    Handle<JSObject> obj = Factory::NewJSObject(function);
+    Handle<JSObject> obj = FACTORY->NewJSObject(function);
     obj->SetProperty(
         *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
     obj->SetProperty(
@@ -225,34 +226,34 @@
     CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex));
   }
 
-  Heap::CollectGarbage(NEW_SPACE);
+  HEAP->CollectGarbage(NEW_SPACE);
 
   // Function should be alive.
-  CHECK(Top::context()->global()->HasLocalProperty(*name));
+  CHECK(Isolate::Current()->context()->global()->HasLocalProperty(*name));
   // Check function is retained.
-  Object* func_value =
-      Top::context()->global()->GetProperty(*name)->ToObjectChecked();
+  Object* func_value = Isolate::Current()->context()->global()->
+      GetProperty(*name)->ToObjectChecked();
   CHECK(func_value->IsJSFunction());
   Handle<JSFunction> function(JSFunction::cast(func_value));
 
   {
     HandleScope inner_scope;
     // Allocate another object, make it reachable from global.
-    Handle<JSObject> obj = Factory::NewJSObject(function);
-    Top::context()->global()->SetProperty(
+    Handle<JSObject> obj = FACTORY->NewJSObject(function);
+    Isolate::Current()->context()->global()->SetProperty(
         *obj_name, *obj, NONE, kNonStrictMode)->ToObjectChecked();
     obj->SetProperty(
         *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
   }
 
   // After gc, it should survive.
-  Heap::CollectGarbage(NEW_SPACE);
+  HEAP->CollectGarbage(NEW_SPACE);
 
-  CHECK(Top::context()->global()->HasLocalProperty(*obj_name));
-  CHECK(Top::context()->global()->GetProperty(*obj_name)->ToObjectChecked()->
-            IsJSObject());
-  Object* obj =
-      Top::context()->global()->GetProperty(*obj_name)->ToObjectChecked();
+  CHECK(Isolate::Current()->context()->global()->HasLocalProperty(*obj_name));
+  CHECK(Isolate::Current()->context()->global()->
+        GetProperty(*obj_name)->ToObjectChecked()->IsJSObject());
+  Object* obj = Isolate::Current()->context()->global()->
+      GetProperty(*obj_name)->ToObjectChecked();
   JSObject* js_obj = JSObject::cast(obj);
   CHECK_EQ(Smi::FromInt(23), js_obj->GetProperty(*prop_name));
 }
@@ -260,7 +261,7 @@
 
 static void VerifyStringAllocation(const char* string) {
   v8::HandleScope scope;
-  Handle<String> s = Factory::NewStringFromUtf8(CStrVector(string));
+  Handle<String> s = FACTORY->NewStringFromUtf8(CStrVector(string));
   CHECK_EQ(StrLength(string), s->length());
   for (int index = 0; index < s->length(); index++) {
     CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index));
@@ -284,12 +285,13 @@
 
   v8::HandleScope scope;
   const char* name = "Kasper the spunky";
-  Handle<String> string = Factory::NewStringFromAscii(CStrVector(name));
+  Handle<String> string = FACTORY->NewStringFromAscii(CStrVector(name));
   CHECK_EQ(StrLength(name), string->length());
 }
 
 
 TEST(GlobalHandles) {
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
   InitializeVM();
 
   Handle<Object> h1;
@@ -300,17 +302,17 @@
   {
     HandleScope scope;
 
-    Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk"));
-    Handle<Object> u = Factory::NewNumber(1.12344);
+    Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
+    Handle<Object> u = FACTORY->NewNumber(1.12344);
 
-    h1 = GlobalHandles::Create(*i);
-    h2 = GlobalHandles::Create(*u);
-    h3 = GlobalHandles::Create(*i);
-    h4 = GlobalHandles::Create(*u);
+    h1 = global_handles->Create(*i);
+    h2 = global_handles->Create(*u);
+    h3 = global_handles->Create(*i);
+    h4 = global_handles->Create(*u);
   }
 
   // after gc, it should survive
-  Heap::CollectGarbage(NEW_SPACE);
+  HEAP->CollectGarbage(NEW_SPACE);
 
   CHECK((*h1)->IsString());
   CHECK((*h2)->IsHeapNumber());
@@ -318,12 +320,12 @@
   CHECK((*h4)->IsHeapNumber());
 
   CHECK_EQ(*h3, *h1);
-  GlobalHandles::Destroy(h1.location());
-  GlobalHandles::Destroy(h3.location());
+  global_handles->Destroy(h1.location());
+  global_handles->Destroy(h3.location());
 
   CHECK_EQ(*h4, *h2);
-  GlobalHandles::Destroy(h2.location());
-  GlobalHandles::Destroy(h4.location());
+  global_handles->Destroy(h2.location());
+  global_handles->Destroy(h4.location());
 }
 
 
@@ -337,6 +339,7 @@
 
 
 TEST(WeakGlobalHandlesScavenge) {
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
   InitializeVM();
 
   WeakPointerCleared = false;
@@ -347,33 +350,34 @@
   {
     HandleScope scope;
 
-    Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk"));
-    Handle<Object> u = Factory::NewNumber(1.12344);
+    Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
+    Handle<Object> u = FACTORY->NewNumber(1.12344);
 
-    h1 = GlobalHandles::Create(*i);
-    h2 = GlobalHandles::Create(*u);
+    h1 = global_handles->Create(*i);
+    h2 = global_handles->Create(*u);
   }
 
-  GlobalHandles::MakeWeak(h2.location(),
-                          reinterpret_cast<void*>(1234),
-                          &TestWeakGlobalHandleCallback);
+  global_handles->MakeWeak(h2.location(),
+                           reinterpret_cast<void*>(1234),
+                           &TestWeakGlobalHandleCallback);
 
   // Scavenge treats weak pointers as normal roots.
-  Heap::PerformScavenge();
+  HEAP->PerformScavenge();
 
   CHECK((*h1)->IsString());
   CHECK((*h2)->IsHeapNumber());
 
   CHECK(!WeakPointerCleared);
-  CHECK(!GlobalHandles::IsNearDeath(h2.location()));
-  CHECK(!GlobalHandles::IsNearDeath(h1.location()));
+  CHECK(!global_handles->IsNearDeath(h2.location()));
+  CHECK(!global_handles->IsNearDeath(h1.location()));
 
-  GlobalHandles::Destroy(h1.location());
-  GlobalHandles::Destroy(h2.location());
+  global_handles->Destroy(h1.location());
+  global_handles->Destroy(h2.location());
 }
 
 
 TEST(WeakGlobalHandlesMark) {
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
   InitializeVM();
 
   WeakPointerCleared = false;
@@ -384,34 +388,35 @@
   {
     HandleScope scope;
 
-    Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk"));
-    Handle<Object> u = Factory::NewNumber(1.12344);
+    Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
+    Handle<Object> u = FACTORY->NewNumber(1.12344);
 
-    h1 = GlobalHandles::Create(*i);
-    h2 = GlobalHandles::Create(*u);
+    h1 = global_handles->Create(*i);
+    h2 = global_handles->Create(*u);
   }
 
-  Heap::CollectGarbage(OLD_POINTER_SPACE);
-  Heap::CollectGarbage(NEW_SPACE);
+  HEAP->CollectGarbage(OLD_POINTER_SPACE);
+  HEAP->CollectGarbage(NEW_SPACE);
   // Make sure the object is promoted.
 
-  GlobalHandles::MakeWeak(h2.location(),
-                          reinterpret_cast<void*>(1234),
-                          &TestWeakGlobalHandleCallback);
+  global_handles->MakeWeak(h2.location(),
+                           reinterpret_cast<void*>(1234),
+                           &TestWeakGlobalHandleCallback);
   CHECK(!GlobalHandles::IsNearDeath(h1.location()));
   CHECK(!GlobalHandles::IsNearDeath(h2.location()));
 
-  Heap::CollectGarbage(OLD_POINTER_SPACE);
+  HEAP->CollectGarbage(OLD_POINTER_SPACE);
 
   CHECK((*h1)->IsString());
 
   CHECK(WeakPointerCleared);
   CHECK(!GlobalHandles::IsNearDeath(h1.location()));
 
-  GlobalHandles::Destroy(h1.location());
+  global_handles->Destroy(h1.location());
 }
 
 TEST(DeleteWeakGlobalHandle) {
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
   InitializeVM();
 
   WeakPointerCleared = false;
@@ -421,21 +426,21 @@
   {
     HandleScope scope;
 
-    Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk"));
-    h = GlobalHandles::Create(*i);
+    Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk"));
+    h = global_handles->Create(*i);
   }
 
-  GlobalHandles::MakeWeak(h.location(),
-                          reinterpret_cast<void*>(1234),
-                          &TestWeakGlobalHandleCallback);
+  global_handles->MakeWeak(h.location(),
+                           reinterpret_cast<void*>(1234),
+                           &TestWeakGlobalHandleCallback);
 
   // Scanvenge does not recognize weak reference.
-  Heap::PerformScavenge();
+  HEAP->PerformScavenge();
 
   CHECK(!WeakPointerCleared);
 
   // Mark-compact treats weak reference properly.
-  Heap::CollectGarbage(OLD_POINTER_SPACE);
+  HEAP->CollectGarbage(OLD_POINTER_SPACE);
 
   CHECK(WeakPointerCleared);
 }
@@ -507,12 +512,12 @@
 static void CheckSymbols(const char** strings) {
   for (const char* string = *strings; *strings != 0; string = *strings++) {
     Object* a;
-    MaybeObject* maybe_a = Heap::LookupAsciiSymbol(string);
+    MaybeObject* maybe_a = HEAP->LookupAsciiSymbol(string);
     // LookupAsciiSymbol may return a failure if a GC is needed.
     if (!maybe_a->ToObject(&a)) continue;
     CHECK(a->IsSymbol());
     Object* b;
-    MaybeObject *maybe_b = Heap::LookupAsciiSymbol(string);
+    MaybeObject* maybe_b = HEAP->LookupAsciiSymbol(string);
     if (!maybe_b->ToObject(&b)) continue;
     CHECK_EQ(b, a);
     CHECK(String::cast(b)->IsEqualTo(CStrVector(string)));
@@ -532,15 +537,15 @@
   InitializeVM();
 
   v8::HandleScope sc;
-  Handle<String> name = Factory::LookupAsciiSymbol("theFunction");
+  Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction");
   Handle<JSFunction> function =
-      Factory::NewFunction(name, Factory::undefined_value());
+      FACTORY->NewFunction(name, FACTORY->undefined_value());
   Handle<Map> initial_map =
-      Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+      FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
   function->set_initial_map(*initial_map);
 
-  Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot");
-  Handle<JSObject> obj = Factory::NewJSObject(function);
+  Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot");
+  Handle<JSObject> obj = FACTORY->NewJSObject(function);
   obj->SetProperty(
       *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
   CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
@@ -555,14 +560,14 @@
   InitializeVM();
 
   v8::HandleScope sc;
-  String* object_symbol = String::cast(Heap::Object_symbol());
-  Object* raw_object =
-      Top::context()->global()->GetProperty(object_symbol)->ToObjectChecked();
+  String* object_symbol = String::cast(HEAP->Object_symbol());
+  Object* raw_object = Isolate::Current()->context()->global()->
+      GetProperty(object_symbol)->ToObjectChecked();
   JSFunction* object_function = JSFunction::cast(raw_object);
   Handle<JSFunction> constructor(object_function);
-  Handle<JSObject> obj = Factory::NewJSObject(constructor);
-  Handle<String> first = Factory::LookupAsciiSymbol("first");
-  Handle<String> second = Factory::LookupAsciiSymbol("second");
+  Handle<JSObject> obj = FACTORY->NewJSObject(constructor);
+  Handle<String> first = FACTORY->LookupAsciiSymbol("first");
+  Handle<String> second = FACTORY->LookupAsciiSymbol("second");
 
   // check for empty
   CHECK(!obj->HasLocalProperty(*first));
@@ -608,18 +613,18 @@
 
   // check string and symbol match
   static const char* string1 = "fisk";
-  Handle<String> s1 = Factory::NewStringFromAscii(CStrVector(string1));
+  Handle<String> s1 = FACTORY->NewStringFromAscii(CStrVector(string1));
   obj->SetProperty(
       *s1, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
-  Handle<String> s1_symbol = Factory::LookupAsciiSymbol(string1);
+  Handle<String> s1_symbol = FACTORY->LookupAsciiSymbol(string1);
   CHECK(obj->HasLocalProperty(*s1_symbol));
 
   // check symbol and string match
   static const char* string2 = "fugl";
-  Handle<String> s2_symbol = Factory::LookupAsciiSymbol(string2);
+  Handle<String> s2_symbol = FACTORY->LookupAsciiSymbol(string2);
   obj->SetProperty(
       *s2_symbol, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
-  Handle<String> s2 = Factory::NewStringFromAscii(CStrVector(string2));
+  Handle<String> s2 = FACTORY->NewStringFromAscii(CStrVector(string2));
   CHECK(obj->HasLocalProperty(*s2));
 }
 
@@ -628,15 +633,15 @@
   InitializeVM();
 
   v8::HandleScope sc;
-  Handle<String> name = Factory::LookupAsciiSymbol("theFunction");
+  Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction");
   Handle<JSFunction> function =
-      Factory::NewFunction(name, Factory::undefined_value());
+      FACTORY->NewFunction(name, FACTORY->undefined_value());
   Handle<Map> initial_map =
-      Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+      FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
   function->set_initial_map(*initial_map);
 
-  Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot");
-  Handle<JSObject> obj = Factory::NewJSObject(function);
+  Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot");
+  Handle<JSObject> obj = FACTORY->NewJSObject(function);
 
   // Set a propery
   obj->SetProperty(
@@ -652,14 +657,14 @@
   InitializeVM();
 
   v8::HandleScope sc;
-  Handle<String> name = Factory::LookupAsciiSymbol("Array");
-  Object* raw_object =
-      Top::context()->global()->GetProperty(*name)->ToObjectChecked();
+  Handle<String> name = FACTORY->LookupAsciiSymbol("Array");
+  Object* raw_object = Isolate::Current()->context()->global()->
+      GetProperty(*name)->ToObjectChecked();
   Handle<JSFunction> function = Handle<JSFunction>(
       JSFunction::cast(raw_object));
 
   // Allocate the object.
-  Handle<JSObject> object = Factory::NewJSObject(function);
+  Handle<JSObject> object = FACTORY->NewJSObject(function);
   Handle<JSArray> array = Handle<JSArray>::cast(object);
   // We just initialized the VM, no heap allocation failure yet.
   Object* ok = array->Initialize(0)->ToObjectChecked();
@@ -676,7 +681,7 @@
 
   // Set array length with larger than smi value.
   Handle<Object> length =
-      Factory::NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1);
+      FACTORY->NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1);
   ok = array->SetElementsLength(*length)->ToObjectChecked();
 
   uint32_t int_length = 0;
@@ -698,14 +703,14 @@
   InitializeVM();
 
   v8::HandleScope sc;
-  String* object_symbol = String::cast(Heap::Object_symbol());
-  Object* raw_object =
-      Top::context()->global()->GetProperty(object_symbol)->ToObjectChecked();
+  String* object_symbol = String::cast(HEAP->Object_symbol());
+  Object* raw_object = Isolate::Current()->context()->global()->
+      GetProperty(object_symbol)->ToObjectChecked();
   JSFunction* object_function = JSFunction::cast(raw_object);
   Handle<JSFunction> constructor(object_function);
-  Handle<JSObject> obj = Factory::NewJSObject(constructor);
-  Handle<String> first = Factory::LookupAsciiSymbol("first");
-  Handle<String> second = Factory::LookupAsciiSymbol("second");
+  Handle<JSObject> obj = FACTORY->NewJSObject(constructor);
+  Handle<String> first = FACTORY->LookupAsciiSymbol("first");
+  Handle<String> second = FACTORY->LookupAsciiSymbol("second");
 
   obj->SetProperty(
       *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
@@ -761,17 +766,17 @@
       non_ascii[3 * i + 2] = chars[2];
     }
     Handle<String> non_ascii_sym =
-        Factory::LookupSymbol(Vector<const char>(non_ascii, 3 * length));
+        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));
+        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));
+        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));
+        FACTORY->NewStringFromUtf8(Vector<const char>(ascii, length));
     ascii_str->Hash();
     CHECK_EQ(length, ascii_str->length());
     DeleteArray(non_ascii);
@@ -805,22 +810,22 @@
   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);
+  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"));
+      FACTORY->NewStringFromAscii(CStrVector("abcdefghij"));
   objs[next_objs_index++] =
-      Factory::NewStringFromAscii(CStrVector("abcdefghij"), TENURED);
+      FACTORY->NewStringFromAscii(CStrVector("abcdefghij"), TENURED);
 
   // Allocate a large string (for large object space).
-  int large_size = Heap::MaxObjectSizeInPagedSpace() + 1;
+  int large_size = HEAP->MaxObjectSizeInPagedSpace() + 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);
+      FACTORY->NewStringFromAscii(CStrVector(str), TENURED);
   delete[] str;
 
   // Add a Map object to look for.
@@ -834,9 +839,9 @@
 TEST(LargeObjectSpaceContains) {
   InitializeVM();
 
-  Heap::CollectGarbage(NEW_SPACE);
+  HEAP->CollectGarbage(NEW_SPACE);
 
-  Address current_top = Heap::new_space()->top();
+  Address current_top = HEAP->new_space()->top();
   Page* page = Page::FromAddress(current_top);
   Address current_page = page->address();
   Address next_page = current_page + Page::kPageSize;
@@ -859,7 +864,7 @@
       kPointerSize;
   CHECK_EQ(bytes_to_allocate, FixedArray::SizeFor(n_elements));
   FixedArray* array = FixedArray::cast(
-      Heap::AllocateFixedArray(n_elements)->ToObjectChecked());
+      HEAP->AllocateFixedArray(n_elements)->ToObjectChecked());
 
   int index = n_elements - 1;
   CHECK_EQ(flags_ptr,
@@ -869,8 +874,8 @@
   // CHECK(Page::FromAddress(next_page)->IsLargeObjectPage());
 
   HeapObject* addr = HeapObject::FromAddress(next_page + 2 * kPointerSize);
-  CHECK(Heap::new_space()->Contains(addr));
-  CHECK(!Heap::lo_space()->Contains(addr));
+  CHECK(HEAP->new_space()->Contains(addr));
+  CHECK(!HEAP->lo_space()->Contains(addr));
 }
 
 
@@ -901,7 +906,7 @@
 
   // Increase the chance of 'bump-the-pointer' allocation in old space.
   bool force_compaction = true;
-  Heap::CollectAllGarbage(force_compaction);
+  HEAP->CollectAllGarbage(force_compaction);
 
   v8::HandleScope scope;
 
@@ -910,11 +915,12 @@
   // that region dirty marks are updated correctly.
 
   // Step 1: prepare a map for the object.  We add 1 inobject property to it.
-  Handle<JSFunction> object_ctor(Top::global_context()->object_function());
+  Handle<JSFunction> object_ctor(
+      Isolate::Current()->global_context()->object_function());
   CHECK(object_ctor->has_initial_map());
   Handle<Map> object_map(object_ctor->initial_map());
   // Create a map with single inobject property.
-  Handle<Map> my_map = Factory::CopyMap(object_map, 1);
+  Handle<Map> my_map = FACTORY->CopyMap(object_map, 1);
   int n_properties = my_map->inobject_properties();
   CHECK_GT(n_properties, 0);
 
@@ -924,15 +930,15 @@
   // just enough room to allocate JSObject and thus fill the newspace.
 
   int allocation_amount = Min(FixedArray::kMaxSize,
-                              Heap::MaxObjectSizeInNewSpace());
+                              HEAP->MaxObjectSizeInNewSpace());
   int allocation_len = LenFromSize(allocation_amount);
-  NewSpace* new_space = Heap::new_space();
+  NewSpace* new_space = HEAP->new_space();
   Address* top_addr = new_space->allocation_top_address();
   Address* limit_addr = new_space->allocation_limit_address();
   while ((*limit_addr - *top_addr) > allocation_amount) {
-    CHECK(!Heap::always_allocate());
-    Object* array =
-        Heap::AllocateFixedArray(allocation_len)->ToObjectChecked();
+    CHECK(!HEAP->always_allocate());
+    Object* array = HEAP->AllocateFixedArray(allocation_len)->ToObjectChecked();
+    CHECK(!array->IsFailure());
     CHECK(new_space->Contains(array));
   }
 
@@ -941,12 +947,12 @@
   int fixed_array_len = LenFromSize(to_fill);
   CHECK(fixed_array_len < FixedArray::kMaxLength);
 
-  CHECK(!Heap::always_allocate());
-  Object* array =
-      Heap::AllocateFixedArray(fixed_array_len)->ToObjectChecked();
+  CHECK(!HEAP->always_allocate());
+  Object* array = HEAP->AllocateFixedArray(fixed_array_len)->ToObjectChecked();
+  CHECK(!array->IsFailure());
   CHECK(new_space->Contains(array));
 
-  Object* object = Heap::AllocateJSObjectFromMap(*my_map)->ToObjectChecked();
+  Object* object = HEAP->AllocateJSObjectFromMap(*my_map)->ToObjectChecked();
   CHECK(new_space->Contains(object));
   JSObject* jsobject = JSObject::cast(object);
   CHECK_EQ(0, FixedArray::cast(jsobject->elements())->length());
@@ -958,15 +964,15 @@
 
   // Step 4: clone jsobject, but force always allocate first to create a clone
   // in old pointer space.
-  Address old_pointer_space_top = Heap::old_pointer_space()->top();
+  Address old_pointer_space_top = HEAP->old_pointer_space()->top();
   AlwaysAllocateScope aa_scope;
-  Object* clone_obj = Heap::CopyJSObject(jsobject)->ToObjectChecked();
+  Object* clone_obj = HEAP->CopyJSObject(jsobject)->ToObjectChecked();
   JSObject* clone = JSObject::cast(clone_obj);
   if (clone->address() != old_pointer_space_top) {
     // Alas, got allocated from free list, we cannot do checks.
     return;
   }
-  CHECK(Heap::old_pointer_space()->Contains(clone->address()));
+  CHECK(HEAP->old_pointer_space()->Contains(clone->address()));
 
   // Step 5: verify validity of region dirty marks.
   Address clone_addr = clone->address();
@@ -988,7 +994,7 @@
                        "  var z = x + y;"
                        "};"
                        "foo()";
-  Handle<String> foo_name = Factory::LookupAsciiSymbol("foo");
+  Handle<String> foo_name = FACTORY->LookupAsciiSymbol("foo");
 
   // This compile will add the code to the compilation cache.
   { v8::HandleScope scope;
@@ -996,23 +1002,23 @@
   }
 
   // Check function is compiled.
-  Object* func_value =
-      Top::context()->global()->GetProperty(*foo_name)->ToObjectChecked();
+  Object* func_value = Isolate::Current()->context()->global()->
+      GetProperty(*foo_name)->ToObjectChecked();
   CHECK(func_value->IsJSFunction());
   Handle<JSFunction> function(JSFunction::cast(func_value));
   CHECK(function->shared()->is_compiled());
 
-  Heap::CollectAllGarbage(true);
-  Heap::CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
 
   CHECK(function->shared()->is_compiled());
 
-  Heap::CollectAllGarbage(true);
-  Heap::CollectAllGarbage(true);
-  Heap::CollectAllGarbage(true);
-  Heap::CollectAllGarbage(true);
-  Heap::CollectAllGarbage(true);
-  Heap::CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
 
   // foo should no longer be in the compilation cache
   CHECK(!function->shared()->is_compiled() || function->IsOptimized());
@@ -1027,7 +1033,7 @@
 // Count the number of global contexts in the weak list of global contexts.
 static int CountGlobalContexts() {
   int count = 0;
-  Object* object = Heap::global_contexts_list();
+  Object* object = HEAP->global_contexts_list();
   while (!object->IsUndefined()) {
     count++;
     object = Context::cast(object)->get(Context::NEXT_CONTEXT_LINK);
@@ -1051,6 +1057,8 @@
 
 
 TEST(TestInternalWeakLists) {
+  v8::V8::Initialize();
+
   static const int kNumTestContexts = 10;
 
   v8::HandleScope scope;
@@ -1094,35 +1102,35 @@
 
     // Scavenge treats these references as strong.
     for (int j = 0; j < 10; j++) {
-      Heap::PerformScavenge();
+      HEAP->PerformScavenge();
       CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i]));
     }
 
     // Mark compact handles the weak references.
-    Heap::CollectAllGarbage(true);
+    HEAP->CollectAllGarbage(true);
     CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i]));
 
     // Get rid of f3 and f5 in the same way.
     CompileRun("f3=null");
     for (int j = 0; j < 10; j++) {
-      Heap::PerformScavenge();
+      HEAP->PerformScavenge();
       CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i]));
     }
-    Heap::CollectAllGarbage(true);
+    HEAP->CollectAllGarbage(true);
     CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i]));
     CompileRun("f5=null");
     for (int j = 0; j < 10; j++) {
-      Heap::PerformScavenge();
+      HEAP->PerformScavenge();
       CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i]));
     }
-    Heap::CollectAllGarbage(true);
+    HEAP->CollectAllGarbage(true);
     CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i]));
 
     ctx[i]->Exit();
   }
 
   // Force compilation cache cleanup.
-  Heap::CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
 
   // Dispose the global contexts one by one.
   for (int i = 0; i < kNumTestContexts; i++) {
@@ -1131,12 +1139,12 @@
 
     // Scavenge treats these references as strong.
     for (int j = 0; j < 10; j++) {
-      Heap::PerformScavenge();
+      HEAP->PerformScavenge();
       CHECK_EQ(kNumTestContexts - i, CountGlobalContexts());
     }
 
     // Mark compact handles the weak references.
-    Heap::CollectAllGarbage(true);
+    HEAP->CollectAllGarbage(true);
     CHECK_EQ(kNumTestContexts - i - 1, CountGlobalContexts());
   }
 
@@ -1148,10 +1156,10 @@
 // causing a GC after the specified number of elements.
 static int CountGlobalContextsWithGC(int n) {
   int count = 0;
-  Handle<Object> object(Heap::global_contexts_list());
+  Handle<Object> object(HEAP->global_contexts_list());
   while (!object->IsUndefined()) {
     count++;
-    if (count == n) Heap::CollectAllGarbage(true);
+    if (count == n) HEAP->CollectAllGarbage(true);
     object =
         Handle<Object>(Context::cast(*object)->get(Context::NEXT_CONTEXT_LINK));
   }
@@ -1170,7 +1178,7 @@
   while (object->IsJSFunction() &&
          !Handle<JSFunction>::cast(object)->IsBuiltin()) {
     count++;
-    if (count == n) Heap::CollectAllGarbage(true);
+    if (count == n) HEAP->CollectAllGarbage(true);
     object = Handle<Object>(
         Object::cast(JSFunction::cast(*object)->next_function_link()));
   }
@@ -1179,6 +1187,8 @@
 
 
 TEST(TestInternalWeakListsTraverseWithGC) {
+  v8::V8::Initialize();
+
   static const int kNumTestContexts = 10;
 
   v8::HandleScope scope;
@@ -1228,7 +1238,7 @@
 
 TEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
   InitializeVM();
-  intptr_t size_of_objects_1 = Heap::SizeOfObjects();
+  intptr_t size_of_objects_1 = HEAP->SizeOfObjects();
   HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
   intptr_t size_of_objects_2 = 0;
   for (HeapObject* obj = iterator.next();
@@ -1283,10 +1293,10 @@
   InitializeVM();
   v8::HandleScope scope;
   CompileRun("a = {}; b = {};");
-  v8::Handle<Object> a(Top::context()->global()->GetProperty(
-      *Factory::LookupAsciiSymbol("a"))->ToObjectChecked());
-  v8::Handle<Object> b(Top::context()->global()->GetProperty(
-      *Factory::LookupAsciiSymbol("b"))->ToObjectChecked());
+  v8::Handle<Object> a(ISOLATE->context()->global()->GetProperty(
+      *FACTORY->LookupAsciiSymbol("a"))->ToObjectChecked());
+  v8::Handle<Object> b(ISOLATE->context()->global()->GetProperty(
+      *FACTORY->LookupAsciiSymbol("b"))->ToObjectChecked());
   CHECK_NE(*a, *b);
   {
     HeapIteratorTestHelper helper(*a, *b);
@@ -1294,8 +1304,8 @@
     CHECK(helper.a_found());
     CHECK(helper.b_found());
   }
-  CHECK(Top::context()->global()->DeleteProperty(
-      *Factory::LookupAsciiSymbol("a"), JSObject::FORCE_DELETION));
+  CHECK(ISOLATE->context()->global()->DeleteProperty(
+      *FACTORY->LookupAsciiSymbol("a"), JSObject::FORCE_DELETION));
   // We ensure that GC will not happen, so our raw pointer stays valid.
   AssertNoAllocation no_alloc;
   Object* a_saved = *a;
diff --git a/test/cctest/test-liveedit.cc b/test/cctest/test-liveedit.cc
index 244980a..9232354 100644
--- a/test/cctest/test-liveedit.cc
+++ b/test/cctest/test-liveedit.cc
@@ -158,6 +158,7 @@
 // --- T h e   A c t u a l   T e s t s
 
 TEST(LiveEditDiffer) {
+  v8::internal::V8::Initialize(NULL);
   CompareStrings("zz1zzz12zz123zzz", "zzzzzzzzzz", 6);
   CompareStrings("zz1zzz12zz123zzz", "zz0zzz0zz0zzz", 9);
   CompareStrings("123456789", "987654321", 16);
diff --git a/test/cctest/test-log-stack-tracer.cc b/test/cctest/test-log-stack-tracer.cc
index bf72184..df0806f 100644
--- a/test/cctest/test-log-stack-tracer.cc
+++ b/test/cctest/test-log-stack-tracer.cc
@@ -36,7 +36,7 @@
 #include "api.h"
 #include "codegen.h"
 #include "log.h"
-#include "top.h"
+#include "isolate.h"
 #include "cctest.h"
 #include "disassembler.h"
 #include "register-allocator-inl.h"
@@ -52,10 +52,10 @@
 using v8::internal::byte;
 using v8::internal::Address;
 using v8::internal::Handle;
+using v8::internal::Isolate;
 using v8::internal::JSFunction;
 using v8::internal::StackTracer;
 using v8::internal::TickSample;
-using v8::internal::Top;
 
 namespace i = v8::internal;
 
@@ -78,18 +78,19 @@
   // sp is only used to define stack high bound
   trace_env.sample->sp =
       reinterpret_cast<Address>(trace_env.sample) - 10240;
-  StackTracer::Trace(trace_env.sample);
+  StackTracer::Trace(Isolate::Current(), trace_env.sample);
 }
 
 
 // Hide c_entry_fp to emulate situation when sampling is done while
 // pure JS code is being executed
 static void DoTraceHideCEntryFPAddress(Address fp) {
-  v8::internal::Address saved_c_frame_fp = *(Top::c_entry_fp_address());
+  v8::internal::Address saved_c_frame_fp =
+      *(Isolate::Current()->c_entry_fp_address());
   CHECK(saved_c_frame_fp);
-  *(Top::c_entry_fp_address()) = 0;
+  *(Isolate::Current()->c_entry_fp_address()) = 0;
   DoTrace(fp);
-  *(Top::c_entry_fp_address()) = saved_c_frame_fp;
+  *(Isolate::Current()->c_entry_fp_address()) = saved_c_frame_fp;
 }
 
 
@@ -163,8 +164,8 @@
 
 
 static Address GetJsEntrySp() {
-  CHECK_NE(NULL, Top::GetCurrentThread());
-  return Top::js_entry_sp(Top::GetCurrentThread());
+  CHECK_NE(NULL, i::Isolate::Current()->thread_local_top());
+  return Isolate::js_entry_sp(i::Isolate::Current()->thread_local_top());
 }
 
 
@@ -276,7 +277,7 @@
 
 // This test verifies that stack tracing works when called during
 // execution of a native function called from JS code. In this case,
-// StackTracer uses Top::c_entry_fp as a starting point for stack
+// StackTracer uses Isolate::c_entry_fp as a starting point for stack
 // walking.
 TEST(CFromJSStackTrace) {
   TickSample sample;
@@ -302,13 +303,11 @@
   //         DoTrace(EBP) [native]
   //           StackTracer::Trace
 
-  // The VM state tracking keeps track of external callbacks and puts
-  // them at the top of the sample stack.
-  int base = 0;
-  CHECK(sample.stack[0] == FUNCTION_ADDR(TraceExtension::Trace));
-  base++;
+  CHECK(sample.has_external_callback);
+  CHECK_EQ(FUNCTION_ADDR(TraceExtension::Trace), sample.external_callback);
 
   // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace"
+  int base = 0;
   CHECK_GT(sample.frames_count, base + 1);
   CHECK(IsAddressWithinFuncCode("JSFuncDoTrace", sample.stack[base + 0]));
   CHECK(IsAddressWithinFuncCode("JSTrace", sample.stack[base + 1]));
@@ -318,7 +317,7 @@
 // This test verifies that stack tracing works when called during
 // execution of JS code. However, as calling StackTracer requires
 // entering native code, we can only emulate pure JS by erasing
-// Top::c_entry_fp value. In this case, StackTracer uses passed frame
+// Isolate::c_entry_fp value. In this case, StackTracer uses passed frame
 // pointer value as a starting point for stack walking.
 TEST(PureJSStackTrace) {
   // This test does not pass with inlining enabled since inlined functions
@@ -353,13 +352,11 @@
   //             StackTracer::Trace
   //
 
-  // The VM state tracking keeps track of external callbacks and puts
-  // them at the top of the sample stack.
-  int base = 0;
-  CHECK(sample.stack[0] == FUNCTION_ADDR(TraceExtension::JSTrace));
-  base++;
+  CHECK(sample.has_external_callback);
+  CHECK_EQ(FUNCTION_ADDR(TraceExtension::JSTrace), sample.external_callback);
 
   // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace"
+  int base = 0;
   CHECK_GT(sample.frames_count, base + 1);
   CHECK(IsAddressWithinFuncCode("JSTrace", sample.stack[base + 0]));
   CHECK(IsAddressWithinFuncCode("OuterJSTrace", sample.stack[base + 1]));
@@ -397,6 +394,7 @@
 TEST(PureCStackTrace) {
   TickSample sample;
   InitTraceEnv(&sample);
+  InitializeVM();
   // Check that sampler doesn't crash
   CHECK_EQ(10, CFunc(10));
 }
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index 30b8a48..17c7387 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -29,61 +29,61 @@
   // Log to memory buffer.
   i::FLAG_logfile = "*";
   i::FLAG_log = true;
-  Logger::Setup();
+  LOGGER->Setup();
 }
 
 static void TearDown() {
-  Logger::TearDown();
+  LOGGER->TearDown();
 }
 
 
 TEST(EmptyLog) {
   SetUp();
-  CHECK_EQ(0, Logger::GetLogLines(0, NULL, 0));
-  CHECK_EQ(0, Logger::GetLogLines(100, NULL, 0));
-  CHECK_EQ(0, Logger::GetLogLines(0, NULL, 100));
-  CHECK_EQ(0, Logger::GetLogLines(100, NULL, 100));
+  CHECK_EQ(0, LOGGER->GetLogLines(0, NULL, 0));
+  CHECK_EQ(0, LOGGER->GetLogLines(100, NULL, 0));
+  CHECK_EQ(0, LOGGER->GetLogLines(0, NULL, 100));
+  CHECK_EQ(0, LOGGER->GetLogLines(100, NULL, 100));
   TearDown();
 }
 
 
 TEST(GetMessages) {
   SetUp();
-  Logger::StringEvent("aaa", "bbb");
-  Logger::StringEvent("cccc", "dddd");
-  CHECK_EQ(0, Logger::GetLogLines(0, NULL, 0));
+  LOGGER->StringEvent("aaa", "bbb");
+  LOGGER->StringEvent("cccc", "dddd");
+  CHECK_EQ(0, LOGGER->GetLogLines(0, NULL, 0));
   char log_lines[100];
   memset(log_lines, 0, sizeof(log_lines));
   // See Logger::StringEvent.
   const char* line_1 = "aaa,\"bbb\"\n";
   const int line_1_len = StrLength(line_1);
   // The exact size.
-  CHECK_EQ(line_1_len, Logger::GetLogLines(0, log_lines, line_1_len));
+  CHECK_EQ(line_1_len, LOGGER->GetLogLines(0, log_lines, line_1_len));
   CHECK_EQ(line_1, log_lines);
   memset(log_lines, 0, sizeof(log_lines));
   // A bit more than the first line length.
-  CHECK_EQ(line_1_len, Logger::GetLogLines(0, log_lines, line_1_len + 3));
+  CHECK_EQ(line_1_len, LOGGER->GetLogLines(0, log_lines, line_1_len + 3));
   log_lines[line_1_len] = '\0';
   CHECK_EQ(line_1, log_lines);
   memset(log_lines, 0, sizeof(log_lines));
   const char* line_2 = "cccc,\"dddd\"\n";
   const int line_2_len = StrLength(line_2);
   // Now start with line_2 beginning.
-  CHECK_EQ(0, Logger::GetLogLines(line_1_len, log_lines, 0));
-  CHECK_EQ(line_2_len, Logger::GetLogLines(line_1_len, log_lines, line_2_len));
+  CHECK_EQ(0, LOGGER->GetLogLines(line_1_len, log_lines, 0));
+  CHECK_EQ(line_2_len, LOGGER->GetLogLines(line_1_len, log_lines, line_2_len));
   CHECK_EQ(line_2, log_lines);
   memset(log_lines, 0, sizeof(log_lines));
   CHECK_EQ(line_2_len,
-           Logger::GetLogLines(line_1_len, log_lines, line_2_len + 3));
+           LOGGER->GetLogLines(line_1_len, log_lines, line_2_len + 3));
   CHECK_EQ(line_2, log_lines);
   memset(log_lines, 0, sizeof(log_lines));
   // Now get entire buffer contents.
   const char* all_lines = "aaa,\"bbb\"\ncccc,\"dddd\"\n";
   const int all_lines_len = StrLength(all_lines);
-  CHECK_EQ(all_lines_len, Logger::GetLogLines(0, log_lines, all_lines_len));
+  CHECK_EQ(all_lines_len, LOGGER->GetLogLines(0, log_lines, all_lines_len));
   CHECK_EQ(all_lines, log_lines);
   memset(log_lines, 0, sizeof(log_lines));
-  CHECK_EQ(all_lines_len, Logger::GetLogLines(0, log_lines, all_lines_len + 3));
+  CHECK_EQ(all_lines_len, LOGGER->GetLogLines(0, log_lines, all_lines_len + 3));
   CHECK_EQ(all_lines, log_lines);
   memset(log_lines, 0, sizeof(log_lines));
   TearDown();
@@ -91,26 +91,26 @@
 
 
 static int GetLogLines(int start_pos, i::Vector<char>* buffer) {
-  return Logger::GetLogLines(start_pos, buffer->start(), buffer->length());
+  return LOGGER->GetLogLines(start_pos, buffer->start(), buffer->length());
 }
 
 
 TEST(BeyondWritePosition) {
   SetUp();
-  Logger::StringEvent("aaa", "bbb");
-  Logger::StringEvent("cccc", "dddd");
+  LOGGER->StringEvent("aaa", "bbb");
+  LOGGER->StringEvent("cccc", "dddd");
   // See Logger::StringEvent.
   const char* all_lines = "aaa,\"bbb\"\ncccc,\"dddd\"\n";
   const int all_lines_len = StrLength(all_lines);
   EmbeddedVector<char, 100> buffer;
   const int beyond_write_pos = all_lines_len;
-  CHECK_EQ(0, Logger::GetLogLines(beyond_write_pos, buffer.start(), 1));
+  CHECK_EQ(0, LOGGER->GetLogLines(beyond_write_pos, buffer.start(), 1));
   CHECK_EQ(0, GetLogLines(beyond_write_pos, &buffer));
-  CHECK_EQ(0, Logger::GetLogLines(beyond_write_pos + 1, buffer.start(), 1));
+  CHECK_EQ(0, LOGGER->GetLogLines(beyond_write_pos + 1, buffer.start(), 1));
   CHECK_EQ(0, GetLogLines(beyond_write_pos + 1, &buffer));
-  CHECK_EQ(0, Logger::GetLogLines(beyond_write_pos + 100, buffer.start(), 1));
+  CHECK_EQ(0, LOGGER->GetLogLines(beyond_write_pos + 100, buffer.start(), 1));
   CHECK_EQ(0, GetLogLines(beyond_write_pos + 100, &buffer));
-  CHECK_EQ(0, Logger::GetLogLines(10 * 1024 * 1024, buffer.start(), 1));
+  CHECK_EQ(0, LOGGER->GetLogLines(10 * 1024 * 1024, buffer.start(), 1));
   CHECK_EQ(0, GetLogLines(10 * 1024 * 1024, &buffer));
   TearDown();
 }
@@ -120,12 +120,12 @@
   // Log to stdout
   i::FLAG_logfile = "-";
   i::FLAG_log = true;
-  Logger::Setup();
-  CHECK_EQ(0, Logger::GetLogLines(0, NULL, 0));
-  CHECK_EQ(0, Logger::GetLogLines(100, NULL, 0));
-  CHECK_EQ(0, Logger::GetLogLines(0, NULL, 100));
-  CHECK_EQ(0, Logger::GetLogLines(100, NULL, 100));
-  Logger::TearDown();
+  LOGGER->Setup();
+  CHECK_EQ(0, LOGGER->GetLogLines(0, NULL, 0));
+  CHECK_EQ(0, LOGGER->GetLogLines(100, NULL, 0));
+  CHECK_EQ(0, LOGGER->GetLogLines(0, NULL, 100));
+  CHECK_EQ(0, LOGGER->GetLogLines(100, NULL, 100));
+  LOGGER->TearDown();
 }
 
 
@@ -139,12 +139,12 @@
 
 class LoggerTestHelper : public AllStatic {
  public:
-  static bool IsSamplerActive() { return Logger::IsProfilerSamplerActive(); }
+  static bool IsSamplerActive() { return LOGGER->IsProfilerSamplerActive(); }
   static void ResetSamplesTaken() {
-    reinterpret_cast<Sampler*>(Logger::ticker_)->ResetSamplesTaken();
+    reinterpret_cast<Sampler*>(LOGGER->ticker_)->ResetSamplesTaken();
   }
   static bool has_samples_taken() {
-    return reinterpret_cast<Sampler*>(Logger::ticker_)->samples_taken() > 0;
+    return reinterpret_cast<Sampler*>(LOGGER->ticker_)->samples_taken() > 0;
   }
 };
 
@@ -166,13 +166,13 @@
         need_to_set_up_logger_(i::V8::IsRunning()),
         scope_(),
         env_(v8::Context::New()) {
-    if (need_to_set_up_logger_) Logger::Setup();
+    if (need_to_set_up_logger_) LOGGER->Setup();
     env_->Enter();
   }
 
   ~ScopedLoggerInitializer() {
     env_->Exit();
-    Logger::TearDown();
+    LOGGER->TearDown();
     i::FLAG_prof_lazy = saved_prof_lazy_;
     i::FLAG_prof = saved_prof_;
     i::FLAG_prof_auto = saved_prof_auto_;
@@ -251,7 +251,7 @@
         !LoggerTestHelper::IsSamplerActive());
   LoggerTestHelper::ResetSamplesTaken();
 
-  Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 0);
+  LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 0);
   CHECK(LoggerTestHelper::IsSamplerActive());
 
   // Verify that the current map of compiled functions has been logged.
@@ -273,7 +273,7 @@
     i::OS::Sleep(1);
   }
 
-  Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 0);
+  LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 0);
   CHECK(i::RuntimeProfiler::IsEnabled() ||
         !LoggerTestHelper::IsSamplerActive());
 
@@ -329,8 +329,8 @@
 
 class LoopingThread : public v8::internal::Thread {
  public:
-  LoopingThread()
-      : v8::internal::Thread(),
+  explicit LoopingThread(v8::internal::Isolate* isolate)
+      : v8::internal::Thread(isolate),
         semaphore_(v8::internal::OS::CreateSemaphore(0)),
         run_(true) {
   }
@@ -369,9 +369,12 @@
 
 class LoopingJsThread : public LoopingThread {
  public:
+  explicit LoopingJsThread(v8::internal::Isolate* isolate)
+      : LoopingThread(isolate) { }
   void RunLoop() {
     v8::Locker locker;
-    CHECK(v8::internal::ThreadManager::HasId());
+    CHECK(i::Isolate::Current() != NULL);
+    CHECK_GT(i::Isolate::Current()->thread_manager()->CurrentId(), 0);
     SetV8ThreadId();
     while (IsRunning()) {
       v8::HandleScope scope;
@@ -392,11 +395,14 @@
 
 class LoopingNonJsThread : public LoopingThread {
  public:
+  explicit LoopingNonJsThread(v8::internal::Isolate* isolate)
+      : LoopingThread(isolate) { }
   void RunLoop() {
     v8::Locker locker;
     v8::Unlocker unlocker;
     // Now thread has V8's id, but will not run VM code.
-    CHECK(v8::internal::ThreadManager::HasId());
+    CHECK(i::Isolate::Current() != NULL);
+    CHECK_GT(i::Isolate::Current()->thread_manager()->CurrentId(), 0);
     double i = 10;
     SignalRunning();
     while (IsRunning()) {
@@ -409,8 +415,8 @@
 
 class TestSampler : public v8::internal::Sampler {
  public:
-  TestSampler()
-      : Sampler(0, true, true),
+  explicit TestSampler(v8::internal::Isolate* isolate)
+      : Sampler(isolate, 0, true, true),
         semaphore_(v8::internal::OS::CreateSemaphore(0)),
         was_sample_stack_called_(false) {
   }
@@ -441,14 +447,14 @@
   TestSampler* sampler = NULL;
   {
     v8::Locker locker;
-    sampler = new TestSampler();
+    sampler = new TestSampler(v8::internal::Isolate::Current());
     sampler->Start();
     CHECK(sampler->IsActive());
   }
 
-  LoopingJsThread jsThread;
+  LoopingJsThread jsThread(v8::internal::Isolate::Current());
   jsThread.Start();
-  LoopingNonJsThread nonJsThread;
+  LoopingNonJsThread nonJsThread(v8::internal::Isolate::Current());
   nonJsThread.Start();
 
   CHECK(!sampler->WasSampleStackCalled());
@@ -515,7 +521,7 @@
   i_source->set_resource(NULL);
 
   // Must not crash.
-  i::Logger::LogCompiledFunctions();
+  LOGGER->LogCompiledFunctions();
 }
 
 
@@ -541,7 +547,7 @@
   initialize_logger.env()->Global()->Set(v8_str("Obj"), obj->GetFunction());
   CompileAndRunScript("Obj.prototype.method1.toString();");
 
-  i::Logger::LogCompiledFunctions();
+  LOGGER->LogCompiledFunctions();
   CHECK_GT(matcher.GetNextChunk(), 0);
 
   const char* callback_rec = "code-creation,Callback,";
@@ -584,7 +590,7 @@
   inst->SetAccessor(v8::String::New("prop1"), Prop1Getter, Prop1Setter);
   inst->SetAccessor(v8::String::New("prop2"), Prop2Getter);
 
-  i::Logger::LogAccessorCallbacks();
+  LOGGER->LogAccessorCallbacks();
   CHECK_GT(matcher.GetNextChunk(), 0);
   matcher.PrintBuffer();
 
@@ -616,11 +622,11 @@
   const char* close_tag = "close-tag,";
 
   // Check compatibility with the old style behavior.
-  CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
-  Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 0);
-  CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
-  Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 0);
-  CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+  CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules());
+  LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 0);
+  CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules());
+  LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 0);
+  CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules());
   CHECK_EQ(NULL, matcher.Find(open_tag));
   CHECK_EQ(NULL, matcher.Find(close_tag));
 
@@ -628,11 +634,11 @@
   const char* close_tag1 = "close-tag,1\n";
 
   // Check non-nested tag case.
-  CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
-  Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 1);
-  CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
-  Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 1);
-  CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+  CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules());
+  LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 1);
+  CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules());
+  LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 1);
+  CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules());
   CHECK_GT(matcher.GetNextChunk(), 0);
   CHECK(matcher.IsInSequence(open_tag1, close_tag1));
 
@@ -640,15 +646,15 @@
   const char* close_tag2 = "close-tag,2\n";
 
   // Check nested tags case.
-  CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
-  Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 1);
-  CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
-  Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 2);
-  CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
-  Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 2);
-  CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
-  Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 1);
-  CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+  CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules());
+  LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 1);
+  CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules());
+  LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 2);
+  CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules());
+  LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 2);
+  CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules());
+  LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 1);
+  CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules());
   CHECK_GT(matcher.GetNextChunk(), 0);
   // open_tag1 < open_tag2 < close_tag2 < close_tag1
   CHECK(matcher.IsInSequence(open_tag1, open_tag2));
@@ -656,15 +662,15 @@
   CHECK(matcher.IsInSequence(close_tag2, close_tag1));
 
   // Check overlapped tags case.
-  CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
-  Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 1);
-  CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
-  Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 2);
-  CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
-  Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 1);
-  CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
-  Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 2);
-  CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+  CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules());
+  LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 1);
+  CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules());
+  LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 2);
+  CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules());
+  LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 1);
+  CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules());
+  LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 2);
+  CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules());
   CHECK_GT(matcher.GetNextChunk(), 0);
   // open_tag1 < open_tag2 < close_tag1 < close_tag2
   CHECK(matcher.IsInSequence(open_tag1, open_tag2));
@@ -675,19 +681,19 @@
   const char* close_tag3 = "close-tag,3\n";
 
   // Check pausing overflow case.
-  CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
-  Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 1);
-  CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
-  Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 2);
-  CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
-  Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 2);
-  CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
-  Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 1);
-  CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
-  Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 3);
-  CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
-  Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 3);
-  CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+  CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules());
+  LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 1);
+  CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules());
+  LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 2);
+  CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules());
+  LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 2);
+  CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules());
+  LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 1);
+  CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules());
+  LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 3);
+  CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules());
+  LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 3);
+  CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules());
   // Must be no tags, because logging must be disabled.
   CHECK_EQ(NULL, matcher.Find(open_tag3));
   CHECK_EQ(NULL, matcher.Find(close_tag3));
@@ -697,29 +703,29 @@
 TEST(IsLoggingPreserved) {
   ScopedLoggerInitializer initialize_logger(false);
 
-  CHECK(Logger::is_logging());
-  Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 1);
-  CHECK(Logger::is_logging());
-  Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 1);
-  CHECK(Logger::is_logging());
+  CHECK(LOGGER->is_logging());
+  LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 1);
+  CHECK(LOGGER->is_logging());
+  LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 1);
+  CHECK(LOGGER->is_logging());
 
-  CHECK(Logger::is_logging());
-  Logger::ResumeProfiler(
+  CHECK(LOGGER->is_logging());
+  LOGGER->ResumeProfiler(
       v8::PROFILER_MODULE_HEAP_STATS | v8::PROFILER_MODULE_JS_CONSTRUCTORS, 1);
-  CHECK(Logger::is_logging());
-  Logger::PauseProfiler(
+  CHECK(LOGGER->is_logging());
+  LOGGER->PauseProfiler(
       v8::PROFILER_MODULE_HEAP_STATS | v8::PROFILER_MODULE_JS_CONSTRUCTORS, 1);
-  CHECK(Logger::is_logging());
+  CHECK(LOGGER->is_logging());
 
-  CHECK(Logger::is_logging());
-  Logger::ResumeProfiler(
+  CHECK(LOGGER->is_logging());
+  LOGGER->ResumeProfiler(
       v8::PROFILER_MODULE_CPU |
       v8::PROFILER_MODULE_HEAP_STATS | v8::PROFILER_MODULE_JS_CONSTRUCTORS, 1);
-  CHECK(Logger::is_logging());
-  Logger::PauseProfiler(
+  CHECK(LOGGER->is_logging());
+  LOGGER->PauseProfiler(
       v8::PROFILER_MODULE_CPU |
       v8::PROFILER_MODULE_HEAP_STATS | v8::PROFILER_MODULE_JS_CONSTRUCTORS, 1);
-  CHECK(Logger::is_logging());
+  CHECK(LOGGER->is_logging());
 }
 
 
@@ -1128,7 +1134,7 @@
       "  obj.test =\n"
       "    (function a(j) { return function b() { return j; } })(100);\n"
       "})(this);");
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
 
   EmbeddedVector<char, 204800> buffer;
   int log_size;
@@ -1148,9 +1154,9 @@
   }
 
   // Iterate heap to find compiled functions, will write to log.
-  i::Logger::LogCompiledFunctions();
+  LOGGER->LogCompiledFunctions();
   char* new_log_start = buffer.start() + log_size;
-  const int new_log_size = Logger::GetLogLines(
+  const int new_log_size = LOGGER->GetLogLines(
       log_size, new_log_start, buffer.length() - log_size);
   CHECK_GT(new_log_size, 0);
   CHECK_GT(buffer.length(), log_size + new_log_size);
@@ -1184,7 +1190,7 @@
   CHECK(results_equal);
 
   env->Exit();
-  Logger::TearDown();
+  LOGGER->TearDown();
   i::FLAG_always_compact = saved_always_compact;
 }
 
diff --git a/test/cctest/test-macro-assembler-x64.cc b/test/cctest/test-macro-assembler-x64.cc
index 9b1fc46..c7c67b0 100755
--- a/test/cctest/test-macro-assembler-x64.cc
+++ b/test/cctest/test-macro-assembler-x64.cc
@@ -57,9 +57,9 @@
 using v8::internal::r8;
 using v8::internal::r9;
 using v8::internal::r11;
-using v8::internal::r12;
 using v8::internal::r13;
 using v8::internal::r14;
+using v8::internal::r15;
 using v8::internal::times_pointer_size;
 using v8::internal::FUNCTION_CAST;
 using v8::internal::CodeDesc;
@@ -95,7 +95,9 @@
 static void EntryCode(MacroAssembler* masm) {
   // Smi constant register is callee save.
   __ push(v8::internal::kSmiConstantRegister);
+  __ push(v8::internal::kRootRegister);
   __ InitializeSmiConstantRegister();
+  __ InitializeRootRegister();
 }
 
 
@@ -105,6 +107,7 @@
   __ cmpq(rdx, v8::internal::kSmiConstantRegister);
   __ movq(rdx, Immediate(-1));
   __ cmovq(not_equal, rax, rdx);
+  __ pop(v8::internal::kRootRegister);
   __ pop(v8::internal::kSmiConstantRegister);
 }
 
@@ -146,6 +149,7 @@
 
 // Test that we can move a Smi value literally into a register.
 TEST(SmiMove) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -220,7 +224,7 @@
       __ j(less_equal, exit);
     }
   } else {
-    __ SmiCompare(rcx, rcx);
+    __ cmpq(rcx, rcx);
     __ movl(rax, Immediate(id + 11));
     __ j(not_equal, exit);
     __ incq(rax);
@@ -232,10 +236,11 @@
 
 // Test that we can compare smis for equality (and more).
 TEST(SmiCompare) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer =
-      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
                                       &actual_size,
                                       true));
   CHECK(buffer);
@@ -282,6 +287,7 @@
 
 
 TEST(Integer32ToSmi) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -300,35 +306,35 @@
   __ movl(rcx, Immediate(0));
   __ Integer32ToSmi(rcx, rcx);
   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
-  __ SmiCompare(rcx, rdx);
+  __ cmpq(rcx, rdx);
   __ j(not_equal, &exit);
 
   __ movq(rax, Immediate(2));  // Test number.
   __ movl(rcx, Immediate(1024));
   __ Integer32ToSmi(rcx, rcx);
   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
-  __ SmiCompare(rcx, rdx);
+  __ cmpq(rcx, rdx);
   __ j(not_equal, &exit);
 
   __ movq(rax, Immediate(3));  // Test number.
   __ movl(rcx, Immediate(-1));
   __ Integer32ToSmi(rcx, rcx);
   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
-  __ SmiCompare(rcx, rdx);
+  __ cmpq(rcx, rdx);
   __ j(not_equal, &exit);
 
   __ movq(rax, Immediate(4));  // Test number.
   __ movl(rcx, Immediate(Smi::kMaxValue));
   __ Integer32ToSmi(rcx, rcx);
   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
-  __ SmiCompare(rcx, rdx);
+  __ cmpq(rcx, rdx);
   __ j(not_equal, &exit);
 
   __ movq(rax, Immediate(5));  // Test number.
   __ movl(rcx, Immediate(Smi::kMinValue));
   __ Integer32ToSmi(rcx, rcx);
   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
-  __ SmiCompare(rcx, rdx);
+  __ cmpq(rcx, rdx);
   __ j(not_equal, &exit);
 
   // Different target register.
@@ -337,35 +343,35 @@
   __ movl(rcx, Immediate(0));
   __ Integer32ToSmi(r8, rcx);
   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
-  __ SmiCompare(r8, rdx);
+  __ cmpq(r8, rdx);
   __ j(not_equal, &exit);
 
   __ movq(rax, Immediate(7));  // Test number.
   __ movl(rcx, Immediate(1024));
   __ Integer32ToSmi(r8, rcx);
   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
-  __ SmiCompare(r8, rdx);
+  __ cmpq(r8, rdx);
   __ j(not_equal, &exit);
 
   __ movq(rax, Immediate(8));  // Test number.
   __ movl(rcx, Immediate(-1));
   __ Integer32ToSmi(r8, rcx);
   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
-  __ SmiCompare(r8, rdx);
+  __ cmpq(r8, rdx);
   __ j(not_equal, &exit);
 
   __ movq(rax, Immediate(9));  // Test number.
   __ movl(rcx, Immediate(Smi::kMaxValue));
   __ Integer32ToSmi(r8, rcx);
   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
-  __ SmiCompare(r8, rdx);
+  __ cmpq(r8, rdx);
   __ j(not_equal, &exit);
 
   __ movq(rax, Immediate(10));  // Test number.
   __ movl(rcx, Immediate(Smi::kMinValue));
   __ Integer32ToSmi(r8, rcx);
   __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
-  __ SmiCompare(r8, rdx);
+  __ cmpq(r8, rdx);
   __ j(not_equal, &exit);
 
 
@@ -394,21 +400,22 @@
   __ movq(rcx, x, RelocInfo::NONE);
   __ movq(r11, rcx);
   __ Integer64PlusConstantToSmi(rdx, rcx, y);
-  __ SmiCompare(rdx, r8);
+  __ cmpq(rdx, r8);
   __ j(not_equal, exit);
 
   __ incq(rax);
-  __ SmiCompare(r11, rcx);
+  __ cmpq(r11, rcx);
   __ j(not_equal, exit);
 
   __ incq(rax);
   __ Integer64PlusConstantToSmi(rcx, rcx, y);
-  __ SmiCompare(rcx, r8);
+  __ cmpq(rcx, r8);
   __ j(not_equal, exit);
 }
 
 
 TEST(Integer64PlusConstantToSmi) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -452,6 +459,7 @@
 
 
 TEST(SmiCheck) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -660,14 +668,14 @@
     __ SmiNeg(r9, rcx, exit);
 
     __ incq(rax);
-    __ SmiCompare(r11, rcx);
+    __ cmpq(r11, rcx);
     __ j(not_equal, exit);
 
     __ incq(rax);
     __ SmiNeg(rcx, rcx, exit);
 
     __ incq(rax);
-    __ SmiCompare(r11, rcx);
+    __ cmpq(r11, rcx);
     __ j(not_equal, exit);
   } else {
     Label smi_ok, smi_ok2;
@@ -679,11 +687,11 @@
     __ jmp(exit);
     __ bind(&smi_ok);
     __ incq(rax);
-    __ SmiCompare(r9, r8);
+    __ cmpq(r9, r8);
     __ j(not_equal, exit);
 
     __ incq(rax);
-    __ SmiCompare(r11, rcx);
+    __ cmpq(r11, rcx);
     __ j(not_equal, exit);
 
     __ incq(rax);
@@ -691,13 +699,14 @@
     __ jmp(exit);
     __ bind(&smi_ok2);
     __ incq(rax);
-    __ SmiCompare(rcx, r8);
+    __ cmpq(rcx, r8);
     __ j(not_equal, exit);
   }
 }
 
 
 TEST(SmiNeg) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer =
@@ -751,12 +760,12 @@
 
   __ movl(rax, Immediate(id));  // Test number.
   __ SmiAdd(r9, rcx, rdx, exit);
-  __ SmiCompare(r9, r8);
+  __ cmpq(r9, r8);
   __ j(not_equal, exit);
 
   __ incq(rax);
   __ SmiAdd(rcx, rcx, rdx, exit);                              \
-  __ SmiCompare(rcx, r8);
+  __ cmpq(rcx, r8);
   __ j(not_equal, exit);
 
   __ movl(rcx, Immediate(first));
@@ -764,11 +773,11 @@
 
   __ incq(rax);
   __ SmiAddConstant(r9, rcx, Smi::FromInt(second));
-  __ SmiCompare(r9, r8);
+  __ cmpq(r9, r8);
   __ j(not_equal, exit);
 
   __ SmiAddConstant(rcx, rcx, Smi::FromInt(second));
-  __ SmiCompare(rcx, r8);
+  __ cmpq(rcx, r8);
   __ j(not_equal, exit);
 
   __ movl(rcx, Immediate(first));
@@ -776,16 +785,17 @@
 
   __ incq(rax);
   __ SmiAddConstant(r9, rcx, Smi::FromInt(second), exit);
-  __ SmiCompare(r9, r8);
+  __ cmpq(r9, r8);
   __ j(not_equal, exit);
 
   __ incq(rax);
   __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), exit);
-  __ SmiCompare(rcx, r8);
+  __ cmpq(rcx, r8);
   __ j(not_equal, exit);
 }
 
 TEST(SmiAdd) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -834,36 +844,36 @@
 
   __ movl(rax, Immediate(id));  // Test 0.
   __ SmiSub(r9, rcx, rdx, exit);
-  __ SmiCompare(r9, r8);
+  __ cmpq(r9, r8);
   __ j(not_equal, exit);
 
   __ incq(rax);  // Test 1.
   __ SmiSub(rcx, rcx, rdx, exit);
-  __ SmiCompare(rcx, r8);
+  __ cmpq(rcx, r8);
   __ j(not_equal, exit);
 
   __ Move(rcx, Smi::FromInt(first));
 
   __ incq(rax);  // Test 2.
   __ SmiSubConstant(r9, rcx, Smi::FromInt(second));
-  __ SmiCompare(r9, r8);
+  __ cmpq(r9, r8);
   __ j(not_equal, exit);
 
   __ incq(rax);  // Test 3.
   __ SmiSubConstant(rcx, rcx, Smi::FromInt(second));
-  __ SmiCompare(rcx, r8);
+  __ cmpq(rcx, r8);
   __ j(not_equal, exit);
 
   __ Move(rcx, Smi::FromInt(first));
 
   __ incq(rax);  // Test 4.
   __ SmiSubConstant(r9, rcx, Smi::FromInt(second), exit);
-  __ SmiCompare(r9, r8);
+  __ cmpq(r9, r8);
   __ j(not_equal, exit);
 
   __ incq(rax);  // Test 5.
   __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), exit);
-  __ SmiCompare(rcx, r8);
+  __ cmpq(rcx, r8);
   __ j(not_equal, exit);
 }
 
@@ -886,7 +896,7 @@
     __ jmp(exit);
     __ bind(&overflow_ok);
     __ incq(rax);
-    __ SmiCompare(rcx, r11);
+    __ cmpq(rcx, r11);
     __ j(not_equal, exit);
   }
 
@@ -897,7 +907,7 @@
     __ jmp(exit);
     __ bind(&overflow_ok);
     __ incq(rax);
-    __ SmiCompare(rcx, r11);
+    __ cmpq(rcx, r11);
     __ j(not_equal, exit);
   }
 
@@ -909,7 +919,7 @@
     __ jmp(exit);
     __ bind(&overflow_ok);
     __ incq(rax);
-    __ SmiCompare(rcx, r11);
+    __ cmpq(rcx, r11);
     __ j(not_equal, exit);
   }
 
@@ -920,7 +930,7 @@
     __ jmp(exit);
     __ bind(&overflow_ok);
     __ incq(rax);
-    __ SmiCompare(rcx, r11);
+    __ cmpq(rcx, r11);
     __ j(not_equal, exit);
   }
 
@@ -933,7 +943,7 @@
     __ jmp(exit);
     __ bind(&overflow_ok);
     __ incq(rax);
-    __ SmiCompare(rcx, r11);
+    __ cmpq(rcx, r11);
     __ j(not_equal, exit);
   }
 
@@ -944,7 +954,7 @@
     __ jmp(exit);
     __ bind(&overflow_ok);
     __ incq(rax);
-    __ SmiCompare(rcx, r11);
+    __ cmpq(rcx, r11);
     __ j(not_equal, exit);
   }
 
@@ -956,7 +966,7 @@
     __ jmp(exit);
     __ bind(&overflow_ok);
     __ incq(rax);
-    __ SmiCompare(rcx, r11);
+    __ cmpq(rcx, r11);
     __ j(not_equal, exit);
   }
 
@@ -967,13 +977,14 @@
     __ jmp(exit);
     __ bind(&overflow_ok);
     __ incq(rax);
-    __ SmiCompare(rcx, r11);
+    __ cmpq(rcx, r11);
     __ j(not_equal, exit);
   }
 }
 
 
 TEST(SmiSub) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer =
@@ -1032,15 +1043,15 @@
     __ Move(r8, Smi::FromIntptr(result));
     __ SmiMul(r9, rcx, rdx, exit);
     __ incq(rax);
-    __ SmiCompare(r11, rcx);
+    __ cmpq(r11, rcx);
     __ j(not_equal, exit);
     __ incq(rax);
-    __ SmiCompare(r9, r8);
+    __ cmpq(r9, r8);
     __ j(not_equal, exit);
 
     __ incq(rax);
     __ SmiMul(rcx, rcx, rdx, exit);
-    __ SmiCompare(rcx, r8);
+    __ cmpq(rcx, r8);
     __ j(not_equal, exit);
   } else {
     __ movl(rax, Immediate(id + 8));
@@ -1049,7 +1060,7 @@
     __ jmp(exit);
     __ bind(&overflow_ok);
     __ incq(rax);
-    __ SmiCompare(r11, rcx);
+    __ cmpq(r11, rcx);
     __ j(not_equal, exit);
     __ incq(rax);
     __ SmiMul(rcx, rcx, rdx, &overflow_ok2);
@@ -1057,13 +1068,14 @@
     __ bind(&overflow_ok2);
     // 31-bit version doesn't preserve rcx on failure.
     // __ incq(rax);
-    // __ SmiCompare(r11, rcx);
+    // __ cmpq(r11, rcx);
     // __ j(not_equal, exit);
   }
 }
 
 
 TEST(SmiMul) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -1120,30 +1132,30 @@
   if (!fraction && !overflow && !negative_zero && !division_by_zero) {
     // Division succeeds
     __ movq(rcx, r11);
-    __ movq(r12, Immediate(id));
+    __ movq(r15, Immediate(id));
     int result = x / y;
     __ Move(r8, Smi::FromInt(result));
     __ SmiDiv(r9, rcx, r14, exit);
     // Might have destroyed rcx and r14.
-    __ incq(r12);
-    __ SmiCompare(r9, r8);
+    __ incq(r15);
+    __ cmpq(r9, r8);
     __ j(not_equal, exit);
 
-    __ incq(r12);
+    __ incq(r15);
     __ movq(rcx, r11);
     __ Move(r14, Smi::FromInt(y));
-    __ SmiCompare(rcx, r11);
+    __ cmpq(rcx, r11);
     __ j(not_equal, exit);
 
-    __ incq(r12);
+    __ incq(r15);
     __ SmiDiv(rcx, rcx, r14, exit);
 
-    __ incq(r12);
-    __ SmiCompare(rcx, r8);
+    __ incq(r15);
+    __ cmpq(rcx, r8);
     __ j(not_equal, exit);
   } else {
     // Division fails.
-    __ movq(r12, Immediate(id + 8));
+    __ movq(r15, Immediate(id + 8));
 
     Label fail_ok, fail_ok2;
     __ movq(rcx, r11);
@@ -1151,23 +1163,24 @@
     __ jmp(exit);
     __ bind(&fail_ok);
 
-    __ incq(r12);
-    __ SmiCompare(rcx, r11);
+    __ incq(r15);
+    __ cmpq(rcx, r11);
     __ j(not_equal, exit);
 
-    __ incq(r12);
+    __ incq(r15);
     __ SmiDiv(rcx, rcx, r14, &fail_ok2);
     __ jmp(exit);
     __ bind(&fail_ok2);
 
-    __ incq(r12);
-    __ SmiCompare(rcx, r11);
+    __ incq(r15);
+    __ cmpq(rcx, r11);
     __ j(not_equal, exit);
   }
 }
 
 
 TEST(SmiDiv) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer =
@@ -1184,7 +1197,7 @@
   Label exit;
 
   __ push(r14);
-  __ push(r12);
+  __ push(r15);
   TestSmiDiv(masm, &exit, 0x10, 1, 1);
   TestSmiDiv(masm, &exit, 0x20, 1, 0);
   TestSmiDiv(masm, &exit, 0x30, -1, 0);
@@ -1206,10 +1219,10 @@
   TestSmiDiv(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
   TestSmiDiv(masm, &exit, 0x140, Smi::kMinValue, -1);
 
-  __ xor_(r12, r12);  // Success.
+  __ xor_(r15, r15);  // Success.
   __ bind(&exit);
-  __ movq(rax, r12);
-  __ pop(r12);
+  __ movq(rax, r15);
+  __ pop(r15);
   __ pop(r14);
   ExitCode(masm);
   __ ret(0);
@@ -1232,51 +1245,52 @@
   __ Move(r14, Smi::FromInt(y));
   if (!division_overflow && !negative_zero && !division_by_zero) {
     // Modulo succeeds
-    __ movq(r12, Immediate(id));
+    __ movq(r15, Immediate(id));
     int result = x % y;
     __ Move(r8, Smi::FromInt(result));
     __ SmiMod(r9, rcx, r14, exit);
 
-    __ incq(r12);
-    __ SmiCompare(r9, r8);
+    __ incq(r15);
+    __ cmpq(r9, r8);
     __ j(not_equal, exit);
 
-    __ incq(r12);
-    __ SmiCompare(rcx, r11);
+    __ incq(r15);
+    __ cmpq(rcx, r11);
     __ j(not_equal, exit);
 
-    __ incq(r12);
+    __ incq(r15);
     __ SmiMod(rcx, rcx, r14, exit);
 
-    __ incq(r12);
-    __ SmiCompare(rcx, r8);
+    __ incq(r15);
+    __ cmpq(rcx, r8);
     __ j(not_equal, exit);
   } else {
     // Modulo fails.
-    __ movq(r12, Immediate(id + 8));
+    __ movq(r15, Immediate(id + 8));
 
     Label fail_ok, fail_ok2;
     __ SmiMod(r9, rcx, r14, &fail_ok);
     __ jmp(exit);
     __ bind(&fail_ok);
 
-    __ incq(r12);
-    __ SmiCompare(rcx, r11);
+    __ incq(r15);
+    __ cmpq(rcx, r11);
     __ j(not_equal, exit);
 
-    __ incq(r12);
+    __ incq(r15);
     __ SmiMod(rcx, rcx, r14, &fail_ok2);
     __ jmp(exit);
     __ bind(&fail_ok2);
 
-    __ incq(r12);
-    __ SmiCompare(rcx, r11);
+    __ incq(r15);
+    __ cmpq(rcx, r11);
     __ j(not_equal, exit);
   }
 }
 
 
 TEST(SmiMod) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer =
@@ -1293,7 +1307,7 @@
   Label exit;
 
   __ push(r14);
-  __ push(r12);
+  __ push(r15);
   TestSmiMod(masm, &exit, 0x10, 1, 1);
   TestSmiMod(masm, &exit, 0x20, 1, 0);
   TestSmiMod(masm, &exit, 0x30, -1, 0);
@@ -1315,10 +1329,10 @@
   TestSmiMod(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
   TestSmiMod(masm, &exit, 0x140, Smi::kMinValue, -1);
 
-  __ xor_(r12, r12);  // Success.
+  __ xor_(r15, r15);  // Success.
   __ bind(&exit);
-  __ movq(rax, r12);
-  __ pop(r12);
+  __ movq(rax, r15);
+  __ pop(r15);
   __ pop(r14);
   ExitCode(masm);
   __ ret(0);
@@ -1340,7 +1354,7 @@
     ASSERT(index.reg.is(rcx) || index.reg.is(rdx));
     __ shl(index.reg, Immediate(index.scale));
     __ Set(r8, static_cast<intptr_t>(x) << i);
-    __ SmiCompare(index.reg, r8);
+    __ cmpq(index.reg, r8);
     __ j(not_equal, exit);
     __ incq(rax);
     __ Move(rcx, Smi::FromInt(x));
@@ -1348,7 +1362,7 @@
     ASSERT(index.reg.is(rcx));
     __ shl(rcx, Immediate(index.scale));
     __ Set(r8, static_cast<intptr_t>(x) << i);
-    __ SmiCompare(rcx, r8);
+    __ cmpq(rcx, r8);
     __ j(not_equal, exit);
     __ incq(rax);
 
@@ -1357,7 +1371,7 @@
     ASSERT(index.reg.is(rcx) || index.reg.is(rdx));
     __ shl(index.reg, Immediate(index.scale));
     __ Set(r8, static_cast<intptr_t>(-x) << i);
-    __ SmiCompare(index.reg, r8);
+    __ cmpq(index.reg, r8);
     __ j(not_equal, exit);
     __ incq(rax);
     __ Move(rcx, Smi::FromInt(x));
@@ -1365,13 +1379,14 @@
     ASSERT(index.reg.is(rcx));
     __ shl(rcx, Immediate(index.scale));
     __ Set(r8, static_cast<intptr_t>(-x) << i);
-    __ SmiCompare(rcx, r8);
+    __ cmpq(rcx, r8);
     __ j(not_equal, exit);
     __ incq(rax);
   }
 }
 
 TEST(SmiIndex) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer =
@@ -1414,7 +1429,7 @@
   __ SelectNonSmi(r9, rcx, rdx, exit);
 
   __ incq(rax);
-  __ SmiCompare(r9, rdx);
+  __ cmpq(r9, rdx);
   __ j(not_equal, exit);
 
   __ incq(rax);
@@ -1424,7 +1439,7 @@
   __ SelectNonSmi(r9, rcx, rdx, exit);
 
   __ incq(rax);
-  __ SmiCompare(r9, rcx);
+  __ cmpq(r9, rcx);
   __ j(not_equal, exit);
 
   __ incq(rax);
@@ -1440,6 +1455,7 @@
 
 
 TEST(SmiSelectNonSmi) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer =
@@ -1488,36 +1504,37 @@
   __ Move(rdx, Smi::FromInt(y));
   __ Move(r8, Smi::FromInt(result));
   __ SmiAnd(r9, rcx, rdx);
-  __ SmiCompare(r8, r9);
+  __ cmpq(r8, r9);
   __ j(not_equal, exit);
 
   __ incq(rax);
-  __ SmiCompare(r11, rcx);
+  __ cmpq(r11, rcx);
   __ j(not_equal, exit);
 
   __ incq(rax);
   __ SmiAnd(rcx, rcx, rdx);
-  __ SmiCompare(r8, rcx);
+  __ cmpq(r8, rcx);
   __ j(not_equal, exit);
 
   __ movq(rcx, r11);
   __ incq(rax);
   __ SmiAndConstant(r9, rcx, Smi::FromInt(y));
-  __ SmiCompare(r8, r9);
+  __ cmpq(r8, r9);
   __ j(not_equal, exit);
 
   __ incq(rax);
-  __ SmiCompare(r11, rcx);
+  __ cmpq(r11, rcx);
   __ j(not_equal, exit);
 
   __ incq(rax);
   __ SmiAndConstant(rcx, rcx, Smi::FromInt(y));
-  __ SmiCompare(r8, rcx);
+  __ cmpq(r8, rcx);
   __ j(not_equal, exit);
 }
 
 
 TEST(SmiAnd) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer =
@@ -1568,36 +1585,37 @@
   __ Move(rdx, Smi::FromInt(y));
   __ Move(r8, Smi::FromInt(result));
   __ SmiOr(r9, rcx, rdx);
-  __ SmiCompare(r8, r9);
+  __ cmpq(r8, r9);
   __ j(not_equal, exit);
 
   __ incq(rax);
-  __ SmiCompare(r11, rcx);
+  __ cmpq(r11, rcx);
   __ j(not_equal, exit);
 
   __ incq(rax);
   __ SmiOr(rcx, rcx, rdx);
-  __ SmiCompare(r8, rcx);
+  __ cmpq(r8, rcx);
   __ j(not_equal, exit);
 
   __ movq(rcx, r11);
   __ incq(rax);
   __ SmiOrConstant(r9, rcx, Smi::FromInt(y));
-  __ SmiCompare(r8, r9);
+  __ cmpq(r8, r9);
   __ j(not_equal, exit);
 
   __ incq(rax);
-  __ SmiCompare(r11, rcx);
+  __ cmpq(r11, rcx);
   __ j(not_equal, exit);
 
   __ incq(rax);
   __ SmiOrConstant(rcx, rcx, Smi::FromInt(y));
-  __ SmiCompare(r8, rcx);
+  __ cmpq(r8, rcx);
   __ j(not_equal, exit);
 }
 
 
 TEST(SmiOr) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer =
@@ -1650,36 +1668,37 @@
   __ Move(rdx, Smi::FromInt(y));
   __ Move(r8, Smi::FromInt(result));
   __ SmiXor(r9, rcx, rdx);
-  __ SmiCompare(r8, r9);
+  __ cmpq(r8, r9);
   __ j(not_equal, exit);
 
   __ incq(rax);
-  __ SmiCompare(r11, rcx);
+  __ cmpq(r11, rcx);
   __ j(not_equal, exit);
 
   __ incq(rax);
   __ SmiXor(rcx, rcx, rdx);
-  __ SmiCompare(r8, rcx);
+  __ cmpq(r8, rcx);
   __ j(not_equal, exit);
 
   __ movq(rcx, r11);
   __ incq(rax);
   __ SmiXorConstant(r9, rcx, Smi::FromInt(y));
-  __ SmiCompare(r8, r9);
+  __ cmpq(r8, r9);
   __ j(not_equal, exit);
 
   __ incq(rax);
-  __ SmiCompare(r11, rcx);
+  __ cmpq(r11, rcx);
   __ j(not_equal, exit);
 
   __ incq(rax);
   __ SmiXorConstant(rcx, rcx, Smi::FromInt(y));
-  __ SmiCompare(r8, rcx);
+  __ cmpq(r8, rcx);
   __ j(not_equal, exit);
 }
 
 
 TEST(SmiXor) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer =
@@ -1731,21 +1750,22 @@
   __ movq(r11, rcx);
 
   __ SmiNot(r9, rcx);
-  __ SmiCompare(r9, r8);
+  __ cmpq(r9, r8);
   __ j(not_equal, exit);
 
   __ incq(rax);
-  __ SmiCompare(r11, rcx);
+  __ cmpq(r11, rcx);
   __ j(not_equal, exit);
 
   __ incq(rax);
   __ SmiNot(rcx, rcx);
-  __ SmiCompare(rcx, r8);
+  __ cmpq(rcx, r8);
   __ j(not_equal, exit);
 }
 
 
 TEST(SmiNot) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer =
@@ -1797,7 +1817,7 @@
     __ SmiShiftLeftConstant(r9, rcx, shift);
 
     __ incq(rax);
-    __ SmiCompare(r9, r8);
+    __ cmpq(r9, r8);
     __ j(not_equal, exit);
 
     __ incq(rax);
@@ -1805,7 +1825,7 @@
     __ SmiShiftLeftConstant(rcx, rcx, shift);
 
     __ incq(rax);
-    __ SmiCompare(rcx, r8);
+    __ cmpq(rcx, r8);
     __ j(not_equal, exit);
 
     __ incq(rax);
@@ -1814,7 +1834,7 @@
     __ SmiShiftLeft(r9, rdx, rcx);
 
     __ incq(rax);
-    __ SmiCompare(r9, r8);
+    __ cmpq(r9, r8);
     __ j(not_equal, exit);
 
     __ incq(rax);
@@ -1823,7 +1843,7 @@
     __ SmiShiftLeft(r9, rdx, r11);
 
     __ incq(rax);
-    __ SmiCompare(r9, r8);
+    __ cmpq(r9, r8);
     __ j(not_equal, exit);
 
     __ incq(rax);
@@ -1832,7 +1852,7 @@
     __ SmiShiftLeft(rdx, rdx, r11);
 
     __ incq(rax);
-    __ SmiCompare(rdx, r8);
+    __ cmpq(rdx, r8);
     __ j(not_equal, exit);
 
     __ incq(rax);
@@ -1841,6 +1861,7 @@
 
 
 TEST(SmiShiftLeft) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer =
@@ -1893,7 +1914,7 @@
       __ SmiShiftLogicalRightConstant(r9, rcx, shift, exit);
 
       __ incq(rax);
-      __ SmiCompare(r9, r8);
+      __ cmpq(r9, r8);
       __ j(not_equal, exit);
 
       __ incq(rax);
@@ -1902,7 +1923,7 @@
       __ SmiShiftLogicalRight(r9, rdx, rcx, exit);
 
       __ incq(rax);
-      __ SmiCompare(r9, r8);
+      __ cmpq(r9, r8);
       __ j(not_equal, exit);
 
       __ incq(rax);
@@ -1911,7 +1932,7 @@
       __ SmiShiftLogicalRight(r9, rdx, r11, exit);
 
       __ incq(rax);
-      __ SmiCompare(r9, r8);
+      __ cmpq(r9, r8);
       __ j(not_equal, exit);
 
       __ incq(rax);
@@ -1925,7 +1946,7 @@
       __ bind(&fail_ok);
 
       __ incq(rax);
-      __ SmiCompare(rcx, r11);
+      __ cmpq(rcx, r11);
       __ j(not_equal, exit);
 
       __ incq(rax);
@@ -1936,7 +1957,7 @@
       __ bind(&fail_ok3);
 
       __ incq(rax);
-      __ SmiCompare(rcx, r11);
+      __ cmpq(rcx, r11);
       __ j(not_equal, exit);
 
       __ addq(rax, Immediate(3));
@@ -1946,6 +1967,7 @@
 
 
 TEST(SmiShiftLogicalRight) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer =
@@ -1997,7 +2019,7 @@
     __ Move(rcx, Smi::FromInt(x));
     __ SmiShiftArithmeticRightConstant(rcx, rcx, shift);
 
-    __ SmiCompare(rcx, r8);
+    __ cmpq(rcx, r8);
     __ j(not_equal, exit);
 
     __ incq(rax);
@@ -2005,7 +2027,7 @@
     __ Move(r11, Smi::FromInt(shift));
     __ SmiShiftArithmeticRight(rdx, rdx, r11);
 
-    __ SmiCompare(rdx, r8);
+    __ cmpq(rdx, r8);
     __ j(not_equal, exit);
 
     __ incq(rax);
@@ -2014,6 +2036,7 @@
 
 
 TEST(SmiShiftArithmeticRight) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer =
@@ -2062,14 +2085,14 @@
     __ Move(rcx, Smi::FromInt(x));
     __ movq(r11, rcx);
     __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rcx, power);
-    __ SmiCompare(rdx, r8);
+    __ cmpq(rdx, r8);
     __ j(not_equal, exit);
     __ incq(rax);
-    __ SmiCompare(r11, rcx);  // rcx unchanged.
+    __ cmpq(r11, rcx);  // rcx unchanged.
     __ j(not_equal, exit);
     __ incq(rax);
     __ PositiveSmiTimesPowerOfTwoToInteger64(rcx, rcx, power);
-    __ SmiCompare(rdx, r8);
+    __ cmpq(rdx, r8);
     __ j(not_equal, exit);
     __ incq(rax);
   }
@@ -2077,10 +2100,11 @@
 
 
 TEST(PositiveSmiTimesPowerOfTwoToInteger64) {
+  v8::internal::V8::Initialize(NULL);
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer =
-      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
+      static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 4,
                                       &actual_size,
                                       true));
   CHECK(buffer);
@@ -2116,6 +2140,7 @@
 
 
 TEST(OperandOffset) {
+  v8::internal::V8::Initialize(NULL);
   int data[256];
   for (int i = 0; i < 256; i++) { data[i] = i * 0x01010101; }
 
@@ -2150,7 +2175,7 @@
   __ push(Immediate(0x108));
   __ push(Immediate(0x109));  // <-- rsp
   // rbp = rsp[9]
-  // r12 = rsp[3]
+  // r15 = rsp[3]
   // rbx = rsp[5]
   // r13 = rsp[7]
   __ lea(r14, Operand(rsp, 3 * kPointerSize));
diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc
index 3e3175e..6d1b5ce 100644
--- a/test/cctest/test-mark-compact.cc
+++ b/test/cctest/test-mark-compact.cc
@@ -31,7 +31,6 @@
 
 #include "global-handles.h"
 #include "snapshot.h"
-#include "top.h"
 #include "cctest.h"
 
 using namespace v8::internal;
@@ -79,7 +78,7 @@
   // from new space.
   FLAG_gc_global = true;
   FLAG_always_compact = true;
-  Heap::ConfigureHeap(2*256*KB, 4*MB, 4*MB);
+  HEAP->ConfigureHeap(2*256*KB, 4*MB, 4*MB);
 
   InitializeVM();
 
@@ -87,25 +86,25 @@
 
   // Allocate a fixed array in the new space.
   int array_size =
-      (Heap::MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) /
+      (HEAP->MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) /
       (kPointerSize * 4);
-  Object* obj = Heap::AllocateFixedArray(array_size)->ToObjectChecked();
+  Object* obj = HEAP->AllocateFixedArray(array_size)->ToObjectChecked();
 
   Handle<FixedArray> array(FixedArray::cast(obj));
 
   // Array should be in the new space.
-  CHECK(Heap::InSpace(*array, NEW_SPACE));
+  CHECK(HEAP->InSpace(*array, NEW_SPACE));
 
   // Call the m-c collector, so array becomes an old object.
-  Heap::CollectGarbage(OLD_POINTER_SPACE);
+  HEAP->CollectGarbage(OLD_POINTER_SPACE);
 
   // Array now sits in the old space
-  CHECK(Heap::InSpace(*array, OLD_POINTER_SPACE));
+  CHECK(HEAP->InSpace(*array, OLD_POINTER_SPACE));
 }
 
 
 TEST(NoPromotion) {
-  Heap::ConfigureHeap(2*256*KB, 4*MB, 4*MB);
+  HEAP->ConfigureHeap(2*256*KB, 4*MB, 4*MB);
 
   // Test the situation that some objects in new space are promoted to
   // the old space
@@ -114,23 +113,23 @@
   v8::HandleScope sc;
 
   // Do a mark compact GC to shrink the heap.
-  Heap::CollectGarbage(OLD_POINTER_SPACE);
+  HEAP->CollectGarbage(OLD_POINTER_SPACE);
 
   // Allocate a big Fixed array in the new space.
-  int size = (Heap::MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) /
+  int size = (HEAP->MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) /
       kPointerSize;
-  Object* obj = Heap::AllocateFixedArray(size)->ToObjectChecked();
+  Object* obj = HEAP->AllocateFixedArray(size)->ToObjectChecked();
 
   Handle<FixedArray> array(FixedArray::cast(obj));
 
   // Array still stays in the new space.
-  CHECK(Heap::InSpace(*array, 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;
-    { MaybeObject* maybe_obj = Heap::AllocateFixedArray(100, TENURED);
+    { MaybeObject* maybe_obj = HEAP->AllocateFixedArray(100, TENURED);
       if (!maybe_obj->ToObject(&obj)) break;
     }
 
@@ -139,10 +138,10 @@
   }
 
   // Call mark compact GC, and it should pass.
-  Heap::CollectGarbage(OLD_POINTER_SPACE);
+  HEAP->CollectGarbage(OLD_POINTER_SPACE);
 
   // array should not be promoted because the old space is full.
-  CHECK(Heap::InSpace(*array, NEW_SPACE));
+  CHECK(HEAP->InSpace(*array, NEW_SPACE));
 }
 
 
@@ -151,90 +150,86 @@
 
   v8::HandleScope sc;
   // call mark-compact when heap is empty
-  Heap::CollectGarbage(OLD_POINTER_SPACE);
+  HEAP->CollectGarbage(OLD_POINTER_SPACE);
 
   // keep allocating garbage in new space until it fails
   const int ARRAY_SIZE = 100;
   Object* array;
   MaybeObject* maybe_array;
   do {
-    maybe_array = Heap::AllocateFixedArray(ARRAY_SIZE);
+    maybe_array = HEAP->AllocateFixedArray(ARRAY_SIZE);
   } while (maybe_array->ToObject(&array));
-  Heap::CollectGarbage(NEW_SPACE);
+  HEAP->CollectGarbage(NEW_SPACE);
 
-  array = Heap::AllocateFixedArray(ARRAY_SIZE)->ToObjectChecked();
+  array = HEAP->AllocateFixedArray(ARRAY_SIZE)->ToObjectChecked();
 
   // keep allocating maps until it fails
   Object* mapp;
   MaybeObject* maybe_mapp;
   do {
-    maybe_mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+    maybe_mapp = HEAP->AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
   } while (maybe_mapp->ToObject(&mapp));
-  Heap::CollectGarbage(MAP_SPACE);
-  mapp = Heap::AllocateMap(JS_OBJECT_TYPE,
+  HEAP->CollectGarbage(MAP_SPACE);
+  mapp = HEAP->AllocateMap(JS_OBJECT_TYPE,
                            JSObject::kHeaderSize)->ToObjectChecked();
 
   // allocate a garbage
   String* func_name =
-      String::cast(Heap::LookupAsciiSymbol("theFunction")->ToObjectChecked());
+      String::cast(HEAP->LookupAsciiSymbol("theFunction")->ToObjectChecked());
   SharedFunctionInfo* function_share = SharedFunctionInfo::cast(
-      Heap::AllocateSharedFunctionInfo(func_name)->ToObjectChecked());
+      HEAP->AllocateSharedFunctionInfo(func_name)->ToObjectChecked());
   JSFunction* function = JSFunction::cast(
-      Heap::AllocateFunction(*Top::function_map(),
+      HEAP->AllocateFunction(*Isolate::Current()->function_map(),
                              function_share,
-                             Heap::undefined_value())->ToObjectChecked());
+                             HEAP->undefined_value())->ToObjectChecked());
   Map* initial_map =
-      Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE,
+      Map::cast(HEAP->AllocateMap(JS_OBJECT_TYPE,
                                   JSObject::kHeaderSize)->ToObjectChecked());
   function->set_initial_map(initial_map);
-  Top::context()->global()->SetProperty(func_name,
-                                        function,
-                                        NONE,
-                                        kNonStrictMode)->ToObjectChecked();
+  Isolate::Current()->context()->global()->SetProperty(
+      func_name, function, NONE, kNonStrictMode)->ToObjectChecked();
 
-  JSObject* obj =
-      JSObject::cast(Heap::AllocateJSObject(function)->ToObjectChecked());
-  Heap::CollectGarbage(OLD_POINTER_SPACE);
+  JSObject* obj = JSObject::cast(
+      HEAP->AllocateJSObject(function)->ToObjectChecked());
+  HEAP->CollectGarbage(OLD_POINTER_SPACE);
 
   func_name =
-      String::cast(Heap::LookupAsciiSymbol("theFunction")->ToObjectChecked());
-  CHECK(Top::context()->global()->HasLocalProperty(func_name));
-  Object* func_value =
-      Top::context()->global()->GetProperty(func_name)->ToObjectChecked();
+      String::cast(HEAP->LookupAsciiSymbol("theFunction")->ToObjectChecked());
+  CHECK(Isolate::Current()->context()->global()->HasLocalProperty(func_name));
+  Object* func_value = Isolate::Current()->context()->global()->
+      GetProperty(func_name)->ToObjectChecked();
   CHECK(func_value->IsJSFunction());
   function = JSFunction::cast(func_value);
 
-  obj = JSObject::cast(Heap::AllocateJSObject(function)->ToObjectChecked());
+  obj = JSObject::cast(HEAP->AllocateJSObject(function)->ToObjectChecked());
   String* obj_name =
-      String::cast(Heap::LookupAsciiSymbol("theObject")->ToObjectChecked());
-  Top::context()->global()->SetProperty(obj_name,
-                                        obj,
-                                        NONE,
-                                        kNonStrictMode)->ToObjectChecked();
+      String::cast(HEAP->LookupAsciiSymbol("theObject")->ToObjectChecked());
+  Isolate::Current()->context()->global()->SetProperty(
+      obj_name, obj, NONE, kNonStrictMode)->ToObjectChecked();
   String* prop_name =
-      String::cast(Heap::LookupAsciiSymbol("theSlot")->ToObjectChecked());
+      String::cast(HEAP->LookupAsciiSymbol("theSlot")->ToObjectChecked());
   obj->SetProperty(prop_name,
                    Smi::FromInt(23),
                    NONE,
                    kNonStrictMode)->ToObjectChecked();
 
-  Heap::CollectGarbage(OLD_POINTER_SPACE);
+  HEAP->CollectGarbage(OLD_POINTER_SPACE);
 
   obj_name =
-      String::cast(Heap::LookupAsciiSymbol("theObject")->ToObjectChecked());
-  CHECK(Top::context()->global()->HasLocalProperty(obj_name));
-  CHECK(Top::context()->global()->
-            GetProperty(obj_name)->ToObjectChecked()->IsJSObject());
-  obj = JSObject::cast(
-      Top::context()->global()->GetProperty(obj_name)->ToObjectChecked());
+      String::cast(HEAP->LookupAsciiSymbol("theObject")->ToObjectChecked());
+  CHECK(Isolate::Current()->context()->global()->HasLocalProperty(obj_name));
+  CHECK(Isolate::Current()->context()->global()->
+        GetProperty(obj_name)->ToObjectChecked()->IsJSObject());
+  obj = JSObject::cast(Isolate::Current()->context()->global()->
+                       GetProperty(obj_name)->ToObjectChecked());
   prop_name =
-      String::cast(Heap::LookupAsciiSymbol("theSlot")->ToObjectChecked());
-  CHECK(obj->GetProperty(prop_name)->ToObjectChecked() == Smi::FromInt(23));
+      String::cast(HEAP->LookupAsciiSymbol("theSlot")->ToObjectChecked());
+  CHECK(obj->GetProperty(prop_name) == Smi::FromInt(23));
 }
 
 
 static Handle<Map> CreateMap() {
-  return Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+  return FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
 }
 
 
@@ -246,20 +241,20 @@
     v8::HandleScope sc;
     // keep allocating maps while pointers are still encodable and thus
     // mark compact is permitted.
-    Handle<JSObject> root = Factory::NewJSObjectFromMap(CreateMap());
+    Handle<JSObject> root = FACTORY->NewJSObjectFromMap(CreateMap());
     do {
       Handle<Map> map = CreateMap();
       map->set_prototype(*root);
-      root = Factory::NewJSObjectFromMap(map);
-    } while (Heap::map_space()->MapPointersEncodable());
+      root = FACTORY->NewJSObjectFromMap(map);
+    } while (HEAP->map_space()->MapPointersEncodable());
   }
   // Now, as we don't have any handles to just allocated maps, we should
   // be able to trigger map compaction.
   // To give an additional chance to fail, try to force compaction which
   // should be impossible right now.
-  Heap::CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
   // And now map pointers should be encodable again.
-  CHECK(Heap::map_space()->MapPointersEncodable());
+  CHECK(HEAP->map_space()->MapPointersEncodable());
 }
 
 
@@ -281,16 +276,16 @@
 TEST(GCCallback) {
   InitializeVM();
 
-  Heap::SetGlobalGCPrologueCallback(&GCPrologueCallbackFunc);
-  Heap::SetGlobalGCEpilogueCallback(&GCEpilogueCallbackFunc);
+  HEAP->SetGlobalGCPrologueCallback(&GCPrologueCallbackFunc);
+  HEAP->SetGlobalGCEpilogueCallback(&GCEpilogueCallbackFunc);
 
   // Scavenge does not call GC callback functions.
-  Heap::PerformScavenge();
+  HEAP->PerformScavenge();
 
   CHECK_EQ(0, gc_starts);
   CHECK_EQ(gc_ends, gc_starts);
 
-  Heap::CollectGarbage(OLD_POINTER_SPACE);
+  HEAP->CollectGarbage(OLD_POINTER_SPACE);
   CHECK_EQ(1, gc_starts);
   CHECK_EQ(gc_ends, gc_starts);
 }
@@ -298,39 +293,51 @@
 
 static int NumberOfWeakCalls = 0;
 static void WeakPointerCallback(v8::Persistent<v8::Value> handle, void* id) {
+  ASSERT(id == reinterpret_cast<void*>(1234));
   NumberOfWeakCalls++;
   handle.Dispose();
 }
 
 TEST(ObjectGroups) {
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
   InitializeVM();
 
   NumberOfWeakCalls = 0;
   v8::HandleScope handle_scope;
 
   Handle<Object> g1s1 =
-    GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked());
+      global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
   Handle<Object> g1s2 =
-    GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked());
-  GlobalHandles::MakeWeak(g1s1.location(),
-                          reinterpret_cast<void*>(1234),
-                          &WeakPointerCallback);
-  GlobalHandles::MakeWeak(g1s2.location(),
-                          reinterpret_cast<void*>(1234),
-                          &WeakPointerCallback);
+    global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
+  Handle<Object> g1c1 =
+    global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
+  global_handles->MakeWeak(g1s1.location(),
+                           reinterpret_cast<void*>(1234),
+                           &WeakPointerCallback);
+  global_handles->MakeWeak(g1s2.location(),
+                           reinterpret_cast<void*>(1234),
+                           &WeakPointerCallback);
+  global_handles->MakeWeak(g1c1.location(),
+                           reinterpret_cast<void*>(1234),
+                           &WeakPointerCallback);
 
   Handle<Object> g2s1 =
-    GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked());
+      global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
   Handle<Object> g2s2 =
-    GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked());
-  GlobalHandles::MakeWeak(g2s1.location(),
-                          reinterpret_cast<void*>(1234),
-                          &WeakPointerCallback);
-  GlobalHandles::MakeWeak(g2s2.location(),
-                          reinterpret_cast<void*>(1234),
-                          &WeakPointerCallback);
+    global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
+  Handle<Object> g2c1 =
+    global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
+  global_handles->MakeWeak(g2s1.location(),
+                           reinterpret_cast<void*>(1234),
+                           &WeakPointerCallback);
+  global_handles->MakeWeak(g2s2.location(),
+                           reinterpret_cast<void*>(1234),
+                           &WeakPointerCallback);
+  global_handles->MakeWeak(g2c1.location(),
+                           reinterpret_cast<void*>(1234),
+                           &WeakPointerCallback);
 
-  Handle<Object> root = GlobalHandles::Create(*g1s1);  // make a root.
+  Handle<Object> root = global_handles->Create(*g1s1);  // make a root.
 
   // Connect group 1 and 2, make a cycle.
   Handle<FixedArray>::cast(g1s2)->set(0, *g2s2);
@@ -338,31 +345,58 @@
 
   {
     Object** g1_objects[] = { g1s1.location(), g1s2.location() };
+    Object** g1_children[] = { g1c1.location() };
     Object** g2_objects[] = { g2s1.location(), g2s2.location() };
-    GlobalHandles::AddGroup(g1_objects, 2);
-    GlobalHandles::AddGroup(g2_objects, 2);
+    Object** g2_children[] = { g2c1.location() };
+    global_handles->AddObjectGroup(g1_objects, 2, NULL);
+    global_handles->AddImplicitReferences(HeapObject::cast(*g1s1),
+                                          g1_children, 1);
+    global_handles->AddObjectGroup(g2_objects, 2, NULL);
+    global_handles->AddImplicitReferences(HeapObject::cast(*g2s2),
+                                          g2_children, 1);
   }
   // Do a full GC
-  Heap::CollectGarbage(OLD_POINTER_SPACE);
+  HEAP->CollectGarbage(OLD_POINTER_SPACE);
 
   // All object should be alive.
   CHECK_EQ(0, NumberOfWeakCalls);
 
   // Weaken the root.
-  GlobalHandles::MakeWeak(root.location(),
-                          reinterpret_cast<void*>(1234),
-                          &WeakPointerCallback);
+  global_handles->MakeWeak(root.location(),
+                           reinterpret_cast<void*>(1234),
+                           &WeakPointerCallback);
+  // But make children strong roots---all the objects (except for children)
+  // should be collectable now.
+  global_handles->ClearWeakness(g1c1.location());
+  global_handles->ClearWeakness(g2c1.location());
 
   // Groups are deleted, rebuild groups.
   {
     Object** g1_objects[] = { g1s1.location(), g1s2.location() };
+    Object** g1_children[] = { g1c1.location() };
     Object** g2_objects[] = { g2s1.location(), g2s2.location() };
-    GlobalHandles::AddGroup(g1_objects, 2);
-    GlobalHandles::AddGroup(g2_objects, 2);
+    Object** g2_children[] = { g2c1.location() };
+    global_handles->AddObjectGroup(g1_objects, 2, NULL);
+    global_handles->AddImplicitReferences(HeapObject::cast(*g1s1),
+                                         g1_children, 1);
+    global_handles->AddObjectGroup(g2_objects, 2, NULL);
+    global_handles->AddImplicitReferences(HeapObject::cast(*g2s2),
+                                         g2_children, 1);
   }
 
-  Heap::CollectGarbage(OLD_POINTER_SPACE);
+  HEAP->CollectGarbage(OLD_POINTER_SPACE);
 
   // All objects should be gone. 5 global handles in total.
   CHECK_EQ(5, NumberOfWeakCalls);
+
+  // And now make children weak again and collect them.
+  global_handles->MakeWeak(g1c1.location(),
+                           reinterpret_cast<void*>(1234),
+                           &WeakPointerCallback);
+  global_handles->MakeWeak(g2c1.location(),
+                           reinterpret_cast<void*>(1234),
+                           &WeakPointerCallback);
+
+  HEAP->CollectGarbage(OLD_POINTER_SPACE);
+  CHECK_EQ(7, NumberOfWeakCalls);
 }
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index 8ee4038..98a5870 100755
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -31,6 +31,7 @@
 
 #include "v8.h"
 
+#include "isolate.h"
 #include "token.h"
 #include "scanner.h"
 #include "parser.h"
@@ -153,7 +154,7 @@
 
   // Parser/Scanner needs a stack limit.
   int marker;
-  i::StackGuard::SetStackLimit(
+  i::Isolate::Current()->stack_guard()->SetStackLimit(
       reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
 
   for (int i = 0; tests[i]; i++) {
@@ -184,7 +185,7 @@
   v8::Persistent<v8::Context> context = v8::Context::New();
   v8::Context::Scope context_scope(context);
   int marker;
-  i::StackGuard::SetStackLimit(
+  i::Isolate::Current()->stack_guard()->SetStackLimit(
       reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
 
   // Source containing functions that might be lazily compiled  and all types
@@ -245,7 +246,7 @@
 
 TEST(StandAlonePreParser) {
   int marker;
-  i::StackGuard::SetStackLimit(
+  i::Isolate::Current()->stack_guard()->SetStackLimit(
       reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
 
   const char* programs[] = {
@@ -257,14 +258,14 @@
       NULL
   };
 
-  uintptr_t stack_limit = i::StackGuard::real_climit();
+  uintptr_t stack_limit = ISOLATE->stack_guard()->real_climit();
   for (int i = 0; programs[i]; i++) {
     const char* program = programs[i];
     i::Utf8ToUC16CharacterStream stream(
         reinterpret_cast<const i::byte*>(program),
         static_cast<unsigned>(strlen(program)));
     i::CompleteParserRecorder log;
-    i::V8JavaScriptScanner scanner;
+    i::V8JavaScriptScanner scanner(ISOLATE->scanner_constants());
     scanner.Initialize(&stream);
 
     v8::preparser::PreParser::PreParseResult result =
@@ -281,7 +282,7 @@
 
 TEST(RegressChromium62639) {
   int marker;
-  i::StackGuard::SetStackLimit(
+  ISOLATE->stack_guard()->SetStackLimit(
       reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
 
   const char* program = "var x = 'something';\n"
@@ -306,7 +307,7 @@
   // the block could be lazily compiled, and an extra, unexpected,
   // entry was added to the data.
   int marker;
-  i::StackGuard::SetStackLimit(
+  ISOLATE->stack_guard()->SetStackLimit(
       reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
 
   const char* program =
@@ -342,7 +343,7 @@
 
 TEST(PreParseOverflow) {
   int marker;
-  i::StackGuard::SetStackLimit(
+  ISOLATE->stack_guard()->SetStackLimit(
       reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
 
   size_t kProgramSize = 1024 * 1024;
@@ -351,13 +352,13 @@
   memset(*program, '(', kProgramSize);
   program[kProgramSize] = '\0';
 
-  uintptr_t stack_limit = i::StackGuard::real_climit();
+  uintptr_t stack_limit = ISOLATE->stack_guard()->real_climit();
 
   i::Utf8ToUC16CharacterStream stream(
       reinterpret_cast<const i::byte*>(*program),
       static_cast<unsigned>(kProgramSize));
   i::CompleteParserRecorder log;
-  i::V8JavaScriptScanner scanner;
+  i::V8JavaScriptScanner scanner(ISOLATE->scanner_constants());
   scanner.Initialize(&stream);
 
 
@@ -405,10 +406,10 @@
   }
   i::Vector<const char> ascii_vector(ascii_source, static_cast<int>(length));
   i::Handle<i::String> ascii_string(
-      i::Factory::NewStringFromAscii(ascii_vector));
+      FACTORY->NewStringFromAscii(ascii_vector));
   TestExternalResource resource(*uc16_buffer, length);
   i::Handle<i::String> uc16_string(
-      i::Factory::NewExternalStringFromTwoByte(&resource));
+      FACTORY->NewExternalStringFromTwoByte(&resource));
 
   i::ExternalTwoByteStringUC16CharacterStream uc16_stream(
       i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end);
@@ -575,7 +576,7 @@
                        i::Token::Value* expected_tokens,
                        int skip_pos = 0,  // Zero means not skipping.
                        int skip_to = 0) {
-  i::V8JavaScriptScanner scanner;
+  i::V8JavaScriptScanner scanner(ISOLATE->scanner_constants());
   scanner.Initialize(stream);
 
   int i = 0;
@@ -654,7 +655,7 @@
   i::Utf8ToUC16CharacterStream stream(
        reinterpret_cast<const i::byte*>(re_source),
        static_cast<unsigned>(strlen(re_source)));
-  i::V8JavaScriptScanner scanner;
+  i::V8JavaScriptScanner scanner(ISOLATE->scanner_constants());
   scanner.Initialize(&stream);
 
   i::Token::Value start = scanner.peek();
diff --git a/test/cctest/test-platform-linux.cc b/test/cctest/test-platform-linux.cc
index e1a00e1..756b947 100644
--- a/test/cctest/test-platform-linux.cc
+++ b/test/cctest/test-platform-linux.cc
@@ -67,6 +67,7 @@
 
 
 TEST(VirtualMemory) {
+  OS::Setup();
   VirtualMemory* vm = new VirtualMemory(1 * MB);
   CHECK(vm->IsReserved());
   void* block_addr = vm->address();
diff --git a/test/cctest/test-platform-tls.cc b/test/cctest/test-platform-tls.cc
new file mode 100644
index 0000000..b2cb101
--- /dev/null
+++ b/test/cctest/test-platform-tls.cc
@@ -0,0 +1,66 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+//
+// Tests of fast TLS support.
+
+#include "v8.h"
+
+#include "cctest.h"
+#include "checks.h"
+#include "platform.h"
+
+using v8::internal::Thread;
+
+static const int kValueCount = 128;
+
+static Thread::LocalStorageKey keys[kValueCount];
+
+static void* GetValue(int num) {
+  return reinterpret_cast<void*>(static_cast<intptr_t>(num + 1));
+}
+
+static void DoTest() {
+  for (int i = 0; i < kValueCount; i++) {
+    CHECK(!Thread::HasThreadLocal(keys[i]));
+  }
+  for (int i = 0; i < kValueCount; i++) {
+    Thread::SetThreadLocal(keys[i], GetValue(i));
+  }
+  for (int i = 0; i < kValueCount; i++) {
+    CHECK(Thread::HasThreadLocal(keys[i]));
+  }
+  for (int i = 0; i < kValueCount; i++) {
+    CHECK_EQ(GetValue(i), Thread::GetThreadLocal(keys[i]));
+    CHECK_EQ(GetValue(i), Thread::GetExistingThreadLocal(keys[i]));
+  }
+  for (int i = 0; i < kValueCount; i++) {
+    Thread::SetThreadLocal(keys[i], GetValue(kValueCount - i - 1));
+  }
+  for (int i = 0; i < kValueCount; i++) {
+    CHECK(Thread::HasThreadLocal(keys[i]));
+  }
+  for (int i = 0; i < kValueCount; i++) {
+    CHECK_EQ(GetValue(kValueCount - i - 1),
+             Thread::GetThreadLocal(keys[i]));
+    CHECK_EQ(GetValue(kValueCount - i - 1),
+             Thread::GetExistingThreadLocal(keys[i]));
+  }
+}
+
+class TestThread : public Thread {
+ public:
+  TestThread() : Thread(NULL, "TestThread") {}
+
+  virtual void Run() {
+    DoTest();
+  }
+};
+
+TEST(FastTLS) {
+  for (int i = 0; i < kValueCount; i++) {
+    keys[i] = Thread::CreateThreadLocalKey();
+  }
+  DoTest();
+  TestThread thread;
+  thread.Start();
+  thread.Join();
+}
diff --git a/test/cctest/test-platform-win32.cc b/test/cctest/test-platform-win32.cc
index a5a6dd5..9bd0014 100644
--- a/test/cctest/test-platform-win32.cc
+++ b/test/cctest/test-platform-win32.cc
@@ -13,6 +13,7 @@
 
 
 TEST(VirtualMemory) {
+  OS::Setup();
   VirtualMemory* vm = new VirtualMemory(1 * MB);
   CHECK(vm->IsReserved());
   void* block_addr = vm->address();
diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc
index c60d072..fbe5834 100644
--- a/test/cctest/test-profile-generator.cc
+++ b/test/cctest/test-profile-generator.cc
@@ -56,7 +56,7 @@
     CHECK_EQ(0, te.GetTokenId(*v8::Utils::OpenHandle(*token1)));
   }
   CHECK(!i::TokenEnumeratorTester::token_removed(&te)->at(2));
-  i::Heap::CollectAllGarbage(false);
+  HEAP->CollectAllGarbage(false);
   CHECK(i::TokenEnumeratorTester::token_removed(&te)->at(2));
   CHECK_EQ(1, te.GetTokenId(*v8::Utils::OpenHandle(*token2)));
   CHECK_EQ(0, te.GetTokenId(*v8::Utils::OpenHandle(*token1)));
diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc
index 51fef71..e7026d4 100644
--- a/test/cctest/test-regexp.cc
+++ b/test/cctest/test-regexp.cc
@@ -45,6 +45,10 @@
 #include "arm/macro-assembler-arm.h"
 #include "arm/regexp-macro-assembler-arm.h"
 #endif
+#ifdef V8_TARGET_ARCH_MIPS
+#include "mips/macro-assembler-mips.h"
+#include "mips/regexp-macro-assembler-mips.h"
+#endif
 #ifdef V8_TARGET_ARCH_X64
 #include "x64/macro-assembler-x64.h"
 #include "x64/regexp-macro-assembler-x64.h"
@@ -62,7 +66,7 @@
   V8::Initialize(NULL);
   v8::HandleScope scope;
   ZoneScope zone_scope(DELETE_ON_EXIT);
-  FlatStringReader reader(CStrVector(input));
+  FlatStringReader reader(Isolate::Current(), CStrVector(input));
   RegExpCompileData result;
   return v8::internal::RegExpParser::ParseRegExp(&reader, false, &result);
 }
@@ -72,7 +76,7 @@
   V8::Initialize(NULL);
   v8::HandleScope scope;
   ZoneScope zone_scope(DELETE_ON_EXIT);
-  FlatStringReader reader(CStrVector(input));
+  FlatStringReader reader(Isolate::Current(), CStrVector(input));
   RegExpCompileData result;
   CHECK(v8::internal::RegExpParser::ParseRegExp(&reader, false, &result));
   CHECK(result.tree != NULL);
@@ -86,7 +90,7 @@
   v8::HandleScope scope;
   unibrow::Utf8InputBuffer<> buffer(input, StrLength(input));
   ZoneScope zone_scope(DELETE_ON_EXIT);
-  FlatStringReader reader(CStrVector(input));
+  FlatStringReader reader(Isolate::Current(), CStrVector(input));
   RegExpCompileData result;
   CHECK(v8::internal::RegExpParser::ParseRegExp(&reader, false, &result));
   CHECK(result.tree != NULL);
@@ -104,7 +108,7 @@
   v8::HandleScope scope;
   unibrow::Utf8InputBuffer<> buffer(input, StrLength(input));
   ZoneScope zone_scope(DELETE_ON_EXIT);
-  FlatStringReader reader(CStrVector(input));
+  FlatStringReader reader(Isolate::Current(), CStrVector(input));
   RegExpCompileData result;
   CHECK(v8::internal::RegExpParser::ParseRegExp(&reader, false, &result));
   CHECK(result.tree != NULL);
@@ -375,7 +379,7 @@
   V8::Initialize(NULL);
   v8::HandleScope scope;
   ZoneScope zone_scope(DELETE_ON_EXIT);
-  FlatStringReader reader(CStrVector(input));
+  FlatStringReader reader(Isolate::Current(), CStrVector(input));
   RegExpCompileData result;
   CHECK(!v8::internal::RegExpParser::ParseRegExp(&reader, false, &result));
   CHECK(result.tree == NULL);
@@ -471,6 +475,7 @@
 
 
 TEST(CharacterClassEscapes) {
+  v8::internal::V8::Initialize(NULL);
   TestCharacterClassEscapes('.', IsRegExpNewline);
   TestCharacterClassEscapes('d', IsDigit);
   TestCharacterClassEscapes('D', NotDigit);
@@ -483,12 +488,12 @@
 
 static RegExpNode* Compile(const char* input, bool multiline, bool is_ascii) {
   V8::Initialize(NULL);
-  FlatStringReader reader(CStrVector(input));
+  FlatStringReader reader(Isolate::Current(), CStrVector(input));
   RegExpCompileData compile_data;
   if (!v8::internal::RegExpParser::ParseRegExp(&reader, multiline,
                                                &compile_data))
     return NULL;
-  Handle<String> pattern = Factory::NewStringFromUtf8(CStrVector(input));
+  Handle<String> pattern = FACTORY->NewStringFromUtf8(CStrVector(input));
   RegExpEngine::Compile(&compile_data, false, multiline, pattern, is_ascii);
   return compile_data.node;
 }
@@ -538,6 +543,7 @@
 
 
 TEST(SplayTreeSimple) {
+  v8::internal::V8::Initialize(NULL);
   static const unsigned kLimit = 1000;
   ZoneScope zone_scope(DELETE_ON_EXIT);
   ZoneSplayTree<TestConfig> tree;
@@ -590,6 +596,7 @@
 
 
 TEST(DispatchTableConstruction) {
+  v8::internal::V8::Initialize(NULL);
   // Initialize test data.
   static const int kLimit = 1000;
   static const int kRangeCount = 8;
@@ -667,13 +674,13 @@
 #elif V8_TARGET_ARCH_ARM
 typedef RegExpMacroAssemblerARM ArchRegExpMacroAssembler;
 #elif V8_TARGET_ARCH_MIPS
-typedef RegExpMacroAssembler ArchRegExpMacroAssembler;
+typedef RegExpMacroAssemblerMIPS ArchRegExpMacroAssembler;
 #endif
 
 class ContextInitializer {
  public:
   ContextInitializer()
-      : env_(), scope_(), zone_(DELETE_ON_EXIT), stack_guard_() {
+      : env_(), scope_(), zone_(DELETE_ON_EXIT) {
     env_ = v8::Context::New();
     env_->Enter();
   }
@@ -685,7 +692,6 @@
   v8::Persistent<v8::Context> env_;
   v8::HandleScope scope_;
   v8::internal::ZoneScope zone_;
-  v8::internal::StackGuard stack_guard_;
 };
 
 
@@ -701,7 +707,8 @@
       start_offset,
       input_start,
       input_end,
-      captures);
+      captures,
+      Isolate::Current());
 }
 
 
@@ -713,12 +720,12 @@
 
   m.Succeed();
 
-  Handle<String> source = Factory::NewStringFromAscii(CStrVector(""));
+  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<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());
@@ -757,12 +764,12 @@
   m.Bind(&fail);
   m.Fail();
 
-  Handle<String> source = Factory::NewStringFromAscii(CStrVector("^foo"));
+  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<String> input = FACTORY->NewStringFromAscii(CStrVector("foofoo"));
   Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
   Address start_adr = seq_input->GetCharsAddress();
 
@@ -780,7 +787,7 @@
   CHECK_EQ(-1, captures[2]);
   CHECK_EQ(-1, captures[3]);
 
-  input = Factory::NewStringFromAscii(CStrVector("barbarbar"));
+  input = FACTORY->NewStringFromAscii(CStrVector("barbarbar"));
   seq_input = Handle<SeqAsciiString>::cast(input);
   start_adr = seq_input->GetCharsAddress();
 
@@ -813,14 +820,14 @@
   m.Bind(&fail);
   m.Fail();
 
-  Handle<String> source = Factory::NewStringFromAscii(CStrVector("^foo"));
+  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));
+      FACTORY->NewStringFromTwoByte(Vector<const uc16>(input_data, 6));
   Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::cast(input);
   Address start_adr = seq_input->GetCharsAddress();
 
@@ -839,7 +846,7 @@
   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));
+  input = FACTORY->NewStringFromTwoByte(Vector<const uc16>(input_data2, 9));
   seq_input = Handle<SeqTwoByteString>::cast(input);
   start_adr = seq_input->GetCharsAddress();
 
@@ -871,11 +878,11 @@
   m.Bind(&backtrack);
   m.Fail();
 
-  Handle<String> source = Factory::NewStringFromAscii(CStrVector(".........."));
+  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<String> input = FACTORY->NewStringFromAscii(CStrVector("foofoo"));
   Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
   Address start_adr = seq_input->GetCharsAddress();
 
@@ -912,11 +919,11 @@
   m.Bind(&missing_match);
   m.Fail();
 
-  Handle<String> source = Factory::NewStringFromAscii(CStrVector("^(..)..\1"));
+  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<String> input = FACTORY->NewStringFromAscii(CStrVector("fooofo"));
   Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
   Address start_adr = seq_input->GetCharsAddress();
 
@@ -958,13 +965,13 @@
   m.Bind(&missing_match);
   m.Fail();
 
-  Handle<String> source = Factory::NewStringFromAscii(CStrVector("^(..)..\1"));
+  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));
+      FACTORY->NewStringFromTwoByte(Vector<const uc16>(input_data, 6));
   Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::cast(input);
   Address start_adr = seq_input->GetCharsAddress();
 
@@ -1013,11 +1020,11 @@
   m.CheckNotCharacter('b', &fail);
   m.Succeed();
 
-  Handle<String> source = Factory::NewStringFromAscii(CStrVector("(^f|ob)"));
+  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<String> input = FACTORY->NewStringFromAscii(CStrVector("foobar"));
   Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
   Address start_adr = seq_input->GetCharsAddress();
 
@@ -1071,12 +1078,12 @@
   m.Succeed();
 
   Handle<String> source =
-      Factory::NewStringFromAscii(CStrVector("^(abc)\1\1(?!\1)...(?!\1)"));
+      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"));
+      FACTORY->NewStringFromAscii(CStrVector("aBcAbCABCxYzab"));
   Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
   Address start_adr = seq_input->GetCharsAddress();
 
@@ -1169,13 +1176,13 @@
   m.Fail();
 
   Handle<String> source =
-      Factory::NewStringFromAscii(CStrVector("<loop test>"));
+      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"));
+      FACTORY->NewStringFromAscii(CStrVector("foofoofoofoofoo"));
   Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
   Address start_adr = seq_input->GetCharsAddress();
 
@@ -1210,13 +1217,13 @@
   m.GoTo(&loop);
 
   Handle<String> source =
-      Factory::NewStringFromAscii(CStrVector("<stack overflow test>"));
+      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"));
+      FACTORY->NewStringFromAscii(CStrVector("dummy"));
   Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
   Address start_adr = seq_input->GetCharsAddress();
 
@@ -1229,8 +1236,8 @@
               NULL);
 
   CHECK_EQ(NativeRegExpMacroAssembler::EXCEPTION, result);
-  CHECK(Top::has_pending_exception());
-  Top::clear_pending_exception();
+  CHECK(Isolate::Current()->has_pending_exception());
+  Isolate::Current()->clear_pending_exception();
 }
 
 
@@ -1254,13 +1261,13 @@
   m.Succeed();
 
   Handle<String> source =
-      Factory::NewStringFromAscii(CStrVector("<huge register space test>"));
+      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"));
+      FACTORY->NewStringFromAscii(CStrVector("sample text"));
   Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
   Address start_adr = seq_input->GetCharsAddress();
 
@@ -1277,7 +1284,7 @@
   CHECK_EQ(0, captures[0]);
   CHECK_EQ(42, captures[1]);
 
-  Top::clear_pending_exception();
+  Isolate::Current()->clear_pending_exception();
 }
 
 #else  // V8_INTERPRETED_REGEXP
@@ -1322,13 +1329,13 @@
 
   v8::HandleScope scope;
 
-  Handle<String> source = Factory::NewStringFromAscii(CStrVector("^f(o)o"));
+  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));
+      FACTORY->NewStringFromTwoByte(Vector<const uc16>(str1, 6));
 
   CHECK(IrregexpInterpreter::Match(array, f1_16, captures, 0));
   CHECK_EQ(0, captures[0]);
@@ -1339,7 +1346,7 @@
 
   const uc16 str2[] = {'b', 'a', 'r', 'f', 'o', 'o'};
   Handle<String> f2_16 =
-      Factory::NewStringFromTwoByte(Vector<const uc16>(str2, 6));
+      FACTORY->NewStringFromTwoByte(Vector<const uc16>(str2, 6));
 
   CHECK(!IrregexpInterpreter::Match(array, f2_16, captures, 0));
   CHECK_EQ(42, captures[0]);
@@ -1349,6 +1356,7 @@
 
 
 TEST(AddInverseToTable) {
+  v8::internal::V8::Initialize(NULL);
   static const int kLimit = 1000;
   static const int kRangeCount = 16;
   for (int t = 0; t < 10; t++) {
@@ -1507,6 +1515,7 @@
 
 
 TEST(CharacterRangeCaseIndependence) {
+  v8::internal::V8::Initialize(NULL);
   TestSimpleRangeCaseIndependence(CharacterRange::Singleton('a'),
                                   CharacterRange::Singleton('A'));
   TestSimpleRangeCaseIndependence(CharacterRange::Singleton('z'),
@@ -1548,6 +1557,7 @@
 
 
 TEST(CharClassDifference) {
+  v8::internal::V8::Initialize(NULL);
   ZoneScope zone_scope(DELETE_ON_EXIT);
   ZoneList<CharacterRange>* base = new ZoneList<CharacterRange>(1);
   base->Add(CharacterRange::Everything());
@@ -1574,6 +1584,7 @@
 
 
 TEST(CanonicalizeCharacterSets) {
+  v8::internal::V8::Initialize(NULL);
   ZoneScope scope(DELETE_ON_EXIT);
   ZoneList<CharacterRange>* list = new ZoneList<CharacterRange>(4);
   CharacterSet set(list);
@@ -1644,6 +1655,7 @@
 }
 
 TEST(CharacterRangeMerge) {
+  v8::internal::V8::Initialize(NULL);
   ZoneScope zone_scope(DELETE_ON_EXIT);
   ZoneList<CharacterRange> l1(4);
   ZoneList<CharacterRange> l2(4);
diff --git a/test/cctest/test-reloc-info.cc b/test/cctest/test-reloc-info.cc
index 2b9beac..0378fb3 100644
--- a/test/cctest/test-reloc-info.cc
+++ b/test/cctest/test-reloc-info.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -42,24 +42,31 @@
 // Tests that writing both types of positions and then reading either
 // or both works as expected.
 TEST(Positions) {
-  const int instr_size = 10 << 10;
-  const int reloc_size = 10 << 10;
-  const int buf_size = instr_size + reloc_size;
-  SmartPointer<byte> buf(new byte[buf_size]);
-  byte* pc = *buf;
-  CodeDesc desc = { *buf, buf_size, instr_size, reloc_size, NULL };
+  const int code_size = 10 * KB;
+  int relocation_info_size = 10 * KB;
+  const int buffer_size = code_size + relocation_info_size;
+  SmartPointer<byte> buffer(new byte[buffer_size]);
 
-  RelocInfoWriter writer(*buf + buf_size, pc);
+  byte* pc = *buffer;
+  byte* buffer_end = *buffer + buffer_size;
+
+  RelocInfoWriter writer(buffer_end, pc);
+  byte* relocation_info_end = buffer_end - relocation_info_size;
   for (int i = 0, pos = 0; i < 100; i++, pc += i, pos += i) {
     RelocInfo::Mode mode = (i % 2 == 0) ?
         RelocInfo::STATEMENT_POSITION : RelocInfo::POSITION;
     WriteRinfo(&writer, pc, mode, pos);
+    CHECK(writer.pos() - RelocInfoWriter::kMaxSize >= relocation_info_end);
   }
 
+  relocation_info_size = static_cast<int>(buffer_end - writer.pos());
+  CodeDesc desc = { *buffer, buffer_size, code_size,
+                    relocation_info_size, NULL };
+
   // Read only (non-statement) positions.
   {
     RelocIterator it(desc, RelocInfo::ModeMask(RelocInfo::POSITION));
-    pc = *buf;
+    pc = *buffer;
     for (int i = 0, pos = 0; i < 100; i++, pc += i, pos += i) {
       RelocInfo::Mode mode = (i % 2 == 0) ?
           RelocInfo::STATEMENT_POSITION : RelocInfo::POSITION;
@@ -76,7 +83,7 @@
   // Read only statement positions.
   {
     RelocIterator it(desc, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
-    pc = *buf;
+    pc = *buffer;
     for (int i = 0, pos = 0; i < 100; i++, pc += i, pos += i) {
       RelocInfo::Mode mode = (i % 2 == 0) ?
           RelocInfo::STATEMENT_POSITION : RelocInfo::POSITION;
@@ -93,7 +100,7 @@
   // Read both types of positions.
   {
     RelocIterator it(desc, RelocInfo::kPositionMask);
-    pc = *buf;
+    pc = *buffer;
     for (int i = 0, pos = 0; i < 100; i++, pc += i, pos += i) {
       RelocInfo::Mode mode = (i % 2 == 0) ?
           RelocInfo::STATEMENT_POSITION : RelocInfo::POSITION;
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index 80910c2..730d72a 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -83,7 +83,7 @@
 
 template <class T>
 static Address AddressOf(T id) {
-  return ExternalReference(id).address();
+  return ExternalReference(id, i::Isolate::Current()).address();
 }
 
 
@@ -99,70 +99,75 @@
 
 
 TEST(ExternalReferenceEncoder) {
-  StatsTable::SetCounterFunction(counter_function);
-  Heap::Setup(false);
+  OS::Setup();
+  Isolate* isolate = i::Isolate::Current();
+  isolate->stats_table()->SetCounterFunction(counter_function);
+  HEAP->Setup(false);
   ExternalReferenceEncoder encoder;
-  CHECK_EQ(make_code(BUILTIN, Builtins::ArrayCode),
-           Encode(encoder, Builtins::ArrayCode));
+  CHECK_EQ(make_code(BUILTIN, Builtins::kArrayCode),
+           Encode(encoder, Builtins::kArrayCode));
   CHECK_EQ(make_code(v8::internal::RUNTIME_FUNCTION, Runtime::kAbort),
            Encode(encoder, Runtime::kAbort));
   CHECK_EQ(make_code(IC_UTILITY, IC::kLoadCallbackProperty),
            Encode(encoder, IC_Utility(IC::kLoadCallbackProperty)));
   ExternalReference keyed_load_function_prototype =
-      ExternalReference(&Counters::keyed_load_function_prototype);
+      ExternalReference(isolate->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 the_hole_value_location =
-      ExternalReference::the_hole_value_location();
+      ExternalReference::the_hole_value_location(isolate);
   CHECK_EQ(make_code(UNCLASSIFIED, 2),
            encoder.Encode(the_hole_value_location.address()));
   ExternalReference stack_limit_address =
-      ExternalReference::address_of_stack_limit();
+      ExternalReference::address_of_stack_limit(isolate);
   CHECK_EQ(make_code(UNCLASSIFIED, 4),
            encoder.Encode(stack_limit_address.address()));
   ExternalReference real_stack_limit_address =
-      ExternalReference::address_of_real_stack_limit();
+      ExternalReference::address_of_real_stack_limit(isolate);
   CHECK_EQ(make_code(UNCLASSIFIED, 5),
            encoder.Encode(real_stack_limit_address.address()));
 #ifdef ENABLE_DEBUGGER_SUPPORT
   CHECK_EQ(make_code(UNCLASSIFIED, 15),
-           encoder.Encode(ExternalReference::debug_break().address()));
+           encoder.Encode(ExternalReference::debug_break(isolate).address()));
 #endif  // ENABLE_DEBUGGER_SUPPORT
   CHECK_EQ(make_code(UNCLASSIFIED, 10),
-           encoder.Encode(ExternalReference::new_space_start().address()));
+           encoder.Encode(
+               ExternalReference::new_space_start(isolate).address()));
   CHECK_EQ(make_code(UNCLASSIFIED, 3),
-           encoder.Encode(ExternalReference::roots_address().address()));
+           encoder.Encode(ExternalReference::roots_address(isolate).address()));
 }
 
 
 TEST(ExternalReferenceDecoder) {
-  StatsTable::SetCounterFunction(counter_function);
-  Heap::Setup(false);
+  OS::Setup();
+  Isolate* isolate = i::Isolate::Current();
+  isolate->stats_table()->SetCounterFunction(counter_function);
+  HEAP->Setup(false);
   ExternalReferenceDecoder decoder;
-  CHECK_EQ(AddressOf(Builtins::ArrayCode),
-           decoder.Decode(make_code(BUILTIN, Builtins::ArrayCode)));
+  CHECK_EQ(AddressOf(Builtins::kArrayCode),
+           decoder.Decode(make_code(BUILTIN, Builtins::kArrayCode)));
   CHECK_EQ(AddressOf(Runtime::kAbort),
            decoder.Decode(make_code(v8::internal::RUNTIME_FUNCTION,
                                     Runtime::kAbort)));
   CHECK_EQ(AddressOf(IC_Utility(IC::kLoadCallbackProperty)),
            decoder.Decode(make_code(IC_UTILITY, IC::kLoadCallbackProperty)));
   ExternalReference keyed_load_function =
-      ExternalReference(&Counters::keyed_load_function_prototype);
+      ExternalReference(isolate->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::the_hole_value_location().address(),
+  CHECK_EQ(ExternalReference::the_hole_value_location(isolate).address(),
            decoder.Decode(make_code(UNCLASSIFIED, 2)));
-  CHECK_EQ(ExternalReference::address_of_stack_limit().address(),
+  CHECK_EQ(ExternalReference::address_of_stack_limit(isolate).address(),
            decoder.Decode(make_code(UNCLASSIFIED, 4)));
-  CHECK_EQ(ExternalReference::address_of_real_stack_limit().address(),
+  CHECK_EQ(ExternalReference::address_of_real_stack_limit(isolate).address(),
            decoder.Decode(make_code(UNCLASSIFIED, 5)));
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  CHECK_EQ(ExternalReference::debug_break().address(),
+  CHECK_EQ(ExternalReference::debug_break(isolate).address(),
            decoder.Decode(make_code(UNCLASSIFIED, 15)));
 #endif  // ENABLE_DEBUGGER_SUPPORT
-  CHECK_EQ(ExternalReference::new_space_start().address(),
+  CHECK_EQ(ExternalReference::new_space_start(isolate).address(),
            decoder.Decode(make_code(UNCLASSIFIED, 10)));
 }
 
@@ -276,12 +281,12 @@
 static void SanityCheck() {
   v8::HandleScope scope;
 #ifdef DEBUG
-  Heap::Verify();
+  HEAP->Verify();
 #endif
-  CHECK(Top::global()->IsJSObject());
-  CHECK(Top::global_context()->IsContext());
-  CHECK(Heap::symbol_table()->IsSymbolTable());
-  CHECK(!Factory::LookupAsciiSymbol("Empty")->IsFailure());
+  CHECK(Isolate::Current()->global()->IsJSObject());
+  CHECK(Isolate::Current()->global_context()->IsContext());
+  CHECK(HEAP->symbol_table()->IsSymbolTable());
+  CHECK(!FACTORY->LookupAsciiSymbol("Empty")->IsFailure());
 }
 
 
@@ -291,7 +296,6 @@
   // serialize a snapshot in a VM that is booted from a snapshot.
   if (!Snapshot::IsEnabled()) {
     v8::HandleScope scope;
-
     Deserialize();
 
     v8::Persistent<v8::Context> env = v8::Context::New();
@@ -305,7 +309,6 @@
 DEPENDENT_TEST(DeserializeFromSecondSerialization, SerializeTwice) {
   if (!Snapshot::IsEnabled()) {
     v8::HandleScope scope;
-
     Deserialize();
 
     v8::Persistent<v8::Context> env = v8::Context::New();
@@ -319,7 +322,6 @@
 DEPENDENT_TEST(DeserializeAndRunScript2, Serialize) {
   if (!Snapshot::IsEnabled()) {
     v8::HandleScope scope;
-
     Deserialize();
 
     v8::Persistent<v8::Context> env = v8::Context::New();
@@ -337,7 +339,6 @@
                SerializeTwice) {
   if (!Snapshot::IsEnabled()) {
     v8::HandleScope scope;
-
     Deserialize();
 
     v8::Persistent<v8::Context> env = v8::Context::New();
@@ -361,11 +362,11 @@
   // Make sure all builtin scripts are cached.
   { HandleScope scope;
     for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
-      Bootstrapper::NativesSourceLookup(i);
+      Isolate::Current()->bootstrapper()->NativesSourceLookup(i);
     }
   }
-  Heap::CollectAllGarbage(true);
-  Heap::CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
 
   Object* raw_foo;
   {
@@ -425,7 +426,7 @@
 #undef fscanf
 #endif
   fclose(fp);
-  Heap::ReserveSpace(new_size,
+  HEAP->ReserveSpace(new_size,
                      pointer_size,
                      data_size,
                      code_size,
@@ -482,12 +483,12 @@
   // Make sure all builtin scripts are cached.
   { HandleScope scope;
     for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
-      Bootstrapper::NativesSourceLookup(i);
+      Isolate::Current()->bootstrapper()->NativesSourceLookup(i);
     }
   }
   // If we don't do this then we end up with a stray root pointing at the
   // context even after we have disposed of env.
-  Heap::CollectAllGarbage(true);
+  HEAP->CollectAllGarbage(true);
 
   int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
   Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
@@ -561,7 +562,7 @@
 
   for (int size = 1000; size < 5 * MB; size += size >> 1) {
     int new_space_size = (size < new_space_max) ? size : new_space_max;
-    Heap::ReserveSpace(
+    HEAP->ReserveSpace(
         new_space_size,
         size,              // Old pointer space.
         size,              // Old data space.
@@ -584,7 +585,7 @@
          i + kSmallFixedArraySize <= new_space_size;
          i += kSmallFixedArraySize) {
       Object* obj =
-          Heap::AllocateFixedArray(kSmallFixedArrayLength)->ToObjectChecked();
+          HEAP->AllocateFixedArray(kSmallFixedArrayLength)->ToObjectChecked();
       if (new_last != NULL) {
         CHECK(reinterpret_cast<char*>(obj) ==
               reinterpret_cast<char*>(new_last) + kSmallFixedArraySize);
@@ -596,7 +597,7 @@
     for (int i = 0;
          i + kSmallFixedArraySize <= size;
          i += kSmallFixedArraySize) {
-      Object* obj = Heap::AllocateFixedArray(kSmallFixedArrayLength,
+      Object* obj = HEAP->AllocateFixedArray(kSmallFixedArrayLength,
                                              TENURED)->ToObjectChecked();
       int old_page_fullness = i % Page::kPageSize;
       int page_fullness = (i + kSmallFixedArraySize) % Page::kPageSize;
@@ -614,7 +615,7 @@
 
     Object* data_last = NULL;
     for (int i = 0; i + kSmallStringSize <= size; i += kSmallStringSize) {
-      Object* obj = Heap::AllocateRawAsciiString(kSmallStringLength,
+      Object* obj = HEAP->AllocateRawAsciiString(kSmallStringLength,
                                                  TENURED)->ToObjectChecked();
       int old_page_fullness = i % Page::kPageSize;
       int page_fullness = (i + kSmallStringSize) % Page::kPageSize;
@@ -632,7 +633,7 @@
 
     Object* map_last = NULL;
     for (int i = 0; i + kMapSize <= size; i += kMapSize) {
-      Object* obj = Heap::AllocateMap(JS_OBJECT_TYPE,
+      Object* obj = HEAP->AllocateMap(JS_OBJECT_TYPE,
                                       42 * kPointerSize)->ToObjectChecked();
       int old_page_fullness = i % Page::kPageSize;
       int page_fullness = (i + kMapSize) % Page::kPageSize;
@@ -654,7 +655,7 @@
       AlwaysAllocateScope always;
       int large_object_array_length =
           (size - FixedArray::kHeaderSize) / kPointerSize;
-      Object* obj = Heap::AllocateFixedArray(large_object_array_length,
+      Object* obj = HEAP->AllocateFixedArray(large_object_array_length,
                                              TENURED)->ToObjectChecked();
       CHECK(!obj->IsFailure());
     }
diff --git a/test/cctest/test-sockets.cc b/test/cctest/test-sockets.cc
index 822a23f..5246d09 100644
--- a/test/cctest/test-sockets.cc
+++ b/test/cctest/test-sockets.cc
@@ -10,8 +10,12 @@
 
 class SocketListenerThread : public Thread {
  public:
-  explicit SocketListenerThread(int port, int data_size)
-      : port_(port), data_size_(data_size), server_(NULL), client_(NULL),
+  explicit SocketListenerThread(Isolate* isolate, int port, int data_size)
+      : Thread(isolate, "SocketListenerThread"),
+        port_(port),
+        data_size_(data_size),
+        server_(NULL),
+        client_(NULL),
         listening_(OS::CreateSemaphore(0)) {
     data_ = new char[data_size_];
   }
@@ -88,7 +92,8 @@
   OS::SNPrintF(Vector<char>(port_str, kPortBuferLen), "%d", port);
 
   // Create a socket listener.
-  SocketListenerThread* listener = new SocketListenerThread(port, len);
+  SocketListenerThread* listener = new SocketListenerThread(Isolate::Current(),
+      port, len);
   listener->Start();
   listener->WaitForListening();
 
diff --git a/test/cctest/test-spaces.cc b/test/cctest/test-spaces.cc
index 706c6bf..de0c41e 100644
--- a/test/cctest/test-spaces.cc
+++ b/test/cctest/test-spaces.cc
@@ -65,6 +65,8 @@
   Address page_start = RoundUp(start, Page::kPageSize);
 
   Page* p = Page::FromAddress(page_start);
+  // Initialized Page has heap pointer, normally set by memory_allocator.
+  p->heap_ = HEAP;
   CHECK(p->address() == page_start);
   CHECK(p->is_valid());
 
@@ -90,37 +92,45 @@
 
 
 TEST(MemoryAllocator) {
-  CHECK(Heap::ConfigureHeapDefault());
-  CHECK(MemoryAllocator::Setup(Heap::MaxReserved(), Heap::MaxExecutableSize()));
+  OS::Setup();
+  Isolate* isolate = Isolate::Current();
+  CHECK(HEAP->ConfigureHeapDefault());
+  CHECK(isolate->memory_allocator()->Setup(HEAP->MaxReserved(),
+                                           HEAP->MaxExecutableSize()));
 
-  OldSpace faked_space(Heap::MaxReserved(), OLD_POINTER_SPACE, NOT_EXECUTABLE);
+  OldSpace faked_space(HEAP,
+                       HEAP->MaxReserved(),
+                       OLD_POINTER_SPACE,
+                       NOT_EXECUTABLE);
   int total_pages = 0;
   int requested = MemoryAllocator::kPagesPerChunk;
   int allocated;
   // If we request n pages, we should get n or n - 1.
   Page* first_page =
-      MemoryAllocator::AllocatePages(requested, &allocated, &faked_space);
+      isolate->memory_allocator()->AllocatePages(
+          requested, &allocated, &faked_space);
   CHECK(first_page->is_valid());
   CHECK(allocated == requested || allocated == requested - 1);
   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));
+    CHECK(isolate->memory_allocator()->IsPageInSpace(p, &faked_space));
     last_page = p;
   }
 
   // Again, we should get n or n - 1 pages.
   Page* others =
-      MemoryAllocator::AllocatePages(requested, &allocated, &faked_space);
+      isolate->memory_allocator()->AllocatePages(
+          requested, &allocated, &faked_space);
   CHECK(others->is_valid());
   CHECK(allocated == requested || allocated == requested - 1);
   total_pages += allocated;
 
-  MemoryAllocator::SetNextPage(last_page, others);
+  isolate->memory_allocator()->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));
+    CHECK(isolate->memory_allocator()->IsPageInSpace(p, &faked_space));
     page_count++;
   }
   CHECK(total_pages == page_count);
@@ -131,31 +141,34 @@
   // Freeing pages at the first chunk starting at or after the second page
   // should free the entire second chunk.  It will return the page it was passed
   // (since the second page was in the first chunk).
-  Page* free_return = MemoryAllocator::FreePages(second_page);
+  Page* free_return = isolate->memory_allocator()->FreePages(second_page);
   CHECK(free_return == second_page);
-  MemoryAllocator::SetNextPage(first_page, free_return);
+  isolate->memory_allocator()->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);
+  Page* invalid_page = isolate->memory_allocator()->FreePages(first_page);
   CHECK(!invalid_page->is_valid());
 
-  MemoryAllocator::TearDown();
+  isolate->memory_allocator()->TearDown();
 }
 
 
 TEST(NewSpace) {
-  CHECK(Heap::ConfigureHeapDefault());
-  CHECK(MemoryAllocator::Setup(Heap::MaxReserved(), Heap::MaxExecutableSize()));
+  OS::Setup();
+  CHECK(HEAP->ConfigureHeapDefault());
+  CHECK(Isolate::Current()->memory_allocator()->Setup(
+      HEAP->MaxReserved(), HEAP->MaxExecutableSize()));
 
-  NewSpace new_space;
+  NewSpace new_space(HEAP);
 
   void* chunk =
-      MemoryAllocator::ReserveInitialChunk(4 * Heap::ReservedSemiSpaceSize());
+      Isolate::Current()->memory_allocator()->ReserveInitialChunk(
+          4 * HEAP->ReservedSemiSpaceSize());
   CHECK(chunk != NULL);
   Address start = RoundUp(static_cast<Address>(chunk),
-                          2 * Heap::ReservedSemiSpaceSize());
-  CHECK(new_space.Setup(start, 2 * Heap::ReservedSemiSpaceSize()));
+                          2 * HEAP->ReservedSemiSpaceSize());
+  CHECK(new_space.Setup(start, 2 * HEAP->ReservedSemiSpaceSize()));
   CHECK(new_space.HasBeenSetup());
 
   while (new_space.Available() >= Page::kMaxHeapObjectSize) {
@@ -165,24 +178,28 @@
   }
 
   new_space.TearDown();
-  MemoryAllocator::TearDown();
+  Isolate::Current()->memory_allocator()->TearDown();
 }
 
 
 TEST(OldSpace) {
-  CHECK(Heap::ConfigureHeapDefault());
-  CHECK(MemoryAllocator::Setup(Heap::MaxReserved(), Heap::MaxExecutableSize()));
+  OS::Setup();
+  CHECK(HEAP->ConfigureHeapDefault());
+  CHECK(Isolate::Current()->memory_allocator()->Setup(
+      HEAP->MaxReserved(), HEAP->MaxExecutableSize()));
 
-  OldSpace* s = new OldSpace(Heap::MaxOldGenerationSize(),
+  OldSpace* s = new OldSpace(HEAP,
+                             HEAP->MaxOldGenerationSize(),
                              OLD_POINTER_SPACE,
                              NOT_EXECUTABLE);
   CHECK(s != NULL);
 
   void* chunk =
-      MemoryAllocator::ReserveInitialChunk(4 * Heap::ReservedSemiSpaceSize());
+      Isolate::Current()->memory_allocator()->ReserveInitialChunk(
+          4 * HEAP->ReservedSemiSpaceSize());
   CHECK(chunk != NULL);
   Address start = static_cast<Address>(chunk);
-  size_t size = RoundUp(start, 2 * Heap::ReservedSemiSpaceSize()) - start;
+  size_t size = RoundUp(start, 2 * HEAP->ReservedSemiSpaceSize()) - start;
 
   CHECK(s->Setup(start, size));
 
@@ -192,14 +209,15 @@
 
   s->TearDown();
   delete s;
-  MemoryAllocator::TearDown();
+  Isolate::Current()->memory_allocator()->TearDown();
 }
 
 
 TEST(LargeObjectSpace) {
-  CHECK(Heap::Setup(false));
+  OS::Setup();
+  CHECK(HEAP->Setup(false));
 
-  LargeObjectSpace* lo = Heap::lo_space();
+  LargeObjectSpace* lo = HEAP->lo_space();
   CHECK(lo != NULL);
 
   Map* faked_map = reinterpret_cast<Map*>(HeapObject::FromAddress(0));
@@ -233,5 +251,5 @@
   lo->TearDown();
   delete lo;
 
-  MemoryAllocator::TearDown();
+  Isolate::Current()->memory_allocator()->TearDown();
 }
diff --git a/test/cctest/test-strings.cc b/test/cctest/test-strings.cc
index 3f02b32..9c76d2c 100644
--- a/test/cctest/test-strings.cc
+++ b/test/cctest/test-strings.cc
@@ -94,7 +94,7 @@
           buf[j] = gen() % 65536;
         }
         building_blocks[i] =
-            Factory::NewStringFromTwoByte(Vector<const uc16>(buf, len));
+            FACTORY->NewStringFromTwoByte(Vector<const uc16>(buf, len));
         for (int j = 0; j < len; j++) {
           CHECK_EQ(buf[j], building_blocks[i]->Get(j));
         }
@@ -106,19 +106,19 @@
           buf[j] = gen() % 128;
         }
         building_blocks[i] =
-            Factory::NewStringFromAscii(Vector<const char>(buf, len));
+            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: {
-        uc16* buf = Zone::NewArray<uc16>(len);
+        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);
+        building_blocks[i] = FACTORY->NewExternalStringFromTwoByte(resource);
         for (int j = 0; j < len; j++) {
           CHECK_EQ(buf[j], building_blocks[i]->Get(j));
         }
@@ -130,7 +130,7 @@
           buf[j] = gen() % 128;
         }
         building_blocks[i] =
-            Factory::NewStringFromAscii(Vector<const char>(buf, len));
+            FACTORY->NewStringFromAscii(Vector<const char>(buf, len));
         for (int j = 0; j < len; j++) {
           CHECK_EQ(buf[j], building_blocks[i]->Get(j));
         }
@@ -145,9 +145,9 @@
 static Handle<String> ConstructLeft(
     Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
     int depth) {
-  Handle<String> answer = Factory::NewStringFromAscii(CStrVector(""));
+  Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector(""));
   for (int i = 0; i < depth; i++) {
-    answer = Factory::NewConsString(
+    answer = FACTORY->NewConsString(
         answer,
         building_blocks[i % NUMBER_OF_BUILDING_BLOCKS]);
   }
@@ -158,9 +158,9 @@
 static Handle<String> ConstructRight(
     Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
     int depth) {
-  Handle<String> answer = Factory::NewStringFromAscii(CStrVector(""));
+  Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector(""));
   for (int i = depth - 1; i >= 0; i--) {
-    answer = Factory::NewConsString(
+    answer = FACTORY->NewConsString(
         building_blocks[i % NUMBER_OF_BUILDING_BLOCKS],
         answer);
   }
@@ -177,7 +177,7 @@
     return building_blocks[from % NUMBER_OF_BUILDING_BLOCKS];
   }
   if (to - from == 2) {
-    return Factory::NewConsString(
+    return FACTORY->NewConsString(
         building_blocks[from % NUMBER_OF_BUILDING_BLOCKS],
         building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS]);
   }
@@ -185,7 +185,7 @@
     ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2));
   Handle<String> part2 =
     ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to);
-  return Factory::NewConsString(part1, part2);
+  return FACTORY->NewConsString(part1, part2);
 }
 
 
@@ -286,12 +286,12 @@
     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"));
+      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);
+    string = FACTORY->NewConsString(string, foo_string);
   }
-  Handle<String> flat_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++) {
@@ -365,7 +365,7 @@
 
   // Generate short ascii and non-ascii external strings.
   for (int i = 0; i <= kMaxLength; i++) {
-    char* ascii = Zone::NewArray<char>(i + 1);
+    char* ascii = ZONE->NewArray<char>(i + 1);
     for (int j = 0; j < i; j++) {
       ascii[j] = 'a';
     }
@@ -377,7 +377,7 @@
         v8::String::NewExternal(ascii_resource);
 
     ascii_external_strings->Set(v8::Integer::New(i), ascii_external_string);
-    uc16* non_ascii = Zone::NewArray<uc16>(i + 1);
+    uc16* non_ascii = ZONE->NewArray<uc16>(i + 1);
     for (int j = 0; j < i; j++) {
       non_ascii[j] = 0x1234;
     }
@@ -459,10 +459,10 @@
   Handle<Smi> fortytwo(Smi::FromInt(42));
   Handle<Smi> thirtyseven(Smi::FromInt(37));
   Handle<Object> results[] = {
-      Factory::undefined_value(),
+      FACTORY->undefined_value(),
       fortytwo,
-      Factory::undefined_value(),
-      Factory::undefined_value(),
+      FACTORY->undefined_value(),
+      FACTORY->undefined_value(),
       thirtyseven,
       fortytwo,
       thirtyseven  // Bug yielded 42 here.
diff --git a/test/cctest/test-thread-termination.cc b/test/cctest/test-thread-termination.cc
index aed7466..5635b17 100644
--- a/test/cctest/test-thread-termination.cc
+++ b/test/cctest/test-thread-termination.cc
@@ -159,6 +159,9 @@
 
 
 class TerminatorThread : public v8::internal::Thread {
+ public:
+  explicit TerminatorThread(i::Isolate* isolate)
+      : Thread(isolate, "TerminatorThread") { }
   void Run() {
     semaphore->Wait();
     CHECK(!v8::V8::IsExecutionTerminating());
@@ -171,7 +174,7 @@
 // from the side by another thread.
 TEST(TerminateOnlyV8ThreadFromOtherThread) {
   semaphore = v8::internal::OS::CreateSemaphore(0);
-  TerminatorThread thread;
+  TerminatorThread thread(i::Isolate::Current());
   thread.Start();
 
   v8::HandleScope scope;
@@ -193,6 +196,8 @@
 
 class LoopingThread : public v8::internal::Thread {
  public:
+  explicit LoopingThread(i::Isolate* isolate)
+      : Thread(isolate, "LoopingThread") { }
   void Run() {
     v8::Locker locker;
     v8::HandleScope scope;
@@ -225,9 +230,9 @@
     v8::Locker::StartPreemption(1);
     semaphore = v8::internal::OS::CreateSemaphore(0);
   }
-  LoopingThread thread1;
+  LoopingThread thread1(i::Isolate::Current());
   thread1.Start();
-  LoopingThread thread2;
+  LoopingThread thread2(i::Isolate::Current());
   thread2.Start();
   // Wait until both threads have signaled the semaphore.
   semaphore->Wait();
diff --git a/test/cctest/test-threads.cc b/test/cctest/test-threads.cc
index 0f48e24..37f0205 100644
--- a/test/cctest/test-threads.cc
+++ b/test/cctest/test-threads.cc
@@ -64,6 +64,7 @@
 
 class ThreadA: public v8::internal::Thread {
  public:
+  explicit ThreadA(i::Isolate* isolate) : Thread(isolate, "ThreadA") { }
   void Run() {
     v8::Locker locker;
     v8::HandleScope scope;
@@ -99,6 +100,7 @@
 
 class ThreadB: public v8::internal::Thread {
  public:
+  explicit ThreadB(i::Isolate* isolate) : Thread(isolate, "ThreadB") { }
   void Run() {
     do {
       {
@@ -108,7 +110,7 @@
           v8::Context::Scope context_scope(v8::Context::New());
 
           // Clear the caches by forcing major GC.
-          v8::internal::Heap::CollectAllGarbage(false);
+          HEAP->CollectAllGarbage(false);
           turn = SECOND_TIME_FILL_CACHE;
           break;
         }
@@ -123,8 +125,8 @@
 TEST(JSFunctionResultCachesInTwoThreads) {
   v8::V8::Initialize();
 
-  ThreadA threadA;
-  ThreadB threadB;
+  ThreadA threadA(i::Isolate::Current());
+  ThreadB threadB(i::Isolate::Current());
 
   threadA.Start();
   threadB.Start();
diff --git a/test/cctest/test-utils.cc b/test/cctest/test-utils.cc
index b48dcb8..018018a 100644
--- a/test/cctest/test-utils.cc
+++ b/test/cctest/test-utils.cc
@@ -103,7 +103,7 @@
 
 
 TEST(MemCopy) {
-  V8::Initialize(NULL);
+  OS::Setup();
   const int N = kMinComplexMemCopy + 128;
   Vector<byte> buffer1 = Vector<byte>::New(N);
   Vector<byte> buffer2 = Vector<byte>::New(N);
diff --git a/test/cctest/testcfg.py b/test/cctest/testcfg.py
index b15342e..a137275 100644
--- a/test/cctest/testcfg.py
+++ b/test/cctest/testcfg.py
@@ -34,11 +34,12 @@
 
 class CcTestCase(test.TestCase):
 
-  def __init__(self, path, executable, mode, raw_name, dependency, context):
+  def __init__(self, path, executable, mode, raw_name, dependency, context, variant_flags):
     super(CcTestCase, self).__init__(context, path, mode)
     self.executable = executable
     self.raw_name = raw_name
     self.dependency = dependency
+    self.variant_flags = variant_flags
 
   def GetLabel(self):
     return "%s %s %s" % (self.mode, self.path[-2], self.path[-1])
@@ -49,6 +50,8 @@
   def BuildCommand(self, name):
     serialization_file = join('obj', 'test', self.mode, 'serdes')
     serialization_file += '_' + self.GetName()
+    serialization_file = join(self.context.buildspace, serialization_file)
+    serialization_file += ''.join(self.variant_flags).replace('-', '_')
     serialization_option = '--testing_serialization_file=' + serialization_file
     result = [ self.executable, name, serialization_option ]
     result += self.context.GetVmFlags(self, self.mode)
@@ -74,10 +77,11 @@
   def GetBuildRequirements(self):
     return ['cctests']
 
-  def ListTests(self, current_path, path, mode):
+  def ListTests(self, current_path, path, mode, variant_flags):
     executable = join('obj', 'test', mode, 'cctest')
     if utils.IsWindows():
       executable += '.exe'
+    executable = join(self.context.buildspace, executable)
     output = test.Execute([executable, '--list'], self.context)
     if output.exit_code != 0:
       print output.stdout
@@ -91,7 +95,7 @@
       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))
+        result.append(CcTestCase(full_path, executable, mode, raw_test, dependency, self.context, variant_flags))
     result.sort()
     return result
 
diff --git a/test/es5conform/es5conform.status b/test/es5conform/es5conform.status
index d6f7caf..1dc90d3 100644
--- a/test/es5conform/es5conform.status
+++ b/test/es5conform/es5conform.status
@@ -239,20 +239,11 @@
 # Incorrect test - need double escape in eval.
 chapter07/7.8/7.8.4/7.8.4-1-s: FAIL
 
-# arguments[i] remains same after changing actual parameters in strict mode
-chapter10/10.6/10.6-10-c-ii-1-s: FAIL
-# arguments[i] doesn't map to actual parameters in strict mode
-chapter10/10.6/10.6-10-c-ii-2-s: FAIL
-
-# Accessing caller property of Arguments object throws TypeError in strict mode
-chapter10/10.6/10.6-13-b-1-s: FAIL
-# arguments.caller exists in strict mode
-chapter10/10.6/10.6-13-b-2-s: FAIL
 # arguments.caller is non-configurable in strict mode
+# Invalid test case. Checks for "writable == true" and presence of "put"..
 chapter10/10.6/10.6-13-b-3-s: FAIL
-# Accessing callee property of Arguments object throws TypeError in strict mode
-chapter10/10.6/10.6-13-c-1-s: FAIL
 # arguments.callee is non-configurable in strict mode
+# Invalid test case. Checks for "put" property accessor.
 chapter10/10.6/10.6-13-c-3-s: FAIL
 
 # simple assignment throws TypeError if LeftHandSide is a property reference
diff --git a/test/es5conform/testcfg.py b/test/es5conform/testcfg.py
index e3a60cc..af74b8c 100644
--- a/test/es5conform/testcfg.py
+++ b/test/es5conform/testcfg.py
@@ -73,7 +73,7 @@
   def __init__(self, context, root):
     super(ES5ConformTestConfiguration, self).__init__(context, root)
 
-  def ListTests(self, current_path, path, mode):
+  def ListTests(self, current_path, path, mode, variant_flags):
     tests = []
     current_root = join(self.root, 'data', 'TestCases')
     harness = []
diff --git a/test/message/testcfg.py b/test/message/testcfg.py
index 21a0428..aabbfef 100644
--- a/test/message/testcfg.py
+++ b/test/message/testcfg.py
@@ -103,7 +103,7 @@
     else:
         return []
 
-  def ListTests(self, current_path, path, mode):
+  def ListTests(self, current_path, path, mode, variant_flags):
     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'))]
diff --git a/test/mjsunit/accessors-on-global-object.js b/test/mjsunit/accessors-on-global-object.js
index 8d95692..dc910b7 100644
--- a/test/mjsunit/accessors-on-global-object.js
+++ b/test/mjsunit/accessors-on-global-object.js
@@ -28,7 +28,7 @@
 // Test that installing a getter on the global object instead of a
 // normal property works.
 
-var x = 0;
+x = 0;
 
 function getX() { return x; }
 
@@ -41,7 +41,7 @@
 // Test that installing a setter on the global object instead of a
 // normal property works.
 
-var y = 0;
+y = 0;
 var setter_y;
 
 function setY(value) { y = value; }
@@ -67,6 +67,6 @@
   assertEquals(i < 5 ? 42 : 0, getZ());
   if (i == 4) {
     delete z;
-    var z = 0;
+    z = 0;
   }
 }
diff --git a/test/mjsunit/bitops-info.js b/test/mjsunit/bitops-info.js
index 4660fdf..4b114c5 100644
--- a/test/mjsunit/bitops-info.js
+++ b/test/mjsunit/bitops-info.js
@@ -37,7 +37,6 @@
   return 1600822924;  // It's a signed Int32.
 }
 
-
 function f() {
   var x = non_int32();  // Not a constant.
   var y = hidden_smi();  // Not a constant.
@@ -66,6 +65,13 @@
   assertEquals(46512102 & 2600822924, x & y, "10rev");
   assertEquals(1600822924 & 2600822924, x & z, "11rev");
 
+  assertEquals((46512102 & -0x20123456) | 1, (y & -0x20123456) | 1, "12");
+  assertEquals((1600822924 & -0x20123456) | 1, (z & -0x20123456) | 1, "13");
+  assertEquals((2600822924 & -0x20123456) | 1, (x & -0x20123456) | 1, "14");
+  assertEquals((46512102 & -0x20123456) | 1, (-0x20123456 & y) | 1, "12rev");
+  assertEquals((1600822924 & -0x20123456) | 1, (-0x20123456 & z) | 1, "13rev");
+  assertEquals((2600822924 & -0x20123456) | 1, (-0x20123456 & x) | 1, "14rev");
+
   assertEquals(2600822924 & 2600822924, x & x, "xx");
   assertEquals(y, y & y, "yy");
   assertEquals(z, z & z, "zz");
diff --git a/test/mjsunit/compiler/array-length.js b/test/mjsunit/compiler/array-length.js
index 7adb9ab..126c7a0 100644
--- a/test/mjsunit/compiler/array-length.js
+++ b/test/mjsunit/compiler/array-length.js
@@ -36,7 +36,7 @@
 var a0 = [];
 var a2 = [1,2];
 var a5 = [1,2,3,4,5];
-for (var i = 0; i < 10000000; i++) Test(a0, a2, a5);
+for (var i = 0; i < 100000; i++) Test(a0, a2, a5);
 assertEquals("undefined", typeof(ArrayLength(0)));
-for (var i = 0; i < 10000000; i++) Test(a0, a2, a5);
+for (var i = 0; i < 100000; i++) Test(a0, a2, a5);
 assertEquals(4, ArrayLength("hest"));
diff --git a/test/mjsunit/compiler/pic.js b/test/mjsunit/compiler/pic.js
index a0b5d8f..06f2b3e 100644
--- a/test/mjsunit/compiler/pic.js
+++ b/test/mjsunit/compiler/pic.js
@@ -53,7 +53,7 @@
 
 // Run the test until we're fairly sure we've optimized the
 // polymorphic property access.
-for (var i = 0; i < 1000000; i++) {
+for (var i = 0; i < 100000; i++) {
   Test(o1);
   Test(o2);
   Test(o3);
diff --git a/test/cctest/test-mips.cc b/test/mjsunit/compiler/regress-loadfield.js
similarity index 69%
copy from test/cctest/test-mips.cc
copy to test/mjsunit/compiler/regress-loadfield.js
index efd4cc9..a202891 100644
--- a/test/cctest/test-mips.cc
+++ b/test/mjsunit/compiler/regress-loadfield.js
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -25,28 +25,41 @@
 // (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 GVN on field loads.
 
-#include "v8.h"
-#include "execution.h"
+function bar() {}
 
-#include "cctest.h"
+// Make sure there is a transition on adding "bar" inobject property.
+var b = new bar();
+b.bar = "bar";
 
-using ::v8::Local;
-using ::v8::String;
-using ::v8::Script;
+function test(a) {
+  var b = new Array(10);
+  for (var i = 0; i < 10; i++) {
+    b[i] = new bar();
+  }
 
-namespace i = ::v8::internal;
-
-TEST(MIPSFunctionCalls) {
-  // Disable compilation of natives.
-  i::FLAG_disable_native_files = true;
-  i::FLAG_full_compiler = false;
-
-  v8::HandleScope scope;
-  LocalContext env;  // from cctest.h
-
-  const char* c_source = "function foo() { return 0x1234; }; foo();";
-  Local<String> source = ::v8::String::New(c_source);
-  Local<Script> script = ::v8::Script::Compile(source);
-  CHECK_EQ(0x1234,  script->Run()->Int32Value());
+  for (var i = 0; i < 10; i++) {
+    b[i].bar = a.foo;
+  }
 }
+
+// Create an object with fast backing store properties.
+var a = {};
+a.p1 = "";
+a.p2 = "";
+a.p3 = "";
+a.p4 = "";
+a.p5 = "";
+a.p6 = "";
+a.p7 = "";
+a.p8 = "";
+a.p9 = "";
+a.p10 = "";
+a.p11 = "";
+a.foo = "foo";
+for (var i = 0; i < 100000; i++) {
+ test(a);
+}
+
+test("");
diff --git a/test/mjsunit/math-sqrt.js b/test/mjsunit/math-sqrt.js
index fb00d5b..43fbf6b 100644
--- a/test/mjsunit/math-sqrt.js
+++ b/test/mjsunit/math-sqrt.js
@@ -29,7 +29,11 @@
 
 function test(expected_sqrt, value) {
   assertEquals(expected_sqrt, Math.sqrt(value));
-  if (isFinite(value)) { 
+  if (isFinite(value)) {
+    if (value === 0 && (1 / value) == -Infinity) {
+      // Math.pow(-0, 0.5) must be zero, but Math.sqrt(-0) is -0.
+      expected_sqrt = 0;
+    }
     assertEquals(expected_sqrt, Math.pow(value, 0.5));
   }
 }
diff --git a/test/mjsunit/mjsunit.js b/test/mjsunit/mjsunit.js
index fe580f3..436bdc8 100644
--- a/test/mjsunit/mjsunit.js
+++ b/test/mjsunit/mjsunit.js
@@ -41,15 +41,62 @@
  * the f-word and ignore all other lines.
  */
 
+function MjsUnitToString(value) {
+  switch (typeof value) {
+    case "string":
+      return JSON.stringify(value);
+    case "number":
+      if (value === 0 && (1 / value) < 0) return "-0";
+    case "boolean":
+    case "null":
+    case "undefined":
+    case "function":
+      return String(value);
+    case "object":
+      if (value === null) return "null";
+      var clazz = Object.prototype.toString.call(value);
+      clazz = clazz.substring(8, clazz.length - 1);
+      switch (clazz) {
+        case "Number":
+        case "String":
+        case "Boolean":
+        case "Date":
+          return clazz + "(" + MjsUnitToString(value.valueOf()) + ")";
+        case "RegExp":
+          return value.toString();
+        case "Array":
+          return "[" + value.map(MjsUnitArrayElementToString).join(",") + "]";
+        case "Object":
+          break;
+        default:
+          return clazz + "()";
+      }
+      // [[Class]] is "Object".
+      var constructor = value.constructor.name;
+      if (name) return name + "()";
+      return "Object()";
+    default:
+      return "-- unknown value --";
+  }
+}
+
+
+function MjsUnitArrayElementToString(value, index, array) {
+  if (value === undefined && !(index in array)) return "";
+  return MjsUnitToString(value);
+}
+
+
 function fail(expected, found, name_opt) {
-  var start;
+  var message = "Fail" + "ure";
   if (name_opt) {
     // Fix this when we ditch the old test runner.
-    start = "Fail" + "ure (" + name_opt + "): ";
-  } else {
-    start = "Fail" + "ure:";
+    message += " (" + name_opt + ")";
   }
-  throw new MjsUnitAssertionError(start + " expected <" + expected + "> found <" + found + ">");
+
+  message += ": expected <" + MjsUnitToString(expected) +
+      "> found <" + MjsUnitToString(found) + ">";
+  throw new MjsUnitAssertionError(message);
 }
 
 
@@ -73,13 +120,17 @@
 
 
 function deepEquals(a, b) {
-  if (a == b) return true;
+  if (a == b) {
+    // Check for -0.
+    if (a === 0 && b === 0) return (1 / a) === (1 / b);
+    return true;
+  }
   if (typeof a == "number" && typeof b == "number" && isNaN(a) && isNaN(b)) {
     return true;
   }
   if (a == null || b == null) return false;
   if (a.constructor === RegExp || b.constructor === RegExp) {
-    return (a.constructor === b.constructor) && (a.toString === b.toString);
+    return (a.constructor === b.constructor) && (a.toString() === b.toString());
   }
   if ((typeof a) !== 'object' || (typeof b) !== 'object' ||
       (a === null) || (b === null))
@@ -205,7 +256,7 @@
 
 function assertUnreachable(name_opt) {
   // Fix this when we ditch the old test runner.
-  var message = "Fail" + "ure: unreachable"
+  var message = "Fail" + "ure: unreachable";
   if (name_opt) {
     message += " - " + name_opt;
   }
diff --git a/test/mjsunit/mul-exhaustive.js b/test/mjsunit/mul-exhaustive.js
index 452f933..12689db 100644
--- a/test/mjsunit/mul-exhaustive.js
+++ b/test/mjsunit/mul-exhaustive.js
@@ -26,41 +26,64 @@
 // 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);
+// Converts a number to string respecting -0.
+function stringify(n) {
+  if ((1 / n) === -Infinity) return "-0";
+  return String(n);
 }
 
+function f(expected, y) {
+  function testEval(string, x, y) {
+    var mulFunction = Function("x, y", "return " + string);
+    return mulFunction(x, y);
+  }
+  function mulTest(expected, x, y) {
+    assertEquals(expected, x * y);
+    assertEquals(expected, testEval(stringify(x) + " * y", x, y));
+    assertEquals(expected, testEval("x * " + stringify(y), x, y));
+    assertEquals(expected, testEval(stringify(x) + " * " + stringify(y), x, y));
+  }
+  mulTest(expected, x, y);
+  mulTest(-expected, -x, y);
+  mulTest(-expected, x, -y);
+  mulTest(expected, -x, -y);
+  if (x === y) return;  // Symmetric cases not necessary.
+  mulTest(expected, y, x);
+  mulTest(-expected, -y, x);
+  mulTest(-expected, y, -x);
+  mulTest(expected, -y, -x);
+}
+
+x = 0;
+f(0, 0);
 x = 1;
+f(0, 0);
 f(1, 1);
 x = 2;
+f(0, 0);
 f(2, 1);
 f(4, 2);
 x = 3;
+f(0, 0);
 f(3, 1);
 f(6, 2);
 f(9, 3);
 x = 4;
+f(0, 0);
 f(4, 1);
 f(8, 2);
 f(12, 3);
 f(16, 4);
 x = 5;
+f(0, 0);
 f(5, 1);
 f(10, 2);
 f(15, 3);
 f(20, 4);
 f(25, 5);
 x = 7;
+f(0, 0);
 f(7, 1);
 f(14, 2);
 f(21, 3);
@@ -68,6 +91,7 @@
 f(35, 5);
 f(49, 7);
 x = 8;
+f(0, 0);
 f(8, 1);
 f(16, 2);
 f(24, 3);
@@ -76,6 +100,7 @@
 f(56, 7);
 f(64, 8);
 x = 9;
+f(0, 0);
 f(9, 1);
 f(18, 2);
 f(27, 3);
@@ -85,6 +110,7 @@
 f(72, 8);
 f(81, 9);
 x = 15;
+f(0, 0);
 f(15, 1);
 f(30, 2);
 f(45, 3);
@@ -95,6 +121,7 @@
 f(135, 9);
 f(225, 15);
 x = 16;
+f(0, 0);
 f(16, 1);
 f(32, 2);
 f(48, 3);
@@ -106,6 +133,7 @@
 f(240, 15);
 f(256, 16);
 x = 17;
+f(0, 0);
 f(17, 1);
 f(34, 2);
 f(51, 3);
@@ -118,6 +146,7 @@
 f(272, 16);
 f(289, 17);
 x = 31;
+f(0, 0);
 f(31, 1);
 f(62, 2);
 f(93, 3);
@@ -131,6 +160,7 @@
 f(527, 17);
 f(961, 31);
 x = 32;
+f(0, 0);
 f(32, 1);
 f(64, 2);
 f(96, 3);
@@ -145,6 +175,7 @@
 f(992, 31);
 f(1024, 32);
 x = 33;
+f(0, 0);
 f(33, 1);
 f(66, 2);
 f(99, 3);
@@ -160,6 +191,7 @@
 f(1056, 32);
 f(1089, 33);
 x = 63;
+f(0, 0);
 f(63, 1);
 f(126, 2);
 f(189, 3);
@@ -176,6 +208,7 @@
 f(2079, 33);
 f(3969, 63);
 x = 64;
+f(0, 0);
 f(64, 1);
 f(128, 2);
 f(192, 3);
@@ -193,6 +226,7 @@
 f(4032, 63);
 f(4096, 64);
 x = 65;
+f(0, 0);
 f(65, 1);
 f(130, 2);
 f(195, 3);
@@ -211,6 +245,7 @@
 f(4160, 64);
 f(4225, 65);
 x = 127;
+f(0, 0);
 f(127, 1);
 f(254, 2);
 f(381, 3);
@@ -230,6 +265,7 @@
 f(8255, 65);
 f(16129, 127);
 x = 128;
+f(0, 0);
 f(128, 1);
 f(256, 2);
 f(384, 3);
@@ -250,6 +286,7 @@
 f(16256, 127);
 f(16384, 128);
 x = 129;
+f(0, 0);
 f(129, 1);
 f(258, 2);
 f(387, 3);
@@ -271,6 +308,7 @@
 f(16512, 128);
 f(16641, 129);
 x = 255;
+f(0, 0);
 f(255, 1);
 f(510, 2);
 f(765, 3);
@@ -293,6 +331,7 @@
 f(32895, 129);
 f(65025, 255);
 x = 256;
+f(0, 0);
 f(256, 1);
 f(512, 2);
 f(768, 3);
@@ -316,6 +355,7 @@
 f(65280, 255);
 f(65536, 256);
 x = 257;
+f(0, 0);
 f(257, 1);
 f(514, 2);
 f(771, 3);
@@ -340,6 +380,7 @@
 f(65792, 256);
 f(66049, 257);
 x = 511;
+f(0, 0);
 f(511, 1);
 f(1022, 2);
 f(1533, 3);
@@ -365,6 +406,7 @@
 f(131327, 257);
 f(261121, 511);
 x = 512;
+f(0, 0);
 f(512, 1);
 f(1024, 2);
 f(1536, 3);
@@ -391,6 +433,7 @@
 f(261632, 511);
 f(262144, 512);
 x = 513;
+f(0, 0);
 f(513, 1);
 f(1026, 2);
 f(1539, 3);
@@ -418,6 +461,7 @@
 f(262656, 512);
 f(263169, 513);
 x = 1023;
+f(0, 0);
 f(1023, 1);
 f(2046, 2);
 f(3069, 3);
@@ -446,6 +490,7 @@
 f(524799, 513);
 f(1046529, 1023);
 x = 1024;
+f(0, 0);
 f(1024, 1);
 f(2048, 2);
 f(3072, 3);
@@ -475,6 +520,7 @@
 f(1047552, 1023);
 f(1048576, 1024);
 x = 1025;
+f(0, 0);
 f(1025, 1);
 f(2050, 2);
 f(3075, 3);
@@ -505,6 +551,7 @@
 f(1049600, 1024);
 f(1050625, 1025);
 x = 2047;
+f(0, 0);
 f(2047, 1);
 f(4094, 2);
 f(6141, 3);
@@ -536,6 +583,7 @@
 f(2098175, 1025);
 f(4190209, 2047);
 x = 2048;
+f(0, 0);
 f(2048, 1);
 f(4096, 2);
 f(6144, 3);
@@ -568,6 +616,7 @@
 f(4192256, 2047);
 f(4194304, 2048);
 x = 2049;
+f(0, 0);
 f(2049, 1);
 f(4098, 2);
 f(6147, 3);
@@ -601,6 +650,7 @@
 f(4196352, 2048);
 f(4198401, 2049);
 x = 4095;
+f(0, 0);
 f(4095, 1);
 f(8190, 2);
 f(12285, 3);
@@ -635,6 +685,7 @@
 f(8390655, 2049);
 f(16769025, 4095);
 x = 4096;
+f(0, 0);
 f(4096, 1);
 f(8192, 2);
 f(12288, 3);
@@ -670,6 +721,7 @@
 f(16773120, 4095);
 f(16777216, 4096);
 x = 4097;
+f(0, 0);
 f(4097, 1);
 f(8194, 2);
 f(12291, 3);
@@ -706,6 +758,7 @@
 f(16781312, 4096);
 f(16785409, 4097);
 x = 8191;
+f(0, 0);
 f(8191, 1);
 f(16382, 2);
 f(24573, 3);
@@ -743,6 +796,7 @@
 f(33558527, 4097);
 f(67092481, 8191);
 x = 8192;
+f(0, 0);
 f(8192, 1);
 f(16384, 2);
 f(24576, 3);
@@ -781,6 +835,7 @@
 f(67100672, 8191);
 f(67108864, 8192);
 x = 8193;
+f(0, 0);
 f(8193, 1);
 f(16386, 2);
 f(24579, 3);
@@ -820,6 +875,7 @@
 f(67117056, 8192);
 f(67125249, 8193);
 x = 16383;
+f(0, 0);
 f(16383, 1);
 f(32766, 2);
 f(49149, 3);
@@ -860,6 +916,7 @@
 f(134225919, 8193);
 f(268402689, 16383);
 x = 16384;
+f(0, 0);
 f(16384, 1);
 f(32768, 2);
 f(49152, 3);
@@ -901,6 +958,7 @@
 f(268419072, 16383);
 f(268435456, 16384);
 x = 16385;
+f(0, 0);
 f(16385, 1);
 f(32770, 2);
 f(49155, 3);
@@ -943,6 +1001,7 @@
 f(268451840, 16384);
 f(268468225, 16385);
 x = 32767;
+f(0, 0);
 f(32767, 1);
 f(65534, 2);
 f(98301, 3);
@@ -986,6 +1045,7 @@
 f(536887295, 16385);
 f(1073676289, 32767);
 x = 32768;
+f(0, 0);
 f(32768, 1);
 f(65536, 2);
 f(98304, 3);
@@ -1030,6 +1090,7 @@
 f(1073709056, 32767);
 f(1073741824, 32768);
 x = 32769;
+f(0, 0);
 f(32769, 1);
 f(65538, 2);
 f(98307, 3);
@@ -1075,6 +1136,7 @@
 f(1073774592, 32768);
 f(1073807361, 32769);
 x = 65535;
+f(0, 0);
 f(65535, 1);
 f(131070, 2);
 f(196605, 3);
@@ -1121,6 +1183,7 @@
 f(2147516415, 32769);
 f(4294836225, 65535);
 x = 65536;
+f(0, 0);
 f(65536, 1);
 f(131072, 2);
 f(196608, 3);
@@ -1168,6 +1231,7 @@
 f(4294901760, 65535);
 f(4294967296, 65536);
 x = 65537;
+f(0, 0);
 f(65537, 1);
 f(131074, 2);
 f(196611, 3);
@@ -1216,6 +1280,7 @@
 f(4295032832, 65536);
 f(4295098369, 65537);
 x = 131071;
+f(0, 0);
 f(131071, 1);
 f(262142, 2);
 f(393213, 3);
@@ -1265,6 +1330,7 @@
 f(8590000127, 65537);
 f(17179607041, 131071);
 x = 131072;
+f(0, 0);
 f(131072, 1);
 f(262144, 2);
 f(393216, 3);
@@ -1315,6 +1381,7 @@
 f(17179738112, 131071);
 f(17179869184, 131072);
 x = 131073;
+f(0, 0);
 f(131073, 1);
 f(262146, 2);
 f(393219, 3);
@@ -1366,6 +1433,7 @@
 f(17180000256, 131072);
 f(17180131329, 131073);
 x = 262143;
+f(0, 0);
 f(262143, 1);
 f(524286, 2);
 f(786429, 3);
@@ -1418,6 +1486,7 @@
 f(34359869439, 131073);
 f(68718952449, 262143);
 x = 262144;
+f(0, 0);
 f(262144, 1);
 f(524288, 2);
 f(786432, 3);
@@ -1471,6 +1540,7 @@
 f(68719214592, 262143);
 f(68719476736, 262144);
 x = 262145;
+f(0, 0);
 f(262145, 1);
 f(524290, 2);
 f(786435, 3);
@@ -1525,6 +1595,7 @@
 f(68719738880, 262144);
 f(68720001025, 262145);
 x = 524287;
+f(0, 0);
 f(524287, 1);
 f(1048574, 2);
 f(1572861, 3);
@@ -1580,6 +1651,7 @@
 f(137439215615, 262145);
 f(274876858369, 524287);
 x = 524288;
+f(0, 0);
 f(524288, 1);
 f(1048576, 2);
 f(1572864, 3);
@@ -1636,6 +1708,7 @@
 f(274877382656, 524287);
 f(274877906944, 524288);
 x = 524289;
+f(0, 0);
 f(524289, 1);
 f(1048578, 2);
 f(1572867, 3);
@@ -1693,6 +1766,7 @@
 f(274878431232, 524288);
 f(274878955521, 524289);
 x = 1048575;
+f(0, 0);
 f(1048575, 1);
 f(2097150, 2);
 f(3145725, 3);
@@ -1751,6 +1825,7 @@
 f(549756338175, 524289);
 f(1099509530625, 1048575);
 x = 1048576;
+f(0, 0);
 f(1048576, 1);
 f(2097152, 2);
 f(3145728, 3);
@@ -1810,6 +1885,7 @@
 f(1099510579200, 1048575);
 f(1099511627776, 1048576);
 x = 1048577;
+f(0, 0);
 f(1048577, 1);
 f(2097154, 2);
 f(3145731, 3);
@@ -1870,6 +1946,7 @@
 f(1099512676352, 1048576);
 f(1099513724929, 1048577);
 x = 2097151;
+f(0, 0);
 f(2097151, 1);
 f(4194302, 2);
 f(6291453, 3);
@@ -1931,6 +2008,7 @@
 f(2199024304127, 1048577);
 f(4398042316801, 2097151);
 x = 2097152;
+f(0, 0);
 f(2097152, 1);
 f(4194304, 2);
 f(6291456, 3);
@@ -1993,6 +2071,7 @@
 f(4398044413952, 2097151);
 f(4398046511104, 2097152);
 x = 2097153;
+f(0, 0);
 f(2097153, 1);
 f(4194306, 2);
 f(6291459, 3);
@@ -2056,6 +2135,7 @@
 f(4398048608256, 2097152);
 f(4398050705409, 2097153);
 x = 4194303;
+f(0, 0);
 f(4194303, 1);
 f(8388606, 2);
 f(12582909, 3);
@@ -2120,6 +2200,7 @@
 f(8796095119359, 2097153);
 f(17592177655809, 4194303);
 x = 4194304;
+f(0, 0);
 f(4194304, 1);
 f(8388608, 2);
 f(12582912, 3);
@@ -2185,6 +2266,7 @@
 f(17592181850112, 4194303);
 f(17592186044416, 4194304);
 x = 4194305;
+f(0, 0);
 f(4194305, 1);
 f(8388610, 2);
 f(12582915, 3);
@@ -2251,6 +2333,7 @@
 f(17592190238720, 4194304);
 f(17592194433025, 4194305);
 x = 8388607;
+f(0, 0);
 f(8388607, 1);
 f(16777214, 2);
 f(25165821, 3);
@@ -2318,6 +2401,7 @@
 f(35184376283135, 4194305);
 f(70368727400449, 8388607);
 x = 8388608;
+f(0, 0);
 f(8388608, 1);
 f(16777216, 2);
 f(25165824, 3);
@@ -2386,6 +2470,7 @@
 f(70368735789056, 8388607);
 f(70368744177664, 8388608);
 x = 8388609;
+f(0, 0);
 f(8388609, 1);
 f(16777218, 2);
 f(25165827, 3);
@@ -2455,6 +2540,7 @@
 f(70368752566272, 8388608);
 f(70368760954881, 8388609);
 x = 16777215;
+f(0, 0);
 f(16777215, 1);
 f(33554430, 2);
 f(50331645, 3);
@@ -2525,6 +2611,7 @@
 f(140737496743935, 8388609);
 f(281474943156225, 16777215);
 x = 16777216;
+f(0, 0);
 f(16777216, 1);
 f(33554432, 2);
 f(50331648, 3);
@@ -2596,6 +2683,7 @@
 f(281474959933440, 16777215);
 f(281474976710656, 16777216);
 x = 16777217;
+f(0, 0);
 f(16777217, 1);
 f(33554434, 2);
 f(50331651, 3);
@@ -2668,6 +2756,7 @@
 f(281474993487872, 16777216);
 f(281475010265089, 16777217);
 x = 33554431;
+f(0, 0);
 f(33554431, 1);
 f(67108862, 2);
 f(100663293, 3);
@@ -2741,6 +2830,7 @@
 f(562949970198527, 16777217);
 f(1125899839733761, 33554431);
 x = 33554432;
+f(0, 0);
 f(33554432, 1);
 f(67108864, 2);
 f(100663296, 3);
@@ -2815,6 +2905,7 @@
 f(1125899873288192, 33554431);
 f(1125899906842624, 33554432);
 x = 33554433;
+f(0, 0);
 f(33554433, 1);
 f(67108866, 2);
 f(100663299, 3);
@@ -2890,6 +2981,7 @@
 f(1125899940397056, 33554432);
 f(1125899973951489, 33554433);
 x = 67108863;
+f(0, 0);
 f(67108863, 1);
 f(134217726, 2);
 f(201326589, 3);
@@ -2962,6 +3054,7 @@
 f(1125899890065408, 16777216);
 f(1125899957174271, 16777217);
 x = 67108864;
+f(0, 0);
 f(67108864, 1);
 f(134217728, 2);
 f(201326592, 3);
@@ -3034,6 +3127,7 @@
 f(1125899906842624, 16777216);
 f(1125899973951488, 16777217);
 x = 67108865;
+f(0, 0);
 f(67108865, 1);
 f(134217730, 2);
 f(201326595, 3);
@@ -3106,6 +3200,7 @@
 f(1125899923619840, 16777216);
 f(1125899990728705, 16777217);
 x = 134217727;
+f(0, 0);
 f(134217727, 1);
 f(268435454, 2);
 f(402653181, 3);
@@ -3175,6 +3270,7 @@
 f(1125899898454016, 8388608);
 f(1125900032671743, 8388609);
 x = 134217728;
+f(0, 0);
 f(134217728, 1);
 f(268435456, 2);
 f(402653184, 3);
@@ -3244,6 +3340,7 @@
 f(1125899906842624, 8388608);
 f(1125900041060352, 8388609);
 x = 134217729;
+f(0, 0);
 f(134217729, 1);
 f(268435458, 2);
 f(402653187, 3);
@@ -3313,6 +3410,7 @@
 f(1125899915231232, 8388608);
 f(1125900049448961, 8388609);
 x = 268435455;
+f(0, 0);
 f(268435455, 1);
 f(536870910, 2);
 f(805306365, 3);
@@ -3379,6 +3477,7 @@
 f(1125899902648320, 4194304);
 f(1125900171083775, 4194305);
 x = 268435456;
+f(0, 0);
 f(268435456, 1);
 f(536870912, 2);
 f(805306368, 3);
@@ -3445,6 +3544,7 @@
 f(1125899906842624, 4194304);
 f(1125900175278080, 4194305);
 x = 268435457;
+f(0, 0);
 f(268435457, 1);
 f(536870914, 2);
 f(805306371, 3);
@@ -3511,6 +3611,7 @@
 f(1125899911036928, 4194304);
 f(1125900179472385, 4194305);
 x = 536870911;
+f(0, 0);
 f(536870911, 1);
 f(1073741822, 2);
 f(1610612733, 3);
@@ -3574,6 +3675,7 @@
 f(1125899904745472, 2097152);
 f(1125900441616383, 2097153);
 x = 536870912;
+f(0, 0);
 f(536870912, 1);
 f(1073741824, 2);
 f(1610612736, 3);
@@ -3637,6 +3739,7 @@
 f(1125899906842624, 2097152);
 f(1125900443713536, 2097153);
 x = 536870913;
+f(0, 0);
 f(536870913, 1);
 f(1073741826, 2);
 f(1610612739, 3);
@@ -3700,6 +3803,7 @@
 f(1125899908939776, 2097152);
 f(1125900445810689, 2097153);
 x = 1073741823;
+f(0, 0);
 f(1073741823, 1);
 f(2147483646, 2);
 f(3221225469, 3);
@@ -3760,6 +3864,7 @@
 f(1125899905794048, 1048576);
 f(1125900979535871, 1048577);
 x = 1073741824;
+f(0, 0);
 f(1073741824, 1);
 f(2147483648, 2);
 f(3221225472, 3);
@@ -3820,6 +3925,7 @@
 f(1125899906842624, 1048576);
 f(1125900980584448, 1048577);
 x = 1073741825;
+f(0, 0);
 f(1073741825, 1);
 f(2147483650, 2);
 f(3221225475, 3);
@@ -3880,6 +3986,7 @@
 f(1125899907891200, 1048576);
 f(1125900981633025, 1048577);
 x = 2147483647;
+f(0, 0);
 f(2147483647, 1);
 f(4294967294, 2);
 f(6442450941, 3);
@@ -3937,6 +4044,7 @@
 f(1125899906318336, 524288);
 f(1125902053801983, 524289);
 x = 2147483648;
+f(0, 0);
 f(2147483648, 1);
 f(4294967296, 2);
 f(6442450944, 3);
@@ -3994,6 +4102,7 @@
 f(1125899906842624, 524288);
 f(1125902054326272, 524289);
 x = 2147483649;
+f(0, 0);
 f(2147483649, 1);
 f(4294967298, 2);
 f(6442450947, 3);
@@ -4051,6 +4160,7 @@
 f(1125899907366912, 524288);
 f(1125902054850561, 524289);
 x = 4294967295;
+f(0, 0);
 f(4294967295, 1);
 f(8589934590, 2);
 f(12884901885, 3);
@@ -4105,6 +4215,7 @@
 f(1125899906580480, 262144);
 f(1125904201547775, 262145);
 x = 4294967296;
+f(0, 0);
 f(4294967296, 1);
 f(8589934592, 2);
 f(12884901888, 3);
@@ -4159,6 +4270,7 @@
 f(1125899906842624, 262144);
 f(1125904201809920, 262145);
 x = 4294967297;
+f(0, 0);
 f(4294967297, 1);
 f(8589934594, 2);
 f(12884901891, 3);
@@ -4213,6 +4325,7 @@
 f(1125899907104768, 262144);
 f(1125904202072065, 262145);
 x = 8589934591;
+f(0, 0);
 f(8589934591, 1);
 f(17179869182, 2);
 f(25769803773, 3);
@@ -4264,6 +4377,7 @@
 f(1125899906711552, 131072);
 f(1125908496646143, 131073);
 x = 8589934592;
+f(0, 0);
 f(8589934592, 1);
 f(17179869184, 2);
 f(25769803776, 3);
@@ -4315,6 +4429,7 @@
 f(1125899906842624, 131072);
 f(1125908496777216, 131073);
 x = 8589934593;
+f(0, 0);
 f(8589934593, 1);
 f(17179869186, 2);
 f(25769803779, 3);
@@ -4366,6 +4481,7 @@
 f(1125899906973696, 131072);
 f(1125908496908289, 131073);
 x = 17179869183;
+f(0, 0);
 f(17179869183, 1);
 f(34359738366, 2);
 f(51539607549, 3);
@@ -4414,6 +4530,7 @@
 f(1125899906777088, 65536);
 f(1125917086646271, 65537);
 x = 17179869184;
+f(0, 0);
 f(17179869184, 1);
 f(34359738368, 2);
 f(51539607552, 3);
@@ -4462,6 +4579,7 @@
 f(1125899906842624, 65536);
 f(1125917086711808, 65537);
 x = 17179869185;
+f(0, 0);
 f(17179869185, 1);
 f(34359738370, 2);
 f(51539607555, 3);
diff --git a/test/mjsunit/negate-zero.js b/test/mjsunit/negate-zero.js
index 31d460a..558be94 100644
--- a/test/mjsunit/negate-zero.js
+++ b/test/mjsunit/negate-zero.js
@@ -26,7 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 function IsNegativeZero(x) {
-  assertEquals(0, x);
+  assertTrue(x == 0);  // Is 0 or -0.
   var y = 1 / x;
   assertFalse(isFinite(y));
   return y < 0;
diff --git a/test/mjsunit/object-freeze.js b/test/mjsunit/object-freeze.js
index 15e19ab..3eefffd 100644
--- a/test/mjsunit/object-freeze.js
+++ b/test/mjsunit/object-freeze.js
@@ -70,12 +70,8 @@
 assertFalse(Object.isExtensible(obj));
 assertTrue(Object.isFrozen(obj));
 
-try {
-   obj.foo = 42;
-   assertUnreachable();
-} catch(e) {
-  assertTrue(/object is not extensible/.test(e));
-}
+obj.foo = 42;
+assertEquals(obj.foo, undefined);
 
 desc = Object.getOwnPropertyDescriptor(obj, 'x');
 assertFalse(desc.writable);
@@ -88,7 +84,7 @@
 assertEquals("foobar", desc.value);
 
 // Make sure that even if we try overwrite a value that is not writable, it is
-// not changed. 
+// not changed.
 obj.x = "tete";
 assertEquals(42, obj.x);
 obj.x = { get: function() {return 43}, set: function() {} };
@@ -118,12 +114,8 @@
 assertEquals(set, desc.set);
 assertEquals(get, desc.get);
 
-try {
-  obj2.foo = 42;
-  assertUnreachable();
-} catch(e) {
-  assertTrue(/object is not extensible/.test(e));
-}
+obj2.foo = 42;
+assertEquals(obj2.foo, undefined);
 
 
 // Test freeze on arrays.
diff --git a/test/mjsunit/object-prevent-extensions.js b/test/mjsunit/object-prevent-extensions.js
index ebc2cfa6..dc32342 100644
--- a/test/mjsunit/object-prevent-extensions.js
+++ b/test/mjsunit/object-prevent-extensions.js
@@ -35,22 +35,11 @@
 
 // Make sure the is_extensible flag is set. 
 assertFalse(Object.isExtensible(obj1));
-// Try adding a new property.
-try {
-  obj1.x = 42;
-  assertUnreachable();
-} catch (e) {
-  assertTrue(/object is not extensible/.test(e));
-}
+obj1.x = 42;
 assertEquals(undefined, obj1.x);
 
 // Try adding a new element.
-try {
-  obj1[1] = 42;
-  assertUnreachable();
-} catch (e) {
-  assertTrue(/object is not extensible/.test(e));
-}
+obj1[1] = 42;
 assertEquals(undefined, obj1[1]);
 
 
@@ -64,25 +53,14 @@
 Object.preventExtensions(obj2);
 assertEquals(42, obj2.x);
 
-try {
-  obj2.y = 42;
-  assertUnreachable();
-} catch (e) {
-  assertTrue(/object is not extensible/.test(e));
-}
-
+obj2.y = 42;
 // obj2.y should still be undefined.
 assertEquals(undefined, obj2.y);
 // Make sure we can still write values to obj.x.
 obj2.x = 43;
 assertEquals(43, obj2.x)
 
-try {
-  obj2.y = new function() { return 42; };
-  assertUnreachable();
-} catch (e) {
-  assertTrue(/object is not extensible/.test(e));
-}
+obj2.y = new function() { return 42; };
 // obj2.y should still be undefined.
 assertEquals(undefined, obj2.y);
 assertEquals(43, obj2.x)
@@ -97,12 +75,7 @@
 assertEquals(undefined, obj2.y);
 assertEquals(43, obj2.x);
 
-try {
-  obj2[1] = 42;
-} catch (e) {
-  assertTrue(/object is not extensible/.test(e));
-}
-
+obj2[1] = 42;
 assertEquals(undefined, obj2[1]);
 
 var arr = new Array();
@@ -110,12 +83,7 @@
 
 Object.preventExtensions(arr);
 
-try {
-  arr[2] = 42;
-  assertUnreachable();
-} catch (e) {
-  assertTrue(/object is not extensible/.test(e));
-}
+arr[2] = 42;
 assertEquals(10, arr[1]);
 
 // We should still be able to change exiting elements.
@@ -134,12 +102,7 @@
 child.y = 42;
 
 // This should have no influence on the parent class.
-try {
-  parent.y = 29;
-  assertUnreachable();
-} catch (e) {
-  assertTrue(/object is not extensible/.test(e));
-}
+parent.y = 29;
 
 
 // Test that attributes on functions are also handled correctly.
@@ -149,9 +112,5 @@
 
 Object.preventExtensions(foo);
 
-try {
-  foo.x = 29;
-  assertUnreachable();
-} catch (e) {
-  assertTrue(/object is not extensible/.test(e));
-}
+foo.x = 29;
+assertEquals(undefined, foo.x);
diff --git a/test/mjsunit/object-seal.js b/test/mjsunit/object-seal.js
index 9e7f44b..3ce2367 100644
--- a/test/mjsunit/object-seal.js
+++ b/test/mjsunit/object-seal.js
@@ -75,12 +75,8 @@
 assertFalse(Object.isFrozen(obj));
 
 // We should not allow new properties to be added.
-try {
-   obj.foo = 42;
-   assertUnreachable();
-} catch(e) {
-  assertTrue(/object is not extensible/.test(e));
-}
+obj.foo = 42;
+assertEquals(obj.foo, undefined);
 
 desc = Object.getOwnPropertyDescriptor(obj, 'x');
 assertTrue(desc.writable);
@@ -125,13 +121,8 @@
 assertEquals(set, desc.set);
 assertEquals(get, desc.get);
 
-try {
-  obj2.foo = 42;
-  assertUnreachable();
-} catch(e) {
-  assertTrue(/object is not extensible/.test(e));
-}
-
+obj2.foo = 42;
+assertEquals(obj2.foo, undefined);
 
 // Test seal on arrays.
 var arr = new Array(42,43);
diff --git a/test/cctest/test-mips.cc b/test/mjsunit/regress/regress-1233.js
similarity index 69%
copy from test/cctest/test-mips.cc
copy to test/mjsunit/regress/regress-1233.js
index efd4cc9..a09b715 100644
--- a/test/cctest/test-mips.cc
+++ b/test/mjsunit/regress/regress-1233.js
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -25,28 +25,23 @@
 // (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 Object.freeze and Object.getOwnPropertyDescriptor do not
+// call toString or valueOf on members of the object.
 
-#include "v8.h"
-#include "execution.h"
+// See http://code.google.com/p/v8/issues/detail?id=1233.
 
-#include "cctest.h"
 
-using ::v8::Local;
-using ::v8::String;
-using ::v8::Script;
+var delicate = new Object();
+delicate.toString = function(){ throw Error("toString"); };
+delicate.valueOf = function(){ throw Error("valueOf"); };
 
-namespace i = ::v8::internal;
+var x = { foo: delicate };
 
-TEST(MIPSFunctionCalls) {
-  // Disable compilation of natives.
-  i::FLAG_disable_native_files = true;
-  i::FLAG_full_compiler = false;
+var status = "fail";
+try {
+  Object.getOwnPropertyDescriptor(x, "foo");
+  Object.freeze(x);
+  status = "succeed";
+} catch (e) {}
 
-  v8::HandleScope scope;
-  LocalContext env;  // from cctest.h
-
-  const char* c_source = "function foo() { return 0x1234; }; foo();";
-  Local<String> source = ::v8::String::New(c_source);
-  Local<Script> script = ::v8::Script::Compile(source);
-  CHECK_EQ(0x1234,  script->Run()->Int32Value());
-}
+assertEquals("succeed", status);
diff --git a/test/cctest/test-mips.cc b/test/mjsunit/regress/regress-1236.js
similarity index 69%
copy from test/cctest/test-mips.cc
copy to test/mjsunit/regress/regress-1236.js
index efd4cc9..48e3d3d 100644
--- a/test/cctest/test-mips.cc
+++ b/test/mjsunit/regress/regress-1236.js
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -25,28 +25,10 @@
 // (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.
 
-#include "v8.h"
-#include "execution.h"
-
-#include "cctest.h"
-
-using ::v8::Local;
-using ::v8::String;
-using ::v8::Script;
-
-namespace i = ::v8::internal;
-
-TEST(MIPSFunctionCalls) {
-  // Disable compilation of natives.
-  i::FLAG_disable_native_files = true;
-  i::FLAG_full_compiler = false;
-
-  v8::HandleScope scope;
-  LocalContext env;  // from cctest.h
-
-  const char* c_source = "function foo() { return 0x1234; }; foo();";
-  Local<String> source = ::v8::String::New(c_source);
-  Local<Script> script = ::v8::Script::Compile(source);
-  CHECK_EQ(0x1234,  script->Run()->Int32Value());
-}
+pattern = RegExp("","");  // RegExp is irrelevant, as long as it's not an atom.
+string = 'a';             // Anything non-empty (flat ASCII).
+pattern.exec(string);     // Ensure that JSRegExp is compiled.
+pattern["@"] = 42;        // Change layout of JSRegExp object.
+pattern.exec(string);     // Call again to trigger bug in stub.
diff --git a/test/cctest/test-mips.cc b/test/mjsunit/regress/regress-1237.js
similarity index 69%
copy from test/cctest/test-mips.cc
copy to test/mjsunit/regress/regress-1237.js
index efd4cc9..f97f978 100644
--- a/test/cctest/test-mips.cc
+++ b/test/mjsunit/regress/regress-1237.js
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -25,28 +25,12 @@
 // (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 "cctest.h"
-
-using ::v8::Local;
-using ::v8::String;
-using ::v8::Script;
-
-namespace i = ::v8::internal;
-
-TEST(MIPSFunctionCalls) {
-  // Disable compilation of natives.
-  i::FLAG_disable_native_files = true;
-  i::FLAG_full_compiler = false;
-
-  v8::HandleScope scope;
-  LocalContext env;  // from cctest.h
-
-  const char* c_source = "function foo() { return 0x1234; }; foo();";
-  Local<String> source = ::v8::String::New(c_source);
-  Local<Script> script = ::v8::Script::Compile(source);
-  CHECK_EQ(0x1234,  script->Run()->Int32Value());
+// Deoptimization after a conditional expression in an effect context should
+// not see the value of the expression.
+function observe(x, y) { return x; }
+function test(x) {
+  return observe(1, ((x? observe(observe.prototype.x): 'c'), x + 1));
 }
+
+for (var i = 0; i < 10000000; ++i) test(0);
+test("a");
diff --git a/test/cctest/test-mips.cc b/test/mjsunit/regress/regress-1240.js
similarity index 69%
copy from test/cctest/test-mips.cc
copy to test/mjsunit/regress/regress-1240.js
index efd4cc9..1a0bf2e 100644
--- a/test/cctest/test-mips.cc
+++ b/test/mjsunit/regress/regress-1240.js
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -25,28 +25,15 @@
 // (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 regression tests that we are not allowed to overwrite an existing
+// non-configurable getter with a new getter. In addition, we should not
+// be able to change the configurable flag from false to true.
 
-#include "v8.h"
-#include "execution.h"
-
-#include "cctest.h"
-
-using ::v8::Local;
-using ::v8::String;
-using ::v8::Script;
-
-namespace i = ::v8::internal;
-
-TEST(MIPSFunctionCalls) {
-  // Disable compilation of natives.
-  i::FLAG_disable_native_files = true;
-  i::FLAG_full_compiler = false;
-
-  v8::HandleScope scope;
-  LocalContext env;  // from cctest.h
-
-  const char* c_source = "function foo() { return 0x1234; }; foo();";
-  Local<String> source = ::v8::String::New(c_source);
-  Local<Script> script = ::v8::Script::Compile(source);
-  CHECK_EQ(0x1234,  script->Run()->Int32Value());
-}
+var a = {};
+Object.defineProperty(a, 'b',
+                      { get: function () { return 42; }, configurable: false });
+// Do not allow us to redefine b on a.
+a.__defineGetter__('b', function _b(){ return 'foo'; });
+assertEquals(42, a.b);
+var desc = Object.getOwnPropertyDescriptor(a, 'b');
+assertFalse(desc.configurable);
diff --git a/test/cctest/test-mips.cc b/test/mjsunit/regress/regress-1257.js
similarity index 69%
copy from test/cctest/test-mips.cc
copy to test/mjsunit/regress/regress-1257.js
index efd4cc9..c20fb86 100644
--- a/test/cctest/test-mips.cc
+++ b/test/mjsunit/regress/regress-1257.js
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -25,28 +25,34 @@
 // (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 g(y) { assertEquals(y, 12); }
 
-#include "v8.h"
-#include "execution.h"
+var X = 0;
 
-#include "cctest.h"
-
-using ::v8::Local;
-using ::v8::String;
-using ::v8::Script;
-
-namespace i = ::v8::internal;
-
-TEST(MIPSFunctionCalls) {
-  // Disable compilation of natives.
-  i::FLAG_disable_native_files = true;
-  i::FLAG_full_compiler = false;
-
-  v8::HandleScope scope;
-  LocalContext env;  // from cctest.h
-
-  const char* c_source = "function foo() { return 0x1234; }; foo();";
-  Local<String> source = ::v8::String::New(c_source);
-  Local<Script> script = ::v8::Script::Compile(source);
-  CHECK_EQ(0x1234,  script->Run()->Int32Value());
+function foo () {
+  var cnt = 0;
+  var l = -1;
+  var x = 0;
+  while (1) switch (l) {
+      case -1:
+        var y = x + 12;
+        l = 0;
+        break;
+      case 0:
+        // Loop for to hit OSR.
+        if (cnt++ < 10000000) {
+          l = 0;
+          break;
+        } else {
+          l = 1;
+          break;
+        }
+      case 1:
+        // This case will contain deoptimization
+        // because it has no type feedback.
+        g(y);
+        return;
+    };
 }
+
+foo();
diff --git a/test/cctest/test-mips.cc b/test/mjsunit/regress/regress-1278.js
similarity index 63%
copy from test/cctest/test-mips.cc
copy to test/mjsunit/regress/regress-1278.js
index efd4cc9..7ad8cda 100644
--- a/test/cctest/test-mips.cc
+++ b/test/mjsunit/regress/regress-1278.js
@@ -25,28 +25,45 @@
 // (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=1278
 
-#include "v8.h"
-#include "execution.h"
+// Test that that handling of 0/-0 is correct for binary operations when the
+// TypeRecordingBinaryOpStub transitions through different states.
 
-#include "cctest.h"
+function add(x, y) {
+  return x + y;
+}
 
-using ::v8::Local;
-using ::v8::String;
-using ::v8::Script;
+function sub(x, y) {
+  return x - y;
+}
 
-namespace i = ::v8::internal;
+function mul(x, y) {
+  return x * y;
+}
 
-TEST(MIPSFunctionCalls) {
-  // Disable compilation of natives.
-  i::FLAG_disable_native_files = true;
-  i::FLAG_full_compiler = false;
+function div(x, y) {
+  return x / y;
+}
 
-  v8::HandleScope scope;
-  LocalContext env;  // from cctest.h
+for (var i = 0; i < 10; i++) {
+  assertEquals(0, add(0, 0));
+  assertEquals(0, add(0, -0));
+  assertEquals(0, add(-0, 0));
+  assertEquals(-0, add(-0, -0));
 
-  const char* c_source = "function foo() { return 0x1234; }; foo();";
-  Local<String> source = ::v8::String::New(c_source);
-  Local<Script> script = ::v8::Script::Compile(source);
-  CHECK_EQ(0x1234,  script->Run()->Int32Value());
+  assertEquals(0, sub(0, 0));
+  assertEquals(0, sub(0, -0));
+  assertEquals(-0, sub(-0, 0));
+  assertEquals(0, sub(-0, -0));
+
+  assertEquals(0, mul(0, 0));
+  assertEquals(-0, mul(0, -0));
+  assertEquals(-0, mul(-0, 0));
+  assertEquals(0, mul(-0, -0));
+
+  assertEquals(0, div(0, 1));
+  assertEquals(-0, div(0, -1));
+  assertEquals(-0, div(-0, 1));
+  assertEquals(0, div(-0, -1));
 }
diff --git a/test/mjsunit/regress/regress-create-exception.js b/test/mjsunit/regress/regress-create-exception.js
index 2119ce2..d3face9 100644
--- a/test/mjsunit/regress/regress-create-exception.js
+++ b/test/mjsunit/regress/regress-create-exception.js
@@ -26,6 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --max-new-space-size=256
+"use strict";
 
 // Check for GC bug constructing exceptions.
 var v = [1, 2, 3, 4]
diff --git a/test/cctest/test-mips.cc b/test/mjsunit/regress/regress-lazy-deopt-reloc.js
similarity index 69%
copy from test/cctest/test-mips.cc
copy to test/mjsunit/regress/regress-lazy-deopt-reloc.js
index efd4cc9..f1fe6d5 100644
--- a/test/cctest/test-mips.cc
+++ b/test/mjsunit/regress/regress-lazy-deopt-reloc.js
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -25,28 +25,28 @@
 // (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 generate debug code since that will space things differently
+// in the generated code.
+// Flags: --allow-natives-syntax --expose-gc --nodebug-code
 
-#include "v8.h"
-#include "execution.h"
+// Regression test for issue where we did not pad the relocation
+// information enough to have room for lazy deoptimization.
 
-#include "cctest.h"
-
-using ::v8::Local;
-using ::v8::String;
-using ::v8::Script;
-
-namespace i = ::v8::internal;
-
-TEST(MIPSFunctionCalls) {
-  // Disable compilation of natives.
-  i::FLAG_disable_native_files = true;
-  i::FLAG_full_compiler = false;
-
-  v8::HandleScope scope;
-  LocalContext env;  // from cctest.h
-
-  const char* c_source = "function foo() { return 0x1234; }; foo();";
-  Local<String> source = ::v8::String::New(c_source);
-  Local<Script> script = ::v8::Script::Compile(source);
-  CHECK_EQ(0x1234,  script->Run()->Int32Value());
+function kaboom() {
+  var a = function () {},
+      b = function () {},
+      c, d = function () { var d = []; },
+      e = function () { var e = {}; };
+    c = function () { d(); b(); };
+    return function (x, y) {
+      c();
+      a();
+      return function f() { }({});
+    };
 }
+
+kaboom();
+
+%DeoptimizeFunction(kaboom);
+
+gc();
diff --git a/test/mjsunit/sin-cos.js b/test/mjsunit/sin-cos.js
index ae02451..e38dfdf 100644
--- a/test/mjsunit/sin-cos.js
+++ b/test/mjsunit/sin-cos.js
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -27,19 +27,24 @@
 
 // Test Math.sin and Math.cos.
 
-var input_sin = [0, Math.PI / 2];
-var input_cos = [0, Math.PI];
+function sinTest() {
+  assertEquals(0, Math.sin(0));
+  assertEquals(1, Math.sin(Math.PI / 2));
+}
 
-var output_sin = input_sin.map(Math.sin);
-var output_cos = input_cos.map(Math.cos);
+function cosTest() {
+  assertEquals(1, Math.cos(0));
+  assertEquals(-1, Math.cos(Math.PI));
+}
 
-var expected_sin = [0, 1];
-var expected_cos = [1, -1];
-
-assertArrayEquals(expected_sin, output_sin, "sine");
-assertArrayEquals(expected_cos, output_cos, "cosine");
+sinTest();
+cosTest();
 
 // By accident, the slow case for sine and cosine were both sine at
 // some point.  This is a regression test for that issue.
 var x = Math.pow(2, 70);
 assertTrue(Math.sin(x) != Math.cos(x));
+
+// Ensure that sine and log are not the same.
+x = 0.5;
+assertTrue(Math.sin(x) != Math.log(x));
diff --git a/test/mjsunit/smi-negative-zero.js b/test/mjsunit/smi-negative-zero.js
index ea2fa5a..1bab920 100644
--- a/test/mjsunit/smi-negative-zero.js
+++ b/test/mjsunit/smi-negative-zero.js
@@ -109,5 +109,5 @@
   return -x;
 }
 
-assertEquals(0, foo(x));
-assertEquals(0, foo(x));
+assertEquals(-0, foo(x));
+assertEquals(-0, foo(x));
diff --git a/test/mjsunit/str-to-num.js b/test/mjsunit/str-to-num.js
index 28e98d9..bbfa7d3 100644
--- a/test/mjsunit/str-to-num.js
+++ b/test/mjsunit/str-to-num.js
@@ -190,7 +190,7 @@
 assertEquals(Infinity,  toNumber("1e999"), "1e999");
 assertEquals(-Infinity, toNumber("-1e999"));
 assertEquals(0,         toNumber("1e-999"));
-assertEquals(0,         toNumber("-1e-999"));
+assertEquals(-0,        toNumber("-1e-999"));
 assertEquals(Infinity,  1 / toNumber("1e-999"), "1e-999");
 assertEquals(-Infinity, 1 / toNumber("-1e-999"));
 
diff --git a/test/mjsunit/strict-mode.js b/test/mjsunit/strict-mode.js
index 69be19c..84ccb30 100644
--- a/test/mjsunit/strict-mode.js
+++ b/test/mjsunit/strict-mode.js
@@ -957,3 +957,181 @@
   assertThrows(function() { str_obj.length = 1; }, TypeError);
   assertThrows(function() { str_cat.length = 1; }, TypeError);
 })();
+
+
+(function TestArgumentsAliasing() {
+  function strict(a, b) {
+    "use strict";
+    a = "c";
+    b = "d";
+    return [a, b, arguments[0], arguments[1]];
+  }
+
+  function nonstrict(a, b) {
+    a = "c";
+    b = "d";
+    return [a, b, arguments[0], arguments[1]];
+  }
+
+  assertEquals(["c", "d", "a", "b"], strict("a", "b"));
+  assertEquals(["c", "d", "c", "d"], nonstrict("a", "b"));
+})();
+
+
+function CheckPillDescriptor(func, name) {
+
+  function CheckPill(pill) {
+    assertEquals("function", typeof pill);
+    assertInstanceof(pill, Function);
+    pill.property = "value";
+    assertEquals(pill.value, undefined);
+    assertThrows(function() { 'use strict'; pill.property = "value"; },
+                 TypeError);
+    assertThrows(pill, TypeError);
+    assertEquals(pill.prototype, (function(){}).prototype);
+    var d = Object.getOwnPropertyDescriptor(pill, "prototype");
+    assertFalse(d.writable);
+    assertFalse(d.configurable);
+    assertFalse(d.enumerable);
+  }
+
+  var descriptor = Object.getOwnPropertyDescriptor(func, name);
+  CheckPill(descriptor.get)
+  CheckPill(descriptor.set);
+  assertFalse(descriptor.enumerable);
+  assertFalse(descriptor.configurable);
+}
+
+
+(function TestStrictFunctionPills() {
+  function strict() {
+    "use strict";
+  }
+  assertThrows(function() { strict.caller; }, TypeError);
+  assertThrows(function() { strict.arguments; }, TypeError);
+
+  var another = new Function("'use strict'");
+  assertThrows(function() { another.caller; }, TypeError);
+  assertThrows(function() { another.arguments; }, TypeError);
+
+  var third = (function() { "use strict"; return function() {}; })();
+  assertThrows(function() { third.caller; }, TypeError);
+  assertThrows(function() { third.arguments; }, TypeError);
+
+  CheckPillDescriptor(strict, "caller");
+  CheckPillDescriptor(strict, "arguments");
+  CheckPillDescriptor(another, "caller");
+  CheckPillDescriptor(another, "arguments");
+  CheckPillDescriptor(third, "caller");
+  CheckPillDescriptor(third, "arguments");
+})();
+
+
+(function TestStrictFunctionWritablePrototype() {
+  "use strict";
+  function TheClass() {
+  }
+  assertThrows(function() { TheClass.caller; }, TypeError);
+  assertThrows(function() { TheClass.arguments; }, TypeError);
+
+  // Strict functions must have writable prototype.
+  TheClass.prototype = {
+    func: function() { return "func_value"; },
+    get accessor() { return "accessor_value"; },
+    property: "property_value",
+  };
+
+  var o = new TheClass();
+  assertEquals(o.func(), "func_value");
+  assertEquals(o.accessor, "accessor_value");
+  assertEquals(o.property, "property_value");
+})();
+
+
+(function TestStrictArgumentPills() {
+  function strict() {
+    "use strict";
+    return arguments;
+  }
+
+  var args = strict();
+  CheckPillDescriptor(args, "caller");
+  CheckPillDescriptor(args, "callee");
+
+  args = strict(17, "value", strict);
+  assertEquals(17, args[0])
+  assertEquals("value", args[1])
+  assertEquals(strict, args[2]);
+  CheckPillDescriptor(args, "caller");
+  CheckPillDescriptor(args, "callee");
+
+  function outer() {
+    "use strict";
+    function inner() {
+      return arguments;
+    }
+    return inner;
+  }
+
+  var args = outer()();
+  CheckPillDescriptor(args, "caller");
+  CheckPillDescriptor(args, "callee");
+
+  args = outer()(17, "value", strict);
+  assertEquals(17, args[0])
+  assertEquals("value", args[1])
+  assertEquals(strict, args[2]);
+  CheckPillDescriptor(args, "caller");
+  CheckPillDescriptor(args, "callee");
+})();
+
+
+(function TestNonStrictFunctionCallerPillSimple() {
+  function return_my_caller() {
+    return return_my_caller.caller;
+  }
+
+  function strict() {
+    "use strict";
+    return_my_caller();
+  }
+  assertThrows(strict, TypeError);
+
+  function non_strict() {
+    return return_my_caller();
+  }
+  assertSame(non_strict(), non_strict);
+})();
+
+
+(function TestNonStrictFunctionCallerPill() {
+  function strict(n) {
+    "use strict";
+    non_strict(n);
+  }
+
+  function recurse(n, then) {
+    if (n > 0) {
+      recurse(n - 1);
+    } else {
+      return then();
+    }
+  }
+
+  function non_strict(n) {
+    recurse(n, function() { non_strict.caller; });
+  }
+
+  function test(n) {
+    try {
+      recurse(n, function() { strict(n); });
+    } catch(e) {
+      return e instanceof TypeError;
+    }
+    return false;
+  }
+
+  for (var i = 0; i < 10; i ++) {
+    assertEquals(test(i), true);
+  }
+})();
diff --git a/test/mjsunit/testcfg.py b/test/mjsunit/testcfg.py
index 5cb46bc..3dd6581 100644
--- a/test/mjsunit/testcfg.py
+++ b/test/mjsunit/testcfg.py
@@ -38,24 +38,31 @@
 
 class MjsunitTestCase(test.TestCase):
 
-  def __init__(self, path, file, mode, context, config):
+  def __init__(self, path, file, mode, context, config, isolates):
     super(MjsunitTestCase, self).__init__(context, path, mode)
     self.file = file
     self.config = config
     self.self_script = False
+    self.isolates = isolates
 
   def GetLabel(self):
     return "%s %s" % (self.mode, self.GetName())
 
   def GetName(self):
-    return self.path[-1]
+    return self.path[-1] + ["", "-isolates"][self.isolates]
 
-  def GetCommand(self):
+  def TestsIsolates(self):
+    return self.isolates
+
+  def GetVmCommand(self, source):
     result = self.config.context.GetVmCommand(self, self.mode)
-    source = open(self.file).read()
     flags_match = FLAGS_PATTERN.search(source)
     if flags_match:
       result += flags_match.group(1).strip().split()
+    return result
+
+  def GetVmArguments(self, source):
+    result = []
     additional_files = []
     files_match = FILES_PATTERN.search(source);
     # Accept several lines of 'Files:'
@@ -73,6 +80,15 @@
     result += [framework, self.file]
     return result
 
+  def GetCommand(self):
+    source = open(self.file).read()
+    result = self.GetVmCommand(source)
+    result += self.GetVmArguments(source)
+    if self.isolates:
+      result.append("--isolate")
+      result += self.GetVmArguments(source)
+    return result
+
   def GetSource(self):
     return open(self.file).read()
 
@@ -104,7 +120,7 @@
       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):
+  def ListTests(self, current_path, path, mode, variant_flags):
     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'))]
@@ -122,7 +138,8 @@
     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))
+        result.append(MjsunitTestCase(test, file_path, mode, self.context, self, False))
+        result.append(MjsunitTestCase(test, file_path, mode, self.context, self, True))
     return result
 
   def GetBuildRequirements(self):
diff --git a/test/mjsunit/tools/tickprocessor-test-func-info.log b/test/mjsunit/tools/tickprocessor-test-func-info.log
index 755fbb2..e4015d4 100644
--- a/test/mjsunit/tools/tickprocessor-test-func-info.log
+++ b/test/mjsunit/tools/tickprocessor-test-func-info.log
@@ -5,7 +5,7 @@
 code-creation,Stub,0x424260,348,"CompareStub_GE"
 code-creation,LazyCompile,0x2a8100,18535,"DrawQube 3d-cube.js:188",0xf43abcac,
 code-creation,LazyCompile,0x480100,3908,"DrawLine 3d-cube.js:17",0xf43abc50,
-tick,0x424284,0xbfffeea0,0x480600,0,0x2aaaa5
-tick,0x42429f,0xbfffed88,0x480600,0,0x2aacb4
-tick,0x48063d,0xbfffec7c,0x2d0f7c,0,0x2aaec6
+tick,0x424284,0xbfffeea0,0,0x480600,0,0x2aaaa5
+tick,0x42429f,0xbfffed88,0,0x480600,0,0x2aacb4
+tick,0x48063d,0xbfffec7c,0,0x2d0f7c,0,0x2aaec6
 profiler,"end"
diff --git a/test/mjsunit/tools/tickprocessor-test.log b/test/mjsunit/tools/tickprocessor-test.log
index 80e7ec1..db8be79 100644
--- a/test/mjsunit/tools/tickprocessor-test.log
+++ b/test/mjsunit/tools/tickprocessor-test.log
@@ -9,17 +9,17 @@
 function-creation,0xf441d280,0xf541d120
 code-creation,LoadIC,0xf541d280,117,"j"
 code-creation,LoadIC,0xf541d360,63,"i"
-tick,0x80f82d1,0xffdfe880,0,0,0xf541ce5c
-tick,0x80f89a1,0xffdfecf0,0,0,0xf541ce5c
-tick,0x8123b5c,0xffdff1a0,0,0,0xf541d1a1,0xf541ceea
-tick,0x8123b65,0xffdff1a0,0,0,0xf541d1a1,0xf541ceea
-tick,0xf541d2be,0xffdff1e4,0,0
-tick,0xf541d320,0xffdff1dc,0,0
-tick,0xf541d384,0xffdff1d8,0,0
-tick,0xf7db94da,0xffdff0ec,0,0,0xf541d1a1,0xf541ceea
-tick,0xf7db951c,0xffdff0f0,0,0,0xf541d1a1,0xf541ceea
-tick,0xf7dbc508,0xffdff14c,0,0,0xf541d1a1,0xf541ceea
-tick,0xf7dbff21,0xffdff198,0,0,0xf541d1a1,0xf541ceea
-tick,0xf7edec90,0xffdff0ec,0,0,0xf541d1a1,0xf541ceea
-tick,0xffffe402,0xffdff488,0,0
+tick,0x80f82d1,0xffdfe880,0,0,0,0xf541ce5c
+tick,0x80f89a1,0xffdfecf0,0,0,0,0xf541ce5c
+tick,0x8123b5c,0xffdff1a0,0,0,0,0xf541d1a1,0xf541ceea
+tick,0x8123b65,0xffdff1a0,0,0,0,0xf541d1a1,0xf541ceea
+tick,0xf541d2be,0xffdff1e4,0,0,0
+tick,0xf541d320,0xffdff1dc,0,0,0
+tick,0xf541d384,0xffdff1d8,0,0,0
+tick,0xf7db94da,0xffdff0ec,0,0,0,0xf541d1a1,0xf541ceea
+tick,0xf7db951c,0xffdff0f0,0,0,0,0xf541d1a1,0xf541ceea
+tick,0xf7dbc508,0xffdff14c,0,0,0,0xf541d1a1,0xf541ceea
+tick,0xf7dbff21,0xffdff198,0,0,0,0xf541d1a1,0xf541ceea
+tick,0xf7edec90,0xffdff0ec,0,0,0,0xf541d1a1,0xf541ceea
+tick,0xffffe402,0xffdff488,0,0,0
 profiler,"end"
diff --git a/test/mozilla/mozilla.status b/test/mozilla/mozilla.status
index 3b6a524..b9528bd 100644
--- a/test/mozilla/mozilla.status
+++ b/test/mozilla/mozilla.status
@@ -745,8 +745,6 @@
 # error message in debug mode.
 js1_5/extensions/regress-336410-1: FAIL_OK || TIMEOUT if ($mode == debug && $arch == x64)
 
-
-
 ##################### DECOMPILATION TESTS #####################
 
 # We don't really about the outcome of running the
diff --git a/test/mozilla/testcfg.py b/test/mozilla/testcfg.py
index 7a6438f..3728f79 100644
--- a/test/mozilla/testcfg.py
+++ b/test/mozilla/testcfg.py
@@ -92,7 +92,7 @@
   def __init__(self, context, root):
     super(MozillaTestConfiguration, self).__init__(context, root)
 
-  def ListTests(self, current_path, path, mode):
+  def ListTests(self, current_path, path, mode, variant_flags):
     tests = []
     for test_dir in TEST_DIRS:
       current_root = join(self.root, 'data', test_dir)
diff --git a/test/sputnik/testcfg.py b/test/sputnik/testcfg.py
index 31e4b22..c1e3c1b 100644
--- a/test/sputnik/testcfg.py
+++ b/test/sputnik/testcfg.py
@@ -81,7 +81,7 @@
   def __init__(self, context, root):
     super(SputnikTestConfiguration, self).__init__(context, root)
 
-  def ListTests(self, current_path, path, mode):
+  def ListTests(self, current_path, path, mode, variant_flags):
     # Import the sputnik test runner script as a module
     testroot = join(self.root, 'sputniktests')
     modroot = join(testroot, 'tools')
diff --git a/test/test262/README b/test/test262/README
new file mode 100644
index 0000000..6d9e56e
--- /dev/null
+++ b/test/test262/README
@@ -0,0 +1,16 @@
+This directory contains code for binding the test262 test suite
+into the v8 test harness. To use the tests check out the test262
+tests from
+
+  http://hg.ecmascript.org/tests/test262
+
+at revision 62 as 'data' in this directory.  Using later version
+may be possible but the tests are only known to pass (and indeed run)
+with that revision.
+
+hg clone -r 62 http://hg.ecmascript.org/tests/test262 data
+
+If you do update to a newer revision you may have to change the test
+harness adapter code since it uses internal functionality from the
+harness that comes bundled with the tests.  You will most likely also
+have to update the test expectation file.
diff --git a/test/test262/harness-adapt.js b/test/test262/harness-adapt.js
new file mode 100644
index 0000000..b52afdb
--- /dev/null
+++ b/test/test262/harness-adapt.js
@@ -0,0 +1,80 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 fnGlobalObject() { return (function() { return this; })(); }
+
+var ES5Harness = (function() {
+  var currentTest = {};
+  var $this = this;
+
+  function Test262Error(id, path, description, codeString,
+                        preconditionString, result, error) {
+    this.id = id;
+    this.path = path;
+    this.description = description;
+    this.result = result;
+    this.error = error;
+    this.code = codeString;
+    this.pre = preconditionString;
+  }
+
+  Test262Error.prototype.toString = function() {
+    return this.result;
+  }
+
+  function registerTest(test) {
+    if (!(test.precondition && !test.precondition())) {
+      var error;
+      try {
+        var res = test.test.call($this);
+      } catch(e) {
+        print(e);
+        res = 'fail'; error = e;
+      }
+      var retVal = /^s/i.test(test.id)
+          ? (res === true || typeof res == 'undefined' ? 'pass' : 'fail')
+          : (res === true ? 'pass' : 'fail');
+
+      if (retVal != 'pass') {
+         throw new Test262Error(
+            test.id,
+            test.path,
+            test.description,
+            test.test.toString(),
+            (test.precondition !== undefined)
+                ? test.precondition.toString()
+                : '',
+            retVal,
+            error);
+      }
+    }
+  }
+
+  return {
+    registerTest: registerTest
+  }
+})();
diff --git a/test/test262/test262.status b/test/test262/test262.status
new file mode 100644
index 0000000..bdc8b9c
--- /dev/null
+++ b/test/test262/test262.status
@@ -0,0 +1,1506 @@
+# Copyright 2011 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+#       copyright notice, this list of conditions and the following
+#       disclaimer in the documentation and/or other materials provided
+#       with the distribution.
+#     * Neither the name of Google Inc. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#
+# ietestcenter tests.
+#
+
+prefix ietestcenter
+
+# BUG: 7.6 - SyntaxError expected: reserved words used as Identifier
+#      Names in UTF8: class (class)
+7.6-30: FAIL
+# BUG: 7.6 - SyntaxError expected: reserved words used as Identifier
+#      Names in UTF8: extends (extends)
+7.6-31: FAIL
+# BUG: 7.6 - SyntaxError expected: reserved words used as Identifier
+#      Names in UTF8: \u0065\u006e\u0075\u006d (enum)
+7.6-32: FAIL
+# BUG: 7.6 - SyntaxError expected: reserved words used as Identifier
+#      Names in UTF8: \u0073uper (super)
+7.6-33: FAIL
+# BUG: 7.6 - SyntaxError expected: reserved words used as Identifier
+#      Names in UTF8: expor\u0074 (export)
+7.6-35: FAIL
+# BUG: 7.6 - SyntaxError expected: reserved words used as Identifier
+#      Names in UTF8: \u0069\u006d\u0070\u006f\u0072\u0074 (import)
+7.6-36: FAIL
+# Invalid test: https://bugs.ecmascript.org/show_bug.cgi?id=76
+10.4.2-2-c-1: FAIL
+# BUG: 11.8.2 Greater-than Operator - Partial left to right order enforced
+#      when using Greater-than operator: valueOf > valueOf
+11.8.2-1: FAIL
+# BUG: 11.8.2 Greater-than Operator - Partial left to right order enforced
+#      when using Greater-than operator: valueOf > toString
+11.8.2-2: FAIL
+# BUG: 11.8.2 Greater-than Operator - Partial left to right order enforced
+#      when using Greater-than operator: toString > valueOf
+11.8.2-3: FAIL
+# BUG: 11.8.2 Greater-than Operator - Partial left to right order enforced
+#       when using Greater-than operator: toString > toString
+11.8.2-4: FAIL
+# BUG: 11.8.3 Less-than-or-equal Operator - Partial left to right order
+#      enforced when using Less-than-or-equal operator: valueOf <= valueOf
+11.8.3-1: FAIL
+# BUG: 11.8.3 Less-than-or-equal Operator - Partial left to right order
+#      enforced when using Less-than-or-equal operator: valueOf <= toString
+11.8.3-2: FAIL
+# BUG: 11.8.3 Less-than-or-equal Operator - Partial left to right order
+#      enforced when using Less-than-or-equal operator: toString <= valueOf
+11.8.3-3: FAIL
+# BUG: 11.8.3 Less-than-or-equal Operator - Partial left to right order
+#      enforced when using Less-than-or-equal operator: toString <= toString
+11.8.3-4: FAIL
+# BUG: 11.8.3 Less-than-or-equal Operator - Partial left to right order
+#      enforced when using Less-than-or-equal operator: valueOf <= valueOf
+11.8.3-5: FAIL
+# BUG: Global.NaN is a data property with default attribute values
+15.1.1.1-0: FAIL
+# BUG: Global.Infinity is a data property with default attribute values
+15.1.1.2-0: FAIL
+# BUG: Global.undefined is a data property with default attribute values
+15.1.1.3-0: FAIL
+# BUG: Object.getOwnPropertyDescriptor returns data desc (all false)
+#      for properties on built-ins (Global.NaN)
+15.2.3.3-4-178: FAIL
+# BUG: Object.getOwnPropertyDescriptor returns data desc (all false)
+#      for properties on built-ins (Global.Infinity)
+15.2.3.3-4-179: FAIL
+# BUG: Object.getOwnPropertyDescriptor returns data desc (all false)
+#      for properties on built-ins (Global.undefined)
+15.2.3.3-4-180: FAIL
+# BUG: Object.getOwnPropertyDescriptor returns data desc (all false)
+#      for properties on built-ins (RegExp.prototype.source)
+# There is no RegExp.prototype.source
+15.2.3.3-4-212: FAIL
+# BUG: Object.getOwnPropertyDescriptor returns data desc (all false)
+#      for properties on built-ins (RegExp.prototype.global)
+# There is no RegExp.prototype.global
+15.2.3.3-4-213: FAIL
+# BUG: Object.getOwnPropertyDescriptor returns data desc (all false)
+#      for properties on built-ins (RegExp.prototype.ignoreCase)
+# There is no RegExp.prototype.ignoreCase
+15.2.3.3-4-214: FAIL
+# BUG: Object.getOwnPropertyDescriptor returns data desc (all false)
+#      for properties on built-ins (RegExp.prototype.multiline)
+15.2.3.3-4-215: FAIL
+# Bug? Object.create - 'set' property of one property in 'Properties'
+#      is not present (8.10.5 step 8)
+# V8 throws.
+15.2.3.5-4-267: FAIL
+# Bug? Object.create - 'set' property of one property in 'Properties'
+#      is undefined (8.10.5 step 8.b)
+# V8 throws.
+15.2.3.5-4-292: FAIL
+# Bug? Object.defineProperty - 'set' property in 'Attributes' is not
+#      present (8.10.5 step 8)
+# V8 throws.
+15.2.3.6-3-236: FAIL
+# Bug? Object.defineProperty - 'set' property in 'Attributes' is own
+#      accessor property without a get function (8.10.5 step 8.a)
+# V8 throws.
+15.2.3.6-3-245: FAIL
+# Bug? Object.defineProperty - 'set' property in 'Attributes' is own
+#      accessor property(without a get function) that overrides an inherited
+#      accessor property (8.10.5 step 8.a)
+# V8 throws.
+15.2.3.6-3-246: FAIL
+# Bug? Object.defineProperty - 'set' property in 'Attributes' is an
+#      inherited accessor property without a get function (8.10.5 step 8.a)
+# V8 throws.
+15.2.3.6-3-247: FAIL
+# Bug? Object.defineProperty - value of 'set' property in 'Attributes'
+#      is undefined (8.10.5 step 8.b)
+# V8 throws.
+15.2.3.6-3-261: FAIL
+# Bug? Object.defineProperty - Update [[Enumerable]] attribute of 'name'
+#      property to true successfully when [[Enumerable]] attribute of 'name'
+#      is false and [[Configurable]] attribute of 'name' is true,  the 'desc'
+#      is a generic descriptor which only contains [[Enumerable]] attribute
+#      as true, 'name' property is an index data property (8.12.9 step 8)
+15.2.3.6-4-82-18: FAIL
+# Bug? Object.defineProperty - Update [[Enumerable]] attribute of 'name'
+#      property to false successfully when [[Enumerable]] and [[Configurable]]
+#      attributes of 'name' property are true,  the 'desc' is a generic
+#      descriptor which only contains [Enumerable]] attribute as false and
+#      'name' property is an index accessor property (8.12.9 step 8)
+15.2.3.6-4-82-19: FAIL
+# Bug? Object.defineProperty - Update [[Enumerable]] attribute of 'name'
+#      property to false successfully when [[Enumerable]] and [[Configurable]]
+#      attributes of 'name' property are true,  the 'desc' is a generic
+#      descriptor which contains [Enumerable]] attribute as false and
+#      [[Configurable]] property is true, 'name' property is an index accessor
+#      property (8.12.9 step 8)
+15.2.3.6-4-82-20: FAIL
+# Bug? Object.defineProperty - Update [[Configurable]] attribute of 'name'
+#      property to false successfully when [[Enumerable]] and [[Configurable]]
+#      attributes of 'name' property are true, the 'desc' is a generic
+#      descriptor which only contains [[Configurable]] attribute as false,
+#      'name' property is an index accessor property (8.12.9 step 8)
+15.2.3.6-4-82-21: FAIL
+# Bug? Object.defineProperty - Update [[Configurable]] attribute of 'name'
+#      property to false successfully when [[Enumerable]] and [[Configurable]]
+#      attributes of 'name' property are true, the 'desc' is a generic
+#      descriptor which contains [[Enumerable]] attribute as true and
+#      [[Configurable]] attribute is false, 'name' property is an index accessor
+#      property (8.12.9 step 8)
+15.2.3.6-4-82-22: FAIL
+# Bug? Object.defineProperty - Update [[Enumerable]] and [[Configurable]]
+#      attributes of 'name' property to false successfully when [[Enumerable]]
+#      and [[Configurable]] attributes of 'name' property are true, the 'desc'
+#      is a generic descriptor which contains [[Enumerable]] and
+#      [[Configurable]] attributes as false, 'name' property is an index
+#      accessor property (8.12.9 step 8)
+15.2.3.6-4-82-23: FAIL
+# Bug? Object.defineProperty - Update [[Enumerable]] attributes of 'name'
+#      property to true successfully when [[Enumerable]] attribute of 'name' is
+#      false and [[Configurable]] attribute of 'name' is true, the 'desc' is a
+#      generic descriptor which only contains [[Enumerable]] attribute as true,
+#      'name' property is an index accessor property (8.12.9 step 8)
+15.2.3.6-4-82-24: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, test the length property of 'O'
+#      is own data property (15.4.5.1 step 1)
+15.2.3.6-4-116: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, test the length property of 'O'
+#      is own data property that overrides an inherited data property (15.4.5.1
+#      step 1)
+15.2.3.6-4-117: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test that RangeError exception is thrown when [[Value]] field of
+#      'desc' is undefined (15.4.5.1 step 3.c)
+15.2.3.6-4-125: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test the [[Value]] field of 'desc' is null (15.4.5.1 step 3.c)
+15.2.3.6-4-126: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test the [[Value]] field of 'desc' is a boolean with value false
+#      (15.4.5.1 step 3.c)
+15.2.3.6-4-127: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test the [[Value]] field of 'desc' is a boolean with value true
+#      (15.4.5.1 step 3.c)
+15.2.3.6-4-128: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError exception is not thrown when the [[Value]] field of
+#      'desc' is 0 (15.4.5.1 step 3.c)
+15.2.3.6-4-129: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError exception is not thrown when the [[Value]] field of
+#      'desc' is +0 (15.4.5.1 step 3.c)
+15.2.3.6-4-130: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError exception is not thrown when the [[Value]] field of
+#      'desc' is -0 (15.4.5.1 step 3.c)
+15.2.3.6-4-131: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError exception is not thrown when the [[Value]] field of
+#      'desc' is a positive number (15.4.5.1 step 3.c)
+15.2.3.6-4-132: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError exception is thrown when the [[Value]] field of
+#      'desc' is a negative number (15.4.5.1 step 3.c)
+15.2.3.6-4-133: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError exception is thrown when the [[Value]] field of
+#      'desc' is +Infinity (15.4.5.1 step 3.c)
+15.2.3.6-4-134: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError exception is thrown when the [[Value]] field of
+#      'desc' is -Infinity (15.4.5.1 step 3.c)
+15.2.3.6-4-135: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError exception is thrown when the [[Value]] field of
+#      'desc' is NaN (15.4.5.1 step 3.c)
+15.2.3.6-4-136: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError exception is not thrown when the [[Value]] field of
+#      'desc' is a string containing a positive number (15.4.5.1 step 3.c)
+15.2.3.6-4-137: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError exception is thrown when the [[Value]] field of
+#      'desc' is a string containing a negative number (15.4.5.1 step 3.c)
+15.2.3.6-4-138: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError exception is thrown when the [[Value]] field of
+#      'desc' is a string containing a decimal number (15.4.5.1 step 3.c)
+15.2.3.6-4-139: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError exception is thrown when the [[Value]] field of
+#      'desc' is a string containing +Infinity (15.4.5.1 step 3.c)
+15.2.3.6-4-140: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError exception is thrown when the [[Value]] field of
+#      'desc' is a string containing -Infinity (15.4.5.1 step 3.c)
+15.2.3.6-4-141: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test the [[Value]] field of 'desc' is a string containing an
+#      exponential number (15.4.5.1 step 3.c)
+15.2.3.6-4-142: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test the [[Value]] field of 'desc' is a string containing a hex
+#      number (15.4.5.1 step 3.c)
+15.2.3.6-4-143: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test the [[Value]] field of 'desc' is a string containing a number
+#      with leading zeros (15.4.5.1 step 3.c)
+15.2.3.6-4-144: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError exception is thrown when the [[Value]] field of
+#      'desc' is a string which doesn't convert to a number (15.4.5.1 step 3.c)
+15.2.3.6-4-145: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test the [[Value]] field of 'desc' is an object which has an own
+#      toString method (15.4.5.1 step 3.c)
+15.2.3.6-4-146: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test the [[Value]] field of 'desc' is an Object which has an own
+#      valueOf method (15.4.5.1 step 3.c)
+15.2.3.6-4-147: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test the [[Value]] field of 'desc' is an Object which has an own
+#      valueOf method that returns an object and toString method that returns a
+#      string (15.4.5.1 step 3.c)
+15.2.3.6-4-148: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test the [[Value]] field of 'desc' is an Object which has an own
+#      toString and valueOf method (15.4.5.1 step 3.c)
+15.2.3.6-4-149: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test TypeError is thrown when the [[Value]] field of 'desc' is an
+#      Object that both toString and valueOf wouldn't return primitive value
+#      (15.4.5.1 step 3.c)
+15.2.3.6-4-150: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', and the [[Value]] field of 'desc' is an Object with an own toString
+#      method and an inherited valueOf method (15.4.5.1 step 3.c), test that the
+#      inherited valueOf method is used
+15.2.3.6-4-151: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError is thrown when the [[Value]] field of 'desc' is a
+#      positive non-integer values (15.4.5.1 step 3.c)
+15.2.3.6-4-152: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length prosperty
+#      of 'O', test RangeError is thrown when the [[Value]] field of 'desc' is a
+#      negative non-integer values (15.4.5.1 step 3.c)
+15.2.3.6-4-153: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test the [[Value]] field of 'desc' is boundary value 2^32 - 2
+#      (15.4.5.1 step 3.c)
+15.2.3.6-4-154: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test the [[Value]] field of 'desc' is boundary value 2^32 - 1
+#      (15.4.5.1 step 3.c)
+15.2.3.6-4-155: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError is thrown when the [[Value]] field of 'desc' is
+#      boundary value 2^32 (15.4.5.1 step 3.c)
+15.2.3.6-4-156: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', test RangeError is thrown when the [[Value]] field of 'desc' is
+#      boundary value 2^32 + 1 (15.4.5.1 step 3.c)
+15.2.3.6-4-157: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', set the [[Value]] field of 'desc' to a value greater than the
+#      existing value of length (15.4.5.1 step 3.f)
+15.2.3.6-4-159: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', set the [[Value]] field of 'desc' to a value lesser than the
+#      existing value of length and test that indexes beyond the new length are
+#      deleted(15.4.5.1 step 3.f)
+15.2.3.6-4-161: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Writable]] attribute of the length property is set
+#      to true after deleting properties with large index named if the
+#      [[Writable]] field of 'desc' is absent (15.4.5.1 step 3.h)
+15.2.3.6-4-165: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Writable]] attribute of the length property is set
+#      to true after deleting properties with large index named if the
+#      [[Writable]] field of 'desc' is true (15.4.5.1 step 3.h)
+15.2.3.6-4-166: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Writable]] attribute of the length property is set
+#      to false after deleting properties with large index named if the
+#      [[Writable]] field of 'desc' is false (15.4.5.1 step 3.i.ii)
+15.2.3.6-4-167: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', whose writable attribute is being changed to false and the [[Value]]
+#      field of 'desc' is less than value of the length property and also lesser
+#      than an index of the array which is set to configurable:false, test that
+#      new length is set to a value greater than the non-deletable index by 1,
+#      writable attribute of length is set to false and TypeError exception is
+#      thrown (15.4.5.1 step 3.i.iii)
+15.2.3.6-4-168: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property and also lesser than an index of the array which is set to
+#      configurable: false, test that new length is set to a value greater than
+#      the non-deletable index by 1, and TypeError is thrown (15.4.5.1 step
+#      3.l.i)
+15.2.3.6-4-169: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property and also lesser than an index of the array which is set to
+#      configurable: false, test that new length is set to a value greater than
+#      the non-deletable index by 1, writable attribute of length is set to
+#      false and TypeError exception is thrown (15.4.5.1 step 3.l.ii)
+15.2.3.6-4-170: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Configurable]] attribute of an inherited data
+#      property with large index named in 'O' can't stop deleting index named
+#      properties (15.4.5.1 step 3.l.ii)
+15.2.3.6-4-171: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Configurable]] attribute of own data property with
+#      large index named in 'O' that overrides an inherited data property can
+#      stop deleting index named properties (15.4.5.1 step 3.l.ii)
+15.2.3.6-4-172: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Configurable]] attribute of own data property with
+#      large index named in 'O' that overrides an inherited accessor property
+#      can stop deleting index named properties (15.4.5.1 step 3.l.ii)
+15.2.3.6-4-173: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Configurable]] attribute of own accessor property
+#      with large index named in 'O' can stop deleting index named properties
+#      (15.4.5.1 step 3.l.ii)
+15.2.3.6-4-174: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Configurable]] attribute of an inherited accessor
+#      property with large index named in 'O' can't stop deleting index named
+#      properties (15.4.5.1 step 3.l.ii)
+15.2.3.6-4-175: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Configurable]] attribute of own accessor property
+#      with large index named in 'O' that overrides an inherited data property
+#      can stop deleting index named properties (15.4.5.1 step 3.l.ii)
+15.2.3.6-4-176: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Configurable]] attribute of own accessor property
+#      with large index named in 'O' that overrides an inherited accessor
+#      property can stop deleting index named properties (15.4.5.1 step 3.l.ii)
+15.2.3.6-4-177: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the configurable large index named property of 'O' is
+#      deleted (15.4.5.1 step 3.l.ii)
+15.2.3.6-4-178: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', the [[Value]] field of 'desc' is greater than value of the length
+#      property, test value of the length property is same as [[Value]]
+#      (15.4.5.1 step 3.l.iii.1)
+15.2.3.6-4-179-1: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Writable]] attribute of the length property is set
+#      to false at last when the [[Writable]] field of 'desc' is false and 'O'
+#      doesn't contain non-configurable large index named property (15.4.5.1
+#      step 3.m)
+15.2.3.6-4-181: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named
+#      property, 'name' is boundary value 2^32 - 2 (15.4.5.1 step 4.a)
+15.2.3.6-4-183: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named
+#      property, test TypeError is thrown if the [[Writable]] attribute of the
+#      length property in 'O' is false and value of 'name' equals to value of
+#      the length property (15.4.5.1 step 4.b)
+15.2.3.6-4-188: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named
+#      property, test TypeError is thrown if the [[Writable]] attribute of the
+#      length property in 'O' is false and value of 'name' is greater than value
+#      of the length property (15.4.5.1 step 4.b)
+15.2.3.6-4-189: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named
+#      property, 'desc' is accessor descriptor, test updating all attribute
+#      values of 'name' (15.4.5.1 step 4.c)
+15.2.3.6-4-209: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named
+#      property, 'name' is accessor property and assignment to the accessor
+#      property, fails to convert accessor property from accessor property to
+#      data property (15.4.5.1 step 4.c)
+15.2.3.6-4-243-1: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named
+#      property, name is accessor property and 'desc' is accessor descriptor,
+#      test updating the [[Enumerable]] attribute value of 'name' (15.4.5.1 step
+#      4.c)
+15.2.3.6-4-271: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named
+#      property, name is accessor property and 'desc' is accessor descriptor,
+#      test updating the [[Configurable]] attribute value of 'name' (15.4.5.1
+#      step 4.c)
+15.2.3.6-4-272: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named
+#      property, name is accessor property and 'desc' is accessor descriptor,
+#      test updating multiple attribute values of 'name' (15.4.5.1 step 4.c)
+15.2.3.6-4-273: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named
+#      property, test the length property of 'O' is set as ToUint32('name') + 1
+#      if ToUint32('name') equals to value of the length property in 'O'
+#      (15.4.5.1 step 4.e.ii)
+15.2.3.6-4-275: FAIL
+# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named
+#      property, test the length property of 'O' is set as ToUint32('name') + 1
+#      if ToUint32('name') is greater than value of the length property in 'O'
+#      (15.4.5.1 step 4.e.ii)
+15.2.3.6-4-276: FAIL
+# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has
+#      formal parameters, 'name' is own property which is defined in both
+#      [[ParameterMap]] of 'O' and 'O', and is deleted afterwards, and 'desc' is
+#      data descriptor, test 'name' is redefined in 'O' with all correct
+#      attribute values (10.6 [[DefineOwnProperty]] step 3)
+15.2.3.6-4-289-1: FAIL
+# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has
+#      formal parameters, 'name' is own property which is defined in both
+#      [[ParameterMap]] of 'O' and 'O', is deleted afterwards, and 'desc' is
+#      accessor descriptor, test 'name' is redefined in 'O' with all correct
+#      attribute values (10.6 [[DefineOwnProperty]] step 3)
+15.2.3.6-4-290-1: FAIL
+# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has
+#      formal parameters, 'name' is own accessor property of 'O' which is also
+#      defined in [[ParameterMap]] of 'O', and 'desc' is accessor descriptor,
+#      test updating multiple attribute values of 'name' (10.6
+#      [[DefineOwnProperty]] step 3 and 5.a.i)
+15.2.3.6-4-291-1: FAIL
+# Bug? Object.defineProperty - 'O' is an Arguments object, 'name' is own
+#      accessor property of 'O', and 'desc' is accessor descriptor, test
+#      updating multiple attribute values of 'name' (10.6 [[DefineOwnProperty]]
+#      step 3)
+15.2.3.6-4-291: FAIL
+# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has
+#      formal parameters, 'name' is own data property of 'O' which is also
+#      defined in [[ParameterMap]] of 'O', test TypeError is not thrown when
+#      updating the [[Value]] attribute value of 'name' which is defined as
+#      non-writable and configurable (10.6 [[DefineOwnProperty]] step 3 and step
+#      5.b)
+15.2.3.6-4-293-3: FAIL
+# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has
+#      formal parameters, 'name' is own accessor property of 'O' which is also
+#      defined in [[ParameterMap]] of 'O', test TypeError is thrown when
+#      updating the [[Get]] attribute value of 'name' which is defined as
+#      non-configurable (10.6 [[DefineOwnProperty]] step 4 and step 5a)
+15.2.3.6-4-297-1: FAIL
+# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has
+#      formal parameters, 'name' is own accessor property of 'O' which is also
+#      defined in [[ParameterMap]] of 'O', test TypeError is thrown when
+#      updating the [[Set]] attribute value of 'name' which is defined as
+#      non-configurable (10.6 [[DefineOwnProperty]] steps 4 and 5a)
+15.2.3.6-4-298-1: FAIL
+# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has
+#      formal parameters, 'name' is own accessor property of 'O' which is also
+#      defined in [[ParameterMap]] of 'O', test TypeError is thrown when
+#      updating the [[Enumerable]] attribute value of 'name' which is defined as
+#      non-configurable (10.6 [[DefineOwnProperty]] steps 4 and 5a)
+15.2.3.6-4-299-1: FAIL
+# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has
+#      formal parameters, 'name' is an index named property of 'O', and 'desc'
+#      is data descriptor, test 'name' is defined in 'O' with all correct
+#      attribute values (10.6 [[DefineOwnProperty]] step 3)
+15.2.3.6-4-301-1: FAIL
+# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has
+#      formal parameters, 'name' is an index named property of 'O' but not
+#      defined in [[ParameterMap]] of 'O', and 'desc' is accessor descriptor,
+#      test 'name' is defined in 'O' with all correct attribute values (10.6
+#      [[DefineOwnProperty]] step 3 and step 5a)
+15.2.3.6-4-302-1: FAIL
+# Bug? Object.defineProperty - 'O' is an Arguments object, 'name' is an index
+#      named accessor property of 'O' but not defined in [[ParameterMap]] of
+#      'O', and 'desc' is accessor descriptor, test updating multiple attribute
+#      values of 'name' (10.6 [[DefineOwnProperty]] step 3)
+15.2.3.6-4-303: FAIL
+# Bug? ES5 Attributes - [[Value]] attribute of data property is the activex host
+#      object
+15.2.3.6-4-401: FAIL
+# Bug? ES5 Attributes - Failed to add a property to an object when the object's
+#      object has a property with same name and [[Writable]] attribute is set to
+#      false (Number instance)
+15.2.3.6-4-405: FAIL
+# Bug? ES5 Attributes - Failed to add a property to an object when the object's
+#      prototype has a property with the same name and [[Writable]] set to false
+#      (JSON)
+15.2.3.6-4-410: FAIL
+# Bug? ES5 Attributes - Failed to add properties to an object when the object's
+#      prototype has properties with the same name and [[Writable]] set to false
+#      (Object.create)
+15.2.3.6-4-415: FAIL
+# Bug? ES5 Attributes - Failed to add a property to an object when the object's
+#      prototype has a property with the same name and [[Writable]] set to
+#      false(Function.prototype.bind)
+15.2.3.6-4-420: FAIL
+# Bug? ES5 Attributes - Fail to add property into object (Number instance)
+15.2.3.6-4-581: FAIL
+# Bug? ES5 Attributes - Fail to update value of property into of [[Proptotype]]
+#      internal property (JSON)
+15.2.3.6-4-586: FAIL
+# Bug? ES5 Attributes - Fail to update value of property of [[Proptotype]]
+#      internal property (Object.create)
+15.2.3.6-4-591: FAIL
+# Bug? ES5 Attributes - Fail to update value of property into of [[Proptotype]]
+#      internal property (Function.prototype.bind)
+15.2.3.6-4-596: FAIL
+# Bug? ES5 Attributes - all attributes in Array.prototype.indexOf are correct
+15.2.3.6-4-612: FAIL
+# Bug? ES5 Attributes - all attributes in Object.lastIndexOf are correct
+15.2.3.6-4-613: FAIL
+# Bug? ES5 Attributes - all attributes in Array.prototype.every are correct
+15.2.3.6-4-614: FAIL
+# Bug? ES5 Attributes - all attributes in Array.prototype.some are correct
+15.2.3.6-4-615: FAIL
+# Bug? ES5 Attributes - all attributes in Array.prototype.forEach are correct
+15.2.3.6-4-616: FAIL
+# Bug? ES5 Attributes - all attributes in Array.prototype.map are correct
+15.2.3.6-4-617: FAIL
+# Bug? ES5 Attributes - all attributes in Array.prototype.filter are correct
+15.2.3.6-4-618: FAIL
+# Bug? ES5 Attributes - all attributes in Array.prototype.reduce are correct
+15.2.3.6-4-619: FAIL
+# Bug? ES5 Attributes - all attributes in Array.prototype.reduceRight are
+#      correct
+15.2.3.6-4-620: FAIL
+# Bug? ES5 Attributes - all attributes in String.prototype.trim are correct
+15.2.3.6-4-621: FAIL
+# Bug? ES5 Attributes - all attributes in Date.prototype.toISOString are correct
+15.2.3.6-4-623: FAIL
+# Bug? ES5 Attributes - all attributes in Date.prototype.toJSON are correct
+15.2.3.6-4-624: FAIL
+# Bug? Object.defineProperties - argument 'Properties' is an Error object
+#      props.description = obj1;
+15.2.3.7-2-15: FAIL
+# Bug? Object.defineProperties - 'Properties' is an Error object which
+#      implements its own [[Get]] method to get enumerable own property
+#      props.description = obj1;
+15.2.3.7-5-a-16: FAIL
+# Bug? Object.defineProperties - 'set' property of 'descObj' is not present
+#      (8.10.5 step 8)
+15.2.3.7-5-b-227: FAIL
+# Bug? Object.defineProperties - 'descObj' is an Error object which implements
+#      its own [[Get]] method to get 'set' property (8.10.5 step 8.a)
+#      descObj.description = { value: 11 };
+15.2.3.7-5-b-248: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, test the length property of
+#      'O' is own data property (15.4.5.1 step 1)
+15.2.3.7-6-a-112: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, test the length property of
+#      'O' is own data property that overrides an inherited data property
+#      (15.4.5.1 step 1)
+15.2.3.7-6-a-113: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', test RangeError is thrown when setting the [[Value]] field of 'desc'
+#      to undefined (15.4.5.1 step 3.c)
+15.2.3.7-6-a-121: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', test setting the [[Value]] field of 'desc' to null actuall is set to
+#      0 (15.4.5.1 step 3.c)
+15.2.3.7-6-a-122: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is a boolean with value false
+#      (15.4.5.1 step 3.c)
+15.2.3.7-6-a-123: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is a boolean with value true
+#      (15.4.5.1 step 3.c)
+15.2.3.7-6-a-124: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is 0 (15.4.5.1 step 3.c)
+15.2.3.7-6-a-125: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is +0 (15.4.5.1 step 3.c)
+15.2.3.7-6-a-126: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is -0 (15.4.5.1 step 3.c)
+15.2.3.7-6-a-127: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is positive number (15.4.5.1
+#      step 3.c)
+15.2.3.7-6-a-128: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is negative number (15.4.5.1
+#      step 3.c)
+15.2.3.7-6-a-129: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is +Infinity (15.4.5.1 step
+#      3.c)
+15.2.3.7-6-a-130: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is -Infinity (15.4.5.1 step
+#      3.c)
+15.2.3.7-6-a-131: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is NaN (15.4.5.1 step 3.c)
+15.2.3.7-6-a-132: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is a string containing a
+#      positive number (15.4.5.1 step 3.c)
+15.2.3.7-6-a-133: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is a string containing a
+#      negative number (15.4.5.1 step 3.c)
+15.2.3.7-6-a-134: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is a string containing a
+#      decimal number (15.4.5.1 step 3.c)
+15.2.3.7-6-a-135: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is a string containing
+#      +Infinity (15.4.5.1 step 3.c)
+15.2.3.7-6-a-136: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is a string containing
+#      -Infinity (15.4.5.1 step 3.c)
+15.2.3.7-6-a-137: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is a string containing an
+#      exponential number (15.4.5.1 step 3.c)
+15.2.3.7-6-a-138: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is a string containing an hex
+#      number (15.4.5.1 step 3.c)
+15.2.3.7-6-a-139: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is a string containing an
+#      leading zero number (15.4.5.1 step 3.c)
+15.2.3.7-6-a-140: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', test the [[Value]] field of 'desc' is a string which doesn't convert
+#      to a number (15.4.5.1 step 3.c)
+15.2.3.7-6-a-141: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', test the [[Value]] field of 'desc' is an Object which has an own
+#      toString method (15.4.5.1 step 3.c)
+15.2.3.7-6-a-142: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is an Object which has an own
+#      valueOf method (15.4.5.1 step 3.c)
+15.2.3.7-6-a-143: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is an Object which has an own
+#      valueOf method that returns an object and toString method that returns a
+#      string (15.4.5.1 step 3.c)
+15.2.3.7-6-a-144: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is an Object which has an own
+#      toString and valueOf method (15.4.5.1 step 3.c)
+15.2.3.7-6-a-145: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test TypeError is thrown when the [[Value]] field of 'desc' is an
+#      Object that both toString and valueOf wouldn't return primitive value
+#      (15.4.5.1 step 3.c)
+15.2.3.7-6-a-146: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test using inherited valueOf method when the [[Value]] field of
+#      'desc' is an Objec with an own toString and inherited valueOf methods
+#      (15.4.5.1 step 3.c)
+15.2.3.7-6-a-147: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test RangeError is thrown when the [[Value]] field of 'desc' is
+#      positive non-integer values (15.4.5.1 step 3.c)
+15.2.3.7-6-a-148: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test RangeError is thrown when the [[Value]] field of 'desc' is
+#      negative non-integer values (15.4.5.1 step 3.c)
+15.2.3.7-6-a-149: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is boundary value 2^32 - 2
+#      (15.4.5.1 step 3.c)
+15.2.3.7-6-a-150: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test the [[Value]] field of 'desc' is boundary value 2^32 - 1
+#      (15.4.5.1 step 3.c)
+15.2.3.7-6-a-151: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test RangeError is thrown when the [[Value]] field of 'desc' is
+#      boundary value 2^32 (15.4.5.1 step 3.c)
+15.2.3.7-6-a-152: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property
+#      of 'O', test RangeError is thrown when the [[Value]] field of 'desc' is
+#      boundary value 2^32 + 1 (15.4.5.1 step 3.c)
+15.2.3.7-6-a-153: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', test the [[Value]] field of 'desc' which is greater than value of
+#      the length property is defined into 'O' without deleting any property
+#      with large index named (15.4.5.1 step 3.f)
+15.2.3.7-6-a-155: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', test the [[Value]] field of 'desc' which is less than value of the
+#      length property is defined into 'O' with deleting properties with large
+#      index named (15.4.5.1 step 3.f)
+15.2.3.7-6-a-157: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Writable]] attribute of the length property is set
+#      to true at last after deleting properties with large index named if the
+#      [[Writable]] field of 'desc' is absent (15.4.5.1 step 3.h)
+15.2.3.7-6-a-161: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Writable]] attribute of the length property is set
+#      to true at last after deleting properties with large index named if the
+#      [[Writable]] field of 'desc' is true (15.4.5.1 step 3.h)
+15.2.3.7-6-a-162: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Writable]] attribute of the length property is set
+#      to false at last after deleting properties with large index named if the
+#      [[Writable]] field of 'desc' is false (15.4.5.1 step 3.i.ii)
+15.2.3.7-6-a-163: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Writable]] attribute of the length property in 'O'
+#      is set as true before deleting properties with large index named
+#      (15.4.5.1 step 3.i.iii)
+15.2.3.7-6-a-164: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the length property is decreased by 1 (15.4.5.1 step
+#      3.l.i)
+15.2.3.7-6-a-165: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Configurable]] attribute of own data property with
+#      large index named in 'O' can stop deleting index named properties
+#      (15.4.5.1 step 3.l.ii)
+15.2.3.7-6-a-166: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Configurable]] attribute of inherited data property
+#      with large index named in 'O' can't stop deleting index named properties
+#      (15.4.5.1 step 3.l.ii)
+15.2.3.7-6-a-167: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Configurable]] attribute of own data property with
+#      large index named in 'O' that overrides inherited data property can stop
+#      deleting index named properties (15.4.5.1 step 3.l.ii)
+15.2.3.7-6-a-168: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Configurable]] attribute of own data property with
+#      large index named in 'O' that overrides inherited accessor property can
+#      stop deleting index named properties (15.4.5.1 step 3.l.ii)
+15.2.3.7-6-a-169: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Configurable]] attribute of own accessor property
+#      with large index named in 'O' can stop deleting index named properties
+#      (15.4.5.1 step 3.l.ii)
+15.2.3.7-6-a-170: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Configurable]] attribute of inherited accessor
+#      property with large index named in 'O' can't stop deleting index named
+#      properties (15.4.5.1 step 3.l.ii)
+15.2.3.7-6-a-171: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Configurable]] attribute of own accessor property
+#      with large index named in 'O' that overrides inherited data property can
+#      stop deleting index named properties (15.4.5.1 step 3.l.ii)
+15.2.3.7-6-a-172: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Configurable]] attribute of own accessor property
+#      with large index named in 'O' that overrides inherited accessor property
+#      can stop deleting index named properties (15.4.5.1 step 3.l.ii)
+15.2.3.7-6-a-173: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the configurable large index named property of 'O' can be
+#      deleted (15.4.5.1 step 3.l.ii)
+15.2.3.7-6-a-174: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test value of the length property is set to the last
+#      non-configurable index named property of 'O' plus 1 (15.4.5.1 step
+#      3.l.iii.1)
+15.2.3.7-6-a-175: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Writable]] attribute of the length property is set
+#      to false at last when the [[Writable]] field of 'desc' is false and 'O'
+#      contains non-configurable large index named property (15.4.5.1 step
+#      3.l.iii.2)
+15.2.3.7-6-a-176: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of
+#      'O', the [[Value]] field of 'desc' is less than value of the length
+#      property, test the [[Writable]] attribute of the length property is set
+#      to false at last when the [[Writable]] field of 'desc' is false and 'O'
+#      doesn't contain non-configurable large index named property (15.4.5.1
+#      step 3.m)
+15.2.3.7-6-a-177: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named
+#      property, 'P' is boundary value 2^32 - 2 (15.4.5.1 step 4.a)
+15.2.3.7-6-a-179: FAIL
+# Bug? Object.defineProperties - TypeError is thrown if 'O' is an Array, 'P' is
+#      an array index named property,[[Writable]] attribute of the length
+#      property in 'O' is false, value of 'P' is equal to value of the length
+#      property in 'O' (15.4.5.1 step 4.b)
+15.2.3.7-6-a-184: FAIL
+# Bug? Object.defineProperties - TypeError is thrown if 'O' is an Array, 'P' is
+#      an array index named property,[[Writable]] attribute of the length
+#      property in 'O' is false, value of 'P' is bigger than value of the length
+#      property in 'O' (15.4.5.1 step 4.b)
+15.2.3.7-6-a-185: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named
+#      property, 'desc' is accessor descriptor, test updating all attribute
+#      values of 'P' (15.4.5.1 step 4.c)
+15.2.3.7-6-a-205: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named
+#      property that already exists on 'O' is accessor property and 'desc' is
+#      accessor descriptor, test updating the [[Enumerable]] attribute value of
+#      'P' (15.4.5.1 step 4.c)
+15.2.3.7-6-a-260: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named
+#      property that already exists on 'O' is accessor property and 'desc' is
+#      accessor descriptor, test updating the [[Configurable]] attribute value
+#      of 'P' (15.4.5.1 step 4.c)
+15.2.3.7-6-a-261: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named
+#      property that already exists on 'O' is accessor property and 'desc' is
+#      accessor descriptor, test updating multiple attribute values of 'P'
+#      (15.4.5.1 step 4.c)
+15.2.3.7-6-a-262: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named
+#      property, test the length property of 'O' is set as ToUint32('P') + 1 if
+#      ToUint32('P') equals to value of the length property in 'O' (15.4.5.1
+#      step 4.e.ii)
+15.2.3.7-6-a-264: FAIL
+# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named
+#      property, test the length property of 'O' is set as ToUint32('P') + 1 if
+#      ToUint32('P') is greater than value of the length property in 'O'
+#      (15.4.5.1 step 4.e.ii)
+15.2.3.7-6-a-265: FAIL
+# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is own accessor
+#      property of 'O' which is also defined in [[ParameterMap]] of 'O', and
+#      'desc' is accessor descriptor, test updating multiple attribute values of
+#      'P' (10.6 [[DefineOwnProperty]] step 3)
+15.2.3.7-6-a-280: FAIL
+# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is an array
+#      index named accessor property of 'O' but not defined in [[ParameterMap]]
+#      of 'O', and 'desc' is accessor descriptor, test updating multiple
+#      attribute values of 'P' (10.6 [[DefineOwnProperty]] step 3)
+15.2.3.7-6-a-292: FAIL
+# Bug? Object.preventExtensions - indexed properties cannot be added into the
+#      returned object
+15.2.3.10-3-2: FAIL
+# Bug? Object.preventExtensions - indexed properties cannot be added into a
+#      Function object
+15.2.3.10-3-3: FAIL
+# Bug? Object.preventExtensions - indexed properties cannot be added into an
+#      Array object
+15.2.3.10-3-4: FAIL
+# Bug? Object.preventExtensions - indexed properties cannot be added into a
+#      String object
+15.2.3.10-3-5-1: FAIL
+# Bug? Object.preventExtensions - indexed properties cannot be added into a
+#      Boolean object
+15.2.3.10-3-6: FAIL
+# Bug? Object.preventExtensions - indexed properties cannot be added into a
+#      Number object
+15.2.3.10-3-7: FAIL
+# Bug? Object.preventExtensions - indexed properties cannot be added into a Date
+#      object
+15.2.3.10-3-8: FAIL
+# Bug? Object.preventExtensions - indexed properties cannot be added into a
+#      RegExp object
+15.2.3.10-3-9: FAIL
+# Bug? Object.preventExtensions - indexed properties cannot be added into an
+#      Error object
+15.2.3.10-3-10: FAIL
+# Bug? Object.preventExtensions - indexed properties cannot be added into an
+#      Arguments object
+15.2.3.10-3-11: FAIL
+# Bug? Object.preventExtensions - named properties cannot be added into the
+#      returned object
+15.2.3.10-3-12: FAIL
+# Bug? Object.preventExtensions - named properties cannot be added into a
+#      Function object
+15.2.3.10-3-13: FAIL
+# Bug? Object.preventExtensions - named properties cannot be added into an Array
+#      object
+15.2.3.10-3-14: FAIL
+# Bug? Object.preventExtensions - named properties cannot be added into a String
+#      object
+15.2.3.10-3-15: FAIL
+# Bug? Object.preventExtensions - named properties cannot be added into a
+#      Boolean object
+15.2.3.10-3-16: FAIL
+# Bug? Object.preventExtensions - named properties cannot be added into a Number
+#      object
+15.2.3.10-3-17: FAIL
+# Bug? Object.preventExtensions - named properties cannot be added into a Date
+#      object
+15.2.3.10-3-18: FAIL
+# Bug? Object.preventExtensions - named properties cannot be added into a RegExp
+#      object
+15.2.3.10-3-19: FAIL
+# Bug? Object.preventExtensions - named properties cannot be added into an Error
+#      object
+15.2.3.10-3-20: FAIL
+# Bug? Object.preventExtensions - named properties cannot be added into an
+#      Arguments object
+15.2.3.10-3-21: FAIL
+# Bug? Object.prototype.toString - '[object Undefined]' will be returned when
+#      'this' value is undefined
+15.2.4.2-1-1: FAIL
+# Bug? Object.prototype.toString - '[object Undefined]' will be returned when
+#      'this' value is undefined
+15.2.4.2-1-2: FAIL
+# Bug? Object.prototype.toString - '[object Null]' will be returned when 'this'
+#      value is null
+15.2.4.2-2-1: FAIL
+# Bug? Object.prototype.toString - '[object Null]' will be returned when 'this'
+#      value is null
+15.2.4.2-2-2: FAIL
+# Bug? Function.prototype.bind - [[Get]] attribute of 'caller' property in 'F'
+#      is thrower
+15.3.4.5-20-2: FAIL
+# Bug? Function.prototype.bind - [[Set]] attribute of 'caller' property in 'F'
+#      is thrower
+15.3.4.5-20-3: FAIL
+# Bug? Function.prototype.bind - [[Get]] attribute of 'arguments' property in
+#      'F' is thrower
+15.3.4.5-21-2: FAIL
+# Bug? Function.prototype.bind - [[Set]] attribute of 'arguments' property in
+#      'F' is thrower
+15.3.4.5-21-3: FAIL
+# Bug? Array.prototype.concat will concat an Array when index property
+#      (read-only) exists in Array.prototype (Step 5.c.i)
+15.4.4.4-5-c-i-1: FAIL
+# Bug? Array.prototype.indexOf applied to undefined throws a TypeError
+15.4.4.14-1-1: FAIL
+# Bug? Array.prototype.indexOf applied to null throws a TypeError
+15.4.4.14-1-2: FAIL
+# Bug? Array.prototype.indexOf - side effects produced by step 1 are visible
+#      when an exception occurs
+15.4.4.14-5-28: FAIL
+# Bug? Array.prototype.indexOf - decreasing length of array does not delete
+#      non-configurable properties
+15.4.4.14-9-a-19: FAIL
+# Bug? Array.prototype.indexOf - element to be retrieved is own accessor
+#      property that overrides an inherited data property on an Array
+15.4.4.14-9-b-i-11: FAIL
+# Bug? Array.prototype.indexOf - element to be retrieved is own accessor
+#      property that overrides an inherited accessor property on an Array
+15.4.4.14-9-b-i-13: FAIL
+# Bug? Array.prototype.indexOf - element to be retrieved is own accessor
+#      property without a get function on an Array
+15.4.4.14-9-b-i-17: FAIL
+# Bug? Array.prototype.indexOf - element to be retrieved is own accessor
+#      property without a get function that overrides an inherited accessor
+#      property on an Array
+15.4.4.14-9-b-i-19: FAIL
+# Bug? Array.prototype.indexOf - side-effects are visible in subsequent
+#      iterations on an Array
+15.4.4.14-9-b-i-28: FAIL
+# Bug? Array.prototype.indexOf - terminates iteration on unhandled exception on
+#      an Array
+15.4.4.14-9-b-i-30: FAIL
+# Bug? Array.prototype.lastIndexOf applied to undefined throws a TypeError
+15.4.4.15-1-1: FAIL
+# Bug? Array.prototype.lastIndexOf applied to null throws a TypeError
+15.4.4.15-1-2: FAIL
+# Bug? Array.prototype.lastIndexOf - side effects produced by step 1 are visible
+#      when an exception occurs
+15.4.4.15-5-28: FAIL
+# Bug? Array.prototype.lastIndexOf - deleting property of prototype causes
+#      prototype index property not to be visited on an Array
+15.4.4.15-8-a-14: FAIL
+# Bug? Array.prototype.lastIndexOf - decreasing length of array does not delete
+#      non-configurable properties
+15.4.4.15-8-a-19: FAIL
+# Bug? Array.prototype.lastIndexOf - element to be retrieved is own accessor
+#      property that overrides an inherited data property on an Array
+15.4.4.15-8-b-i-11: FAIL
+# Bug? Array.prototype.lastIndexOf - element to be retrieved is own accessor
+#      property that overrides an inherited accessor property on an Array
+15.4.4.15-8-b-i-13: FAIL
+# Bug? Array.prototype.lastIndexOf - element to be retrieved is own accessor
+#      property without a get function on an Array
+15.4.4.15-8-b-i-17: FAIL
+# Bug? Array.prototype.lastIndexOf - side-effects are visible in subsequent
+#      iterations on an Array
+15.4.4.15-8-b-i-28: FAIL
+# Bug? Array.prototype.lastIndexOf terminates iteration on unhandled exception
+#      on an Array
+15.4.4.15-8-b-i-30: FAIL
+# Bug? Array.prototype.every - side effects produced by step 2 are visible when
+#      an exception occurs
+15.4.4.16-4-8: FAIL
+# Bug? Array.prototype.every - side effects produced by step 3 are visible when
+#      an exception occurs
+15.4.4.16-4-9: FAIL
+# Bug? Array.prototype.every - the exception is not thrown if exception was
+#      thrown by step 2
+15.4.4.16-4-10: FAIL
+# Bug? Array.prototype.every - the exception is not thrown if exception was
+#      thrown by step 3
+15.4.4.16-4-11: FAIL
+# Bug? Array.prototype.every - calling with no callbackfn is the same as passing
+#      undefined for callbackfn
+15.4.4.16-4-15: FAIL
+# Bug? Array.prototype.every - decreasing length of array does not delete
+#      non-configurable properties
+15.4.4.16-7-b-16: FAIL
+# Bug? Array.prototype.every - element to be retrieved is own accessor property
+#      on an Array
+15.4.4.16-7-c-i-10: FAIL
+# Bug? Array.prototype.every - element to be retrieved is own accessor property
+#      that overrides an inherited data property on an Array
+15.4.4.16-7-c-i-12: FAIL
+# Bug? Array.prototype.every - element to be retrieved is own accessor property
+#      that overrides an inherited accessor property on an Array
+15.4.4.16-7-c-i-14: FAIL
+# Bug? Array.prototype.every - element to be retrieved is own accessor property
+#      without a get function on an Array
+15.4.4.16-7-c-i-18: FAIL
+# Bug? Array.prototype.every - element to be retrieved is own accessor property
+#      without a get function that overrides an inherited accessor property on
+#      an Array
+15.4.4.16-7-c-i-20: FAIL
+# Bug? Array.prototype.every - element changed by getter on previous iterations
+#      is observed on an Array
+15.4.4.16-7-c-i-28: FAIL
+# Bug? Array.prototype.some - side effects produced by step 2 are visible when
+#      an exception occurs
+15.4.4.17-4-8: FAIL
+# Bug? Array.prototype.some - side effects produced by step 3 are visible when
+#      an exception occurs
+15.4.4.17-4-9: FAIL
+# Bug? Array.prototype.some - the exception is not thrown if exception was
+#      thrown by step 2
+15.4.4.17-4-10: FAIL
+# Bug? Array.prototype.some - the exception is not thrown if exception was
+#      thrown by step 3
+15.4.4.17-4-11: FAIL
+# Bug? Array.prototype.some - calling with no callbackfn is the same as passing
+#      undefined for callbackfn
+15.4.4.17-4-15: FAIL
+# Bug? Array.prototype.some - decreasing length of array does not delete
+#      non-configurable properties
+15.4.4.17-7-b-16: FAIL
+# Bug? Array.prototype.some - element to be retrieved is own accessor property
+#      on an Array
+15.4.4.17-7-c-i-10: FAIL
+# Bug? Array.prototype.some - element to be retrieved is own accessor property
+#      that overrides an inherited data property on an Array
+15.4.4.17-7-c-i-12: FAIL
+# Bug? Array.prototype.some - element to be retrieved is own accessor property
+#      that overrides an inherited accessor property on an Array
+15.4.4.17-7-c-i-14: FAIL
+# Bug? Array.prototype.some - element to be retrieved is own accessor property
+#      without a get function on an Array
+15.4.4.17-7-c-i-18: FAIL
+# Bug? Array.prototype.some - element to be retrieved is own accessor property
+#      without a get function that overrides an inherited accessor property on
+#      an Array
+15.4.4.17-7-c-i-20: FAIL
+# Bug? Array.prototype.some - element changed by getter on previous iterations
+#      is observed on an Array
+15.4.4.17-7-c-i-28: FAIL
+# Bug? Array.prototype.forEach - side effects produced by step 2 are visible
+#      when an exception occurs
+15.4.4.18-4-8: FAIL
+# Bug? Array.prototype.forEach - side effects produced by step 3 are visible
+#      when an exception occurs
+15.4.4.18-4-9: FAIL
+# Bug? Array.prototype.forEach - the exception is not thrown if exception was
+#      thrown by step 2
+15.4.4.18-4-10: FAIL
+# Bug? Array.prototype.forEach - the exception is not thrown if exception was
+#      thrown by step 3
+15.4.4.18-4-11: FAIL
+# Bug? Array.prototype.forEach - calling with no callbackfn is the same as
+#      passing undefined for callbackfn
+15.4.4.18-4-15: FAIL
+# Bug? Array.prototype.forEach - decreasing length of array does not delete
+#      non-configurable properties
+15.4.4.18-7-b-16: FAIL
+# Bug? Array.prototype.forEach - element to be retrieved is own accessor
+#      property on an Array
+15.4.4.18-7-c-i-10: FAIL
+# Bug? Array.prototype.forEach - element to be retrieved is own accessor
+#      property that overrides an inherited data property on an Array
+15.4.4.18-7-c-i-12: FAIL
+# Bug? Array.prototype.forEach - element to be retrieved is own accessor
+#      property that overrides an inherited accessor property on an Array
+15.4.4.18-7-c-i-14: FAIL
+# Bug? Array.prototype.forEach - element to be retrieved is own accessor
+#      property without a get function on an Array
+15.4.4.18-7-c-i-18: FAIL
+# Bug? Array.prototype.forEach - element to be retrieved is own accessor
+#      property without a get function that overrides an inherited accessor
+#      property on an Array
+15.4.4.18-7-c-i-20: FAIL
+# Bug? Array.prototype.forEach - element changed by getter on previous
+#      iterations is observed on an Array
+15.4.4.18-7-c-i-28: FAIL
+# Bug? Array.prototype.map - applied to Array-like object, 'length' is an own
+#      data property that overrides an inherited accessor property
+15.4.4.19-2-5: FAIL
+# Bug? Array.prototype.map - Side effects produced by step 2 are visible when an
+#      exception occurs
+15.4.4.19-4-8: FAIL
+# Bug? Array.prototype.map - Side effects produced by step 3 are visible when an
+#      exception occurs
+15.4.4.19-4-9: FAIL
+# Bug? Array.prototype.map - the exception is not thrown if exception was thrown
+#      by step 2
+15.4.4.19-4-10: FAIL
+# Bug? Array.prototype.map - the exception is not thrown if exception was thrown
+#      by step 3
+15.4.4.19-4-11: FAIL
+# Bug? Array.prototype.map - calling with no callbackfn is the same as passing
+#      undefined for callbackfn
+15.4.4.19-4-15: FAIL
+# Bug? Array.prototype.map - decreasing length of array does not delete
+#      non-configurable properties
+15.4.4.19-8-b-16: FAIL
+# Bug? Array.prototype.map - element to be retrieved is own accessor property on
+#      an Array
+15.4.4.19-8-c-i-10: FAIL
+# Bug? Array.prototype.map - element to be retrieved is own accessor property
+#      that overrides an inherited data property on an Array
+15.4.4.19-8-c-i-12: FAIL
+# Bug? Array.prototype.map - element to be retrieved is own accessor property
+#      that overrides an inherited accessor property on an Array
+15.4.4.19-8-c-i-14: FAIL
+# Bug? Array.prototype.map - element to be retrieved is own accessor property
+#      without a get function on an Array
+15.4.4.19-8-c-i-18: FAIL
+# Bug? Array.prototype.map - element to be retrieved is own accessor property
+#      without a get function that overrides an inherited accessor property on
+#      an Array
+15.4.4.19-8-c-i-19: FAIL
+# Bug? Array.prototype.map - element changed by getter on previous iterations is
+#      observed on an Array
+15.4.4.19-8-c-i-28: FAIL
+# Bug? Array.prototype.filter - value of 'length' is a number (value is
+#      negative)
+15.4.4.20-3-7: FAIL
+# Bug? Array.prototype.filter - value of 'length' is a number (value is
+#      Infinity)
+# V8 timeout
+15.4.4.20-3-8: SKIP
+# Bug? Array.prototype.filter - 'length' is a string containing a negative
+#      number
+15.4.4.20-3-12: FAIL
+# Bug? Array.prototype.filter - 'length' is a string containing a decimal number
+15.4.4.20-3-13: FAIL
+# Bug? Array.prototype.filter - 'length' is a string containing +/-Infinity
+15.4.4.20-3-14: SKIP
+# Bug? Array.prototype.filter - value of 'length' is a positive non-integer,
+#      ensure truncation occurs in the proper direction
+# V8 timeout
+15.4.4.20-3-24: FAIL
+# Bug? Array.prototype.filter - value of 'length' is a negative non-integer,
+#      ensure truncation occurs in the proper direction
+15.4.4.20-3-25: FAIL
+# Bug? Array.prototype.filter - value of 'length' is boundary value (2^32)
+# V8 timeout
+15.4.4.20-3-28: SKIP
+# Bug? Array.prototype.filter - value of 'length' is boundary value (2^32 + 1)
+# V8 timeout
+15.4.4.20-3-29: SKIP
+# Bug? Array.prototype.filter - side effects produced by step 2 are visible when
+#      an exception occurs
+15.4.4.20-4-8: FAIL
+# Bug? Array.prototype.filter - side effects produced by step 3 are visible when
+#      an exception occurs
+15.4.4.20-4-9: FAIL
+# Bug? Array.prototype.filter - the exception is not thrown if exception was
+#      thrown by step 2
+15.4.4.20-4-10: FAIL
+# Bug? Array.prototype.filter - the exception is not thrown if exception was
+#      thrown by step 3
+15.4.4.20-4-11: FAIL
+# Bug? Array.prototype.filter - calling with no callbackfn is the same as
+#      passing undefined for callbackfn
+15.4.4.20-4-15: FAIL
+# Bug? Array.prototype.filter - properties can be added to prototype after
+#      current position are visited on an Array-like object
+15.4.4.20-9-b-6: FAIL
+# Bug? Array.prototype.filter - properties can be added to prototype after
+#      current position are visited on an Array
+15.4.4.20-9-b-7: FAIL
+# Bug? Array.prototype.filter - decreasing length of array does not delete
+#      non-configurable properties
+15.4.4.20-9-b-16: FAIL
+# Bug? Array.prototype.filter - element to be retrieved is own data property
+#      that overrides an inherited accessor property on an Array
+15.4.4.20-9-c-i-6: FAIL
+# Bug? Array.prototype.filter - element to be retrieved is own accessor property
+#      on an Array
+15.4.4.20-9-c-i-10: FAIL
+# Bug? Array.prototype.filter - element to be retrieved is own accessor property
+#      that overrides an inherited data property on an Array
+15.4.4.20-9-c-i-12: FAIL
+# Bug? Array.prototype.filter - element to be retrieved is own accessor property
+#      that overrides an inherited accessor property on an Array
+15.4.4.20-9-c-i-14: FAIL
+# Bug? Array.prototype.filter - element to be retrieved is inherited accessor
+#      property on an Array
+15.4.4.20-9-c-i-16: FAIL
+# Bug? Array.prototype.filter - element to be retrieved is own accessor property
+#      without a get function on an Array
+15.4.4.20-9-c-i-18: FAIL
+# Bug? Array.prototype.filter - element to be retrieved is own accessor property
+#      without a get function that overrides an inherited accessor property on
+#      an Array
+15.4.4.20-9-c-i-20: FAIL
+# Bug? Array.prototype.filter - element to be retrieved is inherited accessor
+#      property without a get function on an Array
+15.4.4.20-9-c-i-22: FAIL
+# Bug? Array.prototype.filter - element changed by getter on previous iterations
+#      is observed on an Array
+15.4.4.20-9-c-i-28: FAIL
+# Bug? Array.prototype.reduce - value of 'length' is a number (value is
+#      negative)
+15.4.4.21-3-7: FAIL
+# Bug? Array.prototype.reduce - value of 'length' is a number (value is
+#      Infinity)
+# V8 timeout.
+15.4.4.21-3-8: SKIP
+# Bug? Array.prototype.reduce - 'length' is a string containing a negative
+#      number
+15.4.4.21-3-12: FAIL
+# Bug? Array.prototype.reduce - 'length' is a string containing a decimal number
+15.4.4.21-3-13: FAIL
+# Bug? Array.prototype.reduce - 'length' is a string containing +/-Infinity
+# V8 timeout.
+15.4.4.21-3-14: SKIP
+# Bug? Array.prototype.reduce - value of 'length' is a positive non-integer,
+#      ensure truncation occurs in the proper direction
+15.4.4.21-3-24: FAIL
+# Bug? Array.prototype.reduce - value of 'length' is a negative non-integer,
+#      ensure truncation occurs in the proper direction
+15.4.4.21-3-25: FAIL
+# Bug? Array.prototype.reduce - value of 'length' is boundary value (2^32)
+# V8 timeout.
+15.4.4.21-3-28: SKIP
+# Bug? Array.prototype.reduce - value of 'length' is boundary value (2^32 + 1)
+# V8 timeout.
+15.4.4.21-3-29: SKIP
+# Bug? Array.prototype.reduce - side effects produced by step 2 are visible when
+#      an exception occurs
+15.4.4.21-4-8: FAIL
+# Bug? Array.prototype.reduce - side effects produced by step 3 are visible when
+#      an exception occurs
+15.4.4.21-4-9: FAIL
+# Bug? Array.prototype.reduce - the exception is not thrown if exception was
+#      thrown by step 2
+15.4.4.21-4-10: FAIL
+# Bug? Array.prototype.reduce - the exception is not thrown if exception was
+#      thrown by step 3
+15.4.4.21-4-11: FAIL
+# Bug? Array.prototype.reduce - calling with no callbackfn is the same as
+#      passing undefined for callbackfn
+15.4.4.21-4-15: FAIL
+# Bug? Array.prototype.reduce - decreasing length of array in step 8 does not
+#      delete non-configurable properties
+15.4.4.21-9-b-16: FAIL
+# Bug? Array.prototype.reduce - decreasing length of array does not delete
+#      non-configurable properties
+15.4.4.21-9-b-29: FAIL
+# Bug? Array.prototype.reduceRight - value of 'length' is a number (value is
+#      negative)
+15.4.4.22-3-7: FAIL
+# Bug? Array.prototype.reduceRight - value of 'length' is a number (value is
+#      Infinity)
+# V8 timeout.
+15.4.4.22-3-8: SKIP
+# Bug? Array.prototype.reduceRight - value of 'length' is a string containing a
+#      negative number
+15.4.4.22-3-12: FAIL
+# Bug? Array.prototype.reduceRight - value of 'length' is a string containing a
+#      decimal number
+15.4.4.22-3-13: FAIL
+# Bug? Array.prototype.reduceRight - value of 'length' is a string containing
+#      +/-Infinity
+# V8 timeout.
+15.4.4.22-3-14: SKIP
+# Bug? Array.prototype.reduceRight - value of 'length' is a positive
+#      non-integer, ensure truncation occurs in the proper direction
+15.4.4.22-3-24: FAIL
+# Bug? Array.prototype.reduceRight - value of 'length' is a negative
+#      non-integer, ensure truncation occurs in the proper direction
+15.4.4.22-3-25: FAIL
+# Bug? Array.prototype.reduceRight - value of 'length' is boundary value (2^32)
+# V8 timeout.
+15.4.4.22-3-28: SKIP
+# Bug? Array.prototype.reduceRight - value of 'length' is boundary value (2^32 +
+#      1)
+# V8 timeout.
+15.4.4.22-3-29: SKIP
+# Bug? Array.prototype.reduceRight - side effects produced by step 2 are visible
+#      when an exception occurs
+15.4.4.22-4-8: FAIL
+# Bug? Array.prototype.reduceRight - side effects produced by step 3 are visible
+#      when an exception occurs
+15.4.4.22-4-9: FAIL
+# Bug? Array.prototype.reduceRight - the exception is not thrown if exception
+#      was thrown by step 2
+15.4.4.22-4-10: FAIL
+# Bug? Array.prototype.reduceRight - the exception is not thrown if exception
+#      was thrown by step 3
+15.4.4.22-4-11: FAIL
+# Bug? Array.prototype.reduceRight - calling with no callbackfn is the same as
+#      passing undefined for callbackfn
+15.4.4.22-4-15: FAIL
+# Bug? Array.prototype.reduceRight - element to be retrieved is own accessor
+#      property that overrides an inherited data property on an Array
+15.4.4.22-8-b-iii-1-12: FAIL
+# Bug? Array.prototype.reduceRight - element to be retrieved is own accessor
+#      property without a get function on an Array
+15.4.4.22-8-b-iii-1-18: FAIL
+# Bug? Array.prototype.reduceRight - element to be retrieved is own accessor
+#      property without a get function that overrides an inherited accessor
+#      property on an Array
+15.4.4.22-8-b-iii-1-20: FAIL
+# Bug? Array.prototype.reduceRight - element changed by getter on current
+#      iteration is observed in subsequent iterations on an Array
+15.4.4.22-8-b-iii-1-30: FAIL
+# Bug? Array.prototype.reduceRight - Exception in getter terminate iteration on
+#      an Array
+15.4.4.22-8-b-iii-1-33: FAIL
+# Bug? Array.prototype.reduceRight - modifications to length don't change number
+#      of iterations in step 9
+15.4.4.22-8-b-2: FAIL
+# Bug? Array.prototype.reduceRight - deleting own property in step 8 causes
+#      deleted index property not to be visited on an Array
+15.4.4.22-9-b-9: FAIL
+# Bug? Array.prototype.reduceRight - deleting own property with prototype
+#      property in step 8 causes prototype index property to be visited on an
+#      Array
+15.4.4.22-9-b-13: FAIL
+# Bug? Array.prototype.reduceRight - decreasing length of array in step 8 does
+#      not delete non-configurable properties
+15.4.4.22-9-b-16: FAIL
+# Bug? Array.prototype.reduceRight - deleting property of prototype causes
+#      deleted index property not to be visited on an Array
+15.4.4.22-9-b-24: FAIL
+# Bug? Array.prototype.reduceRight - deleting own property with prototype
+#      property causes prototype index property to be visited on an Array
+15.4.4.22-9-b-26: FAIL
+# Bug? Array.prototype.reduceRight - decreasing length of array does not delete
+#      non-configurable properties
+15.4.4.22-9-b-29: FAIL
+# Bug? Array.prototype.reduceRight - element changed by getter on previous
+#      iterations is observed on an Array
+15.4.4.22-9-c-i-30: FAIL
+# Bug? Array.prototype.reduceRight - modifications to length will change number
+#      of iterations
+15.4.4.22-9-9: FAIL
+# Bug? String.prototype.trim throws TypeError when string is undefined
+15.5.4.20-1-1: FAIL
+# Bug? String.prototype.trim throws TypeError when string is null
+15.5.4.20-1-2: FAIL
+# Bug? String.prototype.trim - 'S' is a string with all WhiteSpace
+15.5.4.20-3-2: FAIL
+# Bug? String.prototype.trim - 'S' is a string with all union of WhiteSpace and
+#      LineTerminator
+15.5.4.20-3-3: FAIL
+# Bug? String.prototype.trim - 'S' is a string start with union of all
+#      LineTerminator and all WhiteSpace
+15.5.4.20-3-4: FAIL
+# Bug? String.prototype.trim - 'S' is a string end with union of all
+#      LineTerminator and all WhiteSpace
+15.5.4.20-3-5: FAIL
+# Bug? String.prototype.trim - 'S' is a string start with union of all
+#      LineTerminator and all WhiteSpace and end with union of all
+#      LineTerminator and all WhiteSpace
+15.5.4.20-3-6: FAIL
+# Bug? String.prototype.trim handles whitepace and lineterminators (\\uFEFFabc)
+15.5.4.20-4-10: FAIL
+# Bug? String.prototype.trim handles whitepace and lineterminators (abc\\uFEFF)
+15.5.4.20-4-18: FAIL
+# Bug? String.prototype.trim handles whitepace and lineterminators
+#      (\\uFEFF\\uFEFF)
+15.5.4.20-4-34: FAIL
+# Bug? Date Time String Format - specified default values will be set for all
+#      optional fields(MM, DD, mm, ss and time zone) when they are absent
+15.9.1.15-1: FAIL
+# Bug? Date.prototype.toISOString - RangeError is thrown when value of date is
+#      Date(1970, 0, -99999999, 0, 0, 0, -1), the time zone is UTC(0)
+15.9.5.43-0-8: FAIL
+# Bug? Date.prototype.toISOString - RangeError is not thrown when value of date
+#      is Date(1970, 0, 100000001, 0, 0, 0, -1), the time zone is UTC(0)
+15.9.5.43-0-11: FAIL
+# Bug? Date.prototype.toISOString - RangeError is not thrown when value of date
+#      is Date(1970, 0, 100000001, 0, 0, 0, 0), the time zone is UTC(0)
+15.9.5.43-0-12: FAIL
+# Bug? Date.prototype.toISOString - RangeError is thrown when value of date is
+#      Date(1970, 0, 100000001, 0, 0, 0, 1), the time zone is UTC(0)
+15.9.5.43-0-13: FAIL
+# Bug? Date.prototype.toISOString - when value of year is -Infinity
+#      Date.prototype.toISOString throw the RangeError
+15.9.5.43-0-14: FAIL
+# Bug? Date.prototype.toISOString - value of year is Infinity
+#      Date.prototype.toISOString throw the RangeError
+15.9.5.43-0-15: FAIL
+# Bug? RegExp - the thrown error is SyntaxError instead of RegExpError when 'F'
+#      contains any character other than 'g', 'i', or 'm'
+15.10.4.1-3: FAIL
+# Bug? RegExp.prototype is itself a RegExp
+15.10.6: FAIL
+# Bug? RegExp.prototype.source is of type String
+15.10.7.1-1: FAIL
+# Bug? RegExp.prototype.source is a data property with default attribute values
+#      (false)
+15.10.7.1-2: FAIL
+# Bug? RegExp.prototype.global is of type Boolean
+15.10.7.2-1: FAIL
+# Bug? RegExp.prototype.global is a data property with default attribute values
+#      (false)
+15.10.7.2-2: FAIL
+# Bug? RegExp.prototype.ignoreCase is of type Boolean
+15.10.7.3-1: FAIL
+# Bug? RegExp.prototype.ignoreCase is a data property with default attribute
+#      values (false)
+15.10.7.3-2: FAIL
+# Bug? RegExp.prototype.multiline is of type Boolean
+15.10.7.4-1: FAIL
+# Bug? RegExp.prototype.multiline is a data property with default attribute
+#      values (false)
+15.10.7.4-2: FAIL
+# Bug? RegExp.prototype.lastIndex is of type Number
+15.10.7.5-1: FAIL
+# Bug? RegExp.prototype.lastIndex is a data property with specified attribute
+#      values
+15.10.7.5-2: FAIL
+# Bug? Error.prototype.toString return the value of 'msg' when 'name' is empty
+#      string and 'msg' isn't undefined
+15.11.4.4-8-1: FAIL
diff --git a/test/test262/testcfg.py b/test/test262/testcfg.py
new file mode 100644
index 0000000..aa1212e
--- /dev/null
+++ b/test/test262/testcfg.py
@@ -0,0 +1,123 @@
+# Copyright 2011 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+#       copyright notice, this list of conditions and the following
+#       disclaimer in the documentation and/or other materials provided
+#       with the distribution.
+#     * Neither the name of Google Inc. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (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
+
+
+TEST_262_HARNESS = ['sta.js']
+
+
+class Test262TestCase(test.TestCase):
+
+  def __init__(self, filename, path, context, root, mode, framework):
+    super(Test262TestCase, self).__init__(context, path, mode)
+    self.filename = filename
+    self.framework = framework
+    self.root = root
+
+  def IsNegative(self):
+    return self.filename.endswith('-n.js')
+
+  def GetLabel(self):
+    return "%s test262 %s %s" % (self.mode, self.GetGroup(), self.GetName())
+
+  def IsFailureOutput(self, output):
+    if output.exit_code != 0:
+      return True
+    return 'FAILED!' in output.stdout
+
+  def GetCommand(self):
+    result = self.context.GetVmCommand(self, self.mode)
+    result += ['-e', 'var window = this']
+    result += self.framework
+    result.append(self.filename)
+    return result
+
+  def GetName(self):
+    return self.path[-1]
+
+  def GetGroup(self):
+    return self.path[0]
+
+  def GetSource(self):
+    return open(self.filename).read()
+
+
+class Test262TestConfiguration(test.TestConfiguration):
+
+  def __init__(self, context, root):
+    super(Test262TestConfiguration, self).__init__(context, root)
+
+  def AddIETestCenter(self, tests, current_path, path, mode):
+    current_root = join(self.root, 'data', 'test', 'suite', 'ietestcenter')
+    harness = [join(self.root, 'data', 'test', 'harness', f)
+                   for f in TEST_262_HARNESS]
+    harness += [join(self.root, 'harness-adapt.js')]
+    for root, dirs, files in os.walk(current_root):
+      for dotted in [x  for x in dirs if x.startswith('.')]:
+        dirs.remove(dotted)
+      dirs.sort()
+      root_path = root[len(self.root):].split(os.path.sep)
+      root_path = current_path + [x for x in root_path if x]
+      files.sort()
+      for file in files:
+        if file.endswith('.js'):
+          if self.Contains(path, root_path):
+            test_path = ['ietestcenter', file[:-3]]
+            test = Test262TestCase(join(root, file), test_path, self.context,
+                                   self.root, mode, harness)
+            tests.append(test)
+
+  def AddSputnikConvertedTests(self, tests, current_path, path, mode):
+    # To be enabled
+    pass
+
+  def AddSputnikTests(self, tests, current_path, path, mode):
+    # To be enabled
+    pass
+
+  def ListTests(self, current_path, path, mode, variant_flags):
+    tests = []
+    self.AddIETestCenter(tests, current_path, path, mode)
+    self.AddSputnikConvertedTests(tests, current_path, path, mode)
+    self.AddSputnikTests(tests, current_path, path, mode)
+    return tests
+
+  def GetBuildRequirements(self):
+    return ['sample', 'sample=shell']
+
+  def GetTestStatus(self, sections, defs):
+    status_file = join(self.root, 'test262.status')
+    if exists(status_file):
+      test.ReadConfigurationInto(status_file, sections, defs)
+
+
+def GetConfiguration(context, root):
+  return Test262TestConfiguration(context, root)
diff --git a/tools/freebsd-tick-processor b/tools/freebsd-tick-processor
new file mode 100755
index 0000000..2bb2618
--- /dev/null
+++ b/tools/freebsd-tick-processor
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# A wrapper script to call 'linux-tick-processor'.
+
+# Known issues on FreeBSD:
+#  No ticks from C++ code.
+#  You must have d8 built and in your path before calling this.
+
+tools_path=`cd $(dirname "$0");pwd`
+$tools_path/linux-tick-processor "$@"
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 6dab52d..8804454 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -41,6 +41,7 @@
           'ENABLE_LOGGING_AND_PROFILING',
           'ENABLE_DEBUGGER_SUPPORT',
           'ENABLE_VMSTATE_TRACKING',
+          'V8_FAST_TLS',
         ],
         'conditions': [
           ['OS!="mac"', {
@@ -211,38 +212,6 @@
           },
         },
         {
-          'target_name': 'v8_preparser',
-          'include_dirs': [
-            '../../include',
-            '../../src',
-          ],
-          'sources': [
-            '../../src/allocation.cc',
-            '../../src/hashmap.cc',
-            '../../src/preparse-data.cc',
-            '../../src/preparser.cc',
-            '../../src/preparser-api.cc',
-            '../../src/scanner-base.cc',
-            '../../src/token.cc',
-            '../../src/unicode.cc',
-          ],
-          'conditions': [
-            ['OS=="win" and component=="shared_library"', {
-              'sources': [ '../../src/v8preparserdll-main.cc' ],
-              'defines': [ 'BUILDING_V8_SHARED' ],
-              'direct_dependent_settings': {
-                'defines': [ 'USING_V8_SHARED' ]
-              },
-              'type': '<(component)',
-            } , {
-              'type': 'none'
-            }],
-            ['OS!="win"', {
-              'type': '<(library)'
-            }],
-          ]
-        },
-        {
           'target_name': 'v8_snapshot',
           'type': '<(library)',
           'conditions': [
@@ -435,6 +404,8 @@
             '../../src/jump-target.h',
             '../../src/jsregexp.cc',
             '../../src/jsregexp.h',
+            '../../src/isolate.cc',
+            '../../src/isolate.h',
             '../../src/list-inl.h',
             '../../src/list.h',
             '../../src/lithium.cc',
@@ -455,7 +426,6 @@
             '../../src/macro-assembler.h',
             '../../src/mark-compact.cc',
             '../../src/mark-compact.h',
-            '../../src/memory.h',
             '../../src/messages.cc',
             '../../src/messages.h',
             '../../src/natives.h',
@@ -468,6 +438,9 @@
             '../../src/objects.h',
             '../../src/parser.cc',
             '../../src/parser.h',
+            '../../src/platform-tls-mac.h',
+            '../../src/platform-tls-win32.h',
+            '../../src/platform-tls.h',
             '../../src/platform.h',
             '../../src/preparse-data.cc',
             '../../src/preparse-data.h',
@@ -511,6 +484,7 @@
             '../../src/serialize.cc',
             '../../src/serialize.h',
             '../../src/shell.h',
+            '../../src/small-pointer-list.h',
             '../../src/smart-pointer.h',
             '../../src/snapshot-common.cc',
             '../../src/snapshot.h',
@@ -544,6 +518,7 @@
             '../../src/v8.h',
             '../../src/v8checks.h',
             '../../src/v8globals.h',
+            '../../src/v8memory.h',
             '../../src/v8threads.cc',
             '../../src/v8threads.h',
             '../../src/v8utils.h',
diff --git a/tools/linux-tick-processor b/tools/linux-tick-processor
index 1715705..9789697 100755
--- a/tools/linux-tick-processor
+++ b/tools/linux-tick-processor
@@ -3,12 +3,12 @@
 tools_path=`cd $(dirname "$0");pwd`
 if [ ! "$D8_PATH" ]; then
   d8_public=`which d8`
-  if [ $d8_public ]; then D8_PATH=$(dirname "$d8_public"); fi
+  if [ -x $d8_public ]; then D8_PATH=$(dirname "$d8_public"); fi
 fi
 [ "$D8_PATH" ] || D8_PATH=$tools_path/..
 d8_exec=$D8_PATH/d8
 
-if [ "$1" == "--no-build" ]; then
+if [ "$1" = "--no-build" ]; then
   shift
 else
 # compile d8 if it doesn't exist, assuming this script
@@ -16,15 +16,17 @@
   [ -x $d8_exec ] || scons -j4 -C $D8_PATH -Y $tools_path/.. d8
 fi
 
+
 # find the name of the log file to process, it must not start with a dash.
 log_file="v8.log"
 for arg in "$@"
 do
-  if [[ "${arg}" != -* ]]; then
+  if ! expr "X${arg}" : "^X-" > /dev/null; then
     log_file=${arg}
   fi
 done
 
+
 # nm spits out 'no symbols found' messages to stderr.
 cat $log_file | $d8_exec $tools_path/splaytree.js $tools_path/codemap.js \
   $tools_path/csvparser.js $tools_path/consarray.js \
diff --git a/tools/test.py b/tools/test.py
index 939ca0c..066a559 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -340,6 +340,9 @@
   def IsNegative(self):
     return False
 
+  def TestsIsolates(self):
+    return False
+
   def CompareTime(self, other):
     return cmp(other.duration, self.duration)
 
@@ -371,6 +374,9 @@
   def AfterRun(self, result):
     pass
 
+  def GetCustomFlags(self, mode):
+    return None
+
   def Run(self):
     self.BeforeRun()
     try:
@@ -499,11 +505,19 @@
 
 
 def CheckedUnlink(name):
-  try:
-    os.unlink(name)
-  except OSError, e:
-    PrintError("os.unlink() " + str(e))
-
+  # On Windows, when run with -jN in parallel processes,
+  # OS often fails to unlink the temp file. Not sure why.
+  # Need to retry.
+  # Idea from https://bugs.webkit.org/attachment.cgi?id=75982&action=prettypatch
+  retry_count = 0
+  while retry_count < 30:
+    try:
+      os.unlink(name)
+      return
+    except OSError, e:
+      retry_count += 1;
+      time.sleep(retry_count * 0.1)
+  PrintError("os.unlink() " + str(e))
 
 def Execute(args, context, timeout=None):
   (fd_out, outname) = tempfile.mkstemp()
@@ -600,7 +614,7 @@
 
   def AddTestsToList(self, result, current_path, path, context, mode):
     for v in VARIANT_FLAGS:
-      tests = self.GetConfiguration(context).ListTests(current_path, path, mode)
+      tests = self.GetConfiguration(context).ListTests(current_path, path, mode, v)
       for t in tests: t.variant_flags = v
       result += tests
 
@@ -623,7 +637,7 @@
         result += test.GetBuildRequirements(rest, context)
     return result
 
-  def ListTests(self, current_path, path, context, mode):
+  def ListTests(self, current_path, path, context, mode, variant_flags):
     (name, rest) = CarCdr(path)
     result = [ ]
     for test in self.tests:
@@ -671,7 +685,10 @@
     return [self.GetVm(mode)] + self.GetVmFlags(testcase, mode)
 
   def GetVmFlags(self, testcase, mode):
-    return testcase.variant_flags + FLAGS[mode]
+    flags = testcase.GetCustomFlags(mode)
+    if flags is None:
+      flags = FLAGS[mode]
+    return testcase.variant_flags + flags
 
   def GetTimeout(self, testcase, mode):
     result = self.timeout * TIMEOUT_SCALEFACTOR[mode]
@@ -1007,6 +1024,9 @@
     self.case = case
     self.outcomes = outcomes
 
+  def TestsIsolates(self):
+    return self.case.TestsIsolates()
+
 
 class Configuration(object):
   """The parsed contents of a configuration file"""
@@ -1166,6 +1186,7 @@
   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")
+  result.add_option("--isolates", help="Whether to test isolates", default=False, action="store_true")
   result.add_option("--store-unexpected-output",
       help="Store the temporary JS files from tests that fails",
       dest="store_unexpected_output", default=True, action="store_true")
@@ -1398,7 +1419,7 @@
         'simulator': options.simulator,
         'crankshaft': options.crankshaft
       }
-      test_list = root.ListTests([], path, context, mode)
+      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:
@@ -1432,6 +1453,8 @@
   def DoSkip(case):
     return SKIP in case.outcomes or SLOW in case.outcomes
   cases_to_run = [ c for c in all_cases if not DoSkip(c) ]
+  if not options.isolates:
+    cases_to_run = [c for c in cases_to_run if not c.TestsIsolates()]
   if len(cases_to_run) == 0:
     print "No tests to run."
     return 0
diff --git a/tools/tickprocessor.js b/tools/tickprocessor.js
index f105a21..7a05ef1 100644
--- a/tools/tickprocessor.js
+++ b/tools/tickprocessor.js
@@ -161,7 +161,9 @@
           processor: this.processFunctionMove },
       'snapshot-pos': { parsers: [parseInt, parseInt],
           processor: this.processSnapshotPosition },
-      'tick': { parsers: [parseInt, parseInt, parseInt, parseInt, 'var-args'],
+      'tick': {
+          parsers: [parseInt, parseInt, parseInt,
+                    parseInt, parseInt, 'var-args'],
           processor: this.processTick },
       'heap-sample-begin': { parsers: [null, null, parseInt],
           processor: this.processHeapSampleBegin },
@@ -344,22 +346,33 @@
 };
 
 
-TickProcessor.prototype.processTick = function(pc, sp, tos, vmState, stack) {
+TickProcessor.prototype.processTick = function(pc,
+                                               sp,
+                                               is_external_callback,
+                                               tos_or_external_callback,
+                                               vmState,
+                                               stack) {
   this.ticks_.total++;
   if (vmState == TickProcessor.VmStates.GC) this.ticks_.gc++;
   if (!this.includeTick(vmState)) {
     this.ticks_.excluded++;
     return;
   }
-
-  if (tos) {
-    var funcEntry = this.profile_.findEntry(tos);
+  if (is_external_callback) {
+    // Don't use PC when in external callback code, as it can point
+    // inside callback's code, and we will erroneously report
+    // that a callback calls itself.
+    pc = 0;
+  } else if (tos_or_external_callback) {
+    // Find out, if top of stack was pointing inside a JS function
+    // meaning that we have encountered a frameless invocation.
+    var funcEntry = this.profile_.findEntry(tos_or_external_callback);
     if (!funcEntry || !funcEntry.isJSFunction || !funcEntry.isJSFunction()) {
-      tos = 0;
+      tos_or_external_callback = 0;
     }
   }
 
-  this.profile_.recordTick(this.processStack(pc, tos, stack));
+  this.profile_.recordTick(this.processStack(pc, tos_or_external_callback, stack));
 };
 
 
diff --git a/tools/v8.xcodeproj/project.pbxproj b/tools/v8.xcodeproj/project.pbxproj
index 10fbc58..386e7f0 100644
--- a/tools/v8.xcodeproj/project.pbxproj
+++ b/tools/v8.xcodeproj/project.pbxproj
@@ -210,6 +210,9 @@
 		895692A412D4ED240072C313 /* gc-extension.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E24DA12B14B9F0083370F /* gc-extension.cc */; };
 		895692A512D4ED240072C313 /* objects-printer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8946827412C26EB700C914BC /* objects-printer.cc */; };
 		8956B6CF0F5D86730033B5A2 /* debug-agent.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8956B6CD0F5D86570033B5A2 /* debug-agent.cc */; };
+		895D5B531334212D00254083 /* isolate.cc in Sources */ = {isa = PBXBuildFile; fileRef = 895D5B521334212D00254083 /* isolate.cc */; };
+		895D5B541334212D00254083 /* isolate.cc in Sources */ = {isa = PBXBuildFile; fileRef = 895D5B521334212D00254083 /* isolate.cc */; };
+		895D5B551334212D00254083 /* isolate.cc in Sources */ = {isa = PBXBuildFile; fileRef = 895D5B521334212D00254083 /* isolate.cc */; };
 		895FA753107FFED3006F39D4 /* constants-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 895FA748107FFE73006F39D4 /* constants-arm.cc */; };
 		896FA1E5130F93D300042054 /* lithium-gap-resolver-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 896FA1E3130F93D300042054 /* lithium-gap-resolver-arm.cc */; };
 		896FD03A0E78D717003DFB6A /* libv8-arm.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 89F23C870E78D5B2006B2466 /* libv8-arm.a */; };
@@ -562,6 +565,8 @@
 		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>"; };
+		891C92FD1334226000FF4757 /* lithium-allocator-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "lithium-allocator-inl.h"; sourceTree = "<group>"; };
+		891C92FE133422EB00FF4757 /* isolate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = isolate.h; sourceTree = "<group>"; };
 		8924315A12F8539900906AB2 /* lithium-gap-resolver-x64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lithium-gap-resolver-x64.cc"; path = "x64/lithium-gap-resolver-x64.cc"; sourceTree = "<group>"; };
 		8924315B12F8539900906AB2 /* lithium-gap-resolver-x64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lithium-gap-resolver-x64.h"; path = "x64/lithium-gap-resolver-x64.h"; sourceTree = "<group>"; };
 		8938A2A212D63B630080CDDE /* lithium-x64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lithium-x64.cc"; path = "x64/lithium-x64.cc"; sourceTree = "<group>"; };
@@ -638,6 +643,8 @@
 		895692AA12D4ED240072C313 /* libv8-x64.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libv8-x64.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 		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>"; };
+		895D5B4C1334210400254083 /* allocation-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "allocation-inl.h"; sourceTree = "<group>"; };
+		895D5B521334212D00254083 /* isolate.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = isolate.cc; sourceTree = "<group>"; };
 		895FA720107FFB15006F39D4 /* jump-target-heavy-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "jump-target-heavy-inl.h"; sourceTree = "<group>"; };
 		895FA725107FFB57006F39D4 /* codegen-ia32-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "codegen-ia32-inl.h"; path = "ia32/codegen-ia32-inl.h"; sourceTree = "<group>"; };
 		895FA72A107FFB85006F39D4 /* register-allocator-ia32-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "register-allocator-ia32-inl.h"; path = "ia32/register-allocator-ia32-inl.h"; sourceTree = "<group>"; };
@@ -754,7 +761,7 @@
 		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>"; };
+		897FF15B0E719B8F00D62E90 /* v8memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = v8memory.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>"; };
@@ -907,6 +914,9 @@
 		89F3605A12DCDF6400ACF8A6 /* lithium-codegen-x64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lithium-codegen-x64.cc"; path = "x64/lithium-codegen-x64.cc"; sourceTree = "<group>"; };
 		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>"; };
+		9C1F8E1D133906180068B362 /* small-pointer-list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "small-pointer-list.h"; sourceTree = "<group>"; };
+		9C76176D133FB7740057370B /* platform-tls-mac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "platform-tls-mac.h"; sourceTree = "<group>"; };
+		9C8E8061133CF772004058A5 /* platform-tls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "platform-tls.h"; sourceTree = "<group>"; };
 		9F11D99E105AF0A300EBE5B2 /* heap-profiler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "heap-profiler.cc"; sourceTree = "<group>"; };
 		9F11D99F105AF0A300EBE5B2 /* heap-profiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "heap-profiler.h"; sourceTree = "<group>"; };
 		9F2B370E114FF62D007CDAF4 /* circular-queue-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "circular-queue-inl.h"; sourceTree = "<group>"; };
@@ -1055,6 +1065,7 @@
 				89B91B7A12D4EF65002FF4BC /* x64 */,
 				897FF0F60E719B8F00D62E90 /* accessors.cc */,
 				897FF0F70E719B8F00D62E90 /* accessors.h */,
+				895D5B4C1334210400254083 /* allocation-inl.h */,
 				897FF0F80E719B8F00D62E90 /* allocation.cc */,
 				897FF0F90E719B8F00D62E90 /* allocation.h */,
 				897FF0FA0E719B8F00D62E90 /* api.cc */,
@@ -1180,6 +1191,8 @@
 				89D7DDD912E8DE09001E2B82 /* inspector.h */,
 				89A15C660EE4665300B48DEB /* interpreter-irregexp.cc */,
 				89A15C670EE4665300B48DEB /* interpreter-irregexp.h */,
+				895D5B521334212D00254083 /* isolate.cc */,
+				891C92FE133422EB00FF4757 /* isolate.h */,
 				897FF14E0E719B8F00D62E90 /* jsregexp.cc */,
 				897FF14F0E719B8F00D62E90 /* jsregexp.h */,
 				895FA720107FFB15006F39D4 /* jump-target-heavy-inl.h */,
@@ -1193,6 +1206,7 @@
 				58950D510F55514900F3E8BA /* jump-target.h */,
 				897FF1500E719B8F00D62E90 /* list-inl.h */,
 				897FF1510E719B8F00D62E90 /* list.h */,
+				891C92FD1334226000FF4757 /* lithium-allocator-inl.h */,
 				893E249312B14B3D0083370F /* lithium-allocator.cc */,
 				893E249412B14B3D0083370F /* lithium-allocator.h */,
 				894A59E712D777E80000766D /* lithium.cc */,
@@ -1207,7 +1221,7 @@
 				897FF1580E719B8F00D62E90 /* macro-assembler.h */,
 				897FF1590E719B8F00D62E90 /* mark-compact.cc */,
 				897FF15A0E719B8F00D62E90 /* mark-compact.h */,
-				897FF15B0E719B8F00D62E90 /* memory.h */,
+				897FF15B0E719B8F00D62E90 /* v8memory.h */,
 				897FF15C0E719B8F00D62E90 /* messages.cc */,
 				897FF15D0E719B8F00D62E90 /* messages.h */,
 				897FF15E0E719B8F00D62E90 /* mksnapshot.cc */,
@@ -1226,6 +1240,8 @@
 				897FF1670E719B8F00D62E90 /* platform-macos.cc */,
 				897FF1680E719B8F00D62E90 /* platform-nullos.cc */,
 				893A72230F7B0FF200303DD2 /* platform-posix.cc */,
+				9C76176D133FB7740057370B /* platform-tls-mac.h */,
+				9C8E8061133CF772004058A5 /* platform-tls.h */,
 				897FF1690E719B8F00D62E90 /* platform-win32.cc */,
 				897FF16A0E719B8F00D62E90 /* platform.h */,
 				893E249512B14B3D0083370F /* preparse-data.cc */,
@@ -1272,6 +1288,7 @@
 				897FF17B0E719B8F00D62E90 /* serialize.h */,
 				897FF17C0E719B8F00D62E90 /* shell.h */,
 				893E24A012B14B3D0083370F /* simulator.h */,
+				9C1F8E1D133906180068B362 /* small-pointer-list.h */,
 				897FF1810E719B8F00D62E90 /* smart-pointer.h */,
 				897FF1820E719B8F00D62E90 /* snapshot-common.cc */,
 				897FF1830E719B8F00D62E90 /* snapshot-empty.cc */,
@@ -1982,6 +1999,7 @@
 				89D7DDDE12E8DE09001E2B82 /* gdb-jit.cc in Sources */,
 				89D7DDDF12E8DE09001E2B82 /* inspector.cc in Sources */,
 				8924315C12F8539900906AB2 /* lithium-gap-resolver-x64.cc in Sources */,
+				895D5B551334212D00254083 /* isolate.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -2119,6 +2137,7 @@
 				89D7DDD512E8DDCF001E2B82 /* lithium-gap-resolver-ia32.cc in Sources */,
 				89D7DDDA12E8DE09001E2B82 /* gdb-jit.cc in Sources */,
 				89D7DDDB12E8DE09001E2B82 /* inspector.cc in Sources */,
+				895D5B531334212D00254083 /* isolate.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -2296,6 +2315,7 @@
 				89D7DDDC12E8DE09001E2B82 /* gdb-jit.cc in Sources */,
 				89D7DDDD12E8DE09001E2B82 /* inspector.cc in Sources */,
 				896FA1E5130F93D300042054 /* lithium-gap-resolver-arm.cc in Sources */,
+				895D5B541334212D00254083 /* isolate.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/tools/visual_studio/v8_base.vcproj b/tools/visual_studio/v8_base.vcproj
index 5f76069..a005f7a 100644
--- a/tools/visual_studio/v8_base.vcproj
+++ b/tools/visual_studio/v8_base.vcproj
@@ -781,7 +781,7 @@
         >
       </File>
       <File
-        RelativePath="..\..\src\memory.h"
+        RelativePath="..\..\src\v8memory.h"
         >
       </File>
       <File
@@ -870,6 +870,14 @@
         >
       </File>
       <File
+        RelativePath="..\..\src\platform-tls-win32.h"
+        >
+      </File>
+      <File
+        RelativePath="..\..\src\platform-tls.h"
+        >
+      </File>
+      <File
         RelativePath="..\..\src\platform-win32.cc"
         >
       </File>
@@ -1026,6 +1034,10 @@
         >
       </File>
       <File
+        RelativePath="..\..\src\small-pointer-list.h"
+        >
+      </File>
+      <File
         RelativePath="..\..\src\snapshot-common.cc"
         >
       </File>
diff --git a/tools/visual_studio/v8_base_arm.vcproj b/tools/visual_studio/v8_base_arm.vcproj
index feb7e6c..87c178a 100644
--- a/tools/visual_studio/v8_base_arm.vcproj
+++ b/tools/visual_studio/v8_base_arm.vcproj
@@ -765,7 +765,7 @@
         >
       </File>
       <File
-        RelativePath="..\..\src\memory.h"
+        RelativePath="..\..\src\v8memory.h"
         >
       </File>
       <File
@@ -984,6 +984,10 @@
         >
       </File>
       <File
+        RelativePath="..\..\src\small-pointer-list.h"
+        >
+      </File>
+      <File
         RelativePath="..\..\src\snapshot-common.cc"
         >
       </File>
diff --git a/tools/visual_studio/v8_base_x64.vcproj b/tools/visual_studio/v8_base_x64.vcproj
index 14ed77e..de921bc 100644
--- a/tools/visual_studio/v8_base_x64.vcproj
+++ b/tools/visual_studio/v8_base_x64.vcproj
@@ -782,7 +782,7 @@
         >
       </File>
       <File
-        RelativePath="..\..\src\memory.h"
+        RelativePath="..\..\src\v8memory.h"
         >
       </File>
       <File
@@ -1026,6 +1026,10 @@
         >
       </File>
       <File
+        RelativePath="..\..\src\small-pointer-list.h"
+        >
+      </File>
+      <File
         RelativePath="..\..\src\snapshot-common.cc"
         >
       </File>