Version 3.5.4

Added preliminary implementation of ES Harmony weak maps.  Weak maps can be enabled by the flag --harmony_weakmaps.

Introduced a toplevel Makefile to support GYP-based building.  GYP can be found at http://gyp.googlecode.com.

Fixed a bug in the length property of functions created by Function.prototype.bind.

Reduced malloc heap allocation on process startup.

Several important code generation bug fixes.

Performance improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@8874 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/.gitignore b/.gitignore
index 7219675..d09889b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,5 +31,4 @@
 /tools/visual_studio/Release
 /xcodebuild/
 TAGS
-Makefile
 *.Makefile
diff --git a/ChangeLog b/ChangeLog
index 643dd36..d05b70e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2011-08-10: Version 3.5.4
+
+        Added a preliminary implementation of ES Harmony weak maps.  Weak
+        maps can be enabled by the flag --harmony-weakmaps.
+
+        Introduced a toplevel Makefile to support GYP-based building.  GYP
+        can be obtained from http://gyp.googlecode.com.
+
+        Fixed a bug in the length property of functions created by
+        Function.prototype.bind.
+
+        Reduced malloc heap allocation on process startup.
+
+        Several important code generation bug fixes.
+
+        Performance improvements on all platforms.
+
+
 2011-08-03: Version 3.5.3
 
         MIPS: Port of fix to ClassOf check from ARM.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..85a8f6f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,110 @@
+# 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.
+
+
+# Variable default definitions. Override them by exporting them in your shell.
+CXX ?= "g++"  # For distcc: export CXX="distcc g++"
+LINK ?= "g++"
+OUTDIR ?= out
+TESTJOBS ?= -j16
+GYPFLAGS ?= -Dv8_can_use_vfp_instructions=true
+
+# Architectures and modes to be compiled.
+ARCHES = ia32 x64 arm
+MODES = release debug
+
+# List of files that trigger Makefile regeneration:
+GYPFILES = build/all.gyp build/common.gypi build/v8-features.gypi \
+           preparser/preparser.gyp samples/samples.gyp src/d8.gyp \
+           test/cctest/cctest.gyp tools/gyp/v8.gyp
+
+# Generates all combinations of ARCHES and MODES, e.g. "ia32.release".
+BUILDS = $(foreach mode,$(MODES),$(addsuffix .$(mode),$(ARCHES)))
+CHECKS = $(addsuffix .check,$(BUILDS))
+# Generates corresponding test targets, e.g. "ia32.release.check".
+
+.PHONY: all release debug ia32 x64 arm $(BUILDS)
+
+# Target definitions. "all" is the default, you can specify any others on the
+# command line, e.g. "make ia32". Targets defined in $(BUILDS), e.g.
+# "ia32.debug", can also be specified.
+all: release debug
+
+release: $(addsuffix .release,$(ARCHES))
+
+debug: $(addsuffix .debug,$(ARCHES))
+
+ia32: $(addprefix ia32.,$(MODES))
+
+x64: $(addprefix x64.,$(MODES))
+
+arm: $(addprefix arm.,$(MODES))
+
+.SECONDEXPANSION:
+$(BUILDS): $(OUTDIR)/Makefile-$$(basename $$@)
+	@$(MAKE) -C "$(OUTDIR)" -f Makefile-$(basename $@) \
+	         CXX="$(CXX)" LINK="$(LINK)" \
+	         BUILDTYPE=$(shell echo $(subst .,,$(suffix $@)) | \
+	                     python -c "print raw_input().capitalize()") \
+	         builddir="$(shell pwd)/$(OUTDIR)/$@"
+
+# Test targets.
+check: all
+	@tools/test-wrapper-gypbuild.py $(TESTJOBS) --outdir=$(OUTDIR)
+
+$(addsuffix .check,$(MODES)): $$(basename $$@)
+	@tools/test-wrapper-gypbuild.py $(TESTJOBS) --outdir=$(OUTDIR) --mode=$(basename $@)
+
+$(addsuffix .check,$(ARCHES)): $$(basename $$@)
+	@tools/test-wrapper-gypbuild.py $(TESTJOBS) --outdir=$(OUTDIR) --arch=$(basename $@)
+
+$(CHECKS): $$(basename $$@)
+	@tools/test-wrapper-gypbuild.py $(TESTJOBS) --outdir=$(OUTDIR) --arch-and-mode=$(basename $@)
+
+# Clean targets. You can clean each architecture individually, or everything.
+$(addsuffix .clean,$(ARCHES)):
+	rm -f $(OUTDIR)/Makefile-$(basename $@)
+	rm -rf $(OUTDIR)/$(basename $@).release
+	rm -rf $(OUTDIR)/$(basename $@).debug
+
+clean: $(addsuffix .clean,$(ARCHES))
+
+# GYP file generation targets.
+$(OUTDIR)/Makefile-ia32: $(GYPFILES)
+	build/gyp/gyp --generator-output="$(OUTDIR)" build/all.gyp \
+	              -Ibuild/common.gypi --depth=. -Dtarget_arch=ia32 -S-ia32 \
+	              $(GYPFLAGS)
+
+$(OUTDIR)/Makefile-x64: $(GYPFILES)
+	build/gyp/gyp --generator-output="$(OUTDIR)" build/all.gyp \
+	              -Ibuild/common.gypi --depth=. -Dtarget_arch=x64 -S-x64 \
+	              $(GYPFLAGS)
+
+$(OUTDIR)/Makefile-arm: $(GYPFILES) build/armu.gypi
+	build/gyp/gyp --generator-output="$(OUTDIR)" build/all.gyp \
+	              -Ibuild/common.gypi --depth=. -Ibuild/armu.gypi -S-arm \
+	              $(GYPFLAGS)
diff --git a/SConstruct b/SConstruct
index 8e16a78..f9c33ca 100644
--- a/SConstruct
+++ b/SConstruct
@@ -153,13 +153,19 @@
         }
       },
       'armeabi:softfp' : {
-        'CPPDEFINES' : ['USE_EABI_HARDFLOAT=0', 'CAN_USE_VFP_INSTRUCTIONS'],
+        'CPPDEFINES' : ['USE_EABI_HARDFLOAT=0'],
+        'vfp3:on': {
+          'CPPDEFINES' : ['CAN_USE_VFP_INSTRUCTIONS']
+        },
         'simulator:none': {
           'CCFLAGS':     ['-mfloat-abi=softfp'],
         }
       },
       'armeabi:hard' : {
-        'CPPDEFINES' : ['USE_EABI_HARDFLOAT=1', 'CAN_USE_VFP_INSTRUCTIONS'],
+        'CPPDEFINES' : ['USE_EABI_HARDFLOAT=1'],
+        'vfp3:on': {
+          'CPPDEFINES' : ['CAN_USE_VFP_INSTRUCTIONS']
+        },
         'simulator:none': {
           'CCFLAGS':     ['-mfloat-abi=hard'],
         }
@@ -436,7 +442,7 @@
     },
     'arch:x64': {
       'CPPDEFINES':   ['V8_TARGET_ARCH_X64'],
-      'LINKFLAGS': ['/STACK:2091752']
+      'LINKFLAGS': ['/STACK:2097152']
     },
   }
 }
@@ -496,7 +502,10 @@
         }
       },
       'armeabi:hard' : {
-        'CPPDEFINES' : ['USE_EABI_HARDFLOAT=1', 'CAN_USE_VFP_INSTRUCTIONS'],
+        'CPPDEFINES' : ['USE_EABI_HARDFLOAT=1'],
+        'vfp3:on': {
+          'CPPDEFINES' : ['CAN_USE_VFP_INSTRUCTIONS']
+        },
         'simulator:none': {
           'CCFLAGS':     ['-mfloat-abi=hard'],
         }
@@ -601,7 +610,7 @@
     },
     'arch:x64': {
       'CPPDEFINES': ['V8_TARGET_ARCH_X64', 'WIN32'],
-      'LINKFLAGS': ['/MACHINE:X64', '/STACK:2091752']
+      'LINKFLAGS': ['/MACHINE:X64', '/STACK:2097152']
     },
     'mode:debug': {
       'CCFLAGS':    ['/Od'],
@@ -756,7 +765,7 @@
     },
     'arch:x64': {
       'CPPDEFINES': ['V8_TARGET_ARCH_X64', 'WIN32'],
-      'LINKFLAGS': ['/MACHINE:X64', '/STACK:2091752']
+      'LINKFLAGS': ['/MACHINE:X64', '/STACK:2097152']
     },
     'mode:debug': {
       'CCFLAGS':    ['/Od'],
@@ -822,6 +831,57 @@
   'msvc': {
     'all': {
       'LIBS': ['winmm', 'ws2_32']
+    },
+    'verbose:off': {
+      'CCFLAGS': ['/nologo'],
+      'LINKFLAGS': ['/NOLOGO']
+    },
+    'verbose:on': {
+      'LINKFLAGS': ['/VERBOSE']
+    },
+    '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:2097152']
+    },
+    'mode:debug': {
+      'CCFLAGS':    ['/Od'],
+      'LINKFLAGS':  ['/DEBUG'],
+      'CPPDEFINES': ['DEBUG'],
+      'msvcrt:static': {
+        'CCFLAGS':  ['/MTd']
+      },
+      'msvcrt:shared': {
+        'CCFLAGS':  ['/MDd']
+      }
     }
   }
 }
@@ -1039,6 +1099,12 @@
     'default': 'off',
     'help': 'compress startup data (snapshot) [Linux only]'
   },
+  'vfp3': {
+    'values': ['on', 'off'],
+    'default': 'on',
+    'help': 'use vfp3 instructions when building the snapshot [Arm only]'
+  },
+
 }
 
 ALL_OPTIONS = dict(PLATFORM_OPTIONS, **SIMPLE_OPTIONS)
@@ -1343,10 +1409,12 @@
     env['SONAME'] = soname
 
   # Build the object files by invoking SCons recursively.
+  d8_env = Environment(tools=tools)
+  d8_env.Replace(**context.flags['d8'])
   (object_files, shell_files, mksnapshot, preparser_files) = env.SConscript(
     join('src', 'SConscript'),
     build_dir=join('obj', target_id),
-    exports='context tools',
+    exports='context tools d8_env',
     duplicate=False
   )
 
@@ -1375,8 +1443,6 @@
   context.library_targets.append(library)
   context.library_targets.append(preparser_library)
 
-  d8_env = Environment(tools=tools)
-  d8_env.Replace(**context.flags['d8'])
   context.ApplyEnvOverrides(d8_env)
   if context.options['library'] == 'static':
     shell = d8_env.Program('d8' + suffix, object_files + shell_files)
diff --git a/build/all.gyp b/build/all.gyp
index 38287e3..9c0f05c 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -1,4 +1,4 @@
-# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -8,6 +8,7 @@
       'target_name': 'All',
       'type': 'none',
       'dependencies': [
+        '../preparser/preparser.gyp:*',
         '../samples/samples.gyp:*',
         '../src/d8.gyp:d8',
       ],
diff --git a/build/armu.gypi b/build/armu.gypi
index 3f874c0..d15b8ab 100644
--- a/build/armu.gypi
+++ b/build/armu.gypi
@@ -32,5 +32,5 @@
     'armv7': 1,
     'arm_neon': 0,
     'arm_fpu': 'vfpv3',
-  }
+  },
 }
diff --git a/build/common.gypi b/build/common.gypi
index 7020495..5a3da52 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -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:
@@ -30,6 +30,7 @@
     'library%': 'static_library',
     'component%': 'static_library',
     'visibility%': 'hidden',
+    'msvs_multi_core_compile%': '1',
     'variables': {
       'conditions': [
         [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
@@ -46,23 +47,41 @@
     'host_arch%': '<(host_arch)',
     'target_arch%': '<(host_arch)',
     'v8_target_arch%': '<(target_arch)',
+    'v8_enable_debugger_support%': 1,
+    'conditions': [
+      ['(target_arch=="arm" and host_arch!="arm") or \
+        (target_arch=="x64" and host_arch!="x64")', {
+        'want_separate_host_toolset': 1,
+      }, {
+        'want_separate_host_toolset': 0,
+      }],
+    ],
   },
   'target_defaults': {
     'default_configuration': 'Debug',
+    'conditions': [
+      ['v8_enable_debugger_support==1', {
+          'defines': ['ENABLE_DEBUGGER_SUPPORT',],
+        },
+      ],
+    ],
     'configurations': {
       'Debug': {
         'cflags': [ '-g', '-O0' ],
-        'defines': [ 'ENABLE_DISASSEMBLER', 'DEBUG' ],
+        'defines': [ 'ENABLE_DISASSEMBLER', 'DEBUG', 'V8_ENABLE_CHECKS',
+                     'OBJECT_PRINT' ],
       },
       'Release': {
-        'cflags': [ '-O3', '-fomit-frame-pointer', '-fdata-sections', '-ffunction-sections' ],
+        'cflags': [ '-O3', '-fomit-frame-pointer', '-fdata-sections',
+                    '-ffunction-sections' ],
       },
     },
   },
   'conditions': [
     [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
       'target_defaults': {
-        'cflags': [ '-Wall', '-pthread', '-fno-rtti', '-fno-exceptions' ],
+        'cflags': [ '-Wall', '-pthread', '-fno-rtti', '-fno-exceptions',
+                    '-pedantic' ],
         'ldflags': [ '-pthread', ],
         'conditions': [
           [ 'target_arch=="ia32"', {
diff --git a/build/v8-features.gypi b/build/v8-features.gypi
index 4037452..cb9b61c 100644
--- a/build/v8-features.gypi
+++ b/build/v8-features.gypi
@@ -89,6 +89,19 @@
                   'USE_EABI_HARDFLOAT=1',
                   'CAN_USE_VFP_INSTRUCTIONS',
                 ],
+                'cflags': [
+                  '-mfloat-abi=hard',
+                ],
+              }, {
+                'defines': [
+                  'USE_EABI_HARDFLOAT=0',
+                ],
+              }],
+              # The ARM assembler assumes the host is 32 bits,
+              # so force building 32-bit host tools.
+              [ 'host_arch=="x64"', {
+                'cflags': ['-m32'],
+                'ldflags': ['-m32'],
               }],
             ],
           }],
diff --git a/include/v8.h b/include/v8.h
index fa59712..d1bceca 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -3606,7 +3606,7 @@
   /**
    * Returns whether v8::Locker is being used by this V8 instance.
    */
-  static bool IsActive() { return active_; }
+  static bool IsActive();
 
  private:
   bool has_lock_;
diff --git a/preparser/preparser.gyp b/preparser/preparser.gyp
new file mode 100644
index 0000000..bcccb48
--- /dev/null
+++ b/preparser/preparser.gyp
@@ -0,0 +1,41 @@
+# 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.
+
+{
+  'targets': [
+    {
+      'target_name': 'preparser',
+      'type': 'executable',
+      'dependencies': [
+        '../tools/gyp/v8.gyp:preparser_lib',
+      ],
+      'sources': [
+        'preparser-process.cc',
+      ],
+    },
+  ],
+}
diff --git a/samples/samples.gyp b/samples/samples.gyp
index f383ee2..7023e0a 100644
--- a/samples/samples.gyp
+++ b/samples/samples.gyp
@@ -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:
@@ -26,23 +26,24 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 {
+  'target_defaults': {
+    'type': 'executable',
+    'dependencies': [
+      '../tools/gyp/v8.gyp:v8',
+    ],
+    'include_dirs': [
+      '../include',
+    ],
+  },
   'targets': [
     {
       'target_name': 'shell',
-      'type': 'executable',
-      'dependencies': [
-        '../tools/gyp/v8.gyp:v8',
-      ],
       'sources': [
         'shell.cc',
       ],
     },
     {
       'target_name': 'process',
-      'type': 'executable',
-      'dependencies': [
-        '../tools/gyp/v8.gyp:v8',
-      ],
       'sources': [
         'process.cc',
       ],
diff --git a/src/SConscript b/src/SConscript
index b45a567..453a7c6 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -32,6 +32,7 @@
 import js2c
 Import('context')
 Import('tools')
+Import('d8_env')
 
 
 SOURCES = {
@@ -65,6 +66,7 @@
     disassembler.cc
     diy-fp.cc
     dtoa.cc
+    elements.cc
     execution.cc
     factory.cc
     flags.cc
@@ -307,6 +309,7 @@
 
 EXPERIMENTAL_LIBRARY_FILES = '''
 proxy.js
+weakmap.js
 '''.split()
 
 
@@ -338,7 +341,7 @@
   else:
     d8_files = context.GetRelevantSources(D8_FULL_FILES)
     d8_objs = [d8_js_obj]
-  d8_objs.append(context.ConfigureObject(env, [d8_files]))
+  d8_objs.append(context.ConfigureObject(d8_env, [d8_files]))
 
   # Combine the JavaScript library files into a single C++ file and
   # compile it.
diff --git a/src/api.cc b/src/api.cc
index fa2c88c..7355cd6 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -84,7 +84,7 @@
     if (has_pending_exception) {                                               \
       if (handle_scope_implementer->CallDepthIsZero() &&                       \
           (isolate)->is_out_of_memory()) {                                     \
-        if (!handle_scope_implementer->ignore_out_of_memory())                 \
+        if (!(isolate)->ignore_out_of_memory())                                \
           i::V8::FatalProcessOutOfMemory(NULL);                                \
       }                                                                        \
       bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero();   \
@@ -4259,8 +4259,8 @@
 Local<Value> v8::External::Wrap(void* data) {
   i::Isolate* isolate = i::Isolate::Current();
   STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
-  LOG_API(isolate, "External::Wrap");
   EnsureInitializedForIsolate(isolate, "v8::External::Wrap()");
+  LOG_API(isolate, "External::Wrap");
   ENTER_V8(isolate);
 
   v8::Local<v8::Value> result = CanBeEncodedAsSmi(data)
@@ -4304,8 +4304,8 @@
 Local<External> v8::External::New(void* data) {
   STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
   i::Isolate* isolate = i::Isolate::Current();
-  LOG_API(isolate, "External::New");
   EnsureInitializedForIsolate(isolate, "v8::External::New()");
+  LOG_API(isolate, "External::New");
   ENTER_V8(isolate);
   return ExternalNewImpl(data);
 }
@@ -4797,8 +4797,7 @@
 
 
 void V8::IgnoreOutOfMemoryException() {
-  EnterIsolateIfNeeded()->handle_scope_implementer()->set_ignore_out_of_memory(
-      true);
+  EnterIsolateIfNeeded()->set_ignore_out_of_memory(true);
 }
 
 
diff --git a/src/api.h b/src/api.h
index 8d2e778..ce39d63 100644
--- a/src/api.h
+++ b/src/api.h
@@ -404,7 +404,6 @@
         entered_contexts_(0),
         saved_contexts_(0),
         spare_(NULL),
-        ignore_out_of_memory_(false),
         call_depth_(0) { }
 
   // Threading support for handle data.
@@ -437,10 +436,6 @@
   inline bool HasSavedContexts();
 
   inline List<internal::Object**>* blocks() { return &blocks_; }
-  inline bool ignore_out_of_memory() { return ignore_out_of_memory_; }
-  inline void set_ignore_out_of_memory(bool value) {
-    ignore_out_of_memory_ = value;
-  }
 
  private:
   void ResetAfterArchive() {
@@ -448,7 +443,6 @@
     entered_contexts_.Initialize(0);
     saved_contexts_.Initialize(0);
     spare_ = NULL;
-    ignore_out_of_memory_ = false;
     call_depth_ = 0;
   }
 
@@ -473,7 +467,6 @@
   // Used as a stack to keep track of saved contexts.
   List<Context*> saved_contexts_;
   Object** spare_;
-  bool ignore_out_of_memory_;
   int call_depth_;
   // This is only used for threading support.
   v8::ImplementationUtilities::HandleScopeData handle_scope_data_;
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index eaad9f2..161421e 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -1603,83 +1603,139 @@
 }
 
 
-// The stub returns zero for false, and a non-zero value for true.
+// The stub expects its argument in the tos_ register and returns its result in
+// it, too: zero for false, and a non-zero value for true.
 void ToBooleanStub::Generate(MacroAssembler* masm) {
   // This stub uses VFP3 instructions.
   CpuFeatures::Scope scope(VFP3);
 
-  Label false_result, true_result, not_string;
+  Label patch;
   const Register map = r9.is(tos_) ? r7 : r9;
 
-  // undefined -> false
-  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
-  __ cmp(tos_, ip);
-  __ b(eq, &false_result);
+  // undefined -> false.
+  CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false, &patch);
 
-  // Boolean -> its value
-  __ LoadRoot(ip, Heap::kFalseValueRootIndex);
-  __ cmp(tos_, ip);
-  __ b(eq, &false_result);
-  __ LoadRoot(ip, Heap::kTrueValueRootIndex);
-  __ cmp(tos_, ip);
-  // "tos_" is a register and contains a non-zero value.  Hence we implicitly
-  // return true if the equal condition is satisfied.
-  __ Ret(eq);
+  // Boolean -> its value.
+  CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false, &patch);
+  CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true, &patch);
 
-  // Smis: 0 -> false, all other -> true
-  __ tst(tos_, tos_);
-  __ b(eq, &false_result);
-  __ tst(tos_, Operand(kSmiTagMask));
-  // "tos_" is a register and contains a non-zero value.  Hence we implicitly
-  // return true if the not equal condition is satisfied.
-  __ Ret(eq);
+  // 'null' -> false.
+  CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false, &patch);
 
-  // 'null' -> false
-  __ LoadRoot(ip, Heap::kNullValueRootIndex);
-  __ cmp(tos_, ip);
-  __ b(eq, &false_result);
+  if (types_.Contains(SMI)) {
+    // Smis: 0 -> false, all other -> true
+    __ tst(tos_, Operand(kSmiTagMask));
+    // tos_ contains the correct return value already
+    __ Ret(eq);
+  } else if (types_.NeedsMap()) {
+    // If we need a map later and have a Smi -> patch.
+    __ JumpIfSmi(tos_, &patch);
+  }
 
-  // Get the map of the heap object.
-  __ ldr(map, FieldMemOperand(tos_, HeapObject::kMapOffset));
+  if (types_.NeedsMap()) {
+    __ ldr(map, FieldMemOperand(tos_, HeapObject::kMapOffset));
 
-  // Undetectable -> false.
-  __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset));
-  __ tst(ip, Operand(1 << Map::kIsUndetectable));
-  __ b(&false_result, ne);
+    // Everything with a map could be undetectable, so check this now.
+    __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset));
+    __ tst(ip, Operand(1 << Map::kIsUndetectable));
+    // Undetectable -> false.
+    __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, ne);
+    __ Ret(ne);
+  }
 
-  // JavaScript object -> true.
-  __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE);
-  // "tos_" is a register and contains a non-zero value. Hence we implicitly
-  // return true if the greater than condition is satisfied.
-  __ Ret(ge);
+  if (types_.Contains(SPEC_OBJECT)) {
+    // Spec object -> true.
+    __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE);
+    // tos_ contains the correct non-zero return value already.
+    __ Ret(ge);
+  } else if (types_.Contains(INTERNAL_OBJECT)) {
+    // We've seen a spec object for the first time -> patch.
+    __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE);
+    __ b(ge, &patch);
+  }
 
-  // String value -> false iff empty.
+  if (types_.Contains(STRING)) {
+    // String value -> false iff empty.
   __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE);
-  __ b(&not_string, ge);
-  __ ldr(tos_, FieldMemOperand(tos_, String::kLengthOffset));
-  // Return string length as boolean value, i.e. return false iff length is 0.
-  __ Ret();
+  __ ldr(tos_, FieldMemOperand(tos_, String::kLengthOffset), lt);
+  __ Ret(lt);  // the string length is OK as the return value
+  } else if (types_.Contains(INTERNAL_OBJECT)) {
+    // We've seen a string for the first time -> patch
+    __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE);
+    __ b(lt, &patch);
+  }
 
-  __ bind(&not_string);
-  // HeapNumber -> false iff +0, -0, or NaN.
-  __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
-  __ b(&true_result, ne);
-  __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset));
-  __ VFPCompareAndSetFlags(d1, 0.0);
-  // "tos_" is a register, and contains a non zero value by default.
-  // Hence we only need to overwrite "tos_" with zero to return false for
-  // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true.
-  __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, eq);  // for FP_ZERO
-  __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, vs);  // for FP_NAN
-  __ Ret();
+  if (types_.Contains(HEAP_NUMBER)) {
+    // Heap number -> false iff +0, -0, or NaN.
+    Label not_heap_number;
+    __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
+    __ b(ne, &not_heap_number);
+    __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset));
+    __ VFPCompareAndSetFlags(d1, 0.0);
+    // "tos_" is a register, and contains a non zero value by default.
+    // Hence we only need to overwrite "tos_" with zero to return false for
+    // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true.
+    __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, eq);  // for FP_ZERO
+    __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, vs);  // for FP_NAN
+    __ Ret();
+    __ bind(&not_heap_number);
+  } else if (types_.Contains(INTERNAL_OBJECT)) {
+    // We've seen a heap number for the first time -> patch
+    __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
+    __ b(eq, &patch);
+  }
 
-  // Return 1/0 for true/false in tos_.
-  __ bind(&true_result);
-  __ mov(tos_, Operand(1, RelocInfo::NONE));
-  __ Ret();
-  __ bind(&false_result);
-  __ mov(tos_, Operand(0, RelocInfo::NONE));
-  __ Ret();
+  if (types_.Contains(INTERNAL_OBJECT)) {
+    // Internal objects -> true.
+    __ mov(tos_, Operand(1, RelocInfo::NONE));
+    __ Ret();
+  }
+
+  if (!types_.IsAll()) {
+    __ bind(&patch);
+    GenerateTypeTransition(masm);
+  }
+}
+
+
+void ToBooleanStub::CheckOddball(MacroAssembler* masm,
+                                 Type type,
+                                 Heap::RootListIndex value,
+                                 bool result,
+                                 Label* patch) {
+  if (types_.Contains(type)) {
+    // If we see an expected oddball, return its ToBoolean value tos_.
+    __ LoadRoot(ip, value);
+    __ cmp(tos_, ip);
+    // The value of a root is never NULL, so we can avoid loading a non-null
+    // value into tos_ when we want to return 'true'.
+    if (!result) {
+      __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, eq);
+    }
+    __ Ret(eq);
+  } else if (types_.Contains(INTERNAL_OBJECT)) {
+    // If we see an unexpected oddball and handle internal objects, we must
+    // patch because the code for internal objects doesn't handle it explictly.
+    __ LoadRoot(ip, value);
+    __ cmp(tos_, ip);
+    __ b(eq, patch);
+  }
+}
+
+
+void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
+  if (!tos_.is(r3)) {
+    __ mov(r3, Operand(tos_));
+  }
+  __ mov(r2, Operand(Smi::FromInt(tos_.code())));
+  __ mov(r1, Operand(Smi::FromInt(types_.ToByte())));
+  __ Push(r3, r2, r1);
+  // Patch the caller to an appropriate specialized stub and return the
+  // operation result to the caller of the stub.
+  __ TailCallExternalReference(
+      ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
+      3,
+      1);
 }
 
 
diff --git a/src/arm/deoptimizer-arm.cc b/src/arm/deoptimizer-arm.cc
index cd70e6d..9d9c045 100644
--- a/src/arm/deoptimizer-arm.cc
+++ b/src/arm/deoptimizer-arm.cc
@@ -35,7 +35,7 @@
 namespace v8 {
 namespace internal {
 
-int Deoptimizer::table_entry_size_ = 16;
+const int Deoptimizer::table_entry_size_ = 16;
 
 
 int Deoptimizer::patch_size() {
@@ -65,8 +65,6 @@
 
   // For each return after a safepoint insert an absolute call to the
   // corresponding deoptimization entry.
-  ASSERT(patch_size() % Assembler::kInstrSize == 0);
-  int call_size_in_words = patch_size() / Assembler::kInstrSize;
   unsigned last_pc_offset = 0;
   SafepointTable table(function->code());
   for (unsigned i = 0; i < table.length(); i++) {
@@ -87,13 +85,18 @@
 #endif
     last_pc_offset = pc_offset;
     if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
-      last_pc_offset += gap_code_size;
-      CodePatcher patcher(code->instruction_start() + last_pc_offset,
-                          call_size_in_words);
       Address deoptimization_entry = Deoptimizer::GetDeoptimizationEntry(
           deoptimization_index, Deoptimizer::LAZY);
+      last_pc_offset += gap_code_size;
+      int call_size_in_bytes = MacroAssembler::CallSize(deoptimization_entry,
+                                                        RelocInfo::NONE);
+      int call_size_in_words = call_size_in_bytes / Assembler::kInstrSize;
+      ASSERT(call_size_in_bytes % Assembler::kInstrSize == 0);
+      ASSERT(call_size_in_bytes <= patch_size());
+      CodePatcher patcher(code->instruction_start() + last_pc_offset,
+                          call_size_in_words);
       patcher.masm()->Call(deoptimization_entry, RelocInfo::NONE);
-      last_pc_offset += patch_size();
+      last_pc_offset += call_size_in_bytes;
     }
   }
 
@@ -530,8 +533,6 @@
     output_frame->SetContinuation(
         reinterpret_cast<uint32_t>(continuation->entry()));
   }
-
-  if (output_count_ - 1 == frame_index) iterator->Done();
 }
 
 
diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc
index d4bd81c..603b3cf 100644
--- a/src/arm/disasm-arm.cc
+++ b/src/arm/disasm-arm.cc
@@ -200,7 +200,7 @@
 
 // These shift names are defined in a way to match the native disassembler
 // formatting. See for example the command "objdump -d <binary file>".
-static const char* shift_names[kNumberOfShifts] = {
+static const char* const shift_names[kNumberOfShifts] = {
   "lsl", "lsr", "asr", "ror"
 };
 
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index ea06064..1eb4aff 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1039,7 +1039,13 @@
         : instr->SecondSuccessor();
     return new LGoto(successor->block_id());
   }
-  return new LBranch(UseRegisterAtStart(v));
+  LInstruction* branch = new LBranch(UseRegister(v));
+  // When we handle all cases, we never deopt, so we don't need to assign the
+  // environment then. Note that we map the "empty" case to the "all" case in
+  // the code generator.
+  ToBooleanStub::Types types = instr->expected_input_types();
+  bool all_cases_handled = types.IsAll() || types.IsEmpty();
+  return all_cases_handled ? branch : AssignEnvironment(branch);
 }
 
 
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index ee2bb84..3f3f31a 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -1564,52 +1564,138 @@
   } else {
     ASSERT(r.IsTagged());
     Register reg = ToRegister(instr->InputAt(0));
-    if (instr->hydrogen()->value()->type().IsBoolean()) {
-      __ LoadRoot(ip, Heap::kTrueValueRootIndex);
-      __ cmp(reg, ip);
+    HType type = instr->hydrogen()->value()->type();
+    if (type.IsBoolean()) {
+      __ CompareRoot(reg, Heap::kTrueValueRootIndex);
       EmitBranch(true_block, false_block, eq);
+    } else if (type.IsSmi()) {
+      __ cmp(reg, Operand(0));
+      EmitBranch(true_block, false_block, ne);
     } else {
       Label* true_label = chunk_->GetAssemblyLabel(true_block);
       Label* false_label = chunk_->GetAssemblyLabel(false_block);
 
-      __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
-      __ cmp(reg, ip);
-      __ b(eq, false_label);
-      __ LoadRoot(ip, Heap::kTrueValueRootIndex);
-      __ cmp(reg, ip);
-      __ b(eq, true_label);
-      __ LoadRoot(ip, Heap::kFalseValueRootIndex);
-      __ cmp(reg, ip);
-      __ b(eq, false_label);
-      __ cmp(reg, Operand(0));
-      __ b(eq, false_label);
-      __ JumpIfSmi(reg, true_label);
+      ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
+      // Avoid deopts in the case where we've never executed this path before.
+      if (expected.IsEmpty()) expected = ToBooleanStub::all_types();
 
-      // Test double values. Zero and NaN are false.
-      Label call_stub;
-      DoubleRegister dbl_scratch = double_scratch0();
-      Register scratch = scratch0();
-      __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
-      __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
-      __ cmp(scratch, Operand(ip));
-      __ b(ne, &call_stub);
-      __ sub(ip, reg, Operand(kHeapObjectTag));
-      __ vldr(dbl_scratch, ip, HeapNumber::kValueOffset);
-      __ VFPCompareAndLoadFlags(dbl_scratch, 0.0, scratch);
-      __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit));
-      __ b(ne, false_label);
-      __ b(true_label);
+      if (expected.Contains(ToBooleanStub::UNDEFINED)) {
+        // undefined -> false.
+        __ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
+        __ b(eq, false_label);
+      } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) {
+        // We've seen undefined for the first time -> deopt.
+        __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+        DeoptimizeIf(eq, instr->environment());
+      }
 
-      // The conversion stub doesn't cause garbage collections so it's
-      // safe to not record a safepoint after the call.
-      __ bind(&call_stub);
-      ToBooleanStub stub(reg);
-      RegList saved_regs = kJSCallerSaved | kCalleeSaved;
-      __ stm(db_w, sp, saved_regs);
-      __ CallStub(&stub);
-      __ cmp(reg, Operand(0));
-      __ ldm(ia_w, sp, saved_regs);
-      EmitBranch(true_block, false_block, ne);
+      if (expected.Contains(ToBooleanStub::BOOLEAN)) {
+        // Boolean -> its value.
+        __ CompareRoot(reg, Heap::kTrueValueRootIndex);
+        __ b(eq, true_label);
+        __ CompareRoot(reg, Heap::kFalseValueRootIndex);
+        __ b(eq, false_label);
+      } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) {
+        // We've seen a boolean for the first time -> deopt.
+        __ CompareRoot(reg, Heap::kTrueValueRootIndex);
+        DeoptimizeIf(eq, instr->environment());
+        __ CompareRoot(reg, Heap::kFalseValueRootIndex);
+        DeoptimizeIf(eq, instr->environment());
+      }
+
+#if 0
+      if (expected.Contains(ToBooleanStub::BOOLEAN)) {
+        // false -> false.
+        __ CompareRoot(reg, Heap::kFalseValueRootIndex);
+        __ b(eq, false_label);
+      } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) {
+        // We've seen a boolean for the first time -> deopt.
+        __ CompareRoot(reg, Heap::kFalseValueRootIndex);
+        DeoptimizeIf(eq, instr->environment());
+      }
+#endif
+
+      if (expected.Contains(ToBooleanStub::NULL_TYPE)) {
+        // 'null' -> false.
+        __ CompareRoot(reg, Heap::kNullValueRootIndex);
+        __ b(eq, false_label);
+      } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) {
+        // We've seen null for the first time -> deopt.
+        __ CompareRoot(reg, Heap::kNullValueRootIndex);
+        DeoptimizeIf(eq, instr->environment());
+      }
+
+      if (expected.Contains(ToBooleanStub::SMI)) {
+        // Smis: 0 -> false, all other -> true.
+        __ cmp(reg, Operand(0));
+        __ b(eq, false_label);
+        __ JumpIfSmi(reg, true_label);
+      } else if (expected.NeedsMap()) {
+        // If we need a map later and have a Smi -> deopt.
+        __ tst(reg, Operand(kSmiTagMask));
+        DeoptimizeIf(eq, instr->environment());
+      }
+
+      const Register map = scratch0();
+      if (expected.NeedsMap()) {
+        __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset));
+        // Everything with a map could be undetectable, so check this now.
+        __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset));
+        __ tst(ip, Operand(1 << Map::kIsUndetectable));
+        __ b(ne, false_label);
+      }
+
+      if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) {
+        // spec object -> true.
+        __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE);
+        __ b(ge, true_label);
+      } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) {
+        // We've seen a spec object for the first time -> deopt.
+        __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE);
+        DeoptimizeIf(ge, instr->environment());
+      }
+
+      if (expected.Contains(ToBooleanStub::STRING)) {
+        // String value -> false iff empty.
+        Label not_string;
+        __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE);
+        __ b(ge, &not_string);
+        __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset));
+        __ cmp(ip, Operand(0));
+        __ b(ne, true_label);
+        __ b(false_label);
+        __ bind(&not_string);
+      } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) {
+        // We've seen a string for the first time -> deopt
+        __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE);
+        DeoptimizeIf(lt, instr->environment());
+      }
+
+      if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
+        // heap number -> false iff +0, -0, or NaN.
+        DoubleRegister dbl_scratch = double_scratch0();
+        Label not_heap_number;
+        __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
+        __ b(ne, &not_heap_number);
+        __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
+        __ VFPCompareAndSetFlags(dbl_scratch, 0.0);
+        __ b(vs, false_label);  // NaN -> false.
+        __ b(eq, false_label);  // +0, -0 -> false.
+        __ b(true_label);
+        __ bind(&not_heap_number);
+      } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) {
+        // We've seen a heap number for the first time -> deopt.
+        __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
+        DeoptimizeIf(eq, instr->environment());
+      }
+
+      if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) {
+        // internal objects -> true
+        __ b(true_label);
+      } else {
+        // We've seen something for the first time -> deopt.
+        DeoptimizeIf(al, instr->environment());
+      }
     }
   }
 }
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 07281a7..9c653ad 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -92,14 +92,16 @@
   void Jump(Register target, Condition cond = al);
   void Jump(Address 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);
+  static int CallSize(Register target, Condition cond = al);
   void Call(Register target, Condition cond = al);
-  int CallSize(Address target, RelocInfo::Mode rmode, Condition cond = al);
+  static int CallSize(Address target,
+                      RelocInfo::Mode rmode,
+                      Condition cond = al);
   void Call(Address target, RelocInfo::Mode rmode, Condition cond = al);
-  int CallSize(Handle<Code> code,
-               RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
-               unsigned ast_id = kNoASTId,
-               Condition cond = al);
+  static int CallSize(Handle<Code> code,
+                      RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
+                      unsigned ast_id = kNoASTId,
+                      Condition cond = al);
   void Call(Handle<Code> code,
             RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
             unsigned ast_id = kNoASTId,
diff --git a/src/assembler.cc b/src/assembler.cc
index fbd8089..ad5f350 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -74,7 +74,7 @@
 const double DoubleConstant::canonical_non_hole_nan = OS::nan_value();
 const double DoubleConstant::the_hole_nan = BitCast<double>(kHoleNanInt64);
 const double DoubleConstant::negative_infinity = -V8_INFINITY;
-const char* RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
+const char* const RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
 
 // -----------------------------------------------------------------------------
 // Implementation of AssemblerBase
diff --git a/src/assembler.h b/src/assembler.h
index 2d14f06..d58034d 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -171,7 +171,7 @@
   // where we are not sure to have enough space for patching in during
   // lazy deoptimization. This is the case if we have indirect calls for which
   // we do not normally record relocation info.
-  static const char* kFillerCommentString;
+  static const char* const kFillerCommentString;
 
   // The minimum size of a comment is equal to three bytes for the extra tagged
   // pc + the tag for the data, and kPointerSize for the actual pointer to the
diff --git a/src/ast.h b/src/ast.h
index 23df48b..b4705f6 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1711,6 +1711,12 @@
 
 class FunctionLiteral: public Expression {
  public:
+  enum Type {
+    ANONYMOUS_EXPRESSION,
+    NAMED_EXPRESSION,
+    DECLARATION
+  };
+
   FunctionLiteral(Isolate* isolate,
                   Handle<String> name,
                   Scope* scope,
@@ -1722,7 +1728,7 @@
                   int num_parameters,
                   int start_position,
                   int end_position,
-                  bool is_expression,
+                  Type type,
                   bool has_duplicate_parameters)
       : Expression(isolate),
         name_(name),
@@ -1738,7 +1744,8 @@
         end_position_(end_position),
         function_token_position_(RelocInfo::kNoPosition),
         inferred_name_(HEAP->empty_string()),
-        is_expression_(is_expression),
+        is_expression_(type != DECLARATION),
+        is_anonymous_(type == ANONYMOUS_EXPRESSION),
         pretenure_(false),
         has_duplicate_parameters_(has_duplicate_parameters) {
   }
@@ -1753,6 +1760,7 @@
   int start_position() const { return start_position_; }
   int end_position() const { return end_position_; }
   bool is_expression() const { return is_expression_; }
+  bool is_anonymous() const { return is_anonymous_; }
   bool strict_mode() const;
 
   int materialized_literal_count() { return materialized_literal_count_; }
@@ -1797,6 +1805,7 @@
   int function_token_position_;
   Handle<String> inferred_name_;
   bool is_expression_;
+  bool is_anonymous_;
   bool pretenure_;
   bool has_duplicate_parameters_;
 };
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 8cca561..a5cb555 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -199,6 +199,7 @@
   // New context initialization.  Used for creating a context from scratch.
   void InitializeGlobal(Handle<GlobalObject> inner_global,
                         Handle<JSFunction> empty_function);
+  void InitializeExperimentalGlobal();
   // Installs the contents of the native .js files on the global objects.
   // Used for creating a context from scratch.
   void InstallNativeFunctions();
@@ -1190,6 +1191,21 @@
 }
 
 
+void Genesis::InitializeExperimentalGlobal() {
+  Isolate* isolate = this->isolate();
+  Handle<JSObject> global = Handle<JSObject>(global_context()->global());
+
+  // TODO(mstarzinger): Move this into Genesis::InitializeGlobal once we no
+  // longer need to live behind a flag, so WeakMap gets added to the snapshot.
+  if (FLAG_harmony_weakmaps) {  // -- W e a k M a p
+    Handle<JSFunction> weakmap_fun =
+        InstallFunction(global, "WeakMap", JS_WEAK_MAP_TYPE, JSWeakMap::kSize,
+                        isolate->initial_object_prototype(),
+                        Builtins::kIllegal, true);
+  }
+}
+
+
 bool Genesis::CompileBuiltin(Isolate* isolate, int index) {
   Vector<const char> name = Natives::GetScriptName(index);
   Handle<String> source_code =
@@ -1680,6 +1696,11 @@
                "native proxy.js") == 0) {
       if (!CompileExperimentalBuiltin(isolate(), i)) return false;
     }
+    if (FLAG_harmony_weakmaps &&
+        strcmp(ExperimentalNatives::GetScriptName(i).start(),
+               "native weakmap.js") == 0) {
+      if (!CompileExperimentalBuiltin(isolate(), i)) return false;
+    }
   }
 
   InstallExperimentalNativeFunctions();
@@ -2169,7 +2190,8 @@
     isolate->counters()->contexts_created_from_scratch()->Increment();
   }
 
-  // Install experimental natives.
+  // Initialize experimental globals and install experimental natives.
+  InitializeExperimentalGlobal();
   if (!InstallExperimentalNatives()) return;
 
   result_ = global_context_;
diff --git a/src/codegen.cc b/src/codegen.cc
index fb723a3..cdc9ba1 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -169,7 +169,6 @@
 #endif  // ENABLE_DISASSEMBLER
 }
 
-static Vector<const char> kRegexp = CStrVector("regexp");
 
 bool CodeGenerator::ShouldGenerateLog(Expression* type) {
   ASSERT(type != NULL);
@@ -179,7 +178,7 @@
   }
   Handle<String> name = Handle<String>::cast(type->AsLiteral()->handle());
   if (FLAG_log_regexp) {
-    if (name->IsEqualTo(kRegexp))
+    if (name->IsEqualTo(CStrVector("regexp")))
       return true;
   }
   return false;
diff --git a/src/compiler.cc b/src/compiler.cc
index c265b95..a87eecc 100755
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -736,6 +736,7 @@
   function_info->set_start_position(lit->start_position());
   function_info->set_end_position(lit->end_position());
   function_info->set_is_expression(lit->is_expression());
+  function_info->set_is_anonymous(lit->is_anonymous());
   function_info->set_is_toplevel(is_toplevel);
   function_info->set_inferred_name(*lit->inferred_name());
   function_info->SetThisPropertyAssignmentsInfo(
diff --git a/src/d8.cc b/src/d8.cc
index f4ace87..3b9c183 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -26,8 +26,8 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
-#ifdef V8_SHARED
-#define USING_V8_SHARED
+#ifdef USING_V8_SHARED  // Defined when linking against shared lib on Windows.
+#define V8_SHARED
 #endif
 
 #ifdef COMPRESS_STARTUP_DATA_BZ2
@@ -37,15 +37,16 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
 
-#ifdef USING_V8_SHARED
+#ifdef V8_SHARED
 #include <assert.h>
 #include "../include/v8-testing.h"
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
 #include "d8.h"
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
 #include "api.h"
 #include "checks.h"
 #include "d8-debug.h"
@@ -53,20 +54,20 @@
 #include "natives.h"
 #include "platform.h"
 #include "v8.h"
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
 #if !defined(_WIN32) && !defined(_WIN64)
 #include <unistd.h>  // NOLINT
 #endif
 
-#ifdef USING_V8_SHARED
+#ifndef ASSERT
 #define ASSERT(condition) assert(condition)
-#endif  // USING_V8_SHARED
+#endif
 
 namespace v8 {
 
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
 LineEditor *LineEditor::first_ = NULL;
 const char* Shell::kHistoryFileName = ".d8_history";
 
@@ -116,20 +117,20 @@
 CounterCollection* Shell::counters_ = &local_counters_;
 i::Mutex* Shell::context_mutex_(i::OS::CreateMutex());
 Persistent<Context> Shell::utility_context_;
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
 Persistent<Context> Shell::evaluation_context_;
 ShellOptions Shell::options;
 const char* Shell::kPrompt = "d8> ";
 
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
 bool CounterMap::Match(void* key1, void* key2) {
   const char* name1 = reinterpret_cast<const char*>(key1);
   const char* name2 = reinterpret_cast<const char*>(key2);
   return strcmp(name1, name2) == 0;
 }
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
 
 // Converts a V8 value to a C string.
@@ -143,11 +144,11 @@
                           Handle<Value> name,
                           bool print_result,
                           bool report_exceptions) {
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   bool FLAG_debugger = i::FLAG_debugger;
 #else
   bool FLAG_debugger = false;
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
   HandleScope handle_scope;
   TryCatch try_catch;
   options.script_executed = true;
@@ -276,9 +277,9 @@
         String::New("Array constructor needs one parameter."));
   }
   static const int kMaxLength = 0x3fffffff;
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   ASSERT(kMaxLength == i::ExternalArray::kMaxLength);
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
   size_t length = 0;
   if (args[0]->IsUint32()) {
     length = args[0]->Uint32Value();
@@ -378,9 +379,9 @@
 
 Handle<Value> Shell::Quit(const Arguments& args) {
   int exit_code = args[0]->Int32Value();
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   OnExit();
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
   exit(exit_code);
   return Undefined();
 }
@@ -429,7 +430,7 @@
 }
 
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
 Handle<Array> Shell::GetCompletions(Handle<String> text, Handle<String> full) {
   HandleScope handle_scope;
   Context::Scope context_scope(utility_context_);
@@ -464,10 +465,10 @@
   return val;
 }
 #endif  // ENABLE_DEBUGGER_SUPPORT
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
 int32_t* Counter::Bind(const char* name, bool is_histogram) {
   int i;
   for (i = 0; i < kMaxNameSize - 1 && name[i]; i++)
@@ -615,7 +616,7 @@
   }
 #endif  // ENABLE_DEBUGGER_SUPPORT
 }
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
 
 #ifdef COMPRESS_STARTUP_DATA_BZ2
@@ -682,11 +683,11 @@
   global_template->Set(String::New("lol_is_enabled"), Boolean::New(false));
 #endif
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   Handle<ObjectTemplate> os_templ = ObjectTemplate::New();
   AddOSMethods(os_templ);
   global_template->Set(String::New("os"), os_templ);
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
   return global_template;
 }
@@ -702,7 +703,7 @@
   }
 #endif
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   Shell::counter_map_ = new CounterMap();
   // Set up counters
   if (i::StrLength(i::FLAG_map_counters) != 0)
@@ -712,10 +713,10 @@
     V8::SetCreateHistogramFunction(CreateHistogram);
     V8::SetAddHistogramSampleFunction(AddHistogramSample);
   }
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
   if (options.test_shell) return;
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   Locker lock;
   HandleScope scope;
   Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
@@ -727,21 +728,21 @@
     v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true);
   }
 #endif  // ENABLE_DEBUGGER_SUPPORT
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 }
 
 
 Persistent<Context> Shell::CreateEvaluationContext() {
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   // This needs to be a critical section since this is not thread-safe
   i::ScopedLock lock(context_mutex_);
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
   // Initialize the global objects
   Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
   Persistent<Context> context = Context::New(NULL, global_template);
   Context::Scope scope(context);
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   i::JSArguments js_args = i::FLAG_js_arguments;
   i::Handle<i::FixedArray> arguments_array =
       FACTORY->NewFixedArray(js_args.argc());
@@ -754,12 +755,12 @@
       FACTORY->NewJSArrayWithElements(arguments_array);
   context->Global()->Set(String::New("arguments"),
                          Utils::ToLocal(arguments_jsarray));
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
   return context;
 }
 
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
 void Shell::OnExit() {
   if (i::FLAG_dump_counters) {
     printf("+----------------------------------------+-------------+\n");
@@ -779,18 +780,34 @@
   if (counters_file_ != NULL)
     delete counters_file_;
 }
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
+
+
+static FILE* FOpen(const char* path, const char* mode) {
+#if (defined(_WIN32) || defined(_WIN64))
+  FILE* result;
+  if (fopen_s(&result, path, mode) == 0) {
+    return result;
+  } else {
+    return NULL;
+  }
+#else
+  FILE* file = fopen(path, mode);
+  if (file == NULL) return NULL;
+  struct stat file_stat;
+  if (fstat(fileno(file), &file_stat) != 0) return NULL;
+  bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0);
+  if (is_regular_file) return file;
+  fclose(file);
+  return NULL;
+#endif
+}
 
 
 static char* ReadChars(const char* name, int* size_out) {
   // Release the V8 lock while reading files.
   v8::Unlocker unlocker(Isolate::GetCurrent());
-#ifndef USING_V8_SHARED
-  FILE* file = i::OS::FOpen(name, "rb");
-#else
-  // TODO(yangguo@chromium.org): reading from a directory hangs!
-  FILE* file = fopen(name, "rb");
-#endif  // USING_V8_SHARED
+  FILE* file = FOpen(name, "rb");
   if (file == NULL) return NULL;
 
   fseek(file, 0, SEEK_END);
@@ -809,7 +826,7 @@
 }
 
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
 static char* ReadToken(char* data, char token) {
   char* next = i::OS::StrChr(data, token);
   if (next != NULL) {
@@ -829,7 +846,7 @@
 static char* ReadWord(char* data) {
   return ReadToken(data, ' ');
 }
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
 
 // Reads a file into a v8 string.
@@ -848,7 +865,7 @@
   Context::Scope context_scope(evaluation_context_);
   HandleScope handle_scope;
   Handle<String> name = String::New("(d8)");
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   LineEditor* editor = LineEditor::Get();
   printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name());
   if (i::FLAG_debugger) {
@@ -871,12 +888,12 @@
     if (fgets(buffer, kBufferSize, stdin) == NULL) break;
     ExecuteString(String::New(buffer), name, true, true);
   }
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
   printf("\n");
 }
 
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
 class ShellThread : public i::Thread {
  public:
   ShellThread(int no, i::Vector<const char> files)
@@ -929,7 +946,7 @@
     ptr = next_line;
   }
 }
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
 
 void SourceGroup::ExitShell(int exit_code) {
@@ -976,32 +993,16 @@
 
 
 Handle<String> SourceGroup::ReadFile(const char* name) {
-#ifndef USING_V8_SHARED
-  FILE* file = i::OS::FOpen(name, "rb");
-#else
-  // TODO(yangguo@chromium.org): reading from a directory hangs!
-  FILE* file = fopen(name, "rb");
-#endif  // USING_V8_SHARED
-  if (file == NULL) return Handle<String>();
-
-  fseek(file, 0, SEEK_END);
-  int size = ftell(file);
-  rewind(file);
-
-  char* chars = new char[size + 1];
-  chars[size] = '\0';
-  for (int i = 0; i < size;) {
-    int read = static_cast<int>(fread(&chars[i], 1, size - i, file));
-    i += read;
-  }
-  fclose(file);
+  int size;
+  const char* chars = ReadChars(name, &size);
+  if (chars == NULL) return Handle<String>();
   Handle<String> result = String::New(chars, size);
   delete[] chars;
   return result;
 }
 
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
 i::Thread::Options SourceGroup::GetThreadOptions() {
   i::Thread::Options options;
   options.name = "IsolateThread";
@@ -1053,7 +1054,7 @@
     done_semaphore_->Wait();
   }
 }
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
 
 bool Shell::SetOptions(int argc, char* argv[]) {
@@ -1075,23 +1076,23 @@
       options.test_shell = true;
       argv[i] = NULL;
     } else if (strcmp(argv[i], "--preemption") == 0) {
-#ifdef USING_V8_SHARED
+#ifdef V8_SHARED
       printf("D8 with shared library does not support multi-threading\n");
       return false;
 #else
       options.use_preemption = true;
       argv[i] = NULL;
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
     } else if (strcmp(argv[i], "--no-preemption") == 0) {
-#ifdef USING_V8_SHARED
+#ifdef V8_SHARED
       printf("D8 with shared library does not support multi-threading\n");
       return false;
 #else
       options.use_preemption = false;
       argv[i] = NULL;
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
     } else if (strcmp(argv[i], "--preemption-interval") == 0) {
-#ifdef USING_V8_SHARED
+#ifdef V8_SHARED
       printf("D8 with shared library does not support multi-threading\n");
       return false;
 #else
@@ -1110,19 +1111,19 @@
         printf("Missing value for --preemption-interval\n");
         return false;
       }
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
     } else if (strcmp(argv[i], "-f") == 0) {
       // Ignore any -f flags for compatibility with other stand-alone
       // JavaScript engines.
       continue;
     } else if (strcmp(argv[i], "--isolate") == 0) {
-#ifdef USING_V8_SHARED
+#ifdef V8_SHARED
       printf("D8 with shared library does not support multi-threading\n");
       return false;
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
       options.num_isolates++;
     }
-#ifdef USING_V8_SHARED
+#ifdef V8_SHARED
     else if (strcmp(argv[i], "--dump-counters") == 0) {
       printf("D8 with shared library does not include counters\n");
       return false;
@@ -1133,10 +1134,10 @@
       printf("Javascript debugger not included\n");
       return false;
     }
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
   }
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   // Run parallel threads if we are not using --isolate
   for (int i = 1; i < argc; i++) {
     if (argv[i] == NULL) continue;
@@ -1157,9 +1158,10 @@
       }
       argv[i] = NULL;
       options.parallel_files->Add(i::Vector<const char>(files, size));
+      delete[] files;
     }
   }
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
   v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
 
@@ -1184,7 +1186,7 @@
 
 
 int Shell::RunMain(int argc, char* argv[]) {
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   i::List<i::Thread*> threads(1);
   if (options.parallel_files != NULL)
     for (int i = 0; i < options.parallel_files->length(); i++) {
@@ -1197,7 +1199,7 @@
   for (int i = 1; i < options.num_isolates; ++i) {
     options.isolate_sources[i].StartExecuteInThread();
   }
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
   {  // NOLINT
     Locker lock;
     HandleScope scope;
@@ -1213,17 +1215,17 @@
       context.Dispose();
     }
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
     // Start preemption if threads have been created and preemption is enabled.
     if (options.parallel_files != NULL
         && threads.length() > 0
         && options.use_preemption) {
       Locker::StartPreemption(options.preemption_interval);
     }
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
   }
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   for (int i = 1; i < options.num_isolates; ++i) {
     options.isolate_sources[i].WaitForThread();
   }
@@ -1236,7 +1238,7 @@
     }
 
   OnExit();
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
   return 0;
 }
 
@@ -1264,14 +1266,14 @@
   }
 
 
-#if !defined(USING_V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
+#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
   // Run remote debugger if requested, but never on --test
   if (i::FLAG_remote_debugger && !options.test_shell) {
     InstallUtilityScript();
     RunRemoteDebugger(i::FLAG_debugger_port);
     return 0;
   }
-#endif  // !USING_V8_SHARED && ENABLE_DEBUGGER_SUPPORT
+#endif  // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
 
   // Run interactive shell if explicitly requested or if no script has been
   // executed, but never on --test
@@ -1279,9 +1281,9 @@
   if (( options.interactive_shell
       || !options.script_executed )
       && !options.test_shell ) {
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
     InstallUtilityScript();
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
     RunShell();
   }
 
diff --git a/src/d8.gyp b/src/d8.gyp
index d2b4254..2d9af78 100644
--- a/src/d8.gyp
+++ b/src/d8.gyp
@@ -47,9 +47,17 @@
       ],
       'conditions': [
         [ 'component!="shared_library"', {
-          'dependencies': [ 'd8_js2c#host', ], 
           'sources': [ 'd8-debug.cc', '<(SHARED_INTERMEDIATE_DIR)/d8-js.cc', ],
           'conditions': [
+            [ 'want_separate_host_toolset==1', {
+              'dependencies': [
+                'd8_js2c#host',
+              ],
+            }, {
+              'dependencies': [
+                'd8_js2c',
+              ],
+            }],
             [ 'console=="readline"', {
               'libraries': [ '-lreadline', ],
               'sources': [ 'd8-readline.cc' ],
@@ -68,13 +76,19 @@
     {
       'target_name': 'd8_js2c',
       'type': 'none',
-      'toolsets': ['host'],
       'variables': {
         'js_files': [
           'd8.js',
           'macros.py',
         ],
       },
+      'conditions': [
+        [ 'want_separate_host_toolset==1', {
+          'toolsets': ['host'],
+        }, {
+          'toolsets': ['target'],
+        }]
+      ],
       'actions': [
         {
           'action_name': 'd8_js2c',
@@ -90,6 +104,7 @@
             '../tools/js2c.py',
             '<@(_outputs)',
             'D8',
+            'off',  # compress startup data
             '<@(js_files)'
           ],
         },
diff --git a/src/d8.h b/src/d8.h
index 840ca1e..40cc83b 100644
--- a/src/d8.h
+++ b/src/d8.h
@@ -29,22 +29,22 @@
 #define V8_D8_H_
 
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
 #include "v8.h"
 #include "allocation.h"
 #include "hashmap.h"
 #else
 #include "../include/v8.h"
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
 namespace v8 {
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
 namespace i = v8::internal;
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
 // A single counter in a counter collection.
 class Counter {
  public:
@@ -117,17 +117,17 @@
   static bool Match(void* key1, void* key2);
   i::HashMap hash_map_;
 };
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
 
 class SourceGroup {
  public:
   SourceGroup() :
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
       next_semaphore_(v8::internal::OS::CreateSemaphore(0)),
       done_semaphore_(v8::internal::OS::CreateSemaphore(0)),
       thread_(NULL),
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
       argv_(NULL),
       begin_offset_(0),
       end_offset_(0) { }
@@ -141,7 +141,7 @@
 
   void Execute();
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   void StartExecuteInThread();
   void WaitForThread();
 
@@ -165,7 +165,7 @@
   i::Semaphore* next_semaphore_;
   i::Semaphore* done_semaphore_;
   i::Thread* thread_;
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
   void ExitShell(int exit_code);
   Handle<String> ReadFile(const char* name);
@@ -179,11 +179,11 @@
 class ShellOptions {
  public:
   ShellOptions() :
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
      use_preemption(true),
      preemption_interval(10),
      parallel_files(NULL),
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
      script_executed(false),
      last_run(true),
      stress_opt(false),
@@ -193,11 +193,11 @@
      num_isolates(1),
      isolate_sources(NULL) { }
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   bool use_preemption;
   int preemption_interval;
   i::List< i::Vector<const char> >* parallel_files;
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
   bool script_executed;
   bool last_run;
   bool stress_opt;
@@ -208,11 +208,11 @@
   SourceGroup* isolate_sources;
 };
 
-#ifdef USING_V8_SHARED
+#ifdef V8_SHARED
 class Shell {
 #else
 class Shell : public i::AllStatic {
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
  public:
   static bool ExecuteString(Handle<String> source,
                             Handle<Value> name,
@@ -225,7 +225,7 @@
   static int RunMain(int argc, char* argv[]);
   static int Main(int argc, char* argv[]);
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   static Handle<Array> GetCompletions(Handle<String> text,
                                       Handle<String> full);
   static void OnExit();
@@ -236,7 +236,7 @@
                                size_t buckets);
   static void AddHistogramSample(void* histogram, int sample);
   static void MapCounters(const char* name);
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   static Handle<Object> DebugMessageDetails(Handle<String> message);
@@ -300,15 +300,15 @@
   static Handle<Value> RemoveDirectory(const Arguments& args);
 
   static void AddOSMethods(Handle<ObjectTemplate> os_template);
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   static const char* kHistoryFileName;
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
   static const char* kPrompt;
   static ShellOptions options;
 
  private:
   static Persistent<Context> evaluation_context_;
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
   static Persistent<Context> utility_context_;
   static CounterMap* counter_map_;
   // We statically allocate a set of local counters to be used if we
@@ -320,7 +320,7 @@
 
   static Counter* GetCounter(const char* name, bool is_histogram);
   static void InstallUtilityScript();
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
   static void Initialize();
   static void RunShell();
   static bool SetOptions(int argc, char* argv[]);
@@ -332,7 +332,7 @@
 };
 
 
-#ifndef USING_V8_SHARED
+#ifndef V8_SHARED
 class LineEditor {
  public:
   enum Type { DUMB = 0, READLINE = 1 };
@@ -352,7 +352,7 @@
   LineEditor* next_;
   static LineEditor* first_;
 };
-#endif  // USING_V8_SHARED
+#endif  // V8_SHARED
 
 
 }  // namespace v8
diff --git a/src/debug.cc b/src/debug.cc
index 5024bce..2d58ce1 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -1965,7 +1965,7 @@
 
 
 Debugger::Debugger(Isolate* isolate)
-    : debugger_access_(OS::CreateMutex()),
+    : debugger_access_(isolate->debugger_access()),
       event_listener_(Handle<Object>()),
       event_listener_data_(Handle<Object>()),
       compiling_natives_(false),
@@ -1987,8 +1987,6 @@
 
 
 Debugger::~Debugger() {
-  delete debugger_access_;
-  debugger_access_ = 0;
   delete dispatch_handler_access_;
   dispatch_handler_access_ = 0;
   delete command_received_;
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index 3a7b33a..5feb73d 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -1183,11 +1183,11 @@
 
 
 int32_t TranslationIterator::Next() {
-  ASSERT(HasNext());
   // Run through the bytes until we reach one with a least significant
   // bit of zero (marks the end).
   uint32_t bits = 0;
   for (int i = 0; true; i += 7) {
+    ASSERT(HasNext());
     uint8_t next = buffer_->get(index_++);
     bits |= (next >> 1) << i;
     if ((next & 1) == 0) break;
@@ -1438,6 +1438,7 @@
   UNREACHABLE();
 }
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 
 DeoptimizedFrameInfo::DeoptimizedFrameInfo(
     Deoptimizer* deoptimizer, int frame_index) {
@@ -1467,5 +1468,6 @@
   v->VisitPointers(expression_stack_, expression_stack_ + expression_count_);
 }
 
+#endif  // ENABLE_DEBUGGER_SUPPORT
 
 } }  // namespace v8::internal
diff --git a/src/deoptimizer.h b/src/deoptimizer.h
index 9265905..033d924 100644
--- a/src/deoptimizer.h
+++ b/src/deoptimizer.h
@@ -317,7 +317,7 @@
 
   List<HeapNumberMaterializationDescriptor> deferred_heap_numbers_;
 
-  static int table_entry_size_;
+  static const int table_entry_size_;
 
   friend class FrameDescription;
   friend class DeoptimizingCodeListNode;
@@ -497,9 +497,7 @@
 
   int32_t Next();
 
-  bool HasNext() const { return index_ >= 0; }
-
-  void Done() { index_ = -1; }
+  bool HasNext() const { return index_ < buffer_->length(); }
 
   void Skip(int n) {
     for (int i = 0; i < n; i++) Next();
diff --git a/src/elements.cc b/src/elements.cc
new file mode 100644
index 0000000..9cfccee
--- /dev/null
+++ b/src/elements.cc
@@ -0,0 +1,536 @@
+// 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 "objects.h"
+#include "elements.h"
+
+namespace v8 {
+namespace internal {
+
+
+ElementsAccessor** ElementsAccessor::elements_accessors_;
+
+
+bool HasKey(FixedArray* array, Object* key) {
+  int len0 = array->length();
+  for (int i = 0; i < len0; i++) {
+    Object* element = array->get(i);
+    if (element->IsSmi() && element == key) return true;
+    if (element->IsString() &&
+        key->IsString() && String::cast(element)->Equals(String::cast(key))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+
+// Base class for element handler implementations. Contains the
+// the common logic for objects with different ElementsKinds.
+// Subclasses must specialize method for which the element
+// implementation differs from the base class implementation.
+//
+// This class is intended to be used in the following way:
+//
+//   class SomeElementsAccessor :
+//       public ElementsAccessorBase<SomeElementsAccessor,
+//                                   BackingStoreClass> {
+//     ...
+//   }
+//
+// This is an example of the Curiously Recurring Template Pattern (see
+// http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).  We use
+// CRTP to guarantee aggressive compile time optimizations (i.e.  inlining and
+// specialization of SomeElementsAccessor methods).
+template <typename ElementsAccessorSubclass, typename BackingStoreClass>
+class ElementsAccessorBase : public ElementsAccessor {
+ public:
+  ElementsAccessorBase() { }
+  virtual MaybeObject* GetWithReceiver(JSObject* obj,
+                                       Object* receiver,
+                                       uint32_t index) {
+    if (index < ElementsAccessorSubclass::GetLength(obj)) {
+      BackingStoreClass* backing_store =
+          ElementsAccessorSubclass::GetBackingStore(obj);
+      return backing_store->get(index);
+    }
+    return obj->GetHeap()->the_hole_value();
+  }
+
+  virtual MaybeObject* Delete(JSObject* obj,
+                              uint32_t index,
+                              JSReceiver::DeleteMode mode) = 0;
+
+  virtual MaybeObject* AddJSArrayKeysToFixedArray(JSArray* other,
+                                                  FixedArray* keys) {
+    int len0 = keys->length();
+#ifdef DEBUG
+    if (FLAG_enable_slow_asserts) {
+      for (int i = 0; i < len0; i++) {
+        ASSERT(keys->get(i)->IsString() || keys->get(i)->IsNumber());
+      }
+    }
+#endif
+    int len1 = ElementsAccessorSubclass::GetCapacity(other);
+
+    // Optimize if 'other' is empty.
+    // We cannot optimize if 'this' is empty, as other may have holes
+    // or non keys.
+    if (len1 == 0) return keys;
+
+    // Compute how many elements are not in other.
+    int extra = 0;
+    for (int y = 0; y < len1; y++) {
+      Object* value;
+      MaybeObject* maybe_value =
+          ElementsAccessorSubclass::GetElementAtCapacityIndex(other, y);
+      if (!maybe_value->ToObject(&value)) return maybe_value;
+      if (!value->IsTheHole() && !HasKey(keys, value)) extra++;
+    }
+
+    if (extra == 0) return keys;
+
+    // Allocate the result
+    FixedArray* result;
+    MaybeObject* maybe_obj =
+        other->GetHeap()->AllocateFixedArray(len0 + extra);
+    if (!maybe_obj->To<FixedArray>(&result)) return maybe_obj;
+
+    // Fill in the content
+    {
+      AssertNoAllocation no_gc;
+      WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
+      for (int i = 0; i < len0; i++) {
+        Object* e = keys->get(i);
+        ASSERT(e->IsString() || e->IsNumber());
+        result->set(i, e, mode);
+      }
+    }
+    // Fill in the extra keys.
+    int index = 0;
+    for (int y = 0; y < len1; y++) {
+      MaybeObject* maybe_value =
+          ElementsAccessorSubclass::GetElementAtCapacityIndex(other, y);
+      Object* value;
+      if (!maybe_value->ToObject(&value)) return maybe_value;
+      if (!value->IsTheHole() && !HasKey(keys, value)) {
+        ASSERT(value->IsString() || value->IsNumber());
+        result->set(len0 + index, value);
+        index++;
+      }
+    }
+    ASSERT(extra == index);
+    return result;
+  }
+
+  static uint32_t GetCapacity(JSObject* obj) {
+    return ElementsAccessorSubclass::GetBackingStore(obj)->length();
+  }
+
+  static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) {
+    BackingStoreClass* backing_store =
+        ElementsAccessorSubclass::GetBackingStore(obj);
+    return backing_store->get(index);
+  }
+
+ protected:
+  static BackingStoreClass* GetBackingStore(JSObject* obj) {
+    return BackingStoreClass::cast(obj->elements());
+  }
+
+  static uint32_t GetLength(JSObject* obj) {
+    return ElementsAccessorSubclass::GetBackingStore(obj)->length();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase);
+};
+
+
+class FastElementsAccessor
+    : public ElementsAccessorBase<FastElementsAccessor, FixedArray> {
+ public:
+  static MaybeObject* DeleteCommon(JSObject* obj,
+                                   uint32_t index) {
+    ASSERT(obj->HasFastElements() || obj->HasFastArgumentsElements());
+    Heap* heap = obj->GetHeap();
+    FixedArray* backing_store = FixedArray::cast(obj->elements());
+    if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
+      backing_store = FixedArray::cast(backing_store->get(1));
+    } else {
+      Object* writable;
+      MaybeObject* maybe = obj->EnsureWritableFastElements();
+      if (!maybe->ToObject(&writable)) return maybe;
+      backing_store = FixedArray::cast(writable);
+    }
+    uint32_t length = static_cast<uint32_t>(
+        obj->IsJSArray()
+        ? Smi::cast(JSArray::cast(obj)->length())->value()
+        : backing_store->length());
+    if (index < length) {
+      backing_store->set_the_hole(index);
+      // If an old space backing store is larger than a certain size and
+      // has too few used values, normalize it.
+      // To avoid doing the check on every delete we require at least
+      // one adjacent hole to the value being deleted.
+      Object* hole = heap->the_hole_value();
+      const int kMinLengthForSparsenessCheck = 64;
+      if (backing_store->length() >= kMinLengthForSparsenessCheck &&
+          !heap->InNewSpace(backing_store) &&
+          ((index > 0 && backing_store->get(index - 1) == hole) ||
+           (index + 1 < length && backing_store->get(index + 1) == hole))) {
+        int num_used = 0;
+        for (int i = 0; i < backing_store->length(); ++i) {
+          if (backing_store->get(i) != hole) ++num_used;
+          // Bail out early if more than 1/4 is used.
+          if (4 * num_used > backing_store->length()) break;
+        }
+        if (4 * num_used <= backing_store->length()) {
+          MaybeObject* result = obj->NormalizeElements();
+          if (result->IsFailure()) return result;
+        }
+      }
+    }
+    return heap->true_value();
+  }
+
+  virtual MaybeObject* Delete(JSObject* obj,
+                              uint32_t index,
+                              JSReceiver::DeleteMode mode) {
+    return DeleteCommon(obj, index);
+  }
+};
+
+
+class FastDoubleElementsAccessor
+    : public ElementsAccessorBase<FastDoubleElementsAccessor,
+                                  FixedDoubleArray> {
+  virtual MaybeObject* Delete(JSObject* obj,
+                              uint32_t index,
+                              JSReceiver::DeleteMode mode) {
+    int length = obj->IsJSArray()
+        ? Smi::cast(JSArray::cast(obj)->length())->value()
+        : FixedDoubleArray::cast(obj->elements())->length();
+    if (index < static_cast<uint32_t>(length)) {
+      FixedDoubleArray::cast(obj->elements())->set_the_hole(index);
+    }
+    return obj->GetHeap()->true_value();
+  }
+};
+
+
+// Super class for all external element arrays.
+template<typename ExternalElementsAccessorSubclass,
+         typename ExternalArray>
+class ExternalElementsAccessor
+    : public ElementsAccessorBase<ExternalElementsAccessorSubclass,
+                                  ExternalArray> {
+ public:
+  virtual MaybeObject* GetWithReceiver(JSObject* obj,
+                                       Object* receiver,
+                                       uint32_t index) {
+    if (index < ExternalElementsAccessorSubclass::GetLength(obj)) {
+      ExternalArray* backing_store =
+          ExternalElementsAccessorSubclass::GetBackingStore(obj);
+      return backing_store->get(index);
+    } else {
+      return obj->GetHeap()->undefined_value();
+    }
+  }
+
+  virtual MaybeObject* Delete(JSObject* obj,
+                              uint32_t index,
+                              JSReceiver::DeleteMode mode) {
+    // External arrays always ignore deletes.
+    return obj->GetHeap()->true_value();
+  }
+};
+
+
+class ExternalByteElementsAccessor
+    : public ExternalElementsAccessor<ExternalByteElementsAccessor,
+                                      ExternalByteArray> {
+};
+
+
+class ExternalUnsignedByteElementsAccessor
+    : public ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor,
+                                      ExternalUnsignedByteArray> {
+};
+
+
+class ExternalShortElementsAccessor
+    : public ExternalElementsAccessor<ExternalShortElementsAccessor,
+                                      ExternalShortArray> {
+};
+
+
+class ExternalUnsignedShortElementsAccessor
+    : public ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor,
+                                      ExternalUnsignedShortArray> {
+};
+
+
+class ExternalIntElementsAccessor
+    : public ExternalElementsAccessor<ExternalIntElementsAccessor,
+                                      ExternalIntArray> {
+};
+
+
+class ExternalUnsignedIntElementsAccessor
+    : public ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor,
+                                      ExternalUnsignedIntArray> {
+};
+
+
+class ExternalFloatElementsAccessor
+    : public ExternalElementsAccessor<ExternalFloatElementsAccessor,
+                                      ExternalFloatArray> {
+};
+
+
+class ExternalDoubleElementsAccessor
+    : public ExternalElementsAccessor<ExternalDoubleElementsAccessor,
+                                      ExternalDoubleArray> {
+};
+
+
+class PixelElementsAccessor
+    : public ExternalElementsAccessor<PixelElementsAccessor,
+                                      ExternalPixelArray> {
+};
+
+
+class DictionaryElementsAccessor
+    : public ElementsAccessorBase<DictionaryElementsAccessor,
+                                  NumberDictionary> {
+ public:
+  static MaybeObject* GetNumberDictionaryElement(
+      JSObject* obj,
+      Object* receiver,
+      NumberDictionary* backing_store,
+      uint32_t index) {
+    int entry = backing_store->FindEntry(index);
+    if (entry != NumberDictionary::kNotFound) {
+      Object* element = backing_store->ValueAt(entry);
+      PropertyDetails details = backing_store->DetailsAt(entry);
+      if (details.type() == CALLBACKS) {
+        return obj->GetElementWithCallback(receiver,
+                                           element,
+                                           index,
+                                           obj);
+      } else {
+        return element;
+      }
+    }
+    return obj->GetHeap()->the_hole_value();
+  }
+
+
+  static MaybeObject* DeleteCommon(JSObject* obj,
+                                   uint32_t index,
+                                   JSReceiver::DeleteMode mode) {
+    Isolate* isolate = obj->GetIsolate();
+    Heap* heap = isolate->heap();
+    FixedArray* backing_store = FixedArray::cast(obj->elements());
+    bool is_arguments =
+        (obj->GetElementsKind() == JSObject::NON_STRICT_ARGUMENTS_ELEMENTS);
+    if (is_arguments) {
+      backing_store = FixedArray::cast(backing_store->get(1));
+    }
+    NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
+    int entry = dictionary->FindEntry(index);
+    if (entry != NumberDictionary::kNotFound) {
+      Object* result = dictionary->DeleteProperty(entry, mode);
+      if (result == heap->true_value()) {
+        MaybeObject* maybe_elements = dictionary->Shrink(index);
+        FixedArray* new_elements = NULL;
+        if (!maybe_elements->To(&new_elements)) {
+          return maybe_elements;
+        }
+        if (is_arguments) {
+          FixedArray::cast(obj->elements())->set(1, new_elements);
+        } else {
+          obj->set_elements(new_elements);
+        }
+      }
+      if (mode == JSObject::STRICT_DELETION &&
+          result == heap->false_value()) {
+        // In strict mode, attempting to delete a non-configurable property
+        // throws an exception.
+        HandleScope scope(isolate);
+        Handle<Object> holder(obj);
+        Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
+        Handle<Object> args[2] = { name, holder };
+        Handle<Object> error =
+            isolate->factory()->NewTypeError("strict_delete_property",
+                                             HandleVector(args, 2));
+        return isolate->Throw(*error);
+      }
+    }
+    return heap->true_value();
+  }
+
+  virtual MaybeObject* Delete(JSObject* obj,
+                              uint32_t index,
+                              JSReceiver::DeleteMode mode) {
+    return DeleteCommon(obj, index, mode);
+  }
+
+  virtual MaybeObject* GetWithReceiver(JSObject* obj,
+                                       Object* receiver,
+                                       uint32_t index) {
+    return GetNumberDictionaryElement(obj,
+                                      receiver,
+                                      obj->element_dictionary(),
+                                      index);
+  }
+
+  static uint32_t GetCapacity(JSObject* obj) {
+    return obj->element_dictionary()->Capacity();
+  }
+
+  static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) {
+    NumberDictionary* dict = obj->element_dictionary();
+    if (dict->IsKey(dict->KeyAt(index))) {
+      return dict->ValueAt(index);
+    } else {
+      return obj->GetHeap()->the_hole_value();
+    }
+  }
+};
+
+
+class NonStrictArgumentsElementsAccessor
+    : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor,
+                                  FixedArray> {
+ public:
+  virtual MaybeObject* GetWithReceiver(JSObject* obj,
+                                       Object* receiver,
+                                       uint32_t index) {
+    FixedArray* parameter_map = GetBackingStore(obj);
+    uint32_t length = parameter_map->length();
+    Object* probe =
+        (index < length - 2) ? parameter_map->get(index + 2) : NULL;
+    if (probe != NULL && !probe->IsTheHole()) {
+      Context* context = Context::cast(parameter_map->get(0));
+      int context_index = Smi::cast(probe)->value();
+      ASSERT(!context->get(context_index)->IsTheHole());
+      return context->get(context_index);
+    } else {
+      // Object is not mapped, defer to the arguments.
+      FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
+      if (arguments->IsDictionary()) {
+        return DictionaryElementsAccessor::GetNumberDictionaryElement(
+            obj,
+            receiver,
+            NumberDictionary::cast(arguments),
+            index);
+      } else if (index < static_cast<uint32_t>(arguments->length())) {
+        return arguments->get(index);
+      }
+    }
+    return obj->GetHeap()->the_hole_value();
+  }
+
+  virtual MaybeObject* Delete(JSObject* obj,
+                              uint32_t index,
+                              JSReceiver::DeleteMode mode) {
+    FixedArray* parameter_map = FixedArray::cast(obj->elements());
+    uint32_t length = parameter_map->length();
+    Object* probe =
+        index < (length - 2) ? parameter_map->get(index + 2) : NULL;
+    if (probe != NULL && !probe->IsTheHole()) {
+      // TODO(kmillikin): We could check if this was the last aliased
+      // parameter, and revert to normal elements in that case.  That
+      // would enable GC of the context.
+      parameter_map->set_the_hole(index + 2);
+    } else {
+      FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
+      if (arguments->IsDictionary()) {
+        return DictionaryElementsAccessor::DeleteCommon(obj, index, mode);
+      } else {
+        return FastElementsAccessor::DeleteCommon(obj, index);
+      }
+    }
+    return obj->GetHeap()->true_value();
+  }
+
+  static uint32_t GetCapacity(JSObject* obj) {
+    // TODO(danno): Return max of parameter map length or backing store
+    // capacity.
+    return 0;
+  }
+
+  static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) {
+    // TODO(danno): Return either value from parameter map of backing
+    // store value at index.
+    return obj->GetHeap()->the_hole_value();
+  }
+};
+
+
+void ElementsAccessor::InitializeOncePerProcess() {
+  static struct ConcreteElementsAccessors {
+    FastElementsAccessor fast_elements_handler;
+    FastDoubleElementsAccessor fast_double_elements_handler;
+    DictionaryElementsAccessor dictionary_elements_handler;
+    NonStrictArgumentsElementsAccessor non_strict_arguments_elements_handler;
+    ExternalByteElementsAccessor byte_elements_handler;
+    ExternalUnsignedByteElementsAccessor unsigned_byte_elements_handler;
+    ExternalShortElementsAccessor short_elements_handler;
+    ExternalUnsignedShortElementsAccessor unsigned_short_elements_handler;
+    ExternalIntElementsAccessor int_elements_handler;
+    ExternalUnsignedIntElementsAccessor unsigned_int_elements_handler;
+    ExternalFloatElementsAccessor float_elements_handler;
+    ExternalDoubleElementsAccessor double_elements_handler;
+    PixelElementsAccessor pixel_elements_handler;
+  } element_accessors;
+
+  static ElementsAccessor* accessor_array[] = {
+    &element_accessors.fast_elements_handler,
+    &element_accessors.fast_double_elements_handler,
+    &element_accessors.dictionary_elements_handler,
+    &element_accessors.non_strict_arguments_elements_handler,
+    &element_accessors.byte_elements_handler,
+    &element_accessors.unsigned_byte_elements_handler,
+    &element_accessors.short_elements_handler,
+    &element_accessors.unsigned_short_elements_handler,
+    &element_accessors.int_elements_handler,
+    &element_accessors.unsigned_int_elements_handler,
+    &element_accessors.float_elements_handler,
+    &element_accessors.double_elements_handler,
+    &element_accessors.pixel_elements_handler
+  };
+
+  elements_accessors_ = accessor_array;
+}
+
+
+} }  // namespace v8::internal
diff --git a/src/elements.h b/src/elements.h
new file mode 100644
index 0000000..f64244e
--- /dev/null
+++ b/src/elements.h
@@ -0,0 +1,69 @@
+// 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_ELEMENTS_H_
+#define V8_ELEMENTS_H_
+
+#include "objects.h"
+
+namespace v8 {
+namespace internal {
+
+// Abstract base class for handles that can operate on objects with differing
+// ElementsKinds.
+class ElementsAccessor {
+ public:
+  ElementsAccessor() { }
+  virtual ~ElementsAccessor() { }
+  virtual MaybeObject* GetWithReceiver(JSObject* obj,
+                                       Object* receiver,
+                                       uint32_t index) = 0;
+
+  virtual MaybeObject* Delete(JSObject* obj,
+                              uint32_t index,
+                              JSReceiver::DeleteMode mode) = 0;
+
+  virtual MaybeObject* AddJSArrayKeysToFixedArray(JSArray* other,
+                                                  FixedArray* keys) = 0;
+
+  // Returns a shared ElementsAccessor for the specified ElementsKind.
+  static ElementsAccessor* ForKind(JSObject::ElementsKind elements_kind) {
+    ASSERT(elements_kind < JSObject::kElementsKindCount);
+    return elements_accessors_[elements_kind];
+  }
+
+  static void InitializeOncePerProcess();
+
+ private:
+  static ElementsAccessor** elements_accessors_;
+
+  DISALLOW_COPY_AND_ASSIGN(ElementsAccessor);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_ELEMENTS_H_
diff --git a/src/execution.cc b/src/execution.cc
index 6ab73e7..bdbdca8 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -132,7 +132,7 @@
   if (*has_pending_exception) {
     isolate->ReportPendingMessages();
     if (isolate->pending_exception() == Failure::OutOfMemoryException()) {
-      if (!isolate->handle_scope_implementer()->ignore_out_of_memory()) {
+      if (!isolate->ignore_out_of_memory()) {
         V8::FatalProcessOutOfMemory("JS", true);
       }
     }
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 6900a9e..2ea9651 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -98,6 +98,7 @@
 
 // Flags for experimental language features.
 DEFINE_bool(harmony_proxies, false, "enable harmony proxies")
+DEFINE_bool(harmony_weakmaps, false, "enable harmony weak maps")
 
 // Flags for experimental implementation features.
 DEFINE_bool(unbox_double_arrays, true, "automatically unbox arrays of doubles")
diff --git a/src/heap.cc b/src/heap.cc
index efdb549..dbf3b95 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -438,7 +438,9 @@
 #if defined(DEBUG)
   ReportStatisticsAfterGC();
 #endif  // DEBUG
+#ifdef ENABLE_DEBUGGER_SUPPORT
   isolate_->debug()->AfterGarbageCollection();
+#endif  // ENABLE_DEBUGGER_SUPPORT
 }
 
 
@@ -1292,6 +1294,10 @@
                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
                         template VisitSpecialized<SharedFunctionInfo::kSize>);
 
+    table_.Register(kVisitJSWeakMap,
+                    &ObjectEvacuationStrategy<POINTER_OBJECT>::
+                    Visit);
+
     table_.Register(kVisitJSRegExp,
                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
                     Visit);
@@ -2393,40 +2399,41 @@
 
 
 MaybeObject* Heap::AllocateSharedFunctionInfo(Object* name) {
-  Object* result;
-  { MaybeObject* maybe_result =
-        Allocate(shared_function_info_map(), OLD_POINTER_SPACE);
-    if (!maybe_result->ToObject(&result)) return maybe_result;
-  }
+  SharedFunctionInfo* share;
+  MaybeObject* maybe = Allocate(shared_function_info_map(), OLD_POINTER_SPACE);
+  if (!maybe->To<SharedFunctionInfo>(&share)) return maybe;
 
-  SharedFunctionInfo* share = SharedFunctionInfo::cast(result);
+  // Set pointer fields.
   share->set_name(name);
   Code* illegal = isolate_->builtins()->builtin(Builtins::kIllegal);
   share->set_code(illegal);
   share->set_scope_info(SerializedScopeInfo::Empty());
-  Code* construct_stub = isolate_->builtins()->builtin(
-      Builtins::kJSConstructStubGeneric);
+  Code* construct_stub =
+      isolate_->builtins()->builtin(Builtins::kJSConstructStubGeneric);
   share->set_construct_stub(construct_stub);
-  share->set_expected_nof_properties(0);
-  share->set_length(0);
-  share->set_formal_parameter_count(0);
   share->set_instance_class_name(Object_symbol());
   share->set_function_data(undefined_value());
   share->set_script(undefined_value());
-  share->set_start_position_and_type(0);
   share->set_debug_info(undefined_value());
   share->set_inferred_name(empty_string());
-  share->set_compiler_hints(0);
-  share->set_deopt_counter(Smi::FromInt(FLAG_deopt_every_n_times));
   share->set_initial_map(undefined_value());
-  share->set_this_property_assignments_count(0);
   share->set_this_property_assignments(undefined_value());
-  share->set_opt_count(0);
+  share->set_deopt_counter(Smi::FromInt(FLAG_deopt_every_n_times));
+
+  // Set integer fields (smi or int, depending on the architecture).
+  share->set_length(0);
+  share->set_formal_parameter_count(0);
+  share->set_expected_nof_properties(0);
   share->set_num_literals(0);
+  share->set_start_position_and_type(0);
   share->set_end_position(0);
   share->set_function_token_position(0);
-  share->set_native(false);
-  return result;
+  // All compiler hints default to false or 0.
+  share->set_compiler_hints(0);
+  share->set_this_property_assignments_count(0);
+  share->set_opt_count(0);
+
+  return share;
 }
 
 
diff --git a/src/heap.h b/src/heap.h
index a7a24b0..4f4ef14 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -1646,6 +1646,7 @@
   friend class Page;
   friend class Isolate;
   friend class MarkCompactCollector;
+  friend class StaticMarkingVisitor;
   friend class MapCompact;
 
   DISALLOW_COPY_AND_ASSIGN(Heap);
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 5bea55a..2be2a03 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -862,10 +862,19 @@
 
 
 Range* HValue::InferRange() {
-  // Untagged integer32 cannot be -0, all other representations can.
-  Range* result = new Range();
-  result->set_can_be_minus_zero(!representation().IsInteger32());
-  return result;
+  if (representation().IsTagged()) {
+    // Tagged values are always in int32 range when converted to integer,
+    // but they can contain -0.
+    Range* result = new Range();
+    result->set_can_be_minus_zero(true);
+    return result;
+  } else if (representation().IsNone()) {
+    return NULL;
+  } else {
+    // Untagged integer32 cannot be -0 and we don't compute ranges for
+    // untagged doubles.
+    return new Range();
+  }
 }
 
 
diff --git a/src/ia32/deoptimizer-ia32.cc b/src/ia32/deoptimizer-ia32.cc
index 4ff1bfc..e23f3e9 100644
--- a/src/ia32/deoptimizer-ia32.cc
+++ b/src/ia32/deoptimizer-ia32.cc
@@ -37,7 +37,7 @@
 namespace v8 {
 namespace internal {
 
-int Deoptimizer::table_entry_size_ = 10;
+const int Deoptimizer::table_entry_size_ = 10;
 
 
 int Deoptimizer::patch_size() {
@@ -601,8 +601,6 @@
     output_frame->SetContinuation(
         reinterpret_cast<uint32_t>(continuation->entry()));
   }
-
-  if (output_count_ - 1 == frame_index) iterator->Done();
 }
 
 
diff --git a/src/ia32/disasm-ia32.cc b/src/ia32/disasm-ia32.cc
index 7a59a4f..900668f 100644
--- a/src/ia32/disasm-ia32.cc
+++ b/src/ia32/disasm-ia32.cc
@@ -54,7 +54,7 @@
 };
 
 
-static ByteMnemonic two_operands_instr[] = {
+static const ByteMnemonic two_operands_instr[] = {
   {0x03, "add", REG_OPER_OP_ORDER},
   {0x09, "or", OPER_REG_OP_ORDER},
   {0x0B, "or", REG_OPER_OP_ORDER},
@@ -79,7 +79,7 @@
 };
 
 
-static ByteMnemonic zero_operands_instr[] = {
+static const ByteMnemonic zero_operands_instr[] = {
   {0xC3, "ret", UNSET_OP_ORDER},
   {0xC9, "leave", UNSET_OP_ORDER},
   {0x90, "nop", UNSET_OP_ORDER},
@@ -98,14 +98,14 @@
 };
 
 
-static ByteMnemonic call_jump_instr[] = {
+static const ByteMnemonic call_jump_instr[] = {
   {0xE8, "call", UNSET_OP_ORDER},
   {0xE9, "jmp", UNSET_OP_ORDER},
   {-1, "", UNSET_OP_ORDER}
 };
 
 
-static ByteMnemonic short_immediate_instr[] = {
+static const ByteMnemonic short_immediate_instr[] = {
   {0x05, "add", UNSET_OP_ORDER},
   {0x0D, "or", UNSET_OP_ORDER},
   {0x15, "adc", UNSET_OP_ORDER},
@@ -117,7 +117,7 @@
 };
 
 
-static const char* jump_conditional_mnem[] = {
+static const char* const jump_conditional_mnem[] = {
   /*0*/ "jo", "jno", "jc", "jnc",
   /*4*/ "jz", "jnz", "jna", "ja",
   /*8*/ "js", "jns", "jpe", "jpo",
@@ -125,7 +125,7 @@
 };
 
 
-static const char* set_conditional_mnem[] = {
+static const char* const set_conditional_mnem[] = {
   /*0*/ "seto", "setno", "setc", "setnc",
   /*4*/ "setz", "setnz", "setna", "seta",
   /*8*/ "sets", "setns", "setpe", "setpo",
@@ -133,7 +133,7 @@
 };
 
 
-static const char* conditional_move_mnem[] = {
+static const char* const conditional_move_mnem[] = {
   /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc",
   /*4*/ "cmovz", "cmovnz", "cmovna", "cmova",
   /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo",
@@ -169,7 +169,7 @@
   InstructionDesc instructions_[256];
   void Clear();
   void Init();
-  void CopyTable(ByteMnemonic bm[], InstructionType type);
+  void CopyTable(const ByteMnemonic bm[], InstructionType type);
   void SetTableRange(InstructionType type,
                      byte start,
                      byte end,
@@ -208,7 +208,8 @@
 }
 
 
-void InstructionTable::CopyTable(ByteMnemonic bm[], InstructionType type) {
+void InstructionTable::CopyTable(const ByteMnemonic bm[],
+                                 InstructionType type) {
   for (int i = 0; bm[i].b >= 0; i++) {
     InstructionDesc* id = &instructions_[bm[i].b];
     id->mnem = bm[i].mnem;
diff --git a/src/isolate.cc b/src/isolate.cc
index 8a30e79..9ca6117 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -76,6 +76,10 @@
 
 ThreadLocalTop::ThreadLocalTop() {
   InitializeInternal();
+  // This flag may be set using v8::V8::IgnoreOutOfMemoryException()
+  // before an isolate is initialized. The initialize methods below do
+  // not touch it to preserve its value.
+  ignore_out_of_memory_ = false;
 }
 
 
@@ -382,7 +386,6 @@
   if (Thread::GetThreadLocal(isolate_key_) == NULL) {
     Thread::SetThreadLocal(isolate_key_, default_isolate_);
   }
-  CHECK(default_isolate_->PreInit());
 }
 
 
@@ -654,6 +657,7 @@
     incomplete_message_ = &accumulator;
     PrintStack(&accumulator);
     accumulator.OutputToStdOut();
+    InitializeLoggingAndCounters();
     accumulator.Log();
     incomplete_message_ = NULL;
     stack_trace_nesting_level_ = 0;
@@ -1375,11 +1379,15 @@
       bootstrapper_(NULL),
       runtime_profiler_(NULL),
       compilation_cache_(NULL),
-      counters_(new Counters()),
+      counters_(NULL),
       code_range_(NULL),
+      // Must be initialized early to allow v8::SetResourceConstraints calls.
       break_access_(OS::CreateMutex()),
-      logger_(new Logger()),
-      stats_table_(new StatsTable()),
+      debugger_initialized_(false),
+      // Must be initialized early to allow v8::Debug calls.
+      debugger_access_(OS::CreateMutex()),
+      logger_(NULL),
+      stats_table_(NULL),
       stub_cache_(NULL),
       deoptimizer_data_(NULL),
       capture_stack_trace_for_uncaught_exceptions_(false),
@@ -1510,7 +1518,7 @@
     logger_->TearDown();
 
     // The default isolate is re-initializable due to legacy API.
-    state_ = PREINITIALIZED;
+    state_ = UNINITIALIZED;
   }
 }
 
@@ -1592,58 +1600,6 @@
 }
 
 
-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(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)
-#undef C
-
-  string_tracker_ = new StringTracker();
-  string_tracker_->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();
-  unicode_cache_ = new UnicodeCache();
-  pc_to_code_cache_ = new PcToCodeCache(this);
-  write_input_buffer_ = new StringInputBuffer();
-  global_handles_ = new GlobalHandles(this);
-  bootstrapper_ = new Bootstrapper();
-  handle_scope_implementer_ = new HandleScopeImplementer(this);
-  stub_cache_ = new StubCache(this);
-  ast_sentinels_ = new AstSentinels();
-  regexp_stack_ = new RegExpStack();
-  regexp_stack_->isolate_ = this;
-
-  state_ = PREINITIALIZED;
-  return true;
-}
-
-
 void Isolate::InitializeThreadLocal() {
   thread_local_top_.isolate_ = this;
   thread_local_top_.Initialize();
@@ -1680,19 +1636,71 @@
 }
 
 
+void Isolate::InitializeLoggingAndCounters() {
+  if (logger_ == NULL) {
+    logger_ = new Logger;
+  }
+  if (counters_ == NULL) {
+    counters_ = new Counters;
+  }
+}
+
+
+void Isolate::InitializeDebugger() {
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  ScopedLock lock(debugger_access_);
+  if (NoBarrier_Load(&debugger_initialized_)) return;
+  InitializeLoggingAndCounters();
+  debug_ = new Debug(this);
+  debugger_ = new Debugger(this);
+  Release_Store(&debugger_initialized_, true);
+#endif
+}
+
+
 bool Isolate::Init(Deserializer* des) {
   ASSERT(state_ != INITIALIZED);
-
+  ASSERT(Isolate::Current() == this);
   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;
+  InitializeLoggingAndCounters();
+
+  InitializeDebugger();
+
+  memory_allocator_ = new MemoryAllocator(this);
+  code_range_ = new CodeRange(this);
+
+  // Safe after setting Heap::isolate_, initializing StackGuard and
+  // ensuring that Isolate::Current() == this.
+  heap_.SetStackLimits();
+
+#define C(name) isolate_addresses_[Isolate::k_##name] =                        \
+    reinterpret_cast<Address>(name());
+  ISOLATE_ADDRESS_LIST(C)
+#undef C
+
+  string_tracker_ = new StringTracker();
+  string_tracker_->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();
+  unicode_cache_ = new UnicodeCache();
+  pc_to_code_cache_ = new PcToCodeCache(this);
+  write_input_buffer_ = new StringInputBuffer();
+  global_handles_ = new GlobalHandles(this);
+  bootstrapper_ = new Bootstrapper();
+  handle_scope_implementer_ = new HandleScopeImplementer(this);
+  stub_cache_ = new StubCache(this);
+  ast_sentinels_ = new AstSentinels();
+  regexp_stack_ = new RegExpStack();
+  regexp_stack_->isolate_ = this;
 
   // Enable logging before setting up the heap
   logger_->Setup();
@@ -1715,7 +1723,8 @@
     stack_guard_.InitThread(lock);
   }
 
-  // Setup the object heap
+  // Setup the object heap.
+  const bool create_heap_objects = (des == NULL);
   ASSERT(!heap_.HasBeenSetup());
   if (!heap_.Setup(create_heap_objects)) {
     V8::SetFatalError();
@@ -1775,6 +1784,16 @@
 }
 
 
+// Initialized lazily to allow early
+// v8::V8::SetAddHistogramSampleFunction calls.
+StatsTable* Isolate::stats_table() {
+  if (stats_table_ == NULL) {
+    stats_table_ = new StatsTable;
+  }
+  return stats_table_;
+}
+
+
 void Isolate::Enter() {
   Isolate* current_isolate = NULL;
   PerIsolateThreadData* current_data = CurrentPerIsolateThreadData();
@@ -1814,8 +1833,6 @@
 
   SetIsolateThreadLocals(this, data);
 
-  CHECK(PreInit());
-
   // In case it's the first time some thread enters the isolate.
   set_thread_id(data->thread_id());
 }
diff --git a/src/isolate.h b/src/isolate.h
index f2281aa..5bb504d 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -256,6 +256,9 @@
   // Call back function to report unsafe JS accesses.
   v8::FailedAccessCheckCallback failed_access_check_callback_;
 
+  // Whether out of memory exceptions should be ignored.
+  bool ignore_out_of_memory_;
+
  private:
   void InitializeInternal();
 
@@ -446,6 +449,13 @@
     return reinterpret_cast<Isolate*>(Thread::GetThreadLocal(isolate_key_));
   }
 
+  // Usually called by Init(), but can be called early e.g. to allow
+  // testing components that require logging but not the whole
+  // isolate.
+  //
+  // Safe to call more than once.
+  void InitializeLoggingAndCounters();
+
   bool Init(Deserializer* des);
 
   bool IsInitialized() { return state_ == INITIALIZED; }
@@ -498,10 +508,12 @@
   // switched to non-legacy behavior).
   static void EnterDefaultIsolate();
 
-  // Debug.
   // Mutex for serializing access to break control structures.
   Mutex* break_access() { return break_access_; }
 
+  // Mutex for serializing access to debugger.
+  Mutex* debugger_access() { return debugger_access_; }
+
   Address get_address_from_id(AddressId id);
 
   // Access to top context (where the current function object was created).
@@ -661,6 +673,12 @@
   // Tells whether the current context has experienced an out of memory
   // exception.
   bool is_out_of_memory();
+  bool ignore_out_of_memory() {
+    return thread_local_top_.ignore_out_of_memory_;
+  }
+  void set_ignore_out_of_memory(bool value) {
+    thread_local_top_.ignore_out_of_memory_ = value;
+  }
 
   void PrintCurrentStackTrace(FILE* out);
   void PrintStackTrace(FILE* out, char* thread_data);
@@ -769,14 +787,24 @@
 #undef GLOBAL_CONTEXT_FIELD_ACCESSOR
 
   Bootstrapper* bootstrapper() { return bootstrapper_; }
-  Counters* counters() { return counters_; }
+  Counters* counters() {
+    // Call InitializeLoggingAndCounters() if logging is needed before
+    // the isolate is fully initialized.
+    ASSERT(counters_ != NULL);
+    return counters_;
+  }
   CodeRange* code_range() { return code_range_; }
   RuntimeProfiler* runtime_profiler() { return runtime_profiler_; }
   CompilationCache* compilation_cache() { return compilation_cache_; }
-  Logger* logger() { return logger_; }
+  Logger* logger() {
+    // Call InitializeLoggingAndCounters() if logging is needed before
+    // the isolate is fully initialized.
+    ASSERT(logger_ != NULL);
+    return logger_;
+  }
   StackGuard* stack_guard() { return &stack_guard_; }
   Heap* heap() { return &heap_; }
-  StatsTable* stats_table() { return stats_table_; }
+  StatsTable* stats_table();
   StubCache* stub_cache() { return stub_cache_; }
   DeoptimizerData* deoptimizer_data() { return deoptimizer_data_; }
   ThreadLocalTop* thread_local_top() { return &thread_local_top_; }
@@ -877,8 +905,14 @@
   void PreallocatedStorageInit(size_t size);
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  Debugger* debugger() { return debugger_; }
-  Debug* debug() { return debug_; }
+  Debugger* debugger() {
+    if (!NoBarrier_Load(&debugger_initialized_)) InitializeDebugger();
+    return debugger_;
+  }
+  Debug* debug() {
+    if (!NoBarrier_Load(&debugger_initialized_)) InitializeDebugger();
+    return debug_;
+  }
 #endif
 
   inline bool DebuggerHasBreakPoints();
@@ -1010,8 +1044,6 @@
   static Isolate* default_isolate_;
   static ThreadDataTable* thread_data_table_;
 
-  bool PreInit();
-
   void Deinit();
 
   static void SetIsolateThreadLocals(Isolate* isolate,
@@ -1019,7 +1051,6 @@
 
   enum State {
     UNINITIALIZED,    // Some components may not have been allocated.
-    PREINITIALIZED,   // Components have been allocated but not initialized.
     INITIALIZED       // All components are fully initialized.
   };
 
@@ -1063,6 +1094,8 @@
 
   void PropagatePendingExceptionToExternalTryCatch();
 
+  void InitializeDebugger();
+
   int stack_trace_nesting_level_;
   StringStream* incomplete_message_;
   // The preallocated memory thread singleton.
@@ -1076,6 +1109,8 @@
   Counters* counters_;
   CodeRange* code_range_;
   Mutex* break_access_;
+  Atomic32 debugger_initialized_;
+  Mutex* debugger_access_;
   Heap heap_;
   Logger* logger_;
   StackGuard stack_guard_;
@@ -1165,6 +1200,7 @@
   friend class Simulator;
   friend class StackGuard;
   friend class ThreadId;
+  friend class TestMemoryAllocatorScope;
   friend class v8::Isolate;
   friend class v8::Locker;
   friend class v8::Unlocker;
diff --git a/src/json-parser.h b/src/json-parser.h
index f93b04d..68eab65 100644
--- a/src/json-parser.h
+++ b/src/json-parser.h
@@ -458,12 +458,12 @@
   String::WriteToFlat(*prefix, dest, start, end);
 
   while (c0_ != '"') {
+    // Check for control character (0x00-0x1f) or unterminated string (<0).
+    if (c0_ < 0x20) return Handle<String>::null();
     if (count >= length) {
       // We need to create a longer sequential string for the result.
       return SlowScanJsonString<StringType, SinkChar>(seq_str, 0, count);
     }
-    // Check for control character (0x00-0x1f) or unterminated string (<0).
-    if (c0_ < 0x20) return Handle<String>::null();
     if (c0_ != '\\') {
       // If the sink can contain UC16 characters, or source_ contains only
       // ASCII characters, there's no need to test whether we can store the
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index bc47df8..af64437 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -267,7 +267,7 @@
                                seq_sub->ToUC16Vector(),
                                needle->ToUC16Vector(),
                                index)));
-    if (index == -1) return FACTORY->null_value();
+    if (index == -1) return isolate->factory()->null_value();
   }
   ASSERT(last_match_info->HasFastElements());
 
diff --git a/src/log-utils.cc b/src/log-utils.cc
index 6112e34..27e654d 100644
--- a/src/log-utils.cc
+++ b/src/log-utils.cc
@@ -34,7 +34,7 @@
 namespace internal {
 
 
-const char* Log::kLogToTemporaryFile = "&";
+const char* const Log::kLogToTemporaryFile = "&";
 
 
 Log::Log(Logger* logger)
diff --git a/src/log-utils.h b/src/log-utils.h
index d336d71..2b20a01 100644
--- a/src/log-utils.h
+++ b/src/log-utils.h
@@ -59,7 +59,7 @@
 
   // This mode is only used in tests, as temporary files are automatically
   // deleted on close and thus can't be accessed afterwards.
-  static const char* kLogToTemporaryFile;
+  static const char* const kLogToTemporaryFile;
 
  private:
   explicit Log(Logger* logger);
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 0bf8286..0961350 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -64,13 +64,15 @@
       live_bytes_(0),
 #endif
       heap_(NULL),
-      code_flusher_(NULL) { }
+      code_flusher_(NULL),
+      encountered_weak_maps_(NULL) { }
 
 
 void MarkCompactCollector::CollectGarbage() {
   // Make sure that Prepare() has been called. The individual steps below will
   // update the state as they proceed.
   ASSERT(state_ == PREPARE_GC);
+  ASSERT(encountered_weak_maps_ == Smi::FromInt(0));
 
   // Prepare has selected whether to compact the old generation or not.
   // Tell the tracer.
@@ -80,6 +82,8 @@
 
   if (FLAG_collect_maps) ClearNonLiveTransitions();
 
+  ClearWeakMaps();
+
   SweepLargeObjectSpace();
 
   if (IsCompacting()) {
@@ -407,6 +411,8 @@
     table_.Register(kVisitSeqAsciiString, &DataObjectVisitor::Visit);
     table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit);
 
+    table_.Register(kVisitJSWeakMap, &VisitJSWeakMap);
+
     table_.Register(kVisitOddball,
                     &FixedBodyVisitor<StaticMarkingVisitor,
                                       Oddball::BodyDescriptor,
@@ -556,6 +562,34 @@
                               StructBodyDescriptor,
                               void> StructObjectVisitor;
 
+  static void VisitJSWeakMap(Map* map, HeapObject* object) {
+    MarkCompactCollector* collector = map->heap()->mark_compact_collector();
+    JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(object);
+
+    // Enqueue weak map in linked list of encountered weak maps.
+    ASSERT(weak_map->next() == Smi::FromInt(0));
+    weak_map->set_next(collector->encountered_weak_maps());
+    collector->set_encountered_weak_maps(weak_map);
+
+    // Skip visiting the backing hash table containing the mappings.
+    int object_size = JSWeakMap::BodyDescriptor::SizeOf(map, object);
+    BodyVisitorBase<StaticMarkingVisitor>::IteratePointers(
+        map->heap(),
+        object,
+        JSWeakMap::BodyDescriptor::kStartOffset,
+        JSWeakMap::kTableOffset);
+    BodyVisitorBase<StaticMarkingVisitor>::IteratePointers(
+        map->heap(),
+        object,
+        JSWeakMap::kTableOffset + kPointerSize,
+        object_size);
+
+    // Mark the backing hash table without pushing it on the marking stack.
+    ASSERT(!weak_map->unchecked_table()->IsMarked());
+    ASSERT(weak_map->unchecked_table()->map()->IsMarked());
+    collector->SetMark(weak_map->unchecked_table());
+  }
+
   static void VisitCode(Map* map, HeapObject* object) {
     reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>(
         map->heap());
@@ -1369,20 +1403,26 @@
 // marking stack have been marked, or are overflowed in the heap.
 void MarkCompactCollector::EmptyMarkingStack() {
   while (!marking_stack_.is_empty()) {
-    HeapObject* object = marking_stack_.Pop();
-    ASSERT(object->IsHeapObject());
-    ASSERT(heap()->Contains(object));
-    ASSERT(object->IsMarked());
-    ASSERT(!object->IsOverflowed());
+    while (!marking_stack_.is_empty()) {
+      HeapObject* object = marking_stack_.Pop();
+      ASSERT(object->IsHeapObject());
+      ASSERT(heap()->Contains(object));
+      ASSERT(object->IsMarked());
+      ASSERT(!object->IsOverflowed());
 
-    // Because the object is marked, we have to recover the original map
-    // pointer and use it to mark the object's body.
-    MapWord map_word = object->map_word();
-    map_word.ClearMark();
-    Map* map = map_word.ToMap();
-    MarkObject(map);
+      // Because the object is marked, we have to recover the original map
+      // pointer and use it to mark the object's body.
+      MapWord map_word = object->map_word();
+      map_word.ClearMark();
+      Map* map = map_word.ToMap();
+      MarkObject(map);
 
-    StaticMarkingVisitor::IterateBody(map, object);
+      StaticMarkingVisitor::IterateBody(map, object);
+    }
+
+    // Process encountered weak maps, mark objects only reachable by those
+    // weak maps and repeat until fix-point is reached.
+    ProcessWeakMaps();
   }
 }
 
@@ -1735,6 +1775,45 @@
   }
 }
 
+
+void MarkCompactCollector::ProcessWeakMaps() {
+  Object* weak_map_obj = encountered_weak_maps();
+  while (weak_map_obj != Smi::FromInt(0)) {
+    ASSERT(HeapObject::cast(weak_map_obj)->IsMarked());
+    JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(weak_map_obj);
+    ObjectHashTable* table = weak_map->unchecked_table();
+    for (int i = 0; i < table->Capacity(); i++) {
+      if (HeapObject::cast(table->KeyAt(i))->IsMarked()) {
+        Object* value = table->get(table->EntryToValueIndex(i));
+        StaticMarkingVisitor::MarkObjectByPointer(heap(), &value);
+        table->set_unchecked(heap(),
+                             table->EntryToValueIndex(i),
+                             value,
+                             UPDATE_WRITE_BARRIER);
+      }
+    }
+    weak_map_obj = weak_map->next();
+  }
+}
+
+
+void MarkCompactCollector::ClearWeakMaps() {
+  Object* weak_map_obj = encountered_weak_maps();
+  while (weak_map_obj != Smi::FromInt(0)) {
+    ASSERT(HeapObject::cast(weak_map_obj)->IsMarked());
+    JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(weak_map_obj);
+    ObjectHashTable* table = weak_map->unchecked_table();
+    for (int i = 0; i < table->Capacity(); i++) {
+      if (!HeapObject::cast(table->KeyAt(i))->IsMarked()) {
+        table->RemoveEntry(i, heap());
+      }
+    }
+    weak_map_obj = weak_map->next();
+    weak_map->set_next(Smi::FromInt(0));
+  }
+  set_encountered_weak_maps(Smi::FromInt(0));
+}
+
 // -------------------------------------------------------------------------
 // Phase 2: Encode forwarding addresses.
 // When compacting, forwarding addresses for objects in old space and map
diff --git a/src/mark-compact.h b/src/mark-compact.h
index 179edba..9b67c8a 100644
--- a/src/mark-compact.h
+++ b/src/mark-compact.h
@@ -193,6 +193,11 @@
   inline bool is_code_flushing_enabled() const { return code_flusher_ != NULL; }
   void EnableCodeFlushing(bool enable);
 
+  inline Object* encountered_weak_maps() { return encountered_weak_maps_; }
+  inline void set_encountered_weak_maps(Object* weak_map) {
+    encountered_weak_maps_ = weak_map;
+  }
+
  private:
   MarkCompactCollector();
   ~MarkCompactCollector();
@@ -329,6 +334,16 @@
   // We replace them with a null descriptor, with the same key.
   void ClearNonLiveTransitions();
 
+  // Mark all values associated with reachable keys in weak maps encountered
+  // so far.  This might push new object or even new weak maps onto the
+  // marking stack.
+  void ProcessWeakMaps();
+
+  // After all reachable objects have been marked those weak map entries
+  // with an unreachable key are removed from all encountered weak maps.
+  // The linked list of all encountered weak maps is destroyed.
+  void ClearWeakMaps();
+
   // -----------------------------------------------------------------------
   // Phase 2: Sweeping to clear mark bits and free non-live objects for
   // a non-compacting collection, or else computing and encoding
@@ -499,6 +514,7 @@
   Heap* heap_;
   MarkingStack marking_stack_;
   CodeFlusher* code_flusher_;
+  Object* encountered_weak_maps_;
 
   friend class Heap;
   friend class OverflowedObjectsScanner;
diff --git a/src/messages.js b/src/messages.js
index c1618e5..6603185 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -201,6 +201,7 @@
       proxy_prop_not_configurable:  ["Trap ", "%1", " of proxy handler ", "%0", " returned non-configurable descriptor for property ", "%2"],
       proxy_non_object_prop_names:  ["Trap ", "%1", " returned non-object ", "%0"],
       proxy_repeated_prop_name:     ["Trap ", "%1", " returned repeated property name ", "%2"],
+      invalid_weakmap_key:          ["Invalid value used as weak map key"],
       // RangeError
       invalid_array_length:         ["Invalid array length"],
       stack_overflow:               ["Maximum call stack size exceeded"],
diff --git a/src/mips/deoptimizer-mips.cc b/src/mips/deoptimizer-mips.cc
index 9a19aba..18b6231 100644
--- a/src/mips/deoptimizer-mips.cc
+++ b/src/mips/deoptimizer-mips.cc
@@ -39,7 +39,7 @@
 namespace internal {
 
 
-int Deoptimizer::table_entry_size_ = 10;
+const int Deoptimizer::table_entry_size_ = 10;
 
 
 int Deoptimizer::patch_size() {
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 2963231..8c0330d 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -153,6 +153,9 @@
     case JS_ARRAY_TYPE:
       JSArray::cast(this)->JSArrayVerify();
       break;
+    case JS_WEAK_MAP_TYPE:
+      JSWeakMap::cast(this)->JSWeakMapVerify();
+      break;
     case JS_REGEXP_TYPE:
       JSRegExp::cast(this)->JSRegExpVerify();
       break;
@@ -313,7 +316,7 @@
 void FixedDoubleArray::FixedDoubleArrayVerify() {
   for (int i = 0; i < length(); i++) {
     if (!is_the_hole(i)) {
-      double value = get(i);
+      double value = get_scalar(i);
       ASSERT(!isnan(value) ||
              (BitCast<uint64_t>(value) ==
               BitCast<uint64_t>(canonical_not_the_hole_nan_as_double())));
@@ -453,6 +456,14 @@
 }
 
 
+void JSWeakMap::JSWeakMapVerify() {
+  CHECK(IsJSWeakMap());
+  JSObjectVerify();
+  VerifyHeapPointer(table());
+  ASSERT(table()->IsHashTable());
+}
+
+
 void JSRegExp::JSRegExpVerify() {
   JSObjectVerify();
   ASSERT(data()->IsUndefined() || data()->IsFixedArray());
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 6870ce0..70ed47b 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -35,6 +35,7 @@
 #ifndef V8_OBJECTS_INL_H_
 #define V8_OBJECTS_INL_H_
 
+#include "elements.h"
 #include "objects.h"
 #include "contexts.h"
 #include "conversions-inl.h"
@@ -480,6 +481,12 @@
 }
 
 
+bool Object::IsJSWeakMap() {
+  return Object::IsJSObject() &&
+      HeapObject::cast(this)->map()->instance_type() == JS_WEAK_MAP_TYPE;
+}
+
+
 bool Object::IsJSContextExtensionObject() {
   return IsHeapObject()
       && (HeapObject::cast(this)->map()->instance_type() ==
@@ -1416,6 +1423,8 @@
       return JSValue::kSize;
     case JS_ARRAY_TYPE:
       return JSValue::kSize;
+    case JS_WEAK_MAP_TYPE:
+      return JSWeakMap::kSize;
     case JS_REGEXP_TYPE:
       return JSValue::kSize;
     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
@@ -1603,6 +1612,7 @@
 
 void FixedArray::set(int index, Smi* value) {
   ASSERT(map() != HEAP->fixed_cow_array_map());
+  ASSERT(index >= 0 && index < this->length());
   ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
   int offset = kHeaderSize + index * kPointerSize;
   WRITE_FIELD(this, offset, value);
@@ -1635,7 +1645,7 @@
 }
 
 
-double FixedDoubleArray::get(int index) {
+double FixedDoubleArray::get_scalar(int index) {
   ASSERT(map() != HEAP->fixed_cow_array_map() &&
          map() != HEAP->fixed_array_map());
   ASSERT(index >= 0 && index < this->length());
@@ -1645,6 +1655,15 @@
 }
 
 
+MaybeObject* FixedDoubleArray::get(int index) {
+  if (is_the_hole(index)) {
+    return GetHeap()->the_hole_value();
+  } else {
+    return GetHeap()->NumberFromDouble(get_scalar(index));
+  }
+}
+
+
 void FixedDoubleArray::set(int index, double value) {
   ASSERT(map() != HEAP->fixed_cow_array_map() &&
          map() != HEAP->fixed_array_map());
@@ -2066,6 +2085,7 @@
 CAST_ACCESSOR(JSRegExp)
 CAST_ACCESSOR(JSProxy)
 CAST_ACCESSOR(JSFunctionProxy)
+CAST_ACCESSOR(JSWeakMap)
 CAST_ACCESSOR(Foreign)
 CAST_ACCESSOR(ByteArray)
 CAST_ACCESSOR(ExternalArray)
@@ -2369,13 +2389,18 @@
 }
 
 
-uint8_t ExternalPixelArray::get(int index) {
+uint8_t ExternalPixelArray::get_scalar(int index) {
   ASSERT((index >= 0) && (index < this->length()));
   uint8_t* ptr = external_pixel_pointer();
   return ptr[index];
 }
 
 
+MaybeObject* ExternalPixelArray::get(int index) {
+  return Smi::FromInt(static_cast<int>(get_scalar(index)));
+}
+
+
 void ExternalPixelArray::set(int index, uint8_t value) {
   ASSERT((index >= 0) && (index < this->length()));
   uint8_t* ptr = external_pixel_pointer();
@@ -2395,13 +2420,18 @@
 }
 
 
-int8_t ExternalByteArray::get(int index) {
+int8_t ExternalByteArray::get_scalar(int index) {
   ASSERT((index >= 0) && (index < this->length()));
   int8_t* ptr = static_cast<int8_t*>(external_pointer());
   return ptr[index];
 }
 
 
+MaybeObject* ExternalByteArray::get(int index) {
+  return Smi::FromInt(static_cast<int>(get_scalar(index)));
+}
+
+
 void ExternalByteArray::set(int index, int8_t value) {
   ASSERT((index >= 0) && (index < this->length()));
   int8_t* ptr = static_cast<int8_t*>(external_pointer());
@@ -2409,13 +2439,18 @@
 }
 
 
-uint8_t ExternalUnsignedByteArray::get(int index) {
+uint8_t ExternalUnsignedByteArray::get_scalar(int index) {
   ASSERT((index >= 0) && (index < this->length()));
   uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
   return ptr[index];
 }
 
 
+MaybeObject* ExternalUnsignedByteArray::get(int index) {
+  return Smi::FromInt(static_cast<int>(get_scalar(index)));
+}
+
+
 void ExternalUnsignedByteArray::set(int index, uint8_t value) {
   ASSERT((index >= 0) && (index < this->length()));
   uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
@@ -2423,13 +2458,18 @@
 }
 
 
-int16_t ExternalShortArray::get(int index) {
+int16_t ExternalShortArray::get_scalar(int index) {
   ASSERT((index >= 0) && (index < this->length()));
   int16_t* ptr = static_cast<int16_t*>(external_pointer());
   return ptr[index];
 }
 
 
+MaybeObject* ExternalShortArray::get(int index) {
+  return Smi::FromInt(static_cast<int>(get_scalar(index)));
+}
+
+
 void ExternalShortArray::set(int index, int16_t value) {
   ASSERT((index >= 0) && (index < this->length()));
   int16_t* ptr = static_cast<int16_t*>(external_pointer());
@@ -2437,13 +2477,18 @@
 }
 
 
-uint16_t ExternalUnsignedShortArray::get(int index) {
+uint16_t ExternalUnsignedShortArray::get_scalar(int index) {
   ASSERT((index >= 0) && (index < this->length()));
   uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
   return ptr[index];
 }
 
 
+MaybeObject* ExternalUnsignedShortArray::get(int index) {
+  return Smi::FromInt(static_cast<int>(get_scalar(index)));
+}
+
+
 void ExternalUnsignedShortArray::set(int index, uint16_t value) {
   ASSERT((index >= 0) && (index < this->length()));
   uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
@@ -2451,13 +2496,18 @@
 }
 
 
-int32_t ExternalIntArray::get(int index) {
+int32_t ExternalIntArray::get_scalar(int index) {
   ASSERT((index >= 0) && (index < this->length()));
   int32_t* ptr = static_cast<int32_t*>(external_pointer());
   return ptr[index];
 }
 
 
+MaybeObject* ExternalIntArray::get(int index) {
+    return GetHeap()->NumberFromInt32(get_scalar(index));
+}
+
+
 void ExternalIntArray::set(int index, int32_t value) {
   ASSERT((index >= 0) && (index < this->length()));
   int32_t* ptr = static_cast<int32_t*>(external_pointer());
@@ -2465,13 +2515,18 @@
 }
 
 
-uint32_t ExternalUnsignedIntArray::get(int index) {
+uint32_t ExternalUnsignedIntArray::get_scalar(int index) {
   ASSERT((index >= 0) && (index < this->length()));
   uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
   return ptr[index];
 }
 
 
+MaybeObject* ExternalUnsignedIntArray::get(int index) {
+    return GetHeap()->NumberFromUint32(get_scalar(index));
+}
+
+
 void ExternalUnsignedIntArray::set(int index, uint32_t value) {
   ASSERT((index >= 0) && (index < this->length()));
   uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
@@ -2479,13 +2534,18 @@
 }
 
 
-float ExternalFloatArray::get(int index) {
+float ExternalFloatArray::get_scalar(int index) {
   ASSERT((index >= 0) && (index < this->length()));
   float* ptr = static_cast<float*>(external_pointer());
   return ptr[index];
 }
 
 
+MaybeObject* ExternalFloatArray::get(int index) {
+    return GetHeap()->NumberFromDouble(get_scalar(index));
+}
+
+
 void ExternalFloatArray::set(int index, float value) {
   ASSERT((index >= 0) && (index < this->length()));
   float* ptr = static_cast<float*>(external_pointer());
@@ -2493,13 +2553,18 @@
 }
 
 
-double ExternalDoubleArray::get(int index) {
+double ExternalDoubleArray::get_scalar(int index) {
   ASSERT((index >= 0) && (index < this->length()));
   double* ptr = static_cast<double*>(external_pointer());
   return ptr[index];
 }
 
 
+MaybeObject* ExternalDoubleArray::get(int index) {
+    return GetHeap()->NumberFromDouble(get_scalar(index));
+}
+
+
 void ExternalDoubleArray::set(int index, double value) {
   ASSERT((index >= 0) && (index < this->length()));
   double* ptr = static_cast<double*>(external_pointer());
@@ -3469,35 +3534,14 @@
 }
 
 
-BOOL_ACCESSORS(SharedFunctionInfo,
-               compiler_hints,
-               strict_mode,
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, strict_mode,
                kStrictModeFunction)
-
-
-bool SharedFunctionInfo::native() {
-  return BooleanBit::get(compiler_hints(), kNative);
-}
-
-
-void SharedFunctionInfo::set_native(bool value) {
-  set_compiler_hints(BooleanBit::set(compiler_hints(),
-                                     kNative,
-                                     value));
-}
-
-
-bool SharedFunctionInfo::bound() {
-  return BooleanBit::get(compiler_hints(), kBoundFunction);
-}
-
-
-void SharedFunctionInfo::set_bound(bool value) {
-  set_compiler_hints(BooleanBit::set(compiler_hints(),
-                                     kBoundFunction,
-                                     value));
-}
-
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
+               name_should_print_as_anonymous,
+               kNameShouldPrintAsAnonymous)
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
 
 ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
 ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
@@ -3796,6 +3840,15 @@
 ACCESSORS(JSProxy, padding, Object, kPaddingOffset)
 
 
+ACCESSORS(JSWeakMap, table, ObjectHashTable, kTableOffset)
+ACCESSORS_GCSAFE(JSWeakMap, next, Object, kNextOffset)
+
+
+ObjectHashTable* JSWeakMap::unchecked_table() {
+  return reinterpret_cast<ObjectHashTable*>(READ_FIELD(this, kTableOffset));
+}
+
+
 Address Foreign::address() {
   return AddressFrom<Address>(READ_INTPTR_FIELD(this, kAddressOffset));
 }
@@ -3981,6 +4034,11 @@
 }
 
 
+ElementsAccessor* JSObject::GetElementsAccessor() {
+  return ElementsAccessor::ForKind(GetElementsKind());
+}
+
+
 bool JSObject::HasFastElements() {
   return GetElementsKind() == FAST_ELEMENTS;
 }
@@ -4399,6 +4457,11 @@
 }
 
 
+void ObjectHashTable::RemoveEntry(int entry) {
+  RemoveEntry(entry, GetHeap());
+}
+
+
 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:
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 5cb5269..3573572 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -151,6 +151,9 @@
     case JS_PROXY_TYPE:
       JSProxy::cast(this)->JSProxyPrint(out);
       break;
+    case JS_WEAK_MAP_TYPE:
+      JSWeakMap::cast(this)->JSWeakMapPrint(out);
+      break;
     case FOREIGN_TYPE:
       Foreign::cast(this)->ForeignPrint(out);
       break;
@@ -289,7 +292,7 @@
         if (p->is_the_hole(i)) {
           PrintF(out, "   %d: <the hole>", i);
         } else {
-          PrintF(out, "   %d: %g", i, p->get(i));
+          PrintF(out, "   %d: %g", i, p->get_scalar(i));
         }
         PrintF(out, "\n");
       }
@@ -298,14 +301,14 @@
     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));
+        PrintF(out, "   %d: %d\n", i, p->get_scalar(i));
       }
       break;
     }
     case EXTERNAL_BYTE_ELEMENTS: {
       ExternalByteArray* p = ExternalByteArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
       }
       break;
     }
@@ -313,14 +316,14 @@
       ExternalUnsignedByteArray* p =
           ExternalUnsignedByteArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
       }
       break;
     }
     case EXTERNAL_SHORT_ELEMENTS: {
       ExternalShortArray* p = ExternalShortArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
       }
       break;
     }
@@ -328,14 +331,14 @@
       ExternalUnsignedShortArray* p =
           ExternalUnsignedShortArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
       }
       break;
     }
     case EXTERNAL_INT_ELEMENTS: {
       ExternalIntArray* p = ExternalIntArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
       }
       break;
     }
@@ -343,21 +346,21 @@
       ExternalUnsignedIntArray* p =
           ExternalUnsignedIntArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
       }
       break;
     }
     case EXTERNAL_FLOAT_ELEMENTS: {
       ExternalFloatArray* p = ExternalFloatArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "   %d: %f\n", i, p->get(i));
+        PrintF(out, "   %d: %f\n", i, p->get_scalar(i));
       }
       break;
     }
     case EXTERNAL_DOUBLE_ELEMENTS: {
       ExternalDoubleArray* p = ExternalDoubleArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF(out, "  %d: %f\n", i, p->get(i));
+        PrintF(out, "  %d: %f\n", i, p->get_scalar(i));
       }
       break;
     }
@@ -431,6 +434,7 @@
     case CODE_TYPE: return "CODE";
     case JS_ARRAY_TYPE: return "JS_ARRAY";
     case JS_PROXY_TYPE: return "JS_PROXY";
+    case JS_WEAK_MAP_TYPE: return "JS_WEAK_MAP";
     case JS_REGEXP_TYPE: return "JS_REGEXP";
     case JS_VALUE_TYPE: return "JS_VALUE";
     case JS_GLOBAL_OBJECT_TYPE: return "JS_GLOBAL_OBJECT";
@@ -584,6 +588,16 @@
 }
 
 
+void JSWeakMap::JSWeakMapPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "JSWeakMap");
+  PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
+  PrintF(out, " - number of elements = %d\n", table()->NumberOfElements());
+  PrintF(out, " - table = ");
+  table()->ShortPrint(out);
+  PrintF(out, "\n");
+}
+
+
 void JSFunction::JSFunctionPrint(FILE* out) {
   HeapObject::PrintHeader(out, "Function");
   PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
diff --git a/src/objects-visiting.cc b/src/objects-visiting.cc
index 4cd795e..84ab57f 100644
--- a/src/objects-visiting.cc
+++ b/src/objects-visiting.cc
@@ -88,6 +88,9 @@
     case JS_GLOBAL_PROPERTY_CELL_TYPE:
       return kVisitPropertyCell;
 
+    case JS_WEAK_MAP_TYPE:
+      return kVisitJSWeakMap;
+
     case JS_REGEXP_TYPE:
       return kVisitJSRegExp;
 
diff --git a/src/objects-visiting.h b/src/objects-visiting.h
index cc64763..c96a8ef 100644
--- a/src/objects-visiting.h
+++ b/src/objects-visiting.h
@@ -121,6 +121,7 @@
     kVisitPropertyCell,
     kVisitSharedFunctionInfo,
     kVisitJSFunction,
+    kVisitJSWeakMap,
     kVisitJSRegExp,
 
     kVisitorIdCount,
@@ -317,7 +318,9 @@
                                       SharedFunctionInfo::BodyDescriptor,
                                       int>::Visit);
 
-    table_.Register(kVisitJSRegExp, &VisitJSRegExp);
+    table_.Register(kVisitJSWeakMap, &VisitJSObject);
+
+    table_.Register(kVisitJSRegExp, &VisitJSObject);
 
     table_.Register(kVisitSeqAsciiString, &VisitSeqAsciiString);
 
@@ -356,15 +359,15 @@
     return FixedDoubleArray::SizeFor(length);
   }
 
+  static inline int VisitJSObject(Map* map, HeapObject* object) {
+    return JSObjectVisitor::Visit(map, object);
+  }
+
   static inline int VisitSeqAsciiString(Map* map, HeapObject* object) {
     return SeqAsciiString::cast(object)->
         SeqAsciiStringSize(map->instance_type());
   }
 
-  static inline int VisitJSRegExp(Map* map, HeapObject* object) {
-    return JSObjectVisitor::Visit(map, object);
-  }
-
   static inline int VisitSeqTwoByteString(Map* map, HeapObject* object) {
     return SeqTwoByteString::cast(object)->
         SeqTwoByteStringSize(map->instance_type());
diff --git a/src/objects.cc b/src/objects.cc
index e1318bc..e35274d 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -33,6 +33,7 @@
 #include "codegen.h"
 #include "debug.h"
 #include "deoptimizer.h"
+#include "elements.h"
 #include "execution.h"
 #include "full-codegen.h"
 #include "hydrogen.h"
@@ -602,36 +603,68 @@
 
 
 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
-  Object* holder = NULL;
-  if (IsSmi()) {
-    Context* global_context = Isolate::Current()->context()->global_context();
-    holder = global_context->number_function()->instance_prototype();
-  } else {
-    HeapObject* heap_object = HeapObject::cast(this);
+  Heap* heap = IsSmi()
+      ? Isolate::Current()->heap()
+      : HeapObject::cast(this)->GetHeap();
+  Object* holder = this;
 
-    if (heap_object->IsJSObject()) {
-      return JSObject::cast(this)->GetElementWithReceiver(receiver, index);
-    }
-    Heap* heap = heap_object->GetHeap();
-    Isolate* isolate = heap->isolate();
-
-    Context* global_context = isolate->context()->global_context();
-    if (heap_object->IsString()) {
-      holder = global_context->string_function()->instance_prototype();
-    } else if (heap_object->IsHeapNumber()) {
+  // Iterate up the prototype chain until an element is found or the null
+  // prototype is encountered.
+  for (holder = this;
+       holder != heap->null_value();
+       holder = holder->GetPrototype()) {
+    if (holder->IsSmi()) {
+      Context* global_context = Isolate::Current()->context()->global_context();
       holder = global_context->number_function()->instance_prototype();
-    } else if (heap_object->IsBoolean()) {
-      holder = global_context->boolean_function()->instance_prototype();
-    } else if (heap_object->IsJSProxy()) {
-      return heap->undefined_value();  // For now...
     } else {
-      // Undefined and null have no indexed properties.
-      ASSERT(heap_object->IsUndefined() || heap_object->IsNull());
-      return heap->undefined_value();
+      HeapObject* heap_object = HeapObject::cast(holder);
+      if (!heap_object->IsJSObject()) {
+        Isolate* isolate = heap->isolate();
+        Context* global_context = isolate->context()->global_context();
+        if (heap_object->IsString()) {
+          holder = global_context->string_function()->instance_prototype();
+        } else if (heap_object->IsHeapNumber()) {
+          holder = global_context->number_function()->instance_prototype();
+        } else if (heap_object->IsBoolean()) {
+          holder = global_context->boolean_function()->instance_prototype();
+        } else if (heap_object->IsJSProxy()) {
+          return heap->undefined_value();  // For now...
+        } else {
+          // Undefined and null have no indexed properties.
+          ASSERT(heap_object->IsUndefined() || heap_object->IsNull());
+          return heap->undefined_value();
+        }
+      }
+    }
+
+    // Inline the case for JSObjects. Doing so significantly improves the
+    // performance of fetching elements where checking the prototype chain is
+    // necessary.
+    JSObject* js_object = JSObject::cast(holder);
+
+    // Check access rights if needed.
+    if (js_object->IsAccessCheckNeeded()) {
+      Isolate* isolate = heap->isolate();
+      if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
+        isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
+        return heap->undefined_value();
+      }
+    }
+
+    if (js_object->HasIndexedInterceptor()) {
+      return js_object->GetElementWithInterceptor(receiver, index);
+    }
+
+    if (js_object->elements() != heap->empty_fixed_array()) {
+      MaybeObject* result = js_object->GetElementsAccessor()->GetWithReceiver(
+          js_object,
+          receiver,
+          index);
+      if (result != heap->the_hole_value()) return result;
     }
   }
 
-  return JSObject::cast(holder)->GetElementWithReceiver(receiver, index);
+  return heap->undefined_value();
 }
 
 
@@ -962,6 +995,11 @@
       accumulator->Add("<JS array[%u]>", static_cast<uint32_t>(length));
       break;
     }
+    case JS_WEAK_MAP_TYPE: {
+      int elements = JSWeakMap::cast(this)->table()->NumberOfElements();
+      accumulator->Add("<JS WeakMap[%d]>", elements);
+      break;
+    }
     case JS_REGEXP_TYPE: {
       accumulator->Add("<JS RegExp>");
       break;
@@ -1192,6 +1230,7 @@
     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
     case JS_VALUE_TYPE:
     case JS_ARRAY_TYPE:
+    case JS_WEAK_MAP_TYPE:
     case JS_REGEXP_TYPE:
     case JS_GLOBAL_PROXY_TYPE:
     case JS_GLOBAL_OBJECT_TYPE:
@@ -2923,7 +2962,7 @@
         // exceed the capacity of new space, and we would fail repeatedly
         // trying to convert the FixedDoubleArray.
         MaybeObject* maybe_value_object =
-            GetHeap()->AllocateHeapNumber(double_array->get(i), TENURED);
+            GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
         if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
       }
     } else {
@@ -3101,48 +3140,6 @@
 }
 
 
-MaybeObject* JSObject::DeleteElementPostInterceptor(uint32_t index,
-                                                    DeleteMode mode) {
-  ASSERT(!HasExternalArrayElements());
-  switch (GetElementsKind()) {
-    case FAST_ELEMENTS: {
-      Object* obj;
-      { MaybeObject* maybe_obj = EnsureWritableFastElements();
-        if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-      }
-      uint32_t length = IsJSArray() ?
-      static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) :
-      static_cast<uint32_t>(FixedArray::cast(elements())->length());
-      if (index < length) {
-        FixedArray::cast(elements())->set_the_hole(index);
-      }
-      break;
-    }
-    case DICTIONARY_ELEMENTS: {
-      NumberDictionary* dictionary = element_dictionary();
-      int entry = dictionary->FindEntry(index);
-      if (entry != NumberDictionary::kNotFound) {
-        Object* deleted = dictionary->DeleteProperty(entry, mode);
-        if (deleted == GetHeap()->true_value()) {
-          MaybeObject* maybe_elements = dictionary->Shrink(index);
-          FixedArray* new_elements = NULL;
-          if (!maybe_elements->To(&new_elements)) {
-            return maybe_elements;
-          }
-          set_elements(new_elements);
-        }
-        return deleted;
-      }
-      break;
-    }
-    default:
-      UNREACHABLE();
-      break;
-  }
-  return GetHeap()->true_value();
-}
-
-
 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) {
   Isolate* isolate = GetIsolate();
   Heap* heap = isolate->heap();
@@ -3170,100 +3167,14 @@
     ASSERT(result->IsBoolean());
     return *v8::Utils::OpenHandle(*result);
   }
-  MaybeObject* raw_result =
-      this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION);
+  MaybeObject* raw_result = GetElementsAccessor()->Delete(*this_handle,
+                                                          index,
+                                                          NORMAL_DELETION);
   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   return raw_result;
 }
 
 
-MaybeObject* JSObject::DeleteFastElement(uint32_t index) {
-  ASSERT(HasFastElements() || HasFastArgumentsElements());
-  Heap* heap = GetHeap();
-  FixedArray* backing_store = FixedArray::cast(elements());
-  if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
-    backing_store = FixedArray::cast(backing_store->get(1));
-  } else {
-    Object* writable;
-    MaybeObject* maybe = EnsureWritableFastElements();
-    if (!maybe->ToObject(&writable)) return maybe;
-    backing_store = FixedArray::cast(writable);
-  }
-  uint32_t length = static_cast<uint32_t>(
-      IsJSArray()
-      ? Smi::cast(JSArray::cast(this)->length())->value()
-      : backing_store->length());
-  if (index < length) {
-    backing_store->set_the_hole(index);
-    // If an old space backing store is larger than a certain size and
-    // has too few used values, normalize it.
-    // To avoid doing the check on every delete we require at least
-    // one adjacent hole to the value being deleted.
-    Object* hole = heap->the_hole_value();
-    const int kMinLengthForSparsenessCheck = 64;
-    if (backing_store->length() >= kMinLengthForSparsenessCheck &&
-        !heap->InNewSpace(backing_store) &&
-        ((index > 0 && backing_store->get(index - 1) == hole) ||
-         (index + 1 < length && backing_store->get(index + 1) == hole))) {
-      int num_used = 0;
-      for (int i = 0; i < backing_store->length(); ++i) {
-        if (backing_store->get(i) != hole) ++num_used;
-        // Bail out early if more than 1/4 is used.
-        if (4 * num_used > backing_store->length()) break;
-      }
-      if (4 * num_used <= backing_store->length()) {
-        MaybeObject* result = NormalizeElements();
-        if (result->IsFailure()) return result;
-      }
-    }
-  }
-  return heap->true_value();
-}
-
-
-MaybeObject* JSObject::DeleteDictionaryElement(uint32_t index,
-                                               DeleteMode mode) {
-  Isolate* isolate = GetIsolate();
-  Heap* heap = isolate->heap();
-  FixedArray* backing_store = FixedArray::cast(elements());
-  bool is_arguments =
-      (GetElementsKind() == JSObject::NON_STRICT_ARGUMENTS_ELEMENTS);
-  if (is_arguments) {
-    backing_store = FixedArray::cast(backing_store->get(1));
-  }
-  NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
-  int entry = dictionary->FindEntry(index);
-  if (entry != NumberDictionary::kNotFound) {
-    Object* result = dictionary->DeleteProperty(entry, mode);
-    if (result == heap->true_value()) {
-      MaybeObject* maybe_elements = dictionary->Shrink(index);
-      FixedArray* new_elements = NULL;
-      if (!maybe_elements->To(&new_elements)) {
-        return maybe_elements;
-      }
-      if (is_arguments) {
-        FixedArray::cast(elements())->set(1, new_elements);
-      } else {
-        set_elements(new_elements);
-      }
-    }
-    if (mode == STRICT_DELETION && result == heap->false_value()) {
-      // In strict mode, attempting to delete a non-configurable property
-      // throws an exception.
-      HandleScope scope(isolate);
-      Handle<Object> holder(this);
-      Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
-      Handle<Object> args[2] = { name, holder };
-      Handle<Object> error =
-          isolate->factory()->NewTypeError("strict_delete_property",
-                                           HandleVector(args, 2));
-      return isolate->Throw(*error);
-    }
-  }
-  return heap->true_value();
-}
-
-
 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
   Isolate* isolate = GetIsolate();
   // Check access rights if needed.
@@ -3282,62 +3193,13 @@
 
   if (HasIndexedInterceptor()) {
     // Skip interceptor if forcing deletion.
-    return (mode == FORCE_DELETION)
-        ? DeleteElementPostInterceptor(index, FORCE_DELETION)
-        : DeleteElementWithInterceptor(index);
+    if (mode != FORCE_DELETION) {
+      return DeleteElementWithInterceptor(index);
+    }
+    mode = JSReceiver::FORCE_DELETION;
   }
 
-  switch (GetElementsKind()) {
-    case FAST_ELEMENTS:
-      return DeleteFastElement(index);
-
-    case DICTIONARY_ELEMENTS:
-      return DeleteDictionaryElement(index, mode);
-
-    case FAST_DOUBLE_ELEMENTS: {
-      int length = IsJSArray()
-          ? Smi::cast(JSArray::cast(this)->length())->value()
-          : FixedDoubleArray::cast(elements())->length();
-      if (index < static_cast<uint32_t>(length)) {
-        FixedDoubleArray::cast(elements())->set_the_hole(index);
-      }
-      break;
-    }
-    case EXTERNAL_PIXEL_ELEMENTS:
-    case EXTERNAL_BYTE_ELEMENTS:
-    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
-    case EXTERNAL_SHORT_ELEMENTS:
-    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
-    case EXTERNAL_INT_ELEMENTS:
-    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
-    case EXTERNAL_FLOAT_ELEMENTS:
-    case EXTERNAL_DOUBLE_ELEMENTS:
-      // Pixel and external array elements cannot be deleted. Just
-      // silently ignore here.
-      break;
-
-    case NON_STRICT_ARGUMENTS_ELEMENTS: {
-      FixedArray* parameter_map = FixedArray::cast(elements());
-      uint32_t length = parameter_map->length();
-      Object* probe =
-          index < (length - 2) ? parameter_map->get(index + 2) : NULL;
-      if (probe != NULL && !probe->IsTheHole()) {
-        // TODO(kmillikin): We could check if this was the last aliased
-        // parameter, and revert to normal elements in that case.  That
-        // would enable GC of the context.
-        parameter_map->set_the_hole(index + 2);
-      } else {
-        FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
-        if (arguments->IsDictionary()) {
-          return DeleteDictionaryElement(index, mode);
-        } else {
-          return DeleteFastElement(index);
-        }
-      }
-      break;
-    }
-  }
-  return isolate->heap()->true_value();
+  return GetElementsAccessor()->Delete(this, index, mode);
 }
 
 
@@ -4775,51 +4637,7 @@
 
 
 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
-  ASSERT(!array->HasExternalArrayElements());
-  switch (array->GetElementsKind()) {
-    case JSObject::FAST_ELEMENTS:
-      return UnionOfKeys(FixedArray::cast(array->elements()));
-    case JSObject::FAST_DOUBLE_ELEMENTS:
-      return UnionOfDoubleKeys(FixedDoubleArray::cast(array->elements()));
-      break;
-    case JSObject::DICTIONARY_ELEMENTS: {
-      NumberDictionary* dict = array->element_dictionary();
-      int size = dict->NumberOfElements();
-
-      // Allocate a temporary fixed array.
-      Object* object;
-      { MaybeObject* maybe_object = GetHeap()->AllocateFixedArray(size);
-        if (!maybe_object->ToObject(&object)) return maybe_object;
-      }
-      FixedArray* key_array = FixedArray::cast(object);
-
-      int capacity = dict->Capacity();
-      int pos = 0;
-      // Copy the elements from the JSArray to the temporary fixed array.
-      for (int i = 0; i < capacity; i++) {
-        if (dict->IsKey(dict->KeyAt(i))) {
-          key_array->set(pos++, dict->ValueAt(i));
-        }
-      }
-      // Compute the union of this and the temporary fixed array.
-      return UnionOfKeys(key_array);
-    }
-    case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
-      UNIMPLEMENTED();
-      break;
-    case JSObject::EXTERNAL_BYTE_ELEMENTS:
-    case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
-    case JSObject::EXTERNAL_SHORT_ELEMENTS:
-    case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
-    case JSObject::EXTERNAL_INT_ELEMENTS:
-    case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
-    case JSObject::EXTERNAL_FLOAT_ELEMENTS:
-    case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
-    case JSObject::EXTERNAL_PIXEL_ELEMENTS:
-      break;
-  }
-  UNREACHABLE();
-  return GetHeap()->null_value();  // Failure case needs to "return" a value.
+  return array->GetElementsAccessor()->AddJSArrayKeysToFixedArray(array, this);
 }
 
 
@@ -4877,69 +4695,6 @@
 }
 
 
-MaybeObject* FixedArray::UnionOfDoubleKeys(FixedDoubleArray* other) {
-  int len0 = length();
-#ifdef DEBUG
-  if (FLAG_enable_slow_asserts) {
-    for (int i = 0; i < len0; i++) {
-      ASSERT(get(i)->IsString() || get(i)->IsNumber());
-    }
-  }
-#endif
-  int len1 = other->length();
-  // Optimize if 'other' is empty.
-  // We cannot optimize if 'this' is empty, as other may have holes
-  // or non keys.
-  if (len1 == 0) return this;
-
-  // Compute how many elements are not in this.
-  int extra = 0;
-  Heap* heap = GetHeap();
-  Object* obj;
-  for (int y = 0; y < len1; y++) {
-    if (!other->is_the_hole(y)) {
-      MaybeObject* maybe_obj = heap->NumberFromDouble(other->get(y));
-      if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-      if (!HasKey(this, obj)) extra++;
-    }
-  }
-
-  if (extra == 0) return this;
-
-  // Allocate the result
-  { MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(len0 + extra);
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-  }
-  // Fill in the content
-  FixedArray* result = FixedArray::cast(obj);
-  {
-    // Limit the scope of the AssertNoAllocation
-    AssertNoAllocation no_gc;
-    WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
-    for (int i = 0; i < len0; i++) {
-      Object* e = get(i);
-      ASSERT(e->IsString() || e->IsNumber());
-      result->set(i, e, mode);
-    }
-  }
-
-  // Fill in the extra keys.
-  int index = 0;
-  for (int y = 0; y < len1; y++) {
-    if (!other->is_the_hole(y)) {
-      MaybeObject* maybe_obj = heap->NumberFromDouble(other->get(y));
-      if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-      if (!HasKey(this, obj)) {
-        result->set(len0 + index, obj);
-        index++;
-      }
-    }
-  }
-  ASSERT(extra == index);
-  return result;
-}
-
-
 MaybeObject* FixedArray::CopySize(int new_length) {
   Heap* heap = GetHeap();
   if (new_length == 0) return heap->empty_fixed_array();
@@ -7208,124 +6963,93 @@
 
   PrintF(out, "%6s  %6s  %6s  %12s\n", "index", "ast id", "argc", "commands");
   for (int i = 0; i < deopt_count; i++) {
-    int command_count = 0;
     PrintF(out, "%6d  %6d  %6d",
            i, AstId(i)->value(), ArgumentsStackHeight(i)->value());
+
+    if (!FLAG_print_code_verbose) continue;
+    // Print details of the frame translation.
     int translation_index = TranslationIndex(i)->value();
     TranslationIterator iterator(TranslationByteArray(), translation_index);
     Translation::Opcode opcode =
         static_cast<Translation::Opcode>(iterator.Next());
     ASSERT(Translation::BEGIN == opcode);
     int frame_count = iterator.Next();
-    if (FLAG_print_code_verbose) {
-      PrintF(out, "  %s {count=%d}\n", Translation::StringFor(opcode),
-             frame_count);
-    }
+    PrintF(out, "  %s {count=%d}\n", Translation::StringFor(opcode),
+           frame_count);
 
-    for (int i = 0; i < frame_count; ++i) {
-      opcode = static_cast<Translation::Opcode>(iterator.Next());
-      ASSERT(Translation::FRAME == opcode);
-      int ast_id = iterator.Next();
-      int function_id = iterator.Next();
-      JSFunction* function =
-          JSFunction::cast(LiteralArray()->get(function_id));
-      unsigned height = iterator.Next();
-      if (FLAG_print_code_verbose) {
-        PrintF(out, "%24s  %s {ast_id=%d, function=",
-               "", Translation::StringFor(opcode), ast_id);
-        function->PrintName(out);
-        PrintF(out, ", height=%u}\n", height);
+    while (iterator.HasNext() &&
+           Translation::BEGIN !=
+           (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
+      PrintF(out, "%24s    %s ", "", Translation::StringFor(opcode));
+
+      switch (opcode) {
+        case Translation::BEGIN:
+          UNREACHABLE();
+          break;
+
+        case Translation::FRAME: {
+          int ast_id = iterator.Next();
+          int function_id = iterator.Next();
+          JSFunction* function =
+              JSFunction::cast(LiteralArray()->get(function_id));
+          unsigned height = iterator.Next();
+          PrintF(out, "{ast_id=%d, \nfunction=", ast_id);
+          function->PrintName(out);
+          PrintF(out, ", height=%u}", height);
+          break;
+        }
+
+        case Translation::DUPLICATE:
+          break;
+
+        case Translation::REGISTER: {
+          int reg_code = iterator.Next();
+            PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
+          break;
+        }
+
+        case Translation::INT32_REGISTER: {
+          int reg_code = iterator.Next();
+          PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
+          break;
+        }
+
+        case Translation::DOUBLE_REGISTER: {
+          int reg_code = iterator.Next();
+          PrintF(out, "{input=%s}",
+                 DoubleRegister::AllocationIndexToString(reg_code));
+          break;
+        }
+
+        case Translation::STACK_SLOT: {
+          int input_slot_index = iterator.Next();
+          PrintF(out, "{input=%d}", input_slot_index);
+          break;
+        }
+
+        case Translation::INT32_STACK_SLOT: {
+          int input_slot_index = iterator.Next();
+          PrintF(out, "{input=%d}", input_slot_index);
+          break;
+        }
+
+        case Translation::DOUBLE_STACK_SLOT: {
+          int input_slot_index = iterator.Next();
+          PrintF(out, "{input=%d}", input_slot_index);
+          break;
+        }
+
+        case Translation::LITERAL: {
+          unsigned literal_index = iterator.Next();
+          PrintF(out, "{literal_id=%u}", literal_index);
+          break;
+        }
+
+        case Translation::ARGUMENTS_OBJECT:
+          break;
       }
-
-      // Size of translation is height plus all incoming arguments including
-      // receiver.
-      int size = height + function->shared()->formal_parameter_count() + 1;
-      command_count += size;
-      for (int j = 0; j < size; ++j) {
-        opcode = static_cast<Translation::Opcode>(iterator.Next());
-        if (FLAG_print_code_verbose) {
-          PrintF(out, "%24s    %s ", "", Translation::StringFor(opcode));
-        }
-
-        if (opcode == Translation::DUPLICATE) {
-          opcode = static_cast<Translation::Opcode>(iterator.Next());
-          if (FLAG_print_code_verbose) {
-            PrintF(out, "%s ", Translation::StringFor(opcode));
-          }
-          --j;  // Two commands share the same frame index.
-        }
-
-        switch (opcode) {
-          case Translation::BEGIN:
-          case Translation::FRAME:
-          case Translation::DUPLICATE:
-            UNREACHABLE();
-            break;
-
-          case Translation::REGISTER: {
-            int reg_code = iterator.Next();
-            if (FLAG_print_code_verbose)  {
-              PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
-            }
-            break;
-          }
-
-          case Translation::INT32_REGISTER: {
-            int reg_code = iterator.Next();
-            if (FLAG_print_code_verbose)  {
-              PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
-            }
-            break;
-          }
-
-          case Translation::DOUBLE_REGISTER: {
-            int reg_code = iterator.Next();
-            if (FLAG_print_code_verbose)  {
-              PrintF(out, "{input=%s}",
-                     DoubleRegister::AllocationIndexToString(reg_code));
-            }
-            break;
-          }
-
-          case Translation::STACK_SLOT: {
-            int input_slot_index = iterator.Next();
-            if (FLAG_print_code_verbose)  {
-              PrintF(out, "{input=%d}", input_slot_index);
-            }
-            break;
-          }
-
-          case Translation::INT32_STACK_SLOT: {
-            int input_slot_index = iterator.Next();
-            if (FLAG_print_code_verbose)  {
-              PrintF(out, "{input=%d}", input_slot_index);
-            }
-            break;
-          }
-
-          case Translation::DOUBLE_STACK_SLOT: {
-            int input_slot_index = iterator.Next();
-            if (FLAG_print_code_verbose)  {
-              PrintF(out, "{input=%d}", input_slot_index);
-            }
-            break;
-          }
-
-          case Translation::LITERAL: {
-            unsigned literal_index = iterator.Next();
-            if (FLAG_print_code_verbose)  {
-              PrintF(out, "{literal_id=%u}", literal_index);
-            }
-            break;
-          }
-
-          case Translation::ARGUMENTS_OBJECT:
-            break;
-        }
-        if (FLAG_print_code_verbose) PrintF(out, "\n");
-      }
+      PrintF(out, "\n");
     }
-    if (!FLAG_print_code_verbose) PrintF(out, "  %12d\n", command_count);
   }
 }
 
@@ -7602,7 +7326,8 @@
           // exceed the capacity of new space, and we would fail repeatedly
           // trying to convert the FixedDoubleArray.
           MaybeObject* maybe_value_object =
-              GetHeap()->AllocateHeapNumber(old_elements->get(i), TENURED);
+              GetHeap()->AllocateHeapNumber(old_elements->get_scalar(i),
+                                            TENURED);
           if (!maybe_value_object->ToObject(&obj)) return maybe_value_object;
           // Force write barrier. It's not worth trying to exploit
           // elems->GetWriteBarrierMode(), since it requires an
@@ -8945,71 +8670,6 @@
 }
 
 
-MaybeObject* JSObject::GetElementPostInterceptor(Object* receiver,
-                                                 uint32_t index) {
-  // Get element works for both JSObject and JSArray since
-  // JSArray::length cannot change.
-  switch (GetElementsKind()) {
-    case FAST_ELEMENTS: {
-      FixedArray* elms = FixedArray::cast(elements());
-      if (index < static_cast<uint32_t>(elms->length())) {
-        Object* value = elms->get(index);
-        if (!value->IsTheHole()) return value;
-      }
-      break;
-    }
-    case FAST_DOUBLE_ELEMENTS: {
-      FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
-      if (index < static_cast<uint32_t>(elms->length())) {
-        if (!elms->is_the_hole(index)) {
-          return GetHeap()->NumberFromDouble(elms->get(index));
-        }
-      }
-      break;
-    }
-    case EXTERNAL_PIXEL_ELEMENTS:
-    case EXTERNAL_BYTE_ELEMENTS:
-    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
-    case EXTERNAL_SHORT_ELEMENTS:
-    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
-    case EXTERNAL_INT_ELEMENTS:
-    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
-    case EXTERNAL_FLOAT_ELEMENTS:
-    case EXTERNAL_DOUBLE_ELEMENTS: {
-      MaybeObject* maybe_value = GetExternalElement(index);
-      Object* value;
-      if (!maybe_value->ToObject(&value)) return maybe_value;
-      if (!value->IsUndefined()) return value;
-      break;
-    }
-    case DICTIONARY_ELEMENTS: {
-      NumberDictionary* dictionary = element_dictionary();
-      int entry = dictionary->FindEntry(index);
-      if (entry != NumberDictionary::kNotFound) {
-        Object* element = dictionary->ValueAt(entry);
-        PropertyDetails details = dictionary->DetailsAt(entry);
-        if (details.type() == CALLBACKS) {
-          return GetElementWithCallback(receiver,
-                                        element,
-                                        index,
-                                        this);
-        }
-        return element;
-      }
-      break;
-    }
-    case NON_STRICT_ARGUMENTS_ELEMENTS:
-      UNIMPLEMENTED();
-      break;
-  }
-
-  // Continue searching via the prototype chain.
-  Object* pt = GetPrototype();
-  if (pt->IsNull()) return GetHeap()->undefined_value();
-  return pt->GetElementWithReceiver(receiver, index);
-}
-
-
 MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver,
                                                  uint32_t index) {
   Isolate* isolate = GetIsolate();
@@ -9037,212 +8697,18 @@
     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
   }
 
-  MaybeObject* raw_result =
-      holder_handle->GetElementPostInterceptor(*this_handle, index);
+  Heap* heap = holder_handle->GetHeap();
+  ElementsAccessor* handler = holder_handle->GetElementsAccessor();
+  MaybeObject* raw_result = handler->GetWithReceiver(*holder_handle,
+                                                     *this_handle,
+                                                     index);
+  if (raw_result != heap->the_hole_value()) return raw_result;
+
   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
-  return raw_result;
-}
 
-
-MaybeObject* JSObject::GetElementWithReceiver(Object* receiver,
-                                              uint32_t index) {
-  // Check access rights if needed.
-  if (IsAccessCheckNeeded()) {
-    Heap* heap = GetHeap();
-    if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_GET)) {
-      heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET);
-      return heap->undefined_value();
-    }
-  }
-
-  if (HasIndexedInterceptor()) {
-    return GetElementWithInterceptor(receiver, index);
-  }
-
-  // Get element works for both JSObject and JSArray since
-  // JSArray::length cannot change.
-  switch (GetElementsKind()) {
-    case FAST_ELEMENTS: {
-      FixedArray* elms = FixedArray::cast(elements());
-      if (index < static_cast<uint32_t>(elms->length())) {
-        Object* value = elms->get(index);
-        if (!value->IsTheHole()) return value;
-      }
-      break;
-    }
-    case FAST_DOUBLE_ELEMENTS: {
-      FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
-      if (index < static_cast<uint32_t>(elms->length())) {
-        if (!elms->is_the_hole(index)) {
-          double double_value = elms->get(index);
-          return GetHeap()->NumberFromDouble(double_value);
-        }
-      }
-      break;
-    }
-    case EXTERNAL_PIXEL_ELEMENTS:
-    case EXTERNAL_BYTE_ELEMENTS:
-    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
-    case EXTERNAL_SHORT_ELEMENTS:
-    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
-    case EXTERNAL_INT_ELEMENTS:
-    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
-    case EXTERNAL_FLOAT_ELEMENTS:
-    case EXTERNAL_DOUBLE_ELEMENTS: {
-      MaybeObject* maybe_value = GetExternalElement(index);
-      Object* value;
-      if (!maybe_value->ToObject(&value)) return maybe_value;
-      if (!value->IsUndefined()) return value;
-      break;
-    }
-    case DICTIONARY_ELEMENTS: {
-      NumberDictionary* dictionary = element_dictionary();
-      int entry = dictionary->FindEntry(index);
-      if (entry != NumberDictionary::kNotFound) {
-        Object* element = dictionary->ValueAt(entry);
-        PropertyDetails details = dictionary->DetailsAt(entry);
-        if (details.type() == CALLBACKS) {
-          return GetElementWithCallback(receiver,
-                                        element,
-                                        index,
-                                        this);
-        }
-        return element;
-      }
-      break;
-    }
-    case NON_STRICT_ARGUMENTS_ELEMENTS: {
-      FixedArray* parameter_map = FixedArray::cast(elements());
-      uint32_t length = parameter_map->length();
-      Object* probe =
-          (index < length - 2) ? parameter_map->get(index + 2) : NULL;
-      if (probe != NULL && !probe->IsTheHole()) {
-        Context* context = Context::cast(parameter_map->get(0));
-        int context_index = Smi::cast(probe)->value();
-        ASSERT(!context->get(context_index)->IsTheHole());
-        return context->get(context_index);
-      } else {
-        // Object is not mapped, defer to the arguments.
-        FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
-        if (arguments->IsDictionary()) {
-          NumberDictionary* dictionary = NumberDictionary::cast(arguments);
-          int entry = dictionary->FindEntry(index);
-          if (entry != NumberDictionary::kNotFound) {
-            Object* element = dictionary->ValueAt(entry);
-            PropertyDetails details = dictionary->DetailsAt(entry);
-            if (details.type() == CALLBACKS) {
-              return GetElementWithCallback(receiver,
-                                            element,
-                                            index,
-                                            this);
-            }
-            return element;
-          }
-        } else if (index < static_cast<uint32_t>(arguments->length())) {
-          Object* value = arguments->get(index);
-          if (!value->IsTheHole()) return value;
-        }
-      }
-      break;
-    }
-  }
-
-  Object* pt = GetPrototype();
-  Heap* heap = GetHeap();
+  Object* pt = holder_handle->GetPrototype();
   if (pt == heap->null_value()) return heap->undefined_value();
-  return pt->GetElementWithReceiver(receiver, index);
-}
-
-
-MaybeObject* JSObject::GetExternalElement(uint32_t index) {
-  // Get element works for both JSObject and JSArray since
-  // JSArray::length cannot change.
-  switch (GetElementsKind()) {
-    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);
-      }
-      break;
-    }
-    case EXTERNAL_BYTE_ELEMENTS: {
-      ExternalByteArray* array = ExternalByteArray::cast(elements());
-      if (index < static_cast<uint32_t>(array->length())) {
-        int8_t value = array->get(index);
-        return Smi::FromInt(value);
-      }
-      break;
-    }
-    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
-      ExternalUnsignedByteArray* array =
-          ExternalUnsignedByteArray::cast(elements());
-      if (index < static_cast<uint32_t>(array->length())) {
-        uint8_t value = array->get(index);
-        return Smi::FromInt(value);
-      }
-      break;
-    }
-    case EXTERNAL_SHORT_ELEMENTS: {
-      ExternalShortArray* array = ExternalShortArray::cast(elements());
-      if (index < static_cast<uint32_t>(array->length())) {
-        int16_t value = array->get(index);
-        return Smi::FromInt(value);
-      }
-      break;
-    }
-    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
-      ExternalUnsignedShortArray* array =
-          ExternalUnsignedShortArray::cast(elements());
-      if (index < static_cast<uint32_t>(array->length())) {
-        uint16_t value = array->get(index);
-        return Smi::FromInt(value);
-      }
-      break;
-    }
-    case EXTERNAL_INT_ELEMENTS: {
-      ExternalIntArray* array = ExternalIntArray::cast(elements());
-      if (index < static_cast<uint32_t>(array->length())) {
-        int32_t value = array->get(index);
-        return GetHeap()->NumberFromInt32(value);
-      }
-      break;
-    }
-    case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
-      ExternalUnsignedIntArray* array =
-          ExternalUnsignedIntArray::cast(elements());
-      if (index < static_cast<uint32_t>(array->length())) {
-        uint32_t value = array->get(index);
-        return GetHeap()->NumberFromUint32(value);
-      }
-      break;
-    }
-    case EXTERNAL_FLOAT_ELEMENTS: {
-      ExternalFloatArray* array = ExternalFloatArray::cast(elements());
-      if (index < static_cast<uint32_t>(array->length())) {
-        float value = array->get(index);
-        return GetHeap()->AllocateHeapNumber(value);
-      }
-      break;
-    }
-    case EXTERNAL_DOUBLE_ELEMENTS: {
-      ExternalDoubleArray* array = ExternalDoubleArray::cast(elements());
-      if (index < static_cast<uint32_t>(array->length())) {
-        double value = array->get(index);
-        return GetHeap()->AllocateHeapNumber(value);
-      }
-      break;
-    }
-    case FAST_DOUBLE_ELEMENTS:
-    case FAST_ELEMENTS:
-    case DICTIONARY_ELEMENTS:
-      UNREACHABLE();
-      break;
-    case NON_STRICT_ARGUMENTS_ELEMENTS:
-      UNIMPLEMENTED();
-      break;
-  }
-  return GetHeap()->undefined_value();
+  return pt->GetElementWithReceiver(*this_handle, index);
 }
 
 
@@ -9756,7 +9222,9 @@
     }
     ASSERT(storage->length() >= index);
   } else {
-    property_dictionary()->CopyKeysTo(storage, StringDictionary::UNSORTED);
+    property_dictionary()->CopyKeysTo(storage,
+                                      index,
+                                      StringDictionary::UNSORTED);
   }
 }
 
@@ -10505,6 +9973,7 @@
 
 template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo(
     FixedArray*,
+    int,
     Dictionary<StringDictionaryShape, String*>::SortMode);
 
 template int
@@ -10728,7 +10197,7 @@
         if (elements->is_the_hole(holes)) {
           holes--;
         } else {
-          elements->set(i, elements->get(holes));
+          elements->set(i, elements->get_scalar(holes));
           break;
         }
       }
@@ -11634,11 +11103,11 @@
 template<typename Shape, typename Key>
 void Dictionary<Shape, Key>::CopyKeysTo(
     FixedArray* storage,
+    int index,
     typename Dictionary<Shape, Key>::SortMode sort_mode) {
   ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
       static_cast<PropertyAttributes>(NONE)));
   int capacity = HashTable<Shape, Key>::Capacity();
-  int index = 0;
   for (int i = 0; i < capacity; i++) {
     Object* k = HashTable<Shape, Key>::KeyAt(i);
     if (HashTable<Shape, Key>::IsKey(k)) {
@@ -11859,10 +11328,9 @@
 }
 
 
-void ObjectHashTable::RemoveEntry(int entry) {
-  Object* null_value = GetHeap()->null_value();
-  set(EntryToIndex(entry), null_value);
-  set(EntryToIndex(entry) + 1, null_value);
+void ObjectHashTable::RemoveEntry(int entry, Heap* heap) {
+  set_null(heap, EntryToIndex(entry));
+  set_null(heap, EntryToIndex(entry) + 1);
   ElementRemoved();
 }
 
@@ -12093,7 +11561,7 @@
     Handle<Object> break_point_object) {
   // No break point.
   if (break_point_info->break_point_objects()->IsUndefined()) return false;
-  // Single beak point.
+  // Single break point.
   if (!break_point_info->break_point_objects()->IsFixedArray()) {
     return break_point_info->break_point_objects() == *break_point_object;
   }
@@ -12112,7 +11580,7 @@
 int BreakPointInfo::GetBreakPointCount() {
   // No break point.
   if (break_point_objects()->IsUndefined()) return 0;
-  // Single beak point.
+  // Single break point.
   if (!break_point_objects()->IsFixedArray()) return 1;
   // Multiple break points.
   return FixedArray::cast(break_point_objects())->length();
diff --git a/src/objects.h b/src/objects.h
index ba690ec..ff13aed 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -51,6 +51,7 @@
 //       - JSReceiver  (suitable for property access)
 //         - JSObject
 //           - JSArray
+//           - JSWeakMap
 //           - JSRegExp
 //           - JSFunction
 //           - GlobalObject
@@ -71,17 +72,19 @@
 //         - ExternalIntArray
 //         - ExternalUnsignedIntArray
 //         - ExternalFloatArray
-//       - FixedArray
-//         - DescriptorArray
-//         - HashTable
-//           - Dictionary
-//           - SymbolTable
-//           - CompilationCacheTable
-//           - CodeCacheHashTable
-//           - MapCache
-//         - Context
-//         - JSFunctionResultCache
-//         - SerializedScopeInfo
+//       - FixedArrayBase
+//         - FixedArray
+//           - DescriptorArray
+//           - HashTable
+//             - Dictionary
+//             - SymbolTable
+//             - CompilationCacheTable
+//             - CodeCacheHashTable
+//             - MapCache
+//           - Context
+//           - JSFunctionResultCache
+//           - SerializedScopeInfo
+//         - FixedDoubleArray
 //       - String
 //         - SeqString
 //           - SeqAsciiString
@@ -331,6 +334,7 @@
   V(JS_GLOBAL_PROXY_TYPE)                                                      \
   V(JS_ARRAY_TYPE)                                                             \
   V(JS_PROXY_TYPE)                                                             \
+  V(JS_WEAK_MAP_TYPE)                                                          \
   V(JS_REGEXP_TYPE)                                                            \
                                                                                \
   V(JS_FUNCTION_TYPE)                                                          \
@@ -568,6 +572,7 @@
   JS_GLOBAL_PROXY_TYPE,
   JS_ARRAY_TYPE,
   JS_PROXY_TYPE,
+  JS_WEAK_MAP_TYPE,
 
   JS_REGEXP_TYPE,  // LAST_NONCALLABLE_SPEC_OBJECT_TYPE
 
@@ -630,8 +635,10 @@
                          WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \
 
 
+class ElementsAccessor;
 class StringStream;
 class ObjectVisitor;
+class DictionaryElementsAccessor;
 
 struct ValueInfo : public Malloced {
   ValueInfo() : type(FIRST_TYPE), ptr(NULL), str(NULL), number(0) { }
@@ -748,6 +755,7 @@
   V(JSArray)                                   \
   V(JSProxy)                                   \
   V(JSFunctionProxy)                           \
+  V(JSWeakMap)                                 \
   V(JSRegExp)                                  \
   V(HashTable)                                 \
   V(Dictionary)                                \
@@ -1488,6 +1496,7 @@
   inline void initialize_elements();
   MUST_USE_RESULT inline MaybeObject* ResetElements();
   inline ElementsKind GetElementsKind();
+  inline ElementsAccessor* GetElementsAccessor();
   inline bool HasFastElements();
   inline bool HasFastDoubleElements();
   inline bool HasDictionaryElements();
@@ -1730,14 +1739,8 @@
 
   // Returns the index'th element.
   // The undefined object if index is out of bounds.
-  MaybeObject* GetElementWithReceiver(Object* receiver, uint32_t index);
   MaybeObject* GetElementWithInterceptor(Object* receiver, uint32_t index);
 
-  // Get external element value at index if there is one and undefined
-  // otherwise. Can return a failure if allocation of a heap number
-  // failed.
-  MaybeObject* GetExternalElement(uint32_t index);
-
   // Replace the elements' backing store with fast elements of the given
   // capacity.  Update the length for JSArrays.  Returns the new backing
   // store.
@@ -2001,6 +2004,8 @@
   };
 
  private:
+  friend class DictionaryElementsAccessor;
+
   MUST_USE_RESULT MaybeObject* GetElementWithCallback(Object* receiver,
                                                       Object* structure,
                                                       uint32_t index,
@@ -2021,14 +2026,10 @@
       StrictModeFlag strict_mode,
       bool check_prototype);
 
-  MaybeObject* GetElementPostInterceptor(Object* receiver, uint32_t index);
-
   MUST_USE_RESULT MaybeObject* DeletePropertyPostInterceptor(String* name,
                                                              DeleteMode mode);
   MUST_USE_RESULT MaybeObject* DeletePropertyWithInterceptor(String* name);
 
-  MUST_USE_RESULT MaybeObject* DeleteElementPostInterceptor(uint32_t index,
-                                                            DeleteMode mode);
   MUST_USE_RESULT MaybeObject* DeleteElementWithInterceptor(uint32_t index);
 
   MUST_USE_RESULT MaybeObject* DeleteFastElement(uint32_t index);
@@ -2092,6 +2093,7 @@
   inline Object* get(int index);
   // Setter that uses write barrier.
   inline void set(int index, Object* value);
+  inline bool is_the_hole(int index);
 
   // Setter that doesn't need write barrier).
   inline void set(int index, Smi* value);
@@ -2126,10 +2128,6 @@
   // Compute the union of this and other.
   MUST_USE_RESULT MaybeObject* UnionOfKeys(FixedArray* other);
 
-  // Compute the union of this and other.
-  MUST_USE_RESULT MaybeObject* UnionOfDoubleKeys(
-      FixedDoubleArray* other);
-
   // Copy a sub array from the receiver to dest.
   void CopyTo(int pos, FixedArray* dest, int dest_pos, int len);
 
@@ -2197,7 +2195,8 @@
   inline void Initialize(NumberDictionary* from);
 
   // Setter and getter for elements.
-  inline double get(int index);
+  inline double get_scalar(int index);
+  inline MaybeObject* get(int index);
   inline void set(int index, double value);
   inline void set_the_hole(int index);
 
@@ -2805,7 +2804,7 @@
                   PropertyAttributes filter,
                   SortMode sort_mode);
   // Fill in details for properties into storage.
-  void CopyKeysTo(FixedArray* storage, SortMode sort_mode);
+  void CopyKeysTo(FixedArray* storage, int index, SortMode sort_mode);
 
   // Accessors for next enumeration index.
   void SetNextEnumerationIndex(int index) {
@@ -2979,8 +2978,16 @@
   MUST_USE_RESULT MaybeObject* Put(JSObject* key, Object* value);
 
  private:
+  friend class MarkCompactCollector;
+
   void AddEntry(int entry, JSObject* key, Object* value);
-  void RemoveEntry(int entry);
+  void RemoveEntry(int entry, Heap* heap);
+  inline void RemoveEntry(int entry);
+
+  // Returns the index to the value of an entry.
+  static inline int EntryToValueIndex(int entry) {
+    return EntryToIndex(entry) + 1;
+  }
 };
 
 
@@ -3129,6 +3136,8 @@
   inline int length();
   inline void set_length(int value);
 
+  inline bool is_the_hole(int index) { return false; }
+
   // [external_pointer]: The pointer to the external memory area backing this
   // external array.
   DECL_ACCESSORS(external_pointer, void)  // Pointer to the data store.
@@ -3164,7 +3173,8 @@
   inline uint8_t* external_pixel_pointer();
 
   // Setter and getter.
-  inline uint8_t get(int index);
+  inline uint8_t get_scalar(int index);
+  inline MaybeObject* get(int index);
   inline void set(int index, uint8_t value);
 
   // This accessor applies the correct conversion from Smi, HeapNumber and
@@ -3192,7 +3202,8 @@
 class ExternalByteArray: public ExternalArray {
  public:
   // Setter and getter.
-  inline int8_t get(int index);
+  inline int8_t get_scalar(int index);
+  inline MaybeObject* get(int index);
   inline void set(int index, int8_t value);
 
   // This accessor applies the correct conversion from Smi, HeapNumber
@@ -3220,7 +3231,8 @@
 class ExternalUnsignedByteArray: public ExternalArray {
  public:
   // Setter and getter.
-  inline uint8_t get(int index);
+  inline uint8_t get_scalar(int index);
+  inline MaybeObject* get(int index);
   inline void set(int index, uint8_t value);
 
   // This accessor applies the correct conversion from Smi, HeapNumber
@@ -3248,7 +3260,8 @@
 class ExternalShortArray: public ExternalArray {
  public:
   // Setter and getter.
-  inline int16_t get(int index);
+  inline int16_t get_scalar(int index);
+  inline MaybeObject* get(int index);
   inline void set(int index, int16_t value);
 
   // This accessor applies the correct conversion from Smi, HeapNumber
@@ -3276,7 +3289,8 @@
 class ExternalUnsignedShortArray: public ExternalArray {
  public:
   // Setter and getter.
-  inline uint16_t get(int index);
+  inline uint16_t get_scalar(int index);
+  inline MaybeObject* get(int index);
   inline void set(int index, uint16_t value);
 
   // This accessor applies the correct conversion from Smi, HeapNumber
@@ -3304,7 +3318,8 @@
 class ExternalIntArray: public ExternalArray {
  public:
   // Setter and getter.
-  inline int32_t get(int index);
+  inline int32_t get_scalar(int index);
+  inline MaybeObject* get(int index);
   inline void set(int index, int32_t value);
 
   // This accessor applies the correct conversion from Smi, HeapNumber
@@ -3332,7 +3347,8 @@
 class ExternalUnsignedIntArray: public ExternalArray {
  public:
   // Setter and getter.
-  inline uint32_t get(int index);
+  inline uint32_t get_scalar(int index);
+  inline MaybeObject* get(int index);
   inline void set(int index, uint32_t value);
 
   // This accessor applies the correct conversion from Smi, HeapNumber
@@ -3360,7 +3376,8 @@
 class ExternalFloatArray: public ExternalArray {
  public:
   // Setter and getter.
-  inline float get(int index);
+  inline float get_scalar(int index);
+  inline MaybeObject* get(int index);
   inline void set(int index, float value);
 
   // This accessor applies the correct conversion from Smi, HeapNumber
@@ -3388,7 +3405,8 @@
 class ExternalDoubleArray: public ExternalArray {
  public:
   // Setter and getter.
-  inline double get(int index);
+  inline double get_scalar(int index);
+  inline MaybeObject* get(int index);
   inline void set(int index, double value);
 
   // This accessor applies the correct conversion from Smi, HeapNumber
@@ -4644,12 +4662,10 @@
   inline void set_end_position(int end_position);
 
   // Is this function a function expression in the source code.
-  inline bool is_expression();
-  inline void set_is_expression(bool value);
+  DECL_BOOLEAN_ACCESSORS(is_expression)
 
   // Is this function a top-level function (scripts, evals).
-  inline bool is_toplevel();
-  inline void set_is_toplevel(bool value);
+  DECL_BOOLEAN_ACCESSORS(is_toplevel)
 
   // Bit field containing various information collected by the compiler to
   // drive optimization.
@@ -4705,13 +4721,21 @@
   // These needs special threatment in .call and .apply since
   // null passed as the receiver should not be translated to the
   // global object.
-  inline bool native();
-  inline void set_native(bool value);
+  DECL_BOOLEAN_ACCESSORS(native)
+
+  // Indicates that the function was created by the Function function.
+  // Though it's anonymous, toString should treat it as if it had the name
+  // "anonymous".  We don't set the name itself so that the system does not
+  // see a binding for it.
+  DECL_BOOLEAN_ACCESSORS(name_should_print_as_anonymous)
 
   // Indicates whether the function is a bound function created using
   // the bind function.
-  inline bool bound();
-  inline void set_bound(bool value);
+  DECL_BOOLEAN_ACCESSORS(bound)
+
+  // Indicates that the function is anonymous (the name field can be set
+  // through the API, which does not change this flag).
+  DECL_BOOLEAN_ACCESSORS(is_anonymous)
 
   // Indicates whether or not the code in the shared function support
   // deoptimization.
@@ -4893,7 +4917,6 @@
   // Bit positions in compiler_hints.
   static const int kCodeAgeSize = 3;
   static const int kCodeAgeMask = (1 << kCodeAgeSize) - 1;
-  static const int kBoundFunction = 9;
 
   enum CompilerHints {
     kHasOnlySimpleThisPropertyAssignments,
@@ -4904,7 +4927,11 @@
     kStrictModeFunction,
     kUsesArguments,
     kHasDuplicateParameters,
-    kNative
+    kNative,
+    kBoundFunction,
+    kIsAnonymous,
+    kNameShouldPrintAsAnonymous,
+    kCompilerHintsCount  // Pseudo entry
   };
 
  private:
@@ -4918,6 +4945,9 @@
   static const int kCompilerHintsSize = kIntSize;
 #endif
 
+  STATIC_ASSERT(SharedFunctionInfo::kCompilerHintsCount <=
+                SharedFunctionInfo::kCompilerHintsSize * kBitsPerByte);
+
  public:
   // Constants for optimizing codegen for strict mode function and
   // native tests.
@@ -6620,6 +6650,40 @@
 };
 
 
+// The JSWeakMap describes EcmaScript Harmony weak maps
+class JSWeakMap: public JSObject {
+ public:
+  // [table]: the backing hash table mapping keys to values.
+  DECL_ACCESSORS(table, ObjectHashTable)
+
+  // [next]: linked list of encountered weak maps during GC.
+  DECL_ACCESSORS(next, Object)
+
+  // Unchecked accessors to be used during GC.
+  inline ObjectHashTable* unchecked_table();
+
+  // Casting.
+  static inline JSWeakMap* cast(Object* obj);
+
+#ifdef OBJECT_PRINT
+  inline void JSWeakMapPrint() {
+    JSWeakMapPrint(stdout);
+  }
+  void JSWeakMapPrint(FILE* out);
+#endif
+#ifdef DEBUG
+  void JSWeakMapVerify();
+#endif
+
+  static const int kTableOffset = JSObject::kHeaderSize;
+  static const int kNextOffset = kTableOffset + kPointerSize;
+  static const int kSize = kNextOffset + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakMap);
+};
+
+
 // Foreign describes objects pointing from JavaScript to C structures.
 // Since they cannot contain references to JS HeapObjects they can be
 // placed in old_data_space.
diff --git a/src/parser.cc b/src/parser.cc
index ed6ff49..f32e917 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -659,8 +659,8 @@
           0,
           0,
           source->length(),
-          false,
-          false);
+          FunctionLiteral::ANONYMOUS_EXPRESSION,
+          false);  // Does not have duplicate parameters.
     } else if (stack_overflow_) {
       isolate()->StackOverflow();
     }
@@ -729,12 +729,17 @@
       top_scope_->EnableStrictMode();
     }
 
-    FunctionLiteralType type =
-        shared_info->is_expression() ? EXPRESSION : DECLARATION;
+    FunctionLiteral::Type type = shared_info->is_expression()
+        ? (shared_info->is_anonymous()
+              ? FunctionLiteral::ANONYMOUS_EXPRESSION
+              : FunctionLiteral::NAMED_EXPRESSION)
+        : FunctionLiteral::DECLARATION;
     bool ok = true;
     result = ParseFunctionLiteral(name,
-                                  false,    // Strict mode name already checked.
-                                  RelocInfo::kNoPosition, type, &ok);
+                                  false,  // Strict mode name already checked.
+                                  RelocInfo::kNoPosition,
+                                  type,
+                                  &ok);
     // Make sure the results agree.
     ASSERT(ok == (result != NULL));
   }
@@ -1471,7 +1476,7 @@
   FunctionLiteral* fun = ParseFunctionLiteral(name,
                                               is_strict_reserved,
                                               function_token_position,
-                                              DECLARATION,
+                                              FunctionLiteral::DECLARATION,
                                               CHECK_OK);
   // Even if we're not at the top-level of the global or a function
   // scope, we treat is as such and introduce the function with it's
@@ -2842,8 +2847,14 @@
       name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
                                                  CHECK_OK);
     }
-    result = ParseFunctionLiteral(name, is_strict_reserved_name,
-                                  function_token_position, NESTED, CHECK_OK);
+    FunctionLiteral::Type type = name.is_null()
+        ? FunctionLiteral::ANONYMOUS_EXPRESSION
+        : FunctionLiteral::NAMED_EXPRESSION;
+    result = ParseFunctionLiteral(name,
+                                  is_strict_reserved_name,
+                                  function_token_position,
+                                  type,
+                                  CHECK_OK);
   } else {
     result = ParsePrimaryExpression(CHECK_OK);
   }
@@ -3412,7 +3423,7 @@
         ParseFunctionLiteral(name,
                              false,   // reserved words are allowed here
                              RelocInfo::kNoPosition,
-                             DECLARATION,
+                             FunctionLiteral::ANONYMOUS_EXPRESSION,
                              CHECK_OK);
     // Allow any number of parameters for compatiabilty with JSC.
     // Specification only allows zero parameters for get and one for set.
@@ -3619,30 +3630,27 @@
 }
 
 
-FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
+FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
                                               bool name_is_strict_reserved,
                                               int function_token_position,
-                                              FunctionLiteralType type,
+                                              FunctionLiteral::Type type,
                                               bool* ok) {
   // Function ::
   //   '(' FormalParameterList? ')' '{' FunctionBody '}'
-  bool is_named = !var_name.is_null();
 
-  // The name associated with this function. If it's a function expression,
-  // this is the actual function name, otherwise this is the name of the
-  // variable declared and initialized with the function (expression). In
-  // that case, we don't have a function name (it's empty).
-  Handle<String> name =
-      is_named ? var_name : isolate()->factory()->empty_symbol();
-  // The function name, if any.
-  Handle<String> function_name = isolate()->factory()->empty_symbol();
-  if (is_named && (type == EXPRESSION || type == NESTED)) {
-    function_name = name;
+  // Anonymous functions were passed either the empty symbol or a null
+  // handle as the function name.  Remember if we were passed a non-empty
+  // handle to decide whether to invoke function name inference.
+  bool should_infer_name = function_name.is_null();
+
+  // We want a non-null handle as the function name.
+  if (should_infer_name) {
+    function_name = isolate()->factory()->empty_symbol();
   }
 
   int num_parameters = 0;
   // Function declarations are hoisted.
-  Scope* scope = (type == DECLARATION)
+  Scope* scope = (type == FunctionLiteral::DECLARATION)
       ? NewScope(top_scope_->DeclarationScope(), Scope::FUNCTION_SCOPE, false)
       : NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
   ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8);
@@ -3655,7 +3663,7 @@
   bool has_duplicate_parameters = false;
   // Parse function body.
   { LexicalScope lexical_scope(this, scope, isolate());
-    top_scope_->SetScopeName(name);
+    top_scope_->SetScopeName(function_name);
 
     //  FormalParameterList ::
     //    '(' (Identifier)*[','] ')'
@@ -3705,7 +3713,7 @@
     // NOTE: We create a proxy and resolve it here so that in the
     // future we can change the AST to only refer to VariableProxies
     // instead of Variables and Proxis as is the case now.
-    if (!function_name.is_null() && function_name->length() > 0) {
+    if (type == FunctionLiteral::NAMED_EXPRESSION) {
       Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
       VariableProxy* fproxy =
           top_scope_->NewUnresolved(function_name, inside_with());
@@ -3739,7 +3747,7 @@
         end_pos = entry.end_pos();
         if (end_pos <= function_block_pos) {
           // End position greater than end of stream is safe, and hard to check.
-          ReportInvalidPreparseData(name, CHECK_OK);
+          ReportInvalidPreparseData(function_name, CHECK_OK);
         }
         isolate()->counters()->total_preparse_skipped()->Increment(
             end_pos - function_block_pos);
@@ -3769,7 +3777,7 @@
 
     // Validate strict mode.
     if (top_scope_->is_strict_mode()) {
-      if (IsEvalOrArguments(name)) {
+      if (IsEvalOrArguments(function_name)) {
         int position = function_token_position != RelocInfo::kNoPosition
             ? function_token_position
             : (start_pos > 0 ? start_pos - 1 : start_pos);
@@ -3813,7 +3821,7 @@
 
   FunctionLiteral* function_literal =
       new(zone()) FunctionLiteral(isolate(),
-                                  name,
+                                  function_name,
                                   scope,
                                   body,
                                   materialized_literal_count,
@@ -3823,11 +3831,11 @@
                                   num_parameters,
                                   start_pos,
                                   end_pos,
-                                  (function_name->length() > 0),
+                                  type,
                                   has_duplicate_parameters);
   function_literal->set_function_token_position(function_token_position);
 
-  if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal);
+  if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
   return function_literal;
 }
 
diff --git a/src/parser.h b/src/parser.h
index 13a3603..535b639 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -552,17 +552,11 @@
   // in the object literal boilerplate.
   Handle<Object> GetBoilerplateValue(Expression* expression);
 
-  enum FunctionLiteralType {
-    EXPRESSION,
-    DECLARATION,
-    NESTED
-  };
-
   ZoneList<Expression*>* ParseArguments(bool* ok);
   FunctionLiteral* ParseFunctionLiteral(Handle<String> var_name,
                                         bool name_is_reserved,
                                         int function_token_position,
-                                        FunctionLiteralType type,
+                                        FunctionLiteral::Type type,
                                         bool* ok);
 
 
diff --git a/src/runtime.cc b/src/runtime.cc
index 8c43d64..82733a7 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -615,8 +615,7 @@
 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
   ASSERT(args.length() == 1);
   Object* obj = args[0];
-  return obj->IsJSProxy()
-      ? isolate->heap()->true_value() : isolate->heap()->false_value();
+  return isolate->heap()->ToBoolean(obj->IsJSProxy());
 }
 
 
@@ -635,6 +634,43 @@
 }
 
 
+RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapInitialize) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 1);
+  CONVERT_ARG_CHECKED(JSWeakMap, weakmap, 0);
+  ASSERT(weakmap->map()->inobject_properties() == 0);
+  Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
+  weakmap->set_table(*table);
+  weakmap->set_next(Smi::FromInt(0));
+  return *weakmap;
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapGet) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+  CONVERT_ARG_CHECKED(JSWeakMap, weakmap, 0);
+  // TODO(mstarzinger): Currently we cannot use JSProxy objects as keys
+  // because they cannot be cast to JSObject to get an identity hash code.
+  CONVERT_ARG_CHECKED(JSObject, key, 1);
+  return weakmap->table()->Lookup(*key);
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapSet) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 3);
+  CONVERT_ARG_CHECKED(JSWeakMap, weakmap, 0);
+  // TODO(mstarzinger): See Runtime_WeakMapGet above.
+  CONVERT_ARG_CHECKED(JSObject, key, 1);
+  Handle<Object> value(args[2]);
+  Handle<ObjectHashTable> table(weakmap->table());
+  Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
+  weakmap->set_table(*new_table);
+  return *value;
+}
+
+
 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
@@ -1001,8 +1037,7 @@
     ASSERT(proto->IsJSGlobalObject());
     obj = JSObject::cast(proto);
   }
-  return obj->map()->is_extensible() ? isolate->heap()->true_value()
-                                     : isolate->heap()->false_value();
+  return isolate->heap()->ToBoolean(obj->map()->is_extensible());
 }
 
 
@@ -1068,8 +1103,7 @@
     Map::cast(new_map)->set_is_access_check_needed(false);
     object->set_map(Map::cast(new_map));
   }
-  return needs_access_checks ? isolate->heap()->true_value()
-                             : isolate->heap()->false_value();
+  return isolate->heap()->ToBoolean(needs_access_checks);
 }
 
 
@@ -1880,6 +1914,24 @@
 }
 
 
+RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+  CONVERT_CHECKED(JSFunction, f, args[0]);
+  return isolate->heap()->ToBoolean(
+      f->shared()->name_should_print_as_anonymous());
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+  CONVERT_CHECKED(JSFunction, f, args[0]);
+  f->shared()->set_name_should_print_as_anonymous(true);
+  return isolate->heap()->undefined_value();
+}
+
+
 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetBound) {
   HandleScope scope(isolate);
   ASSERT(args.length() == 1);
@@ -1967,6 +2019,24 @@
 }
 
 
+// Creates a local, readonly, property called length with the correct
+// length (when read by the user). This effectively overwrites the
+// interceptor used to normally provide the length.
+RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionSetLength) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 2);
+  CONVERT_CHECKED(JSFunction, fun, args[0]);
+  CONVERT_CHECKED(Smi, length, args[1]);
+  MaybeObject* maybe_name =
+      isolate->heap()->AllocateStringFromAscii(CStrVector("length"));
+  String* name;
+  if (!maybe_name->To(&name)) return maybe_name;
+  PropertyAttributes attr =
+      static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY);
+  return fun->AddProperty(name, length, attr, kNonStrictMode);
+}
+
+
 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
@@ -2042,8 +2112,7 @@
   ASSERT(args.length() == 1);
 
   CONVERT_CHECKED(JSFunction, f, args[0]);
-  return f->shared()->IsApiFunction() ? isolate->heap()->true_value()
-                                      : isolate->heap()->false_value();
+  return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
 }
 
 
@@ -2052,8 +2121,7 @@
   ASSERT(args.length() == 1);
 
   CONVERT_CHECKED(JSFunction, f, args[0]);
-  return f->IsBuiltin() ? isolate->heap()->true_value() :
-                          isolate->heap()->false_value();
+  return isolate->heap()->ToBoolean(f->IsBuiltin());
 }
 
 
@@ -4529,9 +4597,10 @@
   // Get the property names.
   jsproto = obj;
   int proto_with_hidden_properties = 0;
+  int next_copy_index = 0;
   for (int i = 0; i < length; i++) {
-    jsproto->GetLocalPropertyNames(*names,
-                                   i == 0 ? 0 : local_property_count[i - 1]);
+    jsproto->GetLocalPropertyNames(*names, next_copy_index);
+    next_copy_index += local_property_count[i];
     if (jsproto->HasHiddenProperties()) {
       proto_with_hidden_properties++;
     }
@@ -9200,13 +9269,13 @@
     if (elements_are_guaranteed_smis) {
       for (uint32_t j = 0; j < len; j++) {
         HandleScope loop_scope;
-        Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get(j))));
+        Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))));
         visitor->visit(j, e);
       }
     } else {
       for (uint32_t j = 0; j < len; j++) {
         HandleScope loop_scope;
-        int64_t val = static_cast<int64_t>(array->get(j));
+        int64_t val = static_cast<int64_t>(array->get_scalar(j));
         if (Smi::IsValid(static_cast<intptr_t>(val))) {
           Handle<Smi> e(Smi::FromInt(static_cast<int>(val)));
           visitor->visit(j, e);
@@ -9220,7 +9289,7 @@
   } else {
     for (uint32_t j = 0; j < len; j++) {
       HandleScope loop_scope(isolate);
-      Handle<Object> e = isolate->factory()->NewNumber(array->get(j));
+      Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
       visitor->visit(j, e);
     }
   }
@@ -9406,7 +9475,7 @@
       Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast(
           receiver->elements()));
       for (uint32_t j = 0; j < length; j++) {
-        Handle<Smi> e(Smi::FromInt(pixels->get(j)));
+        Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)));
         visitor->visit(j, e);
       }
       break;
@@ -9924,9 +9993,7 @@
       details->set(0, *value);
       details->set(1, property_details);
       if (hasJavaScriptAccessors) {
-        details->set(2,
-                     caught_exception ? isolate->heap()->true_value()
-                                      : isolate->heap()->false_value());
+        details->set(2, isolate->heap()->ToBoolean(caught_exception));
         details->set(3, FixedArray::cast(*result_callback_obj)->get(0));
         details->set(4, FixedArray::cast(*result_callback_obj)->get(1));
       }
@@ -11378,7 +11445,11 @@
   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()));
-  Handle<Context> function_context(frame_context->declaration_context());
+  Handle<Context> function_context;
+  // Get the function's context if it has one.
+  if (scope_info->HasHeapAllocatedLocals()) {
+    function_context = Handle<Context>(frame_context->declaration_context());
+  }
   context = CopyWithContextChain(isolate, go_between, frame_context, context);
 
   if (additional_context->IsJSObject()) {
@@ -12109,8 +12180,7 @@
 #ifdef LIVE_OBJECT_LIST
   CONVERT_SMI_ARG_CHECKED(id, 0);
   bool success = LiveObjectList::Delete(id);
-  return success ? isolate->heap()->true_value() :
-                   isolate->heap()->false_value();
+  return isolate->heap()->ToBoolean(success);
 #else
   return isolate->heap()->undefined_value();
 #endif
diff --git a/src/runtime.h b/src/runtime.h
index a42b3bc..a52672a 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -209,10 +209,13 @@
   /* Reflection */ \
   F(FunctionSetInstanceClassName, 2, 1) \
   F(FunctionSetLength, 2, 1) \
+  F(BoundFunctionSetLength, 2, 1)    \
   F(FunctionSetPrototype, 2, 1) \
   F(FunctionSetReadOnlyPrototype, 1, 1) \
   F(FunctionGetName, 1, 1) \
   F(FunctionSetName, 2, 1) \
+  F(FunctionNameShouldPrintAsAnonymous, 1, 1) \
+  F(FunctionMarkNameShouldPrintAsAnonymous, 1, 1) \
   F(FunctionSetBound, 1, 1) \
   F(FunctionRemovePrototype, 1, 1) \
   F(FunctionGetSourceCode, 1, 1) \
@@ -287,6 +290,11 @@
   F(GetHandler, 1, 1) \
   F(Fix, 1, 1) \
   \
+  /* Harmony weakmaps */ \
+  F(WeakMapInitialize, 1, 1) \
+  F(WeakMapGet, 2, 1) \
+  F(WeakMapSet, 3, 1) \
+  \
   /* Statements */ \
   F(NewClosure, 3, 1) \
   F(NewObject, 1, 1) \
diff --git a/src/scanner-base.cc b/src/scanner-base.cc
index 16f8db5..e4590b1 100644
--- a/src/scanner-base.cc
+++ b/src/scanner-base.cc
@@ -89,10 +89,158 @@
   Scan();
 }
 
+
+// Ensure that tokens can be stored in a byte.
+STATIC_ASSERT(Token::NUM_TOKENS <= 0x100);
+
+// Table of one-character tokens, by character (0x00..0x7f only).
+static const byte one_char_tokens[] = {
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::LPAREN,       // 0x28
+  Token::RPAREN,       // 0x29
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::COMMA,        // 0x2c
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::COLON,        // 0x3a
+  Token::SEMICOLON,    // 0x3b
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::CONDITIONAL,  // 0x3f
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::LBRACK,     // 0x5b
+  Token::ILLEGAL,
+  Token::RBRACK,     // 0x5d
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::ILLEGAL,
+  Token::LBRACE,       // 0x7b
+  Token::ILLEGAL,
+  Token::RBRACE,       // 0x7d
+  Token::BIT_NOT,      // 0x7e
+  Token::ILLEGAL
+};
+
+
 Token::Value JavaScriptScanner::Next() {
   current_ = next_;
   has_line_terminator_before_next_ = false;
   has_multiline_comment_before_next_ = false;
+  if (static_cast<unsigned>(c0_) <= 0x7f) {
+    Token::Value token = static_cast<Token::Value>(one_char_tokens[c0_]);
+    if (token != Token::ILLEGAL) {
+      int pos = source_pos();
+      next_.token = token;
+      next_.location.beg_pos = pos;
+      next_.location.end_pos = pos + 1;
+      Advance();
+      return current_.token;
+    }
+  }
   Scan();
   return current_.token;
 }
@@ -171,7 +319,7 @@
   Advance();
 
   while (c0_ >= 0) {
-    char ch = c0_;
+    uc32 ch = c0_;
     Advance();
     if (unicode_cache_->IsLineTerminator(ch)) {
       // Following ECMA-262, section 7.4, a comment containing
@@ -662,10 +810,114 @@
 }
 
 
+// ----------------------------------------------------------------------------
+// Keyword Matcher
+
+#define KEYWORDS(KEYWORD_GROUP, KEYWORD)                      \
+  KEYWORD_GROUP('b')                                          \
+  KEYWORD("break", BREAK)                                     \
+  KEYWORD_GROUP('c')                                          \
+  KEYWORD("case", CASE)                                       \
+  KEYWORD("catch", CATCH)                                     \
+  KEYWORD("class", FUTURE_RESERVED_WORD)                      \
+  KEYWORD("const", CONST)                                     \
+  KEYWORD("continue", CONTINUE)                               \
+  KEYWORD_GROUP('d')                                          \
+  KEYWORD("debugger", DEBUGGER)                               \
+  KEYWORD("default", DEFAULT)                                 \
+  KEYWORD("delete", DELETE)                                   \
+  KEYWORD("do", DO)                                           \
+  KEYWORD_GROUP('e')                                          \
+  KEYWORD("else", ELSE)                                       \
+  KEYWORD("enum", FUTURE_RESERVED_WORD)                       \
+  KEYWORD("export", FUTURE_RESERVED_WORD)                     \
+  KEYWORD("extends", FUTURE_RESERVED_WORD)                    \
+  KEYWORD_GROUP('f')                                          \
+  KEYWORD("false", FALSE_LITERAL)                             \
+  KEYWORD("finally", FINALLY)                                 \
+  KEYWORD("for", FOR)                                         \
+  KEYWORD("function", FUNCTION)                               \
+  KEYWORD_GROUP('i')                                          \
+  KEYWORD("if", IF)                                           \
+  KEYWORD("implements", FUTURE_STRICT_RESERVED_WORD)          \
+  KEYWORD("import", FUTURE_RESERVED_WORD)                     \
+  KEYWORD("in", IN)                                           \
+  KEYWORD("instanceof", INSTANCEOF)                           \
+  KEYWORD("interface", FUTURE_STRICT_RESERVED_WORD)           \
+  KEYWORD_GROUP('l')                                          \
+  KEYWORD("let", FUTURE_STRICT_RESERVED_WORD)                 \
+  KEYWORD_GROUP('n')                                          \
+  KEYWORD("new", NEW)                                         \
+  KEYWORD("null", NULL_LITERAL)                               \
+  KEYWORD_GROUP('p')                                          \
+  KEYWORD("package", FUTURE_STRICT_RESERVED_WORD)             \
+  KEYWORD("private", FUTURE_STRICT_RESERVED_WORD)             \
+  KEYWORD("protected", FUTURE_STRICT_RESERVED_WORD)           \
+  KEYWORD("public", FUTURE_STRICT_RESERVED_WORD)              \
+  KEYWORD_GROUP('r')                                          \
+  KEYWORD("return", RETURN)                                   \
+  KEYWORD_GROUP('s')                                          \
+  KEYWORD("static", FUTURE_STRICT_RESERVED_WORD)              \
+  KEYWORD("super", FUTURE_RESERVED_WORD)                      \
+  KEYWORD("switch", SWITCH)                                   \
+  KEYWORD_GROUP('t')                                          \
+  KEYWORD("this", THIS)                                       \
+  KEYWORD("throw", THROW)                                     \
+  KEYWORD("true", TRUE_LITERAL)                               \
+  KEYWORD("try", TRY)                                         \
+  KEYWORD("typeof", TYPEOF)                                   \
+  KEYWORD_GROUP('v')                                          \
+  KEYWORD("var", VAR)                                         \
+  KEYWORD("void", VOID)                                       \
+  KEYWORD_GROUP('w')                                          \
+  KEYWORD("while", WHILE)                                     \
+  KEYWORD("with", WITH)                                       \
+  KEYWORD_GROUP('y')                                          \
+  KEYWORD("yield", FUTURE_STRICT_RESERVED_WORD)
+
+
+static Token::Value KeywordOrIdentifierToken(const char* input,
+                                             int input_length) {
+  ASSERT(input_length >= 1);
+  const int kMinLength = 2;
+  const int kMaxLength = 10;
+  if (input_length < kMinLength || input_length > kMaxLength) {
+    return Token::IDENTIFIER;
+  }
+  switch (input[0]) {
+    default:
+#define KEYWORD_GROUP_CASE(ch)                                \
+      break;                                                  \
+    case ch:
+#define KEYWORD(keyword, token)                               \
+    {                                                         \
+      /* 'keyword' is a char array, so sizeof(keyword) is */  \
+      /* strlen(keyword) plus 1 for the NUL char. */          \
+      const int keyword_length = sizeof(keyword) - 1;         \
+      STATIC_ASSERT(keyword_length >= kMinLength);            \
+      STATIC_ASSERT(keyword_length <= kMaxLength);            \
+      if (input_length == keyword_length &&                   \
+          input[1] == keyword[1] &&                           \
+          (keyword_length <= 2 || input[2] == keyword[2]) &&  \
+          (keyword_length <= 3 || input[3] == keyword[3]) &&  \
+          (keyword_length <= 4 || input[4] == keyword[4]) &&  \
+          (keyword_length <= 5 || input[5] == keyword[5]) &&  \
+          (keyword_length <= 6 || input[6] == keyword[6]) &&  \
+          (keyword_length <= 7 || input[7] == keyword[7]) &&  \
+          (keyword_length <= 8 || input[8] == keyword[8]) &&  \
+          (keyword_length <= 9 || input[9] == keyword[9])) {  \
+        return Token::token;                                  \
+      }                                                       \
+    }
+    KEYWORDS(KEYWORD_GROUP_CASE, KEYWORD)
+  }
+  return Token::IDENTIFIER;
+}
+
+
 Token::Value JavaScriptScanner::ScanIdentifierOrKeyword() {
   ASSERT(unicode_cache_->IsIdentifierStart(c0_));
   LiteralScope literal(this);
-  KeywordMatcher keyword_match;
   // Scan identifier start character.
   if (c0_ == '\\') {
     uc32 c = ScanIdentifierUnicodeEscape();
@@ -678,9 +930,6 @@
   uc32 first_char = c0_;
   Advance();
   AddLiteralChar(first_char);
-  if (!keyword_match.AddChar(first_char)) {
-    return ScanIdentifierSuffix(&literal);
-  }
 
   // Scan the rest of the identifier characters.
   while (unicode_cache_->IsIdentifierPart(c0_)) {
@@ -688,14 +937,20 @@
       uc32 next_char = c0_;
       Advance();
       AddLiteralChar(next_char);
-      if (keyword_match.AddChar(next_char)) continue;
+      continue;
     }
-    // Fallthrough if no loner able to complete keyword.
+    // Fallthrough if no longer able to complete keyword.
     return ScanIdentifierSuffix(&literal);
   }
+
   literal.Complete();
 
-  return keyword_match.token();
+  if (next_.literal_chars->is_ascii()) {
+    Vector<const char> chars = next_.literal_chars->ascii_literal();
+    return KeywordOrIdentifierToken(chars.start(), chars.length());
+  }
+
+  return Token::IDENTIFIER;
 }
 
 
@@ -785,182 +1040,4 @@
   return true;
 }
 
-// ----------------------------------------------------------------------------
-// Keyword Matcher
-
-KeywordMatcher::FirstState KeywordMatcher::first_states_[] = {
-  { "break",  KEYWORD_PREFIX, Token::BREAK },
-  { NULL,     C,              Token::ILLEGAL },
-  { NULL,     D,              Token::ILLEGAL },
-  { NULL,     E,              Token::ILLEGAL },
-  { NULL,     F,              Token::ILLEGAL },
-  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
-  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
-  { NULL,     I,              Token::ILLEGAL },
-  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
-  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
-  { "let",    KEYWORD_PREFIX, Token::FUTURE_STRICT_RESERVED_WORD },
-  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
-  { NULL,     N,              Token::ILLEGAL },
-  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
-  { NULL,     P,              Token::ILLEGAL },
-  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
-  { "return", KEYWORD_PREFIX, Token::RETURN },
-  { NULL,     S,              Token::ILLEGAL },
-  { NULL,     T,              Token::ILLEGAL },
-  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
-  { NULL,     V,              Token::ILLEGAL },
-  { NULL,     W,              Token::ILLEGAL },
-  { NULL,     UNMATCHABLE,    Token::ILLEGAL },
-  { "yield",  KEYWORD_PREFIX, Token::FUTURE_STRICT_RESERVED_WORD }
-};
-
-
-void KeywordMatcher::Step(unibrow::uchar input) {
-  switch (state_) {
-    case INITIAL: {
-      // matching the first character is the only state with significant fanout.
-      // Match only lower-case letters in range 'b'..'y'.
-      unsigned int offset = input - kFirstCharRangeMin;
-      if (offset < kFirstCharRangeLength) {
-        state_ = first_states_[offset].state;
-        if (state_ == KEYWORD_PREFIX) {
-          keyword_ = first_states_[offset].keyword;
-          counter_ = 1;
-          keyword_token_ = first_states_[offset].token;
-        }
-        return;
-      }
-      break;
-    }
-    case KEYWORD_PREFIX:
-      if (static_cast<unibrow::uchar>(keyword_[counter_]) == input) {
-        counter_++;
-        if (keyword_[counter_] == '\0') {
-          state_ = KEYWORD_MATCHED;
-          token_ = keyword_token_;
-        }
-        return;
-      }
-      break;
-    case KEYWORD_MATCHED:
-      token_ = Token::IDENTIFIER;
-      break;
-    case C:
-      if (MatchState(input, 'a', CA)) return;
-      if (MatchKeywordStart(input, "class", 1,
-                            Token::FUTURE_RESERVED_WORD)) return;
-      if (MatchState(input, 'o', CO)) return;
-      break;
-    case CA:
-      if (MatchKeywordStart(input, "case", 2, Token::CASE)) return;
-      if (MatchKeywordStart(input, "catch", 2, Token::CATCH)) return;
-      break;
-    case CO:
-      if (MatchState(input, 'n', CON)) return;
-      break;
-    case CON:
-      if (MatchKeywordStart(input, "const", 3, Token::CONST)) return;
-      if (MatchKeywordStart(input, "continue", 3, Token::CONTINUE)) return;
-      break;
-    case D:
-      if (MatchState(input, 'e', DE)) return;
-      if (MatchKeyword(input, 'o', KEYWORD_MATCHED, Token::DO)) return;
-      break;
-    case DE:
-      if (MatchKeywordStart(input, "debugger", 2, Token::DEBUGGER)) return;
-      if (MatchKeywordStart(input, "default", 2, Token::DEFAULT)) return;
-      if (MatchKeywordStart(input, "delete", 2, Token::DELETE)) return;
-      break;
-    case E:
-      if (MatchKeywordStart(input, "else", 1, Token::ELSE)) return;
-      if (MatchKeywordStart(input, "enum", 1,
-                            Token::FUTURE_RESERVED_WORD)) return;
-      if (MatchState(input, 'x', EX)) return;
-      break;
-    case EX:
-      if (MatchKeywordStart(input, "export", 2,
-                            Token::FUTURE_RESERVED_WORD)) return;
-      if (MatchKeywordStart(input, "extends", 2,
-                            Token::FUTURE_RESERVED_WORD)) return;
-      break;
-    case F:
-      if (MatchKeywordStart(input, "false", 1, Token::FALSE_LITERAL)) return;
-      if (MatchKeywordStart(input, "finally", 1, Token::FINALLY)) return;
-      if (MatchKeywordStart(input, "for", 1, Token::FOR)) return;
-      if (MatchKeywordStart(input, "function", 1, Token::FUNCTION)) return;
-      break;
-    case I:
-      if (MatchKeyword(input, 'f', KEYWORD_MATCHED, Token::IF)) return;
-      if (MatchState(input, 'm', IM)) return;
-      if (MatchKeyword(input, 'n', IN, Token::IN)) return;
-      break;
-    case IM:
-      if (MatchState(input, 'p', IMP)) return;
-      break;
-    case IMP:
-      if (MatchKeywordStart(input, "implements", 3,
-                            Token::FUTURE_STRICT_RESERVED_WORD )) return;
-      if (MatchKeywordStart(input, "import", 3,
-                            Token::FUTURE_RESERVED_WORD)) return;
-      break;
-    case IN:
-      token_ = Token::IDENTIFIER;
-      if (MatchKeywordStart(input, "interface", 2,
-                            Token::FUTURE_STRICT_RESERVED_WORD)) return;
-      if (MatchKeywordStart(input, "instanceof", 2, Token::INSTANCEOF)) return;
-      break;
-    case N:
-      if (MatchKeywordStart(input, "new", 1, Token::NEW)) return;
-      if (MatchKeywordStart(input, "null", 1, Token::NULL_LITERAL)) return;
-      break;
-    case P:
-      if (MatchKeywordStart(input, "package", 1,
-                            Token::FUTURE_STRICT_RESERVED_WORD)) return;
-      if (MatchState(input, 'r', PR)) return;
-      if (MatchKeywordStart(input, "public", 1,
-                            Token::FUTURE_STRICT_RESERVED_WORD)) return;
-      break;
-    case PR:
-      if (MatchKeywordStart(input, "private", 2,
-                            Token::FUTURE_STRICT_RESERVED_WORD)) return;
-      if (MatchKeywordStart(input, "protected", 2,
-                            Token::FUTURE_STRICT_RESERVED_WORD)) return;
-      break;
-    case S:
-      if (MatchKeywordStart(input, "static", 1,
-                            Token::FUTURE_STRICT_RESERVED_WORD)) return;
-      if (MatchKeywordStart(input, "super", 1,
-                            Token::FUTURE_RESERVED_WORD)) return;
-      if (MatchKeywordStart(input, "switch", 1,
-                            Token::SWITCH)) return;
-      break;
-    case T:
-      if (MatchState(input, 'h', TH)) return;
-      if (MatchState(input, 'r', TR)) return;
-      if (MatchKeywordStart(input, "typeof", 1, Token::TYPEOF)) return;
-      break;
-    case TH:
-      if (MatchKeywordStart(input, "this", 2, Token::THIS)) return;
-      if (MatchKeywordStart(input, "throw", 2, Token::THROW)) return;
-      break;
-    case TR:
-      if (MatchKeywordStart(input, "true", 2, Token::TRUE_LITERAL)) return;
-      if (MatchKeyword(input, 'y', KEYWORD_MATCHED, Token::TRY)) return;
-      break;
-    case V:
-      if (MatchKeywordStart(input, "var", 1, Token::VAR)) return;
-      if (MatchKeywordStart(input, "void", 1, Token::VOID)) return;
-      break;
-    case W:
-      if (MatchKeywordStart(input, "while", 1, Token::WHILE)) return;
-      if (MatchKeywordStart(input, "with", 1, Token::WITH)) return;
-      break;
-    case UNMATCHABLE:
-      break;
-  }
-  // On fallthrough, it's a failure.
-  state_ = UNMATCHABLE;
-}
-
 } }  // namespace v8::internal
diff --git a/src/scanner-base.h b/src/scanner-base.h
index 3d67d4e..d3776e5 100644
--- a/src/scanner-base.h
+++ b/src/scanner-base.h
@@ -542,151 +542,6 @@
   bool has_multiline_comment_before_next_;
 };
 
-
-// ----------------------------------------------------------------------------
-// Keyword matching state machine.
-
-class KeywordMatcher {
-//  Incrementally recognize keywords.
-//
-//  We distinguish between normal future reserved words and words that are
-//  considered to be future reserved words only in strict mode as required by
-//  ECMA-262 7.6.1.2.
-//
-//  Recognized as keywords:
-//      break, case, catch, const*, continue, debugger, default, delete, do,
-//      else, finally, false, for, function, if, in, instanceof, new, null,
-//      return, switch, this, throw, true, try, typeof, var, void, while, with.
-//
-//  Recognized as Future Reserved Keywords:
-//      class, enum, export, extends, import, super.
-//
-//  Recognized as Future Reserved Keywords (strict mode only):
-//      implements, interface, let, package, private, protected, public,
-//      static, yield.
-//
-//  *: Actually a "future reserved keyword". It's the only one we are
-//     recognizing outside of ES5 strict mode, the remaining are allowed
-//     as identifiers.
-//
- public:
-  KeywordMatcher()
-      : state_(INITIAL),
-        token_(Token::IDENTIFIER),
-        keyword_(NULL),
-        counter_(0),
-        keyword_token_(Token::ILLEGAL) {}
-
-  Token::Value token() { return token_; }
-
-  inline bool AddChar(unibrow::uchar input) {
-    if (state_ != UNMATCHABLE) {
-      Step(input);
-    }
-    return state_ != UNMATCHABLE;
-  }
-
-  void Fail() {
-    token_ = Token::IDENTIFIER;
-    state_ = UNMATCHABLE;
-  }
-
- private:
-  enum State {
-    UNMATCHABLE,
-    INITIAL,
-    KEYWORD_PREFIX,
-    KEYWORD_MATCHED,
-    C,
-    CA,
-    CO,
-    CON,
-    D,
-    DE,
-    E,
-    EX,
-    F,
-    I,
-    IM,
-    IMP,
-    IN,
-    N,
-    P,
-    PR,
-    S,
-    T,
-    TH,
-    TR,
-    V,
-    W
-  };
-
-  struct FirstState {
-    const char* keyword;
-    State state;
-    Token::Value token;
-  };
-
-  // Range of possible first characters of a keyword.
-  static const unsigned int kFirstCharRangeMin = 'b';
-  static const unsigned int kFirstCharRangeMax = 'y';
-  static const unsigned int kFirstCharRangeLength =
-      kFirstCharRangeMax - kFirstCharRangeMin + 1;
-  // State map for first keyword character range.
-  static FirstState first_states_[kFirstCharRangeLength];
-
-  // If input equals keyword's character at position, continue matching keyword
-  // from that position.
-  inline bool MatchKeywordStart(unibrow::uchar input,
-                                const char* keyword,
-                                int position,
-                                Token::Value token_if_match) {
-    if (input != static_cast<unibrow::uchar>(keyword[position])) {
-      return false;
-    }
-    state_ = KEYWORD_PREFIX;
-    this->keyword_ = keyword;
-    this->counter_ = position + 1;
-    this->keyword_token_ = token_if_match;
-    return true;
-  }
-
-  // If input equals match character, transition to new state and return true.
-  inline bool MatchState(unibrow::uchar input, char match, State new_state) {
-    if (input != static_cast<unibrow::uchar>(match)) {
-      return false;
-    }
-    state_ = new_state;
-    return true;
-  }
-
-  inline bool MatchKeyword(unibrow::uchar input,
-                           char match,
-                           State new_state,
-                           Token::Value keyword_token) {
-    if (input != static_cast<unibrow::uchar>(match)) {
-      return false;
-    }
-    state_ = new_state;
-    token_ = keyword_token;
-    return true;
-  }
-
-  void Step(unibrow::uchar input);
-
-  // Current state.
-  State state_;
-  // Token for currently added characters.
-  Token::Value token_;
-
-  // Matching a specific keyword string (there is only one possible valid
-  // keyword with the current prefix).
-  const char* keyword_;
-  int counter_;
-  Token::Value keyword_token_;
-};
-
-
 } }  // namespace v8::internal
 
 #endif  // V8_SCANNER_BASE_H_
diff --git a/src/spaces.cc b/src/spaces.cc
index 54361da..a782ba9 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -148,12 +148,12 @@
 // CodeRange
 
 
-CodeRange::CodeRange()
-    : code_range_(NULL),
+CodeRange::CodeRange(Isolate* isolate)
+    : isolate_(isolate),
+      code_range_(NULL),
       free_list_(0),
       allocation_list_(0),
-      current_allocation_block_index_(0),
-      isolate_(NULL) {
+      current_allocation_block_index_(0) {
 }
 
 
@@ -279,8 +279,9 @@
 const int kEstimatedNumberOfChunks = 270;
 
 
-MemoryAllocator::MemoryAllocator()
-    : capacity_(0),
+MemoryAllocator::MemoryAllocator(Isolate* isolate)
+    : isolate_(isolate),
+      capacity_(0),
       capacity_executable_(0),
       size_(0),
       size_executable_(0),
@@ -288,8 +289,7 @@
       chunks_(kEstimatedNumberOfChunks),
       free_chunk_ids_(kEstimatedNumberOfChunks),
       max_nof_chunks_(0),
-      top_(0),
-      isolate_(NULL) {
+      top_(0) {
 }
 
 
diff --git a/src/spaces.h b/src/spaces.h
index ac5d998..d8ed27e 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -408,6 +408,8 @@
 // manages a range of virtual memory.
 class CodeRange {
  public:
+  explicit CodeRange(Isolate* isolate);
+
   // 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.
@@ -417,9 +419,9 @@
   // manage it.
   void TearDown();
 
-  bool exists() { return code_range_ != NULL; }
+  bool exists() { return this != NULL && code_range_ != NULL; }
   bool contains(Address address) {
-    if (code_range_ == NULL) return false;
+    if (this == NULL || code_range_ == NULL) return false;
     Address start = static_cast<Address>(code_range_->address());
     return start <= address && address < start + code_range_->size();
   }
@@ -432,7 +434,7 @@
   void FreeRawMemory(void* buf, size_t length);
 
  private:
-  CodeRange();
+  Isolate* isolate_;
 
   // The reserved range of virtual memory that all code objects are put in.
   VirtualMemory* code_range_;
@@ -466,10 +468,6 @@
   static int CompareFreeBlockAddress(const FreeBlock* left,
                                      const FreeBlock* right);
 
-  friend class Isolate;
-
-  Isolate* isolate_;
-
   DISALLOW_COPY_AND_ASSIGN(CodeRange);
 };
 
@@ -500,6 +498,8 @@
 
 class MemoryAllocator {
  public:
+  explicit MemoryAllocator(Isolate* isolate);
+
   // Initializes its internal bookkeeping structures.
   // Max capacity of the total space and executable memory limit.
   bool Setup(intptr_t max_capacity, intptr_t capacity_executable);
@@ -657,10 +657,10 @@
 #endif
 
  private:
-  MemoryAllocator();
-
   static const int kChunkSize = kPagesPerChunk * Page::kPageSize;
 
+  Isolate* isolate_;
+
   // Maximum space size in bytes.
   intptr_t capacity_;
   // Maximum subset of capacity_ that can be executable
@@ -753,10 +753,6 @@
                            Page* prev,
                            Page** last_page_in_use);
 
-  friend class Isolate;
-
-  Isolate* isolate_;
-
   DISALLOW_COPY_AND_ASSIGN(MemoryAllocator);
 };
 
diff --git a/src/token.cc b/src/token.cc
index feca7be..7ba7ed3 100644
--- a/src/token.cc
+++ b/src/token.cc
@@ -33,21 +33,21 @@
 
 #define T(name, string, precedence) #name,
 const char* const Token::name_[NUM_TOKENS] = {
-  TOKEN_LIST(T, T, IGNORE_TOKEN)
+  TOKEN_LIST(T, T)
 };
 #undef T
 
 
 #define T(name, string, precedence) string,
 const char* const Token::string_[NUM_TOKENS] = {
-  TOKEN_LIST(T, T, IGNORE_TOKEN)
+  TOKEN_LIST(T, T)
 };
 #undef T
 
 
 #define T(name, string, precedence) precedence,
 const int8_t Token::precedence_[NUM_TOKENS] = {
-  TOKEN_LIST(T, T, IGNORE_TOKEN)
+  TOKEN_LIST(T, T)
 };
 #undef T
 
@@ -55,7 +55,7 @@
 #define KT(a, b, c) 'T',
 #define KK(a, b, c) 'K',
 const char Token::token_type[] = {
-  TOKEN_LIST(KT, KK, IGNORE_TOKEN)
+  TOKEN_LIST(KT, KK)
 };
 #undef KT
 #undef KK
diff --git a/src/token.h b/src/token.h
index 77333bc..7e6c18c 100644
--- a/src/token.h
+++ b/src/token.h
@@ -41,7 +41,6 @@
 //
 //   T: Non-keyword tokens
 //   K: Keyword tokens
-//   F: Future (reserved) keyword tokens
 
 // IGNORE_TOKEN is a convenience macro that can be supplied as
 // an argument (at any position) for a TOKEN_LIST call. It does
@@ -49,7 +48,7 @@
 
 #define IGNORE_TOKEN(name, string, precedence)
 
-#define TOKEN_LIST(T, K, F)                                             \
+#define TOKEN_LIST(T, K)                                                \
   /* End of source indicator. */                                        \
   T(EOS, "EOS", 0)                                                      \
                                                                         \
@@ -182,7 +181,7 @@
   // All token values.
 #define T(name, string, precedence) name,
   enum Value {
-    TOKEN_LIST(T, T, IGNORE_TOKEN)
+    TOKEN_LIST(T, T)
     NUM_TOKENS
   };
 #undef T
diff --git a/src/v8.cc b/src/v8.cc
index 36f835f..1e9b5dc 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -28,6 +28,7 @@
 #include "v8.h"
 
 #include "isolate.h"
+#include "elements.h"
 #include "bootstrapper.h"
 #include "debug.h"
 #include "deoptimizer.h"
@@ -212,6 +213,8 @@
 
   // Peephole optimization might interfere with deoptimization.
   FLAG_peephole_optimization = !use_crankshaft_;
+
+  ElementsAccessor::InitializeOncePerProcess();
 }
 
 } }  // namespace v8::internal
diff --git a/src/v8natives.js b/src/v8natives.js
index be9b297..88525f6 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 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:
@@ -1428,7 +1428,9 @@
     }
   }
 
-  var name = %FunctionGetName(func);
+  var name = %FunctionNameShouldPrintAsAnonymous(func)
+      ? 'anonymous'
+      : %FunctionGetName(func);
   return 'function ' + name + source;
 }
 
@@ -1498,9 +1500,9 @@
 
   // Set the correct length.
   var length = (this.length - argc_bound) > 0 ? this.length - argc_bound : 0;
-  %FunctionSetLength(result, length);
   %FunctionRemovePrototype(result);
   %FunctionSetBound(result);
+  %BoundFunctionSetLength(result, length);
   return result;
 }
 
@@ -1523,7 +1525,7 @@
   // The call to SetNewFunctionAttributes will ensure the prototype
   // property of the resulting function is enumerable (ECMA262, 15.3.5.2).
   var f = %CompileString(source)();
-  %FunctionSetName(f, "anonymous");
+  %FunctionMarkNameShouldPrintAsAnonymous(f);
   return %SetNewFunctionAttributes(f);
 }
 
diff --git a/src/v8threads.cc b/src/v8threads.cc
index c9a8bb6..52f82e2 100644
--- a/src/v8threads.cc
+++ b/src/v8threads.cc
@@ -94,6 +94,11 @@
 }
 
 
+bool Locker::IsActive() {
+  return active_;
+}
+
+
 Locker::~Locker() {
   ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
   if (has_lock_) {
diff --git a/src/version.cc b/src/version.cc
index 16579df..42bb2fe 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     5
-#define BUILD_NUMBER      3
+#define BUILD_NUMBER      4
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/weakmap.js b/src/weakmap.js
new file mode 100644
index 0000000..15056c7
--- /dev/null
+++ b/src/weakmap.js
@@ -0,0 +1,95 @@
+// 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.
+
+
+// This file relies on the fact that the following declaration has been made
+// in runtime.js:
+// const $Object = global.Object;
+const $WeakMap = global.WeakMap;
+
+// -------------------------------------------------------------------
+
+// Set the WeakMap function and constructor.
+%SetCode($WeakMap, function(x) {
+  if (%_IsConstructCall()) {
+    %WeakMapInitialize(this);
+  } else {
+    return new $WeakMap();
+  }
+});
+
+
+function WeakMapGet(key) {
+  if (!IS_SPEC_OBJECT(key)) {
+    throw %MakeTypeError('invalid_weakmap_key', [this, key]);
+  }
+  return %WeakMapGet(this, key);
+}
+
+
+function WeakMapSet(key, value) {
+  if (!IS_SPEC_OBJECT(key)) {
+    throw %MakeTypeError('invalid_weakmap_key', [this, key]);
+  }
+  return %WeakMapSet(this, key, value);
+}
+
+
+function WeakMapHas(key) {
+  if (!IS_SPEC_OBJECT(key)) {
+    throw %MakeTypeError('invalid_weakmap_key', [this, key]);
+  }
+  return !IS_UNDEFINED(%WeakMapGet(this, key));
+}
+
+
+function WeakMapDelete(key) {
+  if (!IS_SPEC_OBJECT(key)) {
+    throw %MakeTypeError('invalid_weakmap_key', [this, key]);
+  }
+  if (!IS_UNDEFINED(%WeakMapGet(this, key))) {
+    %WeakMapSet(this, key, void 0);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+// -------------------------------------------------------------------
+
+function SetupWeakMap() {
+  // Setup the non-enumerable functions on the WeakMap prototype object.
+  InstallFunctionsOnHiddenPrototype($WeakMap.prototype, DONT_ENUM, $Array(
+    "get", WeakMapGet,
+    "set", WeakMapSet,
+    "has", WeakMapHas,
+    "delete", WeakMapDelete
+  ));
+}
+
+
+SetupWeakMap();
diff --git a/src/x64/deoptimizer-x64.cc b/src/x64/deoptimizer-x64.cc
index 2a31f28..b52e659 100644
--- a/src/x64/deoptimizer-x64.cc
+++ b/src/x64/deoptimizer-x64.cc
@@ -38,7 +38,7 @@
 namespace internal {
 
 
-int Deoptimizer::table_entry_size_ = 10;
+const int Deoptimizer::table_entry_size_ = 10;
 
 
 int Deoptimizer::patch_size() {
@@ -605,8 +605,6 @@
     output_frame->SetContinuation(
         reinterpret_cast<intptr_t>(continuation->entry()));
   }
-
-  if (output_count_ - 1 == frame_index) iterator->Done();
 }
 
 
diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc
index 14c95bc..1b8871f 100644
--- a/src/x64/disasm-x64.cc
+++ b/src/x64/disasm-x64.cc
@@ -58,7 +58,7 @@
 };
 
 
-static ByteMnemonic two_operands_instr[] = {
+static const ByteMnemonic two_operands_instr[] = {
   { 0x00, BYTE_OPER_REG_OP_ORDER, "add" },
   { 0x01, OPER_REG_OP_ORDER,      "add" },
   { 0x02, BYTE_REG_OPER_OP_ORDER, "add" },
@@ -105,7 +105,7 @@
 };
 
 
-static ByteMnemonic zero_operands_instr[] = {
+static const ByteMnemonic zero_operands_instr[] = {
   { 0xC3, UNSET_OP_ORDER, "ret" },
   { 0xC9, UNSET_OP_ORDER, "leave" },
   { 0xF4, UNSET_OP_ORDER, "hlt" },
@@ -125,14 +125,14 @@
 };
 
 
-static ByteMnemonic call_jump_instr[] = {
+static const ByteMnemonic call_jump_instr[] = {
   { 0xE8, UNSET_OP_ORDER, "call" },
   { 0xE9, UNSET_OP_ORDER, "jmp" },
   { -1, UNSET_OP_ORDER, "" }
 };
 
 
-static ByteMnemonic short_immediate_instr[] = {
+static const ByteMnemonic short_immediate_instr[] = {
   { 0x05, UNSET_OP_ORDER, "add" },
   { 0x0D, UNSET_OP_ORDER, "or" },
   { 0x15, UNSET_OP_ORDER, "adc" },
@@ -145,7 +145,7 @@
 };
 
 
-static const char* conditional_code_suffix[] = {
+static const char* const conditional_code_suffix[] = {
   "o", "no", "c", "nc", "z", "nz", "na", "a",
   "s", "ns", "pe", "po", "l", "ge", "le", "g"
 };
@@ -193,7 +193,7 @@
   InstructionDesc instructions_[256];
   void Clear();
   void Init();
-  void CopyTable(ByteMnemonic bm[], InstructionType type);
+  void CopyTable(const ByteMnemonic bm[], InstructionType type);
   void SetTableRange(InstructionType type, byte start, byte end, bool byte_size,
                      const char* mnem);
   void AddJumpConditionalShort();
@@ -228,7 +228,8 @@
 }
 
 
-void InstructionTable::CopyTable(ByteMnemonic bm[], InstructionType type) {
+void InstructionTable::CopyTable(const ByteMnemonic bm[],
+                                 InstructionType type) {
   for (int i = 0; bm[i].b >= 0; i++) {
     InstructionDesc* id = &instructions_[bm[i].b];
     id->mnem = bm[i].mnem;
diff --git a/test/cctest/SConscript b/test/cctest/SConscript
index a228ac1..621d8ec 100644
--- a/test/cctest/SConscript
+++ b/test/cctest/SConscript
@@ -96,7 +96,8 @@
     'test-threads.cc',
     'test-unbound-queue.cc',
     'test-utils.cc',
-    'test-version.cc'
+    'test-version.cc',
+    'test-weakmaps.cc'
   ],
   'arch:arm':  [
     'test-assembler-arm.cc',
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index 07d12c8..5843440 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -79,6 +79,7 @@
         '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',
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index 6e7824f..78f3756 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -38,6 +38,9 @@
 test-serialize/TestThatAlwaysFails: FAIL
 test-serialize/DependentTestThatAlwaysFails: FAIL
 
+# We do not yet shrink weak maps after they have been emptied by the GC
+test-weakmaps/Shrinking: FAIL
+
 ##############################################################################
 [ $arch == arm ]
 
diff --git a/test/cctest/test-alloc.cc b/test/cctest/test-alloc.cc
index 4d9c218..9767192 100644
--- a/test/cctest/test-alloc.cc
+++ b/test/cctest/test-alloc.cc
@@ -186,7 +186,9 @@
 TEST(CodeRange) {
   const int code_range_size = 16*MB;
   OS::Setup();
-  Isolate::Current()->code_range()->Setup(code_range_size);
+  Isolate::Current()->InitializeLoggingAndCounters();
+  CodeRange* code_range = new CodeRange(Isolate::Current());
+  code_range->Setup(code_range_size);
   int current_allocated = 0;
   int total_allocated = 0;
   List<Block> blocks(1000);
@@ -198,8 +200,7 @@
       size_t requested = (Page::kPageSize << (Pseudorandom() % 6)) +
            Pseudorandom() % 5000 + 1;
       size_t allocated = 0;
-      void* base = Isolate::Current()->code_range()->
-          AllocateRawMemory(requested, &allocated);
+      void* base = code_range->AllocateRawMemory(requested, &allocated);
       CHECK(base != NULL);
       blocks.Add(Block(base, static_cast<int>(allocated)));
       current_allocated += static_cast<int>(allocated);
@@ -207,8 +208,7 @@
     } else {
       // Free a block.
       int index = Pseudorandom() % blocks.length();
-      Isolate::Current()->code_range()->FreeRawMemory(
-          blocks[index].base, blocks[index].size);
+      code_range->FreeRawMemory(blocks[index].base, blocks[index].size);
       current_allocated -= blocks[index].size;
       if (index < blocks.length() - 1) {
         blocks[index] = blocks.RemoveLast();
@@ -218,5 +218,6 @@
     }
   }
 
-  Isolate::Current()->code_range()->TearDown();
+  code_range->TearDown();
+  delete code_range;
 }
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index dad5e1b..c694ae3 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -11661,7 +11661,7 @@
   }
   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, pixels->get_scalar(i));
     CHECK_EQ(i % 256, pixel_data[i]);
   }
 
@@ -12134,7 +12134,8 @@
   }
   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->get_scalar(i)));
     CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
   }
 
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 73b84b7..58d970c 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -5844,6 +5844,7 @@
 
 
 TEST(DebuggerAgent) {
+  v8::V8::Initialize();
   i::Debugger* debugger = i::Isolate::Current()->debugger();
   // Make sure these ports is not used by other tests to allow tests to run in
   // parallel.
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index fac9f0a..11b8813 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -291,8 +291,8 @@
 
 
 TEST(GlobalHandles) {
-  GlobalHandles* global_handles = Isolate::Current()->global_handles();
   InitializeVM();
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
 
   Handle<Object> h1;
   Handle<Object> h2;
@@ -339,8 +339,8 @@
 
 
 TEST(WeakGlobalHandlesScavenge) {
-  GlobalHandles* global_handles = Isolate::Current()->global_handles();
   InitializeVM();
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
 
   WeakPointerCleared = false;
 
@@ -377,8 +377,8 @@
 
 
 TEST(WeakGlobalHandlesMark) {
-  GlobalHandles* global_handles = Isolate::Current()->global_handles();
   InitializeVM();
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
 
   WeakPointerCleared = false;
 
@@ -416,8 +416,8 @@
 }
 
 TEST(DeleteWeakGlobalHandle) {
-  GlobalHandles* global_handles = Isolate::Current()->global_handles();
   InitializeVM();
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
 
   WeakPointerCleared = false;
 
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index 96a181d..fe73876 100755
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -42,7 +42,7 @@
 
 namespace i = ::v8::internal;
 
-TEST(KeywordMatcher) {
+TEST(ScanKeywords) {
   struct KeywordToken {
     const char* keyword;
     i::Token::Value token;
@@ -50,90 +50,62 @@
 
   static const KeywordToken keywords[] = {
 #define KEYWORD(t, s, d) { s, i::Token::t },
-#define IGNORE(t, s, d)  /* */
-      TOKEN_LIST(IGNORE, KEYWORD, IGNORE)
+      TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
 #undef KEYWORD
       { NULL, i::Token::IDENTIFIER }
   };
 
-  static const char* future_keywords[] = {
-#define FUTURE(t, s, d) s,
-      TOKEN_LIST(IGNORE, IGNORE, FUTURE)
-#undef FUTURE
-#undef IGNORE
-      NULL
-  };
-
   KeywordToken key_token;
+  i::UnicodeCache unicode_cache;
+  i::byte buffer[32];
   for (int i = 0; (key_token = keywords[i]).keyword != NULL; i++) {
-    i::KeywordMatcher matcher;
-    const char* keyword = key_token.keyword;
-    int length = i::StrLength(keyword);
-    for (int j = 0; j < length; j++) {
-      if (key_token.token == i::Token::INSTANCEOF && j == 2) {
-        // "in" is a prefix of "instanceof". It's the only keyword
-        // that is a prefix of another.
-        CHECK_EQ(i::Token::IN, matcher.token());
-      } else {
-        CHECK_EQ(i::Token::IDENTIFIER, matcher.token());
-      }
-      matcher.AddChar(keyword[j]);
+    const i::byte* keyword =
+        reinterpret_cast<const i::byte*>(key_token.keyword);
+    int length = i::StrLength(key_token.keyword);
+    CHECK(static_cast<int>(sizeof(buffer)) >= length);
+    {
+      i::Utf8ToUC16CharacterStream stream(keyword, length);
+      i::JavaScriptScanner scanner(&unicode_cache);
+      scanner.Initialize(&stream);
+      CHECK_EQ(key_token.token, scanner.Next());
+      CHECK_EQ(i::Token::EOS, scanner.Next());
     }
-    CHECK_EQ(key_token.token, matcher.token());
-    // Adding more characters will make keyword matching fail.
-    matcher.AddChar('z');
-    CHECK_EQ(i::Token::IDENTIFIER, matcher.token());
-    // Adding a keyword later will not make it match again.
-    matcher.AddChar('i');
-    matcher.AddChar('f');
-    CHECK_EQ(i::Token::IDENTIFIER, matcher.token());
-  }
-
-  // Future keywords are not recognized.
-  const char* future_keyword;
-  for (int i = 0; (future_keyword = future_keywords[i]) != NULL; i++) {
-    i::KeywordMatcher matcher;
-    int length = i::StrLength(future_keyword);
-    for (int j = 0; j < length; j++) {
-      matcher.AddChar(future_keyword[j]);
+    // Removing characters will make keyword matching fail.
+    {
+      i::Utf8ToUC16CharacterStream stream(keyword, length - 1);
+      i::JavaScriptScanner scanner(&unicode_cache);
+      scanner.Initialize(&stream);
+      CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
+      CHECK_EQ(i::Token::EOS, scanner.Next());
     }
-    CHECK_EQ(i::Token::IDENTIFIER, matcher.token());
+    // Adding characters will make keyword matching fail.
+    static const char chars_to_append[] = { 'z', '0', '_' };
+    for (int j = 0; j < static_cast<int>(ARRAY_SIZE(chars_to_append)); ++j) {
+      memmove(buffer, keyword, length);
+      buffer[length] = chars_to_append[j];
+      i::Utf8ToUC16CharacterStream stream(buffer, length + 1);
+      i::JavaScriptScanner scanner(&unicode_cache);
+      scanner.Initialize(&stream);
+      CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
+      CHECK_EQ(i::Token::EOS, scanner.Next());
+    }
+    // Replacing characters will make keyword matching fail.
+    {
+      memmove(buffer, keyword, length);
+      buffer[length - 1] = '_';
+      i::Utf8ToUC16CharacterStream stream(buffer, length);
+      i::JavaScriptScanner scanner(&unicode_cache);
+      scanner.Initialize(&stream);
+      CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
+      CHECK_EQ(i::Token::EOS, scanner.Next());
+    }
   }
-
-  // Zero isn't ignored at first.
-  i::KeywordMatcher bad_start;
-  bad_start.AddChar(0);
-  CHECK_EQ(i::Token::IDENTIFIER, bad_start.token());
-  bad_start.AddChar('i');
-  bad_start.AddChar('f');
-  CHECK_EQ(i::Token::IDENTIFIER, bad_start.token());
-
-  // Zero isn't ignored at end.
-  i::KeywordMatcher bad_end;
-  bad_end.AddChar('i');
-  bad_end.AddChar('f');
-  CHECK_EQ(i::Token::IF, bad_end.token());
-  bad_end.AddChar(0);
-  CHECK_EQ(i::Token::IDENTIFIER, bad_end.token());
-
-  // Case isn't ignored.
-  i::KeywordMatcher bad_case;
-  bad_case.AddChar('i');
-  bad_case.AddChar('F');
-  CHECK_EQ(i::Token::IDENTIFIER, bad_case.token());
-
-  // If we mark it as failure, continuing won't help.
-  i::KeywordMatcher full_stop;
-  full_stop.AddChar('i');
-  CHECK_EQ(i::Token::IDENTIFIER, full_stop.token());
-  full_stop.Fail();
-  CHECK_EQ(i::Token::IDENTIFIER, full_stop.token());
-  full_stop.AddChar('f');
-  CHECK_EQ(i::Token::IDENTIFIER, full_stop.token());
 }
 
 
 TEST(ScanHTMLEndComments) {
+  v8::V8::Initialize();
+
   // Regression test. See:
   //    http://code.google.com/p/chromium/issues/detail?id=53548
   // Tests that --> is correctly interpreted as comment-to-end-of-line if there
@@ -263,6 +235,8 @@
 
 
 TEST(StandAlonePreParser) {
+  v8::V8::Initialize();
+
   int marker;
   i::Isolate::Current()->stack_guard()->SetStackLimit(
       reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
@@ -299,6 +273,8 @@
 
 
 TEST(RegressChromium62639) {
+  v8::V8::Initialize();
+
   int marker;
   i::Isolate::Current()->stack_guard()->SetStackLimit(
       reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
@@ -320,6 +296,8 @@
 
 
 TEST(Regress928) {
+  v8::V8::Initialize();
+
   // Preparsing didn't consider the catch clause of a try statement
   // as with-content, which made it assume that a function inside
   // the block could be lazily compiled, and an extra, unexpected,
@@ -360,6 +338,8 @@
 
 
 TEST(PreParseOverflow) {
+  v8::V8::Initialize();
+
   int marker;
   i::Isolate::Current()->stack_guard()->SetStackLimit(
       reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
@@ -610,6 +590,8 @@
 }
 
 TEST(StreamScanner) {
+  v8::V8::Initialize();
+
   const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
   i::Utf8ToUC16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1),
                                        static_cast<unsigned>(strlen(str1)));
@@ -690,6 +672,8 @@
 
 
 TEST(RegExpScanning) {
+  v8::V8::Initialize();
+
   // RegExp token with added garbage at the end. The scanner should only
   // scan the RegExp until the terminating slash just before "flipperwald".
   TestScanRegExp("/b/flipperwald", "b");
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index 46f8ad6..8e85444 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -99,10 +99,10 @@
 
 
 TEST(ExternalReferenceEncoder) {
-  OS::Setup();
   Isolate* isolate = i::Isolate::Current();
   isolate->stats_table()->SetCounterFunction(counter_function);
-  HEAP->Setup(false);
+  v8::V8::Initialize();
+
   ExternalReferenceEncoder encoder;
   CHECK_EQ(make_code(BUILTIN, Builtins::kArrayCode),
            Encode(encoder, Builtins::kArrayCode));
@@ -139,10 +139,10 @@
 
 
 TEST(ExternalReferenceDecoder) {
-  OS::Setup();
   Isolate* isolate = i::Isolate::Current();
   isolate->stats_table()->SetCounterFunction(counter_function);
-  HEAP->Setup(false);
+  v8::V8::Initialize();
+
   ExternalReferenceDecoder decoder;
   CHECK_EQ(AddressOf(Builtins::kArrayCode),
            decoder.Decode(make_code(BUILTIN, Builtins::kArrayCode)));
diff --git a/test/cctest/test-spaces.cc b/test/cctest/test-spaces.cc
index de0c41e..0f22ce1 100644
--- a/test/cctest/test-spaces.cc
+++ b/test/cctest/test-spaces.cc
@@ -91,46 +91,74 @@
 }
 
 
+namespace v8 {
+namespace internal {
+
+// Temporarily sets a given allocator in an isolate.
+class TestMemoryAllocatorScope {
+ public:
+  TestMemoryAllocatorScope(Isolate* isolate, MemoryAllocator* allocator)
+      : isolate_(isolate),
+        old_allocator_(isolate->memory_allocator_) {
+    isolate->memory_allocator_ = allocator;
+  }
+
+  ~TestMemoryAllocatorScope() {
+    isolate_->memory_allocator_ = old_allocator_;
+  }
+
+ private:
+  Isolate* isolate_;
+  MemoryAllocator* old_allocator_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestMemoryAllocatorScope);
+};
+
+} }  // namespace v8::internal
+
+
 TEST(MemoryAllocator) {
   OS::Setup();
   Isolate* isolate = Isolate::Current();
-  CHECK(HEAP->ConfigureHeapDefault());
-  CHECK(isolate->memory_allocator()->Setup(HEAP->MaxReserved(),
-                                           HEAP->MaxExecutableSize()));
+  isolate->InitializeLoggingAndCounters();
+  Heap* heap = isolate->heap();
+  CHECK(heap->ConfigureHeapDefault());
+  MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
+  CHECK(memory_allocator->Setup(heap->MaxReserved(),
+                                heap->MaxExecutableSize()));
+  TestMemoryAllocatorScope test_scope(isolate, memory_allocator);
 
-  OldSpace faked_space(HEAP,
-                       HEAP->MaxReserved(),
+  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 =
-      isolate->memory_allocator()->AllocatePages(
-          requested, &allocated, &faked_space);
+  Page* first_page = 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(isolate->memory_allocator()->IsPageInSpace(p, &faked_space));
+    CHECK(memory_allocator->IsPageInSpace(p, &faked_space));
     last_page = p;
   }
 
   // Again, we should get n or n - 1 pages.
-  Page* others =
-      isolate->memory_allocator()->AllocatePages(
-          requested, &allocated, &faked_space);
+  Page* others = memory_allocator->AllocatePages(
+      requested, &allocated, &faked_space);
   CHECK(others->is_valid());
   CHECK(allocated == requested || allocated == requested - 1);
   total_pages += allocated;
 
-  isolate->memory_allocator()->SetNextPage(last_page, others);
+  memory_allocator->SetNextPage(last_page, others);
   int page_count = 0;
   for (Page* p = first_page; p->is_valid(); p = p->next_page()) {
-    CHECK(isolate->memory_allocator()->IsPageInSpace(p, &faked_space));
+    CHECK(memory_allocator->IsPageInSpace(p, &faked_space));
     page_count++;
   }
   CHECK(total_pages == page_count);
@@ -141,34 +169,39 @@
   // 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 = isolate->memory_allocator()->FreePages(second_page);
+  Page* free_return = memory_allocator->FreePages(second_page);
   CHECK(free_return == second_page);
-  isolate->memory_allocator()->SetNextPage(first_page, free_return);
+  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 = isolate->memory_allocator()->FreePages(first_page);
+  Page* invalid_page = memory_allocator->FreePages(first_page);
   CHECK(!invalid_page->is_valid());
 
-  isolate->memory_allocator()->TearDown();
+  memory_allocator->TearDown();
+  delete memory_allocator;
 }
 
 
 TEST(NewSpace) {
   OS::Setup();
-  CHECK(HEAP->ConfigureHeapDefault());
-  CHECK(Isolate::Current()->memory_allocator()->Setup(
-      HEAP->MaxReserved(), HEAP->MaxExecutableSize()));
+  Isolate* isolate = Isolate::Current();
+  isolate->InitializeLoggingAndCounters();
+  Heap* heap = isolate->heap();
+  CHECK(heap->ConfigureHeapDefault());
+  MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
+  CHECK(memory_allocator->Setup(heap->MaxReserved(),
+                                heap->MaxExecutableSize()));
+  TestMemoryAllocatorScope test_scope(isolate, memory_allocator);
 
-  NewSpace new_space(HEAP);
+  NewSpace new_space(heap);
 
   void* chunk =
-      Isolate::Current()->memory_allocator()->ReserveInitialChunk(
-          4 * HEAP->ReservedSemiSpaceSize());
+      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) {
@@ -178,28 +211,33 @@
   }
 
   new_space.TearDown();
-  Isolate::Current()->memory_allocator()->TearDown();
+  memory_allocator->TearDown();
+  delete memory_allocator;
 }
 
 
 TEST(OldSpace) {
   OS::Setup();
-  CHECK(HEAP->ConfigureHeapDefault());
-  CHECK(Isolate::Current()->memory_allocator()->Setup(
-      HEAP->MaxReserved(), HEAP->MaxExecutableSize()));
+  Isolate* isolate = Isolate::Current();
+  isolate->InitializeLoggingAndCounters();
+  Heap* heap = isolate->heap();
+  CHECK(heap->ConfigureHeapDefault());
+  MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
+  CHECK(memory_allocator->Setup(heap->MaxReserved(),
+                                heap->MaxExecutableSize()));
+  TestMemoryAllocatorScope test_scope(isolate, memory_allocator);
 
-  OldSpace* s = new OldSpace(HEAP,
-                             HEAP->MaxOldGenerationSize(),
+  OldSpace* s = new OldSpace(heap,
+                             heap->MaxOldGenerationSize(),
                              OLD_POINTER_SPACE,
                              NOT_EXECUTABLE);
   CHECK(s != NULL);
 
-  void* chunk =
-      Isolate::Current()->memory_allocator()->ReserveInitialChunk(
-          4 * HEAP->ReservedSemiSpaceSize());
+  void* chunk = 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));
 
@@ -209,13 +247,13 @@
 
   s->TearDown();
   delete s;
-  Isolate::Current()->memory_allocator()->TearDown();
+  memory_allocator->TearDown();
+  delete memory_allocator;
 }
 
 
 TEST(LargeObjectSpace) {
-  OS::Setup();
-  CHECK(HEAP->Setup(false));
+  v8::V8::Initialize();
 
   LargeObjectSpace* lo = HEAP->lo_space();
   CHECK(lo != NULL);
@@ -247,9 +285,4 @@
   CHECK(!lo->IsEmpty());
 
   CHECK(lo->AllocateRaw(lo_size)->IsFailure());
-
-  lo->TearDown();
-  delete lo;
-
-  Isolate::Current()->memory_allocator()->TearDown();
 }
diff --git a/test/cctest/test-weakmaps.cc b/test/cctest/test-weakmaps.cc
new file mode 100644
index 0000000..db4db25
--- /dev/null
+++ b/test/cctest/test-weakmaps.cc
@@ -0,0 +1,149 @@
+// 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 "global-handles.h"
+#include "snapshot.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+
+static Handle<JSWeakMap> AllocateJSWeakMap() {
+  Handle<Map> map = FACTORY->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
+  Handle<JSObject> weakmap_obj = FACTORY->NewJSObjectFromMap(map);
+  Handle<JSWeakMap> weakmap(JSWeakMap::cast(*weakmap_obj));
+  // Do not use handles for the hash table, it would make entries strong.
+  Object* table_obj = ObjectHashTable::Allocate(1)->ToObjectChecked();
+  ObjectHashTable* table = ObjectHashTable::cast(table_obj);
+  weakmap->set_table(table);
+  weakmap->set_next(Smi::FromInt(0));
+  return weakmap;
+}
+
+static void PutIntoWeakMap(Handle<JSWeakMap> weakmap,
+                           Handle<JSObject> key,
+                           int value) {
+  Handle<ObjectHashTable> table = PutIntoObjectHashTable(
+      Handle<ObjectHashTable>(weakmap->table()),
+      Handle<JSObject>(JSObject::cast(*key)),
+      Handle<Smi>(Smi::FromInt(value)));
+  weakmap->set_table(*table);
+}
+
+static int NumberOfWeakCalls = 0;
+static void WeakPointerCallback(v8::Persistent<v8::Value> handle, void* id) {
+  ASSERT(id == reinterpret_cast<void*>(1234));
+  NumberOfWeakCalls++;
+  handle.Dispose();
+}
+
+
+TEST(Weakness) {
+  LocalContext context;
+  v8::HandleScope scope;
+  Handle<JSWeakMap> weakmap = AllocateJSWeakMap();
+  GlobalHandles* global_handles = Isolate::Current()->global_handles();
+
+  // Keep global reference to the key.
+  Handle<Object> key;
+  {
+    v8::HandleScope scope;
+    Handle<Map> map = FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+    Handle<JSObject> object = FACTORY->NewJSObjectFromMap(map);
+    key = global_handles->Create(*object);
+  }
+  CHECK(!global_handles->IsWeak(key.location()));
+
+  // Put entry into weak map.
+  {
+    v8::HandleScope scope;
+    PutIntoWeakMap(weakmap, Handle<JSObject>(JSObject::cast(*key)), 23);
+  }
+  CHECK_EQ(1, weakmap->table()->NumberOfElements());
+
+  // Force a full GC.
+  HEAP->CollectAllGarbage(false);
+  CHECK_EQ(0, NumberOfWeakCalls);
+  CHECK_EQ(1, weakmap->table()->NumberOfElements());
+  CHECK_EQ(0, weakmap->table()->NumberOfDeletedElements());
+
+  // Make the global reference to the key weak.
+  {
+    v8::HandleScope scope;
+    global_handles->MakeWeak(key.location(),
+                             reinterpret_cast<void*>(1234),
+                             &WeakPointerCallback);
+  }
+  CHECK(global_handles->IsWeak(key.location()));
+
+  // Force a full GC.
+  // Perform two consecutive GCs because the first one will only clear
+  // weak references whereas the second one will also clear weak maps.
+  HEAP->CollectAllGarbage(false);
+  CHECK_EQ(1, NumberOfWeakCalls);
+  CHECK_EQ(1, weakmap->table()->NumberOfElements());
+  CHECK_EQ(0, weakmap->table()->NumberOfDeletedElements());
+  HEAP->CollectAllGarbage(false);
+  CHECK_EQ(1, NumberOfWeakCalls);
+  CHECK_EQ(0, weakmap->table()->NumberOfElements());
+  CHECK_EQ(1, weakmap->table()->NumberOfDeletedElements());
+}
+
+
+TEST(Shrinking) {
+  LocalContext context;
+  v8::HandleScope scope;
+  Handle<JSWeakMap> weakmap = AllocateJSWeakMap();
+
+  // Check initial capacity.
+  CHECK_EQ(32, weakmap->table()->Capacity());
+
+  // Fill up weak map to trigger capacity change.
+  {
+    v8::HandleScope scope;
+    Handle<Map> map = FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+    for (int i = 0; i < 32; i++) {
+      Handle<JSObject> object = FACTORY->NewJSObjectFromMap(map);
+      PutIntoWeakMap(weakmap, object, i);
+    }
+  }
+
+  // Check increased capacity.
+  CHECK_EQ(128, weakmap->table()->Capacity());
+
+  // Force a full GC.
+  CHECK_EQ(32, weakmap->table()->NumberOfElements());
+  CHECK_EQ(0, weakmap->table()->NumberOfDeletedElements());
+  HEAP->CollectAllGarbage(false);
+  CHECK_EQ(0, weakmap->table()->NumberOfElements());
+  CHECK_EQ(32, weakmap->table()->NumberOfDeletedElements());
+
+  // Check shrunk capacity.
+  CHECK_EQ(32, weakmap->table()->Capacity());
+}
diff --git a/test/cctest/testcfg.py b/test/cctest/testcfg.py
index a137275..b2eabc4 100644
--- a/test/cctest/testcfg.py
+++ b/test/cctest/testcfg.py
@@ -48,7 +48,11 @@
     return self.path[-1]
 
   def BuildCommand(self, name):
-    serialization_file = join('obj', 'test', self.mode, 'serdes')
+    serialization_file = ''
+    if exists(join(self.context.buildspace, 'obj', 'test', self.mode)):
+      serialization_file = join('obj', 'test', self.mode, 'serdes')
+    else:
+      serialization_file = join('obj', 'serdes')
     serialization_file += '_' + self.GetName()
     serialization_file = join(self.context.buildspace, serialization_file)
     serialization_file += ''.join(self.variant_flags).replace('-', '_')
@@ -78,10 +82,15 @@
     return ['cctests']
 
   def ListTests(self, current_path, path, mode, variant_flags):
-    executable = join('obj', 'test', mode, 'cctest')
+    executable = 'cctest'
     if utils.IsWindows():
       executable += '.exe'
     executable = join(self.context.buildspace, executable)
+    if not exists(executable):
+      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
diff --git a/test/mjsunit/d8-os.js b/test/mjsunit/d8-os.js
index 630a39e..fd6fb77 100644
--- a/test/mjsunit/d8-os.js
+++ b/test/mjsunit/d8-os.js
@@ -30,6 +30,9 @@
 // implemented on Windows, and even if it were then many of the things
 // we are calling would not be available.
 
+var TEST_DIR = "d8-os-test-directory-" + ((Math.random() * (1<<30)) | 0);
+
+
 function arg_error(str) {
   try {
     eval(str);
@@ -53,96 +56,98 @@
 if (this.os && os.system) {
   try {
     // Delete the dir if it is lying around from last time.
-    os.system("ls", ["d8-os-test-directory"]);
-    os.system("rm", ["-r", "d8-os-test-directory"]);
+    os.system("ls", [TEST_DIR]);
+    os.system("rm", ["-r", TEST_DIR]);
   } catch (e) {
   }
-  os.mkdirp("d8-os-test-directory");
-  os.chdir("d8-os-test-directory");
-  // Check the chdir worked.
-  os.system('ls', ['../d8-os-test-directory']);
-  // Simple create dir.
-  os.mkdirp("dir");
-  // Create dir in dir.
-  os.mkdirp("dir/foo");
-  // Check that they are there.
-  os.system('ls', ['dir/foo']);
-  // Check that we can detect when something is not there.
-  assertThrows("os.system('ls', ['dir/bar']);", "dir not there");
-  // Check that mkdirp makes intermediate directories.
-  os.mkdirp("dir2/foo");
-  os.system("ls", ["dir2/foo"]);
-  // Check that mkdirp doesn't mind if the dir is already there.
-  os.mkdirp("dir2/foo");
-  os.mkdirp("dir2/foo/");
-  // Check that mkdirp can cope with trailing /
-  os.mkdirp("dir3/");
-  os.system("ls", ["dir3"]);
-  // Check that we get an error if the name is taken by a file.
-  os.system("sh", ["-c", "echo foo > file1"]);
-  os.system("ls", ["file1"]);
-  assertThrows("os.mkdirp('file1');", "mkdir over file1");
-  assertThrows("os.mkdirp('file1/foo');", "mkdir over file2");
-  assertThrows("os.mkdirp('file1/');", "mkdir over file3");
-  assertThrows("os.mkdirp('file1/foo/');", "mkdir over file4");
-  // Create a dir we cannot read.
-  os.mkdirp("dir4", 0);
-  // This test fails if you are root since root can read any dir.
-  assertThrows("os.chdir('dir4');", "chdir dir4 I");
-  os.rmdir("dir4");
-  assertThrows("os.chdir('dir4');", "chdir dir4 II");
-  // Set umask.
-  var old_umask = os.umask(0777);
-  // Create a dir we cannot read.
-  os.mkdirp("dir5");
-  // This test fails if you are root since root can read any dir.
-  assertThrows("os.chdir('dir5');", "cd dir5 I");
-  os.rmdir("dir5");
-  assertThrows("os.chdir('dir5');", "chdir dir5 II");
-  os.umask(old_umask);
-
-  os.mkdirp("hest/fisk/../fisk/ged");
-  os.system("ls", ["hest/fisk/ged"]);
-
-  os.setenv("FOO", "bar");
-  var environment = os.system("printenv");
-  assertTrue(/FOO=bar/.test(environment));
-
-  // Check we time out.
-  var have_sleep = true;
-  var have_echo = true;
+  os.mkdirp(TEST_DIR);
+  os.chdir(TEST_DIR);
   try {
-    os.system("ls", ["/bin/sleep"]);
-  } catch (e) {
-    have_sleep = false;
-  }
-  try {
-    os.system("ls", ["/bin/echo"]);
-  } catch (e) {
-    have_echo = false;
-  }
-  if (have_sleep) {
-    assertThrows("os.system('sleep', ['2000'], 200);", "sleep 1");
+    // Check the chdir worked.
+    os.system('ls', ['../' + TEST_DIR]);
+    // Simple create dir.
+    os.mkdirp("dir");
+    // Create dir in dir.
+    os.mkdirp("dir/foo");
+    // Check that they are there.
+    os.system('ls', ['dir/foo']);
+    // Check that we can detect when something is not there.
+    assertThrows("os.system('ls', ['dir/bar']);", "dir not there");
+    // Check that mkdirp makes intermediate directories.
+    os.mkdirp("dir2/foo");
+    os.system("ls", ["dir2/foo"]);
+    // Check that mkdirp doesn't mind if the dir is already there.
+    os.mkdirp("dir2/foo");
+    os.mkdirp("dir2/foo/");
+    // Check that mkdirp can cope with trailing /
+    os.mkdirp("dir3/");
+    os.system("ls", ["dir3"]);
+    // Check that we get an error if the name is taken by a file.
+    os.system("sh", ["-c", "echo foo > file1"]);
+    os.system("ls", ["file1"]);
+    assertThrows("os.mkdirp('file1');", "mkdir over file1");
+    assertThrows("os.mkdirp('file1/foo');", "mkdir over file2");
+    assertThrows("os.mkdirp('file1/');", "mkdir over file3");
+    assertThrows("os.mkdirp('file1/foo/');", "mkdir over file4");
+    // Create a dir we cannot read.
+    os.mkdirp("dir4", 0);
+    // This test fails if you are root since root can read any dir.
+    assertThrows("os.chdir('dir4');", "chdir dir4 I");
+    os.rmdir("dir4");
+    assertThrows("os.chdir('dir4');", "chdir dir4 II");
+    // Set umask.
+    var old_umask = os.umask(0777);
+    // Create a dir we cannot read.
+    os.mkdirp("dir5");
+    // This test fails if you are root since root can read any dir.
+    assertThrows("os.chdir('dir5');", "cd dir5 I");
+    os.rmdir("dir5");
+    assertThrows("os.chdir('dir5');", "chdir dir5 II");
+    os.umask(old_umask);
 
-    // Check we time out with total time.
-    assertThrows("os.system('sleep', ['2000'], -1, 200);", "sleep 2");
+    os.mkdirp("hest/fisk/../fisk/ged");
+    os.system("ls", ["hest/fisk/ged"]);
 
-    // Check that -1 means no timeout.
-    os.system('sleep', ['1'], -1, -1);
+    os.setenv("FOO", "bar");
+    var environment = os.system("printenv");
+    assertTrue(/FOO=bar/.test(environment));
 
-  }
+    // Check we time out.
+    var have_sleep = true;
+    var have_echo = true;
+    try {
+      os.system("ls", ["/bin/sleep"]);
+    } catch (e) {
+      have_sleep = false;
+    }
+    try {
+      os.system("ls", ["/bin/echo"]);
+    } catch (e) {
+      have_echo = false;
+    }
+    if (have_sleep) {
+      assertThrows("os.system('sleep', ['2000'], 200);", "sleep 1");
 
-  // Check that we don't fill up the process table with zombies.
-  // Disabled because it's too slow.
-  if (have_echo) {
-    //for (var i = 0; i < 65536; i++) {
+      // Check we time out with total time.
+      assertThrows("os.system('sleep', ['2000'], -1, 200);", "sleep 2");
+
+      // Check that -1 means no timeout.
+      os.system('sleep', ['1'], -1, -1);
+
+    }
+
+    // Check that we don't fill up the process table with zombies.
+    // Disabled because it's too slow.
+    if (have_echo) {
+      //for (var i = 0; i < 65536; i++) {
       assertEquals("baz\n", os.system("echo", ["baz"]));
-    //}
+      //}
+    }
+  } finally {
+    os.chdir("..");
+    os.system("rm", ["-r", TEST_DIR]);
   }
 
-  os.chdir("..");
-  os.system("rm", ["-r", "d8-os-test-directory"]);
-
   // Too few args.
   arg_error("os.umask();");
   arg_error("os.system();");
diff --git a/test/mjsunit/harmony/weakmaps.js b/test/mjsunit/harmony/weakmaps.js
new file mode 100644
index 0000000..d98db10
--- /dev/null
+++ b/test/mjsunit/harmony/weakmaps.js
@@ -0,0 +1,145 @@
+// 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.
+
+// Flags: --harmony-weakmaps --expose-gc
+
+
+// Test valid getter and setter calls
+var m = new WeakMap;
+assertDoesNotThrow(function () { m.get(new Object) });
+assertDoesNotThrow(function () { m.set(new Object) });
+assertDoesNotThrow(function () { m.has(new Object) });
+assertDoesNotThrow(function () { m.delete(new Object) });
+
+
+// Test invalid getter and setter calls
+var m = new WeakMap;
+assertThrows(function () { m.get(undefined) }, TypeError);
+assertThrows(function () { m.set(undefined, 0) }, TypeError);
+assertThrows(function () { m.get(0) }, TypeError);
+assertThrows(function () { m.set(0, 0) }, TypeError);
+assertThrows(function () { m.get('a-key') }, TypeError);
+assertThrows(function () { m.set('a-key', 0) }, TypeError);
+
+
+// Test expected mapping behavior
+var m = new WeakMap;
+function TestMapping(map, key, value) {
+  map.set(key, value);
+  assertSame(value, map.get(key));
+}
+TestMapping(m, new Object, 23);
+TestMapping(m, new Object, 'the-value');
+TestMapping(m, new Object, new Object);
+
+
+// Test expected querying behavior
+var m = new WeakMap;
+var key = new Object;
+TestMapping(m, key, 'to-be-present');
+assertTrue(m.has(key));
+assertFalse(m.has(new Object));
+TestMapping(m, key, undefined);
+assertFalse(m.has(key));
+assertFalse(m.has(new Object));
+
+
+// Test expected deletion behavior
+var m = new WeakMap;
+var key = new Object;
+TestMapping(m, key, 'to-be-deleted');
+assertTrue(m.delete(key));
+assertFalse(m.delete(key));
+assertFalse(m.delete(new Object));
+assertSame(m.get(key), undefined);
+
+
+// Test GC of map with entry
+var m = new WeakMap;
+var key = new Object;
+m.set(key, 'not-collected');
+gc();
+assertSame('not-collected', m.get(key));
+
+
+// Test GC of map with chained entries
+var m = new WeakMap;
+var head = new Object;
+for (key = head, i = 0; i < 10; i++, key = m.get(key)) {
+  m.set(key, new Object);
+}
+gc();
+var count = 0;
+for (key = head; key != undefined; key = m.get(key)) {
+  count++;
+}
+assertEquals(11, count);
+
+
+// Test property attribute [[Enumerable]]
+var m = new WeakMap;
+function props(x) {
+  var array = [];
+  for (var p in x) array.push(p);
+  return array.sort();
+}
+assertArrayEquals([], props(WeakMap));
+assertArrayEquals([], props(WeakMap.prototype));
+assertArrayEquals([], props(m));
+
+
+// Test arbitrary properties on weak maps
+var m = new WeakMap;
+function TestProperty(map, property, value) {
+  map[property] = value;
+  assertEquals(value, map[property]);
+}
+for (i = 0; i < 20; i++) {
+  TestProperty(m, i, 'val' + i);
+  TestProperty(m, 'foo' + i, 'bar' + i);
+}
+TestMapping(m, new Object, 'foobar');
+
+
+// Test direct constructor call
+var m = WeakMap();
+assertTrue(m instanceof WeakMap);
+
+
+// Test some common JavaScript idioms
+var m = new WeakMap;
+assertTrue(m instanceof WeakMap);
+assertTrue(WeakMap.prototype.set instanceof Function)
+assertTrue(WeakMap.prototype.get instanceof Function)
+assertTrue(WeakMap.prototype.has instanceof Function)
+assertTrue(WeakMap.prototype.delete instanceof Function)
+
+
+// Stress Test
+// There is a proposed stress-test available at the es-discuss mailing list
+// which cannot be reasonably automated.  Check it out by hand if you like:
+// https://mail.mozilla.org/pipermail/es-discuss/2011-May/014096.html
diff --git a/test/mjsunit/math-floor.js b/test/mjsunit/math-floor.js
index c299203..11f4cd7 100644
--- a/test/mjsunit/math-floor.js
+++ b/test/mjsunit/math-floor.js
@@ -51,17 +51,6 @@
   testFloor(-Infinity, -Infinity);
   testFloor(NaN, NaN);
 
-  // Ensure that a negative zero coming from Math.floor is properly handled
-  // by other operations.
-  function ifloor(x) {
-    return 1 / Math.floor(x);
-  }
-  assertEquals(-Infinity, ifloor(-0));
-  assertEquals(-Infinity, ifloor(-0));
-  assertEquals(-Infinity, ifloor(-0));
-  %OptimizeFunctionOnNextCall(ifloor);
-  assertEquals(-Infinity, ifloor(-0));
-
   testFloor(0, 0.1);
   testFloor(0, 0.49999999999999994);
   testFloor(0, 0.5);
@@ -140,19 +129,3 @@
 for (var i = 0; i < 500; i++) {
   test();
 }
-
-
-// Regression test for a bug where a negative zero coming from Math.floor
-// was not properly handled by other operations.
-function floorsum(i, n) {
-  var ret = Math.floor(n);
-  while (--i > 0) {
-    ret += Math.floor(n);
-  }
-  return ret;
-}
-assertEquals(-0, floorsum(1, -0));
-%OptimizeFunctionOnNextCall(floorsum);
-// The optimized function will deopt.  Run it with enough iterations to try
-// to optimize via OSR (triggering the bug).
-assertEquals(-0, floorsum(100000, -0));
diff --git a/test/mjsunit/math-round.js b/test/mjsunit/math-round.js
index 973040d..1366557 100644
--- a/test/mjsunit/math-round.js
+++ b/test/mjsunit/math-round.js
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -44,21 +44,6 @@
 testRound(-Infinity, -Infinity);
 testRound(NaN, NaN);
 
-// Regression test for a bug where a negative zero coming from Math.round
-// was not properly handled by other operations.
-function roundsum(i, n) {
-  var ret = Math.round(n);
-  while (--i > 0) {
-    ret += Math.round(n);
-  }
-  return ret;
-}
-assertEquals(-0, roundsum(1, -0));
-%OptimizeFunctionOnNextCall(roundsum);
-// The optimized function will deopt.  Run it with enough iterations to try
-// to optimize via OSR (triggering the bug).
-assertEquals(-0, roundsum(100000, -0));
-
 testRound(1, 0.5);
 testRound(1, 0.7);
 testRound(1, 1);
diff --git a/src/shell.h b/test/mjsunit/regress/regress-1419.js
similarity index 66%
rename from src/shell.h
rename to test/mjsunit/regress/regress-1419.js
index ca51040..98a8b76 100644
--- a/src/shell.h
+++ b/test/mjsunit/regress/regress-1419.js
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 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:
@@ -24,32 +24,24 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// A simple interactive shell.  Enable with --shell.
 
-#ifndef V8_SHELL_H_
-#define V8_SHELL_H_
+// Test that using bind several time does not change the length of existing
+// bound functions.
 
-#include "../public/debug.h"
+function foo() {
+}
 
-namespace v8 {
-namespace internal {
+var f1 = function (x) {}.bind(foo);
+var f2 = function () {};
 
-// Debug event handler for interactive debugging.
-void handle_debug_event(v8::DebugEvent event,
-                        v8::Handle<v8::Object> exec_state,
-                        v8::Handle<v8::Object> event_data,
-                        v8::Handle<Value> data);
+assertEquals(1, f1.length);
 
+// the object we bind to can be any object
+f2.bind(foo);
 
-class Shell {
- public:
-  static void PrintObject(v8::Handle<v8::Value> obj);
-  // Run the read-eval loop, executing code in the specified
-  // environment.
-  static void Run(v8::Handle<v8::Context> context);
-};
+assertEquals(1, f1.length);
 
-} }  // namespace v8::internal
-
-#endif  // V8_SHELL_H_
+var desc = Object.getOwnPropertyDescriptor(f1, 'length');
+assertEquals(false, desc.writable);
+assertEquals(false, desc.enumerable);
+assertEquals(false, desc.configurable);
diff --git a/src/shell.h b/test/mjsunit/regress/regress-1546.js
similarity index 66%
copy from src/shell.h
copy to test/mjsunit/regress/regress-1546.js
index ca51040..7f1fa58 100644
--- a/src/shell.h
+++ b/test/mjsunit/regress/regress-1546.js
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 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:
@@ -24,32 +24,9 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// A simple interactive shell.  Enable with --shell.
 
-#ifndef V8_SHELL_H_
-#define V8_SHELL_H_
+// See: http://code.google.com/p/v8/issues/detail?id=1546
 
-#include "../public/debug.h"
-
-namespace v8 {
-namespace internal {
-
-// Debug event handler for interactive debugging.
-void handle_debug_event(v8::DebugEvent event,
-                        v8::Handle<v8::Object> exec_state,
-                        v8::Handle<v8::Object> event_data,
-                        v8::Handle<Value> data);
-
-
-class Shell {
- public:
-  static void PrintObject(v8::Handle<v8::Value> obj);
-  // Run the read-eval loop, executing code in the specified
-  // environment.
-  static void Run(v8::Handle<v8::Context> context);
-};
-
-} }  // namespace v8::internal
-
-#endif  // V8_SHELL_H_
+// Should't throw. Scanner incorrectly truncated to char before comparing
+// with "*", so it ended the comment early.
+eval("/*\u822a/ */");
\ No newline at end of file
diff --git a/src/shell.h b/test/mjsunit/regress/regress-1583.js
similarity index 64%
copy from src/shell.h
copy to test/mjsunit/regress/regress-1583.js
index ca51040..c4a344c 100644
--- a/src/shell.h
+++ b/test/mjsunit/regress/regress-1583.js
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 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:
@@ -24,32 +24,34 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// A simple interactive shell.  Enable with --shell.
 
-#ifndef V8_SHELL_H_
-#define V8_SHELL_H_
+// Flags: --allow-natives-syntax
 
-#include "../public/debug.h"
+// Regression test for a bug in recompilation of anonymous functions inside
+// catch.  We would incorrectly hoist them outside the catch in some cases.
+function f() {
+  try {
+    throw 0;
+  } catch (e) {
+    try {
+      var x = { a: 'hest' };
+      x.m = function (e) { return x.a; };
+    } catch (e) {
+    }
+  }
+  return x;
+}
 
-namespace v8 {
-namespace internal {
+var o = f();
+assertEquals('hest', o.m());
+assertEquals('hest', o.m());
+assertEquals('hest', o.m());
+%OptimizeFunctionOnNextCall(o.m);
+assertEquals('hest', o.m());
 
-// Debug event handler for interactive debugging.
-void handle_debug_event(v8::DebugEvent event,
-                        v8::Handle<v8::Object> exec_state,
-                        v8::Handle<v8::Object> event_data,
-                        v8::Handle<Value> data);
-
-
-class Shell {
- public:
-  static void PrintObject(v8::Handle<v8::Value> obj);
-  // Run the read-eval loop, executing code in the specified
-  // environment.
-  static void Run(v8::Handle<v8::Context> context);
-};
-
-} }  // namespace v8::internal
-
-#endif  // V8_SHELL_H_
+// Fixing the bug above introduced (revealed?) an inconsistency in named
+// getters and setters.  The property name was also treated as a function
+// name.
+var global = 'horse';
+var p = { get global() { return global; }};
+assertEquals('horse', p.global);
diff --git a/src/shell.h b/test/mjsunit/regress/regress-1586.js
similarity index 61%
copy from src/shell.h
copy to test/mjsunit/regress/regress-1586.js
index ca51040..b15e2f2 100644
--- a/src/shell.h
+++ b/test/mjsunit/regress/regress-1586.js
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 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:
@@ -24,32 +24,41 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// A simple interactive shell.  Enable with --shell.
 
-#ifndef V8_SHELL_H_
-#define V8_SHELL_H_
+// Flags: --expose-debug-as debug
 
-#include "../public/debug.h"
+// Test debug evaluation for functions without local context, but with
+// nested catch contexts.
 
-namespace v8 {
-namespace internal {
-
-// Debug event handler for interactive debugging.
-void handle_debug_event(v8::DebugEvent event,
-                        v8::Handle<v8::Object> exec_state,
-                        v8::Handle<v8::Object> event_data,
-                        v8::Handle<Value> data);
-
-
-class Shell {
- public:
-  static void PrintObject(v8::Handle<v8::Value> obj);
-  // Run the read-eval loop, executing code in the specified
-  // environment.
-  static void Run(v8::Handle<v8::Context> context);
+function f() {
+  var i = 1;          // Line 1.
+  {                   // Line 2.
+    try {             // Line 3.
+      throw 'stuff';  // Line 4.
+    } catch (e) {     // Line 5.
+      x = 2;          // Line 6.
+    }
+  }
 };
 
-} }  // namespace v8::internal
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+// Set breakpoint on line 6.
+var bp = Debug.setBreakPoint(f, 6);
 
-#endif  // V8_SHELL_H_
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    result = exec_state.frame().evaluate("i").value();
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+result = -1;
+f();
+assertEquals(1, result);
+
+// Clear breakpoint.
+Debug.clearBreakPoint(bp);
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/test/mjsunit/regress/regress-91517.js b/test/mjsunit/regress/regress-91517.js
new file mode 100644
index 0000000..68a768c
--- /dev/null
+++ b/test/mjsunit/regress/regress-91517.js
@@ -0,0 +1,112 @@
+// 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.
+
+// Getting property names of an object with a prototype chain that
+// triggers dictionary elements in GetLocalPropertyNames() shouldn't
+// crash the runtime
+
+// Flags: --allow-natives-syntax
+
+function Object1() {
+  this.foo = 1;
+}
+
+function Object2() {
+  this.fuz = 2;
+  this.objects = new Object();
+  this.fuz1 = 2;
+  this.fuz2 = 2;
+  this.fuz3 = 2;
+  this.fuz4 = 2;
+  this.fuz5 = 2;
+  this.fuz6 = 2;
+  this.fuz7 = 2;
+  this.fuz8 = 2;
+  this.fuz9 = 2;
+  this.fuz10 = 2;
+  this.fuz11 = 2;
+  this.fuz12 = 2;
+  this.fuz13 = 2;
+  this.fuz14 = 2;
+  this.fuz15 = 2;
+  this.fuz16 = 2;
+  this.fuz17 = 2;
+  // Force dictionary-based properties
+  for (x=1;x<1000;x++) {
+    this["sdf" + x] = 2;
+  }
+}
+
+function Object3() {
+  this.boo = 3;
+}
+
+function Object4() {
+  this.baz = 4;
+}
+
+obj1 = new Object1();
+obj2 = new Object2();
+obj3 = new Object3();
+obj4 = new Object4();
+
+%SetHiddenPrototype(obj4, obj3);
+%SetHiddenPrototype(obj3, obj2);
+%SetHiddenPrototype(obj2, obj1);
+
+function contains(a, obj) {
+  for(var i = 0; i < a.length; i++) {
+    if(a[i] === obj){
+      return true;
+    }
+  }
+  return false;
+}
+names = %GetLocalPropertyNames(obj4);
+assertEquals(1021, names.length);
+assertTrue(contains(names, "baz"));
+assertTrue(contains(names, "boo"));
+assertTrue(contains(names, "foo"));
+assertTrue(contains(names, "fuz"));
+assertTrue(contains(names, "fuz1"));
+assertTrue(contains(names, "fuz2"));
+assertTrue(contains(names, "fuz3"));
+assertTrue(contains(names, "fuz4"));
+assertTrue(contains(names, "fuz5"));
+assertTrue(contains(names, "fuz6"));
+assertTrue(contains(names, "fuz7"));
+assertTrue(contains(names, "fuz8"));
+assertTrue(contains(names, "fuz9"));
+assertTrue(contains(names, "fuz10"));
+assertTrue(contains(names, "fuz11"));
+assertTrue(contains(names, "fuz12"));
+assertTrue(contains(names, "fuz13"));
+assertTrue(contains(names, "fuz14"));
+assertTrue(contains(names, "fuz15"));
+assertTrue(contains(names, "fuz16"));
+assertTrue(contains(names, "fuz17"));
+assertFalse(names[1020] == undefined);
diff --git a/src/shell.h b/test/mjsunit/regress/regress-91787.js
similarity index 66%
copy from src/shell.h
copy to test/mjsunit/regress/regress-91787.js
index ca51040..96310d0 100644
--- a/src/shell.h
+++ b/test/mjsunit/regress/regress-91787.js
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 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:
@@ -24,32 +24,12 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// A simple interactive shell.  Enable with --shell.
 
-#ifndef V8_SHELL_H_
-#define V8_SHELL_H_
+// Unterminated non-ASCII string literals in JSON code were not
+// detected correctly.
 
-#include "../public/debug.h"
-
-namespace v8 {
-namespace internal {
-
-// Debug event handler for interactive debugging.
-void handle_debug_event(v8::DebugEvent event,
-                        v8::Handle<v8::Object> exec_state,
-                        v8::Handle<v8::Object> event_data,
-                        v8::Handle<Value> data);
-
-
-class Shell {
- public:
-  static void PrintObject(v8::Handle<v8::Value> obj);
-  // Run the read-eval loop, executing code in the specified
-  // environment.
-  static void Run(v8::Handle<v8::Context> context);
-};
-
-} }  // namespace v8::internal
-
-#endif  // V8_SHELL_H_
+// Shouldn't crash (due to stack overflow).
+// Should throw due to invalid syntax.
+assertThrows(function() {
+  JSON.parse('"\x80unterminated');
+});
diff --git a/test/preparser/testcfg.py b/test/preparser/testcfg.py
index 39b62c3..d900e26 100644
--- a/test/preparser/testcfg.py
+++ b/test/preparser/testcfg.py
@@ -27,7 +27,7 @@
 
 import test
 import os
-from os.path import join, dirname, exists
+from os.path import join, dirname, exists, isfile
 import platform
 import utils
 import re
@@ -122,10 +122,15 @@
          {"Test": Test, "Template": Template}, {})
 
   def ListTests(self, current_path, path, mode, variant_flags):
-    executable = join('obj', 'preparser', mode, 'preparser')
+    executable = 'preparser'
     if utils.IsWindows():
       executable += '.exe'
     executable = join(self.context.buildspace, executable)
+    if not isfile(executable):
+      executable = join('obj', 'preparser', mode, 'preparser')
+      if utils.IsWindows():
+        executable += '.exe'
+      executable = join(self.context.buildspace, executable)
     expectations = self.GetExpectations()
     result = []
     # Find all .js files in tests/preparser directory.
diff --git a/tools/grokdump.py b/tools/grokdump.py
index 468e7cc..6bc49c6 100755
--- a/tools/grokdump.py
+++ b/tools/grokdump.py
@@ -345,7 +345,7 @@
       for r in self.memory_list64.ranges:
         if r.start <= address < r.start + r.size:
           return self.memory_list64.base_rva + offset + address - r.start
-      offset += r.size
+        offset += r.size
     if self.memory_list is not None:
       for r in self.memory_list.ranges:
         if r.start <= address < r.start + r.memory.data_size:
@@ -379,64 +379,65 @@
 # };
 # static P p;
 INSTANCE_TYPES = {
-64: "SYMBOL_TYPE",
-68: "ASCII_SYMBOL_TYPE",
-65: "CONS_SYMBOL_TYPE",
-69: "CONS_ASCII_SYMBOL_TYPE",
-66: "EXTERNAL_SYMBOL_TYPE",
-74: "EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE",
-70: "EXTERNAL_ASCII_SYMBOL_TYPE",
-0: "STRING_TYPE",
-4: "ASCII_STRING_TYPE",
-1: "CONS_STRING_TYPE",
-5: "CONS_ASCII_STRING_TYPE",
-2: "EXTERNAL_STRING_TYPE",
-10: "EXTERNAL_STRING_WITH_ASCII_DATA_TYPE",
-6: "EXTERNAL_ASCII_STRING_TYPE",
-6: "PRIVATE_EXTERNAL_ASCII_STRING_TYPE",
-128: "MAP_TYPE",
-129: "CODE_TYPE",
-130: "ODDBALL_TYPE",
-131: "JS_GLOBAL_PROPERTY_CELL_TYPE",
-132: "HEAP_NUMBER_TYPE",
-133: "FOREIGN_TYPE",
-134: "BYTE_ARRAY_TYPE",
-135: "EXTERNAL_BYTE_ARRAY_TYPE",
-136: "EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE",
-137: "EXTERNAL_SHORT_ARRAY_TYPE",
-138: "EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE",
-139: "EXTERNAL_INT_ARRAY_TYPE",
-140: "EXTERNAL_UNSIGNED_INT_ARRAY_TYPE",
-141: "EXTERNAL_FLOAT_ARRAY_TYPE",
-143: "EXTERNAL_PIXEL_ARRAY_TYPE",
-145: "FILLER_TYPE",
-146: "ACCESSOR_INFO_TYPE",
-147: "ACCESS_CHECK_INFO_TYPE",
-148: "INTERCEPTOR_INFO_TYPE",
-149: "CALL_HANDLER_INFO_TYPE",
-150: "FUNCTION_TEMPLATE_INFO_TYPE",
-151: "OBJECT_TEMPLATE_INFO_TYPE",
-152: "SIGNATURE_INFO_TYPE",
-153: "TYPE_SWITCH_INFO_TYPE",
-154: "SCRIPT_TYPE",
-155: "CODE_CACHE_TYPE",
-156: "POLYMORPHIC_CODE_CACHE_TYPE",
-159: "FIXED_ARRAY_TYPE",
-160: "SHARED_FUNCTION_INFO_TYPE",
-161: "JS_MESSAGE_OBJECT_TYPE",
-162: "JS_VALUE_TYPE",
-163: "JS_OBJECT_TYPE",
-164: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
-165: "JS_GLOBAL_OBJECT_TYPE",
-166: "JS_BUILTINS_OBJECT_TYPE",
-167: "JS_GLOBAL_PROXY_TYPE",
-168: "JS_ARRAY_TYPE",
-169: "JS_PROXY_TYPE",
-170: "JS_REGEXP_TYPE",
-171: "JS_FUNCTION_TYPE",
-172: "JS_FUNCTION_PROXY_TYPE",
-157: "DEBUG_INFO_TYPE",
-158: "BREAK_POINT_INFO_TYPE",
+  64: "SYMBOL_TYPE",
+  68: "ASCII_SYMBOL_TYPE",
+  65: "CONS_SYMBOL_TYPE",
+  69: "CONS_ASCII_SYMBOL_TYPE",
+  66: "EXTERNAL_SYMBOL_TYPE",
+  74: "EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE",
+  70: "EXTERNAL_ASCII_SYMBOL_TYPE",
+  0: "STRING_TYPE",
+  4: "ASCII_STRING_TYPE",
+  1: "CONS_STRING_TYPE",
+  5: "CONS_ASCII_STRING_TYPE",
+  2: "EXTERNAL_STRING_TYPE",
+  10: "EXTERNAL_STRING_WITH_ASCII_DATA_TYPE",
+  6: "EXTERNAL_ASCII_STRING_TYPE",
+  6: "PRIVATE_EXTERNAL_ASCII_STRING_TYPE",
+  128: "MAP_TYPE",
+  129: "CODE_TYPE",
+  130: "ODDBALL_TYPE",
+  131: "JS_GLOBAL_PROPERTY_CELL_TYPE",
+  132: "HEAP_NUMBER_TYPE",
+  133: "FOREIGN_TYPE",
+  134: "BYTE_ARRAY_TYPE",
+  135: "EXTERNAL_BYTE_ARRAY_TYPE",
+  136: "EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE",
+  137: "EXTERNAL_SHORT_ARRAY_TYPE",
+  138: "EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE",
+  139: "EXTERNAL_INT_ARRAY_TYPE",
+  140: "EXTERNAL_UNSIGNED_INT_ARRAY_TYPE",
+  141: "EXTERNAL_FLOAT_ARRAY_TYPE",
+  143: "EXTERNAL_PIXEL_ARRAY_TYPE",
+  145: "FILLER_TYPE",
+  146: "ACCESSOR_INFO_TYPE",
+  147: "ACCESS_CHECK_INFO_TYPE",
+  148: "INTERCEPTOR_INFO_TYPE",
+  149: "CALL_HANDLER_INFO_TYPE",
+  150: "FUNCTION_TEMPLATE_INFO_TYPE",
+  151: "OBJECT_TEMPLATE_INFO_TYPE",
+  152: "SIGNATURE_INFO_TYPE",
+  153: "TYPE_SWITCH_INFO_TYPE",
+  154: "SCRIPT_TYPE",
+  155: "CODE_CACHE_TYPE",
+  156: "POLYMORPHIC_CODE_CACHE_TYPE",
+  159: "FIXED_ARRAY_TYPE",
+  160: "SHARED_FUNCTION_INFO_TYPE",
+  161: "JS_MESSAGE_OBJECT_TYPE",
+  162: "JS_VALUE_TYPE",
+  163: "JS_OBJECT_TYPE",
+  164: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
+  165: "JS_GLOBAL_OBJECT_TYPE",
+  166: "JS_BUILTINS_OBJECT_TYPE",
+  167: "JS_GLOBAL_PROXY_TYPE",
+  168: "JS_ARRAY_TYPE",
+  169: "JS_PROXY_TYPE",
+  170: "JS_WEAK_MAP_TYPE",
+  171: "JS_REGEXP_TYPE",
+  172: "JS_FUNCTION_TYPE",
+  173: "JS_FUNCTION_PROXY_TYPE",
+  157: "DEBUG_INFO_TYPE",
+  158: "BREAK_POINT_INFO_TYPE",
 }
 
 
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 2650483..c802e86 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -54,6 +54,12 @@
     # well when compiling for the ARM target.
     'v8_use_arm_eabi_hardfloat%': 'false',
 
+    'v8_enable_debugger_support%': 1,
+
+    # Chrome needs this definition unconditionally. For standalone V8 builds,
+    # it's handled in common.gypi.
+    'want_separate_host_toolset%': 1,
+
     'v8_use_snapshot%': 'true',
     'host_os%': '<(OS)',
     'v8_use_liveobjectlist%': 'false',
@@ -61,10 +67,11 @@
   'conditions': [
     ['use_system_v8==0', {
       'target_defaults': {
-        'defines': [
-          'ENABLE_DEBUGGER_SUPPORT',
-        ],
         'conditions': [
+          ['v8_enable_debugger_support==1', {
+              'defines': ['ENABLE_DEBUGGER_SUPPORT',],
+            },
+          ],
           ['OS!="mac"', {
             # TODO(mark): The OS!="mac" conditional is temporary. It can be
             # removed once the Mac Chromium build stops setting target_arch to
@@ -97,6 +104,19 @@
                       'USE_EABI_HARDFLOAT=1',
                       'CAN_USE_VFP_INSTRUCTIONS',
                     ],
+                    'cflags': [
+                      '-mfloat-abi=hard',
+                    ],
+                  }, {
+                    'defines': [
+                      'USE_EABI_HARDFLOAT=0',
+                    ],
+                  }],
+                  # The ARM assembler assumes the host is 32 bits,
+                  # so force building 32-bit host tools.
+                  [ 'host_arch=="x64"', {
+                    'cflags': ['-m32'],
+                    'ldflags': ['-m32'],
                   }],
                 ],
               }],
@@ -149,12 +169,20 @@
               },
               'VCLinkerTool': {
                 'LinkIncremental': '2',
+                # For future reference, the stack size needs to be increased
+                # when building for Windows 64-bit, otherwise some test cases
+                # can cause stack overflow.
+                # 'StackReserveSize': '297152',
               },
             },
             'conditions': [
              ['OS=="freebsd" or OS=="openbsd"', {
                'cflags': [ '-I/usr/local/include' ],
              }],
+             ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
+               'cflags': [ '-Wall', '-Werror', '-W', '-Wno-unused-parameter',
+                           '-Wnon-virtual-dtor' ],
+             }],
            ],
           },
           'Release': {
@@ -219,6 +247,10 @@
                     'OptimizeReferences': '2',
                     'OptimizeForWindows98': '1',
                     'EnableCOMDATFolding': '2',
+                    # For future reference, the stack size needs to be
+                    # increased when building for Windows 64-bit, otherwise
+                    # some test cases can cause stack overflow.
+                    # 'StackReserveSize': '297152',
                   },
                 },
               }],
@@ -229,8 +261,12 @@
       'targets': [
         {
           'target_name': 'v8',
-          'toolsets': ['host', 'target'],
           'conditions': [
+            ['want_separate_host_toolset==1', {
+              'toolsets': ['host', 'target'],
+            }, {
+              'toolsets': ['target'],
+            }],
             ['v8_use_snapshot=="true"', {
               'dependencies': ['v8_snapshot'],
             },
@@ -272,23 +308,23 @@
           ],
           'direct_dependent_settings': {
             'include_dirs': [
-               '../../include',
+              '../../include',
             ],
           },
         },
         {
           'target_name': 'v8_snapshot',
           'type': '<(library)',
-          'toolsets': ['host', 'target'],
           'conditions': [
+            ['want_separate_host_toolset==1', {
+              'toolsets': ['host', 'target'],
+              'dependencies': ['mksnapshot#host', 'js2c#host'],
+            }, {
+              'toolsets': ['target'],
+              'dependencies': ['mksnapshot', 'js2c'],
+            }],
             ['component=="shared_library"', {
               'conditions': [
-                # The ARM assembler assumes the host is 32 bits, so force building
-                # 32-bit host tools.
-                ['v8_target_arch=="arm" and host_arch=="x64" and _toolset=="host"', {
-                  'cflags': ['-m32'],
-                  'ldflags': ['-m32'],
-                }],
                 ['OS=="win"', {
                   'defines': [
                     'BUILDING_V8_SHARED',
@@ -312,8 +348,6 @@
             }],
           ],
           'dependencies': [
-            'mksnapshot#host',
-            'js2c#host',
             'v8_base',
           ],
           'include_dirs+': [
@@ -380,9 +414,7 @@
         {
           'target_name': 'v8_nosnapshot',
           'type': '<(library)',
-          'toolsets': ['host', 'target'],
           'dependencies': [
-            'js2c#host',
             'v8_base',
           ],
           'include_dirs+': [
@@ -394,11 +426,12 @@
             '../../src/snapshot-empty.cc',
           ],
           'conditions': [
-            # The ARM assembler assumes the host is 32 bits, so force building
-            # 32-bit host tools.
-            ['v8_target_arch=="arm" and host_arch=="x64" and _toolset=="host"', {
-              'cflags': ['-m32'],
-              'ldflags': ['-m32'],
+            ['want_separate_host_toolset==1', {
+              'toolsets': ['host', 'target'],
+              'dependencies': ['js2c#host'],
+            }, {
+              'toolsets': ['target'],
+              'dependencies': ['js2c'],
             }],
             ['component=="shared_library"', {
               'defines': [
@@ -411,7 +444,6 @@
         {
           'target_name': 'v8_base',
           'type': '<(library)',
-          'toolsets': ['host', 'target'],
           'include_dirs+': [
             '../../src',
           ],
@@ -488,6 +520,8 @@
             '../../src/diy-fp.cc',
             '../../src/diy-fp.h',
             '../../src/double.h',
+            '../../src/elements.cc',
+            '../../src/elements.h',
             '../../src/execution.cc',
             '../../src/execution.h',
             '../../src/factory.cc',
@@ -610,7 +644,6 @@
             '../../src/scopes.h',
             '../../src/serialize.cc',
             '../../src/serialize.h',
-            '../../src/shell.h',
             '../../src/small-pointer-list.h',
             '../../src/smart-pointer.h',
             '../../src/snapshot-common.cc',
@@ -666,10 +699,12 @@
             '../../src/extensions/gc-extension.h',
           ],
           'conditions': [
+            ['want_separate_host_toolset==1', {
+              'toolsets': ['host', 'target'],
+            }, {
+              'toolsets': ['target'],
+            }],
             ['v8_target_arch=="arm"', {
-              'include_dirs+': [
-                '../../src/arm',
-              ],
               'sources': [
                 '../../src/arm/assembler-arm-inl.h',
                 '../../src/arm/assembler-arm.cc',
@@ -702,19 +737,8 @@
                 '../../src/arm/simulator-arm.cc',
                 '../../src/arm/stub-cache-arm.cc',
               ],
-              'conditions': [
-                # The ARM assembler assumes the host is 32 bits,
-                # so force building 32-bit host tools.
-                ['host_arch=="x64" and _toolset=="host"', {
-                  'cflags': ['-m32'],
-                  'ldflags': ['-m32'],
-                }]
-              ]
             }],
             ['v8_target_arch=="ia32" or v8_target_arch=="mac" or OS=="mac"', {
-              'include_dirs+': [
-                '../../src/ia32',
-              ],
               'sources': [
                 '../../src/ia32/assembler-ia32-inl.h',
                 '../../src/ia32/assembler-ia32.cc',
@@ -746,9 +770,6 @@
               ],
             }],
             ['v8_target_arch=="x64" or v8_target_arch=="mac" or OS=="mac"', {
-              'include_dirs+': [
-                '../../src/x64',
-              ],
               'sources': [
                 '../../src/x64/assembler-x64-inl.h',
                 '../../src/x64/assembler-x64.cc',
@@ -781,10 +802,6 @@
             }],
             ['OS=="linux"', {
                 'link_settings': {
-                  'libraries': [
-                    # Needed for clock_gettime() used by src/platform-linux.cc.
-                    '-lrt',
-                  ],
                   'conditions': [
                     ['v8_compress_startup_data=="bz2"', {
                       'libraries': [
@@ -870,7 +887,13 @@
         {
           'target_name': 'js2c',
           'type': 'none',
-          'toolsets': ['host'],
+          'conditions': [
+            ['want_separate_host_toolset==1', {
+              'toolsets': ['host'],
+            }, {
+              'toolsets': ['target'],
+            }],
+          ],
           'variables': {
             'library_files': [
               '../../src/runtime.js',
@@ -890,8 +913,9 @@
               '../../src/macros.py',
             ],
             'experimental_library_files': [
-              '../../src/proxy.js',
               '../../src/macros.py',
+              '../../src/proxy.js',
+              '../../src/weakmap.js',
             ],
           },
           'actions': [
@@ -936,7 +960,6 @@
         {
           'target_name': 'mksnapshot',
           'type': 'executable',
-          'toolsets': ['host'],
           'dependencies': [
             'v8_nosnapshot',
           ],
@@ -947,11 +970,10 @@
             '../../src/mksnapshot.cc',
           ],
           'conditions': [
-            # The ARM assembler assumes the host is 32 bits, so force building
-            # 32-bit host tools.
-            ['v8_target_arch=="arm" and host_arch=="x64" and _toolset=="host"', {
-              'cflags': ['-m32'],
-              'ldflags': ['-m32'],
+            ['want_separate_host_toolset==1', {
+              'toolsets': ['host'],
+            }, {
+              'toolsets': ['target'],
             }],
             ['v8_compress_startup_data=="bz2"', {
               'libraries': [
@@ -962,7 +984,6 @@
         {
           'target_name': 'v8_shell',
           'type': 'executable',
-          'toolsets': ['host'],
           'dependencies': [
             'v8'
           ],
@@ -970,29 +991,57 @@
             '../../samples/shell.cc',
           ],
           'conditions': [
+            ['want_separate_host_toolset==1', {
+              'toolsets': ['host'],
+            }, {
+              'toolsets': ['target'],
+            }],
             ['OS=="win"', {
               # This could be gotten by not setting chromium_code, if that's OK.
               'defines': ['_CRT_SECURE_NO_WARNINGS'],
             }],
-            # The ARM assembler assumes the host is 32 bits, so force building
-            # 32-bit host tools.
-            ['v8_target_arch=="arm" and host_arch=="x64" and _toolset=="host"', {
-              'cflags': ['-m32'],
-              'ldflags': ['-m32'],
-            }],
             ['v8_compress_startup_data=="bz2"', {
               'libraries': [
                 '-lbz2',
               ]}],
           ],
         },
+        {
+          'target_name': 'preparser_lib',
+          'type': '<(library)',
+          'include_dirs+': [
+            '../../src',
+          ],
+          'sources': [
+            '../../src/allocation.cc',
+            '../../src/bignum.cc',
+            '../../src/cached-powers.cc',
+            '../../src/conversions.cc',
+            '../../src/hashmap.cc',
+            '../../src/preparse-data.cc',
+            '../../src/preparser.cc',
+            '../../src/preparser-api.cc',
+            '../../src/scanner-base.cc',
+            '../../src/strtod.cc',
+            '../../src/token.cc',
+            '../../src/unicode.cc',
+            '../../src/utils.cc',
+          ],
+        },
       ],
     }, { # use_system_v8 != 0
       'targets': [
         {
           'target_name': 'v8',
           'type': 'settings',
-          'toolsets': ['host', 'target'],
+          'conditions': [
+            ['want_separate_host_toolset==1', {
+              'toolsets': ['host', 'target'],
+            }, {
+              'toolsets': ['target'],
+            }],
+
+          ],
           'link_settings': {
             'libraries': [
               '-lv8',
@@ -1002,7 +1051,13 @@
         {
           'target_name': 'v8_shell',
           'type': 'none',
-          'toolsets': ['host'],
+          'conditions': [
+            ['want_separate_host_toolset==1', {
+              'toolsets': ['host'],
+            }, {
+              'toolsets': ['target'],
+            }],
+          ],
           'dependencies': [
             'v8'
           ],
diff --git a/tools/presubmit.py b/tools/presubmit.py
index 1d80f92..c191fc7 100755
--- a/tools/presubmit.py
+++ b/tools/presubmit.py
@@ -248,12 +248,19 @@
   def IgnoreDir(self, name):
     return (super(SourceProcessor, self).IgnoreDir(name)
               or (name == 'third_party')
+              or (name == 'gyp')
+              or (name == 'out')
               or (name == 'obj'))
 
-  IGNORE_COPYRIGHTS = ['earley-boyer.js', 'raytrace.js', 'crypto.js',
-      'libraries.cc', 'libraries-empty.cc', 'jsmin.py', 'regexp-pcre.js']
-  IGNORE_TABS = IGNORE_COPYRIGHTS + ['unicode-test.js',
-      'html-comments.js']
+  IGNORE_COPYRIGHTS = ['cpplint.py',
+                       'earley-boyer.js',
+                       'raytrace.js',
+                       'crypto.js',
+                       'libraries.cc',
+                       'libraries-empty.cc',
+                       'jsmin.py',
+                       'regexp-pcre.js']
+  IGNORE_TABS = IGNORE_COPYRIGHTS + ['unicode-test.js', 'html-comments.js']
 
   def ProcessContents(self, name, contents):
     result = True
diff --git a/tools/test-wrapper-gypbuild.py b/tools/test-wrapper-gypbuild.py
new file mode 100755
index 0000000..efd1c1d
--- /dev/null
+++ b/tools/test-wrapper-gypbuild.py
@@ -0,0 +1,226 @@
+#!/usr/bin/env python
+#
+# 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.
+
+
+# This is a convenience script to run the existing tools/test.py script
+# when using the gyp/make based build.
+# It is intended as a stop-gap rather than a long-term solution.
+
+
+import optparse
+import os
+from os.path import join, dirname, abspath
+import subprocess
+import sys
+
+
+PROGRESS_INDICATORS = ['verbose', 'dots', 'color', 'mono']
+
+
+def BuildOptions():
+  result = optparse.OptionParser()
+
+  # Flags specific to this wrapper script:
+  result.add_option("--arch-and-mode",
+                    help='Architecture and mode in the format "arch.mode"',
+                    default=None)
+  result.add_option("--outdir",
+                    help='Base output directory',
+                    default='out')
+
+  # Flags this wrapper script handles itself:
+  result.add_option("-m", "--mode",
+                    help="The test modes in which to run (comma-separated)",
+                    default='release,debug')
+  result.add_option("--arch",
+                    help='The architectures to run tests for (comma-separated)',
+                    default='ia32,x64,arm')
+
+  # Flags that are passed on to the wrapped test.py script:
+  result.add_option("-v", "--verbose", help="Verbose output",
+      default=False, action="store_true")
+  result.add_option("-p", "--progress",
+      help="The style of progress indicator (verbose, dots, color, mono)",
+      choices=PROGRESS_INDICATORS, default="mono")
+  result.add_option("--report", help="Print a summary of the tests to be run",
+      default=False, action="store_true")
+  result.add_option("-s", "--suite", help="A test suite",
+      default=[], action="append")
+  result.add_option("-t", "--timeout", help="Timeout in seconds",
+      default=60, type="int")
+  result.add_option("--snapshot", help="Run the tests with snapshot turned on",
+      default=False, action="store_true")
+  result.add_option("--special-command", default=None)
+  result.add_option("--valgrind", help="Run tests through valgrind",
+      default=False, action="store_true")
+  result.add_option("--cat", help="Print the source of the tests",
+      default=False, action="store_true")
+  result.add_option("--warn-unused", help="Report unused rules",
+      default=False, action="store_true")
+  result.add_option("-j", help="The number of parallel tasks to run",
+      default=1, type="int")
+  result.add_option("--time", help="Print timing information after running",
+      default=False, action="store_true")
+  result.add_option("--suppress-dialogs", help="Suppress Windows dialogs for crashing tests",
+        dest="suppress_dialogs", default=True, action="store_true")
+  result.add_option("--no-suppress-dialogs", help="Display Windows dialogs for crashing tests",
+        dest="suppress_dialogs", action="store_false")
+  result.add_option("--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")
+  result.add_option("--no-store-unexpected-output",
+      help="Deletes the temporary JS files from tests that fails",
+      dest="store_unexpected_output", action="store_false")
+  result.add_option("--stress-only",
+                    help="Only run tests with --always-opt --stress-opt",
+                    default=False, action="store_true")
+  result.add_option("--nostress",
+                    help="Don't run crankshaft --always-opt --stress-op test",
+                    default=False, action="store_true")
+  result.add_option("--crankshaft",
+                    help="Run with the --crankshaft flag",
+                    default=False, action="store_true")
+  result.add_option("--shard-count",
+                    help="Split testsuites into this number of shards",
+                    default=1, type="int")
+  result.add_option("--shard-run",
+                    help="Run this shard from the split up tests.",
+                    default=1, type="int")
+  result.add_option("--noprof", help="Disable profiling support",
+                    default=False)
+
+  # Flags present in the original test.py that are unsupported in this wrapper:
+  # -S [-> scons_flags] (we build with gyp/make, not scons)
+  # --no-build (always true)
+  # --build-only (always false)
+  # --build-system (always 'gyp')
+  # --simulator (always true if arch==arm, always false otherwise)
+  # --shell (automatically chosen depending on arch and mode)
+
+  return result
+
+
+def ProcessOptions(options):
+  if options.arch_and_mode != None and options.arch_and_mode != "":
+    tokens = options.arch_and_mode.split(".")
+    options.arch = tokens[0]
+    options.mode = tokens[1]
+  options.mode = options.mode.split(',')
+  for mode in options.mode:
+    if not mode in ['debug', 'release']:
+      print "Unknown mode %s" % mode
+      return False
+  options.arch = options.arch.split(',')
+  for arch in options.arch:
+    if not arch in ['ia32', 'x64', 'arm']:
+      print "Unknown architecture %s" % arch
+      return False
+
+  return True
+
+
+def PassOnOptions(options):
+  result = []
+  if options.verbose:
+    result += ['--verbose']
+  if options.progress != 'mono':
+    result += ['--progress=' + options.progress]
+  if options.report:
+    result += ['--report']
+  if options.suite != []:
+    for suite in options.suite:
+      result += ['--suite=../../test/' + suite]
+  if options.timeout != 60:
+    result += ['--timeout=%s' % options.timeout]
+  if options.snapshot:
+    result += ['--snapshot']
+  if options.special_command:
+    result += ['--special-command=' + options.special_command]
+  if options.valgrind:
+    result += ['--valgrind']
+  if options.cat:
+    result += ['--cat']
+  if options.warn_unused:
+    result += ['--warn-unused']
+  if options.j != 1:
+    result += ['-j%s' % options.j]
+  if options.time:
+    result += ['--time']
+  if not options.suppress_dialogs:
+    result += ['--no-suppress-dialogs']
+  if options.isolates:
+    result += ['--isolates']
+  if not options.store_unexpected_output:
+    result += ['--no-store-unexpected_output']
+  if options.stress_only:
+    result += ['--stress-only']
+  if options.nostress:
+    result += ['--nostress']
+  if options.crankshaft:
+    result += ['--crankshaft']
+  if options.shard_count != 1:
+    result += ['--shard_count=%s' % options.shard_count]
+  if options.shard_run != 1:
+    result += ['--shard_run=%s' % options.shard_run]
+  if options.noprof:
+    result += ['--noprof']
+  return result
+
+
+def Main():
+  parser = BuildOptions()
+  (options, args) = parser.parse_args()
+  if not ProcessOptions(options):
+    parser.print_help()
+    return 1
+
+  workspace = abspath(join(dirname(sys.argv[0]), '..'))
+  args_for_children = [workspace + '/tools/test.py'] + PassOnOptions(options)
+  args_for_children += ['--no-build', '--build-system=gyp']
+  for arg in args:
+    args_for_children += [arg]
+  returncodes = 0
+
+  for mode in options.mode:
+    for arch in options.arch:
+      print ">>> running tests for %s.%s" % (arch, mode)
+      shell = workspace + '/' + options.outdir + '/' + arch + '.' + mode + "/d8"
+      child = subprocess.Popen(' '.join(args_for_children +
+                                        ['--mode=' + mode] +
+                                        ['--shell=' + shell]),
+                               shell=True,
+                               cwd=workspace)
+      returncodes += child.wait()
+
+  return returncodes
+
+
+if __name__ == '__main__':
+  sys.exit(Main())
diff --git a/tools/test.py b/tools/test.py
index 6132614..d40159c 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -1181,6 +1181,8 @@
       default=False, action="store_true")
   result.add_option("--build-only", help="Only build requirements, don't run the tests",
       default=False, action="store_true")
+  result.add_option("--build-system", help="Build system in use (scons or gyp)",
+      default='scons')
   result.add_option("--report", help="Print a summary of the tests to be run",
       default=False, action="store_true")
   result.add_option("-s", "--suite", help="A test suite",
@@ -1271,21 +1273,30 @@
     if options.special_command:
       options.special_command += " --crankshaft"
     else:
-      options.special_command = "@--crankshaft"
-  if options.shell == "d8":
+      options.special_command = "@ --crankshaft"
+  if options.shell.endswith("d8"):
     if options.special_command:
       options.special_command += " --test"
     else:
-      options.special_command = "@--test"
+      options.special_command = "@ --test"
   if options.noprof:
     options.scons_flags.append("prof=off")
     options.scons_flags.append("profilingsupport=off")
+  if options.build_system == 'gyp':
+    if options.build_only:
+      print "--build-only not supported for gyp, please build manually."
+      options.build_only = False
   return True
 
 
+def DoSkip(case):
+  return (SKIP in case.outcomes) or (SLOW in case.outcomes)
+
+
 REPORT_TEMPLATE = """\
 Total: %(total)i tests
  * %(skipped)4d tests will be skipped
+ * %(timeout)4d tests are expected to timeout sometimes
  * %(nocrash)4d tests are expected to be flaky but not crash
  * %(pass)4d tests are expected to pass
  * %(fail_ok)4d tests are expected to fail that we won't fix
@@ -1297,10 +1308,11 @@
     return (PASS in o) and (FAIL in o) and (not CRASH in o) and (not OKAY in o)
   def IsFailOk(o):
     return (len(o) == 2) and (FAIL in o) and (OKAY in o)
-  unskipped = [c for c in cases if not SKIP in c.outcomes]
+  unskipped = [c for c in cases if not DoSkip(c)]
   print REPORT_TEMPLATE % {
     'total': len(cases),
     'skipped': len(cases) - len(unskipped),
+    'timeout': len([t for t in unskipped if TIMEOUT in t.outcomes]),
     'nocrash': len([t for t in unskipped if IsFlaky(t.outcomes)]),
     'pass': len([t for t in unskipped if list(t.outcomes) == [PASS]]),
     'fail_ok': len([t for t in unskipped if IsFailOk(t.outcomes)]),
@@ -1399,6 +1411,9 @@
     run_valgrind = join(workspace, "tools", "run-valgrind.py")
     options.special_command = "python -u " + run_valgrind + " @"
 
+  if options.build_system == 'gyp':
+    SUFFIX['debug'] = ''
+
   shell = abspath(options.shell)
   buildspace = dirname(shell)
 
@@ -1472,15 +1487,14 @@
     for rule in globally_unused_rules:
       print "Rule for '%s' was not used." % '/'.join([str(s) for s in rule.path])
 
+  if not options.isolates:
+    all_cases = [c for c in all_cases if not c.TestsIsolates()]
+
   if options.report:
     PrintReport(all_cases)
 
   result = None
-  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