Update V8 to r7079 as required by WebKit r80534.

Change-Id: I487c152e485d5a40b68997d7c0d2f1fba5da0834
diff --git a/.gitignore b/.gitignore
index 974628d..db57d1b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,11 @@
 shell
 shell_g
 /obj/
+/test/es5conform/data/
+/test/mozilla/data/
+/test/sputnik/sputniktests/
+/tools/oom_dump/oom_dump
+/tools/oom_dump/oom_dump.o
 /tools/visual_studio/Debug
 /tools/visual_studio/Release
 /xcodebuild/
diff --git a/Android.v8common.mk b/Android.v8common.mk
index a976a48..0a57ce6 100644
--- a/Android.v8common.mk
+++ b/Android.v8common.mk
@@ -114,6 +114,7 @@
 		src/arm/jump-target-arm.cc \
 		src/arm/lithium-arm.cc \
 		src/arm/lithium-codegen-arm.cc \
+		src/arm/lithium-gap-resolver-arm.cc \
 		src/arm/macro-assembler-arm.cc \
 		src/arm/regexp-macro-assembler-arm.cc \
 		src/arm/register-allocator-arm.cc \
diff --git a/ChangeLog b/ChangeLog
index 5d2af9c..44935ca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,65 @@
+2011-03-07: Version 3.2.0
+
+        Fixed a number of crash bugs.
+
+        Turned on Crankshaft by default on x64 and ARM.
+
+        Improved Crankshaft for x64 and ARM.
+
+        Implemented more of EcmaScript 5 strict mode.
+
+
+2011-03-02: Version 3.1.8
+
+        Fixed a number of crash bugs.
+
+        Improved Crankshaft for x64 and ARM.
+
+        Implemented more of EcmaScript 5 strict mode.
+
+        Fixed issue with unaligned reads and writes on ARM.
+
+        Improved heap profiler support.
+
+
+2011-02-28: Version 3.1.7
+
+        Fixed a number of crash bugs.
+
+        Improved Crankshaft for x64 and ARM.
+
+        Fixed implementation of indexOf/lastIndexOf for sparse
+        arrays (http://crbug.com/73940).
+
+        Fixed bug in map space compaction (http://crbug.com/59688).
+
+        Added support for direct getter accessors calls on ARM.
+
+
+2011-02-24: Version 3.1.6
+
+        Fixed a number of crash bugs.
+
+        Added support for Cygwin (issue 64).
+
+        Improved Crankshaft for x64 and ARM.
+
+        Added Crankshaft support for stores to pixel arrays.
+
+        Fixed issue in CPU profiler with Crankshaft.
+
+
+2011-02-16: Version 3.1.5
+
+        Change RegExp parsing to disallow /(*)/.
+
+        Added GDB JIT support for ARM.
+
+        Fixed several crash bugs.
+
+        Performance improvements on the IA32 platform.
+
+
 2011-02-14: Version 3.1.4
 
         Fixed incorrect compare of prototypes of the global object (issue
diff --git a/SConstruct b/SConstruct
index 017bcad..84707e9 100644
--- a/SConstruct
+++ b/SConstruct
@@ -663,8 +663,8 @@
 
 
 def GuessVisibility(os, toolchain):
-  if os == 'win32' and toolchain == 'gcc':
-    # MinGW can't do it.
+  if (os == 'win32' or os == 'cygwin') and toolchain == 'gcc':
+    # MinGW / Cygwin can't do it.
     return 'default'
   elif os == 'solaris':
     return 'default'
@@ -685,7 +685,7 @@
     'help': 'the toolchain to use (%s)' % TOOLCHAIN_GUESS
   },
   'os': {
-    'values': ['freebsd', 'linux', 'macos', 'win32', 'android', 'openbsd', 'solaris'],
+    'values': ['freebsd', 'linux', 'macos', 'win32', 'android', 'openbsd', 'solaris', 'cygwin'],
     'default': OS_GUESS,
     'help': 'the os to build for (%s)' % OS_GUESS
   },
@@ -890,7 +890,7 @@
     return False
   if env['os'] == 'win32' and env['library'] == 'shared' and env['prof'] == 'on':
     Abort("Profiling on windows only supported for static library.")
-  if env['gdbjit'] == 'on' and (env['os'] != 'linux' or (env['arch'] != 'ia32' and env['arch'] != 'x64')):
+  if env['gdbjit'] == 'on' and (env['os'] != 'linux' or (env['arch'] != 'ia32' and env['arch'] != 'x64' and env['arch'] != 'arm')):
     Abort("GDBJIT interface is supported only for Intel-compatible (ia32 or x64) Linux target.")
   if env['os'] == 'win32' and env['soname'] == 'on':
     Abort("Shared Object soname not applicable for Windows.")
diff --git a/V8_MERGE_REVISION b/V8_MERGE_REVISION
index 07693bd..120fd67 100644
--- a/V8_MERGE_REVISION
+++ b/V8_MERGE_REVISION
@@ -1,6 +1,5 @@
 We use a V8 revision that has been used for a Chromium release.
 
-http://src.chromium.org/svn/releases/11.0.672.0/DEPS
-http://v8.googlecode.com/svn/trunk@6768 plus a partial cherry-pick to fix Android build ...
-- r7077 - CreateThread() in src/platform-linux.cc
+http://src.chromium.org/svn/releases/11.0.696.0/DEPS
+http://v8.googlecode.com/svn/trunk@7079
 
diff --git a/copy-new-sources b/copy-new-sources
deleted file mode 100755
index 84fc684..0000000
--- a/copy-new-sources
+++ /dev/null
@@ -1 +0,0 @@
-cp -r AUTHORS ChangeLog LICENSE SConstruct benchmarks include samples src test tools ../android/master/external/v8/ 
diff --git a/samples/shell.cc b/samples/shell.cc
index 6b67df6..64f78f0 100644
--- a/samples/shell.cc
+++ b/samples/shell.cc
@@ -27,6 +27,7 @@
 
 #include <v8.h>
 #include <v8-testing.h>
+#include <assert.h>
 #include <fcntl.h>
 #include <string.h>
 #include <stdio.h>
@@ -290,11 +291,13 @@
   } else {
     v8::Handle<v8::Value> result = script->Run();
     if (result.IsEmpty()) {
+      assert(try_catch.HasCaught());
       // Print errors that happened during execution.
       if (report_exceptions)
         ReportException(&try_catch);
       return false;
     } else {
+      assert(!try_catch.HasCaught());
       if (print_result && !result->IsUndefined()) {
         // If all went well and the result wasn't undefined then print
         // the returned value.
diff --git a/src/SConscript b/src/SConscript
index c3561be..34ca91c 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -153,6 +153,7 @@
     arm/jump-target-arm.cc
     arm/lithium-arm.cc
     arm/lithium-codegen-arm.cc
+    arm/lithium-gap-resolver-arm.cc
     arm/macro-assembler-arm.cc
     arm/regexp-macro-assembler-arm.cc
     arm/register-allocator-arm.cc
@@ -233,6 +234,7 @@
   'os:android': ['platform-linux.cc', 'platform-posix.cc'],
   'os:macos':   ['platform-macos.cc', 'platform-posix.cc'],
   'os:solaris': ['platform-solaris.cc', 'platform-posix.cc'],
+  'os:cygwin':  ['platform-cygwin.cc', 'platform-posix.cc'],
   'os:nullos':  ['platform-nullos.cc'],
   'os:win32':   ['platform-win32.cc'],
   'mode:release': [],
@@ -264,6 +266,9 @@
   'os:solaris': [
     'd8-posix.cc'
   ],
+  'os:cygwin': [
+    'd8-posix.cc'
+  ],
   'os:win32': [
     'd8-windows.cc'
   ],
diff --git a/src/accessors.cc b/src/accessors.cc
index 2b205d5..1826425 100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -446,6 +446,14 @@
   bool found_it = false;
   JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
   if (!found_it) return Heap::undefined_value();
+  while (!function->should_have_prototype()) {
+    found_it = false;
+    function = FindInPrototypeChain<JSFunction>(object->GetPrototype(),
+                                                &found_it);
+    // There has to be one because we hit the getter.
+    ASSERT(found_it);
+  }
+
   if (!function->has_prototype()) {
     Object* prototype;
     { MaybeObject* maybe_prototype = Heap::AllocateFunctionPrototype(function);
@@ -466,6 +474,13 @@
   bool found_it = false;
   JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
   if (!found_it) return Heap::undefined_value();
+  if (!function->should_have_prototype()) {
+    // Since we hit this accessor, object will have no prototype property.
+    return object->SetLocalPropertyIgnoreAttributes(Heap::prototype_symbol(),
+                                                    value,
+                                                    NONE);
+  }
+
   if (function->has_initial_map()) {
     // If the function has allocated the initial map
     // replace it with a copy containing the new prototype.
diff --git a/src/api.cc b/src/api.cc
index d718c88..555af84 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2286,7 +2286,8 @@
       self,
       key_obj,
       value_obj,
-      static_cast<PropertyAttributes>(attribs));
+      static_cast<PropertyAttributes>(attribs),
+      i::kNonStrictMode);
   has_pending_exception = obj.is_null();
   EXCEPTION_BAILOUT_CHECK(false);
   return true;
@@ -2303,7 +2304,8 @@
   i::Handle<i::Object> obj = i::SetElement(
       self,
       index,
-      value_obj);
+      value_obj,
+      i::kNonStrictMode);
   has_pending_exception = obj.is_null();
   EXCEPTION_BAILOUT_CHECK(false);
   return true;
@@ -2711,7 +2713,8 @@
       hidden_props,
       key_obj,
       value_obj,
-      static_cast<PropertyAttributes>(None));
+      static_cast<PropertyAttributes>(None),
+      i::kNonStrictMode);
   has_pending_exception = obj.is_null();
   EXCEPTION_BAILOUT_CHECK(false);
   return true;
diff --git a/src/arguments.h b/src/arguments.h
index d51c9e4..5cf8dea 100644
--- a/src/arguments.h
+++ b/src/arguments.h
@@ -78,7 +78,7 @@
 class CustomArguments : public Relocatable {
  public:
   inline CustomArguments(Object* data,
-                         JSObject* self,
+                         Object* self,
                          JSObject* holder) {
     values_[2] = self;
     values_[1] = holder;
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index fb9bb48..c91d4ba 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -1848,11 +1848,31 @@
     offset = -offset;
     u = 0;
   }
-  ASSERT(offset % 4 == 0);
-  ASSERT((offset / 4) < 256);
+
   ASSERT(offset >= 0);
-  emit(cond | u*B23 | 0xD1*B20 | base.code()*B16 | dst.code()*B12 |
-       0xB*B8 | ((offset / 4) & 255));
+  if ((offset % 4) == 0 && (offset / 4) < 256) {
+    emit(cond | u*B23 | 0xD1*B20 | base.code()*B16 | dst.code()*B12 |
+         0xB*B8 | ((offset / 4) & 255));
+  } else {
+    // Larger offsets must be handled by computing the correct address
+    // in the ip register.
+    ASSERT(!base.is(ip));
+    if (u == 1) {
+      add(ip, base, Operand(offset));
+    } else {
+      sub(ip, base, Operand(offset));
+    }
+    emit(cond | 0xD1*B20 | ip.code()*B16 | dst.code()*B12 | 0xB*B8);
+  }
+}
+
+
+void Assembler::vldr(const DwVfpRegister dst,
+                     const MemOperand& operand,
+                     const Condition cond) {
+  ASSERT(!operand.rm().is_valid());
+  ASSERT(operand.am_ == Offset);
+  vldr(dst, operand.rn(), operand.offset(), cond);
 }
 
 
@@ -1870,13 +1890,33 @@
     offset = -offset;
     u = 0;
   }
-  ASSERT(offset % 4 == 0);
-  ASSERT((offset / 4) < 256);
-  ASSERT(offset >= 0);
   int sd, d;
   dst.split_code(&sd, &d);
+  ASSERT(offset >= 0);
+
+  if ((offset % 4) == 0 && (offset / 4) < 256) {
   emit(cond | u*B23 | d*B22 | 0xD1*B20 | base.code()*B16 | sd*B12 |
        0xA*B8 | ((offset / 4) & 255));
+  } else {
+    // Larger offsets must be handled by computing the correct address
+    // in the ip register.
+    ASSERT(!base.is(ip));
+    if (u == 1) {
+      add(ip, base, Operand(offset));
+    } else {
+      sub(ip, base, Operand(offset));
+    }
+    emit(cond | d*B22 | 0xD1*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
+  }
+}
+
+
+void Assembler::vldr(const SwVfpRegister dst,
+                     const MemOperand& operand,
+                     const Condition cond) {
+  ASSERT(!operand.rm().is_valid());
+  ASSERT(operand.am_ == Offset);
+  vldr(dst, operand.rn(), operand.offset(), cond);
 }
 
 
@@ -1894,11 +1934,30 @@
     offset = -offset;
     u = 0;
   }
-  ASSERT(offset % 4 == 0);
-  ASSERT((offset / 4) < 256);
   ASSERT(offset >= 0);
-  emit(cond | u*B23 | 0xD0*B20 | base.code()*B16 | src.code()*B12 |
-       0xB*B8 | ((offset / 4) & 255));
+  if ((offset % 4) == 0 && (offset / 4) < 256) {
+    emit(cond | u*B23 | 0xD0*B20 | base.code()*B16 | src.code()*B12 |
+         0xB*B8 | ((offset / 4) & 255));
+  } else {
+    // Larger offsets must be handled by computing the correct address
+    // in the ip register.
+    ASSERT(!base.is(ip));
+    if (u == 1) {
+      add(ip, base, Operand(offset));
+    } else {
+      sub(ip, base, Operand(offset));
+    }
+    emit(cond | 0xD0*B20 | ip.code()*B16 | src.code()*B12 | 0xB*B8);
+  }
+}
+
+
+void Assembler::vstr(const DwVfpRegister src,
+                     const MemOperand& operand,
+                     const Condition cond) {
+  ASSERT(!operand.rm().is_valid());
+  ASSERT(operand.am_ == Offset);
+  vstr(src, operand.rn(), operand.offset(), cond);
 }
 
 
@@ -1916,13 +1975,32 @@
     offset = -offset;
     u = 0;
   }
-  ASSERT(offset % 4 == 0);
-  ASSERT((offset / 4) < 256);
-  ASSERT(offset >= 0);
   int sd, d;
   src.split_code(&sd, &d);
-  emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 |
-       0xA*B8 | ((offset / 4) & 255));
+  ASSERT(offset >= 0);
+  if ((offset % 4) == 0 && (offset / 4) < 256) {
+    emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 |
+         0xA*B8 | ((offset / 4) & 255));
+  } else {
+    // Larger offsets must be handled by computing the correct address
+    // in the ip register.
+    ASSERT(!base.is(ip));
+    if (u == 1) {
+      add(ip, base, Operand(offset));
+    } else {
+      sub(ip, base, Operand(offset));
+    }
+    emit(cond | d*B22 | 0xD0*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
+  }
+}
+
+
+void Assembler::vstr(const SwVfpRegister src,
+                     const MemOperand& operand,
+                     const Condition cond) {
+  ASSERT(!operand.rm().is_valid());
+  ASSERT(operand.am_ == Offset);
+  vldr(src, operand.rn(), operand.offset(), cond);
 }
 
 
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index 3941c84..f5eb507 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -284,6 +284,7 @@
 const SwVfpRegister s30 = { 30 };
 const SwVfpRegister s31 = { 31 };
 
+const DwVfpRegister no_dreg = { -1 };
 const DwVfpRegister d0  = {  0 };
 const DwVfpRegister d1  = {  1 };
 const DwVfpRegister d2  = {  2 };
@@ -387,7 +388,7 @@
   // Return true if this is a register operand.
   INLINE(bool is_reg() const);
 
-  // Return true of this operand fits in one instruction so that no
+  // Return true if this operand fits in one instruction so that no
   // 2-instruction solution with a load into the ip register is necessary.
   bool is_single_instruction() const;
   bool must_use_constant_pool() const;
@@ -439,7 +440,7 @@
       offset_ = offset;
   }
 
-  uint32_t offset() {
+  uint32_t offset() const {
       ASSERT(rm_.is(no_reg));
       return offset_;
   }
@@ -447,6 +448,10 @@
   Register rn() const { return rn_; }
   Register rm() const { return rm_; }
 
+  bool OffsetIsUint12Encodable() const {
+    return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
+  }
+
  private:
   Register rn_;  // base
   Register rm_;  // register offset
@@ -902,22 +907,34 @@
 
   void vldr(const DwVfpRegister dst,
             const Register base,
-            int offset,  // Offset must be a multiple of 4.
+            int offset,
+            const Condition cond = al);
+  void vldr(const DwVfpRegister dst,
+            const MemOperand& src,
             const Condition cond = al);
 
   void vldr(const SwVfpRegister dst,
             const Register base,
-            int offset,  // Offset must be a multiple of 4.
+            int offset,
+            const Condition cond = al);
+  void vldr(const SwVfpRegister dst,
+            const MemOperand& src,
             const Condition cond = al);
 
   void vstr(const DwVfpRegister src,
             const Register base,
-            int offset,  // Offset must be a multiple of 4.
+            int offset,
+            const Condition cond = al);
+  void vstr(const DwVfpRegister src,
+            const MemOperand& dst,
             const Condition cond = al);
 
   void vstr(const SwVfpRegister src,
             const Register base,
-            int offset,  // Offset must be a multiple of 4.
+            int offset,
+            const Condition cond = al);
+  void vstr(const SwVfpRegister src,
+            const MemOperand& dst,
             const Condition cond = al);
 
   void vmov(const DwVfpRegister dst,
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index f14d77a..961d3ce 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -428,7 +428,7 @@
   GenerateLoadArrayFunction(masm, r1);
 
   if (FLAG_debug_code) {
-    // Initial map for the builtin Array function shoud be a map.
+    // Initial map for the builtin Array functions should be maps.
     __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
     __ tst(r2, Operand(kSmiTagMask));
     __ Assert(ne, "Unexpected initial map for Array function");
@@ -458,11 +458,8 @@
   Label generic_constructor;
 
   if (FLAG_debug_code) {
-    // The array construct code is only set for the builtin Array function which
-    // always have a map.
-    GenerateLoadArrayFunction(masm, r2);
-    __ cmp(r1, r2);
-    __ Assert(eq, "Unexpected Array function");
+    // The array construct code is only set for the builtin and internal
+    // Array functions which always have a map.
     // Initial map for the builtin Array function should be a map.
     __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
     __ tst(r2, Operand(kSmiTagMask));
@@ -1231,6 +1228,14 @@
     // Change context eagerly in case we need the global receiver.
     __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
 
+    // Do not transform the receiver for strict mode functions.
+    __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
+    __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset));
+    __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
+                             kSmiTagSize)));
+    __ b(ne, &shift_arguments);
+
+    // Compute the receiver in non-strict mode.
     __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
     __ ldr(r2, MemOperand(r2, -kPointerSize));
     // r0: actual number of arguments
@@ -1394,10 +1399,20 @@
   // Change context eagerly to get the right global object if necessary.
   __ ldr(r0, MemOperand(fp, kFunctionOffset));
   __ ldr(cp, FieldMemOperand(r0, JSFunction::kContextOffset));
+  // Load the shared function info while the function is still in r0.
+  __ ldr(r1, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
 
   // Compute the receiver.
   Label call_to_object, use_global_receiver, push_receiver;
   __ ldr(r0, MemOperand(fp, kRecvOffset));
+
+  // Do not transform the receiver for strict mode functions.
+  __ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kCompilerHintsOffset));
+  __ tst(r1, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
+                           kSmiTagSize)));
+  __ b(ne, &push_receiver);
+
+  // Compute the receiver in non-strict mode.
   __ tst(r0, Operand(kSmiTagMask));
   __ b(eq, &call_to_object);
   __ LoadRoot(r1, Heap::kNullValueRootIndex);
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 1e7d558..1c6d709 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -398,8 +398,11 @@
                            Label* not_number);
 
   // Loads the number from object into dst as a 32-bit integer if possible. If
-  // the object is not a 32-bit integer control continues at the label
-  // not_int32. If VFP is supported double_scratch is used but not scratch2.
+  // the object cannot be converted to a 32-bit integer control continues at
+  // the label not_int32. If VFP is supported double_scratch is used
+  // but not scratch2.
+  // Floating point value in the 32-bit integer range will be rounded
+  // to an integer.
   static void LoadNumberAsInteger(MacroAssembler* masm,
                                   Register object,
                                   Register dst,
@@ -409,6 +412,76 @@
                                   DwVfpRegister double_scratch,
                                   Label* not_int32);
 
+  // Load the number from object into double_dst in the double format.
+  // Control will jump to not_int32 if the value cannot be exactly represented
+  // by a 32-bit integer.
+  // Floating point value in the 32-bit integer range that are not exact integer
+  // won't be loaded.
+  static void LoadNumberAsInt32Double(MacroAssembler* masm,
+                                      Register object,
+                                      Destination destination,
+                                      DwVfpRegister double_dst,
+                                      Register dst1,
+                                      Register dst2,
+                                      Register heap_number_map,
+                                      Register scratch1,
+                                      Register scratch2,
+                                      SwVfpRegister single_scratch,
+                                      Label* not_int32);
+
+  // Loads the number from object into dst as a 32-bit integer.
+  // Control will jump to not_int32 if the object cannot be exactly represented
+  // by a 32-bit integer.
+  // Floating point value in the 32-bit integer range that are not exact integer
+  // won't be converted.
+  // scratch3 is not used when VFP3 is supported.
+  static void LoadNumberAsInt32(MacroAssembler* masm,
+                                Register object,
+                                Register dst,
+                                Register heap_number_map,
+                                Register scratch1,
+                                Register scratch2,
+                                Register scratch3,
+                                DwVfpRegister double_scratch,
+                                Label* not_int32);
+
+  // Generate non VFP3 code to check if a double can be exactly represented by a
+  // 32-bit integer. This does not check for 0 or -0, which need
+  // to be checked for separately.
+  // Control jumps to not_int32 if the value is not a 32-bit integer, and falls
+  // through otherwise.
+  // src1 and src2 will be cloberred.
+  //
+  // Expected input:
+  // - src1: higher (exponent) part of the double value.
+  // - src2: lower (mantissa) part of the double value.
+  // Output status:
+  // - dst: 32 higher bits of the mantissa. (mantissa[51:20])
+  // - src2: contains 1.
+  // - other registers are clobbered.
+  static void DoubleIs32BitInteger(MacroAssembler* masm,
+                                   Register src1,
+                                   Register src2,
+                                   Register dst,
+                                   Register scratch,
+                                   Label* not_int32);
+
+  // Generates code to call a C function to do a double operation using core
+  // registers. (Used when VFP3 is not supported.)
+  // This code never falls through, but returns with a heap number containing
+  // the result in r0.
+  // Register heapnumber_result must be a heap number in which the
+  // result of the operation will be stored.
+  // Requires the following layout on entry:
+  // r0: Left value (least significant part of mantissa).
+  // r1: Left value (sign, exponent, top of mantissa).
+  // r2: Right value (least significant part of mantissa).
+  // r3: Right value (sign, exponent, top of mantissa).
+  static void CallCCodeForDoubleOperation(MacroAssembler* masm,
+                                          Token::Value op,
+                                          Register heap_number_result,
+                                          Register scratch);
+
  private:
   static void LoadNumber(MacroAssembler* masm,
                          FloatingPointHelper::Destination destination,
@@ -560,6 +633,318 @@
 }
 
 
+void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm,
+                                                  Register object,
+                                                  Destination destination,
+                                                  DwVfpRegister double_dst,
+                                                  Register dst1,
+                                                  Register dst2,
+                                                  Register heap_number_map,
+                                                  Register scratch1,
+                                                  Register scratch2,
+                                                  SwVfpRegister single_scratch,
+                                                  Label* not_int32) {
+  ASSERT(!scratch1.is(object) && !scratch2.is(object));
+  ASSERT(!scratch1.is(scratch2));
+  ASSERT(!heap_number_map.is(object) &&
+         !heap_number_map.is(scratch1) &&
+         !heap_number_map.is(scratch2));
+
+  Label done, obj_is_not_smi;
+
+  __ JumpIfNotSmi(object, &obj_is_not_smi);
+  __ SmiUntag(scratch1, object);
+  if (CpuFeatures::IsSupported(VFP3)) {
+    CpuFeatures::Scope scope(VFP3);
+    __ vmov(single_scratch, scratch1);
+    __ vcvt_f64_s32(double_dst, single_scratch);
+    if (destination == kCoreRegisters) {
+      __ vmov(dst1, dst2, double_dst);
+    }
+  } else {
+    Label fewer_than_20_useful_bits;
+    // Expected output:
+    // |         dst1            |         dst2            |
+    // | s |   exp   |              mantissa               |
+
+    // Check for zero.
+    __ cmp(scratch1, Operand(0));
+    __ mov(dst1, scratch1);
+    __ mov(dst2, scratch1);
+    __ b(eq, &done);
+
+    // Preload the sign of the value.
+    __ and_(dst1, scratch1, Operand(HeapNumber::kSignMask), SetCC);
+    // Get the absolute value of the object (as an unsigned integer).
+    __ rsb(scratch1, scratch1, Operand(0), SetCC, mi);
+
+    // Get mantisssa[51:20].
+
+    // Get the position of the first set bit.
+    __ CountLeadingZeros(dst2, scratch1, scratch2);
+    __ rsb(dst2, dst2, Operand(31));
+
+    // Set the exponent.
+    __ add(scratch2, dst2, Operand(HeapNumber::kExponentBias));
+    __ Bfi(dst1, scratch2, scratch2,
+        HeapNumber::kExponentShift, HeapNumber::kExponentBits);
+
+    // Clear the first non null bit.
+    __ mov(scratch2, Operand(1));
+    __ bic(scratch1, scratch1, Operand(scratch2, LSL, dst2));
+
+    __ cmp(dst2, Operand(HeapNumber::kMantissaBitsInTopWord));
+    // Get the number of bits to set in the lower part of the mantissa.
+    __ sub(scratch2, dst2, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC);
+    __ b(mi, &fewer_than_20_useful_bits);
+    // Set the higher 20 bits of the mantissa.
+    __ orr(dst1, dst1, Operand(scratch1, LSR, scratch2));
+    __ rsb(scratch2, scratch2, Operand(32));
+    __ mov(dst2, Operand(scratch1, LSL, scratch2));
+    __ b(&done);
+
+    __ bind(&fewer_than_20_useful_bits);
+    __ rsb(scratch2, dst2, Operand(HeapNumber::kMantissaBitsInTopWord));
+    __ mov(scratch2, Operand(scratch1, LSL, scratch2));
+    __ orr(dst1, dst1, scratch2);
+    // Set dst2 to 0.
+    __ mov(dst2, Operand(0));
+  }
+
+  __ b(&done);
+
+  __ bind(&obj_is_not_smi);
+  if (FLAG_debug_code) {
+    __ AbortIfNotRootValue(heap_number_map,
+                           Heap::kHeapNumberMapRootIndex,
+                           "HeapNumberMap register clobbered.");
+  }
+  __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
+
+  // Load the number.
+  if (CpuFeatures::IsSupported(VFP3)) {
+    CpuFeatures::Scope scope(VFP3);
+    // Load the double value.
+    __ sub(scratch1, object, Operand(kHeapObjectTag));
+    __ vldr(double_dst, scratch1, HeapNumber::kValueOffset);
+
+    __ EmitVFPTruncate(kRoundToZero,
+                       single_scratch,
+                       double_dst,
+                       scratch1,
+                       scratch2,
+                       kCheckForInexactConversion);
+
+    // Jump to not_int32 if the operation did not succeed.
+    __ b(ne, not_int32);
+
+    if (destination == kCoreRegisters) {
+      __ vmov(dst1, dst2, double_dst);
+    }
+
+  } else {
+    ASSERT(!scratch1.is(object) && !scratch2.is(object));
+    // Load the double value in the destination registers..
+    __ Ldrd(dst1, dst2, FieldMemOperand(object, HeapNumber::kValueOffset));
+
+    // Check for 0 and -0.
+    __ bic(scratch1, dst1, Operand(HeapNumber::kSignMask));
+    __ orr(scratch1, scratch1, Operand(dst2));
+    __ cmp(scratch1, Operand(0));
+    __ b(eq, &done);
+
+    // Check that the value can be exactly represented by a 32-bit integer.
+    // Jump to not_int32 if that's not the case.
+    DoubleIs32BitInteger(masm, dst1, dst2, scratch1, scratch2, not_int32);
+
+    // dst1 and dst2 were trashed. Reload the double value.
+    __ Ldrd(dst1, dst2, FieldMemOperand(object, HeapNumber::kValueOffset));
+  }
+
+  __ bind(&done);
+}
+
+
+void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
+                                            Register object,
+                                            Register dst,
+                                            Register heap_number_map,
+                                            Register scratch1,
+                                            Register scratch2,
+                                            Register scratch3,
+                                            DwVfpRegister double_scratch,
+                                            Label* not_int32) {
+  ASSERT(!dst.is(object));
+  ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object));
+  ASSERT(!scratch1.is(scratch2) &&
+         !scratch1.is(scratch3) &&
+         !scratch2.is(scratch3));
+
+  Label done;
+
+  // Untag the object into the destination register.
+  __ SmiUntag(dst, object);
+  // Just return if the object is a smi.
+  __ JumpIfSmi(object, &done);
+
+  if (FLAG_debug_code) {
+    __ AbortIfNotRootValue(heap_number_map,
+                           Heap::kHeapNumberMapRootIndex,
+                           "HeapNumberMap register clobbered.");
+  }
+  __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
+
+  // Object is a heap number.
+  // Convert the floating point value to a 32-bit integer.
+  if (CpuFeatures::IsSupported(VFP3)) {
+    CpuFeatures::Scope scope(VFP3);
+    SwVfpRegister single_scratch = double_scratch.low();
+    // Load the double value.
+    __ sub(scratch1, object, Operand(kHeapObjectTag));
+    __ vldr(double_scratch, scratch1, HeapNumber::kValueOffset);
+
+    __ EmitVFPTruncate(kRoundToZero,
+                       single_scratch,
+                       double_scratch,
+                       scratch1,
+                       scratch2,
+                       kCheckForInexactConversion);
+
+    // Jump to not_int32 if the operation did not succeed.
+    __ b(ne, not_int32);
+    // Get the result in the destination register.
+    __ vmov(dst, single_scratch);
+
+  } else {
+    // Load the double value in the destination registers.
+    __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
+    __ ldr(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
+
+    // Check for 0 and -0.
+    __ bic(dst, scratch1, Operand(HeapNumber::kSignMask));
+    __ orr(dst, scratch2, Operand(dst));
+    __ cmp(dst, Operand(0));
+    __ b(eq, &done);
+
+    DoubleIs32BitInteger(masm, scratch1, scratch2, dst, scratch3, not_int32);
+
+    // Registers state after DoubleIs32BitInteger.
+    // dst: mantissa[51:20].
+    // scratch2: 1
+
+    // Shift back the higher bits of the mantissa.
+    __ mov(dst, Operand(dst, LSR, scratch3));
+    // Set the implicit first bit.
+    __ rsb(scratch3, scratch3, Operand(32));
+    __ orr(dst, dst, Operand(scratch2, LSL, scratch3));
+    // Set the sign.
+    __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
+    __ tst(scratch1, Operand(HeapNumber::kSignMask));
+    __ rsb(dst, dst, Operand(0), LeaveCC, mi);
+  }
+
+  __ bind(&done);
+}
+
+
+void FloatingPointHelper::DoubleIs32BitInteger(MacroAssembler* masm,
+                                               Register src1,
+                                               Register src2,
+                                               Register dst,
+                                               Register scratch,
+                                               Label* not_int32) {
+  // Get exponent alone in scratch.
+  __ Ubfx(scratch,
+          src1,
+          HeapNumber::kExponentShift,
+          HeapNumber::kExponentBits);
+
+  // Substract the bias from the exponent.
+  __ sub(scratch, scratch, Operand(HeapNumber::kExponentBias), SetCC);
+
+  // src1: higher (exponent) part of the double value.
+  // src2: lower (mantissa) part of the double value.
+  // scratch: unbiased exponent.
+
+  // Fast cases. Check for obvious non 32-bit integer values.
+  // Negative exponent cannot yield 32-bit integers.
+  __ b(mi, not_int32);
+  // Exponent greater than 31 cannot yield 32-bit integers.
+  // Also, a positive value with an exponent equal to 31 is outside of the
+  // signed 32-bit integer range.
+  // Another way to put it is that if (exponent - signbit) > 30 then the
+  // number cannot be represented as an int32.
+  Register tmp = dst;
+  __ sub(tmp, scratch, Operand(src1, LSR, 31));
+  __ cmp(tmp, Operand(30));
+  __ b(gt, not_int32);
+  // - Bits [21:0] in the mantissa are not null.
+  __ tst(src2, Operand(0x3fffff));
+  __ b(ne, not_int32);
+
+  // Otherwise the exponent needs to be big enough to shift left all the
+  // non zero bits left. So we need the (30 - exponent) last bits of the
+  // 31 higher bits of the mantissa to be null.
+  // Because bits [21:0] are null, we can check instead that the
+  // (32 - exponent) last bits of the 32 higher bits of the mantisssa are null.
+
+  // Get the 32 higher bits of the mantissa in dst.
+  __ Ubfx(dst,
+          src2,
+          HeapNumber::kMantissaBitsInTopWord,
+          32 - HeapNumber::kMantissaBitsInTopWord);
+  __ orr(dst,
+         dst,
+         Operand(src1, LSL, HeapNumber::kNonMantissaBitsInTopWord));
+
+  // Create the mask and test the lower bits (of the higher bits).
+  __ rsb(scratch, scratch, Operand(32));
+  __ mov(src2, Operand(1));
+  __ mov(src1, Operand(src2, LSL, scratch));
+  __ sub(src1, src1, Operand(1));
+  __ tst(dst, src1);
+  __ b(ne, not_int32);
+}
+
+
+void FloatingPointHelper::CallCCodeForDoubleOperation(
+    MacroAssembler* masm,
+    Token::Value op,
+    Register heap_number_result,
+    Register scratch) {
+  // Using core registers:
+  // r0: Left value (least significant part of mantissa).
+  // r1: Left value (sign, exponent, top of mantissa).
+  // r2: Right value (least significant part of mantissa).
+  // r3: Right value (sign, exponent, top of mantissa).
+
+  // Assert that heap_number_result is callee-saved.
+  // We currently always use r5 to pass it.
+  ASSERT(heap_number_result.is(r5));
+
+  // Push the current return address before the C call. Return will be
+  // through pop(pc) below.
+  __ push(lr);
+  __ PrepareCallCFunction(4, scratch);  // Two doubles are 4 arguments.
+  // Call C routine that may not cause GC or other trouble.
+  __ CallCFunction(ExternalReference::double_fp_operation(op), 4);
+  // Store answer in the overwritable heap number.
+#if !defined(USE_ARM_EABI)
+  // Double returned in fp coprocessor register 0 and 1, encoded as
+  // register cr8.  Offsets must be divisible by 4 for coprocessor so we
+  // need to substract the tag from heap_number_result.
+  __ sub(scratch, heap_number_result, Operand(kHeapObjectTag));
+  __ stc(p1, cr8, MemOperand(scratch, HeapNumber::kValueOffset));
+#else
+  // Double returned in registers 0 and 1.
+  __ Strd(r0, r1, FieldMemOperand(heap_number_result,
+                                  HeapNumber::kValueOffset));
+#endif
+  // Place heap_number_result in r0 and return to the pushed return address.
+  __ mov(r0, Operand(heap_number_result));
+  __ pop(pc);
+}
+
 
 // See comment for class.
 void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) {
@@ -1296,6 +1681,9 @@
 // This stub does not handle the inlined cases (Smis, Booleans, undefined).
 // The stub returns zero for false, and a non-zero value for true.
 void ToBooleanStub::Generate(MacroAssembler* masm) {
+  // This stub uses VFP3 instructions.
+  ASSERT(CpuFeatures::IsEnabled(VFP3));
+
   Label false_result;
   Label not_heap_number;
   Register scratch = r9.is(tos_) ? r7 : r9;
@@ -2661,8 +3049,8 @@
 
       // Allocate new heap number for result.
       Register result = r5;
-      __ AllocateHeapNumber(
-          result, scratch1, scratch2, heap_number_map, gc_required);
+      GenerateHeapResultAllocation(
+          masm, result, heap_number_map, scratch1, scratch2, gc_required);
 
       // Load the operands.
       if (smi_operands) {
@@ -2704,33 +3092,11 @@
         __ add(r0, r0, Operand(kHeapObjectTag));
         __ Ret();
       } else {
-        // Using core registers:
-        // r0: Left value (least significant part of mantissa).
-        // r1: Left value (sign, exponent, top of mantissa).
-        // r2: Right value (least significant part of mantissa).
-        // r3: Right value (sign, exponent, top of mantissa).
-
-        // Push the current return address before the C call. Return will be
-        // through pop(pc) below.
-        __ push(lr);
-        __ PrepareCallCFunction(4, scratch1);  // Two doubles are 4 arguments.
-        // Call C routine that may not cause GC or other trouble. r5 is callee
-        // save.
-        __ CallCFunction(ExternalReference::double_fp_operation(op_), 4);
-        // Store answer in the overwritable heap number.
-#if !defined(USE_ARM_EABI)
-        // Double returned in fp coprocessor register 0 and 1, encoded as
-        // register cr8.  Offsets must be divisible by 4 for coprocessor so we
-        // need to substract the tag from r5.
-        __ sub(scratch1, result, Operand(kHeapObjectTag));
-        __ stc(p1, cr8, MemOperand(scratch1, HeapNumber::kValueOffset));
-#else
-        // Double returned in registers 0 and 1.
-        __ Strd(r0, r1, FieldMemOperand(result, HeapNumber::kValueOffset));
-#endif
-        // Plase result in r0 and return to the pushed return address.
-        __ mov(r0, Operand(result));
-        __ pop(pc);
+        // Call the C function to handle the double operation.
+        FloatingPointHelper::CallCCodeForDoubleOperation(masm,
+                                                         op_,
+                                                         result,
+                                                         scratch1);
       }
       break;
     }
@@ -2776,7 +3142,6 @@
           break;
         case Token::SAR:
           // Use only the 5 least significant bits of the shift count.
-          __ and_(r2, r2, Operand(0x1f));
           __ GetLeastBitsFromInt32(r2, r2, 5);
           __ mov(r2, Operand(r3, ASR, r2));
           break;
@@ -2811,8 +3176,14 @@
 
       // Allocate new heap number for result.
       __ bind(&result_not_a_smi);
-      __ AllocateHeapNumber(
-          r5, scratch1, scratch2, heap_number_map, gc_required);
+      Register result = r5;
+      if (smi_operands) {
+        __ AllocateHeapNumber(
+            result, scratch1, scratch2, heap_number_map, gc_required);
+      } else {
+        GenerateHeapResultAllocation(
+            masm, result, heap_number_map, scratch1, scratch2, gc_required);
+      }
 
       // r2: Answer as signed int32.
       // r5: Heap number to write answer into.
@@ -2915,7 +3286,288 @@
 void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
   ASSERT(operands_type_ == TRBinaryOpIC::INT32);
 
-  GenerateTypeTransition(masm);
+  Register left = r1;
+  Register right = r0;
+  Register scratch1 = r7;
+  Register scratch2 = r9;
+  DwVfpRegister double_scratch = d0;
+  SwVfpRegister single_scratch = s3;
+
+  Register heap_number_result = no_reg;
+  Register heap_number_map = r6;
+  __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+
+  Label call_runtime;
+  // Labels for type transition, used for wrong input or output types.
+  // Both label are currently actually bound to the same position. We use two
+  // different label to differentiate the cause leading to type transition.
+  Label transition;
+
+  // Smi-smi fast case.
+  Label skip;
+  __ orr(scratch1, left, right);
+  __ JumpIfNotSmi(scratch1, &skip);
+  GenerateSmiSmiOperation(masm);
+  // Fall through if the result is not a smi.
+  __ bind(&skip);
+
+  switch (op_) {
+    case Token::ADD:
+    case Token::SUB:
+    case Token::MUL:
+    case Token::DIV:
+    case Token::MOD: {
+    // Load both operands and check that they are 32-bit integer.
+    // Jump to type transition if they are not. The registers r0 and r1 (right
+    // and left) are preserved for the runtime call.
+    FloatingPointHelper::Destination destination =
+        CpuFeatures::IsSupported(VFP3) && op_ != Token::MOD ?
+        FloatingPointHelper::kVFPRegisters :
+        FloatingPointHelper::kCoreRegisters;
+
+    FloatingPointHelper::LoadNumberAsInt32Double(masm,
+                                                 right,
+                                                 destination,
+                                                 d7,
+                                                 r2,
+                                                 r3,
+                                                 heap_number_map,
+                                                 scratch1,
+                                                 scratch2,
+                                                 s0,
+                                                 &transition);
+    FloatingPointHelper::LoadNumberAsInt32Double(masm,
+                                                 left,
+                                                 destination,
+                                                 d6,
+                                                 r4,
+                                                 r5,
+                                                 heap_number_map,
+                                                 scratch1,
+                                                 scratch2,
+                                                 s0,
+                                                 &transition);
+
+      if (destination == FloatingPointHelper::kVFPRegisters) {
+        CpuFeatures::Scope scope(VFP3);
+        Label return_heap_number;
+        switch (op_) {
+          case Token::ADD:
+            __ vadd(d5, d6, d7);
+            break;
+          case Token::SUB:
+            __ vsub(d5, d6, d7);
+            break;
+          case Token::MUL:
+            __ vmul(d5, d6, d7);
+            break;
+          case Token::DIV:
+            __ vdiv(d5, d6, d7);
+            break;
+          default:
+            UNREACHABLE();
+        }
+
+        if (op_ != Token::DIV) {
+          // These operations produce an integer result.
+          // Try to return a smi if we can.
+          // Otherwise return a heap number if allowed, or jump to type
+          // transition.
+
+          __ EmitVFPTruncate(kRoundToZero,
+                             single_scratch,
+                             d5,
+                             scratch1,
+                             scratch2);
+
+          if (result_type_ <= TRBinaryOpIC::INT32) {
+            // If the ne condition is set, result does
+            // not fit in a 32-bit integer.
+            __ b(ne, &transition);
+          }
+
+          // Check if the result fits in a smi.
+          __ vmov(scratch1, single_scratch);
+          __ add(scratch2, scratch1, Operand(0x40000000), SetCC);
+          // If not try to return a heap number.
+          __ b(mi, &return_heap_number);
+          // Tag the result and return.
+          __ SmiTag(r0, scratch1);
+          __ Ret();
+        }
+
+        if (result_type_ >= (op_ == Token::DIV) ? TRBinaryOpIC::HEAP_NUMBER
+                                                : TRBinaryOpIC::INT32) {
+          __ bind(&return_heap_number);
+          // We are using vfp registers so r5 is available.
+          heap_number_result = r5;
+          GenerateHeapResultAllocation(masm,
+                                       heap_number_result,
+                                       heap_number_map,
+                                       scratch1,
+                                       scratch2,
+                                       &call_runtime);
+          __ sub(r0, heap_number_result, Operand(kHeapObjectTag));
+          __ vstr(d5, r0, HeapNumber::kValueOffset);
+          __ mov(r0, heap_number_result);
+          __ Ret();
+        }
+
+        // A DIV operation expecting an integer result falls through
+        // to type transition.
+
+      } else {
+        // We preserved r0 and r1 to be able to call runtime.
+        // Save the left value on the stack.
+        __ Push(r5, r4);
+
+        // Allocate a heap number to store the result.
+        heap_number_result = r5;
+        GenerateHeapResultAllocation(masm,
+                                     heap_number_result,
+                                     heap_number_map,
+                                     scratch1,
+                                     scratch2,
+                                     &call_runtime);
+
+        // Load the left value from the value saved on the stack.
+        __ Pop(r1, r0);
+
+        // Call the C function to handle the double operation.
+        FloatingPointHelper::CallCCodeForDoubleOperation(
+            masm, op_, heap_number_result, scratch1);
+      }
+
+      break;
+    }
+
+    case Token::BIT_OR:
+    case Token::BIT_XOR:
+    case Token::BIT_AND:
+    case Token::SAR:
+    case Token::SHR:
+    case Token::SHL: {
+      Label return_heap_number;
+      Register scratch3 = r5;
+      // Convert operands to 32-bit integers. Right in r2 and left in r3. The
+      // registers r0 and r1 (right and left) are preserved for the runtime
+      // call.
+      FloatingPointHelper::LoadNumberAsInt32(masm,
+                                             left,
+                                             r3,
+                                             heap_number_map,
+                                             scratch1,
+                                             scratch2,
+                                             scratch3,
+                                             d0,
+                                             &transition);
+      FloatingPointHelper::LoadNumberAsInt32(masm,
+                                             right,
+                                             r2,
+                                             heap_number_map,
+                                             scratch1,
+                                             scratch2,
+                                             scratch3,
+                                             d0,
+                                             &transition);
+
+      // The ECMA-262 standard specifies that, for shift operations, only the
+      // 5 least significant bits of the shift value should be used.
+      switch (op_) {
+        case Token::BIT_OR:
+          __ orr(r2, r3, Operand(r2));
+          break;
+        case Token::BIT_XOR:
+          __ eor(r2, r3, Operand(r2));
+          break;
+        case Token::BIT_AND:
+          __ and_(r2, r3, Operand(r2));
+          break;
+        case Token::SAR:
+          __ and_(r2, r2, Operand(0x1f));
+          __ mov(r2, Operand(r3, ASR, r2));
+          break;
+        case Token::SHR:
+          __ and_(r2, r2, Operand(0x1f));
+          __ mov(r2, Operand(r3, LSR, r2), SetCC);
+          // SHR is special because it is required to produce a positive answer.
+          // We only get a negative result if the shift value (r2) is 0.
+          // This result cannot be respresented as a signed 32-bit integer, try
+          // to return a heap number if we can.
+          // The non vfp3 code does not support this special case, so jump to
+          // runtime if we don't support it.
+          if (CpuFeatures::IsSupported(VFP3)) {
+            __ b(mi,
+                 (result_type_ <= TRBinaryOpIC::INT32) ? &transition
+                                                       : &return_heap_number);
+          } else {
+            __ b(mi, (result_type_ <= TRBinaryOpIC::INT32) ? &transition
+                                                           : &call_runtime);
+          }
+          break;
+        case Token::SHL:
+          __ and_(r2, r2, Operand(0x1f));
+          __ mov(r2, Operand(r3, LSL, r2));
+          break;
+        default:
+          UNREACHABLE();
+      }
+
+      // Check if the result fits in a smi.
+      __ add(scratch1, r2, Operand(0x40000000), SetCC);
+      // If not try to return a heap number. (We know the result is an int32.)
+      __ b(mi, &return_heap_number);
+      // Tag the result and return.
+      __ SmiTag(r0, r2);
+      __ Ret();
+
+      __ bind(&return_heap_number);
+      if (CpuFeatures::IsSupported(VFP3)) {
+        CpuFeatures::Scope scope(VFP3);
+        heap_number_result = r5;
+        GenerateHeapResultAllocation(masm,
+                                     heap_number_result,
+                                     heap_number_map,
+                                     scratch1,
+                                     scratch2,
+                                     &call_runtime);
+
+        if (op_ != Token::SHR) {
+          // Convert the result to a floating point value.
+          __ vmov(double_scratch.low(), r2);
+          __ vcvt_f64_s32(double_scratch, double_scratch.low());
+        } else {
+          // The result must be interpreted as an unsigned 32-bit integer.
+          __ vmov(double_scratch.low(), r2);
+          __ vcvt_f64_u32(double_scratch, double_scratch.low());
+        }
+
+        // Store the result.
+        __ sub(r0, heap_number_result, Operand(kHeapObjectTag));
+        __ vstr(double_scratch, r0, HeapNumber::kValueOffset);
+        __ mov(r0, heap_number_result);
+        __ Ret();
+      } else {
+        // Tail call that writes the int32 in r2 to the heap number in r0, using
+        // r3 as scratch. r0 is preserved and returned.
+        WriteInt32ToHeapNumberStub stub(r2, r0, r3);
+        __ TailCallStub(&stub);
+      }
+
+      break;
+    }
+
+    default:
+      UNREACHABLE();
+  }
+
+  if (transition.is_linked()) {
+    __ bind(&transition);
+    GenerateTypeTransition(masm);
+  }
+
+  __ bind(&call_runtime);
+  GenerateCallRuntime(masm);
 }
 
 
@@ -2934,45 +3586,47 @@
 
 
 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
-  Label call_runtime;
+  Label call_runtime, call_string_add_or_runtime;
 
   GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
 
-  // If all else fails, use the runtime system to get the correct
-  // result.
-  __ bind(&call_runtime);
+  GenerateFPOperation(masm, false, &call_string_add_or_runtime, &call_runtime);
 
-  // Try to add strings before calling runtime.
+  __ bind(&call_string_add_or_runtime);
   if (op_ == Token::ADD) {
     GenerateAddStrings(masm);
   }
 
-  GenericBinaryOpStub stub(op_, mode_, r1, r0);
-  __ TailCallStub(&stub);
+  __ bind(&call_runtime);
+  GenerateCallRuntime(masm);
 }
 
 
 void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
   ASSERT(op_ == Token::ADD);
+  Label left_not_string, call_runtime;
 
   Register left = r1;
   Register right = r0;
-  Label call_runtime;
 
-  // Check if first argument is a string.
-  __ JumpIfSmi(left, &call_runtime);
+  // Check if left argument is a string.
+  __ JumpIfSmi(left, &left_not_string);
   __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE);
-  __ b(ge, &call_runtime);
+  __ b(ge, &left_not_string);
 
-  // First argument is a a string, test second.
+  StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB);
+  GenerateRegisterArgsPush(masm);
+  __ TailCallStub(&string_add_left_stub);
+
+  // Left operand is not a string, test right.
+  __ bind(&left_not_string);
   __ JumpIfSmi(right, &call_runtime);
   __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE);
   __ b(ge, &call_runtime);
 
-  // First and second argument are strings.
-  StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB);
+  StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB);
   GenerateRegisterArgsPush(masm);
-  __ TailCallStub(&string_add_stub);
+  __ TailCallStub(&string_add_right_stub);
 
   // At least one argument is not a string.
   __ bind(&call_runtime);
@@ -3061,32 +3715,47 @@
 
 
 void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
-  // Argument is a number and is on stack and in r0.
-  Label runtime_call;
+  // Untagged case: double input in d2, double result goes
+  //   into d2.
+  // Tagged case: tagged input on top of stack and in r0,
+  //   tagged result (heap number) goes into r0.
+
   Label input_not_smi;
   Label loaded;
+  Label calculate;
+  Label invalid_cache;
+  const Register scratch0 = r9;
+  const Register scratch1 = r7;
+  const Register cache_entry = r0;
+  const bool tagged = (argument_type_ == TAGGED);
 
   if (CpuFeatures::IsSupported(VFP3)) {
-    // Load argument and check if it is a smi.
-    __ JumpIfNotSmi(r0, &input_not_smi);
-
     CpuFeatures::Scope scope(VFP3);
-    // Input is a smi. Convert to double and load the low and high words
-    // of the double into r2, r3.
-    __ IntegerToDoubleConversionWithVFP3(r0, r3, r2);
-    __ b(&loaded);
+    if (tagged) {
+      // Argument is a number and is on stack and in r0.
+      // Load argument and check if it is a smi.
+      __ JumpIfNotSmi(r0, &input_not_smi);
 
-    __ bind(&input_not_smi);
-    // Check if input is a HeapNumber.
-    __ CheckMap(r0,
-                r1,
-                Heap::kHeapNumberMapRootIndex,
-                &runtime_call,
-                true);
-    // Input is a HeapNumber. Load it to a double register and store the
-    // low and high words into r2, r3.
-    __ Ldrd(r2, r3, FieldMemOperand(r0, HeapNumber::kValueOffset));
+      // Input is a smi. Convert to double and load the low and high words
+      // of the double into r2, r3.
+      __ IntegerToDoubleConversionWithVFP3(r0, r3, r2);
+      __ b(&loaded);
 
+      __ bind(&input_not_smi);
+      // Check if input is a HeapNumber.
+      __ CheckMap(r0,
+                  r1,
+                  Heap::kHeapNumberMapRootIndex,
+                  &calculate,
+                  true);
+      // Input is a HeapNumber. Load it to a double register and store the
+      // low and high words into r2, r3.
+      __ vldr(d0, FieldMemOperand(r0, HeapNumber::kValueOffset));
+      __ vmov(r2, r3, d0);
+    } else {
+      // Input is untagged double in d2. Output goes to d2.
+      __ vmov(r2, r3, d2);
+    }
     __ bind(&loaded);
     // r2 = low 32 bits of double value
     // r3 = high 32 bits of double value
@@ -3101,14 +3770,15 @@
     // r2 = low 32 bits of double value.
     // r3 = high 32 bits of double value.
     // r1 = TranscendentalCache::hash(double value).
-    __ mov(r0,
+    __ mov(cache_entry,
            Operand(ExternalReference::transcendental_cache_array_address()));
     // r0 points to cache array.
-    __ ldr(r0, MemOperand(r0, type_ * sizeof(TranscendentalCache::caches_[0])));
+    __ ldr(cache_entry, MemOperand(cache_entry,
+        type_ * sizeof(TranscendentalCache::caches_[0])));
     // r0 points to the cache for the type type_.
     // If NULL, the cache hasn't been initialized yet, so go through runtime.
-    __ cmp(r0, Operand(0, RelocInfo::NONE));
-    __ b(eq, &runtime_call);
+    __ cmp(cache_entry, Operand(0, RelocInfo::NONE));
+    __ b(eq, &invalid_cache);
 
 #ifdef DEBUG
     // Check that the layout of cache elements match expectations.
@@ -3127,21 +3797,109 @@
 
     // Find the address of the r1'st entry in the cache, i.e., &r0[r1*12].
     __ add(r1, r1, Operand(r1, LSL, 1));
-    __ add(r0, r0, Operand(r1, LSL, 2));
+    __ add(cache_entry, cache_entry, Operand(r1, LSL, 2));
     // Check if cache matches: Double value is stored in uint32_t[2] array.
-    __ ldm(ia, r0, r4.bit()| r5.bit() | r6.bit());
+    __ ldm(ia, cache_entry, r4.bit() | r5.bit() | r6.bit());
     __ cmp(r2, r4);
-    __ b(ne, &runtime_call);
+    __ b(ne, &calculate);
     __ cmp(r3, r5);
-    __ b(ne, &runtime_call);
-    // Cache hit. Load result, pop argument and return.
-    __ mov(r0, Operand(r6));
-    __ pop();
+    __ b(ne, &calculate);
+    // Cache hit. Load result, cleanup and return.
+    if (tagged) {
+      // Pop input value from stack and load result into r0.
+      __ pop();
+      __ mov(r0, Operand(r6));
+    } else {
+      // Load result into d2.
+       __ vldr(d2, FieldMemOperand(r6, HeapNumber::kValueOffset));
+    }
+    __ Ret();
+  }  // if (CpuFeatures::IsSupported(VFP3))
+
+  __ bind(&calculate);
+  if (tagged) {
+    __ bind(&invalid_cache);
+    __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
+  } else {
+    if (!CpuFeatures::IsSupported(VFP3)) UNREACHABLE();
+    CpuFeatures::Scope scope(VFP3);
+
+    Label no_update;
+    Label skip_cache;
+    const Register heap_number_map = r5;
+
+    // Call C function to calculate the result and update the cache.
+    // Register r0 holds precalculated cache entry address; preserve
+    // it on the stack and pop it into register cache_entry after the
+    // call.
+    __ push(cache_entry);
+    GenerateCallCFunction(masm, scratch0);
+    __ GetCFunctionDoubleResult(d2);
+
+    // Try to update the cache. If we cannot allocate a
+    // heap number, we return the result without updating.
+    __ pop(cache_entry);
+    __ LoadRoot(r5, Heap::kHeapNumberMapRootIndex);
+    __ AllocateHeapNumber(r6, scratch0, scratch1, r5, &no_update);
+    __ vstr(d2, FieldMemOperand(r6, HeapNumber::kValueOffset));
+    __ stm(ia, cache_entry, r2.bit() | r3.bit() | r6.bit());
+    __ Ret();
+
+    __ bind(&invalid_cache);
+    // The cache is invalid. Call runtime which will recreate the
+    // cache.
+    __ LoadRoot(r5, Heap::kHeapNumberMapRootIndex);
+    __ AllocateHeapNumber(r0, scratch0, scratch1, r5, &skip_cache);
+    __ vstr(d2, FieldMemOperand(r0, HeapNumber::kValueOffset));
+    __ EnterInternalFrame();
+    __ push(r0);
+    __ CallRuntime(RuntimeFunction(), 1);
+    __ LeaveInternalFrame();
+    __ vldr(d2, FieldMemOperand(r0, HeapNumber::kValueOffset));
+    __ Ret();
+
+    __ bind(&skip_cache);
+    // Call C function to calculate the result and answer directly
+    // without updating the cache.
+    GenerateCallCFunction(masm, scratch0);
+    __ GetCFunctionDoubleResult(d2);
+    __ bind(&no_update);
+
+    // We return the value in d2 without adding it to the cache, but
+    // we cause a scavenging GC so that future allocations will succeed.
+    __ EnterInternalFrame();
+
+    // Allocate an aligned object larger than a HeapNumber.
+    ASSERT(4 * kPointerSize >= HeapNumber::kSize);
+    __ mov(scratch0, Operand(4 * kPointerSize));
+    __ push(scratch0);
+    __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace);
+    __ LeaveInternalFrame();
     __ Ret();
   }
+}
 
-  __ bind(&runtime_call);
-  __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
+
+void TranscendentalCacheStub::GenerateCallCFunction(MacroAssembler* masm,
+                                                    Register scratch) {
+  __ push(lr);
+  __ PrepareCallCFunction(2, scratch);
+  __ vmov(r0, r1, d2);
+  switch (type_) {
+    case TranscendentalCache::SIN:
+      __ CallCFunction(ExternalReference::math_sin_double_function(), 2);
+      break;
+    case TranscendentalCache::COS:
+      __ CallCFunction(ExternalReference::math_cos_double_function(), 2);
+      break;
+    case TranscendentalCache::LOG:
+      __ CallCFunction(ExternalReference::math_log_double_function(), 2);
+      break;
+    default:
+      UNIMPLEMENTED();
+      break;
+  }
+  __ pop(lr);
 }
 
 
@@ -3299,105 +4057,13 @@
 
 
 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
-  // r0 holds the exception.
-
-  // Adjust this code if not the case.
-  STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
-
-  // Drop the sp to the top of the handler.
-  __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
-  __ ldr(sp, MemOperand(r3));
-
-  // Restore the next handler and frame pointer, discard handler state.
-  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
-  __ pop(r2);
-  __ str(r2, MemOperand(r3));
-  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
-  __ ldm(ia_w, sp, r3.bit() | fp.bit());  // r3: discarded state.
-
-  // Before returning we restore the context from the frame pointer if
-  // not NULL.  The frame pointer is NULL in the exception handler of a
-  // JS entry frame.
-  __ cmp(fp, Operand(0, RelocInfo::NONE));
-  // Set cp to NULL if fp is NULL.
-  __ mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq);
-  // Restore cp otherwise.
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
-#ifdef DEBUG
-  if (FLAG_debug_code) {
-    __ mov(lr, Operand(pc));
-  }
-#endif
-  STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
-  __ pop(pc);
+  __ Throw(r0);
 }
 
 
 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm,
                                           UncatchableExceptionType type) {
-  // Adjust this code if not the case.
-  STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
-
-  // Drop sp to the top stack handler.
-  __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
-  __ ldr(sp, MemOperand(r3));
-
-  // Unwind the handlers until the ENTRY handler is found.
-  Label loop, done;
-  __ bind(&loop);
-  // Load the type of the current stack handler.
-  const int kStateOffset = StackHandlerConstants::kStateOffset;
-  __ ldr(r2, MemOperand(sp, kStateOffset));
-  __ cmp(r2, Operand(StackHandler::ENTRY));
-  __ b(eq, &done);
-  // Fetch the next handler in the list.
-  const int kNextOffset = StackHandlerConstants::kNextOffset;
-  __ ldr(sp, MemOperand(sp, kNextOffset));
-  __ jmp(&loop);
-  __ bind(&done);
-
-  // Set the top handler address to next handler past the current ENTRY handler.
-  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
-  __ pop(r2);
-  __ str(r2, MemOperand(r3));
-
-  if (type == OUT_OF_MEMORY) {
-    // Set external caught exception to false.
-    ExternalReference external_caught(Top::k_external_caught_exception_address);
-    __ mov(r0, Operand(false, RelocInfo::NONE));
-    __ mov(r2, Operand(external_caught));
-    __ str(r0, MemOperand(r2));
-
-    // Set pending exception and r0 to out of memory exception.
-    Failure* out_of_memory = Failure::OutOfMemoryException();
-    __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
-    __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address)));
-    __ str(r0, MemOperand(r2));
-  }
-
-  // Stack layout at this point. See also StackHandlerConstants.
-  // sp ->   state (ENTRY)
-  //         fp
-  //         lr
-
-  // Discard handler state (r2 is not used) and restore frame pointer.
-  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
-  __ ldm(ia_w, sp, r2.bit() | fp.bit());  // r2: discarded state.
-  // Before returning we restore the context from the frame pointer if
-  // not NULL.  The frame pointer is NULL in the exception handler of a
-  // JS entry frame.
-  __ cmp(fp, Operand(0, RelocInfo::NONE));
-  // Set cp to NULL if fp is NULL.
-  __ mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq);
-  // Restore cp otherwise.
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
-#ifdef DEBUG
-  if (FLAG_debug_code) {
-    __ mov(lr, Operand(pc));
-  }
-#endif
-  STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
-  __ pop(pc);
+  __ ThrowUncatchable(type, r0);
 }
 
 
@@ -3484,7 +4150,9 @@
   // r0:r1: result
   // sp: stack pointer
   // fp: frame pointer
-  __ LeaveExitFrame(save_doubles_);
+  //  Callee-saved register r4 still holds argc.
+  __ LeaveExitFrame(save_doubles_, r4);
+  __ mov(pc, lr);
 
   // check if we should retry or throw exception
   Label retry;
@@ -3796,7 +4464,7 @@
 
     // The offset was stored in r4 safepoint slot.
     // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal)
-    __ ldr(scratch, MacroAssembler::SafepointRegisterSlot(r4));
+    __ LoadFromSafepointRegisterSlot(scratch, r4);
     __ sub(inline_site, lr, scratch);
     // Get the map location in scratch and patch it.
     __ GetRelocatedValueLocation(inline_site, scratch);
@@ -4263,24 +4931,27 @@
   __ IncrementCounter(&Counters::regexp_entry_native, 1, r0, r2);
 
   static const int kRegExpExecuteArguments = 7;
-  __ push(lr);
-  __ PrepareCallCFunction(kRegExpExecuteArguments, r0);
+  static const int kParameterRegisters = 4;
+  __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
 
-  // Argument 7 (sp[8]): Indicate that this is a direct call from JavaScript.
+  // Stack pointer now points to cell where return address is to be written.
+  // Arguments are before that on the stack or in registers.
+
+  // Argument 7 (sp[12]): Indicate that this is a direct call from JavaScript.
   __ mov(r0, Operand(1));
-  __ str(r0, MemOperand(sp, 2 * kPointerSize));
+  __ str(r0, MemOperand(sp, 3 * kPointerSize));
 
-  // Argument 6 (sp[4]): Start (high end) of backtracking stack memory area.
+  // Argument 6 (sp[8]): Start (high end) of backtracking stack memory area.
   __ mov(r0, Operand(address_of_regexp_stack_memory_address));
   __ ldr(r0, MemOperand(r0, 0));
   __ mov(r2, Operand(address_of_regexp_stack_memory_size));
   __ ldr(r2, MemOperand(r2, 0));
   __ add(r0, r0, Operand(r2));
-  __ str(r0, MemOperand(sp, 1 * kPointerSize));
+  __ str(r0, MemOperand(sp, 2 * kPointerSize));
 
-  // Argument 5 (sp[0]): static offsets vector buffer.
+  // Argument 5 (sp[4]): static offsets vector buffer.
   __ mov(r0, Operand(ExternalReference::address_of_static_offsets_vector()));
-  __ str(r0, MemOperand(sp, 0 * kPointerSize));
+  __ str(r0, MemOperand(sp, 1 * kPointerSize));
 
   // For arguments 4 and 3 get string length, calculate start of string data and
   // calculate the shift of the index (0 for ASCII and 1 for two byte).
@@ -4302,8 +4973,10 @@
 
   // Locate the code entry and call it.
   __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag));
-  __ CallCFunction(r7, kRegExpExecuteArguments);
-  __ pop(lr);
+  DirectCEntryStub stub;
+  stub.GenerateCall(masm, r7);
+
+  __ LeaveExitFrame(false, no_reg);
 
   // r0: result
   // subject: subject string (callee saved)
@@ -4312,6 +4985,7 @@
 
   // Check the result.
   Label success;
+
   __ cmp(r0, Operand(NativeRegExpMacroAssembler::SUCCESS));
   __ b(eq, &success);
   Label failure;
@@ -4324,12 +4998,26 @@
   // stack overflow (on the backtrack stack) was detected in RegExp code but
   // haven't created the exception yet. Handle that in the runtime system.
   // TODO(592): Rerunning the RegExp to get the stack overflow exception.
-  __ mov(r0, Operand(ExternalReference::the_hole_value_location()));
-  __ ldr(r0, MemOperand(r0, 0));
-  __ mov(r1, Operand(ExternalReference(Top::k_pending_exception_address)));
+  __ mov(r1, Operand(ExternalReference::the_hole_value_location()));
   __ ldr(r1, MemOperand(r1, 0));
+  __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address)));
+  __ ldr(r0, MemOperand(r2, 0));
   __ cmp(r0, r1);
   __ b(eq, &runtime);
+
+  __ str(r1, MemOperand(r2, 0));  // Clear pending exception.
+
+  // Check if the exception is a termination. If so, throw as uncatchable.
+  __ LoadRoot(ip, Heap::kTerminationExceptionRootIndex);
+  __ cmp(r0, ip);
+  Label termination_exception;
+  __ b(eq, &termination_exception);
+
+  __ Throw(r0);  // Expects thrown value in r0.
+
+  __ bind(&termination_exception);
+  __ ThrowUncatchable(TERMINATION, r0);  // Expects thrown value in r0.
+
   __ bind(&failure);
   // For failure and exception return null.
   __ mov(r0, Operand(Factory::null_value()));
@@ -5508,18 +6196,19 @@
 
 
 void StringAddStub::Generate(MacroAssembler* masm) {
-  Label string_add_runtime;
+  Label string_add_runtime, call_builtin;
+  Builtins::JavaScript builtin_id = Builtins::ADD;
+
   // Stack on entry:
-  // sp[0]: second argument.
-  // sp[4]: first argument.
+  // sp[0]: second argument (right).
+  // sp[4]: first argument (left).
 
   // Load the two arguments.
   __ ldr(r0, MemOperand(sp, 1 * kPointerSize));  // First argument.
   __ ldr(r1, MemOperand(sp, 0 * kPointerSize));  // Second argument.
 
   // Make sure that both arguments are strings if not known in advance.
-  if (string_check_) {
-    STATIC_ASSERT(kSmiTag == 0);
+  if (flags_ == NO_STRING_ADD_FLAGS) {
     __ JumpIfEitherSmi(r0, r1, &string_add_runtime);
     // Load instance types.
     __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
@@ -5531,13 +6220,27 @@
     __ tst(r4, Operand(kIsNotStringMask));
     __ tst(r5, Operand(kIsNotStringMask), eq);
     __ b(ne, &string_add_runtime);
+  } else {
+    // Here at least one of the arguments is definitely a string.
+    // We convert the one that is not known to be a string.
+    if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) {
+      ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0);
+      GenerateConvertArgument(
+          masm, 1 * kPointerSize, r0, r2, r3, r4, r5, &call_builtin);
+      builtin_id = Builtins::STRING_ADD_RIGHT;
+    } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) {
+      ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0);
+      GenerateConvertArgument(
+          masm, 0 * kPointerSize, r1, r2, r3, r4, r5, &call_builtin);
+      builtin_id = Builtins::STRING_ADD_LEFT;
+    }
   }
 
   // Both arguments are strings.
   // r0: first string
   // r1: second string
-  // r4: first string instance type (if string_check_)
-  // r5: second string instance type (if string_check_)
+  // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
+  // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
   {
     Label strings_not_empty;
     // Check if either of the strings are empty. In that case return the other.
@@ -5565,8 +6268,8 @@
   // r1: second string
   // r2: length of first string
   // r3: length of second string
-  // r4: first string instance type (if string_check_)
-  // r5: second string instance type (if string_check_)
+  // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
+  // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
   // Look at the length of the result of adding the two strings.
   Label string_add_flat_result, longer_than_two;
   // Adding two lengths can't overflow.
@@ -5578,7 +6281,7 @@
   __ b(ne, &longer_than_two);
 
   // Check that both strings are non-external ascii strings.
-  if (!string_check_) {
+  if (flags_ != NO_STRING_ADD_FLAGS) {
     __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
     __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
     __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
@@ -5626,7 +6329,7 @@
 
   // If result is not supposed to be flat, allocate a cons string object.
   // If both strings are ascii the result is an ascii cons string.
-  if (!string_check_) {
+  if (flags_ != NO_STRING_ADD_FLAGS) {
     __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
     __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
     __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
@@ -5674,11 +6377,11 @@
   // r1: second string
   // r2: length of first string
   // r3: length of second string
-  // r4: first string instance type (if string_check_)
-  // r5: second string instance type (if string_check_)
+  // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
+  // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
   // r6: sum of lengths.
   __ bind(&string_add_flat_result);
-  if (!string_check_) {
+  if (flags_ != NO_STRING_ADD_FLAGS) {
     __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
     __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
     __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
@@ -5776,6 +6479,60 @@
   // Just jump to runtime to add the two strings.
   __ bind(&string_add_runtime);
   __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
+
+  if (call_builtin.is_linked()) {
+    __ bind(&call_builtin);
+    __ InvokeBuiltin(builtin_id, JUMP_JS);
+  }
+}
+
+
+void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
+                                            int stack_offset,
+                                            Register arg,
+                                            Register scratch1,
+                                            Register scratch2,
+                                            Register scratch3,
+                                            Register scratch4,
+                                            Label* slow) {
+  // First check if the argument is already a string.
+  Label not_string, done;
+  __ JumpIfSmi(arg, &not_string);
+  __ CompareObjectType(arg, scratch1, scratch1, FIRST_NONSTRING_TYPE);
+  __ b(lt, &done);
+
+  // Check the number to string cache.
+  Label not_cached;
+  __ bind(&not_string);
+  // Puts the cached result into scratch1.
+  NumberToStringStub::GenerateLookupNumberStringCache(masm,
+                                                      arg,
+                                                      scratch1,
+                                                      scratch2,
+                                                      scratch3,
+                                                      scratch4,
+                                                      false,
+                                                      &not_cached);
+  __ mov(arg, scratch1);
+  __ str(arg, MemOperand(sp, stack_offset));
+  __ jmp(&done);
+
+  // Check if the argument is a safe string wrapper.
+  __ bind(&not_cached);
+  __ JumpIfSmi(arg, slow);
+  __ CompareObjectType(
+      arg, scratch1, scratch2, JS_VALUE_TYPE);  // map -> scratch1.
+  __ b(ne, slow);
+  __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitField2Offset));
+  __ and_(scratch2,
+          scratch2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
+  __ cmp(scratch2,
+         Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
+  __ b(ne, slow);
+  __ ldr(arg, FieldMemOperand(arg, JSValue::kValueOffset));
+  __ str(arg, MemOperand(sp, stack_offset));
+
+  __ bind(&done);
 }
 
 
@@ -5950,14 +6707,23 @@
 
 
 void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
-                                    ApiFunction *function) {
+                                    ExternalReference function) {
+  __ mov(lr, Operand(reinterpret_cast<intptr_t>(GetCode().location()),
+                     RelocInfo::CODE_TARGET));
+  __ mov(r2, Operand(function));
+  // Push return address (accessible to GC through exit frame pc).
+  __ str(pc, MemOperand(sp, 0));
+  __ Jump(r2);  // Call the api function.
+}
+
+
+void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
+                                    Register target) {
   __ mov(lr, Operand(reinterpret_cast<intptr_t>(GetCode().location()),
                      RelocInfo::CODE_TARGET));
   // Push return address (accessible to GC through exit frame pc).
-  __ mov(r2,
-         Operand(ExternalReference(function, ExternalReference::DIRECT_CALL)));
   __ str(pc, MemOperand(sp, 0));
-  __ Jump(r2);  // Call the api function.
+  __ Jump(target);  // Call the C++ function.
 }
 
 
@@ -6028,6 +6794,91 @@
 }
 
 
+void GenerateFastPixelArrayStore(MacroAssembler* masm,
+                                 Register receiver,
+                                 Register key,
+                                 Register value,
+                                 Register elements,
+                                 Register elements_map,
+                                 Register scratch1,
+                                 Register scratch2,
+                                 bool load_elements_from_receiver,
+                                 bool load_elements_map_from_elements,
+                                 Label* key_not_smi,
+                                 Label* value_not_smi,
+                                 Label* not_pixel_array,
+                                 Label* out_of_range) {
+  // Register use:
+  //   receiver - holds the receiver and is unchanged unless the
+  //              store succeeds.
+  //   key - holds the key (must be a smi) and is unchanged.
+  //   value - holds the value (must be a smi) and is unchanged.
+  //   elements - holds the element object of the receiver on entry if
+  //              load_elements_from_receiver is false, otherwise used
+  //              internally to store the pixel arrays elements and
+  //              external array pointer.
+  //   elements_map - holds the map of the element object if
+  //              load_elements_map_from_elements is false, otherwise
+  //              loaded with the element map.
+  //
+  Register external_pointer = elements;
+  Register untagged_key = scratch1;
+  Register untagged_value = scratch2;
+
+  if (load_elements_from_receiver) {
+    __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
+  }
+
+  // By passing NULL as not_pixel_array, callers signal that they have already
+  // verified that the receiver has pixel array elements.
+  if (not_pixel_array != NULL) {
+    if (load_elements_map_from_elements) {
+      __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
+    }
+    __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
+    __ cmp(elements_map, ip);
+    __ b(ne, not_pixel_array);
+  } else {
+    if (FLAG_debug_code) {
+      // Map check should have already made sure that elements is a pixel array.
+      __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
+      __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
+      __ cmp(elements_map, ip);
+      __ Assert(eq, "Elements isn't a pixel array");
+    }
+  }
+
+  // Some callers already have verified that the key is a smi.  key_not_smi is
+  // set to NULL as a sentinel for that case.  Otherwise, add an explicit check
+  // to ensure the key is a smi must be added.
+  if (key_not_smi != NULL) {
+    __ JumpIfNotSmi(key, key_not_smi);
+  } else {
+    if (FLAG_debug_code) {
+      __ AbortIfNotSmi(key);
+    }
+  }
+
+  __ SmiUntag(untagged_key, key);
+
+  // Perform bounds check.
+  __ ldr(scratch2, FieldMemOperand(elements, PixelArray::kLengthOffset));
+  __ cmp(untagged_key, scratch2);
+  __ b(hs, out_of_range);  // unsigned check handles negative keys.
+
+  __ JumpIfNotSmi(value, value_not_smi);
+  __ SmiUntag(untagged_value, value);
+
+  // Clamp the value to [0..255].
+  __ Usat(untagged_value, 8, Operand(untagged_value));
+  // Get the pointer to the external array. This clobbers elements.
+  __ ldr(external_pointer,
+         FieldMemOperand(elements, PixelArray::kExternalPointerOffset));
+  __ strb(untagged_value, MemOperand(external_pointer, untagged_key));
+  __ Ret();
+}
+
+
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/arm/code-stubs-arm.h b/src/arm/code-stubs-arm.h
index bf7d635..e3ef339 100644
--- a/src/arm/code-stubs-arm.h
+++ b/src/arm/code-stubs-arm.h
@@ -38,13 +38,22 @@
 // TranscendentalCache runtime function.
 class TranscendentalCacheStub: public CodeStub {
  public:
-  explicit TranscendentalCacheStub(TranscendentalCache::Type type)
-      : type_(type) {}
+  enum ArgumentType {
+    TAGGED = 0 << TranscendentalCache::kTranscendentalTypeBits,
+    UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits
+  };
+
+  TranscendentalCacheStub(TranscendentalCache::Type type,
+                          ArgumentType argument_type)
+      : type_(type), argument_type_(argument_type) { }
   void Generate(MacroAssembler* masm);
  private:
   TranscendentalCache::Type type_;
+  ArgumentType argument_type_;
+  void GenerateCallCFunction(MacroAssembler* masm, Register scratch);
+
   Major MajorKey() { return TranscendentalCache; }
-  int MinorKey() { return type_; }
+  int MinorKey() { return type_ | argument_type_; }
   Runtime::FunctionId RuntimeFunction();
 };
 
@@ -335,24 +344,36 @@
 // Flag that indicates how to generate code for the stub StringAddStub.
 enum StringAddFlags {
   NO_STRING_ADD_FLAGS = 0,
-  NO_STRING_CHECK_IN_STUB = 1 << 0  // Omit string check in stub.
+  // Omit left string check in stub (left is definitely a string).
+  NO_STRING_CHECK_LEFT_IN_STUB = 1 << 0,
+  // Omit right string check in stub (right is definitely a string).
+  NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 1,
+  // Omit both string checks in stub.
+  NO_STRING_CHECK_IN_STUB =
+      NO_STRING_CHECK_LEFT_IN_STUB | NO_STRING_CHECK_RIGHT_IN_STUB
 };
 
 
 class StringAddStub: public CodeStub {
  public:
-  explicit StringAddStub(StringAddFlags flags) {
-    string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0);
-  }
+  explicit StringAddStub(StringAddFlags flags) : flags_(flags) {}
 
  private:
   Major MajorKey() { return StringAdd; }
-  int MinorKey() { return string_check_ ? 0 : 1; }
+  int MinorKey() { return flags_; }
 
   void Generate(MacroAssembler* masm);
 
-  // Should the stub check whether arguments are strings?
-  bool string_check_;
+  void GenerateConvertArgument(MacroAssembler* masm,
+                               int stack_offset,
+                               Register arg,
+                               Register scratch1,
+                               Register scratch2,
+                               Register scratch3,
+                               Register scratch4,
+                               Label* slow);
+
+  const StringAddFlags flags_;
 };
 
 
@@ -580,7 +601,8 @@
  public:
   DirectCEntryStub() {}
   void Generate(MacroAssembler* masm);
-  void GenerateCall(MacroAssembler* masm, ApiFunction *function);
+  void GenerateCall(MacroAssembler* masm, ExternalReference function);
+  void GenerateCall(MacroAssembler* masm, Register target);
 
  private:
   Major MajorKey() { return DirectCEntry; }
@@ -589,14 +611,14 @@
 };
 
 
-// Generate code the to load an element from a pixel array. The receiver is
-// assumed to not be a smi and to have elements, the caller must guarantee this
-// precondition. If the receiver does not have elements that are pixel arrays,
-// the generated code jumps to not_pixel_array. If key is not a smi, then the
-// generated code branches to key_not_smi. Callers can specify NULL for
-// key_not_smi to signal that a smi check has already been performed on key so
-// that the smi check is not generated . If key is not a valid index within the
-// bounds of the pixel array, the generated code jumps to out_of_range.
+// Generate code to load an element from a pixel array. The receiver is assumed
+// to not be a smi and to have elements, the caller must guarantee this
+// precondition. If key is not a smi, then the generated code branches to
+// key_not_smi. Callers can specify NULL for key_not_smi to signal that a smi
+// check has already been performed on key so that the smi check is not
+// generated. If key is not a valid index within the bounds of the pixel array,
+// the generated code jumps to out_of_range. receiver, key and elements are
+// unchanged throughout the generated code sequence.
 void GenerateFastPixelArrayLoad(MacroAssembler* masm,
                                 Register receiver,
                                 Register key,
@@ -609,6 +631,35 @@
                                 Label* key_not_smi,
                                 Label* out_of_range);
 
+// Generate code to store an element into a pixel array, clamping values between
+// [0..255]. The receiver is assumed to not be a smi and to have elements, the
+// caller must guarantee this precondition. If key is not a smi, then the
+// generated code branches to key_not_smi. Callers can specify NULL for
+// key_not_smi to signal that a smi check has already been performed on key so
+// that the smi check is not generated. If value is not a smi, the generated
+// code will branch to value_not_smi.  If the receiver doesn't have pixel array
+// elements, the generated code will branch to not_pixel_array, unless
+// not_pixel_array is NULL, in which case the caller must ensure that the
+// receiver has pixel array elements. If key is not a valid index within the
+// bounds of the pixel array, the generated code jumps to out_of_range. If
+// load_elements_from_receiver is true, then the elements of receiver is loaded
+// into elements, otherwise elements is assumed to already be the receiver's
+// elements. If load_elements_map_from_elements is true, elements_map is loaded
+// from elements, otherwise it is assumed to already contain the element map.
+void GenerateFastPixelArrayStore(MacroAssembler* masm,
+                                 Register receiver,
+                                 Register key,
+                                 Register value,
+                                 Register elements,
+                                 Register elements_map,
+                                 Register scratch1,
+                                 Register scratch2,
+                                 bool load_elements_from_receiver,
+                                 bool load_elements_map_from_elements,
+                                 Label* key_not_smi,
+                                 Label* value_not_smi,
+                                 Label* not_pixel_array,
+                                 Label* out_of_range);
 
 } }  // namespace v8::internal
 
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index c827110..d32b009 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -1938,8 +1938,9 @@
   frame_->EmitPush(cp);
   frame_->EmitPush(Operand(pairs));
   frame_->EmitPush(Operand(Smi::FromInt(is_eval() ? 1 : 0)));
+  frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag())));
 
-  frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
+  frame_->CallRuntime(Runtime::kDeclareGlobals, 4);
   // The result is discarded.
 }
 
@@ -3287,7 +3288,8 @@
       // context slot followed by initialization.
       frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
     } else {
-      frame_->CallRuntime(Runtime::kStoreContextSlot, 3);
+      frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag())));
+      frame_->CallRuntime(Runtime::kStoreContextSlot, 4);
     }
     // Storing a variable must keep the (new) value on the expression
     // stack. This is necessary for compiling assignment expressions.
@@ -3637,7 +3639,8 @@
         Load(key);
         Load(value);
         if (property->emit_store()) {
-          frame_->CallRuntime(Runtime::kSetProperty, 3);
+          frame_->EmitPush(Operand(Smi::FromInt(NONE)));  // PropertyAttributes
+          frame_->CallRuntime(Runtime::kSetProperty, 4);
         } else {
           frame_->Drop(3);
         }
@@ -5170,11 +5173,11 @@
 
     // Set the bit in the map to indicate that it has been checked safe for
     // default valueOf and set true result.
-    __ ldr(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset));
+    __ ldrb(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset));
     __ orr(scratch1_,
            scratch1_,
            Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
-    __ str(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset));
+    __ strb(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset));
     __ mov(map_result_, Operand(1));
     __ jmp(exit_label());
     __ bind(&false_result);
@@ -5656,7 +5659,8 @@
   ASSERT_EQ(args->length(), 1);
   Load(args->at(0));
   if (CpuFeatures::IsSupported(VFP3)) {
-    TranscendentalCacheStub stub(TranscendentalCache::SIN);
+    TranscendentalCacheStub stub(TranscendentalCache::SIN,
+                                 TranscendentalCacheStub::TAGGED);
     frame_->SpillAllButCopyTOSToR0();
     frame_->CallStub(&stub, 1);
   } else {
@@ -5670,7 +5674,8 @@
   ASSERT_EQ(args->length(), 1);
   Load(args->at(0));
   if (CpuFeatures::IsSupported(VFP3)) {
-    TranscendentalCacheStub stub(TranscendentalCache::COS);
+    TranscendentalCacheStub stub(TranscendentalCache::COS,
+                                 TranscendentalCacheStub::TAGGED);
     frame_->SpillAllButCopyTOSToR0();
     frame_->CallStub(&stub, 1);
   } else {
@@ -5684,7 +5689,8 @@
   ASSERT_EQ(args->length(), 1);
   Load(args->at(0));
   if (CpuFeatures::IsSupported(VFP3)) {
-    TranscendentalCacheStub stub(TranscendentalCache::LOG);
+    TranscendentalCacheStub stub(TranscendentalCache::LOG,
+                                 TranscendentalCacheStub::TAGGED);
     frame_->SpillAllButCopyTOSToR0();
     frame_->CallStub(&stub, 1);
   } else {
@@ -5844,15 +5850,20 @@
     if (property != NULL) {
       Load(property->obj());
       Load(property->key());
-      frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2);
+      frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag())));
+      frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 3);
       frame_->EmitPush(r0);
 
     } else if (variable != NULL) {
+      // Delete of an unqualified identifier is disallowed in strict mode
+      // but "delete this" is.
+      ASSERT(strict_mode_flag() == kNonStrictMode || variable->is_this());
       Slot* slot = variable->AsSlot();
       if (variable->is_global()) {
         LoadGlobal();
         frame_->EmitPush(Operand(variable->name()));
-        frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2);
+        frame_->EmitPush(Operand(Smi::FromInt(kNonStrictMode)));
+        frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 3);
         frame_->EmitPush(r0);
 
       } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
@@ -6669,8 +6680,12 @@
  public:
   DeferredReferenceSetKeyedValue(Register value,
                                  Register key,
-                                 Register receiver)
-      : value_(value), key_(key), receiver_(receiver) {
+                                 Register receiver,
+                                 StrictModeFlag strict_mode)
+      : value_(value),
+        key_(key),
+        receiver_(receiver),
+        strict_mode_(strict_mode) {
     set_comment("[ DeferredReferenceSetKeyedValue");
   }
 
@@ -6680,6 +6695,7 @@
   Register value_;
   Register key_;
   Register receiver_;
+  StrictModeFlag strict_mode_;
 };
 
 
@@ -6701,7 +6717,9 @@
   { Assembler::BlockConstPoolScope block_const_pool(masm_);
     // Call keyed store IC. It has the arguments value, key and receiver in r0,
     // r1 and r2.
-    Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+    Handle<Code> ic(Builtins::builtin(
+        (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
+                                      : Builtins::KeyedStoreIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET);
     // The call must be followed by a nop instruction to indicate that the
     // keyed store has been inlined.
@@ -6719,8 +6737,12 @@
  public:
   DeferredReferenceSetNamedValue(Register value,
                                  Register receiver,
-                                 Handle<String> name)
-      : value_(value), receiver_(receiver), name_(name) {
+                                 Handle<String> name,
+                                 StrictModeFlag strict_mode)
+      : value_(value),
+        receiver_(receiver),
+        name_(name),
+        strict_mode_(strict_mode) {
     set_comment("[ DeferredReferenceSetNamedValue");
   }
 
@@ -6730,6 +6752,7 @@
   Register value_;
   Register receiver_;
   Handle<String> name_;
+  StrictModeFlag strict_mode_;
 };
 
 
@@ -6749,7 +6772,9 @@
   { Assembler::BlockConstPoolScope block_const_pool(masm_);
     // Call keyed store IC. It has the arguments value, key and receiver in r0,
     // r1 and r2.
-    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+    Handle<Code> ic(Builtins::builtin(
+        (strict_mode_ == kStrictMode) ? Builtins::StoreIC_Initialize_Strict
+                                      : Builtins::StoreIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET);
     // The call must be followed by a nop instruction to indicate that the
     // named store has been inlined.
@@ -6938,7 +6963,8 @@
     Register receiver = r1;
 
     DeferredReferenceSetNamedValue* deferred =
-        new DeferredReferenceSetNamedValue(value, receiver, name);
+        new DeferredReferenceSetNamedValue(
+          value, receiver, name, strict_mode_flag());
 
     // Check that the receiver is a heap object.
     __ tst(receiver, Operand(kSmiTagMask));
@@ -7124,7 +7150,8 @@
 
     // The deferred code expects value, key and receiver in registers.
     DeferredReferenceSetKeyedValue* deferred =
-        new DeferredReferenceSetKeyedValue(value, key, receiver);
+        new DeferredReferenceSetKeyedValue(
+          value, key, receiver, strict_mode_flag());
 
     // Check that the value is a smi. As this inlined code does not set the
     // write barrier it is only possible to store smi values.
@@ -7209,7 +7236,7 @@
 
     deferred->BindExit();
   } else {
-    frame()->CallKeyedStoreIC();
+    frame()->CallKeyedStoreIC(strict_mode_flag());
   }
 }
 
diff --git a/src/arm/constants-arm.h b/src/arm/constants-arm.h
index 7ac38ed..e6033a8 100644
--- a/src/arm/constants-arm.h
+++ b/src/arm/constants-arm.h
@@ -385,7 +385,10 @@
   kDefaultRoundToZero = 1
 };
 
+// This mask does not include the "inexact" or "input denormal" cumulative
+// exceptions flags, because we usually don't want to check for it.
 static const uint32_t kVFPExceptionMask = 0xf;
+static const uint32_t kVFPInexactExceptionBit = 1 << 4;
 static const uint32_t kVFPFlushToZeroMask = 1 << 24;
 static const uint32_t kVFPInvalidExceptionBit = 1;
 
@@ -411,6 +414,11 @@
 
 static const uint32_t kVFPRoundingModeMask = 3 << 22;
 
+enum CheckForInexactConversion {
+  kCheckForInexactConversion,
+  kDontCheckForInexactConversion
+};
+
 // -----------------------------------------------------------------------------
 // Hints.
 
diff --git a/src/arm/cpu-arm.cc b/src/arm/cpu-arm.cc
index 507954d..51c84b3 100644
--- a/src/arm/cpu-arm.cc
+++ b/src/arm/cpu-arm.cc
@@ -50,6 +50,11 @@
 
 
 void CPU::FlushICache(void* start, size_t size) {
+  // Nothing to do flushing no instructions.
+  if (size == 0) {
+    return;
+  }
+
 #if defined (USE_SIMULATOR)
   // Not generating ARM instructions for C-code. This means that we are
   // building an ARM emulator based target.  We should notify the simulator
diff --git a/src/arm/deoptimizer-arm.cc b/src/arm/deoptimizer-arm.cc
index caec55a..9a5aa90 100644
--- a/src/arm/deoptimizer-arm.cc
+++ b/src/arm/deoptimizer-arm.cc
@@ -124,14 +124,62 @@
 void Deoptimizer::PatchStackCheckCodeAt(Address pc_after,
                                         Code* check_code,
                                         Code* replacement_code) {
-  UNIMPLEMENTED();
+  const int kInstrSize = Assembler::kInstrSize;
+  // The call of the stack guard check has the following form:
+  //  e1 5d 00 0c       cmp sp, <limit>
+  //  2a 00 00 01       bcs ok
+  //  e5 9f c? ??       ldr ip, [pc, <stack guard address>]
+  //  e1 2f ff 3c       blx ip
+  ASSERT(Memory::int32_at(pc_after - kInstrSize) ==
+      (al | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | ip.code()));
+  ASSERT(Assembler::IsLdrPcImmediateOffset(
+      Assembler::instr_at(pc_after - 2 * kInstrSize)));
+
+  // We patch the code to the following form:
+  //  e1 5d 00 0c       cmp sp, <limit>
+  //  e1 a0 00 00       mov r0, r0 (NOP)
+  //  e5 9f c? ??       ldr ip, [pc, <on-stack replacement address>]
+  //  e1 2f ff 3c       blx ip
+  // and overwrite the constant containing the
+  // address of the stack check stub.
+
+  // Replace conditional jump with NOP.
+  CodePatcher patcher(pc_after - 3 * kInstrSize, 1);
+  patcher.masm()->nop();
+
+  // Replace the stack check address in the constant pool
+  // with the entry address of the replacement code.
+  uint32_t stack_check_address_offset = Memory::uint16_at(pc_after -
+      2 * kInstrSize) & 0xfff;
+  Address stack_check_address_pointer = pc_after + stack_check_address_offset;
+  ASSERT(Memory::uint32_at(stack_check_address_pointer) ==
+         reinterpret_cast<uint32_t>(check_code->entry()));
+  Memory::uint32_at(stack_check_address_pointer) =
+      reinterpret_cast<uint32_t>(replacement_code->entry());
 }
 
 
 void Deoptimizer::RevertStackCheckCodeAt(Address pc_after,
                                          Code* check_code,
                                          Code* replacement_code) {
-  UNIMPLEMENTED();
+  const int kInstrSize = Assembler::kInstrSize;
+  ASSERT(Memory::uint32_at(pc_after - kInstrSize) == 0xe12fff3c);
+  ASSERT(Memory::uint8_at(pc_after - kInstrSize - 1) == 0xe5);
+  ASSERT(Memory::uint8_at(pc_after - kInstrSize - 2) == 0x9f);
+
+  // Replace NOP with conditional jump.
+  CodePatcher patcher(pc_after - 3 * kInstrSize, 1);
+  patcher.masm()->b(+4, cs);
+
+  // Replace the stack check address in the constant pool
+  // with the entry address of the replacement code.
+  uint32_t stack_check_address_offset = Memory::uint16_at(pc_after -
+      2 * kInstrSize) & 0xfff;
+  Address stack_check_address_pointer = pc_after + stack_check_address_offset;
+  ASSERT(Memory::uint32_at(stack_check_address_pointer) ==
+         reinterpret_cast<uint32_t>(replacement_code->entry()));
+  Memory::uint32_at(stack_check_address_pointer) =
+      reinterpret_cast<uint32_t>(check_code->entry());
 }
 
 
@@ -381,14 +429,16 @@
            fp_value, output_offset, value);
   }
 
-  // The context can be gotten from the function so long as we don't
-  // optimize functions that need local contexts.
+  // For the bottommost output frame the context can be gotten from the input
+  // frame. For all subsequent output frames it can be gotten from the function
+  // so long as we don't inline functions that need local contexts.
   output_offset -= kPointerSize;
   input_offset -= kPointerSize;
-  value = reinterpret_cast<intptr_t>(function->context());
-  // The context for the bottommost output frame should also agree with the
-  // input frame.
-  ASSERT(!is_bottommost || input_->GetFrameSlot(input_offset) == value);
+  if (is_bottommost) {
+    value = input_->GetFrameSlot(input_offset);
+  } else {
+    value = reinterpret_cast<intptr_t>(function->context());
+  }
   output_frame->SetFrameSlot(output_offset, value);
   if (is_topmost) {
     output_frame->SetRegister(cp.code(), value);
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 2685fcb..5f5de3a 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -219,46 +219,47 @@
     Move(dot_arguments_slot, r3, r1, r2);
   }
 
-  { Comment cmnt(masm_, "[ Declarations");
-    // For named function expressions, declare the function name as a
-    // constant.
-    if (scope()->is_function_scope() && scope()->function() != NULL) {
-      EmitDeclaration(scope()->function(), Variable::CONST, NULL);
-    }
-    // Visit all the explicit declarations unless there is an illegal
-    // redeclaration.
-    if (scope()->HasIllegalRedeclaration()) {
-      scope()->VisitIllegalRedeclaration(this);
-    } else {
-      VisitDeclarations(scope()->declarations());
-    }
-  }
-
   if (FLAG_trace) {
     __ CallRuntime(Runtime::kTraceEnter, 0);
   }
 
-  // Check the stack for overflow or break request.
-  { Comment cmnt(masm_, "[ Stack check");
-    PrepareForBailout(info->function(), NO_REGISTERS);
-    Label ok;
-    __ LoadRoot(ip, Heap::kStackLimitRootIndex);
-    __ cmp(sp, Operand(ip));
-    __ b(hs, &ok);
-    StackCheckStub stub;
-    __ CallStub(&stub);
-    __ bind(&ok);
+  // Visit the declarations and body unless there is an illegal
+  // redeclaration.
+  if (scope()->HasIllegalRedeclaration()) {
+    Comment cmnt(masm_, "[ Declarations");
+    scope()->VisitIllegalRedeclaration(this);
+
+  } else {
+    { Comment cmnt(masm_, "[ Declarations");
+      // For named function expressions, declare the function name as a
+      // constant.
+      if (scope()->is_function_scope() && scope()->function() != NULL) {
+        EmitDeclaration(scope()->function(), Variable::CONST, NULL);
+      }
+      VisitDeclarations(scope()->declarations());
+    }
+
+    { Comment cmnt(masm_, "[ Stack check");
+      PrepareForBailout(info->function(), NO_REGISTERS);
+      Label ok;
+      __ LoadRoot(ip, Heap::kStackLimitRootIndex);
+      __ cmp(sp, Operand(ip));
+      __ b(hs, &ok);
+      StackCheckStub stub;
+      __ CallStub(&stub);
+      __ bind(&ok);
+    }
+
+    { Comment cmnt(masm_, "[ Body");
+      ASSERT(loop_depth() == 0);
+      VisitStatements(function()->body());
+      ASSERT(loop_depth() == 0);
+    }
   }
 
-  { Comment cmnt(masm_, "[ Body");
-    ASSERT(loop_depth() == 0);
-    VisitStatements(function()->body());
-    ASSERT(loop_depth() == 0);
-  }
-
+  // Always emit a 'return undefined' in case control fell off the end of
+  // the body.
   { Comment cmnt(masm_, "[ return <undefined>;");
-    // Emit a 'return undefined' in case control fell off the end of the
-    // body.
     __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
   }
   EmitReturnSequence();
@@ -338,13 +339,6 @@
 }
 
 
-FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand(
-    Token::Value op, Expression* left, Expression* right) {
-  ASSERT(ShouldInlineSmiCase(op));
-  return kNoConstants;
-}
-
-
 void FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
 }
 
@@ -563,13 +557,38 @@
 void FullCodeGenerator::DoTest(Label* if_true,
                                Label* if_false,
                                Label* fall_through) {
-  // Call the runtime to find the boolean value of the source and then
-  // translate it into control flow to the pair of labels.
-  __ push(result_register());
-  __ CallRuntime(Runtime::kToBool, 1);
-  __ LoadRoot(ip, Heap::kTrueValueRootIndex);
-  __ cmp(r0, ip);
-  Split(eq, if_true, if_false, fall_through);
+  if (CpuFeatures::IsSupported(VFP3)) {
+    CpuFeatures::Scope scope(VFP3);
+    // Emit the inlined tests assumed by the stub.
+    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+    __ cmp(result_register(), ip);
+    __ b(eq, if_false);
+    __ LoadRoot(ip, Heap::kTrueValueRootIndex);
+    __ cmp(result_register(), ip);
+    __ b(eq, if_true);
+    __ LoadRoot(ip, Heap::kFalseValueRootIndex);
+    __ cmp(result_register(), ip);
+    __ b(eq, if_false);
+    STATIC_ASSERT(kSmiTag == 0);
+    __ tst(result_register(), result_register());
+    __ b(eq, if_false);
+    __ JumpIfSmi(result_register(), if_true);
+
+    // Call the ToBoolean stub for all other cases.
+    ToBooleanStub stub(result_register());
+    __ CallStub(&stub);
+    __ tst(result_register(), result_register());
+  } else {
+    // Call the runtime to find the boolean value of the source and then
+    // translate it into control flow to the pair of labels.
+    __ push(result_register());
+    __ CallRuntime(Runtime::kToBool, 1);
+    __ LoadRoot(ip, Heap::kFalseValueRootIndex);
+    __ cmp(r0, ip);
+  }
+
+  // The stub returns nonzero for true.
+  Split(ne, if_true, if_false, fall_through);
 }
 
 
@@ -684,10 +703,11 @@
         // We bypass the general EmitSlotSearch because we know more about
         // this specific context.
 
-        // The variable in the decl always resides in the current context.
+        // The variable in the decl always resides in the current function
+        // context.
         ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
         if (FLAG_debug_code) {
-          // Check if we have the correct context pointer.
+          // Check that we're not inside a 'with'.
           __ ldr(r1, ContextOperand(cp, Context::FCONTEXT_INDEX));
           __ cmp(r1, cp);
           __ Check(eq, "Unexpected declaration in current context.");
@@ -756,7 +776,9 @@
              prop->key()->AsLiteral()->handle()->IsSmi());
       __ mov(r1, Operand(prop->key()->AsLiteral()->handle()));
 
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(is_strict()
+          ? Builtins::KeyedStoreIC_Initialize_Strict
+          : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       // Value in r0 is ignored (declarations are statements).
     }
@@ -772,10 +794,11 @@
 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
   // Call the runtime to declare the globals.
   // The context is the first argument.
-  __ mov(r1, Operand(pairs));
-  __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
-  __ Push(cp, r1, r0);
-  __ CallRuntime(Runtime::kDeclareGlobals, 3);
+  __ mov(r2, Operand(pairs));
+  __ mov(r1, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
+  __ mov(r0, Operand(Smi::FromInt(strict_mode_flag())));
+  __ Push(cp, r2, r1, r0);
+  __ CallRuntime(Runtime::kDeclareGlobals, 4);
   // Return value is ignored.
 }
 
@@ -784,9 +807,9 @@
   Comment cmnt(masm_, "[ SwitchStatement");
   Breakable nested_statement(this, stmt);
   SetStatementPosition(stmt);
+
   // Keep the switch value on the stack until a case matches.
   VisitForStackValue(stmt->tag());
-
   PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
 
   ZoneList<CaseClause*>* clauses = stmt->cases();
@@ -875,8 +898,9 @@
   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
   __ cmp(r0, ip);
   __ b(eq, &exit);
-  __ LoadRoot(ip, Heap::kNullValueRootIndex);
-  __ cmp(r0, ip);
+  Register null_value = r5;
+  __ LoadRoot(null_value, Heap::kNullValueRootIndex);
+  __ cmp(r0, null_value);
   __ b(eq, &exit);
 
   // Convert the object to a JS object.
@@ -890,12 +914,62 @@
   __ bind(&done_convert);
   __ push(r0);
 
-  // BUG(867): Check cache validity in generated code. This is a fast
-  // case for the JSObject::IsSimpleEnum cache validity checks. If we
-  // cannot guarantee cache validity, call the runtime system to check
-  // cache validity or get the property names in a fixed array.
+  // Check cache validity in generated code. This is a fast case for
+  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
+  // guarantee cache validity, call the runtime system to check cache
+  // validity or get the property names in a fixed array.
+  Label next, call_runtime;
+  // Preload a couple of values used in the loop.
+  Register  empty_fixed_array_value = r6;
+  __ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
+  Register empty_descriptor_array_value = r7;
+  __ LoadRoot(empty_descriptor_array_value,
+              Heap::kEmptyDescriptorArrayRootIndex);
+  __ mov(r1, r0);
+  __ bind(&next);
+
+  // Check that there are no elements.  Register r1 contains the
+  // current JS object we've reached through the prototype chain.
+  __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset));
+  __ cmp(r2, empty_fixed_array_value);
+  __ b(ne, &call_runtime);
+
+  // Check that instance descriptors are not empty so that we can
+  // check for an enum cache.  Leave the map in r2 for the subsequent
+  // prototype load.
+  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ ldr(r3, FieldMemOperand(r2, Map::kInstanceDescriptorsOffset));
+  __ cmp(r3, empty_descriptor_array_value);
+  __ b(eq, &call_runtime);
+
+  // Check that there is an enum cache in the non-empty instance
+  // descriptors (r3).  This is the case if the next enumeration
+  // index field does not contain a smi.
+  __ ldr(r3, FieldMemOperand(r3, DescriptorArray::kEnumerationIndexOffset));
+  __ JumpIfSmi(r3, &call_runtime);
+
+  // For all objects but the receiver, check that the cache is empty.
+  Label check_prototype;
+  __ cmp(r1, r0);
+  __ b(eq, &check_prototype);
+  __ ldr(r3, FieldMemOperand(r3, DescriptorArray::kEnumCacheBridgeCacheOffset));
+  __ cmp(r3, empty_fixed_array_value);
+  __ b(ne, &call_runtime);
+
+  // Load the prototype from the map and loop if non-null.
+  __ bind(&check_prototype);
+  __ ldr(r1, FieldMemOperand(r2, Map::kPrototypeOffset));
+  __ cmp(r1, null_value);
+  __ b(ne, &next);
+
+  // The enum cache is valid.  Load the map of the object being
+  // iterated over and use the cache for the iteration.
+  Label use_cache;
+  __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
+  __ b(&use_cache);
 
   // Get the set of properties to enumerate.
+  __ bind(&call_runtime);
   __ push(r0);  // Duplicate the enumerable object on the stack.
   __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
 
@@ -910,6 +984,7 @@
   __ b(ne, &fixed_array);
 
   // We got a map in register r0. Get the enumeration cache from it.
+  __ bind(&use_cache);
   __ ldr(r1, FieldMemOperand(r0, Map::kInstanceDescriptorsOffset));
   __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset));
   __ ldr(r2, FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));
@@ -998,8 +1073,14 @@
 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
                                        bool pretenure) {
   // Use the fast case closure allocation code that allocates in new
-  // space for nested functions that don't need literals cloning.
-  if (scope()->is_function_scope() &&
+  // space for nested functions that don't need literals cloning. If
+  // we're running with the --always-opt or the --prepare-always-opt
+  // flag, we need to use the runtime function so that the new function
+  // we are creating here gets a chance to have its code optimized and
+  // doesn't just get a copy of the existing unoptimized code.
+  if (!FLAG_always_opt &&
+      !FLAG_prepare_always_opt &&
+      scope()->is_function_scope() &&
       info->num_literals() == 0 &&
       !pretenure) {
     FastNewClosureStub stub;
@@ -1027,7 +1108,7 @@
     Slot* slot,
     Label* slow) {
   ASSERT(slot->type() == Slot::CONTEXT);
-  Register current = cp;
+  Register context = cp;
   Register next = r3;
   Register temp = r4;
 
@@ -1035,22 +1116,25 @@
     if (s->num_heap_slots() > 0) {
       if (s->calls_eval()) {
         // Check that extension is NULL.
-        __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX));
+        __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX));
         __ tst(temp, temp);
         __ b(ne, slow);
       }
-      __ ldr(next, ContextOperand(current, Context::CLOSURE_INDEX));
+      __ ldr(next, ContextOperand(context, Context::CLOSURE_INDEX));
       __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset));
       // Walk the rest of the chain without clobbering cp.
-      current = next;
+      context = next;
     }
   }
   // Check that last extension is NULL.
-  __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX));
+  __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX));
   __ tst(temp, temp);
   __ b(ne, slow);
-  __ ldr(temp, ContextOperand(current, Context::FCONTEXT_INDEX));
-  return ContextOperand(temp, slot->index());
+
+  // This function is used only for loads, not stores, so it's safe to
+  // return an cp-based operand (the write barrier cannot be allowed to
+  // destroy the cp register).
+  return ContextOperand(context, slot->index());
 }
 
 
@@ -1250,18 +1334,19 @@
   Comment cmnt(masm_, "[ RegExpLiteral");
   Label materialized;
   // Registers will be used as follows:
+  // r5 = materialized value (RegExp literal)
   // r4 = JS function, literals array
   // r3 = literal index
   // r2 = RegExp pattern
   // r1 = RegExp flags
-  // r0 = temp + materialized value (RegExp literal)
+  // r0 = RegExp literal clone
   __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
   int literal_offset =
       FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
-  __ ldr(r0, FieldMemOperand(r4, literal_offset));
+  __ ldr(r5, FieldMemOperand(r4, literal_offset));
   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
-  __ cmp(r0, ip);
+  __ cmp(r5, ip);
   __ b(ne, &materialized);
 
   // Create regexp literal using runtime function.
@@ -1271,20 +1356,27 @@
   __ mov(r1, Operand(expr->flags()));
   __ Push(r4, r3, r2, r1);
   __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
+  __ mov(r5, r0);
 
   __ bind(&materialized);
   int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
-  __ push(r0);
+  Label allocated, runtime_allocate;
+  __ AllocateInNewSpace(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT);
+  __ jmp(&allocated);
+
+  __ bind(&runtime_allocate);
+  __ push(r5);
   __ mov(r0, Operand(Smi::FromInt(size)));
   __ push(r0);
   __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
+  __ pop(r5);
 
+  __ bind(&allocated);
   // After this, registers are used as follows:
   // r0: Newly allocated regexp.
-  // r1: Materialized regexp.
+  // r5: Materialized regexp.
   // r2: temp.
-  __ pop(r1);
-  __ CopyFields(r0, r1, r2.bit(), size / kPointerSize);
+  __ CopyFields(r0, r5, r2.bit(), size / kPointerSize);
   context()->Plug(r0);
 }
 
@@ -1350,7 +1442,9 @@
         VisitForStackValue(key);
         VisitForStackValue(value);
         if (property->emit_store()) {
-          __ CallRuntime(Runtime::kSetProperty, 3);
+          __ mov(r0, Operand(Smi::FromInt(NONE)));  // PropertyAttributes
+          __ push(r0);
+          __ CallRuntime(Runtime::kSetProperty, 4);
         } else {
           __ Drop(3);
         }
@@ -1528,14 +1622,8 @@
     }
 
     Token::Value op = expr->binary_op();
-    ConstantOperand constant = ShouldInlineSmiCase(op)
-        ? GetConstantOperand(op, expr->target(), expr->value())
-        : kNoConstants;
-    ASSERT(constant == kRightConstant || constant == kNoConstants);
-    if (constant == kNoConstants) {
-      __ push(r0);  // Left operand goes on the stack.
-      VisitForAccumulatorValue(expr->value());
-    }
+    __ push(r0);  // Left operand goes on the stack.
+    VisitForAccumulatorValue(expr->value());
 
     OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
         ? OVERWRITE_RIGHT
@@ -1547,8 +1635,7 @@
                             op,
                             mode,
                             expr->target(),
-                            expr->value(),
-                            constant);
+                            expr->value());
     } else {
       EmitBinaryOp(op, mode);
     }
@@ -1601,11 +1688,99 @@
 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
                                               Token::Value op,
                                               OverwriteMode mode,
-                                              Expression* left,
-                                              Expression* right,
-                                              ConstantOperand constant) {
-  ASSERT(constant == kNoConstants);  // Only handled case.
-  EmitBinaryOp(op, mode);
+                                              Expression* left_expr,
+                                              Expression* right_expr) {
+  Label done, smi_case, stub_call;
+
+  Register scratch1 = r2;
+  Register scratch2 = r3;
+
+  // Get the arguments.
+  Register left = r1;
+  Register right = r0;
+  __ pop(left);
+
+  // Perform combined smi check on both operands.
+  __ orr(scratch1, left, Operand(right));
+  STATIC_ASSERT(kSmiTag == 0);
+  JumpPatchSite patch_site(masm_);
+  patch_site.EmitJumpIfSmi(scratch1, &smi_case);
+
+  __ bind(&stub_call);
+  TypeRecordingBinaryOpStub stub(op, mode);
+  EmitCallIC(stub.GetCode(), &patch_site);
+  __ jmp(&done);
+
+  __ bind(&smi_case);
+  // Smi case. This code works the same way as the smi-smi case in the type
+  // recording binary operation stub, see
+  // TypeRecordingBinaryOpStub::GenerateSmiSmiOperation for comments.
+  switch (op) {
+    case Token::SAR:
+      __ b(&stub_call);
+      __ GetLeastBitsFromSmi(scratch1, right, 5);
+      __ mov(right, Operand(left, ASR, scratch1));
+      __ bic(right, right, Operand(kSmiTagMask));
+      break;
+    case Token::SHL: {
+      __ b(&stub_call);
+      __ SmiUntag(scratch1, left);
+      __ GetLeastBitsFromSmi(scratch2, right, 5);
+      __ mov(scratch1, Operand(scratch1, LSL, scratch2));
+      __ add(scratch2, scratch1, Operand(0x40000000), SetCC);
+      __ b(mi, &stub_call);
+      __ SmiTag(right, scratch1);
+      break;
+    }
+    case Token::SHR: {
+      __ b(&stub_call);
+      __ SmiUntag(scratch1, left);
+      __ GetLeastBitsFromSmi(scratch2, right, 5);
+      __ mov(scratch1, Operand(scratch1, LSR, scratch2));
+      __ tst(scratch1, Operand(0xc0000000));
+      __ b(ne, &stub_call);
+      __ SmiTag(right, scratch1);
+      break;
+    }
+    case Token::ADD:
+      __ add(scratch1, left, Operand(right), SetCC);
+      __ b(vs, &stub_call);
+      __ mov(right, scratch1);
+      break;
+    case Token::SUB:
+      __ sub(scratch1, left, Operand(right), SetCC);
+      __ b(vs, &stub_call);
+      __ mov(right, scratch1);
+      break;
+    case Token::MUL: {
+      __ SmiUntag(ip, right);
+      __ smull(scratch1, scratch2, left, ip);
+      __ mov(ip, Operand(scratch1, ASR, 31));
+      __ cmp(ip, Operand(scratch2));
+      __ b(ne, &stub_call);
+      __ tst(scratch1, Operand(scratch1));
+      __ mov(right, Operand(scratch1), LeaveCC, ne);
+      __ b(ne, &done);
+      __ add(scratch2, right, Operand(left), SetCC);
+      __ mov(right, Operand(Smi::FromInt(0)), LeaveCC, pl);
+      __ b(mi, &stub_call);
+      break;
+    }
+    case Token::BIT_OR:
+      __ orr(right, left, Operand(right));
+      break;
+    case Token::BIT_AND:
+      __ and_(right, left, Operand(right));
+      break;
+    case Token::BIT_XOR:
+      __ eor(right, left, Operand(right));
+      break;
+    default:
+      UNREACHABLE();
+  }
+
+  __ bind(&done);
+  context()->Plug(r0);
 }
 
 
@@ -1650,18 +1825,32 @@
       __ mov(r1, r0);
       __ pop(r0);  // Restore value.
       __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::StoreIC_Initialize_Strict
+                      : Builtins::StoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
     case KEYED_PROPERTY: {
       __ push(r0);  // Preserve value.
-      VisitForStackValue(prop->obj());
-      VisitForAccumulatorValue(prop->key());
-      __ mov(r1, r0);
-      __ pop(r2);
+      if (prop->is_synthetic()) {
+        ASSERT(prop->obj()->AsVariableProxy() != NULL);
+        ASSERT(prop->key()->AsLiteral() != NULL);
+        { AccumulatorValueContext for_object(this);
+          EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
+        }
+        __ mov(r2, r0);
+        __ mov(r1, Operand(prop->key()->AsLiteral()->handle()));
+      } else {
+        VisitForStackValue(prop->obj());
+        VisitForAccumulatorValue(prop->key());
+        __ mov(r1, r0);
+        __ pop(r2);
+      }
       __ pop(r0);  // Restore value.
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                      : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
@@ -1685,39 +1874,65 @@
     // r2, and the global object in r1.
     __ mov(r2, Operand(var->name()));
     __ ldr(r1, GlobalObjectOperand());
-    Handle<Code> ic(Builtins::builtin(is_strict()
-        ? Builtins::StoreIC_Initialize_Strict
-        : Builtins::StoreIC_Initialize));
+    Handle<Code> ic(Builtins::builtin(
+        is_strict() ? Builtins::StoreIC_Initialize_Strict
+                    : Builtins::StoreIC_Initialize));
     EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
 
-  } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) {
-    // Perform the assignment for non-const variables and for initialization
-    // of const variables.  Const assignments are simply skipped.
-    Label done;
+  } else if (op == Token::INIT_CONST) {
+    // Like var declarations, const declarations are hoisted to function
+    // scope.  However, unlike var initializers, const initializers are able
+    // to drill a hole to that function context, even from inside a 'with'
+    // context.  We thus bypass the normal static scope lookup.
+    Slot* slot = var->AsSlot();
+    Label skip;
+    switch (slot->type()) {
+      case Slot::PARAMETER:
+        // No const parameters.
+        UNREACHABLE();
+        break;
+      case Slot::LOCAL:
+        // Detect const reinitialization by checking for the hole value.
+        __ ldr(r1, MemOperand(fp, SlotOffset(slot)));
+        __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+        __ cmp(r1, ip);
+        __ b(ne, &skip);
+        __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
+        break;
+      case Slot::CONTEXT: {
+        __ ldr(r1, ContextOperand(cp, Context::FCONTEXT_INDEX));
+        __ ldr(r2, ContextOperand(r1, slot->index()));
+        __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+        __ cmp(r2, ip);
+        __ b(ne, &skip);
+        __ str(r0, ContextOperand(r1, slot->index()));
+        int offset = Context::SlotOffset(slot->index());
+        __ mov(r3, r0);  // Preserve the stored value in r0.
+        __ RecordWrite(r1, Operand(offset), r3, r2);
+        break;
+      }
+      case Slot::LOOKUP:
+        __ push(r0);
+        __ mov(r0, Operand(slot->var()->name()));
+        __ Push(cp, r0);  // Context and name.
+        __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
+        break;
+    }
+    __ bind(&skip);
+
+  } else if (var->mode() != Variable::CONST) {
+    // Perform the assignment for non-const variables.  Const assignments
+    // are simply skipped.
     Slot* slot = var->AsSlot();
     switch (slot->type()) {
       case Slot::PARAMETER:
       case Slot::LOCAL:
-        if (op == Token::INIT_CONST) {
-          // Detect const reinitialization by checking for the hole value.
-          __ ldr(r1, MemOperand(fp, SlotOffset(slot)));
-          __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
-          __ cmp(r1, ip);
-          __ b(ne, &done);
-        }
         // Perform the assignment.
         __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
         break;
 
       case Slot::CONTEXT: {
         MemOperand target = EmitSlotSearch(slot, r1);
-        if (op == Token::INIT_CONST) {
-          // Detect const reinitialization by checking for the hole value.
-          __ ldr(r2, target);
-          __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
-          __ cmp(r2, ip);
-          __ b(ne, &done);
-        }
         // Perform the assignment and issue the write barrier.
         __ str(result_register(), target);
         // RecordWrite may destroy all its register arguments.
@@ -1728,20 +1943,14 @@
       }
 
       case Slot::LOOKUP:
-        // Call the runtime for the assignment.  The runtime will ignore
-        // const reinitialization.
+        // Call the runtime for the assignment.
         __ push(r0);  // Value.
-        __ mov(r0, Operand(slot->var()->name()));
-        __ Push(cp, r0);  // Context and name.
-        if (op == Token::INIT_CONST) {
-          // The runtime will ignore const redeclaration.
-          __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
-        } else {
-          __ CallRuntime(Runtime::kStoreContextSlot, 3);
-        }
+        __ mov(r1, Operand(slot->var()->name()));
+        __ mov(r0, Operand(Smi::FromInt(strict_mode_flag())));
+        __ Push(cp, r1, r0);  // Context, name, strict mode.
+        __ CallRuntime(Runtime::kStoreContextSlot, 4);
         break;
     }
-    __ bind(&done);
   }
 }
 
@@ -1774,7 +1983,9 @@
     __ pop(r1);
   }
 
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      is_strict() ? Builtins::StoreIC_Initialize_Strict
+                  : Builtins::StoreIC_Initialize));
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -1818,7 +2029,9 @@
     __ pop(r2);
   }
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                  : Builtins::KeyedStoreIC_Initialize));
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -1933,6 +2146,29 @@
 }
 
 
+void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
+                                                      int arg_count) {
+  // Push copy of the first argument or undefined if it doesn't exist.
+  if (arg_count > 0) {
+    __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
+  } else {
+    __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
+  }
+  __ push(r1);
+
+  // Push the receiver of the enclosing function and do runtime call.
+  __ ldr(r1, MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize));
+  __ push(r1);
+  // Push the strict mode flag.
+  __ mov(r1, Operand(Smi::FromInt(strict_mode_flag())));
+  __ push(r1);
+
+  __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
+                 ? Runtime::kResolvePossiblyDirectEvalNoLookup
+                 : Runtime::kResolvePossiblyDirectEval, 4);
+}
+
+
 void FullCodeGenerator::VisitCall(Call* expr) {
 #ifdef DEBUG
   // We want to verify that RecordJSReturnSite gets called on all paths
@@ -1962,26 +2198,31 @@
         VisitForStackValue(args->at(i));
       }
 
-      // Push copy of the function - found below the arguments.
-      __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
-      __ push(r1);
-
-      // Push copy of the first argument or undefined if it doesn't exist.
-      if (arg_count > 0) {
-        __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
-        __ push(r1);
-      } else {
-        __ push(r2);
+      // If we know that eval can only be shadowed by eval-introduced
+      // variables we attempt to load the global eval function directly
+      // in generated code. If we succeed, there is no need to perform a
+      // context lookup in the runtime system.
+      Label done;
+      if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
+        Label slow;
+        EmitLoadGlobalSlotCheckExtensions(var->AsSlot(),
+                                          NOT_INSIDE_TYPEOF,
+                                          &slow);
+        // Push the function and resolve eval.
+        __ push(r0);
+        EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count);
+        __ jmp(&done);
+        __ bind(&slow);
       }
 
-      // Push the receiver of the enclosing function and do runtime call.
-      __ ldr(r1,
-             MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize));
+      // Push copy of the function (found below the arguments) and
+      // resolve eval.
+      __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
       __ push(r1);
-      // Push the strict mode flag.
-      __ mov(r1, Operand(Smi::FromInt(strict_mode_flag())));
-      __ push(r1);
-      __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
+      EmitResolvePossiblyDirectEval(PERFORM_CONTEXT_LOOKUP, arg_count);
+      if (done.is_linked()) {
+        __ bind(&done);
+      }
 
       // The runtime call returns a pair of values in r0 (function) and
       // r1 (receiver). Touch up the stack with the right values.
@@ -2796,19 +3037,34 @@
 
 
 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
-  // Load the argument on the stack and call the runtime.
+  // Load the argument on the stack and call the stub.
+  TranscendentalCacheStub stub(TranscendentalCache::SIN,
+                               TranscendentalCacheStub::TAGGED);
   ASSERT(args->length() == 1);
   VisitForStackValue(args->at(0));
-  __ CallRuntime(Runtime::kMath_sin, 1);
+  __ CallStub(&stub);
   context()->Plug(r0);
 }
 
 
 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
-  // Load the argument on the stack and call the runtime.
+  // Load the argument on the stack and call the stub.
+  TranscendentalCacheStub stub(TranscendentalCache::COS,
+                               TranscendentalCacheStub::TAGGED);
   ASSERT(args->length() == 1);
   VisitForStackValue(args->at(0));
-  __ CallRuntime(Runtime::kMath_cos, 1);
+  __ CallStub(&stub);
+  context()->Plug(r0);
+}
+
+
+void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
+  // Load the argument on the stack and call the stub.
+  TranscendentalCacheStub stub(TranscendentalCache::LOG,
+                               TranscendentalCacheStub::TAGGED);
+  ASSERT(args->length() == 1);
+  VisitForStackValue(args->at(0));
+  __ CallStub(&stub);
   context()->Plug(r0);
 }
 
@@ -2822,15 +3078,6 @@
 }
 
 
-void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
-  // Load the argument on the stack and call the runtime function.
-  ASSERT(args->length() == 1);
-  VisitForStackValue(args->at(0));
-  __ CallRuntime(Runtime::kMath_log, 1);
-  context()->Plug(r0);
-}
-
-
 void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
   ASSERT(args->length() >= 2);
 
@@ -2866,7 +3113,79 @@
   VisitForStackValue(args->at(0));
   VisitForStackValue(args->at(1));
   VisitForStackValue(args->at(2));
+  Label done;
+  Label slow_case;
+  Register object = r0;
+  Register index1 = r1;
+  Register index2 = r2;
+  Register elements = r3;
+  Register scratch1 = r4;
+  Register scratch2 = r5;
+
+  __ ldr(object, MemOperand(sp, 2 * kPointerSize));
+  // Fetch the map and check if array is in fast case.
+  // Check that object doesn't require security checks and
+  // has no indexed interceptor.
+  __ CompareObjectType(object, scratch1, scratch2, FIRST_JS_OBJECT_TYPE);
+  __ b(lt, &slow_case);
+  // Map is now in scratch1.
+
+  __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset));
+  __ tst(scratch2, Operand(KeyedLoadIC::kSlowCaseBitFieldMask));
+  __ b(ne, &slow_case);
+
+  // Check the object's elements are in fast case and writable.
+  __ ldr(elements, FieldMemOperand(object, JSObject::kElementsOffset));
+  __ ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset));
+  __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
+  __ cmp(scratch1, ip);
+  __ b(ne, &slow_case);
+
+  // Check that both indices are smis.
+  __ ldr(index1, MemOperand(sp, 1 * kPointerSize));
+  __ ldr(index2, MemOperand(sp, 0));
+  __ JumpIfNotBothSmi(index1, index2, &slow_case);
+
+  // Check that both indices are valid.
+  __ ldr(scratch1, FieldMemOperand(object, JSArray::kLengthOffset));
+  __ cmp(scratch1, index1);
+  __ cmp(scratch1, index2, hi);
+  __ b(ls, &slow_case);
+
+  // Bring the address of the elements into index1 and index2.
+  __ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ add(index1,
+         scratch1,
+         Operand(index1, LSL, kPointerSizeLog2 - kSmiTagSize));
+  __ add(index2,
+         scratch1,
+         Operand(index2, LSL, kPointerSizeLog2 - kSmiTagSize));
+
+  // Swap elements.
+  __ ldr(scratch1, MemOperand(index1, 0));
+  __ ldr(scratch2, MemOperand(index2, 0));
+  __ str(scratch1, MemOperand(index2, 0));
+  __ str(scratch2, MemOperand(index1, 0));
+
+  Label new_space;
+  __ InNewSpace(elements, scratch1, eq, &new_space);
+  // Possible optimization: do a check that both values are Smis
+  // (or them and test against Smi mask.)
+
+  __ mov(scratch1, elements);
+  __ RecordWriteHelper(elements, index1, scratch2);
+  __ RecordWriteHelper(scratch1, index2, scratch2);  // scratch1 holds elements.
+
+  __ bind(&new_space);
+  // We are done. Drop elements from the stack, and return undefined.
+  __ Drop(3);
+  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
+  __ jmp(&done);
+
+  __ bind(&slow_case);
   __ CallRuntime(Runtime::kSwapElements, 3);
+
+  __ bind(&done);
   context()->Plug(r0);
 }
 
@@ -2985,16 +3304,248 @@
 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
   ASSERT(args->length() == 1);
   VisitForAccumulatorValue(args->at(0));
+
+  if (FLAG_debug_code) {
+    __ AbortIfNotString(r0);
+  }
+
   __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
   __ IndexFromHash(r0, r0);
+
   context()->Plug(r0);
 }
 
 
 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
+  Label bailout, done, one_char_separator, long_separator,
+      non_trivial_array, not_size_one_array, loop,
+      empty_separator_loop, one_char_separator_loop,
+      one_char_separator_loop_entry, long_separator_loop;
+
+  ASSERT(args->length() == 2);
+  VisitForStackValue(args->at(1));
+  VisitForAccumulatorValue(args->at(0));
+
+  // All aliases of the same register have disjoint lifetimes.
+  Register array = r0;
+  Register elements = no_reg;  // Will be r0.
+  Register result = no_reg;  // Will be r0.
+  Register separator = r1;
+  Register array_length = r2;
+  Register result_pos = no_reg;  // Will be r2
+  Register string_length = r3;
+  Register string = r4;
+  Register element = r5;
+  Register elements_end = r6;
+  Register scratch1 = r7;
+  Register scratch2 = r9;
+
+  // Separator operand is on the stack.
+  __ pop(separator);
+
+  // Check that the array is a JSArray.
+  __ JumpIfSmi(array, &bailout);
+  __ CompareObjectType(array, scratch1, scratch2, JS_ARRAY_TYPE);
+  __ b(ne, &bailout);
+
+  // Check that the array has fast elements.
+  __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitField2Offset));
+  __ tst(scratch2, Operand(1 << Map::kHasFastElements));
+  __ b(eq, &bailout);
+
+  // If the array has length zero, return the empty string.
+  __ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
+  __ SmiUntag(array_length, SetCC);
+  __ b(ne, &non_trivial_array);
+  __ LoadRoot(r0, Heap::kEmptyStringRootIndex);
+  __ b(&done);
+
+  __ bind(&non_trivial_array);
+
+  // Get the FixedArray containing array's elements.
+  elements = array;
+  __ ldr(elements, FieldMemOperand(array, JSArray::kElementsOffset));
+  array = no_reg;  // End of array's live range.
+
+  // Check that all array elements are sequential ASCII strings, and
+  // accumulate the sum of their lengths, as a smi-encoded value.
+  __ mov(string_length, Operand(0));
+  __ add(element,
+         elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2));
+  // Loop condition: while (element < elements_end).
+  // Live values in registers:
+  //   elements: Fixed array of strings.
+  //   array_length: Length of the fixed array of strings (not smi)
+  //   separator: Separator string
+  //   string_length: Accumulated sum of string lengths (smi).
+  //   element: Current array element.
+  //   elements_end: Array end.
+  if (FLAG_debug_code) {
+    __ cmp(array_length, Operand(0));
+    __ Assert(gt, "No empty arrays here in EmitFastAsciiArrayJoin");
+  }
+  __ bind(&loop);
+  __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
+  __ JumpIfSmi(string, &bailout);
+  __ ldr(scratch1, FieldMemOperand(string, HeapObject::kMapOffset));
+  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
+  __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
+  __ ldr(scratch1, FieldMemOperand(string, SeqAsciiString::kLengthOffset));
+  __ add(string_length, string_length, Operand(scratch1));
+  __ b(vs, &bailout);
+  __ cmp(element, elements_end);
+  __ b(lt, &loop);
+
+  // If array_length is 1, return elements[0], a string.
+  __ cmp(array_length, Operand(1));
+  __ b(ne, &not_size_one_array);
+  __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize));
+  __ b(&done);
+
+  __ bind(&not_size_one_array);
+
+  // Live values in registers:
+  //   separator: Separator string
+  //   array_length: Length of the array.
+  //   string_length: Sum of string lengths (smi).
+  //   elements: FixedArray of strings.
+
+  // Check that the separator is a flat ASCII string.
+  __ JumpIfSmi(separator, &bailout);
+  __ ldr(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset));
+  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
+  __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
+
+  // Add (separator length times array_length) - separator length to the
+  // string_length to get the length of the result string. array_length is not
+  // smi but the other values are, so the result is a smi
+  __ ldr(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset));
+  __ sub(string_length, string_length, Operand(scratch1));
+  __ smull(scratch2, ip, array_length, scratch1);
+  // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are
+  // zero.
+  __ cmp(ip, Operand(0));
+  __ b(ne, &bailout);
+  __ tst(scratch2, Operand(0x80000000));
+  __ b(ne, &bailout);
+  __ add(string_length, string_length, Operand(scratch2));
+  __ b(vs, &bailout);
+  __ SmiUntag(string_length);
+
+  // Get first element in the array to free up the elements register to be used
+  // for the result.
+  __ add(element,
+         elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  result = elements;  // End of live range for elements.
+  elements = no_reg;
+  // Live values in registers:
+  //   element: First array element
+  //   separator: Separator string
+  //   string_length: Length of result string (not smi)
+  //   array_length: Length of the array.
+  __ AllocateAsciiString(result,
+                         string_length,
+                         scratch1,
+                         scratch2,
+                         elements_end,
+                         &bailout);
+  // Prepare for looping. Set up elements_end to end of the array. Set
+  // result_pos to the position of the result where to write the first
+  // character.
+  __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2));
+  result_pos = array_length;  // End of live range for array_length.
+  array_length = no_reg;
+  __ add(result_pos,
+         result,
+         Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+
+  // Check the length of the separator.
+  __ ldr(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset));
+  __ cmp(scratch1, Operand(Smi::FromInt(1)));
+  __ b(eq, &one_char_separator);
+  __ b(gt, &long_separator);
+
+  // Empty separator case
+  __ bind(&empty_separator_loop);
+  // Live values in registers:
+  //   result_pos: the position to which we are currently copying characters.
+  //   element: Current array element.
+  //   elements_end: Array end.
+
+  // Copy next array element to the result.
+  __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
+  __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
+  __ SmiUntag(string_length);
+  __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+  __ CopyBytes(string, result_pos, string_length, scratch1);
+  __ cmp(element, elements_end);
+  __ b(lt, &empty_separator_loop);  // End while (element < elements_end).
+  ASSERT(result.is(r0));
+  __ b(&done);
+
+  // One-character separator case
+  __ bind(&one_char_separator);
+  // Replace separator with its ascii character value.
+  __ ldrb(separator, FieldMemOperand(separator, SeqAsciiString::kHeaderSize));
+  // Jump into the loop after the code that copies the separator, so the first
+  // element is not preceded by a separator
+  __ jmp(&one_char_separator_loop_entry);
+
+  __ bind(&one_char_separator_loop);
+  // Live values in registers:
+  //   result_pos: the position to which we are currently copying characters.
+  //   element: Current array element.
+  //   elements_end: Array end.
+  //   separator: Single separator ascii char (in lower byte).
+
+  // Copy the separator character to the result.
+  __ strb(separator, MemOperand(result_pos, 1, PostIndex));
+
+  // Copy next array element to the result.
+  __ bind(&one_char_separator_loop_entry);
+  __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
+  __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
+  __ SmiUntag(string_length);
+  __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+  __ CopyBytes(string, result_pos, string_length, scratch1);
+  __ cmp(element, elements_end);
+  __ b(lt, &one_char_separator_loop);  // End while (element < elements_end).
+  ASSERT(result.is(r0));
+  __ b(&done);
+
+  // Long separator case (separator is more than one character). Entry is at the
+  // label long_separator below.
+  __ bind(&long_separator_loop);
+  // Live values in registers:
+  //   result_pos: the position to which we are currently copying characters.
+  //   element: Current array element.
+  //   elements_end: Array end.
+  //   separator: Separator string.
+
+  // Copy the separator to the result.
+  __ ldr(string_length, FieldMemOperand(separator, String::kLengthOffset));
+  __ SmiUntag(string_length);
+  __ add(string,
+         separator,
+         Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+  __ CopyBytes(string, result_pos, string_length, scratch1);
+
+  __ bind(&long_separator);
+  __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
+  __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
+  __ SmiUntag(string_length);
+  __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+  __ CopyBytes(string, result_pos, string_length, scratch1);
+  __ cmp(element, elements_end);
+  __ b(lt, &long_separator_loop);  // End while (element < elements_end).
+  ASSERT(result.is(r0));
+  __ b(&done);
+
+  __ bind(&bailout);
   __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
+  __ bind(&done);
   context()->Plug(r0);
-  return;
 }
 
 
@@ -3043,19 +3594,8 @@
       Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
       Property* prop = expr->expression()->AsProperty();
       Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
-      if (prop == NULL && var == NULL) {
-        // Result of deleting non-property, non-variable reference is true.
-        // The subexpression may have side effects.
-        VisitForEffect(expr->expression());
-        context()->Plug(true);
-      } else if (var != NULL &&
-                 !var->is_global() &&
-                 var->AsSlot() != NULL &&
-                 var->AsSlot()->type() != Slot::LOOKUP) {
-        // Result of deleting non-global, non-dynamic variables is false.
-        // The subexpression does not have side effects.
-        context()->Plug(false);
-      } else if (prop != NULL) {
+
+      if (prop != NULL) {
         if (prop->is_synthetic()) {
           // Result of deleting parameters is false, even when they rewrite
           // to accesses on the arguments object.
@@ -3063,23 +3603,41 @@
         } else {
           VisitForStackValue(prop->obj());
           VisitForStackValue(prop->key());
+          __ mov(r1, Operand(Smi::FromInt(strict_mode_flag())));
+          __ push(r1);
           __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
           context()->Plug(r0);
         }
-      } else if (var->is_global()) {
-        __ ldr(r1, GlobalObjectOperand());
-        __ mov(r0, Operand(var->name()));
-        __ Push(r1, r0);
-        __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
-        context()->Plug(r0);
+      } else if (var != NULL) {
+        // Delete of an unqualified identifier is disallowed in strict mode
+        // but "delete this" is.
+        ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
+        if (var->is_global()) {
+          __ ldr(r2, GlobalObjectOperand());
+          __ mov(r1, Operand(var->name()));
+          __ mov(r0, Operand(Smi::FromInt(kNonStrictMode)));
+          __ Push(r2, r1, r0);
+          __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
+          context()->Plug(r0);
+        } else if (var->AsSlot() != NULL &&
+                   var->AsSlot()->type() != Slot::LOOKUP) {
+          // Result of deleting non-global, non-dynamic variables is false.
+          // The subexpression does not have side effects.
+          context()->Plug(false);
+        } else {
+          // Non-global variable.  Call the runtime to try to delete from the
+          // context where the variable was introduced.
+          __ push(context_register());
+          __ mov(r2, Operand(var->name()));
+          __ push(r2);
+          __ CallRuntime(Runtime::kDeleteContextSlot, 2);
+          context()->Plug(r0);
+        }
       } else {
-        // Non-global variable.  Call the runtime to try to delete from the
-        // context where the variable was introduced.
-        __ push(context_register());
-        __ mov(r2, Operand(var->name()));
-        __ push(r2);
-        __ CallRuntime(Runtime::kDeleteContextSlot, 2);
-        context()->Plug(r0);
+        // Result of deleting non-property, non-variable reference is true.
+        // The subexpression may have side effects.
+        VisitForEffect(expr->expression());
+        context()->Plug(true);
       }
       break;
     }
@@ -3093,17 +3651,23 @@
 
     case Token::NOT: {
       Comment cmnt(masm_, "[ UnaryOperation (NOT)");
-      Label materialize_true, materialize_false;
-      Label* if_true = NULL;
-      Label* if_false = NULL;
-      Label* fall_through = NULL;
+      if (context()->IsEffect()) {
+        // Unary NOT has no side effects so it's only necessary to visit the
+        // subexpression.  Match the optimizing compiler by not branching.
+        VisitForEffect(expr->expression());
+      } else {
+        Label materialize_true, materialize_false;
+        Label* if_true = NULL;
+        Label* if_false = NULL;
+        Label* fall_through = NULL;
 
-      // Notice that the labels are swapped.
-      context()->PrepareTest(&materialize_true, &materialize_false,
-                             &if_false, &if_true, &fall_through);
-      if (context()->IsTest()) ForwardBailoutToChild(expr);
-      VisitForControl(expr->expression(), if_true, if_false, fall_through);
-      context()->Plug(if_false, if_true);  // Labels swapped.
+        // Notice that the labels are swapped.
+        context()->PrepareTest(&materialize_true, &materialize_false,
+                               &if_false, &if_true, &fall_through);
+        if (context()->IsTest()) ForwardBailoutToChild(expr);
+        VisitForControl(expr->expression(), if_true, if_false, fall_through);
+        context()->Plug(if_false, if_true);  // Labels swapped.
+      }
       break;
     }
 
@@ -3135,9 +3699,7 @@
       bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
       UnaryOverwriteMode overwrite =
           can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
-      GenericUnaryOpStub stub(Token::SUB,
-                              overwrite,
-                              NO_UNARY_FLAGS);
+      GenericUnaryOpStub stub(Token::SUB, overwrite, NO_UNARY_FLAGS);
       // GenericUnaryOpStub expects the argument to be in the
       // accumulator register r0.
       VisitForAccumulatorValue(expr->expression());
@@ -3270,13 +3832,16 @@
 
   // Inline smi case if we are in a loop.
   Label stub_call, done;
+  JumpPatchSite patch_site(masm_);
+
   int count_value = expr->op() == Token::INC ? 1 : -1;
   if (ShouldInlineSmiCase(expr->op())) {
     __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC);
     __ b(vs, &stub_call);
     // We could eliminate this smi check if we split the code at
     // the first smi check before calling ToNumber.
-    __ JumpIfSmi(r0, &done);
+    patch_site.EmitJumpIfSmi(r0, &done);
+
     __ bind(&stub_call);
     // Call stub. Undo operation first.
     __ sub(r0, r0, Operand(Smi::FromInt(count_value)));
@@ -3286,8 +3851,8 @@
   // Record position before stub call.
   SetSourcePosition(expr->position());
 
-  GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0);
-  __ CallStub(&stub);
+  TypeRecordingBinaryOpStub stub(Token::ADD, NO_OVERWRITE);
+  EmitCallIC(stub.GetCode(), &patch_site);
   __ bind(&done);
 
   // Store the value returned in r0.
@@ -3315,7 +3880,9 @@
     case NAMED_PROPERTY: {
       __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
       __ pop(r1);
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::StoreIC_Initialize_Strict
+                      : Builtins::StoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -3330,7 +3897,9 @@
     case KEYED_PROPERTY: {
       __ pop(r1);  // Key.
       __ pop(r2);  // Receiver.
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                      : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -3408,71 +3977,52 @@
   PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
 
   if (check->Equals(Heap::number_symbol())) {
-    __ tst(r0, Operand(kSmiTagMask));
-    __ b(eq, if_true);
+    __ JumpIfSmi(r0, if_true);
     __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
     __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
     __ cmp(r0, ip);
     Split(eq, if_true, if_false, fall_through);
   } else if (check->Equals(Heap::string_symbol())) {
-    __ tst(r0, Operand(kSmiTagMask));
-    __ b(eq, if_false);
+    __ JumpIfSmi(r0, if_false);
     // Check for undetectable objects => false.
-    __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
+    __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE);
+    __ b(ge, if_false);
     __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
-    __ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
-    __ cmp(r1, Operand(1 << Map::kIsUndetectable));
-    __ b(eq, if_false);
-    __ ldrb(r1, FieldMemOperand(r0, Map::kInstanceTypeOffset));
-    __ cmp(r1, Operand(FIRST_NONSTRING_TYPE));
-    Split(lt, if_true, if_false, fall_through);
+    __ tst(r1, Operand(1 << Map::kIsUndetectable));
+    Split(eq, if_true, if_false, fall_through);
   } else if (check->Equals(Heap::boolean_symbol())) {
-    __ LoadRoot(ip, Heap::kTrueValueRootIndex);
-    __ cmp(r0, ip);
+    __ CompareRoot(r0, Heap::kTrueValueRootIndex);
     __ b(eq, if_true);
-    __ LoadRoot(ip, Heap::kFalseValueRootIndex);
-    __ cmp(r0, ip);
+    __ CompareRoot(r0, Heap::kFalseValueRootIndex);
     Split(eq, if_true, if_false, fall_through);
   } else if (check->Equals(Heap::undefined_symbol())) {
-    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
-    __ cmp(r0, ip);
+    __ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
     __ b(eq, if_true);
-    __ tst(r0, Operand(kSmiTagMask));
-    __ b(eq, if_false);
+    __ JumpIfSmi(r0, if_false);
     // Check for undetectable objects => true.
     __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
     __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
-    __ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
-    __ cmp(r1, Operand(1 << Map::kIsUndetectable));
-    Split(eq, if_true, if_false, fall_through);
+    __ tst(r1, Operand(1 << Map::kIsUndetectable));
+    Split(ne, if_true, if_false, fall_through);
+
   } else if (check->Equals(Heap::function_symbol())) {
-    __ tst(r0, Operand(kSmiTagMask));
-    __ b(eq, if_false);
-    __ CompareObjectType(r0, r1, r0, JS_FUNCTION_TYPE);
-    __ b(eq, if_true);
-    // Regular expressions => 'function' (they are callable).
-    __ CompareInstanceType(r1, r0, JS_REGEXP_TYPE);
-    Split(eq, if_true, if_false, fall_through);
+    __ JumpIfSmi(r0, if_false);
+    __ CompareObjectType(r0, r1, r0, FIRST_FUNCTION_CLASS_TYPE);
+    Split(ge, if_true, if_false, fall_through);
+
   } else if (check->Equals(Heap::object_symbol())) {
-    __ tst(r0, Operand(kSmiTagMask));
-    __ b(eq, if_false);
-    __ LoadRoot(ip, Heap::kNullValueRootIndex);
-    __ cmp(r0, ip);
+    __ JumpIfSmi(r0, if_false);
+    __ CompareRoot(r0, Heap::kNullValueRootIndex);
     __ b(eq, if_true);
-    // Regular expressions => 'function', not 'object'.
-    __ CompareObjectType(r0, r1, r0, JS_REGEXP_TYPE);
-    __ b(eq, if_false);
-    // Check for undetectable objects => false.
-    __ ldrb(r0, FieldMemOperand(r1, Map::kBitFieldOffset));
-    __ and_(r0, r0, Operand(1 << Map::kIsUndetectable));
-    __ cmp(r0, Operand(1 << Map::kIsUndetectable));
-    __ b(eq, if_false);
     // Check for JS objects => true.
-    __ ldrb(r0, FieldMemOperand(r1, Map::kInstanceTypeOffset));
-    __ cmp(r0, Operand(FIRST_JS_OBJECT_TYPE));
-    __ b(lt, if_false);
-    __ cmp(r0, Operand(LAST_JS_OBJECT_TYPE));
-    Split(le, if_true, if_false, fall_through);
+    __ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE);
+    __ b(lo, if_false);
+    __ CompareInstanceType(r0, r1, FIRST_FUNCTION_CLASS_TYPE);
+    __ b(hs, if_false);
+    // Check for undetectable objects => false.
+    __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
+    __ tst(r1, Operand(1 << Map::kIsUndetectable));
+    Split(eq, if_true, if_false, fall_through);
   } else {
     if (if_false != fall_through) __ jmp(if_false);
   }
@@ -3644,11 +4194,43 @@
 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) {
   ASSERT(mode == RelocInfo::CODE_TARGET ||
          mode == RelocInfo::CODE_TARGET_CONTEXT);
+  switch (ic->kind()) {
+    case Code::LOAD_IC:
+      __ IncrementCounter(&Counters::named_load_full, 1, r1, r2);
+      break;
+    case Code::KEYED_LOAD_IC:
+      __ IncrementCounter(&Counters::keyed_load_full, 1, r1, r2);
+      break;
+    case Code::STORE_IC:
+      __ IncrementCounter(&Counters::named_store_full, 1, r1, r2);
+      break;
+    case Code::KEYED_STORE_IC:
+      __ IncrementCounter(&Counters::keyed_store_full, 1, r1, r2);
+    default:
+      break;
+  }
+
   __ Call(ic, mode);
 }
 
 
 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) {
+  switch (ic->kind()) {
+    case Code::LOAD_IC:
+      __ IncrementCounter(&Counters::named_load_full, 1, r1, r2);
+      break;
+    case Code::KEYED_LOAD_IC:
+      __ IncrementCounter(&Counters::keyed_load_full, 1, r1, r2);
+      break;
+    case Code::STORE_IC:
+      __ IncrementCounter(&Counters::named_store_full, 1, r1, r2);
+      break;
+    case Code::KEYED_STORE_IC:
+      __ IncrementCounter(&Counters::keyed_store_full, 1, r1, r2);
+    default:
+      break;
+  }
+
   __ Call(ic, RelocInfo::CODE_TARGET);
   if (patch_site != NULL && patch_site->is_bound()) {
     patch_site->EmitPatchInfo();
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index 8c76458..0fc6818 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -115,6 +115,9 @@
                                            Register name,
                                            Register scratch1,
                                            Register scratch2) {
+  // Assert that name contains a string.
+  if (FLAG_debug_code) __ AbortIfNotString(name);
+
   // Compute the capacity mask.
   const int kCapacityOffset = StringDictionary::kHeaderSize +
       StringDictionary::kCapacityIndex * kPointerSize;
@@ -843,7 +846,14 @@
   //  -- lr    : return address
   // -----------------------------------
 
+  // Check if the name is a string.
+  Label miss;
+  __ tst(r2, Operand(kSmiTagMask));
+  __ b(eq, &miss);
+  __ IsObjectJSStringType(r2, r0, &miss);
+
   GenerateCallNormal(masm, argc);
+  __ bind(&miss);
   GenerateMiss(masm, argc);
 }
 
@@ -1390,7 +1400,8 @@
 }
 
 
-void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
+                                              StrictModeFlag strict_mode) {
   // ---------- S t a t e --------------
   //  -- r0     : value
   //  -- r1     : key
@@ -1401,11 +1412,16 @@
   // Push receiver, key and value for runtime call.
   __ Push(r2, r1, r0);
 
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ mov(r1, Operand(Smi::FromInt(NONE)));          // PropertyAttributes
+  __ mov(r0, Operand(Smi::FromInt(strict_mode)));   // Strict mode.
+  __ Push(r1, r0);
+
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 }
 
 
-void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
+                                   StrictModeFlag strict_mode) {
   // ---------- S t a t e --------------
   //  -- r0     : value
   //  -- r1     : key
@@ -1460,29 +1476,25 @@
   // r0: value.
   // r1: key.
   // r2: receiver.
-  GenerateRuntimeSetProperty(masm);
+  GenerateRuntimeSetProperty(masm, strict_mode);
 
   // Check whether the elements is a pixel array.
   // r4: elements map.
   __ bind(&check_pixel_array);
-  __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
-  __ cmp(r4, ip);
-  __ b(ne, &slow);
-  // Check that the value is a smi. If a conversion is needed call into the
-  // runtime to convert and clamp.
-  __ JumpIfNotSmi(value, &slow);
-  __ mov(r4, Operand(key, ASR, kSmiTagSize));  // Untag the key.
-  __ ldr(ip, FieldMemOperand(elements, PixelArray::kLengthOffset));
-  __ cmp(r4, Operand(ip));
-  __ b(hs, &slow);
-  __ mov(r5, Operand(value, ASR, kSmiTagSize));  // Untag the value.
-  __ Usat(r5, 8, Operand(r5));  // Clamp the value to [0..255].
-
-  // Get the pointer to the external array. This clobbers elements.
-  __ ldr(elements,
-         FieldMemOperand(elements, PixelArray::kExternalPointerOffset));
-  __ strb(r5, MemOperand(elements, r4));  // Elements is now external array.
-  __ Ret();
+  GenerateFastPixelArrayStore(masm,
+                              r2,
+                              r1,
+                              r0,
+                              elements,
+                              r4,
+                              r5,
+                              r6,
+                              false,
+                              false,
+                              NULL,
+                              &slow,
+                              &slow,
+                              &slow);
 
   // Extra capacity case: Check if there is extra capacity to
   // perform the store and update the length. Used for adding one
@@ -1534,7 +1546,7 @@
 
 
 void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
-                                  Code::ExtraICState extra_ic_state) {
+                                  StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- r0    : value
   //  -- r1    : receiver
@@ -1546,7 +1558,7 @@
   Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
                                          NOT_IN_LOOP,
                                          MONOMORPHIC,
-                                         extra_ic_state);
+                                         strict_mode);
   StubCache::GenerateProbe(masm, flags, r1, r2, r3, r4, r5);
 
   // Cache miss: Jump to runtime.
@@ -1640,7 +1652,8 @@
 }
 
 
-void StoreIC::GenerateGlobalProxy(MacroAssembler* masm) {
+void StoreIC::GenerateGlobalProxy(MacroAssembler* masm,
+                                  StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- r0    : value
   //  -- r1    : receiver
@@ -1650,8 +1663,12 @@
 
   __ Push(r1, r2, r0);
 
+  __ mov(r1, Operand(Smi::FromInt(NONE)));  // PropertyAttributes
+  __ mov(r0, Operand(Smi::FromInt(strict_mode)));
+  __ Push(r1, r0);
+
   // Do tail-call to runtime routine.
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 }
 
 
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 82de5d3..e79465c 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -346,7 +346,7 @@
 }
 
 
-void LStoreNamed::PrintDataTo(StringStream* stream) {
+void LStoreNamedField::PrintDataTo(StringStream* stream) {
   object()->PrintTo(stream);
   stream->Add(".");
   stream->Add(*String::cast(*name())->ToCString());
@@ -355,7 +355,16 @@
 }
 
 
-void LStoreKeyed::PrintDataTo(StringStream* stream) {
+void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
+  object()->PrintTo(stream);
+  stream->Add(".");
+  stream->Add(*String::cast(*name())->ToCString());
+  stream->Add(" <- ");
+  value()->PrintTo(stream);
+}
+
+
+void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
   object()->PrintTo(stream);
   stream->Add("[");
   key()->PrintTo(stream);
@@ -364,8 +373,18 @@
 }
 
 
-LChunk::LChunk(HGraph* graph)
+void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
+  object()->PrintTo(stream);
+  stream->Add("[");
+  key()->PrintTo(stream);
+  stream->Add("] <- ");
+  value()->PrintTo(stream);
+}
+
+
+LChunk::LChunk(CompilationInfo* info, HGraph* graph)
     : spill_slot_count_(0),
+      info_(info),
       graph_(graph),
       instructions_(32),
       pointer_maps_(8),
@@ -456,7 +475,7 @@
   // shift all parameter indexes down by the number of parameters, and
   // make sure they end up negative so they are distinguishable from
   // spill slots.
-  int result = index - graph()->info()->scope()->num_parameters() - 1;
+  int result = index - info()->scope()->num_parameters() - 1;
   ASSERT(result < 0);
   return result;
 }
@@ -464,7 +483,7 @@
 // A parameter relative to ebp in the arguments stub.
 int LChunk::ParameterAt(int index) {
   ASSERT(-1 <= index);  // -1 is the receiver.
-  return (1 + graph()->info()->scope()->num_parameters() - index) *
+  return (1 + info()->scope()->num_parameters() - index) *
       kPointerSize;
 }
 
@@ -503,7 +522,7 @@
 
 LChunk* LChunkBuilder::Build() {
   ASSERT(is_unused());
-  chunk_ = new LChunk(graph());
+  chunk_ = new LChunk(info(), graph());
   HPhase phase("Building chunk", chunk_);
   status_ = BUILDING;
   const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
@@ -520,8 +539,8 @@
 
 void LChunkBuilder::Abort(const char* format, ...) {
   if (FLAG_trace_bailout) {
-    SmartPointer<char> debug_name = graph()->debug_name()->ToCString();
-    PrintF("Aborting LChunk building in @\"%s\": ", *debug_name);
+    SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
+    PrintF("Aborting LChunk building in @\"%s\": ", *name);
     va_list arguments;
     va_start(arguments, format);
     OS::VPrint(format, arguments);
@@ -855,6 +874,7 @@
   ASSERT(instr->representation().IsDouble());
   ASSERT(instr->left()->representation().IsDouble());
   ASSERT(instr->right()->representation().IsDouble());
+  ASSERT(op != Token::MOD);
   LOperand* left = UseRegisterAtStart(instr->left());
   LOperand* right = UseRegisterAtStart(instr->right());
   LArithmeticD* result = new LArithmeticD(op, left, right);
@@ -1136,8 +1156,7 @@
     HInstanceOfKnownGlobal* instr) {
   LInstanceOfKnownGlobal* result =
       new LInstanceOfKnownGlobal(UseFixed(instr->value(), r0), FixedTemp(r4));
-  MarkAsSaveDoubles(result);
-  return AssignEnvironment(AssignPointerMap(DefineFixed(result, r0)));
+  return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
 
@@ -1193,34 +1212,30 @@
 
 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
   BuiltinFunctionId op = instr->op();
-  LOperand* input = UseRegisterAtStart(instr->value());
-  LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
-  LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
-  switch (op) {
-    case kMathAbs:
-      return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
-    case kMathFloor:
-      return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
-    case kMathSqrt:
-      return DefineSameAsFirst(result);
-    case kMathRound:
-      Abort("MathRound LUnaryMathOperation not implemented");
-      return NULL;
-    case kMathPowHalf:
-      Abort("MathPowHalf LUnaryMathOperation not implemented");
-      return NULL;
-    case kMathLog:
-      Abort("MathLog LUnaryMathOperation not implemented");
-      return NULL;
-    case kMathCos:
-      Abort("MathCos LUnaryMathOperation not implemented");
-      return NULL;
-    case kMathSin:
-      Abort("MathSin LUnaryMathOperation not implemented");
-      return NULL;
-    default:
-      UNREACHABLE();
-      return NULL;
+  if (op == kMathLog || op == kMathSin || op == kMathCos) {
+    LOperand* input = UseFixedDouble(instr->value(), d2);
+    LUnaryMathOperation* result = new LUnaryMathOperation(input, NULL);
+    return MarkAsCall(DefineFixedDouble(result, d2), instr);
+  } else {
+    LOperand* input = UseRegisterAtStart(instr->value());
+    LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
+    LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
+    switch (op) {
+      case kMathAbs:
+        return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
+      case kMathFloor:
+        return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
+      case kMathSqrt:
+        return DefineSameAsFirst(result);
+      case kMathRound:
+        return AssignEnvironment(DefineAsRegister(result));
+      case kMathPowHalf:
+        Abort("MathPowHalf LUnaryMathOperation not implemented");
+        return NULL;
+      default:
+        UNREACHABLE();
+        return NULL;
+    }
   }
 }
 
@@ -1418,8 +1433,19 @@
 
 
 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
-  Abort("LPower instruction not implemented on ARM");
-  return NULL;
+  ASSERT(instr->representation().IsDouble());
+  // We call a C function for double power. It can't trigger a GC.
+  // We need to use fixed result register for the call.
+  Representation exponent_type = instr->right()->representation();
+  ASSERT(instr->left()->representation().IsDouble());
+  LOperand* left = UseFixedDouble(instr->left(), d1);
+  LOperand* right = exponent_type.IsDouble() ?
+      UseFixedDouble(instr->right(), d2) :
+      UseFixed(instr->right(), r0);
+  LPower* result = new LPower(left, right);
+  return MarkAsCall(DefineFixedDouble(result, d3),
+                    instr,
+                    CAN_DEOPTIMIZE_EAGERLY);
 }
 
 
@@ -1491,6 +1517,15 @@
 }
 
 
+LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
+    HGetCachedArrayIndex* instr)  {
+  ASSERT(instr->value()->representation().IsTagged());
+  LOperand* value = UseRegisterAtStart(instr->value());
+
+  return DefineAsRegister(new LGetCachedArrayIndex(value));
+}
+
+
 LInstruction* LChunkBuilder::DoHasCachedArrayIndex(
     HHasCachedArrayIndex* instr) {
   ASSERT(instr->value()->representation().IsTagged());
@@ -1700,11 +1735,13 @@
 
 
 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
-  LOperand* context = UseTempRegister(instr->context());
+  LOperand* context;
   LOperand* value;
   if (instr->NeedsWriteBarrier()) {
+    context = UseTempRegister(instr->context());
     value = UseTempRegister(instr->value());
   } else {
+    context = UseRegister(instr->context());
     value = UseRegister(instr->value());
   }
   return new LStoreContextSlot(context, value);
@@ -1797,6 +1834,13 @@
 }
 
 
+LInstruction* LChunkBuilder::DoStorePixelArrayElement(
+    HStorePixelArrayElement* instr) {
+  Abort("DoStorePixelArrayElement not implemented");
+  return NULL;
+}
+
+
 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
   LOperand* obj = UseFixed(instr->object(), r2);
   LOperand* key = UseFixed(instr->key(), r1);
@@ -1902,8 +1946,10 @@
 
 
 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
-  // There are no real uses of the arguments object (we bail out in all other
-  // cases).
+  // There are no real uses of the arguments object.
+  // arguments.length and element access are supported directly on
+  // stack arguments, and any real arguments object use causes a bailout.
+  // So this value is never used.
   return NULL;
 }
 
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 8d2573d..9cbcc3b 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -42,8 +42,6 @@
 #define LITHIUM_ALL_INSTRUCTION_LIST(V)         \
   V(ControlInstruction)                         \
   V(Call)                                       \
-  V(StoreKeyed)                                 \
-  V(StoreNamed)                                 \
   LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
 
 
@@ -94,6 +92,7 @@
   V(FixedArrayLength)                           \
   V(FunctionLiteral)                            \
   V(Gap)                                        \
+  V(GetCachedArrayIndex)                        \
   V(GlobalObject)                               \
   V(GlobalReceiver)                             \
   V(Goto)                                       \
@@ -134,6 +133,7 @@
   V(OuterContext)                               \
   V(Parameter)                                  \
   V(PixelArrayLength)                           \
+  V(Power)                                      \
   V(PushArgument)                               \
   V(RegExpLiteral)                              \
   V(Return)                                     \
@@ -728,6 +728,17 @@
 };
 
 
+class LGetCachedArrayIndex: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LGetCachedArrayIndex(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index")
+  DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex)
+};
+
+
 class LHasCachedArrayIndex: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LHasCachedArrayIndex(LOperand* value) {
@@ -1046,6 +1057,18 @@
 };
 
 
+class LPower: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LPower(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(Power, "power")
+  DECLARE_HYDROGEN_ACCESSOR(Power)
+};
+
+
 class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
  public:
   LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
@@ -1498,15 +1521,38 @@
 };
 
 
-class LStoreNamed: public LTemplateInstruction<0, 2, 0> {
+class LStoreNamedField: public LTemplateInstruction<0, 2, 0> {
  public:
-  LStoreNamed(LOperand* obj, LOperand* val) {
+  LStoreNamedField(LOperand* obj, LOperand* val) {
     inputs_[0] = obj;
     inputs_[1] = val;
   }
 
-  DECLARE_INSTRUCTION(StoreNamed)
-  DECLARE_HYDROGEN_ACCESSOR(StoreNamed)
+  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
+  DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  LOperand* object() { return inputs_[0]; }
+  LOperand* value() { return inputs_[1]; }
+
+  Handle<Object> name() const { return hydrogen()->name(); }
+  bool is_in_object() { return hydrogen()->is_in_object(); }
+  int offset() { return hydrogen()->offset(); }
+  bool needs_write_barrier() { return hydrogen()->NeedsWriteBarrier(); }
+  Handle<Map> transition() const { return hydrogen()->transition(); }
+};
+
+
+class LStoreNamedGeneric: public LTemplateInstruction<0, 2, 0> {
+ public:
+  LStoreNamedGeneric(LOperand* obj, LOperand* val) {
+    inputs_[0] = obj;
+    inputs_[1] = val;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
+  DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
 
   virtual void PrintDataTo(StringStream* stream);
 
@@ -1516,40 +1562,17 @@
 };
 
 
-class LStoreNamedField: public LStoreNamed {
+class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
  public:
-  LStoreNamedField(LOperand* obj, LOperand* val)
-      : LStoreNamed(obj, val) { }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
-  DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
-
-  bool is_in_object() { return hydrogen()->is_in_object(); }
-  int offset() { return hydrogen()->offset(); }
-  bool needs_write_barrier() { return hydrogen()->NeedsWriteBarrier(); }
-  Handle<Map> transition() const { return hydrogen()->transition(); }
-};
-
-
-class LStoreNamedGeneric: public LStoreNamed {
- public:
-  LStoreNamedGeneric(LOperand* obj, LOperand* val)
-      : LStoreNamed(obj, val) { }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
-  DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
-};
-
-
-class LStoreKeyed: public LTemplateInstruction<0, 3, 0> {
- public:
-  LStoreKeyed(LOperand* obj, LOperand* key, LOperand* val) {
+  LStoreKeyedFastElement(LOperand* obj, LOperand* key, LOperand* val) {
     inputs_[0] = obj;
     inputs_[1] = key;
     inputs_[2] = val;
   }
 
-  DECLARE_INSTRUCTION(StoreKeyed)
+  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
+                               "store-keyed-fast-element")
+  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastElement)
 
   virtual void PrintDataTo(StringStream* stream);
 
@@ -1559,23 +1582,21 @@
 };
 
 
-class LStoreKeyedFastElement: public LStoreKeyed {
+class LStoreKeyedGeneric: public LTemplateInstruction<0, 3, 0> {
  public:
-  LStoreKeyedFastElement(LOperand* obj, LOperand* key, LOperand* val)
-      : LStoreKeyed(obj, key, val) {}
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
-                               "store-keyed-fast-element")
-  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastElement)
-};
-
-
-class LStoreKeyedGeneric: public LStoreKeyed {
- public:
-  LStoreKeyedGeneric(LOperand* obj, LOperand* key, LOperand* val)
-      : LStoreKeyed(obj, key, val) { }
+  LStoreKeyedGeneric(LOperand* obj, LOperand* key, LOperand* val) {
+    inputs_[0] = obj;
+    inputs_[1] = key;
+    inputs_[2] = val;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  LOperand* object() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
+  LOperand* value() { return inputs_[2]; }
 };
 
 
@@ -1808,7 +1829,7 @@
 class LChunkBuilder;
 class LChunk: public ZoneObject {
  public:
-  explicit LChunk(HGraph* graph);
+  explicit LChunk(CompilationInfo* info, HGraph* graph);
 
   void AddInstruction(LInstruction* instruction, HBasicBlock* block);
   LConstantOperand* DefineConstantOperand(HConstant* constant);
@@ -1821,6 +1842,7 @@
   int ParameterAt(int index);
   int GetParameterStackSlot(int index) const;
   int spill_slot_count() const { return spill_slot_count_; }
+  CompilationInfo* info() const { return info_; }
   HGraph* graph() const { return graph_; }
   const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
   void AddGapMove(int index, LOperand* from, LOperand* to);
@@ -1857,6 +1879,7 @@
 
  private:
   int spill_slot_count_;
+  CompilationInfo* info_;
   HGraph* const graph_;
   ZoneList<LInstruction*> instructions_;
   ZoneList<LPointerMap*> pointer_maps_;
@@ -1866,8 +1889,9 @@
 
 class LChunkBuilder BASE_EMBEDDED {
  public:
-  LChunkBuilder(HGraph* graph, LAllocator* allocator)
+  LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator)
       : chunk_(NULL),
+        info_(info),
         graph_(graph),
         status_(UNUSED),
         current_instruction_(NULL),
@@ -1896,6 +1920,7 @@
   };
 
   LChunk* chunk() const { return chunk_; }
+  CompilationInfo* info() const { return info_; }
   HGraph* graph() const { return graph_; }
 
   bool is_unused() const { return status_ == UNUSED; }
@@ -2002,6 +2027,7 @@
                               HArithmeticBinaryOperation* instr);
 
   LChunk* chunk_;
+  CompilationInfo* info_;
   HGraph* const graph_;
   Status status_;
   HInstruction* current_instruction_;
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 057ac24..afe9015 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -26,6 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "arm/lithium-codegen-arm.h"
+#include "arm/lithium-gap-resolver-arm.h"
 #include "code-stubs.h"
 #include "stub-cache.h"
 
@@ -54,157 +55,6 @@
 };
 
 
-class LGapNode: public ZoneObject {
- public:
-  explicit LGapNode(LOperand* operand)
-      : operand_(operand), resolved_(false), visited_id_(-1) { }
-
-  LOperand* operand() const { return operand_; }
-  bool IsResolved() const { return !IsAssigned() || resolved_; }
-  void MarkResolved() {
-    ASSERT(!IsResolved());
-    resolved_ = true;
-  }
-  int visited_id() const { return visited_id_; }
-  void set_visited_id(int id) {
-    ASSERT(id > visited_id_);
-    visited_id_ = id;
-  }
-
-  bool IsAssigned() const { return assigned_from_.is_set(); }
-  LGapNode* assigned_from() const { return assigned_from_.get(); }
-  void set_assigned_from(LGapNode* n) { assigned_from_.set(n); }
-
- private:
-  LOperand* operand_;
-  SetOncePointer<LGapNode> assigned_from_;
-  bool resolved_;
-  int visited_id_;
-};
-
-
-LGapResolver::LGapResolver()
-    : nodes_(32),
-      identified_cycles_(4),
-      result_(16),
-      next_visited_id_(0) {
-}
-
-
-const ZoneList<LMoveOperands>* LGapResolver::Resolve(
-    const ZoneList<LMoveOperands>* moves,
-    LOperand* marker_operand) {
-  nodes_.Rewind(0);
-  identified_cycles_.Rewind(0);
-  result_.Rewind(0);
-  next_visited_id_ = 0;
-
-  for (int i = 0; i < moves->length(); ++i) {
-    LMoveOperands move = moves->at(i);
-    if (!move.IsRedundant()) RegisterMove(move);
-  }
-
-  for (int i = 0; i < identified_cycles_.length(); ++i) {
-    ResolveCycle(identified_cycles_[i], marker_operand);
-  }
-
-  int unresolved_nodes;
-  do {
-    unresolved_nodes = 0;
-    for (int j = 0; j < nodes_.length(); j++) {
-      LGapNode* node = nodes_[j];
-      if (!node->IsResolved() && node->assigned_from()->IsResolved()) {
-        AddResultMove(node->assigned_from(), node);
-        node->MarkResolved();
-      }
-      if (!node->IsResolved()) ++unresolved_nodes;
-    }
-  } while (unresolved_nodes > 0);
-  return &result_;
-}
-
-
-void LGapResolver::AddResultMove(LGapNode* from, LGapNode* to) {
-  AddResultMove(from->operand(), to->operand());
-}
-
-
-void LGapResolver::AddResultMove(LOperand* from, LOperand* to) {
-  result_.Add(LMoveOperands(from, to));
-}
-
-
-void LGapResolver::ResolveCycle(LGapNode* start, LOperand* marker_operand) {
-  ZoneList<LOperand*> cycle_operands(8);
-  cycle_operands.Add(marker_operand);
-  LGapNode* cur = start;
-  do {
-    cur->MarkResolved();
-    cycle_operands.Add(cur->operand());
-    cur = cur->assigned_from();
-  } while (cur != start);
-  cycle_operands.Add(marker_operand);
-
-  for (int i = cycle_operands.length() - 1; i > 0; --i) {
-    LOperand* from = cycle_operands[i];
-    LOperand* to = cycle_operands[i - 1];
-    AddResultMove(from, to);
-  }
-}
-
-
-bool LGapResolver::CanReach(LGapNode* a, LGapNode* b, int visited_id) {
-  ASSERT(a != b);
-  LGapNode* cur = a;
-  while (cur != b && cur->visited_id() != visited_id && cur->IsAssigned()) {
-    cur->set_visited_id(visited_id);
-    cur = cur->assigned_from();
-  }
-
-  return cur == b;
-}
-
-
-bool LGapResolver::CanReach(LGapNode* a, LGapNode* b) {
-  ASSERT(a != b);
-  return CanReach(a, b, next_visited_id_++);
-}
-
-
-void LGapResolver::RegisterMove(LMoveOperands move) {
-  if (move.source()->IsConstantOperand()) {
-    // Constant moves should be last in the machine code. Therefore add them
-    // first to the result set.
-    AddResultMove(move.source(), move.destination());
-  } else {
-    LGapNode* from = LookupNode(move.source());
-    LGapNode* to = LookupNode(move.destination());
-    if (to->IsAssigned() && to->assigned_from() == from) {
-      move.Eliminate();
-      return;
-    }
-    ASSERT(!to->IsAssigned());
-    if (CanReach(from, to)) {
-      // This introduces a cycle. Save.
-      identified_cycles_.Add(from);
-    }
-    to->set_assigned_from(from);
-  }
-}
-
-
-LGapNode* LGapResolver::LookupNode(LOperand* operand) {
-  for (int i = 0; i < nodes_.length(); ++i) {
-    if (nodes_[i]->operand()->Equals(operand)) return nodes_[i];
-  }
-
-  // No node found => create a new one.
-  LGapNode* result = new LGapNode(operand);
-  nodes_.Add(result);
-  return result;
-}
-
-
 #define __ masm()->
 
 bool LCodeGen::GenerateCode() {
@@ -230,8 +80,8 @@
 
 void LCodeGen::Abort(const char* format, ...) {
   if (FLAG_trace_bailout) {
-    SmartPointer<char> debug_name = graph()->debug_name()->ToCString();
-    PrintF("Aborting LCodeGen in @\"%s\": ", *debug_name);
+    SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
+    PrintF("Aborting LCodeGen in @\"%s\": ", *name);
     va_list arguments;
     va_start(arguments, format);
     OS::VPrint(format, arguments);
@@ -294,6 +144,44 @@
     }
   }
 
+  // Possibly allocate a local context.
+  int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+  if (heap_slots > 0) {
+    Comment(";;; Allocate local context");
+    // Argument to NewContext is the function, which is in r1.
+    __ push(r1);
+    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+      FastNewContextStub stub(heap_slots);
+      __ CallStub(&stub);
+    } else {
+      __ CallRuntime(Runtime::kNewContext, 1);
+    }
+    RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
+    // Context is returned in both r0 and cp.  It replaces the context
+    // passed to us.  It's saved in the stack and kept live in cp.
+    __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+    // Copy any necessary parameters into the context.
+    int num_parameters = scope()->num_parameters();
+    for (int i = 0; i < num_parameters; i++) {
+      Slot* slot = scope()->parameter(i)->AsSlot();
+      if (slot != NULL && slot->type() == Slot::CONTEXT) {
+        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
+            (num_parameters - 1 - i) * kPointerSize;
+        // Load parameter from stack.
+        __ ldr(r0, MemOperand(fp, parameter_offset));
+        // Store it in the context.
+        __ mov(r1, Operand(Context::SlotOffset(slot->index())));
+        __ str(r0, MemOperand(cp, r1));
+        // Update the write barrier. This clobbers all involved
+        // registers, so we have to use two more registers to avoid
+        // clobbering cp.
+        __ mov(r2, Operand(cp));
+        __ RecordWrite(r2, Operand(r1), r3, r0);
+      }
+    }
+    Comment(";;; End allocate local context");
+  }
+
   // Trace the call.
   if (FLAG_trace) {
     __ CallRuntime(Runtime::kTraceEnter, 0);
@@ -464,7 +352,6 @@
 
 
 MemOperand LCodeGen::ToMemOperand(LOperand* op) const {
-  // TODO(regis): Revisit.
   ASSERT(!op->IsRegister());
   ASSERT(!op->IsDoubleRegister());
   ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
@@ -480,6 +367,21 @@
 }
 
 
+MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const {
+  ASSERT(op->IsDoubleStackSlot());
+  int index = op->index();
+  if (index >= 0) {
+    // Local or spill slot. Skip the frame pointer, function, context,
+    // and the first word of the double in the fixed part of the frame.
+    return MemOperand(fp, -(index + 3) * kPointerSize + kPointerSize);
+  } else {
+    // Incoming parameter. Skip the return address and the first word of
+    // the double.
+    return MemOperand(fp, -(index - 1) * kPointerSize + kPointerSize);
+  }
+}
+
+
 void LCodeGen::WriteTranslation(LEnvironment* environment,
                                 Translation* translation) {
   if (environment == NULL) return;
@@ -671,7 +573,8 @@
   Handle<DeoptimizationInputData> data =
       Factory::NewDeoptimizationInputData(length, TENURED);
 
-  data->SetTranslationByteArray(*translations_.CreateByteArray());
+  Handle<ByteArray> translations = translations_.CreateByteArray();
+  data->SetTranslationByteArray(*translations);
   data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
 
   Handle<FixedArray> literals =
@@ -751,6 +654,12 @@
 }
 
 
+void LCodeGen::RecordSafepoint(int deoptimization_index) {
+  LPointerMap empty_pointers(RelocInfo::kNoPosition);
+  RecordSafepoint(&empty_pointers, deoptimization_index);
+}
+
+
 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
                                             int arguments,
                                             int deoptimization_index) {
@@ -787,116 +696,7 @@
 
 
 void LCodeGen::DoParallelMove(LParallelMove* move) {
-  // d0 must always be a scratch register.
-  DoubleRegister dbl_scratch = d0;
-  LUnallocated marker_operand(LUnallocated::NONE);
-
-  Register core_scratch = scratch0();
-  bool destroys_core_scratch = false;
-
-  const ZoneList<LMoveOperands>* moves =
-      resolver_.Resolve(move->move_operands(), &marker_operand);
-  for (int i = moves->length() - 1; i >= 0; --i) {
-    LMoveOperands move = moves->at(i);
-    LOperand* from = move.source();
-    LOperand* to = move.destination();
-    ASSERT(!from->IsDoubleRegister() ||
-           !ToDoubleRegister(from).is(dbl_scratch));
-    ASSERT(!to->IsDoubleRegister() || !ToDoubleRegister(to).is(dbl_scratch));
-    ASSERT(!from->IsRegister() || !ToRegister(from).is(core_scratch));
-    ASSERT(!to->IsRegister() || !ToRegister(to).is(core_scratch));
-    if (from == &marker_operand) {
-      if (to->IsRegister()) {
-        __ mov(ToRegister(to), core_scratch);
-        ASSERT(destroys_core_scratch);
-      } else if (to->IsStackSlot()) {
-        __ str(core_scratch, ToMemOperand(to));
-        ASSERT(destroys_core_scratch);
-      } else if (to->IsDoubleRegister()) {
-        __ vmov(ToDoubleRegister(to), dbl_scratch);
-      } else {
-        ASSERT(to->IsDoubleStackSlot());
-        // TODO(regis): Why is vstr not taking a MemOperand?
-        // __ vstr(dbl_scratch, ToMemOperand(to));
-        MemOperand to_operand = ToMemOperand(to);
-        __ vstr(dbl_scratch, to_operand.rn(), to_operand.offset());
-      }
-    } else if (to == &marker_operand) {
-      if (from->IsRegister() || from->IsConstantOperand()) {
-        __ mov(core_scratch, ToOperand(from));
-        destroys_core_scratch = true;
-      } else if (from->IsStackSlot()) {
-        __ ldr(core_scratch, ToMemOperand(from));
-        destroys_core_scratch = true;
-      } else if (from->IsDoubleRegister()) {
-        __ vmov(dbl_scratch, ToDoubleRegister(from));
-      } else {
-        ASSERT(from->IsDoubleStackSlot());
-        // TODO(regis): Why is vldr not taking a MemOperand?
-        // __ vldr(dbl_scratch, ToMemOperand(from));
-        MemOperand from_operand = ToMemOperand(from);
-        __ vldr(dbl_scratch, from_operand.rn(), from_operand.offset());
-      }
-    } else if (from->IsConstantOperand()) {
-      if (to->IsRegister()) {
-        __ mov(ToRegister(to), ToOperand(from));
-      } else {
-        ASSERT(to->IsStackSlot());
-        __ mov(ip, ToOperand(from));
-        __ str(ip, ToMemOperand(to));
-      }
-    } else if (from->IsRegister()) {
-      if (to->IsRegister()) {
-        __ mov(ToRegister(to), ToOperand(from));
-      } else {
-        ASSERT(to->IsStackSlot());
-        __ str(ToRegister(from), ToMemOperand(to));
-      }
-    } else if (to->IsRegister()) {
-      ASSERT(from->IsStackSlot());
-      __ ldr(ToRegister(to), ToMemOperand(from));
-    } else if (from->IsStackSlot()) {
-      ASSERT(to->IsStackSlot());
-      __ ldr(ip, ToMemOperand(from));
-      __ str(ip, ToMemOperand(to));
-    } else if (from->IsDoubleRegister()) {
-      if (to->IsDoubleRegister()) {
-      __ vmov(ToDoubleRegister(to), ToDoubleRegister(from));
-      } else {
-        ASSERT(to->IsDoubleStackSlot());
-        // TODO(regis): Why is vstr not taking a MemOperand?
-        // __ vstr(dbl_scratch, ToMemOperand(to));
-        MemOperand to_operand = ToMemOperand(to);
-        __ vstr(ToDoubleRegister(from), to_operand.rn(), to_operand.offset());
-      }
-    } else if (to->IsDoubleRegister()) {
-      ASSERT(from->IsDoubleStackSlot());
-      // TODO(regis): Why is vldr not taking a MemOperand?
-      // __ vldr(ToDoubleRegister(to), ToMemOperand(from));
-      MemOperand from_operand = ToMemOperand(from);
-      __ vldr(ToDoubleRegister(to), from_operand.rn(), from_operand.offset());
-    } else {
-      ASSERT(to->IsDoubleStackSlot() && from->IsDoubleStackSlot());
-      // TODO(regis): Why is vldr not taking a MemOperand?
-      // __ vldr(dbl_scratch, ToMemOperand(from));
-      MemOperand from_operand = ToMemOperand(from);
-      __ vldr(dbl_scratch, from_operand.rn(), from_operand.offset());
-      // TODO(regis): Why is vstr not taking a MemOperand?
-      // __ vstr(dbl_scratch, ToMemOperand(to));
-      MemOperand to_operand = ToMemOperand(to);
-      __ vstr(dbl_scratch, to_operand.rn(), to_operand.offset());
-    }
-  }
-
-  if (destroys_core_scratch) {
-    __ ldr(core_scratch, MemOperand(fp, -kPointerSize));
-  }
-
-  LInstruction* next = GetNextInstruction();
-  if (next != NULL && next->IsLazyBailout()) {
-    int pc = masm()->pc_offset();
-    safepoints_.SetPcAfterGap(pc);
-  }
+  resolver_.Resolve(move);
 }
 
 
@@ -966,7 +766,8 @@
     }
     case CodeStub::TranscendentalCache: {
       __ ldr(r0, MemOperand(sp, 0));
-      TranscendentalCacheStub stub(instr->transcendental_type());
+      TranscendentalCacheStub stub(instr->transcendental_type(),
+                                   TranscendentalCacheStub::TAGGED);
       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
       break;
     }
@@ -987,7 +788,7 @@
     DeferredModI(LCodeGen* codegen, LModI* instr)
         : LDeferredCode(codegen), instr_(instr) { }
     virtual void Generate() {
-      codegen()->DoDeferredGenericBinaryStub(instr_, Token::MOD);
+      codegen()->DoDeferredBinaryOpStub(instr_, Token::MOD);
     }
    private:
     LModI* instr_;
@@ -1016,7 +817,7 @@
     __ bind(&ok);
   }
 
-  // Try a few common cases before using the generic stub.
+  // Try a few common cases before using the stub.
   Label call_stub;
   const int kUnfolds = 3;
   // Skip if either side is negative.
@@ -1044,7 +845,7 @@
   __ and_(result, scratch, Operand(left));
 
   __ bind(&call_stub);
-  // Call the generic stub. The numbers in r0 and r1 have
+  // Call the stub. The numbers in r0 and r1 have
   // to be tagged to Smis. If that is not possible, deoptimize.
   DeferredModI* deferred = new DeferredModI(this, instr);
   __ TrySmiTag(left, &deoptimize, scratch);
@@ -1070,7 +871,7 @@
     DeferredDivI(LCodeGen* codegen, LDivI* instr)
         : LDeferredCode(codegen), instr_(instr) { }
     virtual void Generate() {
-      codegen()->DoDeferredGenericBinaryStub(instr_, Token::DIV);
+      codegen()->DoDeferredBinaryOpStub(instr_, Token::DIV);
     }
    private:
     LDivI* instr_;
@@ -1123,7 +924,7 @@
   __ mov(result, Operand(left, ASR, 2), LeaveCC, eq);
   __ b(eq, &done);
 
-  // Call the generic stub. The numbers in r0 and r1 have
+  // Call the stub. The numbers in r0 and r1 have
   // to be tagged to Smis. If that is not possible, deoptimize.
   DeferredDivI* deferred = new DeferredDivI(this, instr);
 
@@ -1145,19 +946,33 @@
 
 
 template<int T>
-void LCodeGen::DoDeferredGenericBinaryStub(LTemplateInstruction<1, 2, T>* instr,
-                                           Token::Value op) {
+void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr,
+                                      Token::Value op) {
   Register left = ToRegister(instr->InputAt(0));
   Register right = ToRegister(instr->InputAt(1));
 
   __ PushSafepointRegistersAndDoubles();
-  GenericBinaryOpStub stub(op, OVERWRITE_LEFT, left, right);
+  // Move left to r1 and right to r0 for the stub call.
+  if (left.is(r1)) {
+    __ Move(r0, right);
+  } else if (left.is(r0) && right.is(r1)) {
+    __ Swap(r0, r1, r2);
+  } else if (left.is(r0)) {
+    ASSERT(!right.is(r1));
+    __ mov(r1, r0);
+    __ mov(r0, right);
+  } else {
+    ASSERT(!left.is(r0) && !right.is(r0));
+    __ mov(r0, right);
+    __ mov(r1, left);
+  }
+  TypeRecordingBinaryOpStub stub(op, OVERWRITE_LEFT);
   __ CallStub(&stub);
   RecordSafepointWithRegistersAndDoubles(instr->pointer_map(),
                                          0,
                                          Safepoint::kNoDeoptimizationIndex);
   // Overwrite the stored value of r0 with the result of the stub.
-  __ StoreToSafepointRegistersAndDoublesSlot(r0);
+  __ StoreToSafepointRegistersAndDoublesSlot(r0, r0);
   __ PopSafepointRegistersAndDoubles();
 }
 
@@ -1413,7 +1228,7 @@
       __ vmov(r2, r3, right);
       __ CallCFunction(ExternalReference::double_fp_operation(Token::MOD), 4);
       // Move the result in the double result register.
-      __ vmov(ToDoubleRegister(instr->result()), r0, r1);
+      __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result()));
 
       // Restore r0-r3.
       __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
@@ -1431,10 +1246,7 @@
   ASSERT(ToRegister(instr->InputAt(1)).is(r0));
   ASSERT(ToRegister(instr->result()).is(r0));
 
-  // TODO(regis): Implement TypeRecordingBinaryOpStub and replace current
-  // GenericBinaryOpStub:
-  // TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE);
-  GenericBinaryOpStub stub(instr->op(), NO_OVERWRITE, r1, r0);
+  TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE);
   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
 }
 
@@ -1896,14 +1708,45 @@
 }
 
 
+void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
+  Register input = ToRegister(instr->InputAt(0));
+  Register result = ToRegister(instr->result());
+
+  if (FLAG_debug_code) {
+    __ AbortIfNotString(input);
+  }
+
+  __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset));
+  __ IndexFromHash(result, result);
+}
+
+
 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
-  Abort("DoHasCachedArrayIndex unimplemented.");
+  Register input = ToRegister(instr->InputAt(0));
+  Register result = ToRegister(instr->result());
+  Register scratch = scratch0();
+
+  ASSERT(instr->hydrogen()->value()->representation().IsTagged());
+  __ ldr(scratch,
+         FieldMemOperand(input, String::kHashFieldOffset));
+  __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask));
+  __ LoadRoot(result, Heap::kTrueValueRootIndex, eq);
+  __ LoadRoot(result, Heap::kFalseValueRootIndex, ne);
 }
 
 
 void LCodeGen::DoHasCachedArrayIndexAndBranch(
     LHasCachedArrayIndexAndBranch* instr) {
-  Abort("DoHasCachedArrayIndexAndBranch unimplemented.");
+  Register input = ToRegister(instr->InputAt(0));
+  Register scratch = scratch0();
+
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+  __ ldr(scratch,
+         FieldMemOperand(input, String::kHashFieldOffset));
+  __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask));
+  EmitBranch(true_block, false_block, eq);
 }
 
 
@@ -2146,15 +1989,11 @@
   __ bind(&before_push_delta);
   __ BlockConstPoolFor(kAdditionalDelta);
   __ mov(temp, Operand(delta * kPointerSize));
-  __ StoreToSafepointRegisterSlot(temp);
-  __ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
-  ASSERT_EQ(kAdditionalDelta,
-            masm_->InstructionsGeneratedSince(&before_push_delta));
-  RecordSafepointWithRegisters(
-      instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
+  __ StoreToSafepointRegisterSlot(temp, temp);
+  CallCode(stub.GetCode(),  RelocInfo::CODE_TARGET, instr);
   // Put the result value into the result register slot and
   // restore all registers.
-  __ StoreToSafepointRegisterSlot(result);
+  __ StoreToSafepointRegisterSlot(result, result);
 
   __ PopSafepointRegisters();
 }
@@ -2274,17 +2113,13 @@
 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
   Register context = ToRegister(instr->context());
   Register result = ToRegister(instr->result());
-  __ ldr(result,
-         MemOperand(context, Context::SlotOffset(Context::FCONTEXT_INDEX)));
-  __ ldr(result, ContextOperand(result, instr->slot_index()));
+  __ ldr(result, ContextOperand(context, instr->slot_index()));
 }
 
 
 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
   Register context = ToRegister(instr->context());
   Register value = ToRegister(instr->value());
-  __ ldr(context,
-         MemOperand(context, Context::SlotOffset(Context::FCONTEXT_INDEX)));
   __ str(value, ContextOperand(context, instr->slot_index()));
   if (instr->needs_write_barrier()) {
     int offset = Context::SlotOffset(instr->slot_index());
@@ -2603,7 +2438,7 @@
                                  LInstruction* instr) {
   // Change context if needed.
   bool change_context =
-      (graph()->info()->closure()->context() != function->context()) ||
+      (info()->closure()->context() != function->context()) ||
       scope()->contains_with() ||
       (scope()->num_heap_slots() > 0);
   if (change_context) {
@@ -2687,7 +2522,7 @@
   // Set the pointer to the new heap number in tmp.
   if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0));
   // Restore input_reg after call to runtime.
-  __ LoadFromSafepointRegisterSlot(input);
+  __ LoadFromSafepointRegisterSlot(input, input);
   __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
 
   __ bind(&allocated);
@@ -2698,7 +2533,7 @@
   __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
   __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
 
-  __ str(tmp1, masm()->SafepointRegisterSlot(input));
+  __ StoreToSafepointRegisterSlot(tmp1, input);
   __ PopSafepointRegisters();
 
   __ bind(&done);
@@ -2752,41 +2587,6 @@
 }
 
 
-// Truncates a double using a specific rounding mode.
-// Clears the z flag (ne condition) if an overflow occurs.
-void LCodeGen::EmitVFPTruncate(VFPRoundingMode rounding_mode,
-                               SwVfpRegister result,
-                               DwVfpRegister double_input,
-                               Register scratch1,
-                               Register scratch2) {
-  Register prev_fpscr = scratch1;
-  Register scratch = scratch2;
-
-  // Set custom FPCSR:
-  //  - Set rounding mode.
-  //  - Clear vfp cumulative exception flags.
-  //  - Make sure Flush-to-zero mode control bit is unset.
-  __ vmrs(prev_fpscr);
-  __ bic(scratch, prev_fpscr, Operand(kVFPExceptionMask |
-                                      kVFPRoundingModeMask |
-                                      kVFPFlushToZeroMask));
-  __ orr(scratch, scratch, Operand(rounding_mode));
-  __ vmsr(scratch);
-
-  // Convert the argument to an integer.
-  __ vcvt_s32_f64(result,
-                  double_input,
-                  kFPSCRRounding);
-
-  // Retrieve FPSCR.
-  __ vmrs(scratch);
-  // Restore FPSCR.
-  __ vmsr(prev_fpscr);
-  // Check for vfp exceptions.
-  __ tst(scratch, Operand(kVFPExceptionMask));
-}
-
-
 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
   DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
@@ -2794,11 +2594,11 @@
   Register scratch1 = scratch0();
   Register scratch2 = ToRegister(instr->TempAt(0));
 
-  EmitVFPTruncate(kRoundToMinusInf,
-                  single_scratch,
-                  input,
-                  scratch1,
-                  scratch2);
+  __ EmitVFPTruncate(kRoundToMinusInf,
+                     single_scratch,
+                     input,
+                     scratch1,
+                     scratch2);
   DeoptimizeIf(ne, instr->environment());
 
   // Move the result back to general purpose register r0.
@@ -2815,6 +2615,30 @@
 }
 
 
+void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
+  DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
+  Register result = ToRegister(instr->result());
+  Register scratch1 = scratch0();
+  Register scratch2 = result;
+  __ EmitVFPTruncate(kRoundToNearest,
+                     double_scratch0().low(),
+                     input,
+                     scratch1,
+                     scratch2);
+  DeoptimizeIf(ne, instr->environment());
+  __ vmov(result, double_scratch0().low());
+
+  // Test for -0.
+  Label done;
+  __ cmp(result, Operand(0));
+  __ b(ne, &done);
+  __ vmov(scratch1, input.high());
+  __ tst(scratch1, Operand(HeapNumber::kSignMask));
+  DeoptimizeIf(ne, instr->environment());
+  __ bind(&done);
+}
+
+
 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
   DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
   ASSERT(ToDoubleRegister(instr->result()).is(input));
@@ -2822,6 +2646,88 @@
 }
 
 
+void LCodeGen::DoPower(LPower* instr) {
+  LOperand* left = instr->InputAt(0);
+  LOperand* right = instr->InputAt(1);
+  Register scratch = scratch0();
+  DoubleRegister result_reg = ToDoubleRegister(instr->result());
+  Representation exponent_type = instr->hydrogen()->right()->representation();
+  if (exponent_type.IsDouble()) {
+    // Prepare arguments and call C function.
+    __ PrepareCallCFunction(4, scratch);
+    __ vmov(r0, r1, ToDoubleRegister(left));
+    __ vmov(r2, r3, ToDoubleRegister(right));
+    __ CallCFunction(ExternalReference::power_double_double_function(), 4);
+  } else if (exponent_type.IsInteger32()) {
+    ASSERT(ToRegister(right).is(r0));
+    // Prepare arguments and call C function.
+    __ PrepareCallCFunction(4, scratch);
+    __ mov(r2, ToRegister(right));
+    __ vmov(r0, r1, ToDoubleRegister(left));
+    __ CallCFunction(ExternalReference::power_double_int_function(), 4);
+  } else {
+    ASSERT(exponent_type.IsTagged());
+    ASSERT(instr->hydrogen()->left()->representation().IsDouble());
+
+    Register right_reg = ToRegister(right);
+
+    // Check for smi on the right hand side.
+    Label non_smi, call;
+    __ JumpIfNotSmi(right_reg, &non_smi);
+
+    // Untag smi and convert it to a double.
+    __ SmiUntag(right_reg);
+    SwVfpRegister single_scratch = double_scratch0().low();
+    __ vmov(single_scratch, right_reg);
+    __ vcvt_f64_s32(result_reg, single_scratch);
+    __ jmp(&call);
+
+    // Heap number map check.
+    __ bind(&non_smi);
+    __ ldr(scratch, FieldMemOperand(right_reg, HeapObject::kMapOffset));
+    __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
+    __ cmp(scratch, Operand(ip));
+    DeoptimizeIf(ne, instr->environment());
+    int32_t value_offset = HeapNumber::kValueOffset - kHeapObjectTag;
+    __ add(scratch, right_reg, Operand(value_offset));
+    __ vldr(result_reg, scratch, 0);
+
+    // Prepare arguments and call C function.
+    __ bind(&call);
+    __ PrepareCallCFunction(4, scratch);
+    __ vmov(r0, r1, ToDoubleRegister(left));
+    __ vmov(r2, r3, result_reg);
+    __ CallCFunction(ExternalReference::power_double_double_function(), 4);
+  }
+  // Store the result in the result register.
+  __ GetCFunctionDoubleResult(result_reg);
+}
+
+
+void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
+  ASSERT(ToDoubleRegister(instr->result()).is(d2));
+  TranscendentalCacheStub stub(TranscendentalCache::LOG,
+                               TranscendentalCacheStub::UNTAGGED);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoMathCos(LUnaryMathOperation* instr) {
+  ASSERT(ToDoubleRegister(instr->result()).is(d2));
+  TranscendentalCacheStub stub(TranscendentalCache::COS,
+                               TranscendentalCacheStub::UNTAGGED);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoMathSin(LUnaryMathOperation* instr) {
+  ASSERT(ToDoubleRegister(instr->result()).is(d2));
+  TranscendentalCacheStub stub(TranscendentalCache::SIN,
+                               TranscendentalCacheStub::UNTAGGED);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+}
+
+
 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
   switch (instr->op()) {
     case kMathAbs:
@@ -2830,9 +2736,21 @@
     case kMathFloor:
       DoMathFloor(instr);
       break;
+    case kMathRound:
+      DoMathRound(instr);
+      break;
     case kMathSqrt:
       DoMathSqrt(instr);
       break;
+    case kMathCos:
+      DoMathCos(instr);
+      break;
+    case kMathSin:
+      DoMathSin(instr);
+      break;
+    case kMathLog:
+      DoMathLog(instr);
+      break;
     default:
       Abort("Unimplemented type of LUnaryMathOperation.");
       UNREACHABLE();
@@ -2944,9 +2862,9 @@
 
   // Name is always in r2.
   __ mov(r2, Operand(instr->name()));
-  Handle<Code> ic(Builtins::builtin(info_->is_strict()
-      ? Builtins::StoreIC_Initialize_Strict
-      : Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      info_->is_strict() ? Builtins::StoreIC_Initialize_Strict
+                         : Builtins::StoreIC_Initialize));
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2988,7 +2906,9 @@
   ASSERT(ToRegister(instr->key()).is(r1));
   ASSERT(ToRegister(instr->value()).is(r0));
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      info_->is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                         : Builtins::KeyedStoreIC_Initialize));
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3129,8 +3049,7 @@
     __ AbortIfNotSmi(r0);
   }
   __ SmiUntag(r0);
-  MemOperand result_stack_slot = masm()->SafepointRegisterSlot(result);
-  __ str(r0, result_stack_slot);
+  __ StoreToSafepointRegisterSlot(r0, result);
   __ PopSafepointRegisters();
 }
 
@@ -3211,9 +3130,7 @@
   // register is stored, as this register is in the pointer map, but contains an
   // integer value.
   __ mov(ip, Operand(0));
-  int reg_stack_index = __ SafepointRegisterStackIndex(reg.code());
-  __ str(ip, MemOperand(sp, reg_stack_index * kPointerSize));
-
+  __ StoreToSafepointRegisterSlot(ip, reg);
   __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
   RecordSafepointWithRegisters(
       instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
@@ -3224,7 +3141,7 @@
   __ bind(&done);
   __ sub(ip, reg, Operand(kHeapObjectTag));
   __ vstr(dbl_scratch, ip, HeapNumber::kValueOffset);
-  __ str(reg, MemOperand(sp, reg_stack_index * kPointerSize));
+  __ StoreToSafepointRegisterSlot(reg, reg);
   __ PopSafepointRegisters();
 }
 
@@ -3269,8 +3186,7 @@
   __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
   RecordSafepointWithRegisters(
       instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
-  int reg_stack_index = __ SafepointRegisterStackIndex(reg.code());
-  __ str(r0, MemOperand(sp, reg_stack_index * kPointerSize));
+  __ StoreToSafepointRegisterSlot(r0, reg);
   __ PopSafepointRegisters();
 }
 
@@ -3456,30 +3372,36 @@
   Register scratch1 = scratch0();
   Register scratch2 = ToRegister(instr->TempAt(0));
 
-  VFPRoundingMode rounding_mode = instr->truncating() ? kRoundToMinusInf
-                                                      : kRoundToNearest;
+  __ EmitVFPTruncate(kRoundToZero,
+                     single_scratch,
+                     double_input,
+                     scratch1,
+                     scratch2);
 
-  EmitVFPTruncate(rounding_mode,
-                  single_scratch,
-                  double_input,
-                  scratch1,
-                  scratch2);
   // Deoptimize if we had a vfp invalid exception.
   DeoptimizeIf(ne, instr->environment());
+
   // Retrieve the result.
   __ vmov(result_reg, single_scratch);
 
-  if (instr->truncating() &&
-      instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
-    Label done;
-    __ cmp(result_reg, Operand(0));
-    __ b(ne, &done);
-    // Check for -0.
-    __ vmov(scratch1, double_input.high());
-    __ tst(scratch1, Operand(HeapNumber::kSignMask));
+  if (!instr->truncating()) {
+    // Convert result back to double and compare with input
+    // to check if the conversion was exact.
+    __ vmov(single_scratch, result_reg);
+    __ vcvt_f64_s32(double_scratch0(), single_scratch);
+    __ VFPCompareAndSetFlags(double_scratch0(), double_input);
     DeoptimizeIf(ne, instr->environment());
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      Label done;
+      __ cmp(result_reg, Operand(0));
+      __ b(ne, &done);
+      // Check for -0.
+      __ vmov(scratch1, double_input.high());
+      __ tst(scratch1, Operand(HeapNumber::kSignMask));
+      DeoptimizeIf(ne, instr->environment());
 
-    __ bind(&done);
+      __ bind(&done);
+    }
   }
 }
 
@@ -3750,37 +3672,30 @@
   Condition final_branch_condition = kNoCondition;
   Register scratch = scratch0();
   if (type_name->Equals(Heap::number_symbol())) {
-    __ tst(input, Operand(kSmiTagMask));
-    __ b(eq, true_label);
+    __ JumpIfSmi(input, true_label);
     __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
     __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
     __ cmp(input, Operand(ip));
     final_branch_condition = eq;
 
   } else if (type_name->Equals(Heap::string_symbol())) {
-    __ tst(input, Operand(kSmiTagMask));
-    __ b(eq, false_label);
-    __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, input, scratch, FIRST_NONSTRING_TYPE);
+    __ b(ge, false_label);
     __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
     __ tst(ip, Operand(1 << Map::kIsUndetectable));
-    __ b(ne, false_label);
-    __ CompareInstanceType(input, scratch, FIRST_NONSTRING_TYPE);
-    final_branch_condition = lo;
+    final_branch_condition = eq;
 
   } else if (type_name->Equals(Heap::boolean_symbol())) {
-    __ LoadRoot(ip, Heap::kTrueValueRootIndex);
-    __ cmp(input, ip);
+    __ CompareRoot(input, Heap::kTrueValueRootIndex);
     __ b(eq, true_label);
-    __ LoadRoot(ip, Heap::kFalseValueRootIndex);
-    __ cmp(input, ip);
+    __ CompareRoot(input, Heap::kFalseValueRootIndex);
     final_branch_condition = eq;
 
   } else if (type_name->Equals(Heap::undefined_symbol())) {
-    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
-    __ cmp(input, ip);
+    __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
     __ b(eq, true_label);
-    __ tst(input, Operand(kSmiTagMask));
-    __ b(eq, false_label);
+    __ JumpIfSmi(input, false_label);
     // Check for undetectable objects => true.
     __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
     __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
@@ -3788,32 +3703,22 @@
     final_branch_condition = ne;
 
   } else if (type_name->Equals(Heap::function_symbol())) {
-    __ tst(input, Operand(kSmiTagMask));
-    __ b(eq, false_label);
-    __ CompareObjectType(input, input, scratch, JS_FUNCTION_TYPE);
-    __ b(eq, true_label);
-    // Regular expressions => 'function' (they are callable).
-    __ CompareInstanceType(input, scratch, JS_REGEXP_TYPE);
-    final_branch_condition = eq;
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, input, scratch, FIRST_FUNCTION_CLASS_TYPE);
+    final_branch_condition = ge;
 
   } else if (type_name->Equals(Heap::object_symbol())) {
-    __ tst(input, Operand(kSmiTagMask));
-    __ b(eq, false_label);
-    __ LoadRoot(ip, Heap::kNullValueRootIndex);
-    __ cmp(input, ip);
+    __ JumpIfSmi(input, false_label);
+    __ CompareRoot(input, Heap::kNullValueRootIndex);
     __ b(eq, true_label);
-    // Regular expressions => 'function', not 'object'.
-    __ CompareObjectType(input, input, scratch, JS_REGEXP_TYPE);
-    __ b(eq, false_label);
+    __ CompareObjectType(input, input, scratch, FIRST_JS_OBJECT_TYPE);
+    __ b(lo, false_label);
+    __ CompareInstanceType(input, scratch, FIRST_FUNCTION_CLASS_TYPE);
+    __ b(hs, false_label);
     // Check for undetectable objects => false.
     __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
     __ tst(ip, Operand(1 << Map::kIsUndetectable));
-    __ b(ne, false_label);
-    // Check for JS objects => true.
-    __ CompareInstanceType(input, scratch, FIRST_JS_OBJECT_TYPE);
-    __ b(lo, false_label);
-    __ CompareInstanceType(input, scratch, LAST_JS_OBJECT_TYPE);
-    final_branch_condition = ls;
+    final_branch_condition = eq;
 
   } else {
     final_branch_condition = ne;
@@ -3888,7 +3793,9 @@
 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
   Register object = ToRegister(instr->object());
   Register key = ToRegister(instr->key());
-  __ Push(object, key);
+  Register strict = scratch0();
+  __ mov(strict, Operand(Smi::FromInt(strict_mode_flag())));
+  __ Push(object, key, strict);
   ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
   LPointerMap* pointers = instr->pointer_map();
   LEnvironment* env = instr->deoptimization_environment();
diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h
index 7bc6689..23e0c44 100644
--- a/src/arm/lithium-codegen-arm.h
+++ b/src/arm/lithium-codegen-arm.h
@@ -29,7 +29,7 @@
 #define V8_ARM_LITHIUM_CODEGEN_ARM_H_
 
 #include "arm/lithium-arm.h"
-
+#include "arm/lithium-gap-resolver-arm.h"
 #include "deoptimizer.h"
 #include "safepoint-table.h"
 #include "scopes.h"
@@ -39,31 +39,8 @@
 
 // Forward declarations.
 class LDeferredCode;
-class LGapNode;
 class SafepointGenerator;
 
-class LGapResolver BASE_EMBEDDED {
- public:
-  LGapResolver();
-  const ZoneList<LMoveOperands>* Resolve(const ZoneList<LMoveOperands>* moves,
-                                         LOperand* marker_operand);
-
- private:
-  LGapNode* LookupNode(LOperand* operand);
-  bool CanReach(LGapNode* a, LGapNode* b, int visited_id);
-  bool CanReach(LGapNode* a, LGapNode* b);
-  void RegisterMove(LMoveOperands move);
-  void AddResultMove(LOperand* from, LOperand* to);
-  void AddResultMove(LGapNode* from, LGapNode* to);
-  void ResolveCycle(LGapNode* start, LOperand* marker_operand);
-
-  ZoneList<LGapNode*> nodes_;
-  ZoneList<LGapNode*> identified_cycles_;
-  ZoneList<LMoveOperands> result_;
-  int next_visited_id_;
-};
-
-
 class LCodeGen BASE_EMBEDDED {
  public:
   LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info)
@@ -76,13 +53,39 @@
         deoptimizations_(4),
         deoptimization_literals_(8),
         inlined_function_count_(0),
-        scope_(chunk->graph()->info()->scope()),
+        scope_(info->scope()),
         status_(UNUSED),
         deferred_(8),
-        osr_pc_offset_(-1) {
+        osr_pc_offset_(-1),
+        resolver_(this) {
     PopulateDeoptimizationLiteralsWithInlinedFunctions();
   }
 
+
+  // Simple accessors.
+  MacroAssembler* masm() const { return masm_; }
+  CompilationInfo* info() const { return info_; }
+
+  // Support for converting LOperands to assembler types.
+  // LOperand must be a register.
+  Register ToRegister(LOperand* op) const;
+
+  // LOperand is loaded into scratch, unless already a register.
+  Register EmitLoadRegister(LOperand* op, Register scratch);
+
+  // LOperand must be a double register.
+  DoubleRegister ToDoubleRegister(LOperand* op) const;
+
+  // LOperand is loaded into dbl_scratch, unless already a double register.
+  DoubleRegister EmitLoadDoubleRegister(LOperand* op,
+                                        SwVfpRegister flt_scratch,
+                                        DoubleRegister dbl_scratch);
+  int ToInteger32(LConstantOperand* op) const;
+  Operand ToOperand(LOperand* op);
+  MemOperand ToMemOperand(LOperand* op) const;
+  // Returns a MemOperand pointing to the high word of a DoubleStackSlot.
+  MemOperand ToHighMemOperand(LOperand* op) const;
+
   // Try to generate code for the entire chunk, but it may fail if the
   // chunk contains constructs we cannot handle. Returns true if the
   // code generation attempt succeeded.
@@ -94,8 +97,8 @@
 
   // Deferred code support.
   template<int T>
-  void DoDeferredGenericBinaryStub(LTemplateInstruction<1, 2, T>* instr,
-                                   Token::Value op);
+  void DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr,
+                              Token::Value op);
   void DoDeferredNumberTagD(LNumberTagD* instr);
   void DoDeferredNumberTagI(LNumberTagI* instr);
   void DoDeferredTaggedToI(LTaggedToI* instr);
@@ -129,10 +132,13 @@
   bool is_done() const { return status_ == DONE; }
   bool is_aborted() const { return status_ == ABORTED; }
 
+  int strict_mode_flag() const {
+    return info()->is_strict() ? kStrictMode : kNonStrictMode;
+  }
+
   LChunk* chunk() const { return chunk_; }
   Scope* scope() const { return scope_; }
   HGraph* graph() const { return chunk_->graph(); }
-  MacroAssembler* masm() const { return masm_; }
 
   Register scratch0() { return r9; }
   DwVfpRegister double_scratch0() { return d0; }
@@ -198,34 +204,15 @@
   Register ToRegister(int index) const;
   DoubleRegister ToDoubleRegister(int index) const;
 
-  // LOperand must be a register.
-  Register ToRegister(LOperand* op) const;
-
-  // LOperand is loaded into scratch, unless already a register.
-  Register EmitLoadRegister(LOperand* op, Register scratch);
-
-  // LOperand must be a double register.
-  DoubleRegister ToDoubleRegister(LOperand* op) const;
-
-  // LOperand is loaded into dbl_scratch, unless already a double register.
-  DoubleRegister EmitLoadDoubleRegister(LOperand* op,
-                                        SwVfpRegister flt_scratch,
-                                        DoubleRegister dbl_scratch);
-
-  int ToInteger32(LConstantOperand* op) const;
-  Operand ToOperand(LOperand* op);
-  MemOperand ToMemOperand(LOperand* op) const;
-
   // Specific math operations - used from DoUnaryMathOperation.
   void EmitIntegerMathAbs(LUnaryMathOperation* instr);
   void DoMathAbs(LUnaryMathOperation* instr);
-  void EmitVFPTruncate(VFPRoundingMode rounding_mode,
-                       SwVfpRegister result,
-                       DwVfpRegister double_input,
-                       Register scratch1,
-                       Register scratch2);
   void DoMathFloor(LUnaryMathOperation* instr);
+  void DoMathRound(LUnaryMathOperation* instr);
   void DoMathSqrt(LUnaryMathOperation* instr);
+  void DoMathLog(LUnaryMathOperation* instr);
+  void DoMathCos(LUnaryMathOperation* instr);
+  void DoMathSin(LUnaryMathOperation* instr);
 
   // Support for recording safepoint and position information.
   void RecordSafepoint(LPointerMap* pointers,
@@ -233,6 +220,7 @@
                        int arguments,
                        int deoptimization_index);
   void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
+  void RecordSafepoint(int deoptimization_index);
   void RecordSafepointWithRegisters(LPointerMap* pointers,
                                     int arguments,
                                     int deoptimization_index);
diff --git a/src/arm/lithium-gap-resolver-arm.cc b/src/arm/lithium-gap-resolver-arm.cc
new file mode 100644
index 0000000..1a2326b
--- /dev/null
+++ b/src/arm/lithium-gap-resolver-arm.cc
@@ -0,0 +1,303 @@
+// 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 "arm/lithium-gap-resolver-arm.h"
+#include "arm/lithium-codegen-arm.h"
+
+namespace v8 {
+namespace internal {
+
+static const Register kSavedValueRegister = { 9 };
+static const DoubleRegister kSavedDoubleValueRegister = { 0 };
+
+LGapResolver::LGapResolver(LCodeGen* owner)
+    : cgen_(owner), moves_(32), root_index_(0), in_cycle_(false),
+      saved_destination_(NULL) { }
+
+
+void LGapResolver::Resolve(LParallelMove* parallel_move) {
+  ASSERT(moves_.is_empty());
+  // Build up a worklist of moves.
+  BuildInitialMoveList(parallel_move);
+
+  for (int i = 0; i < moves_.length(); ++i) {
+    LMoveOperands move = moves_[i];
+    // Skip constants to perform them last.  They don't block other moves
+    // and skipping such moves with register destinations keeps those
+    // registers free for the whole algorithm.
+    if (!move.IsEliminated() && !move.source()->IsConstantOperand()) {
+      root_index_ = i;  // Any cycle is found when by reaching this move again.
+      PerformMove(i);
+      if (in_cycle_) {
+        RestoreValue();
+      }
+    }
+  }
+
+  // Perform the moves with constant sources.
+  for (int i = 0; i < moves_.length(); ++i) {
+    if (!moves_[i].IsEliminated()) {
+      ASSERT(moves_[i].source()->IsConstantOperand());
+      EmitMove(i);
+    }
+  }
+
+  moves_.Rewind(0);
+}
+
+
+void LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) {
+  // Perform a linear sweep of the moves to add them to the initial list of
+  // moves to perform, ignoring any move that is redundant (the source is
+  // the same as the destination, the destination is ignored and
+  // unallocated, or the move was already eliminated).
+  const ZoneList<LMoveOperands>* moves = parallel_move->move_operands();
+  for (int i = 0; i < moves->length(); ++i) {
+    LMoveOperands move = moves->at(i);
+    if (!move.IsRedundant()) moves_.Add(move);
+  }
+  Verify();
+}
+
+
+void LGapResolver::PerformMove(int index) {
+  // Each call to this function performs a move and deletes it from the move
+  // graph.  We first recursively perform any move blocking this one.  We
+  // mark a move as "pending" on entry to PerformMove in order to detect
+  // cycles in the move graph.
+
+  // We can only find a cycle, when doing a depth-first traversal of moves,
+  // be encountering the starting move again. So by spilling the source of
+  // the starting move, we break the cycle.  All moves are then unblocked,
+  // and the starting move is completed by writing the spilled value to
+  // its destination.  All other moves from the spilled source have been
+  // completed prior to breaking the cycle.
+  // An additional complication is that moves to MemOperands with large
+  // offsets (more than 1K or 4K) require us to spill this spilled value to
+  // the stack, to free up the register.
+  ASSERT(!moves_[index].IsPending());
+  ASSERT(!moves_[index].IsRedundant());
+
+  // Clear this move's destination to indicate a pending move.  The actual
+  // destination is saved in a stack allocated local.  Multiple moves can
+  // be pending because this function is recursive.
+  ASSERT(moves_[index].source() != NULL);  // Or else it will look eliminated.
+  LOperand* destination = moves_[index].destination();
+  moves_[index].set_destination(NULL);
+
+  // Perform a depth-first traversal of the move graph to resolve
+  // dependencies.  Any unperformed, unpending move with a source the same
+  // as this one's destination blocks this one so recursively perform all
+  // such moves.
+  for (int i = 0; i < moves_.length(); ++i) {
+    LMoveOperands other_move = moves_[i];
+    if (other_move.Blocks(destination) && !other_move.IsPending()) {
+      PerformMove(i);
+      // If there is a blocking, pending move it must be moves_[root_index_]
+      // and all other moves with the same source as moves_[root_index_] are
+      // sucessfully executed (because they are cycle-free) by this loop.
+    }
+  }
+
+  // We are about to resolve this move and don't need it marked as
+  // pending, so restore its destination.
+  moves_[index].set_destination(destination);
+
+  // The move may be blocked on a pending move, which must be the starting move.
+  // In this case, we have a cycle, and we save the source of this move to
+  // a scratch register to break it.
+  LMoveOperands other_move = moves_[root_index_];
+  if (other_move.Blocks(destination)) {
+    ASSERT(other_move.IsPending());
+    BreakCycle(index);
+    return;
+  }
+
+  // This move is no longer blocked.
+  EmitMove(index);
+}
+
+
+void LGapResolver::Verify() {
+#ifdef ENABLE_SLOW_ASSERTS
+  // No operand should be the destination for more than one move.
+  for (int i = 0; i < moves_.length(); ++i) {
+    LOperand* destination = moves_[i].destination();
+    for (int j = i + 1; j < moves_.length(); ++j) {
+      SLOW_ASSERT(!destination->Equals(moves_[j].destination()));
+    }
+  }
+#endif
+}
+
+#define __ ACCESS_MASM(cgen_->masm())
+
+void LGapResolver::BreakCycle(int index) {
+  // We save in a register the value that should end up in the source of
+  // moves_[root_index].  After performing all moves in the tree rooted
+  // in that move, we save the value to that source.
+  ASSERT(moves_[index].destination()->Equals(moves_[root_index_].source()));
+  ASSERT(!in_cycle_);
+  in_cycle_ = true;
+  LOperand* source = moves_[index].source();
+  saved_destination_ = moves_[index].destination();
+  if (source->IsRegister()) {
+    __ mov(kSavedValueRegister, cgen_->ToRegister(source));
+  } else if (source->IsStackSlot()) {
+    __ ldr(kSavedValueRegister, cgen_->ToMemOperand(source));
+  } else if (source->IsDoubleRegister()) {
+    __ vmov(kSavedDoubleValueRegister, cgen_->ToDoubleRegister(source));
+  } else if (source->IsDoubleStackSlot()) {
+    __ vldr(kSavedDoubleValueRegister, cgen_->ToMemOperand(source));
+  } else {
+    UNREACHABLE();
+  }
+  // This move will be done by restoring the saved value to the destination.
+  moves_[index].Eliminate();
+}
+
+
+void LGapResolver::RestoreValue() {
+  ASSERT(in_cycle_);
+  ASSERT(saved_destination_ != NULL);
+
+  // Spilled value is in kSavedValueRegister or kSavedDoubleValueRegister.
+  if (saved_destination_->IsRegister()) {
+    __ mov(cgen_->ToRegister(saved_destination_), kSavedValueRegister);
+  } else if (saved_destination_->IsStackSlot()) {
+    __ str(kSavedValueRegister, cgen_->ToMemOperand(saved_destination_));
+  } else if (saved_destination_->IsDoubleRegister()) {
+    __ vmov(cgen_->ToDoubleRegister(saved_destination_),
+            kSavedDoubleValueRegister);
+  } else if (saved_destination_->IsDoubleStackSlot()) {
+    __ vstr(kSavedDoubleValueRegister,
+            cgen_->ToMemOperand(saved_destination_));
+  } else {
+    UNREACHABLE();
+  }
+
+  in_cycle_ = false;
+  saved_destination_ = NULL;
+}
+
+
+void LGapResolver::EmitMove(int index) {
+  LOperand* source = moves_[index].source();
+  LOperand* destination = moves_[index].destination();
+
+  // Dispatch on the source and destination operand kinds.  Not all
+  // combinations are possible.
+
+  if (source->IsRegister()) {
+    Register source_register = cgen_->ToRegister(source);
+    if (destination->IsRegister()) {
+      __ mov(cgen_->ToRegister(destination), source_register);
+    } else {
+      ASSERT(destination->IsStackSlot());
+      __ str(source_register, cgen_->ToMemOperand(destination));
+    }
+
+  } else if (source->IsStackSlot()) {
+    MemOperand source_operand = cgen_->ToMemOperand(source);
+    if (destination->IsRegister()) {
+      __ ldr(cgen_->ToRegister(destination), source_operand);
+    } else {
+      ASSERT(destination->IsStackSlot());
+      MemOperand destination_operand = cgen_->ToMemOperand(destination);
+      if (in_cycle_) {
+        if (!destination_operand.OffsetIsUint12Encodable()) {
+          // ip is overwritten while saving the value to the destination.
+          // Therefore we can't use ip.  It is OK if the read from the source
+          // destroys ip, since that happens before the value is read.
+          __ vldr(kSavedDoubleValueRegister.low(), source_operand);
+          __ vstr(kSavedDoubleValueRegister.low(), destination_operand);
+        } else {
+          __ ldr(ip, source_operand);
+          __ str(ip, destination_operand);
+        }
+      } else {
+        __ ldr(kSavedValueRegister, source_operand);
+        __ str(kSavedValueRegister, destination_operand);
+      }
+    }
+
+  } else if (source->IsConstantOperand()) {
+    Operand source_operand = cgen_->ToOperand(source);
+    if (destination->IsRegister()) {
+      __ mov(cgen_->ToRegister(destination), source_operand);
+    } else {
+      ASSERT(destination->IsStackSlot());
+      ASSERT(!in_cycle_);  // Constant moves happen after all cycles are gone.
+      MemOperand destination_operand = cgen_->ToMemOperand(destination);
+      __ mov(kSavedValueRegister, source_operand);
+      __ str(kSavedValueRegister, cgen_->ToMemOperand(destination));
+    }
+
+  } else if (source->IsDoubleRegister()) {
+    DoubleRegister source_register = cgen_->ToDoubleRegister(source);
+    if (destination->IsDoubleRegister()) {
+      __ vmov(cgen_->ToDoubleRegister(destination), source_register);
+    } else {
+      ASSERT(destination->IsDoubleStackSlot());
+      MemOperand destination_operand = cgen_->ToMemOperand(destination);
+      __ vstr(source_register, destination_operand);
+    }
+
+  } else if (source->IsDoubleStackSlot()) {
+    MemOperand source_operand = cgen_->ToMemOperand(source);
+    if (destination->IsDoubleRegister()) {
+      __ vldr(cgen_->ToDoubleRegister(destination), source_operand);
+    } else {
+      ASSERT(destination->IsDoubleStackSlot());
+      MemOperand destination_operand = cgen_->ToMemOperand(destination);
+      if (in_cycle_) {
+        // kSavedDoubleValueRegister was used to break the cycle,
+        // but kSavedValueRegister is free.
+        MemOperand source_high_operand =
+            cgen_->ToHighMemOperand(source);
+        MemOperand destination_high_operand =
+            cgen_->ToHighMemOperand(destination);
+        __ ldr(kSavedValueRegister, source_operand);
+        __ str(kSavedValueRegister, destination_operand);
+        __ ldr(kSavedValueRegister, source_high_operand);
+        __ str(kSavedValueRegister, destination_high_operand);
+      } else {
+        __ vldr(kSavedDoubleValueRegister, source_operand);
+        __ vstr(kSavedDoubleValueRegister, destination_operand);
+      }
+    }
+  } else {
+    UNREACHABLE();
+  }
+
+  moves_[index].Eliminate();
+}
+
+
+#undef __
+
+} }  // namespace v8::internal
diff --git a/src/arm/lithium-gap-resolver-arm.h b/src/arm/lithium-gap-resolver-arm.h
new file mode 100644
index 0000000..334d292
--- /dev/null
+++ b/src/arm/lithium-gap-resolver-arm.h
@@ -0,0 +1,84 @@
+// 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_ARM_LITHIUM_GAP_RESOLVER_ARM_H_
+#define V8_ARM_LITHIUM_GAP_RESOLVER_ARM_H_
+
+#include "v8.h"
+
+#include "lithium.h"
+
+namespace v8 {
+namespace internal {
+
+class LCodeGen;
+class LGapResolver;
+
+class LGapResolver BASE_EMBEDDED {
+ public:
+
+  explicit LGapResolver(LCodeGen* owner);
+
+  // Resolve a set of parallel moves, emitting assembler instructions.
+  void Resolve(LParallelMove* parallel_move);
+
+ private:
+  // Build the initial list of moves.
+  void BuildInitialMoveList(LParallelMove* parallel_move);
+
+  // Perform the move at the moves_ index in question (possibly requiring
+  // other moves to satisfy dependencies).
+  void PerformMove(int index);
+
+  // If a cycle is found in the series of moves, save the blocking value to
+  // a scratch register.  The cycle must be found by hitting the root of the
+  // depth-first search.
+  void BreakCycle(int index);
+
+  // After a cycle has been resolved, restore the value from the scratch
+  // register to its proper destination.
+  void RestoreValue();
+
+  // Emit a move and remove it from the move graph.
+  void EmitMove(int index);
+
+  // Verify the move list before performing moves.
+  void Verify();
+
+  LCodeGen* cgen_;
+
+  // List of moves not yet resolved.
+  ZoneList<LMoveOperands> moves_;
+
+  int root_index_;
+  bool in_cycle_;
+  LOperand* saved_destination_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_ARM_LITHIUM_GAP_RESOLVER_ARM_H_
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 5d8df1a..d431f6a 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -271,6 +271,29 @@
 }
 
 
+void MacroAssembler::Bfi(Register dst,
+                         Register src,
+                         Register scratch,
+                         int lsb,
+                         int width,
+                         Condition cond) {
+  ASSERT(0 <= lsb && lsb < 32);
+  ASSERT(0 <= width && width < 32);
+  ASSERT(lsb + width < 32);
+  ASSERT(!scratch.is(dst));
+  if (width == 0) return;
+  if (!CpuFeatures::IsSupported(ARMv7)) {
+    int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
+    bic(dst, dst, Operand(mask));
+    and_(scratch, src, Operand((1 << width) - 1));
+    mov(scratch, Operand(scratch, LSL, lsb));
+    orr(dst, dst, scratch);
+  } else {
+    bfi(dst, src, lsb, width, cond);
+  }
+}
+
+
 void MacroAssembler::Bfc(Register dst, int lsb, int width, Condition cond) {
   ASSERT(lsb < 32);
   if (!CpuFeatures::IsSupported(ARMv7)) {
@@ -485,18 +508,19 @@
   PopSafepointRegisters();
 }
 
-void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register reg) {
-  str(reg, SafepointRegistersAndDoublesSlot(reg));
+void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register src,
+                                                             Register dst) {
+  str(src, SafepointRegistersAndDoublesSlot(dst));
 }
 
 
-void MacroAssembler::StoreToSafepointRegisterSlot(Register reg) {
-  str(reg, SafepointRegisterSlot(reg));
+void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) {
+  str(src, SafepointRegisterSlot(dst));
 }
 
 
-void MacroAssembler::LoadFromSafepointRegisterSlot(Register reg) {
-  ldr(reg, SafepointRegisterSlot(reg));
+void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
+  ldr(dst, SafepointRegisterSlot(src));
 }
 
 
@@ -714,7 +738,8 @@
 }
 
 
-void MacroAssembler::LeaveExitFrame(bool save_doubles) {
+void MacroAssembler::LeaveExitFrame(bool save_doubles,
+                                    Register argument_count) {
   // Optionally restore all double registers.
   if (save_doubles) {
     for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) {
@@ -736,12 +761,20 @@
   str(r3, MemOperand(ip));
 #endif
 
-  // Tear down the exit frame, pop the arguments, and return. Callee-saved
-  // register r4 still holds argc.
+  // Tear down the exit frame, pop the arguments, and return.
   mov(sp, Operand(fp));
   ldm(ia_w, sp, fp.bit() | lr.bit());
-  add(sp, sp, Operand(r4, LSL, kPointerSizeLog2));
-  mov(pc, lr);
+  if (argument_count.is_valid()) {
+    add(sp, sp, Operand(argument_count, LSL, kPointerSizeLog2));
+  }
+}
+
+void MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) {
+#if !defined(USE_ARM_EABI)
+  UNREACHABLE();
+#else
+  vmov(dst, r0, r1);
+#endif
 }
 
 
@@ -929,8 +962,8 @@
 
 
 void MacroAssembler::IsObjectJSStringType(Register object,
-                                           Register scratch,
-                                           Label* fail) {
+                                          Register scratch,
+                                          Label* fail) {
   ASSERT(kNotStringTag != 0);
 
   ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
@@ -1005,6 +1038,117 @@
 }
 
 
+void MacroAssembler::Throw(Register value) {
+  // r0 is expected to hold the exception.
+  if (!value.is(r0)) {
+    mov(r0, value);
+  }
+
+  // Adjust this code if not the case.
+  STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
+
+  // Drop the sp to the top of the handler.
+  mov(r3, Operand(ExternalReference(Top::k_handler_address)));
+  ldr(sp, MemOperand(r3));
+
+  // Restore the next handler and frame pointer, discard handler state.
+  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
+  pop(r2);
+  str(r2, MemOperand(r3));
+  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
+  ldm(ia_w, sp, r3.bit() | fp.bit());  // r3: discarded state.
+
+  // Before returning we restore the context from the frame pointer if
+  // not NULL.  The frame pointer is NULL in the exception handler of a
+  // JS entry frame.
+  cmp(fp, Operand(0, RelocInfo::NONE));
+  // Set cp to NULL if fp is NULL.
+  mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq);
+  // Restore cp otherwise.
+  ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
+#ifdef DEBUG
+  if (FLAG_debug_code) {
+    mov(lr, Operand(pc));
+  }
+#endif
+  STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
+  pop(pc);
+}
+
+
+void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
+                                      Register value) {
+  // Adjust this code if not the case.
+  STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
+
+  // r0 is expected to hold the exception.
+  if (!value.is(r0)) {
+    mov(r0, value);
+  }
+
+  // Drop sp to the top stack handler.
+  mov(r3, Operand(ExternalReference(Top::k_handler_address)));
+  ldr(sp, MemOperand(r3));
+
+  // Unwind the handlers until the ENTRY handler is found.
+  Label loop, done;
+  bind(&loop);
+  // Load the type of the current stack handler.
+  const int kStateOffset = StackHandlerConstants::kStateOffset;
+  ldr(r2, MemOperand(sp, kStateOffset));
+  cmp(r2, Operand(StackHandler::ENTRY));
+  b(eq, &done);
+  // Fetch the next handler in the list.
+  const int kNextOffset = StackHandlerConstants::kNextOffset;
+  ldr(sp, MemOperand(sp, kNextOffset));
+  jmp(&loop);
+  bind(&done);
+
+  // Set the top handler address to next handler past the current ENTRY handler.
+  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
+  pop(r2);
+  str(r2, MemOperand(r3));
+
+  if (type == OUT_OF_MEMORY) {
+    // Set external caught exception to false.
+    ExternalReference external_caught(Top::k_external_caught_exception_address);
+    mov(r0, Operand(false, RelocInfo::NONE));
+    mov(r2, Operand(external_caught));
+    str(r0, MemOperand(r2));
+
+    // Set pending exception and r0 to out of memory exception.
+    Failure* out_of_memory = Failure::OutOfMemoryException();
+    mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
+    mov(r2, Operand(ExternalReference(Top::k_pending_exception_address)));
+    str(r0, MemOperand(r2));
+  }
+
+  // Stack layout at this point. See also StackHandlerConstants.
+  // sp ->   state (ENTRY)
+  //         fp
+  //         lr
+
+  // Discard handler state (r2 is not used) and restore frame pointer.
+  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
+  ldm(ia_w, sp, r2.bit() | fp.bit());  // r2: discarded state.
+  // Before returning we restore the context from the frame pointer if
+  // not NULL.  The frame pointer is NULL in the exception handler of a
+  // JS entry frame.
+  cmp(fp, Operand(0, RelocInfo::NONE));
+  // Set cp to NULL if fp is NULL.
+  mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq);
+  // Restore cp otherwise.
+  ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
+#ifdef DEBUG
+  if (FLAG_debug_code) {
+    mov(lr, Operand(pc));
+  }
+#endif
+  STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
+  pop(pc);
+}
+
+
 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
                                             Register scratch,
                                             Label* miss) {
@@ -1102,6 +1246,8 @@
   ASSERT(!result.is(scratch1));
   ASSERT(!result.is(scratch2));
   ASSERT(!scratch1.is(scratch2));
+  ASSERT(!scratch1.is(ip));
+  ASSERT(!scratch2.is(ip));
 
   // Make object size into bytes.
   if ((flags & SIZE_IN_WORDS) != 0) {
@@ -1391,6 +1537,14 @@
 }
 
 
+void MacroAssembler::CompareRoot(Register obj,
+                                 Heap::RootListIndex index) {
+  ASSERT(!obj.is(ip));
+  LoadRoot(ip, index);
+  cmp(obj, ip);
+}
+
+
 void MacroAssembler::CheckMap(Register obj,
                               Register scratch,
                               Handle<Map> map,
@@ -1497,7 +1651,7 @@
 
 
 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(
-    ApiFunction* function, int stack_space) {
+    ExternalReference function, int stack_space) {
   ExternalReference next_address =
       ExternalReference::handle_scope_next_address();
   const int kNextOffset = 0;
@@ -1554,9 +1708,10 @@
   cmp(r4, r5);
   b(ne, &promote_scheduled_exception);
 
-  // LeaveExitFrame expects unwind space to be in r4.
+  // LeaveExitFrame expects unwind space to be in a register.
   mov(r4, Operand(stack_space));
-  LeaveExitFrame(false);
+  LeaveExitFrame(false, r4);
+  mov(pc, lr);
 
   bind(&promote_scheduled_exception);
   MaybeObject* result = TryTailCallExternalReference(
@@ -1696,9 +1851,9 @@
     ldr(scratch, FieldMemOperand(source, HeapNumber::kExponentOffset));
     // Get exponent alone in scratch2.
     Ubfx(scratch2,
-            scratch,
-            HeapNumber::kExponentShift,
-            HeapNumber::kExponentBits);
+         scratch,
+         HeapNumber::kExponentShift,
+         HeapNumber::kExponentBits);
     // Load dest with zero.  We use this either for the final shift or
     // for the answer.
     mov(dest, Operand(0, RelocInfo::NONE));
@@ -1761,6 +1916,52 @@
 }
 
 
+void MacroAssembler::EmitVFPTruncate(VFPRoundingMode rounding_mode,
+                                     SwVfpRegister result,
+                                     DwVfpRegister double_input,
+                                     Register scratch1,
+                                     Register scratch2,
+                                     CheckForInexactConversion check_inexact) {
+  ASSERT(CpuFeatures::IsSupported(VFP3));
+  CpuFeatures::Scope scope(VFP3);
+  Register prev_fpscr = scratch1;
+  Register scratch = scratch2;
+
+  int32_t check_inexact_conversion =
+    (check_inexact == kCheckForInexactConversion) ? kVFPInexactExceptionBit : 0;
+
+  // Set custom FPCSR:
+  //  - Set rounding mode.
+  //  - Clear vfp cumulative exception flags.
+  //  - Make sure Flush-to-zero mode control bit is unset.
+  vmrs(prev_fpscr);
+  bic(scratch,
+      prev_fpscr,
+      Operand(kVFPExceptionMask |
+              check_inexact_conversion |
+              kVFPRoundingModeMask |
+              kVFPFlushToZeroMask));
+  // 'Round To Nearest' is encoded by 0b00 so no bits need to be set.
+  if (rounding_mode != kRoundToNearest) {
+    orr(scratch, scratch, Operand(rounding_mode));
+  }
+  vmsr(scratch);
+
+  // Convert the argument to an integer.
+  vcvt_s32_f64(result,
+               double_input,
+               (rounding_mode == kRoundToZero) ? kDefaultRoundToZero
+                                               : kFPSCRRounding);
+
+  // Retrieve FPSCR.
+  vmrs(scratch);
+  // Restore FPSCR.
+  vmsr(prev_fpscr);
+  // Check for vfp exceptions.
+  tst(scratch, Operand(kVFPExceptionMask | check_inexact_conversion));
+}
+
+
 void MacroAssembler::GetLeastBitsFromSmi(Register dst,
                                          Register src,
                                          int num_least_bits) {
@@ -2041,11 +2242,22 @@
       ldr(dst, MemOperand(dst, Context::SlotOffset(Context::CLOSURE_INDEX)));
       ldr(dst, FieldMemOperand(dst, JSFunction::kContextOffset));
     }
-    // The context may be an intermediate context, not a function context.
-    ldr(dst, MemOperand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
-  } else {  // Slot is in the current function context.
-    // The context may be an intermediate context, not a function context.
-    ldr(dst, MemOperand(cp, Context::SlotOffset(Context::FCONTEXT_INDEX)));
+  } else {
+    // Slot is in the current function context.  Move it into the
+    // destination register in case we store into it (the write barrier
+    // cannot be allowed to destroy the context in esi).
+    mov(dst, cp);
+  }
+
+  // We should not have found a 'with' context by walking the context chain
+  // (i.e., the static scope chain and runtime context chain do not agree).
+  // A variable occurring in such a scope should have slot type LOOKUP and
+  // not CONTEXT.
+  if (FLAG_debug_code) {
+    ldr(ip, MemOperand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
+    cmp(dst, ip);
+    Check(eq, "Yo dawg, I heard you liked function contexts "
+              "so I put function contexts in all your contexts");
   }
 }
 
@@ -2122,12 +2334,23 @@
 }
 
 
+void MacroAssembler::AbortIfNotString(Register object) {
+  STATIC_ASSERT(kSmiTag == 0);
+  tst(object, Operand(kSmiTagMask));
+  Assert(ne, "Operand is not a string");
+  push(object);
+  ldr(object, FieldMemOperand(object, HeapObject::kMapOffset));
+  CompareInstanceType(object, object, FIRST_NONSTRING_TYPE);
+  pop(object);
+  Assert(lo, "Operand is not a string");
+}
+
+
+
 void MacroAssembler::AbortIfNotRootValue(Register src,
                                          Heap::RootListIndex root_value_index,
                                          const char* message) {
-  ASSERT(!src.is(ip));
-  LoadRoot(ip, root_value_index);
-  cmp(src, ip);
+  CompareRoot(src, root_value_index);
   Assert(eq, message);
 }
 
@@ -2243,6 +2466,60 @@
 }
 
 
+void MacroAssembler::CopyBytes(Register src,
+                               Register dst,
+                               Register length,
+                               Register scratch) {
+  Label align_loop, align_loop_1, word_loop, byte_loop, byte_loop_1, done;
+
+  // Align src before copying in word size chunks.
+  bind(&align_loop);
+  cmp(length, Operand(0));
+  b(eq, &done);
+  bind(&align_loop_1);
+  tst(src, Operand(kPointerSize - 1));
+  b(eq, &word_loop);
+  ldrb(scratch, MemOperand(src, 1, PostIndex));
+  strb(scratch, MemOperand(dst, 1, PostIndex));
+  sub(length, length, Operand(1), SetCC);
+  b(ne, &byte_loop_1);
+
+  // Copy bytes in word size chunks.
+  bind(&word_loop);
+  if (FLAG_debug_code) {
+    tst(src, Operand(kPointerSize - 1));
+    Assert(eq, "Expecting alignment for CopyBytes");
+  }
+  cmp(length, Operand(kPointerSize));
+  b(lt, &byte_loop);
+  ldr(scratch, MemOperand(src, kPointerSize, PostIndex));
+#if CAN_USE_UNALIGNED_ACCESSES
+  str(scratch, MemOperand(dst, kPointerSize, PostIndex));
+#else
+  strb(scratch, MemOperand(dst, 1, PostIndex));
+  mov(scratch, Operand(scratch, LSR, 8));
+  strb(scratch, MemOperand(dst, 1, PostIndex));
+  mov(scratch, Operand(scratch, LSR, 8));
+  strb(scratch, MemOperand(dst, 1, PostIndex));
+  mov(scratch, Operand(scratch, LSR, 8));
+  strb(scratch, MemOperand(dst, 1, PostIndex));
+#endif
+  sub(length, length, Operand(kPointerSize));
+  b(&word_loop);
+
+  // Copy the last bytes if any left.
+  bind(&byte_loop);
+  cmp(length, Operand(0));
+  b(eq, &done);
+  bind(&byte_loop_1);
+  ldrb(scratch, MemOperand(src, 1, PostIndex));
+  strb(scratch, MemOperand(dst, 1, PostIndex));
+  sub(length, length, Operand(1), SetCC);
+  b(ne, &byte_loop_1);
+  bind(&done);
+}
+
+
 void MacroAssembler::CountLeadingZeros(Register zeros,   // Answer.
                                        Register source,  // Input.
                                        Register scratch) {
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 36e4a1f..aaf4458 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -121,6 +121,15 @@
             Condition cond = al);
   void Sbfx(Register dst, Register src, int lsb, int width,
             Condition cond = al);
+  // The scratch register is not used for ARMv7.
+  // scratch can be the same register as src (in which case it is trashed), but
+  // not the same as dst.
+  void Bfi(Register dst,
+           Register src,
+           Register scratch,
+           int lsb,
+           int width,
+           Condition cond = al);
   void Bfc(Register dst, int lsb, int width, Condition cond = al);
   void Usat(Register dst, int satpos, const Operand& src,
             Condition cond = al);
@@ -234,18 +243,30 @@
     }
   }
 
+  // Pop two registers. Pops rightmost register first (from lower address).
+  void Pop(Register src1, Register src2, Condition cond = al) {
+    ASSERT(!src1.is(src2));
+    if (src1.code() > src2.code()) {
+      ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
+    } else {
+      ldr(src2, MemOperand(sp, 4, PostIndex), cond);
+      ldr(src1, MemOperand(sp, 4, PostIndex), cond);
+    }
+  }
+
   // Push and pop the registers that can hold pointers, as defined by the
   // RegList constant kSafepointSavedRegisters.
   void PushSafepointRegisters();
   void PopSafepointRegisters();
   void PushSafepointRegistersAndDoubles();
   void PopSafepointRegistersAndDoubles();
-  void StoreToSafepointRegisterSlot(Register reg);
-  void StoreToSafepointRegistersAndDoublesSlot(Register reg);
-  void LoadFromSafepointRegisterSlot(Register reg);
-  static int SafepointRegisterStackIndex(int reg_code);
-  static MemOperand SafepointRegisterSlot(Register reg);
-  static MemOperand SafepointRegistersAndDoublesSlot(Register reg);
+  // Store value in register src in the safepoint stack slot for
+  // register dst.
+  void StoreToSafepointRegisterSlot(Register src, Register dst);
+  void StoreToSafepointRegistersAndDoublesSlot(Register src, Register dst);
+  // Load the value of the src register from its safepoint stack slot
+  // into register dst.
+  void LoadFromSafepointRegisterSlot(Register dst, Register src);
 
   // Load two consecutive registers with two consecutive memory locations.
   void Ldrd(Register dst1,
@@ -297,7 +318,9 @@
   void EnterExitFrame(bool save_doubles, int stack_space = 0);
 
   // Leave the current exit frame. Expects the return value in r0.
-  void LeaveExitFrame(bool save_doubles);
+  // Expect the number of values, pushed prior to the exit frame, to
+  // remove in a register (or no_reg, if there is nothing to remove).
+  void LeaveExitFrame(bool save_doubles, Register argument_count);
 
   // Get the actual activation frame alignment for target environment.
   static int ActivationFrameAlignment();
@@ -371,6 +394,13 @@
   // Must preserve the result register.
   void PopTryHandler();
 
+  // Passes thrown value (in r0) to the handler of top of the try handler chain.
+  void Throw(Register value);
+
+  // Propagates an uncatchable exception to the top of the current JS stack's
+  // handler chain.
+  void ThrowUncatchable(UncatchableExceptionType type, Register value);
+
   // ---------------------------------------------------------------------------
   // Inline caching support
 
@@ -487,6 +517,14 @@
   // Copies a fixed number of fields of heap objects from src to dst.
   void CopyFields(Register dst, Register src, RegList temps, int field_count);
 
+  // Copies a number of bytes from src to dst. All registers are clobbered. On
+  // exit src and dst will point to the place just after where the last byte was
+  // read or written and length will be zero.
+  void CopyBytes(Register src,
+                 Register dst,
+                 Register length,
+                 Register scratch);
+
   // ---------------------------------------------------------------------------
   // Support functions.
 
@@ -539,6 +577,11 @@
                 bool is_heap_object);
 
 
+  // Compare the object in a register to a value from the root list.
+  // Uses the ip register as scratch.
+  void CompareRoot(Register obj, Heap::RootListIndex index);
+
+
   // Load and check the instance type of an object for being a string.
   // Loads the type into the second argument register.
   // Returns a condition that will be enabled if the object was a string.
@@ -603,6 +646,19 @@
                       DwVfpRegister double_scratch,
                       Label *not_int32);
 
+// Truncates a double using a specific rounding mode.
+// Clears the z flag (ne condition) if an overflow occurs.
+// If exact_conversion is true, the z flag is also cleared if the conversion
+// was inexact, ie. if the double value could not be converted exactly
+// to a 32bit integer.
+  void EmitVFPTruncate(VFPRoundingMode rounding_mode,
+                       SwVfpRegister result,
+                       DwVfpRegister double_input,
+                       Register scratch1,
+                       Register scratch2,
+                       CheckForInexactConversion check
+                           = kDontCheckForInexactConversion);
+
   // Count leading zeros in a 32 bit word.  On ARM5 and later it uses the clz
   // instruction.  On pre-ARM5 hardware this routine gives the wrong answer
   // for 0 (31 instead of 32).  Source and scratch can be the same in which case
@@ -674,11 +730,13 @@
   void CallCFunction(ExternalReference function, int num_arguments);
   void CallCFunction(Register function, int num_arguments);
 
+  void GetCFunctionDoubleResult(const DoubleRegister dst);
+
   // Calls an API function. Allocates HandleScope, extracts returned value
   // from handle and propagates exceptions. Restores context.
   // stack_space - space to be unwound on exit (includes the call js
   // arguments space and the additional space allocated for the fast call).
-  MaybeObject* TryCallApiFunctionAndReturn(ApiFunction* function,
+  MaybeObject* TryCallApiFunctionAndReturn(ExternalReference function,
                                            int stack_space);
 
   // Jump to a runtime routine.
@@ -765,11 +823,11 @@
     mov(reg, scratch);
   }
 
-  void SmiUntag(Register reg) {
-    mov(reg, Operand(reg, ASR, kSmiTagSize));
+  void SmiUntag(Register reg, SBit s = LeaveCC) {
+    mov(reg, Operand(reg, ASR, kSmiTagSize), s);
   }
-  void SmiUntag(Register dst, Register src) {
-    mov(dst, Operand(src, ASR, kSmiTagSize));
+  void SmiUntag(Register dst, Register src, SBit s = LeaveCC) {
+    mov(dst, Operand(src, ASR, kSmiTagSize), s);
   }
 
   // Jump the register contains a smi.
@@ -791,6 +849,9 @@
   void AbortIfSmi(Register object);
   void AbortIfNotSmi(Register object);
 
+  // Abort execution if argument is a string. Used in debug code.
+  void AbortIfNotString(Register object);
+
   // Abort execution if argument is not the root value with the given index.
   void AbortIfNotRootValue(Register src,
                            Heap::RootListIndex root_value_index,
@@ -871,10 +932,19 @@
                            Register scratch1,
                            Register scratch2);
 
+  // Compute memory operands for safepoint stack slots.
+  static int SafepointRegisterStackIndex(int reg_code);
+  MemOperand SafepointRegisterSlot(Register reg);
+  MemOperand SafepointRegistersAndDoublesSlot(Register reg);
+
   bool generating_stub_;
   bool allow_stub_calls_;
   // This handle will be patched with the code object on installation.
   Handle<Object> code_object_;
+
+  // Needs access to SafepointRegisterStackIndex for optimized frame
+  // traversal.
+  friend class OptimizedFrame;
 };
 
 
diff --git a/src/arm/regexp-macro-assembler-arm.cc b/src/arm/regexp-macro-assembler-arm.cc
index 94da042..1f6ed67 100644
--- a/src/arm/regexp-macro-assembler-arm.cc
+++ b/src/arm/regexp-macro-assembler-arm.cc
@@ -57,48 +57,57 @@
  * - r13/sp : points to tip of C stack.
  *
  * The remaining registers are free for computations.
- *
  * Each call to a public method should retain this convention.
+ *
  * The stack will have the following structure:
- *       - direct_call        (if 1, direct call from JavaScript code, if 0 call
- *                             through the runtime system)
- *       - stack_area_base    (High end of the memory area to use as
- *                             backtracking stack)
- *       - int* capture_array (int[num_saved_registers_], for output).
- *       --- sp when called ---
- *       - link address
- *       - backup of registers r4..r11
- *       - end of input       (Address of end of string)
- *       - start of input     (Address of first character in string)
- *       - start index        (character index of start)
- *       --- frame pointer ----
- *       - void* input_string (location of a handle containing the string)
- *       - Offset of location before start of input (effectively character
- *         position -1). Used to initialize capture registers to a non-position.
- *       - At start (if 1, we are starting at the start of the
- *         string, otherwise 0)
- *       - register 0         (Only positions must be stored in the first
- *       - register 1          num_saved_registers_ registers)
- *       - ...
- *       - register num_registers-1
- *       --- sp ---
+ *  - fp[48]  direct_call  (if 1, direct call from JavaScript code,
+ *                          if 0, call through the runtime system).
+ *  - fp[44]  stack_area_base (High end of the memory area to use as
+ *                             backtracking stack).
+ *  - fp[40]  int* capture_array (int[num_saved_registers_], for output).
+ *  - fp[36]  secondary link/return address used by native call.
+ *  --- sp when called ---
+ *  - fp[32]  return address (lr).
+ *  - fp[28]  old frame pointer (r11).
+ *  - fp[0..24]  backup of registers r4..r10.
+ *  --- frame pointer ----
+ *  - fp[-4]  end of input       (Address of end of string).
+ *  - fp[-8]  start of input     (Address of first character in string).
+ *  - fp[-12] start index        (character index of start).
+ *  - fp[-16] void* input_string (location of a handle containing the string).
+ *  - fp[-20] Offset of location before start of input (effectively character
+ *            position -1). Used to initialize capture registers to a
+ *            non-position.
+ *  - fp[-24] At start (if 1, we are starting at the start of the
+ *    string, otherwise 0)
+ *  - fp[-28] register 0         (Only positions must be stored in the first
+ *  -         register 1          num_saved_registers_ registers)
+ *  -         ...
+ *  -         register num_registers-1
+ *  --- sp ---
  *
  * The first num_saved_registers_ registers are initialized to point to
  * "character -1" in the string (i.e., char_size() bytes before the first
  * character of the string). The remaining registers start out as garbage.
  *
  * The data up to the return address must be placed there by the calling
- * code, by calling the code entry as cast to a function with the signature:
+ * code and the remaining arguments are passed in registers, e.g. by calling the
+ * code entry as cast to a function with the signature:
  * int (*match)(String* input_string,
  *              int start_index,
  *              Address start,
  *              Address end,
+ *              Address secondary_return_address,  // Only used by native call.
  *              int* capture_output_array,
- *              bool at_start,
  *              byte* stack_area_base,
- *              bool direct_call)
+ *              bool direct_call = false)
  * The call is performed by NativeRegExpMacroAssembler::Execute()
- * (in regexp-macro-assembler.cc).
+ * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro
+ * in arm/simulator-arm.h.
+ * When calling as a non-direct call (i.e., from C++ code), the return address
+ * area is overwritten with the LR register by the RegExp code. When doing a
+ * direct call from generated code, the return address is placed there by
+ * the calling code, as in a normal exit frame.
  */
 
 #define __ ACCESS_MASM(masm_)
@@ -598,16 +607,17 @@
 
   // Entry code:
   __ bind(&entry_label_);
-  // Push Link register.
   // Push arguments
   // Save callee-save registers.
   // Start new stack frame.
+  // Store link register in existing stack-cell.
   // Order here should correspond to order of offset constants in header file.
   RegList registers_to_retain = r4.bit() | r5.bit() | r6.bit() |
       r7.bit() | r8.bit() | r9.bit() | r10.bit() | fp.bit();
   RegList argument_registers = r0.bit() | r1.bit() | r2.bit() | r3.bit();
   __ stm(db_w, sp, argument_registers | registers_to_retain | lr.bit());
-  // Set frame pointer just above the arguments.
+  // Set frame pointer in space for it if this is not a direct call
+  // from generated code.
   __ add(frame_pointer(), sp, Operand(4 * kPointerSize));
   __ push(r0);  // Make room for "position - 1" constant (value is irrelevant).
   __ push(r0);  // Make room for "at start" constant (value is irrelevant).
@@ -764,10 +774,9 @@
   if (stack_overflow_label_.is_linked()) {
     SafeCallTarget(&stack_overflow_label_);
     // Reached if the backtrack-stack limit has been hit.
-
     Label grow_failed;
 
-    // Call GrowStack(backtrack_stackpointer())
+    // Call GrowStack(backtrack_stackpointer(), &stack_base)
     static const int num_arguments = 2;
     __ PrepareCallCFunction(num_arguments, r0);
     __ mov(r0, backtrack_stackpointer());
diff --git a/src/arm/regexp-macro-assembler-arm.h b/src/arm/regexp-macro-assembler-arm.h
index b487ba5..d9d0b35 100644
--- a/src/arm/regexp-macro-assembler-arm.h
+++ b/src/arm/regexp-macro-assembler-arm.h
@@ -122,8 +122,9 @@
   static const int kStoredRegisters = kFramePointer;
   // Return address (stored from link register, read into pc on return).
   static const int kReturnAddress = kStoredRegisters + 8 * kPointerSize;
+  static const int kSecondaryReturnAddress = kReturnAddress + kPointerSize;
   // Stack parameters placed by caller.
-  static const int kRegisterOutput = kReturnAddress + kPointerSize;
+  static const int kRegisterOutput = kSecondaryReturnAddress + kPointerSize;
   static const int kStackHighEnd = kRegisterOutput + kPointerSize;
   static const int kDirectCall = kStackHighEnd + kPointerSize;
 
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index 8104747..f475a18 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -1005,7 +1005,9 @@
     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
     return *ptr;
   }
-  PrintF("Unaligned read at 0x%08x, pc=%p\n", addr, instr);
+  PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
+         addr,
+         reinterpret_cast<intptr_t>(instr));
   UNIMPLEMENTED();
   return 0;
 #endif
@@ -1023,7 +1025,9 @@
     *ptr = value;
     return;
   }
-  PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr);
+  PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
+         addr,
+         reinterpret_cast<intptr_t>(instr));
   UNIMPLEMENTED();
 #endif
 }
@@ -1038,7 +1042,9 @@
     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
     return *ptr;
   }
-  PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr, instr);
+  PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
+         addr,
+         reinterpret_cast<intptr_t>(instr));
   UNIMPLEMENTED();
   return 0;
 #endif
@@ -1072,7 +1078,9 @@
     *ptr = value;
     return;
   }
-  PrintF("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr, instr);
+  PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
+         addr,
+         reinterpret_cast<intptr_t>(instr));
   UNIMPLEMENTED();
 #endif
 }
@@ -1089,7 +1097,9 @@
     *ptr = value;
     return;
   }
-  PrintF("Unaligned halfword write at 0x%08x, pc=%p\n", addr, instr);
+  PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
+         addr,
+         reinterpret_cast<intptr_t>(instr));
   UNIMPLEMENTED();
 #endif
 }
@@ -1531,7 +1541,11 @@
 
 // This signature supports direct call in to API function native callback
 // (refer to InvocationCallback in v8.h).
-typedef v8::Handle<v8::Value> (*SimulatorRuntimeApiCall)(int32_t arg0);
+typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
+
+// This signature supports direct call to accessor getter callback.
+typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0,
+                                                                  int32_t arg1);
 
 // Software interrupt instructions are used by the simulator to call into the
 // C-based V8 runtime.
@@ -1572,14 +1586,12 @@
         CHECK(stack_aligned);
         double result = target(arg0, arg1, arg2, arg3);
         SetFpResult(result);
-      } else if (redirection->type() == ExternalReference::DIRECT_CALL) {
-        SimulatorRuntimeApiCall target =
-            reinterpret_cast<SimulatorRuntimeApiCall>(external);
+      } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
+        SimulatorRuntimeDirectApiCall target =
+            reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
-          PrintF(
-              "Call to host function at %p args %08x",
-              FUNCTION_ADDR(target),
-              arg0);
+          PrintF("Call to host function at %p args %08x",
+              FUNCTION_ADDR(target), arg0);
           if (!stack_aligned) {
             PrintF(" with unaligned stack %08x\n", get_register(sp));
           }
@@ -1591,6 +1603,23 @@
           PrintF("Returned %p\n", reinterpret_cast<void *>(*result));
         }
         set_register(r0, (int32_t) *result);
+      } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
+        SimulatorRuntimeDirectGetterCall target =
+            reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
+        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
+          PrintF("Call to host function at %p args %08x %08x",
+              FUNCTION_ADDR(target), arg0, arg1);
+          if (!stack_aligned) {
+            PrintF(" with unaligned stack %08x\n", get_register(sp));
+          }
+          PrintF("\n");
+        }
+        CHECK(stack_aligned);
+        v8::Handle<v8::Value> result = target(arg0, arg1);
+        if (::v8::internal::FLAG_trace_sim) {
+          PrintF("Returned %p\n", reinterpret_cast<void *>(*result));
+        }
+        set_register(r0, (int32_t) *result);
       } else {
         // builtin call.
         ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);
@@ -2535,6 +2564,7 @@
       double dn_value = get_double_from_d_register(vn);
       double dm_value = get_double_from_d_register(vm);
       double dd_value = dn_value / dm_value;
+      div_zero_vfp_flag_ = (dm_value == 0);
       set_d_register_from_double(vd, dd_value);
     } else {
       UNIMPLEMENTED();  // Not used by V8.
@@ -2769,14 +2799,17 @@
 
     inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
 
+    double abs_diff =
+      unsigned_integer ? fabs(val - static_cast<uint32_t>(temp))
+                       : fabs(val - temp);
+
+    inexact_vfp_flag_ = (abs_diff != 0);
+
     if (inv_op_vfp_flag_) {
       temp = VFPConversionSaturate(val, unsigned_integer);
     } else {
       switch (mode) {
         case RN: {
-          double abs_diff =
-            unsigned_integer ? fabs(val - static_cast<uint32_t>(temp))
-                             : fabs(val - temp);
           int val_sign = (val > 0) ? 1 : -1;
           if (abs_diff > 0.5) {
             temp += val_sign;
diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h
index 5256ae3..bdf1f8a 100644
--- a/src/arm/simulator-arm.h
+++ b/src/arm/simulator-arm.h
@@ -48,10 +48,16 @@
 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
   (entry(p0, p1, p2, p3, p4))
 
-// Call the generated regexp code directly. The entry function pointer should
-// expect seven int/pointer sized arguments and return an int.
+typedef int (*arm_regexp_matcher)(String*, int, const byte*, const byte*,
+                                  void*, int*, Address, int);
+
+
+// Call the generated regexp code directly. The code at the entry address
+// should act as a function matching the type arm_regexp_matcher.
+// The fifth argument is a dummy that reserves the space used for
+// the return address added by the ExitFrame in native calls.
 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
-  (entry(p0, p1, p2, p3, p4, p5, p6))
+  (FUNCTION_CAST<arm_regexp_matcher>(entry)(p0, p1, p2, p3, NULL, p4, p5, p6))
 
 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
   (reinterpret_cast<TryCatch*>(try_catch_address))
@@ -362,8 +368,7 @@
       FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4))
 
 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
-  Simulator::current()->Call( \
-      FUNCTION_ADDR(entry), 7, p0, p1, p2, p3, p4, p5, p6)
+  Simulator::current()->Call(entry, 8, p0, p1, p2, p3, NULL, p4, p5, p6)
 
 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
   try_catch_address == \
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 9ef6115..60a11f3 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -655,12 +655,10 @@
   // already generated). Do not allow the assembler to perform a
   // garbage collection but instead return the allocation failure
   // object.
-  MaybeObject* result = masm->TryCallApiFunctionAndReturn(
-      &fun, argc + kFastApiCallArguments + 1);
-  if (result->IsFailure()) {
-    return result;
-  }
-  return Heap::undefined_value();
+  const int kStackUnwindSpace = argc + kFastApiCallArguments + 1;
+  ExternalReference ref =
+      ExternalReference(&fun, ExternalReference::DIRECT_API_CALL);
+  return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace);
 }
 
 class CallInterceptorCompiler BASE_EMBEDDED {
@@ -1245,18 +1243,38 @@
       CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3,
                       name, miss);
 
-  // Push the arguments on the JS stack of the caller.
-  __ push(receiver);  // Receiver.
-  __ mov(scratch3, Operand(Handle<AccessorInfo>(callback)));  // callback data
-  __ ldr(ip, FieldMemOperand(scratch3, AccessorInfo::kDataOffset));
-  __ Push(reg, ip, scratch3, name_reg);
+  // Build AccessorInfo::args_ list on the stack and push property name below
+  // the exit frame to make GC aware of them and store pointers to them.
+  __ push(receiver);
+  __ mov(scratch2, sp);  // scratch2 = AccessorInfo::args_
+  Handle<AccessorInfo> callback_handle(callback);
+  if (Heap::InNewSpace(callback_handle->data())) {
+    __ Move(scratch3, callback_handle);
+    __ ldr(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset));
+  } else {
+    __ Move(scratch3, Handle<Object>(callback_handle->data()));
+  }
+  __ Push(reg, scratch3, name_reg);
+  __ mov(r0, sp);  // r0 = Handle<String>
 
-  // Do tail-call to the runtime system.
-  ExternalReference load_callback_property =
-      ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
-  __ TailCallExternalReference(load_callback_property, 5, 1);
+  Address getter_address = v8::ToCData<Address>(callback->getter());
+  ApiFunction fun(getter_address);
 
-  return Heap::undefined_value();  // Success.
+  const int kApiStackSpace = 1;
+  __ EnterExitFrame(false, kApiStackSpace);
+  // Create AccessorInfo instance on the stack above the exit frame with
+  // scratch2 (internal::Object **args_) as the data.
+  __ str(scratch2, MemOperand(sp, 1 * kPointerSize));
+  __ add(r1, sp, Operand(1 * kPointerSize));  // r1 = AccessorInfo&
+
+  // Emitting a stub call may try to allocate (if the code is not
+  // already generated).  Do not allow the assembler to perform a
+  // garbage collection but instead return the allocation failure
+  // object.
+  const int kStackUnwindSpace = 4;
+  ExternalReference ref =
+      ExternalReference(&fun, ExternalReference::DIRECT_GETTER_CALL);
+  return masm()->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace);
 }
 
 
@@ -2332,8 +2350,9 @@
       break;
 
     case STRING_CHECK:
-      if (!function->IsBuiltin()) {
-        // Calling non-builtins with a value as receiver requires boxing.
+      if (!function->IsBuiltin() && !function_info->strict_mode()) {
+        // Calling non-strict non-builtins with a value as the receiver
+        // requires boxing.
         __ jmp(&miss);
       } else {
         // Check that the object is a two-byte string or a symbol.
@@ -2348,8 +2367,9 @@
       break;
 
     case NUMBER_CHECK: {
-      if (!function->IsBuiltin()) {
-        // Calling non-builtins with a value as receiver requires boxing.
+      if (!function->IsBuiltin() && !function_info->strict_mode()) {
+        // Calling non-strict non-builtins with a value as the receiver
+        // requires boxing.
         __ jmp(&miss);
       } else {
         Label fast;
@@ -2369,8 +2389,9 @@
     }
 
     case BOOLEAN_CHECK: {
-      if (!function->IsBuiltin()) {
-        // Calling non-builtins with a value as receiver requires boxing.
+      if (!function->IsBuiltin() && !function_info->strict_mode()) {
+        // Calling non-strict non-builtins with a value as the receiver
+        // requires boxing.
         __ jmp(&miss);
       } else {
         Label fast;
@@ -2650,10 +2671,13 @@
 
   __ Push(r1, r2, r0);  // Receiver, name, value.
 
+  __ mov(r0, Operand(Smi::FromInt(strict_mode_)));
+  __ push(r0);  // strict mode
+
   // Do tail-call to the runtime system.
   ExternalReference store_ic_property =
       ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
-  __ TailCallExternalReference(store_ic_property, 3, 1);
+  __ TailCallExternalReference(store_ic_property, 4, 1);
 
   // Handle store cache miss.
   __ bind(&miss);
@@ -3259,6 +3283,47 @@
 }
 
 
+MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray(
+    JSObject* receiver) {
+  // ----------- S t a t e -------------
+  //  -- r0    : value
+  //  -- r1    : key
+  //  -- r2    : receiver
+  //  -- r3    : scratch
+  //  -- r4    : scratch
+  //  -- r5    : scratch
+  //  -- r6    : scratch
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+
+  // Check that the map matches.
+  __ CheckMap(r2, r6, Handle<Map>(receiver->map()), &miss, false);
+
+  GenerateFastPixelArrayStore(masm(),
+                              r2,
+                              r1,
+                              r0,
+                              r3,
+                              r4,
+                              r5,
+                              r6,
+                              true,
+                              true,
+                              &miss,
+                              &miss,
+                              NULL,
+                              &miss);
+
+  __ bind(&miss);
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(NORMAL, NULL);
+}
+
+
 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
   // ----------- S t a t e -------------
   //  -- r0    : argc
@@ -3994,7 +4059,12 @@
   // Push receiver, key and value for runtime call.
   __ Push(r2, r1, r0);
 
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ mov(r1, Operand(Smi::FromInt(NONE)));  // PropertyAttributes
+  __ mov(r0, Operand(Smi::FromInt(
+      Code::ExtractExtraICStateFromFlags(flags) & kStrictMode)));
+  __ Push(r1, r0);
+
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 
   return GetCode(flags);
 }
diff --git a/src/arm/virtual-frame-arm.cc b/src/arm/virtual-frame-arm.cc
index b4b518c..544e405 100644
--- a/src/arm/virtual-frame-arm.cc
+++ b/src/arm/virtual-frame-arm.cc
@@ -332,9 +332,9 @@
 void VirtualFrame::CallStoreIC(Handle<String> name,
                                bool is_contextual,
                                StrictModeFlag strict_mode) {
-  Handle<Code> ic(Builtins::builtin(strict_mode == kStrictMode
-      ? Builtins::StoreIC_Initialize_Strict
-      : Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode == kStrictMode) ? Builtins::StoreIC_Initialize_Strict
+                                   : Builtins::StoreIC_Initialize));
   PopToR0();
   RelocInfo::Mode mode;
   if (is_contextual) {
@@ -359,8 +359,10 @@
 }
 
 
-void VirtualFrame::CallKeyedStoreIC() {
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+void VirtualFrame::CallKeyedStoreIC(StrictModeFlag strict_mode) {
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
+                                   : Builtins::KeyedStoreIC_Initialize));
   PopToR1R0();
   SpillAll();
   EmitPop(r2);
diff --git a/src/arm/virtual-frame-arm.h b/src/arm/virtual-frame-arm.h
index b6e794a..76470bd 100644
--- a/src/arm/virtual-frame-arm.h
+++ b/src/arm/virtual-frame-arm.h
@@ -303,7 +303,7 @@
 
   // Call keyed store IC. Value, key and receiver are on the stack. All three
   // are consumed. Result is returned in r0.
-  void CallKeyedStoreIC();
+  void CallKeyedStoreIC(StrictModeFlag strict_mode);
 
   // Call into an IC stub given the number of arguments it removes
   // from the stack.  Register arguments to the IC stub are implicit,
diff --git a/src/array.js b/src/array.js
index 1298434..6ed1476 100644
--- a/src/array.js
+++ b/src/array.js
@@ -33,7 +33,7 @@
 
 // Global list of arrays visited during toString, toLocaleString and
 // join invocations.
-var visited_arrays = new $Array();
+var visited_arrays = new InternalArray();
 
 
 // Gets a sorted array of array keys.  Useful for operations on sparse
@@ -73,7 +73,7 @@
   var last_key = -1;
   var keys_length = keys.length;
 
-  var elements = new $Array(keys_length);
+  var elements = new InternalArray(keys_length);
   var elements_length = 0;
 
   for (var i = 0; i < keys_length; i++) {
@@ -122,7 +122,7 @@
     }
 
     // Construct an array for the elements.
-    var elements = new $Array(length);
+    var elements = new InternalArray(length);
 
     // We pull the empty separator check outside the loop for speed!
     if (separator.length == 0) {
@@ -140,7 +140,7 @@
       return %StringBuilderConcat(elements, elements_length, '');
     }
     // Non-empty separator case.
-    // If the first element is a number then use the heuristic that the 
+    // If the first element is a number then use the heuristic that the
     // remaining elements are also likely to be numbers.
     if (!IS_NUMBER(array[0])) {
       for (var i = 0; i < length; i++) {
@@ -148,7 +148,7 @@
         if (!IS_STRING(e)) e = convert(e);
         elements[i] = e;
       }
-    } else { 
+    } else {
       for (var i = 0; i < length; i++) {
         var e = array[i];
         if (IS_NUMBER(e)) elements[i] = %_NumberToString(e);
@@ -157,19 +157,11 @@
           elements[i] = e;
         }
       }
-    }   
-    var result = %_FastAsciiArrayJoin(elements, separator);
-    if (!IS_UNDEFINED(result)) return result;   
-
-    var length2 = (length << 1) - 1;
-    var j = length2;
-    var i = length;
-    elements[--j] = elements[--i];
-    while (i > 0) {
-      elements[--j] = separator;
-      elements[--j] = elements[--i];
     }
-    return %StringBuilderConcat(elements, length2, '');    
+    var result = %_FastAsciiArrayJoin(elements, separator);
+    if (!IS_UNDEFINED(result)) return result;
+
+    return %StringBuilderJoin(elements, length, separator);
   } finally {
     // Make sure to remove the last element of the visited array no
     // matter what happens.
@@ -179,7 +171,7 @@
 
 
 function ConvertToString(x) {
-  // Assumes x is a non-string. 
+  // Assumes x is a non-string.
   if (IS_NUMBER(x)) return %_NumberToString(x);
   if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
   return (IS_NULL_OR_UNDEFINED(x)) ? '' : %ToString(%DefaultString(x));
@@ -249,7 +241,7 @@
 // special array operations to handle sparse arrays in a sensible fashion.
 function SmartMove(array, start_i, del_count, len, num_additional_args) {
   // Move data to new array.
-  var new_array = new $Array(len - del_count + num_additional_args);
+  var new_array = new InternalArray(len - del_count + num_additional_args);
   var intervals = %GetArrayKeys(array, len);
   var length = intervals.length;
   for (var k = 0; k < length; k++) {
@@ -426,9 +418,8 @@
 
 
 function ArrayConcat(arg1) {  // length == 1
-  // TODO: can we just use arguments?
   var arg_count = %_ArgumentsLength();
-  var arrays = new $Array(1 + arg_count);
+  var arrays = new InternalArray(1 + arg_count);
   arrays[0] = this;
   for (var i = 0; i < arg_count; i++) {
     arrays[i + 1] = %_Arguments(i);
@@ -934,7 +925,9 @@
   for (var i = 0; i < length; i++) {
     var current = this[i];
     if (!IS_UNDEFINED(current) || i in this) {
-      if (f.call(receiver, current, i, this)) result[result_length++] = current;
+      if (f.call(receiver, current, i, this)) {
+        result[result_length++] = current;
+      }
     }
   }
   return result;
@@ -999,13 +992,15 @@
   // Pull out the length so that modifications to the length in the
   // loop will not affect the looping.
   var length = TO_UINT32(this.length);
-  var result = new $Array(length);
+  var result = new $Array();
+  var accumulator = new InternalArray(length);
   for (var i = 0; i < length; i++) {
     var current = this[i];
     if (!IS_UNDEFINED(current) || i in this) {
-      result[i] = f.call(receiver, current, i, this);
+      accumulator[i] = f.call(receiver, current, i, this);
     }
   }
+  %MoveArrayContents(accumulator, result);
   return result;
 }
 
@@ -1026,13 +1021,13 @@
   }
   var min = index;
   var max = length;
-  if (UseSparseVariant(this, length, true)) {
+  if (UseSparseVariant(this, length, IS_ARRAY(this))) {
     var intervals = %GetArrayKeys(this, length);
     if (intervals.length == 2 && intervals[0] < 0) {
       // A single interval.
       var intervalMin = -(intervals[0] + 1);
       var intervalMax = intervalMin + intervals[1];
-      min = MAX(min, intervalMin);
+      if (min < intervalMin) min = intervalMin;
       max = intervalMax;  // Capped by length already.
       // Fall through to loop below.
     } else {
@@ -1082,13 +1077,13 @@
   }
   var min = 0;
   var max = index;
-  if (UseSparseVariant(this, length, true)) {
+  if (UseSparseVariant(this, length, IS_ARRAY(this))) {
     var intervals = %GetArrayKeys(this, index + 1);
     if (intervals.length == 2 && intervals[0] < 0) {
       // A single interval.
       var intervalMin = -(intervals[0] + 1);
       var intervalMax = intervalMin + intervals[1];
-      min = MAX(min, intervalMin);
+      if (min < intervalMin) min = intervalMin;
       max = intervalMax;  // Capped by index already.
       // Fall through to loop below.
     } else {
@@ -1234,6 +1229,20 @@
   ));
 
   %FinishArrayPrototypeSetup($Array.prototype);
+
+  // The internal Array prototype doesn't need to be fancy, since it's never
+  // exposed to user code, so no hidden prototypes or DONT_ENUM attributes
+  // are necessary.
+  // The null __proto__ ensures that we never inherit any user created
+  // getters or setters from, e.g., Object.prototype.
+  InternalArray.prototype.__proto__ = null;
+  // Adding only the functions that are actually used, and a toString.
+  InternalArray.prototype.join = getFunction("join", ArrayJoin);
+  InternalArray.prototype.pop = getFunction("pop", ArrayPop);
+  InternalArray.prototype.push = getFunction("push", ArrayPush);
+  InternalArray.prototype.toString = function() {
+    return "Internal Array, length " + this.length;
+  };
 }
 
 
diff --git a/src/assembler.cc b/src/assembler.cc
index ef2094f..b0b44fd 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -68,7 +68,7 @@
 const double DoubleConstant::one_half = 0.5;
 const double DoubleConstant::minus_zero = -0.0;
 const double DoubleConstant::negative_infinity = -V8_INFINITY;
-
+const char* RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
 
 // -----------------------------------------------------------------------------
 // Implementation of Label
@@ -228,6 +228,7 @@
     WriteTaggedPC(pc_delta, kEmbeddedObjectTag);
   } else if (rmode == RelocInfo::CODE_TARGET) {
     WriteTaggedPC(pc_delta, kCodeTargetTag);
+    ASSERT(begin_pos - pos_ <= RelocInfo::kMaxCallSize);
   } else if (RelocInfo::IsPosition(rmode)) {
     // Use signed delta-encoding for data.
     intptr_t data_delta = rinfo->data() - last_data_;
@@ -251,6 +252,7 @@
     WriteExtraTaggedPC(pc_delta, kPCJumpTag);
     WriteExtraTaggedData(rinfo->data() - last_data_, kCommentTag);
     last_data_ = rinfo->data();
+    ASSERT(begin_pos - pos_ >= RelocInfo::kMinRelocCommentSize);
   } else {
     // For all other modes we simply use the mode as the extra tag.
     // None of these modes need a data component.
@@ -814,6 +816,39 @@
 }
 
 
+static double math_sin_double(double x) {
+  return sin(x);
+}
+
+
+static double math_cos_double(double x) {
+  return cos(x);
+}
+
+
+static double math_log_double(double x) {
+  return log(x);
+}
+
+
+ExternalReference ExternalReference::math_sin_double_function() {
+  return ExternalReference(Redirect(FUNCTION_ADDR(math_sin_double),
+                                    FP_RETURN_CALL));
+}
+
+
+ExternalReference ExternalReference::math_cos_double_function() {
+  return ExternalReference(Redirect(FUNCTION_ADDR(math_cos_double),
+                                    FP_RETURN_CALL));
+}
+
+
+ExternalReference ExternalReference::math_log_double_function() {
+  return ExternalReference(Redirect(FUNCTION_ADDR(math_log_double),
+                                    FP_RETURN_CALL));
+}
+
+
 // Helper function to compute x^y, where y is known to be an
 // integer. Uses binary decomposition to limit the number of
 // multiplications; see the discussion in "Hacker's Delight" by Henry
@@ -850,12 +885,14 @@
 
 
 ExternalReference ExternalReference::power_double_double_function() {
-  return ExternalReference(Redirect(FUNCTION_ADDR(power_double_double)));
+  return ExternalReference(Redirect(FUNCTION_ADDR(power_double_double),
+                                    FP_RETURN_CALL));
 }
 
 
 ExternalReference ExternalReference::power_double_int_function() {
-  return ExternalReference(Redirect(FUNCTION_ADDR(power_double_int)));
+  return ExternalReference(Redirect(FUNCTION_ADDR(power_double_int),
+                                    FP_RETURN_CALL));
 }
 
 
diff --git a/src/assembler.h b/src/assembler.h
index b089b09..8ebbfad 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -178,6 +178,20 @@
   // invalid/uninitialized position value.
   static const int kNoPosition = -1;
 
+  // This string is used to add padding comments to the reloc info in cases
+  // 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;
+
+  // 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
+  // comment.
+  static const int kMinRelocCommentSize = 3 + kPointerSize;
+
+  // The maximum size for a call instruction including pc-jump.
+  static const int kMaxCallSize = 6;
+
   enum Mode {
     // Please note the order is important (see IsCodeTarget, IsGCRelocMode).
     CONSTRUCT_CALL,  // code target that is a call to a JavaScript constructor.
@@ -467,21 +481,22 @@
 class ExternalReference BASE_EMBEDDED {
  public:
   // Used in the simulator to support different native api calls.
-  //
-  // BUILTIN_CALL - builtin call.
-  // MaybeObject* f(v8::internal::Arguments).
-  //
-  // FP_RETURN_CALL - builtin call that returns floating point.
-  // double f(double, double).
-  //
-  // DIRECT_CALL - direct call to API function native callback
-  // from generated code.
-  // Handle<Value> f(v8::Arguments&)
-  //
   enum Type {
+    // Builtin call.
+    // MaybeObject* f(v8::internal::Arguments).
     BUILTIN_CALL,  // default
+
+    // Builtin call that returns floating point.
+    // double f(double, double).
     FP_RETURN_CALL,
-    DIRECT_CALL
+
+    // Direct call to API function callback.
+    // Handle<Value> f(v8::Arguments&)
+    DIRECT_API_CALL,
+
+    // Direct call to accessor getter callback.
+    // Handle<value> f(Local<String> property, AccessorInfo& info)
+    DIRECT_GETTER_CALL
   };
 
   typedef void* ExternalReferenceRedirector(void* original, Type type);
@@ -576,6 +591,10 @@
   static ExternalReference address_of_minus_zero();
   static ExternalReference address_of_negative_infinity();
 
+  static ExternalReference math_sin_double_function();
+  static ExternalReference math_cos_double_function();
+  static ExternalReference math_log_double_function();
+
   Address address() const {return reinterpret_cast<Address>(address_);}
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 415d2dd..8cd29b2 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -1240,6 +1240,43 @@
     global_context()->set_opaque_reference_function(*opaque_reference_fun);
   }
 
+  {  // --- I n t e r n a l   A r r a y ---
+    // An array constructor on the builtins object that works like
+    // the public Array constructor, except that its prototype
+    // doesn't inherit from Object.prototype.
+    // To be used only for internal work by builtins. Instances
+    // must not be leaked to user code.
+    // Only works correctly when called as a constructor. The normal
+    // Array code uses Array.prototype as prototype when called as
+    // a function.
+    Handle<JSFunction> array_function =
+        InstallFunction(builtins,
+                        "InternalArray",
+                        JS_ARRAY_TYPE,
+                        JSArray::kSize,
+                        Top::initial_object_prototype(),
+                        Builtins::ArrayCode,
+                        true);
+    Handle<JSObject> prototype =
+        Factory::NewJSObject(Top::object_function(), TENURED);
+    SetPrototype(array_function, prototype);
+
+    array_function->shared()->set_construct_stub(
+        Builtins::builtin(Builtins::ArrayConstructCode));
+    array_function->shared()->DontAdaptArguments();
+
+    // Make "length" magic on instances.
+    Handle<DescriptorArray> array_descriptors =
+        Factory::CopyAppendProxyDescriptor(
+            Factory::empty_descriptor_array(),
+            Factory::length_symbol(),
+            Factory::NewProxy(&Accessors::ArrayLength),
+            static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE));
+
+    array_function->initial_map()->set_instance_descriptors(
+        *array_descriptors);
+  }
+
   if (FLAG_disable_native_files) {
     PrintF("Warning: Running without installed natives!\n");
     return true;
@@ -1358,6 +1395,7 @@
     global_context()->set_regexp_result_map(*initial_map);
   }
 
+
 #ifdef DEBUG
   builtins->Verify();
 #endif
diff --git a/src/builtins.cc b/src/builtins.cc
index 8fdc1b1..01e8deb 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -1328,12 +1328,12 @@
 
 
 static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
-  StoreIC::GenerateMegamorphic(masm, StoreIC::kStoreICNonStrict);
+  StoreIC::GenerateMegamorphic(masm, kNonStrictMode);
 }
 
 
 static void Generate_StoreIC_Megamorphic_Strict(MacroAssembler* masm) {
-  StoreIC::GenerateMegamorphic(masm, StoreIC::kStoreICStrict);
+  StoreIC::GenerateMegamorphic(masm, kStrictMode);
 }
 
 
@@ -1348,17 +1348,22 @@
 
 
 static void Generate_StoreIC_GlobalProxy(MacroAssembler* masm) {
-  StoreIC::GenerateGlobalProxy(masm);
+  StoreIC::GenerateGlobalProxy(masm, kNonStrictMode);
 }
 
 
 static void Generate_StoreIC_GlobalProxy_Strict(MacroAssembler* masm) {
-  StoreIC::GenerateGlobalProxy(masm);
+  StoreIC::GenerateGlobalProxy(masm, kStrictMode);
 }
 
 
 static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
-  KeyedStoreIC::GenerateGeneric(masm);
+  KeyedStoreIC::GenerateGeneric(masm, kNonStrictMode);
+}
+
+
+static void Generate_KeyedStoreIC_Generic_Strict(MacroAssembler* masm) {
+  KeyedStoreIC::GenerateGeneric(masm, kStrictMode);
 }
 
 
@@ -1372,6 +1377,11 @@
 }
 
 
+static void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) {
+  KeyedStoreIC::GenerateInitialize(masm);
+}
+
+
 #ifdef ENABLE_DEBUGGER_SUPPORT
 static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
   Debug::GenerateLoadICDebugBreak(masm);
diff --git a/src/builtins.h b/src/builtins.h
index ada23a7..5ea4665 100644
--- a/src/builtins.h
+++ b/src/builtins.h
@@ -62,111 +62,116 @@
 
 
 // Define list of builtins implemented in assembly.
-#define BUILTIN_LIST_A(V)                                                 \
-  V(ArgumentsAdaptorTrampoline, BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(JSConstructCall,            BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(JSConstructStubCountdown,   BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(JSConstructStubGeneric,     BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(JSConstructStubApi,         BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(JSEntryTrampoline,          BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(JSConstructEntryTrampoline, BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(LazyCompile,                BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(LazyRecompile,              BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(NotifyDeoptimized,          BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(NotifyLazyDeoptimized,      BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(NotifyOSR,                  BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  V(LoadIC_Miss,                BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(KeyedLoadIC_Miss,           BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(StoreIC_Miss,               BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(KeyedStoreIC_Miss,          BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  V(LoadIC_Initialize,          LOAD_IC, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(LoadIC_PreMonomorphic,      LOAD_IC, PREMONOMORPHIC,                  \
-                                Code::kNoExtraICState)                    \
-  V(LoadIC_Normal,              LOAD_IC, MONOMORPHIC,                     \
-                                Code::kNoExtraICState)                    \
-  V(LoadIC_ArrayLength,         LOAD_IC, MONOMORPHIC,                     \
-                                Code::kNoExtraICState)                    \
-  V(LoadIC_StringLength,        LOAD_IC, MONOMORPHIC,                     \
-                                Code::kNoExtraICState)                    \
-  V(LoadIC_StringWrapperLength, LOAD_IC, MONOMORPHIC,                     \
-                                Code::kNoExtraICState)                    \
-  V(LoadIC_FunctionPrototype,   LOAD_IC, MONOMORPHIC,                     \
-                                Code::kNoExtraICState)                    \
-  V(LoadIC_Megamorphic,         LOAD_IC, MEGAMORPHIC,                     \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  V(KeyedLoadIC_Initialize,     KEYED_LOAD_IC, UNINITIALIZED,             \
-                                Code::kNoExtraICState)                    \
-  V(KeyedLoadIC_PreMonomorphic, KEYED_LOAD_IC, PREMONOMORPHIC,            \
-                                Code::kNoExtraICState)                    \
-  V(KeyedLoadIC_Generic,        KEYED_LOAD_IC, MEGAMORPHIC,               \
-                                Code::kNoExtraICState)                    \
-  V(KeyedLoadIC_String,         KEYED_LOAD_IC, MEGAMORPHIC,               \
-                                Code::kNoExtraICState)                    \
-  V(KeyedLoadIC_IndexedInterceptor,         KEYED_LOAD_IC, MEGAMORPHIC,   \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  V(StoreIC_Initialize,         STORE_IC, UNINITIALIZED,                  \
-                                Code::kNoExtraICState)                    \
-  V(StoreIC_ArrayLength,        STORE_IC, MONOMORPHIC,                    \
-                                Code::kNoExtraICState)                    \
-  V(StoreIC_Normal,             STORE_IC, MONOMORPHIC,                    \
-                                Code::kNoExtraICState)                    \
-  V(StoreIC_Megamorphic,        STORE_IC, MEGAMORPHIC,                    \
-                                Code::kNoExtraICState)                    \
-  V(StoreIC_GlobalProxy,        STORE_IC, MEGAMORPHIC,                    \
-                                Code::kNoExtraICState)                    \
-  V(StoreIC_Initialize_Strict,  STORE_IC, UNINITIALIZED,                  \
-                                StoreIC::kStoreICStrict)                  \
-  V(StoreIC_ArrayLength_Strict, STORE_IC, MONOMORPHIC,                    \
-                                StoreIC::kStoreICStrict)                  \
-  V(StoreIC_Normal_Strict,      STORE_IC, MONOMORPHIC,                    \
-                                StoreIC::kStoreICStrict)                  \
-  V(StoreIC_Megamorphic_Strict, STORE_IC, MEGAMORPHIC,                    \
-                                StoreIC::kStoreICStrict)                  \
-  V(StoreIC_GlobalProxy_Strict, STORE_IC, MEGAMORPHIC,                    \
-                                StoreIC::kStoreICStrict)                  \
-                                                                          \
-  V(KeyedStoreIC_Initialize,    KEYED_STORE_IC, UNINITIALIZED,            \
-                                Code::kNoExtraICState)                    \
-  V(KeyedStoreIC_Generic,       KEYED_STORE_IC, MEGAMORPHIC,              \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  /* Uses KeyedLoadIC_Initialize; must be after in list. */               \
-  V(FunctionCall,               BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(FunctionApply,              BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  V(ArrayCode,                  BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(ArrayConstructCode,         BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  V(StringConstructCode,        BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  V(OnStackReplacement,         BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)
+#define BUILTIN_LIST_A(V)                                           \
+  V(ArgumentsAdaptorTrampoline,     BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(JSConstructCall,                BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(JSConstructStubCountdown,       BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(JSConstructStubGeneric,         BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(JSConstructStubApi,             BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(JSEntryTrampoline,              BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(JSConstructEntryTrampoline,     BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(LazyCompile,                    BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(LazyRecompile,                  BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(NotifyDeoptimized,              BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(NotifyLazyDeoptimized,          BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(NotifyOSR,                      BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(LoadIC_Miss,                    BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(KeyedLoadIC_Miss,               BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(StoreIC_Miss,                   BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(KeyedStoreIC_Miss,              BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(LoadIC_Initialize,              LOAD_IC, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(LoadIC_PreMonomorphic,          LOAD_IC, PREMONOMORPHIC,        \
+                                    Code::kNoExtraICState)          \
+  V(LoadIC_Normal,                  LOAD_IC, MONOMORPHIC,           \
+                                    Code::kNoExtraICState)          \
+  V(LoadIC_ArrayLength,             LOAD_IC, MONOMORPHIC,           \
+                                    Code::kNoExtraICState)          \
+  V(LoadIC_StringLength,            LOAD_IC, MONOMORPHIC,           \
+                                    Code::kNoExtraICState)          \
+  V(LoadIC_StringWrapperLength,     LOAD_IC, MONOMORPHIC,           \
+                                    Code::kNoExtraICState)          \
+  V(LoadIC_FunctionPrototype,       LOAD_IC, MONOMORPHIC,           \
+                                    Code::kNoExtraICState)          \
+  V(LoadIC_Megamorphic,             LOAD_IC, MEGAMORPHIC,           \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(KeyedLoadIC_Initialize,         KEYED_LOAD_IC, UNINITIALIZED,   \
+                                    Code::kNoExtraICState)          \
+  V(KeyedLoadIC_PreMonomorphic,     KEYED_LOAD_IC, PREMONOMORPHIC,  \
+                                    Code::kNoExtraICState)          \
+  V(KeyedLoadIC_Generic,            KEYED_LOAD_IC, MEGAMORPHIC,     \
+                                    Code::kNoExtraICState)          \
+  V(KeyedLoadIC_String,             KEYED_LOAD_IC, MEGAMORPHIC,     \
+                                    Code::kNoExtraICState)          \
+  V(KeyedLoadIC_IndexedInterceptor, KEYED_LOAD_IC, MEGAMORPHIC,     \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(StoreIC_Initialize,             STORE_IC, UNINITIALIZED,        \
+                                    Code::kNoExtraICState)          \
+  V(StoreIC_ArrayLength,            STORE_IC, MONOMORPHIC,          \
+                                    Code::kNoExtraICState)          \
+  V(StoreIC_Normal,                 STORE_IC, MONOMORPHIC,          \
+                                    Code::kNoExtraICState)          \
+  V(StoreIC_Megamorphic,            STORE_IC, MEGAMORPHIC,          \
+                                    Code::kNoExtraICState)          \
+  V(StoreIC_GlobalProxy,            STORE_IC, MEGAMORPHIC,          \
+                                    Code::kNoExtraICState)          \
+  V(StoreIC_Initialize_Strict,      STORE_IC, UNINITIALIZED,        \
+                                    kStrictMode)                    \
+  V(StoreIC_ArrayLength_Strict,     STORE_IC, MONOMORPHIC,          \
+                                    kStrictMode)                    \
+  V(StoreIC_Normal_Strict,          STORE_IC, MONOMORPHIC,          \
+                                    kStrictMode)                    \
+  V(StoreIC_Megamorphic_Strict,     STORE_IC, MEGAMORPHIC,          \
+                                    kStrictMode)                    \
+  V(StoreIC_GlobalProxy_Strict,     STORE_IC, MEGAMORPHIC,          \
+                                    kStrictMode)                    \
+                                                                    \
+  V(KeyedStoreIC_Initialize,        KEYED_STORE_IC, UNINITIALIZED,  \
+                                    Code::kNoExtraICState)          \
+  V(KeyedStoreIC_Generic,           KEYED_STORE_IC, MEGAMORPHIC,    \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(KeyedStoreIC_Initialize_Strict, KEYED_STORE_IC, UNINITIALIZED,  \
+                                    kStrictMode)                    \
+  V(KeyedStoreIC_Generic_Strict,    KEYED_STORE_IC, MEGAMORPHIC,    \
+                                    kStrictMode)                    \
+                                                                    \
+  /* Uses KeyedLoadIC_Initialize; must be after in list. */         \
+  V(FunctionCall,                   BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(FunctionApply,                  BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(ArrayCode,                      BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(ArrayConstructCode,             BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(StringConstructCode,            BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(OnStackReplacement,             BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)
 
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
@@ -214,7 +219,7 @@
   V(SHL, 1)                              \
   V(SAR, 1)                              \
   V(SHR, 1)                              \
-  V(DELETE, 1)                           \
+  V(DELETE, 2)                           \
   V(IN, 1)                               \
   V(INSTANCE_OF, 1)                      \
   V(GET_KEYS, 0)                         \
diff --git a/src/code-stubs.h b/src/code-stubs.h
index 0d0e37f..96ac733 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -86,9 +86,6 @@
   CODE_STUB_LIST_ALL_PLATFORMS(V)    \
   CODE_STUB_LIST_ARM(V)
 
-// Types of uncatchable exceptions.
-enum UncatchableExceptionType { OUT_OF_MEMORY, TERMINATION };
-
 // Mode to overwrite BinaryExpression values.
 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
 enum UnaryOverwriteMode { UNARY_OVERWRITE, UNARY_NO_OVERWRITE };
diff --git a/src/compiler.cc b/src/compiler.cc
index ae7b2b9..667432f 100755
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -221,11 +221,12 @@
   // or perform on-stack replacement for function with too many
   // stack-allocated local variables.
   //
-  // The encoding is as a signed value, with parameters using the negative
-  // indices and locals the non-negative ones.
+  // The encoding is as a signed value, with parameters and receiver using
+  // the negative indices and locals the non-negative ones.
   const int limit = LUnallocated::kMaxFixedIndices / 2;
   Scope* scope = info->scope();
-  if (scope->num_parameters() > limit || scope->num_stack_slots() > limit) {
+  if ((scope->num_parameters() + 1) > limit ||
+      scope->num_stack_slots() > limit) {
     AbortAndDisable(info);
     // True indicates the compilation pipeline is still going, not
     // necessarily that we optimized the code.
@@ -261,10 +262,8 @@
       Handle<SharedFunctionInfo> shared = info->shared_info();
       shared->EnableDeoptimizationSupport(*unoptimized.code());
       // The existing unoptimized code was replaced with the new one.
-      Compiler::RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
-          Handle<String>(shared->DebugName()),
-          shared->start_position(),
-          &unoptimized);
+      Compiler::RecordFunctionCompilation(
+          Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
     }
   }
 
@@ -273,7 +272,7 @@
   // optimizable marker in the code object and optimize anyway. This
   // is safe as long as the unoptimized code has deoptimization
   // support.
-  ASSERT(FLAG_always_opt || info->shared_info()->code()->optimizable());
+  ASSERT(FLAG_always_opt || code->optimizable());
   ASSERT(info->shared_info()->has_deoptimization_support());
 
   if (FLAG_trace_hydrogen) {
@@ -282,21 +281,20 @@
     HTracer::Instance()->TraceCompilation(info->function());
   }
 
-  TypeFeedbackOracle oracle(
-      Handle<Code>(info->shared_info()->code()),
-      Handle<Context>(info->closure()->context()->global_context()));
-  HGraphBuilder builder(&oracle);
+  Handle<Context> global_context(info->closure()->context()->global_context());
+  TypeFeedbackOracle oracle(code, global_context);
+  HGraphBuilder builder(info, &oracle);
   HPhase phase(HPhase::kTotal);
-  HGraph* graph = builder.CreateGraph(info);
+  HGraph* graph = builder.CreateGraph();
   if (Top::has_pending_exception()) {
     info->SetCode(Handle<Code>::null());
     return false;
   }
 
   if (graph != NULL && FLAG_build_lithium) {
-    Handle<Code> code = graph->Compile();
-    if (!code.is_null()) {
-      info->SetCode(code);
+    Handle<Code> optimized_code = graph->Compile(info);
+    if (!optimized_code.is_null()) {
+      info->SetCode(optimized_code);
       FinishOptimization(info->closure(), start);
       return true;
     }
@@ -415,13 +413,25 @@
     return Handle<SharedFunctionInfo>::null();
   }
 
+  // Allocate function.
   ASSERT(!info->code().is_null());
+  Handle<SharedFunctionInfo> result =
+      Factory::NewSharedFunctionInfo(
+          lit->name(),
+          lit->materialized_literal_count(),
+          info->code(),
+          SerializedScopeInfo::Create(info->scope()));
+
+  ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
+  Compiler::SetFunctionInfo(result, lit, true, script);
+
   if (script->name()->IsString()) {
     PROFILE(CodeCreateEvent(
         info->is_eval()
             ? Logger::EVAL_TAG
             : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
         *info->code(),
+        *result,
         String::cast(script->name())));
     GDBJIT(AddCode(Handle<String>(String::cast(script->name())),
                    script,
@@ -432,21 +442,11 @@
             ? Logger::EVAL_TAG
             : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
         *info->code(),
-        ""));
+        *result,
+        Heap::empty_string()));
     GDBJIT(AddCode(Handle<String>(), script, info->code()));
   }
 
-  // Allocate function.
-  Handle<SharedFunctionInfo> result =
-      Factory::NewSharedFunctionInfo(
-          lit->name(),
-          lit->materialized_literal_count(),
-          info->code(),
-          SerializedScopeInfo::Create(info->scope()));
-
-  ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
-  Compiler::SetFunctionInfo(result, lit, true, script);
-
   // Hint to the runtime system used when allocating space for initial
   // property space by setting the expected number of properties for
   // the instances of the function.
@@ -613,10 +613,7 @@
       ASSERT(!info->code().is_null());
       Handle<Code> code = info->code();
       Handle<JSFunction> function = info->closure();
-      RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
-                                Handle<String>(shared->DebugName()),
-                                shared->start_position(),
-                                info);
+      RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
 
       if (info->IsOptimizing()) {
         function->ReplaceCode(*code);
@@ -724,10 +721,6 @@
     ASSERT(!info.code().is_null());
 
     // Function compilation complete.
-    RecordFunctionCompilation(Logger::FUNCTION_TAG,
-                              literal->debug_name(),
-                              literal->start_position(),
-                              &info);
     scope_info = SerializedScopeInfo::Create(info.scope());
   }
 
@@ -738,6 +731,7 @@
                                      info.code(),
                                      scope_info);
   SetFunctionInfo(result, literal, false, script);
+  RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
   result->set_allows_lazy_compilation(allow_lazy);
 
   // Set the expected number of properties for instances and return
@@ -776,28 +770,31 @@
 
 
 void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
-                                         Handle<String> name,
-                                         int start_position,
-                                         CompilationInfo* info) {
+                                         CompilationInfo* info,
+                                         Handle<SharedFunctionInfo> shared) {
+  // SharedFunctionInfo is passed separately, because if CompilationInfo
+  // was created using Script object, it will not have it.
+
   // Log the code generation. If source information is available include
   // script name and line number. Check explicitly whether logging is
   // enabled as finding the line number is not free.
-  if (Logger::is_logging() ||
-      CpuProfiler::is_profiling()) {
+  if (Logger::is_logging() || CpuProfiler::is_profiling()) {
     Handle<Script> script = info->script();
     Handle<Code> code = info->code();
+    if (*code == Builtins::builtin(Builtins::LazyCompile)) return;
     if (script->name()->IsString()) {
-      int line_num = GetScriptLineNumber(script, start_position) + 1;
+      int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
       USE(line_num);
       PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
                               *code,
-                              *name,
+                              *shared,
                               String::cast(script->name()),
                               line_num));
     } else {
       PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
                               *code,
-                              *name));
+                              *shared,
+                              shared->DebugName()));
     }
   }
 
diff --git a/src/compiler.h b/src/compiler.h
index 239bea3..e0a437a 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -265,9 +265,8 @@
 #endif
 
   static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
-                                        Handle<String> name,
-                                        int start_position,
-                                        CompilationInfo* info);
+                                        CompilationInfo* info,
+                                        Handle<SharedFunctionInfo> shared);
 };
 
 
diff --git a/src/cpu-profiler-inl.h b/src/cpu-profiler-inl.h
index 5df5893..440dedc 100644
--- a/src/cpu-profiler-inl.h
+++ b/src/cpu-profiler-inl.h
@@ -41,6 +41,9 @@
 
 void CodeCreateEventRecord::UpdateCodeMap(CodeMap* code_map) {
   code_map->AddCode(start, entry, size);
+  if (sfi_address != NULL) {
+    entry->set_shared_id(code_map->GetSFITag(sfi_address));
+  }
 }
 
 
@@ -54,8 +57,8 @@
 }
 
 
-void CodeAliasEventRecord::UpdateCodeMap(CodeMap* code_map) {
-  code_map->AddAlias(start, entry, code_start);
+void SFIMoveEventRecord::UpdateCodeMap(CodeMap* code_map) {
+  code_map->MoveCode(from, to);
 }
 
 
diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc
index fcf539f..ad04a00 100644
--- a/src/cpu-profiler.cc
+++ b/src/cpu-profiler.cc
@@ -53,13 +53,7 @@
       ticks_buffer_(sizeof(TickSampleEventRecord),
                     kTickSamplesBufferChunkSize,
                     kTickSamplesBufferChunksCount),
-      enqueue_order_(0),
-      known_functions_(new HashMap(AddressesMatch)) {
-}
-
-
-ProfilerEventsProcessor::~ProfilerEventsProcessor() {
-  delete known_functions_;
+      enqueue_order_(0) {
 }
 
 
@@ -75,6 +69,7 @@
   rec->start = start;
   rec->entry = generator_->NewCodeEntry(tag, prefix, name);
   rec->size = 1;
+  rec->sfi_address = NULL;
   events_buffer_.Enqueue(evt_rec);
 }
 
@@ -84,7 +79,8 @@
                                               String* resource_name,
                                               int line_number,
                                               Address start,
-                                              unsigned size) {
+                                              unsigned size,
+                                              Address sfi_address) {
   if (FilterOutCodeCreateEvent(tag)) return;
   CodeEventsContainer evt_rec;
   CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
@@ -93,6 +89,7 @@
   rec->start = start;
   rec->entry = generator_->NewCodeEntry(tag, name, resource_name, line_number);
   rec->size = size;
+  rec->sfi_address = sfi_address;
   events_buffer_.Enqueue(evt_rec);
 }
 
@@ -109,6 +106,7 @@
   rec->start = start;
   rec->entry = generator_->NewCodeEntry(tag, name);
   rec->size = size;
+  rec->sfi_address = NULL;
   events_buffer_.Enqueue(evt_rec);
 }
 
@@ -125,6 +123,7 @@
   rec->start = start;
   rec->entry = generator_->NewCodeEntry(tag, args_count);
   rec->size = size;
+  rec->sfi_address = NULL;
   events_buffer_.Enqueue(evt_rec);
 }
 
@@ -150,57 +149,14 @@
 }
 
 
-void ProfilerEventsProcessor::FunctionCreateEvent(Address alias,
-                                                  Address start,
-                                                  int security_token_id) {
+void ProfilerEventsProcessor::SFIMoveEvent(Address from, Address to) {
   CodeEventsContainer evt_rec;
-  CodeAliasEventRecord* rec = &evt_rec.CodeAliasEventRecord_;
-  rec->type = CodeEventRecord::CODE_ALIAS;
+  SFIMoveEventRecord* rec = &evt_rec.SFIMoveEventRecord_;
+  rec->type = CodeEventRecord::SFI_MOVE;
   rec->order = ++enqueue_order_;
-  rec->start = alias;
-  rec->entry = generator_->NewCodeEntry(security_token_id);
-  rec->code_start = start;
+  rec->from = from;
+  rec->to = to;
   events_buffer_.Enqueue(evt_rec);
-
-  known_functions_->Lookup(alias, AddressHash(alias), true);
-}
-
-
-void ProfilerEventsProcessor::FunctionMoveEvent(Address from, Address to) {
-  CodeMoveEvent(from, to);
-
-  if (IsKnownFunction(from)) {
-    known_functions_->Remove(from, AddressHash(from));
-    known_functions_->Lookup(to, AddressHash(to), true);
-  }
-}
-
-
-void ProfilerEventsProcessor::FunctionDeleteEvent(Address from) {
-  CodeDeleteEvent(from);
-
-  known_functions_->Remove(from, AddressHash(from));
-}
-
-
-bool ProfilerEventsProcessor::IsKnownFunction(Address start) {
-  HashMap::Entry* entry =
-      known_functions_->Lookup(start, AddressHash(start), false);
-  return entry != NULL;
-}
-
-
-void ProfilerEventsProcessor::ProcessMovedFunctions() {
-  for (int i = 0; i < moved_functions_.length(); ++i) {
-    JSFunction* function = moved_functions_[i];
-    CpuProfiler::FunctionCreateEvent(function);
-  }
-  moved_functions_.Clear();
-}
-
-
-void ProfilerEventsProcessor::RememberMovedFunction(JSFunction* function) {
-  moved_functions_.Add(function);
 }
 
 
@@ -227,13 +183,12 @@
   TickSample* sample = &record.sample;
   sample->state = Top::current_vm_state();
   sample->pc = reinterpret_cast<Address>(sample);  // Not NULL.
+  sample->tos = NULL;
   sample->frames_count = 0;
   for (StackTraceFrameIterator it;
        !it.done() && sample->frames_count < TickSample::kMaxFramesCount;
        it.Advance()) {
-    JavaScriptFrame* frame = it.frame();
-    sample->stack[sample->frames_count++] =
-        reinterpret_cast<Address>(frame->function());
+    sample->stack[sample->frames_count++] = it.frame()->pc();
   }
   record.order = enqueue_order_;
   ticks_from_vm_buffer_.Enqueue(record);
@@ -393,20 +348,38 @@
       Heap::empty_string(),
       v8::CpuProfileNode::kNoLineNumberInfo,
       code->address(),
-      code->ExecutableSize());
+      code->ExecutableSize(),
+      NULL);
 }
 
 
 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
-                           Code* code, String* name,
-                           String* source, int line) {
+                                  Code* code,
+                                  SharedFunctionInfo* shared,
+                                  String* name) {
   singleton_->processor_->CodeCreateEvent(
       tag,
       name,
+      Heap::empty_string(),
+      v8::CpuProfileNode::kNoLineNumberInfo,
+      code->address(),
+      code->ExecutableSize(),
+      shared->address());
+}
+
+
+void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
+                                  Code* code,
+                                  SharedFunctionInfo* shared,
+                                  String* source, int line) {
+  singleton_->processor_->CodeCreateEvent(
+      tag,
+      shared->DebugName(),
       source,
       line,
       code->address(),
-      code->ExecutableSize());
+      code->ExecutableSize(),
+      shared->address());
 }
 
 
@@ -430,44 +403,8 @@
 }
 
 
-void CpuProfiler::FunctionCreateEvent(JSFunction* function) {
-  int security_token_id = TokenEnumerator::kNoSecurityToken;
-  if (function->unchecked_context()->IsContext()) {
-    security_token_id = singleton_->token_enumerator_->GetTokenId(
-        function->context()->global_context()->security_token());
-  }
-  singleton_->processor_->FunctionCreateEvent(
-      function->address(),
-      function->shared()->code()->address(),
-      security_token_id);
-}
-
-
-void CpuProfiler::ProcessMovedFunctions() {
-  singleton_->processor_->ProcessMovedFunctions();
-}
-
-
-void CpuProfiler::FunctionCreateEventFromMove(JSFunction* function) {
-  // This function is called from GC iterators (during Scavenge,
-  // MC, and MS), so marking bits can be set on objects. That's
-  // why unchecked accessors are used here.
-
-  // The same function can be reported several times.
-  if (function->unchecked_code() == Builtins::builtin(Builtins::LazyCompile)
-      || singleton_->processor_->IsKnownFunction(function->address())) return;
-
-  singleton_->processor_->RememberMovedFunction(function);
-}
-
-
-void CpuProfiler::FunctionMoveEvent(Address from, Address to) {
-  singleton_->processor_->FunctionMoveEvent(from, to);
-}
-
-
-void CpuProfiler::FunctionDeleteEvent(Address from) {
-  singleton_->processor_->FunctionDeleteEvent(from);
+void CpuProfiler::SFIMoveEvent(Address from, Address to) {
+  singleton_->processor_->SFIMoveEvent(from, to);
 }
 
 
@@ -539,7 +476,6 @@
         FLAG_log_code = saved_log_code_flag;
       }
       Logger::LogCompiledFunctions();
-      Logger::LogFunctionObjects();
       Logger::LogAccessorCallbacks();
     }
     // Enable stack sampling.
diff --git a/src/cpu-profiler.h b/src/cpu-profiler.h
index 10165f6..1ebbfeb 100644
--- a/src/cpu-profiler.h
+++ b/src/cpu-profiler.h
@@ -50,7 +50,7 @@
   V(CODE_CREATION, CodeCreateEventRecord)       \
   V(CODE_MOVE,     CodeMoveEventRecord)         \
   V(CODE_DELETE,   CodeDeleteEventRecord)       \
-  V(CODE_ALIAS,    CodeAliasEventRecord)
+  V(SFI_MOVE,      SFIMoveEventRecord)
 
 
 class CodeEventRecord {
@@ -73,6 +73,7 @@
   Address start;
   CodeEntry* entry;
   unsigned size;
+  Address sfi_address;
 
   INLINE(void UpdateCodeMap(CodeMap* code_map));
 };
@@ -95,11 +96,10 @@
 };
 
 
-class CodeAliasEventRecord : public CodeEventRecord {
+class SFIMoveEventRecord : public CodeEventRecord {
  public:
-  Address start;
-  CodeEntry* entry;
-  Address code_start;
+  Address from;
+  Address to;
 
   INLINE(void UpdateCodeMap(CodeMap* code_map));
 };
@@ -134,7 +134,7 @@
 class ProfilerEventsProcessor : public Thread {
  public:
   explicit ProfilerEventsProcessor(ProfileGenerator* generator);
-  virtual ~ProfilerEventsProcessor();
+  virtual ~ProfilerEventsProcessor() {}
 
   // Thread control.
   virtual void Run();
@@ -148,7 +148,8 @@
   void CodeCreateEvent(Logger::LogEventsAndTags tag,
                        String* name,
                        String* resource_name, int line_number,
-                       Address start, unsigned size);
+                       Address start, unsigned size,
+                       Address sfi_address);
   void CodeCreateEvent(Logger::LogEventsAndTags tag,
                        const char* name,
                        Address start, unsigned size);
@@ -157,17 +158,12 @@
                        Address start, unsigned size);
   void CodeMoveEvent(Address from, Address to);
   void CodeDeleteEvent(Address from);
-  void FunctionCreateEvent(Address alias, Address start, int security_token_id);
-  void FunctionMoveEvent(Address from, Address to);
-  void FunctionDeleteEvent(Address from);
+  void SFIMoveEvent(Address from, Address to);
   void RegExpCodeCreateEvent(Logger::LogEventsAndTags tag,
                              const char* prefix, String* name,
                              Address start, unsigned size);
   // Puts current stack into tick sample events buffer.
   void AddCurrentStack();
-  bool IsKnownFunction(Address start);
-  void ProcessMovedFunctions();
-  void RememberMovedFunction(JSFunction* function);
 
   // Tick sample events are filled directly in the buffer of the circular
   // queue (because the structure is of fixed width, but usually not all
@@ -188,13 +184,6 @@
   bool ProcessTicks(unsigned dequeue_order);
 
   INLINE(static bool FilterOutCodeCreateEvent(Logger::LogEventsAndTags tag));
-  INLINE(static bool AddressesMatch(void* key1, void* key2)) {
-    return key1 == key2;
-  }
-  INLINE(static uint32_t AddressHash(Address addr)) {
-    return ComputeIntegerHash(
-        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(addr)));
-  }
 
   ProfileGenerator* generator_;
   bool running_;
@@ -202,10 +191,6 @@
   SamplingCircularQueue ticks_buffer_;
   UnboundQueue<TickSampleEventRecord> ticks_from_vm_buffer_;
   unsigned enqueue_order_;
-
-  // Used from the VM thread.
-  HashMap* known_functions_;
-  List<JSFunction*> moved_functions_;
 };
 
 } }  // namespace v8::internal
@@ -251,23 +236,22 @@
   static void CodeCreateEvent(Logger::LogEventsAndTags tag,
                               Code* code, String* name);
   static void CodeCreateEvent(Logger::LogEventsAndTags tag,
-                              Code* code, String* name,
+                              Code* code,
+                              SharedFunctionInfo *shared,
+                              String* name);
+  static void CodeCreateEvent(Logger::LogEventsAndTags tag,
+                              Code* code,
+                              SharedFunctionInfo *shared,
                               String* source, int line);
   static void CodeCreateEvent(Logger::LogEventsAndTags tag,
                               Code* code, int args_count);
   static void CodeMovingGCEvent() {}
   static void CodeMoveEvent(Address from, Address to);
   static void CodeDeleteEvent(Address from);
-  static void FunctionCreateEvent(JSFunction* function);
-  // Reports function creation in case we had missed it (e.g.
-  // if it was created from compiled code).
-  static void FunctionCreateEventFromMove(JSFunction* function);
-  static void FunctionMoveEvent(Address from, Address to);
-  static void FunctionDeleteEvent(Address from);
   static void GetterCallbackEvent(String* name, Address entry_point);
   static void RegExpCodeCreateEvent(Code* code, String* source);
-  static void ProcessMovedFunctions();
   static void SetterCallbackEvent(String* name, Address entry_point);
+  static void SFIMoveEvent(Address from, Address to);
 
   static INLINE(bool is_profiling()) {
     return NoBarrier_Load(&is_profiling_);
diff --git a/src/d8.cc b/src/d8.cc
index f0da7ac..349ec90 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -127,11 +127,13 @@
   } else {
     Handle<Value> result = script->Run();
     if (result.IsEmpty()) {
+      ASSERT(try_catch.HasCaught());
       // Print errors that happened during execution.
       if (report_exceptions && !i::FLAG_debugger)
         ReportException(&try_catch);
       return false;
     } else {
+      ASSERT(!try_catch.HasCaught());
       if (print_result && !result->IsUndefined()) {
         // If all went well and the result wasn't undefined then print
         // the returned value.
@@ -403,7 +405,7 @@
 void Shell::Initialize() {
   Shell::counter_map_ = new CounterMap();
   // Set up counters
-  if (i::FLAG_map_counters != NULL)
+  if (i::StrLength(i::FLAG_map_counters) != 0)
     MapCounters(i::FLAG_map_counters);
   if (i::FLAG_dump_counters) {
     V8::SetCounterFunction(LookupCounter);
@@ -423,6 +425,12 @@
   global_template->Set(String::New("quit"), FunctionTemplate::New(Quit));
   global_template->Set(String::New("version"), FunctionTemplate::New(Version));
 
+#ifdef LIVE_OBJECT_LIST
+  global_template->Set(String::New("lol_is_enabled"), Boolean::New(true));
+#else
+  global_template->Set(String::New("lol_is_enabled"), Boolean::New(false));
+#endif
+
   Handle<ObjectTemplate> os_templ = ObjectTemplate::New();
   AddOSMethods(os_templ);
   global_template->Set(String::New("os"), os_templ);
diff --git a/src/d8.js b/src/d8.js
index b0edb70..9798078 100644
--- a/src/d8.js
+++ b/src/d8.js
@@ -117,6 +117,10 @@
 var trace_compile = false;  // Tracing all compile events?
 var trace_debug_json = false; // Tracing all debug json packets?
 var last_cmd_line = '';
+//var lol_is_enabled;  // Set to true in d8.cc if LIVE_OBJECT_LIST is defined.
+var lol_next_dump_index = 0;
+const kDefaultLolLinesToPrintAtATime = 10;
+const kMaxLolLinesToPrintAtATime = 1000;
 var repeat_cmd_line = '';
 var is_running = true;
 
@@ -495,6 +499,13 @@
       this.request_ = void 0;
       break;
 
+    case 'liveobjectlist':
+    case 'lol':
+      if (lol_is_enabled) {
+        this.request_ = this.lolToJSONRequest_(args, is_repeating);
+        break;
+      }
+
     default:
       throw new Error('Unknown command "' + cmd + '"');
   }
@@ -539,10 +550,54 @@
 };
 
 
+// Note: we use detected command repetition as a signal for continuation here.
+DebugRequest.prototype.createLOLRequest = function(command,
+                                                   start_index,
+                                                   lines_to_dump,
+                                                   is_continuation) {
+  if (is_continuation) {
+    start_index = lol_next_dump_index;
+  }
+
+  if (lines_to_dump) {
+    lines_to_dump = parseInt(lines_to_dump);
+  } else {
+    lines_to_dump = kDefaultLolLinesToPrintAtATime;
+  }
+  if (lines_to_dump > kMaxLolLinesToPrintAtATime) {
+    lines_to_dump = kMaxLolLinesToPrintAtATime;
+  }
+
+  // Save the next start_index to dump from:
+  lol_next_dump_index = start_index + lines_to_dump;
+
+  var request = this.createRequest(command);
+  request.arguments = {};
+  request.arguments.start = start_index;
+  request.arguments.count = lines_to_dump;
+
+  return request;
+};
+
+
 // Create a JSON request for the evaluation command.
 DebugRequest.prototype.makeEvaluateJSONRequest_ = function(expression) {
   // Global varaible used to store whether a handle was requested.
   lookup_handle = null;
+
+  if (lol_is_enabled) {
+    // Check if the expression is a obj id in the form @<obj id>.
+    var obj_id_match = expression.match(/^@([0-9]+)$/);
+    if (obj_id_match) {
+      var obj_id = parseInt(obj_id_match[1]);
+      // Build a dump request.
+      var request = this.createRequest('getobj');
+      request.arguments = {};
+      request.arguments.obj_id = obj_id;
+      return request.toJSONProtocol();
+    }
+  }
+
   // Check if the expression is a handle id in the form #<handle>#.
   var handle_match = expression.match(/^#([0-9]*)#$/);
   if (handle_match) {
@@ -1103,6 +1158,10 @@
     // Build a evaluate request from the text command.
     request = this.createRequest('frame');
     last_cmd = 'info args';
+  } else if (lol_is_enabled &&
+             args && (args == 'liveobjectlist' || args == 'lol')) {
+    // Build a evaluate request from the text command.
+    return this.liveObjectListToJSONRequest_(null);
   } else {
     throw new Error('Invalid info arguments.');
   }
@@ -1153,6 +1212,262 @@
 };
 
 
+// Args: [v[erbose]] [<N>] [i[ndex] <i>] [t[ype] <type>] [sp[ace] <space>]
+DebugRequest.prototype.lolMakeListRequest =
+    function(cmd, args, first_arg_index, is_repeating) {
+
+  var request;
+  var start_index = 0;
+  var dump_limit = void 0;
+  var type_filter = void 0;
+  var space_filter = void 0;
+  var prop_filter = void 0;
+  var is_verbose = false;
+  var i;
+
+  for (i = first_arg_index; i < args.length; i++) {
+    var arg = args[i];
+    // Check for [v[erbose]]:
+    if (arg === 'verbose' || arg === 'v') {
+      // Nothing to do.  This is already implied by args.length > 3.
+      is_verbose = true;
+
+    // Check for [<N>]:
+    } else if (arg.match(/^[0-9]+$/)) {
+      dump_limit = arg;
+      is_verbose = true;
+
+    // Check for i[ndex] <i>:
+    } else if (arg === 'index' || arg === 'i') {
+      i++;
+      if (args.length < i) {
+        throw new Error('Missing index after ' + arg + '.');
+      }
+      start_index = parseInt(args[i]);
+      // The user input start index starts at 1:
+      if (start_index <= 0) {
+        throw new Error('Invalid index ' + args[i] + '.');                
+      }
+      start_index -= 1;
+      is_verbose = true;
+
+    // Check for t[ype] <type>:
+    } else if (arg === 'type' || arg === 't') {
+      i++;
+      if (args.length < i) {
+        throw new Error('Missing type after ' + arg + '.');
+      }
+      type_filter = args[i];
+
+    // Check for space <heap space name>:
+    } else if (arg === 'space' || arg === 'sp') {
+      i++;
+      if (args.length < i) {
+        throw new Error('Missing space name after ' + arg + '.');
+      }
+      space_filter = args[i];
+
+    // Check for property <prop name>:
+    } else if (arg === 'property' || arg === 'prop') {
+      i++;
+      if (args.length < i) {
+        throw new Error('Missing property name after ' + arg + '.');
+      }
+      prop_filter = args[i];
+
+    } else {
+      throw new Error('Unknown args at ' + arg + '.');
+    }
+  }
+
+  // Build the verbose request:
+  if (is_verbose) {
+    request = this.createLOLRequest('lol-'+cmd,
+                                    start_index,
+                                    dump_limit,
+                                    is_repeating);
+    request.arguments.verbose = true;
+  } else {
+    request = this.createRequest('lol-'+cmd);
+    request.arguments = {};
+  }
+
+  request.arguments.filter = {};
+  if (type_filter) {
+    request.arguments.filter.type = type_filter;
+  }
+  if (space_filter) {
+    request.arguments.filter.space = space_filter;
+  }
+  if (prop_filter) {
+    request.arguments.filter.prop = prop_filter;
+  }
+
+  return request;
+}
+
+
+function extractObjId(args) {
+  var id = args;
+  id = id.match(/^@([0-9]+)$/);
+  if (id) {
+    id = id[1];
+  } else {
+    throw new Error('Invalid obj id ' + args + '.');
+  }
+  return parseInt(id);
+}
+
+
+DebugRequest.prototype.lolToJSONRequest_ = function(args, is_repeating) {
+  var request;
+  // Use default command if one is not specified:
+  if (!args) {
+    args = 'info';
+  }
+
+  var orig_args = args;
+  var first_arg_index;
+
+  var arg, i;
+  var args = args.split(/\s+/g);
+  var cmd = args[0];
+  var id;
+
+  // Command: <id> [v[erbose]] ...
+  if (cmd.match(/^[0-9]+$/)) {
+    // Convert to the padded list command:
+    // Command: l[ist] <dummy> <id> [v[erbose]] ...
+
+    // Insert the implicit 'list' in front and process as normal:
+    cmd = 'list';
+    args.unshift(cmd);
+  }
+
+  switch(cmd) {
+    // Command: c[apture]
+    case 'capture':
+    case 'c':
+      request = this.createRequest('lol-capture');
+      break;
+
+    // Command: clear|d[elete] <id>|all
+    case 'clear':
+    case 'delete':
+    case 'del': {
+      if (args.length < 2) {
+        throw new Error('Missing argument after ' + cmd + '.');
+      } else if (args.length > 2) {
+        throw new Error('Too many arguments after ' + cmd + '.');
+      }
+      id = args[1];
+      if (id.match(/^[0-9]+$/)) {
+        // Delete a specific lol record:
+        request = this.createRequest('lol-delete');
+        request.arguments = {};
+        request.arguments.id = parseInt(id);
+      } else if (id === 'all') {
+        // Delete all:
+        request = this.createRequest('lol-reset');
+      } else {
+        throw new Error('Invalid argument after ' + cmd + '.');
+      }
+      break;
+    }
+
+    // Command: diff <id1> <id2> [<dump options>]
+    case 'diff':
+      first_arg_index = 3;
+
+    // Command: list <dummy> <id> [<dump options>]
+    case 'list':
+
+    // Command: ret[ainers] <obj id> [<dump options>]
+    case 'retainers':
+    case 'ret':
+    case 'retaining-paths':
+    case 'rp': {
+      if (cmd === 'ret') cmd = 'retainers';
+      else if (cmd === 'rp') cmd = 'retaining-paths';
+
+      if (!first_arg_index) first_arg_index = 2;
+
+      if (args.length < first_arg_index) {
+        throw new Error('Too few arguments after ' + cmd + '.');
+      }
+
+      var request_cmd = (cmd === 'list') ? 'diff':cmd;
+      request = this.lolMakeListRequest(request_cmd,
+                                        args,
+                                        first_arg_index,
+                                        is_repeating);
+
+      if (cmd === 'diff') {
+        request.arguments.id1 = parseInt(args[1]);
+        request.arguments.id2 = parseInt(args[2]);
+      } else if (cmd == 'list') {
+        request.arguments.id1 = 0;
+        request.arguments.id2 = parseInt(args[1]);
+      } else {
+        request.arguments.id = extractObjId(args[1]);
+      }
+      break;
+    }
+
+    // Command: getid
+    case 'getid': {
+      request = this.createRequest('lol-getid');
+      request.arguments = {};
+      request.arguments.address = args[1];
+      break;
+    }
+
+    // Command: inf[o] [<N>]
+    case 'info':
+    case 'inf': {
+      if (args.length > 2) {
+        throw new Error('Too many arguments after ' + cmd + '.');
+      }
+      // Built the info request:
+      request = this.createLOLRequest('lol-info', 0, args[1], is_repeating);
+      break;
+    }
+
+    // Command: path <obj id 1> <obj id 2>
+    case 'path': {
+      request = this.createRequest('lol-path');
+      request.arguments = {};
+      if (args.length > 2) {
+        request.arguments.id1 = extractObjId(args[1]);
+        request.arguments.id2 = extractObjId(args[2]);
+      } else {
+        request.arguments.id1 = 0;
+        request.arguments.id2 = extractObjId(args[1]);
+      }
+      break;
+    }
+
+    // Command: print
+    case 'print': {
+      request = this.createRequest('lol-print');
+      request.arguments = {};
+      request.arguments.id = extractObjId(args[1]);
+      break;
+    }
+
+    // Command: reset
+    case 'reset': {
+      request = this.createRequest('lol-reset');
+      break;
+    }
+
+    default:
+      throw new Error('Invalid arguments.');
+  }
+  return request.toJSONProtocol();
+};
+
+
 // Create a JSON request for the threads command.
 DebugRequest.prototype.threadsCommandToJSONRequest_ = function(args) {
   // Build a threads request from the text command.
@@ -1239,6 +1554,49 @@
   print('');
   print('gc                         - runs the garbage collector');
   print('');
+
+  if (lol_is_enabled) {
+    print('liveobjectlist|lol <command> - live object list tracking.');
+    print('  where <command> can be:');
+    print('  c[apture]               - captures a LOL list.');
+    print('  clear|del[ete] <id>|all - clears LOL of id <id>.');
+    print('                            If \'all\' is unspecified instead, will clear all.');
+    print('  diff <id1> <id2> [<dump options>]');
+    print('                          - prints the diff between LOLs id1 and id2.');
+    print('                          - also see <dump options> below.');
+    print('  getid <address>         - gets the obj id for the specified address if available.');
+    print('                            The address must be in hex form prefixed with 0x.');
+    print('  inf[o] [<N>]            - lists summary info of all LOL lists.');
+    print('                            If N is specified, will print N items at a time.');
+    print('  [l[ist]] <id> [<dump options>]');
+    print('                          - prints the listing of objects in LOL id.');
+    print('                          - also see <dump options> below.');
+    print('  reset                   - clears all LOL lists.');
+    print('  ret[ainers] <id> [<dump options>]');
+    print('                          - prints the list of retainers of obj id.');
+    print('                          - also see <dump options> below.');
+    print('  path <id1> <id2>        - prints the retaining path from obj id1 to id2.');
+    print('                            If only one id is specified, will print the path from');
+    print('                            roots to the specified object if available.');
+    print('  print <id>              - prints the obj for the specified obj id if available.');
+    print('');
+    print('  <dump options> includes:');
+    print('     [v[erbose]]            - do verbose dump.');
+    print('     [<N>]                  - dump N items at a time.  Implies verbose dump.');
+    print('                             If unspecified, N will default to '+
+          kDefaultLolLinesToPrintAtATime+'.  Max N is '+
+          kMaxLolLinesToPrintAtATime+'.');
+    print('     [i[ndex] <i>]          - start dump from index i.  Implies verbose dump.');
+    print('     [t[ype] <type>]        - filter by type.');
+    print('     [sp[ace] <space name>] - filter by heap space where <space name> is one of');
+    print('                              { cell, code, lo, map, new, old-data, old-pointer }.');
+    print('');
+    print('     If the verbose option, or an option that implies a verbose dump');
+    print('     is specified, then a verbose dump will requested.  Else, a summary dump');
+    print('     will be requested.');
+    print('');
+  }
+
   print('trace compile');
   // hidden command: trace debug json - toggles tracing of debug json packets
   print('');
@@ -1339,6 +1697,237 @@
 }
 
 
+function decodeLolCaptureResponse(body) {
+  var result;
+  result = 'Captured live object list '+ body.id +
+           ': count '+ body.count + ' size ' + body.size;
+  return result;
+}
+
+
+function decodeLolDeleteResponse(body) {
+  var result;
+  result = 'Deleted live object list '+ body.id;
+  return result;
+}
+
+
+function digitsIn(value) {
+  var digits = 0;
+  if (value === 0) value = 1;
+  while (value >= 1) {
+    digits++;
+    value /= 10;
+  }
+  return digits;
+}
+
+
+function padding(value, max_digits) {
+  var padding_digits = max_digits - digitsIn(value);
+  var padding = '';
+  while (padding_digits > 0) {
+    padding += ' ';
+    padding_digits--;
+  }
+  return padding;
+}
+
+
+function decodeLolInfoResponse(body) {
+  var result;
+  var lists = body.lists;
+  var length = lists.length;
+  var first_index = body.first_index + 1;
+  var has_more = ((first_index + length) <= body.count);
+  result = 'captured live object lists';
+  if (has_more || (first_index != 1)) {
+    result += ' ['+ length +' of '+ body.count +
+              ': starting from '+ first_index +']';
+  }
+  result += ':\n';
+  var max_digits = digitsIn(body.count);
+  var last_count = 0;
+  var last_size = 0;
+  for (var i = 0; i < length; i++) {
+    var entry = lists[i];
+    var count = entry.count;
+    var size = entry.size;
+    var index = first_index + i;
+    result += '  [' + padding(index, max_digits) + index + '] id '+ entry.id +
+              ': count '+ count;
+    if (last_count > 0) {
+      result += '(+' + (count - last_count) + ')';
+    }
+    result += ' size '+ size;
+    if (last_size > 0) {
+      result += '(+' + (size - last_size) + ')';
+    }
+    result += '\n';
+    last_count = count;
+    last_size = size;
+  }
+  result += '  total: '+length+' lists\n';
+  if (has_more) {
+    result += '  -- press <enter> for more --\n';
+  } else {
+    repeat_cmd_line = '';
+  }
+  if (length === 0) result += '  none\n';
+
+  return result;
+}
+
+
+function decodeLolListResponse(body, title) {
+  
+  var result;
+  var total_count = body.count;
+  var total_size = body.size;
+  var length;
+  var max_digits;
+  var i;
+  var entry;
+  var index;
+
+  var max_count_digits = digitsIn(total_count);
+  var max_size_digits;
+
+  var summary = body.summary;
+  if (summary) {
+
+    var roots_count = 0;
+    var found_root = body.found_root || 0;
+    var found_weak_root = body.found_weak_root || 0;
+
+    // Print the summary result:
+    result = 'summary of objects:\n';
+    length = summary.length;
+    if (found_root !== 0) {
+      roots_count++;
+    }
+    if (found_weak_root !== 0) {
+      roots_count++;
+    }
+    max_digits = digitsIn(length + roots_count);
+    max_size_digits = digitsIn(total_size);
+
+    index = 1;
+    if (found_root !== 0) {
+      result += '  [' + padding(index, max_digits) + index + '] ' +
+                ' count '+ 1 + padding(0, max_count_digits) +
+                '      '+ padding(0, max_size_digits+1) +
+                ' : <root>\n';
+      index++;
+    }
+    if (found_weak_root !== 0) {
+      result += '  [' + padding(index, max_digits) + index + '] ' +
+                ' count '+ 1 + padding(0, max_count_digits) +
+                '      '+ padding(0, max_size_digits+1) +
+                ' : <weak root>\n';
+      index++;
+    }
+
+    for (i = 0; i < length; i++) {
+      entry = summary[i];
+      var count = entry.count;
+      var size = entry.size;
+      result += '  [' + padding(index, max_digits) + index + '] ' +
+                ' count '+ count + padding(count, max_count_digits) +
+                ' size '+ size + padding(size, max_size_digits) +
+                ' : <' + entry.desc + '>\n';
+      index++;
+    }
+    result += '\n  total count: '+(total_count+roots_count)+'\n';
+    if (body.size) {
+      result += '  total size:  '+body.size+'\n';
+    }
+
+  } else {
+    // Print the full dump result:
+    var first_index = body.first_index + 1;
+    var elements = body.elements;
+    length = elements.length;
+    var has_more = ((first_index + length) <= total_count);
+    result = title;
+    if (has_more || (first_index != 1)) {
+      result += ' ['+ length +' of '+ total_count +
+                ': starting from '+ first_index +']';
+    }
+    result += ':\n';
+    if (length === 0) result += '  none\n';
+    max_digits = digitsIn(length);
+
+    var max_id = 0;
+    var max_size = 0;
+    for (i = 0; i < length; i++) {
+      entry = elements[i];
+      if (entry.id > max_id) max_id = entry.id;
+      if (entry.size > max_size) max_size = entry.size;
+    }
+    var max_id_digits = digitsIn(max_id);
+    max_size_digits = digitsIn(max_size);
+
+    for (i = 0; i < length; i++) {
+      entry = elements[i];
+      index = first_index + i;
+      result += '  ['+ padding(index, max_digits) + index +']';
+      if (entry.id !== 0) {
+        result += ' @' + entry.id + padding(entry.id, max_id_digits) +
+                  ': size ' + entry.size + ', ' +
+                  padding(entry.size, max_size_digits) +  entry.desc + '\n';
+      } else {
+        // Must be a root or weak root:
+        result += ' ' + entry.desc + '\n';
+      }
+    }
+    if (has_more) {
+      result += '  -- press <enter> for more --\n';
+    } else {
+      repeat_cmd_line = '';
+    }
+    if (length === 0) result += '  none\n';
+  }
+
+  return result;
+}
+
+
+function decodeLolDiffResponse(body) {
+  var title = 'objects';
+  return decodeLolListResponse(body, title);
+}
+
+
+function decodeLolRetainersResponse(body) {
+  var title = 'retainers for @' + body.id;
+  return decodeLolListResponse(body, title);
+}
+
+
+function decodeLolPathResponse(body) {
+  return body.path;
+}
+
+
+function decodeLolResetResponse(body) {
+  return 'Reset all live object lists.';
+}
+
+
+function decodeLolGetIdResponse(body) {
+  if (body.id == 0) {
+    return 'Address is invalid, or object has been moved or collected';
+  }
+  return 'obj id is @' + body.id;
+}
+
+
+function decodeLolPrintResponse(body) {
+  return body.dump;
+}
+
+
 // Rounds number 'num' to 'length' decimal places.
 function roundNumber(num, length) {
   var factor = Math.pow(10, length);
@@ -1510,6 +2099,7 @@
 
       case 'evaluate':
       case 'lookup':
+      case 'getobj':
         if (last_cmd == 'p' || last_cmd == 'print') {
           result = body.text;
         } else {
@@ -1671,6 +2261,34 @@
         }
         break;
 
+      case 'lol-capture':
+        details.text = decodeLolCaptureResponse(body);
+        break;
+      case 'lol-delete':
+        details.text = decodeLolDeleteResponse(body);
+        break;
+      case 'lol-diff':
+        details.text = decodeLolDiffResponse(body);
+        break;
+      case 'lol-getid':
+        details.text = decodeLolGetIdResponse(body);
+        break;
+      case 'lol-info':
+        details.text = decodeLolInfoResponse(body);
+        break;
+      case 'lol-print':
+        details.text = decodeLolPrintResponse(body);
+        break;
+      case 'lol-reset':
+        details.text = decodeLolResetResponse(body);
+        break;
+      case 'lol-retainers':
+        details.text = decodeLolRetainersResponse(body);
+        break;
+      case 'lol-path':
+        details.text = decodeLolPathResponse(body);
+        break;
+
       default:
         details.text =
             'Response for unknown command \'' + response.command() + '\'' +
diff --git a/src/date.js b/src/date.js
index 1fb4897..242ab7b 100644
--- a/src/date.js
+++ b/src/date.js
@@ -81,12 +81,7 @@
 
 
 function InLeapYear(time) {
-  return DaysInYear(YearFromTime(time)) == 366 ? 1 : 0;
-}
-
-
-function DayWithinYear(time) {
-  return DAY(time) - DayFromYear(YearFromTime(time));
+  return DaysInYear(YearFromTime(time)) - 365;  // Returns 1 or 0.
 }
 
 
diff --git a/src/debug-debugger.js b/src/debug-debugger.js
index 1adf73a..bc0f966 100644
--- a/src/debug-debugger.js
+++ b/src/debug-debugger.js
@@ -109,6 +109,7 @@
     }
   },
 };
+var lol_is_enabled = %HasLOLEnabled();
 
 
 // Create a new break point object and add it to the list of break points.
@@ -1391,6 +1392,8 @@
         this.scopeRequest_(request, response);
       } else if (request.command == 'evaluate') {
         this.evaluateRequest_(request, response);
+      } else if (lol_is_enabled && request.command == 'getobj') {
+        this.getobjRequest_(request, response);
       } else if (request.command == 'lookup') {
         this.lookupRequest_(request, response);
       } else if (request.command == 'references') {
@@ -1418,6 +1421,28 @@
       } else if (request.command == 'gc') {
         this.gcRequest_(request, response);
 
+      // LiveObjectList tools:
+      } else if (lol_is_enabled && request.command == 'lol-capture') {
+        this.lolCaptureRequest_(request, response);
+      } else if (lol_is_enabled && request.command == 'lol-delete') {
+        this.lolDeleteRequest_(request, response);
+      } else if (lol_is_enabled && request.command == 'lol-diff') {
+        this.lolDiffRequest_(request, response);
+      } else if (lol_is_enabled && request.command == 'lol-getid') {
+        this.lolGetIdRequest_(request, response);
+      } else if (lol_is_enabled && request.command == 'lol-info') {
+        this.lolInfoRequest_(request, response);
+      } else if (lol_is_enabled && request.command == 'lol-reset') {
+        this.lolResetRequest_(request, response);
+      } else if (lol_is_enabled && request.command == 'lol-retainers') {
+        this.lolRetainersRequest_(request, response);
+      } else if (lol_is_enabled && request.command == 'lol-path') {
+        this.lolPathRequest_(request, response);
+      } else if (lol_is_enabled && request.command == 'lol-print') {
+        this.lolPrintRequest_(request, response);
+      } else if (lol_is_enabled && request.command == 'lol-stats') {
+        this.lolStatsRequest_(request, response);
+
       } else {
         throw new Error('Unknown command "' + request.command + '" in request');
       }
@@ -2011,6 +2036,24 @@
 };
 
 
+DebugCommandProcessor.prototype.getobjRequest_ = function(request, response) {
+  if (!request.arguments) {
+    return response.failed('Missing arguments');
+  }
+
+  // Pull out arguments.
+  var obj_id = request.arguments.obj_id;
+
+  // Check for legal arguments.
+  if (IS_UNDEFINED(obj_id)) {
+    return response.failed('Argument "obj_id" missing');
+  }
+
+  // Dump the object.
+  response.body = MakeMirror(%GetLOLObj(obj_id));
+};
+
+
 DebugCommandProcessor.prototype.lookupRequest_ = function(request, response) {
   if (!request.arguments) {
     return response.failed('Missing arguments');
@@ -2341,6 +2384,84 @@
 };
 
 
+DebugCommandProcessor.prototype.lolCaptureRequest_ =
+    function(request, response) {
+  response.body = %CaptureLOL();
+};
+
+
+DebugCommandProcessor.prototype.lolDeleteRequest_ =
+    function(request, response) {
+  var id = request.arguments.id;
+  var result = %DeleteLOL(id);
+  if (result) {
+    response.body = { id: id };
+  } else {
+    response.failed('Failed to delete: live object list ' + id + ' not found.');
+  }
+};
+
+
+DebugCommandProcessor.prototype.lolDiffRequest_ = function(request, response) {
+  var id1 = request.arguments.id1;
+  var id2 = request.arguments.id2;
+  var verbose = request.arguments.verbose;
+  var filter = request.arguments.filter;
+  if (verbose === true) {
+    var start = request.arguments.start;
+    var count = request.arguments.count;
+    response.body = %DumpLOL(id1, id2, start, count, filter);
+  } else {
+    response.body = %SummarizeLOL(id1, id2, filter);
+  }
+};
+
+
+DebugCommandProcessor.prototype.lolGetIdRequest_ = function(request, response) {
+  var address = request.arguments.address;
+  response.body = {};
+  response.body.id = %GetLOLObjId(address);
+};
+
+
+DebugCommandProcessor.prototype.lolInfoRequest_ = function(request, response) {
+  var start = request.arguments.start;
+  var count = request.arguments.count;
+  response.body = %InfoLOL(start, count);
+};
+
+
+DebugCommandProcessor.prototype.lolResetRequest_ = function(request, response) {
+  %ResetLOL();
+};
+
+
+DebugCommandProcessor.prototype.lolRetainersRequest_ =
+    function(request, response) {
+  var id = request.arguments.id;
+  var verbose = request.arguments.verbose;
+  var start = request.arguments.start;
+  var count = request.arguments.count;
+  var filter = request.arguments.filter;
+
+  response.body = %GetLOLObjRetainers(id, Mirror.prototype, verbose,
+                                      start, count, filter);
+};
+
+
+DebugCommandProcessor.prototype.lolPathRequest_ = function(request, response) {
+  var id1 = request.arguments.id1;
+  var id2 = request.arguments.id2;
+  response.body = {};
+  response.body.path = %GetLOLPath(id1, id2, Mirror.prototype);
+};
+
+
+DebugCommandProcessor.prototype.lolPrintRequest_ = function(request, response) {
+  var id = request.arguments.id;
+  response.body = {};
+  response.body.dump = %PrintLOLObj(id);
+};
 
 
 // Check whether the previously processed command caused the VM to become
diff --git a/src/debug.cc b/src/debug.cc
index d8201a1..d91ad92 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -836,7 +836,8 @@
   Handle<String> key = Factory::LookupAsciiSymbol("builtins");
   Handle<GlobalObject> global = Handle<GlobalObject>(context->global());
   RETURN_IF_EMPTY_HANDLE_VALUE(
-      SetProperty(global, key, Handle<Object>(global->builtins()), NONE),
+      SetProperty(global, key, Handle<Object>(global->builtins()),
+                  NONE, kNonStrictMode),
       false);
 
   // Compile the JavaScript for the debugger in the debugger context.
@@ -1012,14 +1013,18 @@
     for (int i = 0; i < array->length(); i++) {
       Handle<Object> o(array->get(i));
       if (CheckBreakPoint(o)) {
-        SetElement(break_points_hit, break_points_hit_count++, o);
+        SetElement(break_points_hit,
+                   break_points_hit_count++,
+                   o,
+                   kNonStrictMode);
       }
     }
   } else {
     if (CheckBreakPoint(break_point_objects)) {
       SetElement(break_points_hit,
                  break_points_hit_count++,
-                 break_point_objects);
+                 break_point_objects,
+                 kNonStrictMode);
     }
   }
 
diff --git a/src/execution.cc b/src/execution.cc
index f484d8d..de8f0a4 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -106,6 +106,11 @@
   ASSERT(*has_pending_exception == Top::has_pending_exception());
   if (*has_pending_exception) {
     Top::ReportPendingMessages();
+    if (Top::pending_exception() == Failure::OutOfMemoryException()) {
+      if (!HandleScopeImplementer::instance()->ignore_out_of_memory()) {
+        V8::FatalProcessOutOfMemory("JS", true);
+      }
+    }
     return Handle<Object>();
   } else {
     Top::clear_pending_message();
diff --git a/src/extensions/experimental/break-iterator.cc b/src/extensions/experimental/break-iterator.cc
new file mode 100644
index 0000000..6f574d4
--- /dev/null
+++ b/src/extensions/experimental/break-iterator.cc
@@ -0,0 +1,249 @@
+// 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 "break-iterator.h"
+
+#include "unicode/brkiter.h"
+#include "unicode/locid.h"
+#include "unicode/rbbi.h"
+
+namespace v8 {
+namespace internal {
+
+v8::Persistent<v8::FunctionTemplate> BreakIterator::break_iterator_template_;
+
+icu::BreakIterator* BreakIterator::UnpackBreakIterator(
+    v8::Handle<v8::Object> obj) {
+  if (break_iterator_template_->HasInstance(obj)) {
+    return static_cast<icu::BreakIterator*>(
+        obj->GetPointerFromInternalField(0));
+  }
+
+  return NULL;
+}
+
+UnicodeString* BreakIterator::ResetAdoptedText(
+    v8::Handle<v8::Object> obj, v8::Handle<v8::Value> value) {
+  // Get the previous value from the internal field.
+  UnicodeString* text = static_cast<UnicodeString*>(
+      obj->GetPointerFromInternalField(1));
+  delete text;
+
+  // Assign new value to the internal pointer.
+  v8::String::Value text_value(value);
+  text = new UnicodeString(
+      reinterpret_cast<const UChar*>(*text_value), text_value.length());
+  obj->SetPointerInInternalField(1, text);
+
+  // Return new unicode string pointer.
+  return text;
+}
+
+void BreakIterator::DeleteBreakIterator(v8::Persistent<v8::Value> object,
+                                        void* param) {
+  v8::Persistent<v8::Object> persistent_object =
+      v8::Persistent<v8::Object>::Cast(object);
+
+  // First delete the hidden C++ object.
+  // Unpacking should never return NULL here. That would only happen if
+  // this method is used as the weak callback for persistent handles not
+  // pointing to a break iterator.
+  delete UnpackBreakIterator(persistent_object);
+
+  delete static_cast<UnicodeString*>(
+      persistent_object->GetPointerFromInternalField(1));
+
+  // Then dispose of the persistent handle to JS object.
+  persistent_object.Dispose();
+}
+
+// Throws a JavaScript exception.
+static v8::Handle<v8::Value> ThrowUnexpectedObjectError() {
+  // Returns undefined, and schedules an exception to be thrown.
+  return v8::ThrowException(v8::Exception::Error(
+      v8::String::New("BreakIterator method called on an object "
+                      "that is not a BreakIterator.")));
+}
+
+v8::Handle<v8::Value> BreakIterator::BreakIteratorAdoptText(
+    const v8::Arguments& args) {
+  if (args.Length() != 1 || !args[0]->IsString()) {
+    return v8::ThrowException(v8::Exception::SyntaxError(
+        v8::String::New("Text input is required.")));
+  }
+
+  icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder());
+  if (!break_iterator) {
+    return ThrowUnexpectedObjectError();
+  }
+
+  break_iterator->setText(*ResetAdoptedText(args.Holder(), args[0]));
+
+  return v8::Undefined();
+}
+
+v8::Handle<v8::Value> BreakIterator::BreakIteratorFirst(
+    const v8::Arguments& args) {
+  icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder());
+  if (!break_iterator) {
+    return ThrowUnexpectedObjectError();
+  }
+
+  return v8::Int32::New(break_iterator->first());
+}
+
+v8::Handle<v8::Value> BreakIterator::BreakIteratorNext(
+    const v8::Arguments& args) {
+  icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder());
+  if (!break_iterator) {
+    return ThrowUnexpectedObjectError();
+  }
+
+  return v8::Int32::New(break_iterator->next());
+}
+
+v8::Handle<v8::Value> BreakIterator::BreakIteratorCurrent(
+    const v8::Arguments& args) {
+  icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder());
+  if (!break_iterator) {
+    return ThrowUnexpectedObjectError();
+  }
+
+  return v8::Int32::New(break_iterator->current());
+}
+
+v8::Handle<v8::Value> BreakIterator::BreakIteratorBreakType(
+    const v8::Arguments& args) {
+  icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder());
+  if (!break_iterator) {
+    return ThrowUnexpectedObjectError();
+  }
+
+  // TODO(cira): Remove cast once ICU fixes base BreakIterator class.
+  int32_t status =
+      static_cast<RuleBasedBreakIterator*>(break_iterator)->getRuleStatus();
+  // Keep return values in sync with JavaScript BreakType enum.
+  if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
+    return v8::Int32::New(UBRK_WORD_NONE);
+  } else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
+    return v8::Int32::New(UBRK_WORD_NUMBER);
+  } else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
+    return v8::Int32::New(UBRK_WORD_LETTER);
+  } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
+    return v8::Int32::New(UBRK_WORD_KANA);
+  } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
+    return v8::Int32::New(UBRK_WORD_IDEO);
+  } else {
+    return v8::Int32::New(-1);
+  }
+}
+
+v8::Handle<v8::Value> BreakIterator::JSBreakIterator(
+    const v8::Arguments& args) {
+  v8::HandleScope handle_scope;
+
+  if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) {
+    return v8::ThrowException(v8::Exception::SyntaxError(
+        v8::String::New("Locale and iterator type are required.")));
+  }
+
+  v8::String::Utf8Value locale(args[0]);
+  icu::Locale icu_locale(*locale);
+
+  UErrorCode status = U_ZERO_ERROR;
+  icu::BreakIterator* break_iterator = NULL;
+  v8::String::Utf8Value type(args[1]);
+  if (!strcmp(*type, "character")) {
+    break_iterator =
+        icu::BreakIterator::createCharacterInstance(icu_locale, status);
+  } else if (!strcmp(*type, "word")) {
+    break_iterator =
+        icu::BreakIterator::createWordInstance(icu_locale, status);
+  } else if (!strcmp(*type, "sentence")) {
+    break_iterator =
+        icu::BreakIterator::createSentenceInstance(icu_locale, status);
+  } else if (!strcmp(*type, "line")) {
+    break_iterator =
+        icu::BreakIterator::createLineInstance(icu_locale, status);
+  } else {
+    return v8::ThrowException(v8::Exception::SyntaxError(
+        v8::String::New("Invalid iterator type.")));
+  }
+
+  if (U_FAILURE(status)) {
+    delete break_iterator;
+    return v8::ThrowException(v8::Exception::Error(
+        v8::String::New("Failed to create break iterator.")));
+  }
+
+  if (break_iterator_template_.IsEmpty()) {
+    v8::Local<v8::FunctionTemplate> raw_template(v8::FunctionTemplate::New());
+
+    raw_template->SetClassName(v8::String::New("v8Locale.v8BreakIterator"));
+
+    // Define internal field count on instance template.
+    v8::Local<v8::ObjectTemplate> object_template =
+        raw_template->InstanceTemplate();
+
+    // Set aside internal fields for icu break iterator and adopted text.
+    object_template->SetInternalFieldCount(2);
+
+    // Define all of the prototype methods on prototype template.
+    v8::Local<v8::ObjectTemplate> proto = raw_template->PrototypeTemplate();
+    proto->Set(v8::String::New("adoptText"),
+               v8::FunctionTemplate::New(BreakIteratorAdoptText));
+    proto->Set(v8::String::New("first"),
+               v8::FunctionTemplate::New(BreakIteratorFirst));
+    proto->Set(v8::String::New("next"),
+               v8::FunctionTemplate::New(BreakIteratorNext));
+    proto->Set(v8::String::New("current"),
+               v8::FunctionTemplate::New(BreakIteratorCurrent));
+    proto->Set(v8::String::New("breakType"),
+               v8::FunctionTemplate::New(BreakIteratorBreakType));
+
+    break_iterator_template_ =
+        v8::Persistent<v8::FunctionTemplate>::New(raw_template);
+  }
+
+  // Create an empty object wrapper.
+  v8::Local<v8::Object> local_object =
+      break_iterator_template_->GetFunction()->NewInstance();
+  v8::Persistent<v8::Object> wrapper =
+      v8::Persistent<v8::Object>::New(local_object);
+
+  // Set break iterator as internal field of the resulting JS object.
+  wrapper->SetPointerInInternalField(0, break_iterator);
+  // Make sure that the pointer to adopted text is NULL.
+  wrapper->SetPointerInInternalField(1, NULL);
+
+  // Make object handle weak so we can delete iterator once GC kicks in.
+  wrapper.MakeWeak(NULL, DeleteBreakIterator);
+
+  return wrapper;
+}
+
+} }  // namespace v8::internal
diff --git a/src/extensions/experimental/break-iterator.h b/src/extensions/experimental/break-iterator.h
new file mode 100644
index 0000000..473bc89
--- /dev/null
+++ b/src/extensions/experimental/break-iterator.h
@@ -0,0 +1,89 @@
+// 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_EXTENSIONS_EXPERIMENTAL_BREAK_ITERATOR_H_
+#define V8_EXTENSIONS_EXPERIMENTAL_BREAK_ITERATOR_H_
+
+#include <v8.h>
+
+#include "unicode/uversion.h"
+
+namespace U_ICU_NAMESPACE {
+class BreakIterator;
+class UnicodeString;
+}
+
+namespace v8 {
+namespace internal {
+
+class BreakIterator {
+ public:
+  static v8::Handle<v8::Value> JSBreakIterator(const v8::Arguments& args);
+
+  // Helper methods for various bindings.
+
+  // Unpacks break iterator object from corresponding JavaScript object.
+  static icu::BreakIterator* UnpackBreakIterator(v8::Handle<v8::Object> obj);
+
+  // Deletes the old value and sets the adopted text in
+  // corresponding JavaScript object.
+  static UnicodeString* ResetAdoptedText(v8::Handle<v8::Object> obj,
+                                         v8::Handle<v8::Value> text_value);
+
+  // Release memory we allocated for the BreakIterator once the JS object that
+  // holds the pointer gets garbage collected.
+  static void DeleteBreakIterator(v8::Persistent<v8::Value> object,
+                                  void* param);
+
+  // Assigns new text to the iterator.
+  static v8::Handle<v8::Value> BreakIteratorAdoptText(
+      const v8::Arguments& args);
+
+  // Moves iterator to the beginning of the string and returns new position.
+  static v8::Handle<v8::Value> BreakIteratorFirst(const v8::Arguments& args);
+
+  // Moves iterator to the next position and returns it.
+  static v8::Handle<v8::Value> BreakIteratorNext(const v8::Arguments& args);
+
+  // Returns current iterator's current position.
+  static v8::Handle<v8::Value> BreakIteratorCurrent(
+      const v8::Arguments& args);
+
+  // Returns type of the item from current position.
+  // This call is only valid for word break iterators. Others just return 0.
+  static v8::Handle<v8::Value> BreakIteratorBreakType(
+      const v8::Arguments& args);
+
+ private:
+  BreakIterator() {}
+
+  static v8::Persistent<v8::FunctionTemplate> break_iterator_template_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_EXTENSIONS_EXPERIMENTAL_BREAK_ITERATOR_H_
diff --git a/src/extensions/experimental/experimental.gyp b/src/extensions/experimental/experimental.gyp
index 4d7a936..761f4c7 100644
--- a/src/extensions/experimental/experimental.gyp
+++ b/src/extensions/experimental/experimental.gyp
@@ -37,6 +37,8 @@
       'target_name': 'i18n_api',
       'type': 'static_library',
       'sources': [
+        'break-iterator.cc',
+        'break-iterator.h',
         'i18n-extension.cc',
         'i18n-extension.h',
       ],
diff --git a/src/extensions/experimental/i18n-extension.cc b/src/extensions/experimental/i18n-extension.cc
index a721ba5..e65fdcc 100644
--- a/src/extensions/experimental/i18n-extension.cc
+++ b/src/extensions/experimental/i18n-extension.cc
@@ -30,6 +30,7 @@
 #include <algorithm>
 #include <string>
 
+#include "break-iterator.h"
 #include "unicode/locid.h"
 #include "unicode/uloc.h"
 
@@ -87,6 +88,23 @@
   "  var displayLocale = this.displayLocale_(optDisplayLocale);"
   "  native function NativeJSDisplayName();"
   "  return NativeJSDisplayName(this.locale, displayLocale);"
+  "};"
+  "v8Locale.v8BreakIterator = function(locale, type) {"
+  "  native function NativeJSBreakIterator();"
+  "  var iterator = NativeJSBreakIterator(locale, type);"
+  "  iterator.type = type;"
+  "  return iterator;"
+  "};"
+  "v8Locale.v8BreakIterator.BreakType = {"
+  "  'unknown': -1,"
+  "  'none': 0,"
+  "  'number': 100,"
+  "  'word': 200,"
+  "  'kana': 300,"
+  "  'ideo': 400"
+  "};"
+  "v8Locale.prototype.v8CreateBreakIterator = function(type) {"
+  "  return new v8Locale.v8BreakIterator(this.locale, type);"
   "};";
 
 v8::Handle<v8::FunctionTemplate> I18NExtension::GetNativeFunction(
@@ -107,6 +125,8 @@
     return v8::FunctionTemplate::New(JSDisplayRegion);
   } else if (name->Equals(v8::String::New("NativeJSDisplayName"))) {
     return v8::FunctionTemplate::New(JSDisplayName);
+  } else if (name->Equals(v8::String::New("NativeJSBreakIterator"))) {
+    return v8::FunctionTemplate::New(BreakIterator::JSBreakIterator);
   }
 
   return v8::Handle<v8::FunctionTemplate>();
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 57defdc..2566766 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -97,11 +97,7 @@
 #define FLAG FLAG_FULL
 
 // Flags for Crankshaft.
-#ifdef V8_TARGET_ARCH_IA32
 DEFINE_bool(crankshaft, true, "use crankshaft")
-#else
-DEFINE_bool(crankshaft, false, "use crankshaft")
-#endif
 DEFINE_string(hydrogen_filter, "", "hydrogen use/trace filter")
 DEFINE_bool(use_hydrogen, true, "use generated hydrogen for compilation")
 DEFINE_bool(build_lithium, true, "use lithium chunk builder")
@@ -110,7 +106,6 @@
 DEFINE_bool(use_range, true, "use hydrogen range analysis")
 DEFINE_bool(eliminate_dead_phis, true, "eliminate dead phis")
 DEFINE_bool(use_gvn, true, "use hydrogen global value numbering")
-DEFINE_bool(use_peeling, false, "use loop peeling")
 DEFINE_bool(use_canonicalizing, true, "use hydrogen instruction canonicalizing")
 DEFINE_bool(use_inlining, true, "use function inlining")
 DEFINE_bool(limit_inlining, true, "limit code size growth from inlining")
@@ -120,6 +115,7 @@
 DEFINE_bool(trace_hydrogen, false, "trace generated hydrogen to file")
 DEFINE_bool(trace_inlining, false, "trace inlining decisions")
 DEFINE_bool(trace_alloc, false, "trace register allocator")
+DEFINE_bool(trace_all_uses, false, "trace all use positions")
 DEFINE_bool(trace_range, false, "trace range analysis")
 DEFINE_bool(trace_gvn, false, "trace global value numbering")
 DEFINE_bool(trace_representation, false, "trace representation types")
@@ -134,11 +130,8 @@
 DEFINE_bool(polymorphic_inlining, true, "polymorphic inlining")
 DEFINE_bool(aggressive_loop_invariant_motion, true,
             "aggressive motion of instructions out of loops")
-#ifdef V8_TARGET_ARCH_IA32
 DEFINE_bool(use_osr, true, "use on-stack replacement")
-#else
-DEFINE_bool(use_osr, false, "use on-stack replacement")
-#endif
+
 DEFINE_bool(trace_osr, false, "trace on-stack replacement")
 DEFINE_int(stress_runs, 0, "number of stress runs")
 DEFINE_bool(optimize_closures, true, "optimize closures")
@@ -269,6 +262,12 @@
 // ic.cc
 DEFINE_bool(use_ic, true, "use inline caching")
 
+#ifdef LIVE_OBJECT_LIST
+// liveobjectlist.cc
+DEFINE_string(lol_workdir, NULL, "path for lol temp files")
+DEFINE_bool(verify_lol, false, "perform debugging verification for lol")
+#endif
+
 // macro-assembler-ia32.cc
 DEFINE_bool(native_code_counters, false,
             "generate extra code for manipulating stats counters")
@@ -357,7 +356,7 @@
                                     "debugger agent in another process")
 DEFINE_bool(debugger_agent, false, "Enable debugger agent")
 DEFINE_int(debugger_port, 5858, "Port to use for remote debugging")
-DEFINE_string(map_counters, NULL, "Map counters to a file")
+DEFINE_string(map_counters, "", "Map counters to a file")
 DEFINE_args(js_arguments, JSArguments(),
             "Pass all remaining arguments to the script. Alias for \"--\".")
 
@@ -378,6 +377,7 @@
 
 DEFINE_bool(gdbjit, false, "enable GDBJIT interface (disables compacting GC)")
 DEFINE_bool(gdbjit_full, false, "enable GDBJIT interface for all code objects")
+DEFINE_bool(gdbjit_dump, false, "dump elf objects with debug info to disk")
 
 //
 // Debug only flags
diff --git a/src/frame-element.h b/src/frame-element.h
index 3b91b9d..ae5d6a1 100644
--- a/src/frame-element.h
+++ b/src/frame-element.h
@@ -113,6 +113,10 @@
 
   static ZoneObjectList* ConstantList();
 
+  static bool ConstantPoolOverflowed() {
+    return !DataField::is_valid(ConstantList()->length());
+  }
+
   // Clear the constants indirection table.
   static void ClearConstantList() {
     ConstantList()->Clear();
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index 252fb92..b3dc95b 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -739,25 +739,13 @@
     case Token::SHL:
     case Token::SHR:
     case Token::SAR: {
-      // Figure out if either of the operands is a constant.
-      ConstantOperand constant = ShouldInlineSmiCase(op)
-          ? GetConstantOperand(op, left, right)
-          : kNoConstants;
-
-      // Load only the operands that we need to materialize.
-      if (constant == kNoConstants) {
-        VisitForStackValue(left);
-        VisitForAccumulatorValue(right);
-      } else if (constant == kRightConstant) {
-        VisitForAccumulatorValue(left);
-      } else {
-        ASSERT(constant == kLeftConstant);
-        VisitForAccumulatorValue(right);
-      }
+      // Load both operands.
+      VisitForStackValue(left);
+      VisitForAccumulatorValue(right);
 
       SetSourcePosition(expr->position());
       if (ShouldInlineSmiCase(op)) {
-        EmitInlineSmiBinaryOp(expr, op, mode, left, right, constant);
+        EmitInlineSmiBinaryOp(expr, op, mode, left, right);
       } else {
         EmitBinaryOp(op, mode);
       }
diff --git a/src/full-codegen.h b/src/full-codegen.h
index 655e560..5fb11b4 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -274,12 +274,6 @@
     ForwardBailoutStack* const parent_;
   };
 
-  enum ConstantOperand {
-    kNoConstants,
-    kLeftConstant,
-    kRightConstant
-  };
-
   // Type of a member function that generates inline code for a native function.
   typedef void (FullCodeGenerator::*InlineFunctionGenerator)
       (ZoneList<Expression*>*);
@@ -298,11 +292,6 @@
   // operation.
   bool ShouldInlineSmiCase(Token::Value op);
 
-  // Compute which (if any) of the operands is a compile-time constant.
-  ConstantOperand GetConstantOperand(Token::Value op,
-                                     Expression* left,
-                                     Expression* right);
-
   // Helper function to convert a pure value into a test context.  The value
   // is expected on the stack or the accumulator, depending on the platform.
   // See the platform-specific implementation for details.
@@ -432,6 +421,14 @@
                                        Label* done);
   void EmitVariableLoad(Variable* expr);
 
+  enum ResolveEvalFlag {
+    SKIP_CONTEXT_LOOKUP,
+    PERFORM_CONTEXT_LOOKUP
+  };
+
+  // Expects the arguments and the function already pushed.
+  void EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, int arg_count);
+
   // Platform-specific support for allocating a new closure based on
   // the given function info.
   void EmitNewClosure(Handle<SharedFunctionInfo> info, bool pretenure);
@@ -457,34 +454,7 @@
                              Token::Value op,
                              OverwriteMode mode,
                              Expression* left,
-                             Expression* right,
-                             ConstantOperand constant);
-
-  void EmitConstantSmiBinaryOp(Expression* expr,
-                               Token::Value op,
-                               OverwriteMode mode,
-                               bool left_is_constant_smi,
-                               Smi* value);
-
-  void EmitConstantSmiBitOp(Expression* expr,
-                            Token::Value op,
-                            OverwriteMode mode,
-                            Smi* value);
-
-  void EmitConstantSmiShiftOp(Expression* expr,
-                              Token::Value op,
-                              OverwriteMode mode,
-                              Smi* value);
-
-  void EmitConstantSmiAdd(Expression* expr,
-                          OverwriteMode mode,
-                          bool left_is_constant_smi,
-                          Smi* value);
-
-  void EmitConstantSmiSub(Expression* expr,
-                          OverwriteMode mode,
-                          bool left_is_constant_smi,
-                          Smi* value);
+                             Expression* right);
 
   // Assign to the given expression as if via '='. The right-hand-side value
   // is expected in the accumulator.
diff --git a/src/gdb-jit.cc b/src/gdb-jit.cc
index c26ecf5..5136ded 100644
--- a/src/gdb-jit.cc
+++ b/src/gdb-jit.cc
@@ -395,7 +395,7 @@
   void WriteHeader(Writer* w) {
     ASSERT(w->position() == 0);
     Writer::Slot<ELFHeader> header = w->CreateSlotHere<ELFHeader>();
-#if defined(V8_TARGET_ARCH_IA32)
+#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_ARM)
     const uint8_t ident[16] =
         { 0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 #elif defined(V8_TARGET_ARCH_X64)
@@ -413,6 +413,10 @@
     //    System V ABI, AMD64 Supplement
     //    http://www.x86-64.org/documentation/abi.pdf
     header->machine = 62;
+#elif defined(V8_TARGET_ARCH_ARM)
+    // Set to EM_ARM, defined as 40, in "ARM ELF File Format" at
+    // infocenter.arm.com/help/topic/com.arm.doc.dui0101a/DUI0101A_Elf.pdf
+    header->machine = 40;
 #else
 #error Unsupported target architecture.
 #endif
@@ -503,8 +507,7 @@
   Binding binding() const {
     return static_cast<Binding>(info >> 4);
   }
-
-#if defined(V8_TARGET_ARCH_IA32)
+#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_ARM)
   struct SerializedLayout {
     SerializedLayout(uint32_t name,
                      uintptr_t value,
@@ -857,14 +860,20 @@
     Writer::Slot<uint32_t> total_length = w->CreateSlotHere<uint32_t>();
     uintptr_t start = w->position();
 
+    // Used for special opcodes
+    const int8_t line_base = 1;
+    const uint8_t line_range = 7;
+    const int8_t max_line_incr = (line_base + line_range - 1);
+    const uint8_t opcode_base = DW_LNS_NEGATE_STMT + 1;
+
     w->Write<uint16_t>(2);  // Field version.
     Writer::Slot<uint32_t> prologue_length = w->CreateSlotHere<uint32_t>();
     uintptr_t prologue_start = w->position();
     w->Write<uint8_t>(1);  // Field minimum_instruction_length.
     w->Write<uint8_t>(1);  // Field default_is_stmt.
-    w->Write<int8_t>(0);  // Field line_base.
-    w->Write<uint8_t>(2);  // Field line_range.
-    w->Write<uint8_t>(DW_LNS_NEGATE_STMT + 1);  // Field opcode_base.
+    w->Write<int8_t>(line_base);  // Field line_base.
+    w->Write<uint8_t>(line_range);  // Field line_range.
+    w->Write<uint8_t>(opcode_base);  // Field opcode_base.
     w->Write<uint8_t>(0);  // DW_LNS_COPY operands count.
     w->Write<uint8_t>(1);  // DW_LNS_ADVANCE_PC operands count.
     w->Write<uint8_t>(1);  // DW_LNS_ADVANCE_LINE operands count.
@@ -881,6 +890,7 @@
 
     WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS, sizeof(intptr_t));
     w->Write<intptr_t>(desc_->CodeStart());
+    w->Write<uint8_t>(DW_LNS_COPY);
 
     intptr_t pc = 0;
     intptr_t line = 1;
@@ -888,29 +898,66 @@
 
     List<GDBJITLineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
     pc_info->Sort(&ComparePCInfo);
-    for (int i = 0; i < pc_info->length(); i++) {
+
+    int pc_info_length = pc_info->length();
+    for (int i = 0; i < pc_info_length; i++) {
       GDBJITLineInfo::PCInfo* info = &pc_info->at(i);
-      uintptr_t pc_diff = info->pc_ - pc;
       ASSERT(info->pc_ >= pc);
-      if (pc_diff != 0) {
-        w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
-        w->WriteSLEB128(pc_diff);
-        pc += pc_diff;
+
+      // Reduce bloating in the debug line table by removing duplicate line
+      // entries (per DWARF2 standard).
+      intptr_t  new_line = desc_->GetScriptLineNumber(info->pos_);
+      if (new_line == line) {
+        continue;
       }
-      intptr_t line_diff = desc_->GetScriptLineNumber(info->pos_) - line;
-      if (line_diff != 0) {
-        w->Write<uint8_t>(DW_LNS_ADVANCE_LINE);
-        w->WriteSLEB128(line_diff);
-        line += line_diff;
-      }
-      if (is_statement != info->is_statement_) {
+
+      // Mark statement boundaries.  For a better debugging experience, mark
+      // the last pc address in the function as a statement (e.g. "}"), so that
+      // a user can see the result of the last line executed in the function,
+      // should control reach the end.
+      if ((i+1) == pc_info_length) {
+        if (!is_statement) {
+          w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
+        }
+      } else if (is_statement != info->is_statement_) {
         w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
         is_statement = !is_statement;
       }
-      if (pc_diff != 0 || i == 0) {
+
+      // Generate special opcodes, if possible.  This results in more compact
+      // debug line tables.  See the DWARF 2.0 standard to learn more about
+      // special opcodes.
+      uintptr_t pc_diff = info->pc_ - pc;
+      intptr_t line_diff = new_line - line;
+
+      // Compute special opcode (see DWARF 2.0 standard)
+      intptr_t special_opcode = (line_diff - line_base) +
+                                (line_range * pc_diff) + opcode_base;
+
+      // If special_opcode is less than or equal to 255, it can be used as a
+      // special opcode.  If line_diff is larger than the max line increment
+      // allowed for a special opcode, or if line_diff is less than the minimum
+      // line that can be added to the line register (i.e. line_base), then
+      // special_opcode can't be used.
+      if ((special_opcode >= opcode_base) && (special_opcode <= 255) &&
+          (line_diff <= max_line_incr) && (line_diff >= line_base)) {
+        w->Write<uint8_t>(special_opcode);
+      } else {
+        w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
+        w->WriteSLEB128(pc_diff);
+        w->Write<uint8_t>(DW_LNS_ADVANCE_LINE);
+        w->WriteSLEB128(line_diff);
         w->Write<uint8_t>(DW_LNS_COPY);
       }
+
+      // Increment the pc and line operands.
+      pc += pc_diff;
+      line += line_diff;
     }
+    // Advance the pc to the end of the routine, since the end sequence opcode
+    // requires this.
+    w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
+    w->WriteSLEB128(desc_->CodeSize() - pc);
     WriteExtendedOpcode(w, DW_LNE_END_SEQUENCE, 0);
     total_length.set(static_cast<uint32_t>(w->position() - start));
     return true;
@@ -1237,6 +1284,20 @@
 
 
 static void RegisterCodeEntry(JITCodeEntry* entry) {
+#if defined(DEBUG) && !defined(WIN32)
+  static int file_num = 0;
+  if (FLAG_gdbjit_dump) {
+    static const int kMaxFileNameSize = 64;
+    static const char* kElfFilePrefix = "/tmp/elfdump";
+    static const char* kObjFileExt = ".o";
+    char file_name[64];
+
+    OS::SNPrintF(Vector<char>(file_name, kMaxFileNameSize), "%s%d%s",
+                 kElfFilePrefix, file_num++, kObjFileExt);
+    WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_);
+  }
+#endif
+
   entry->next_ = __jit_debug_descriptor.first_entry_;
   if (entry->next_ != NULL) entry->next_->prev_ = entry;
   __jit_debug_descriptor.first_entry_ =
@@ -1294,7 +1355,13 @@
 }
 
 
-static HashMap entries(&SameCodeObjects);
+static HashMap* GetEntries() {
+  static HashMap* entries = NULL;
+  if (entries == NULL) {
+    entries = new HashMap(&SameCodeObjects);
+  }
+  return entries;
+}
 
 
 static uint32_t HashForCodeObject(Code* code) {
@@ -1344,9 +1411,8 @@
 #ifdef V8_TARGET_ARCH_X64
   if (desc->tag() == GDBJITInterface::FUNCTION) {
     // To avoid propagating unwinding information through
-    // compilation pipeline we rely on function prologue
-    // and epilogue being the same for all code objects generated
-    // by the full code generator.
+    // compilation pipeline we use an approximation.
+    // For most use cases this should not affect usability.
     static const int kFramePointerPushOffset = 1;
     static const int kFramePointerSetOffset = 4;
     static const int kFramePointerPopOffset = -3;
@@ -1360,19 +1426,6 @@
     uintptr_t frame_pointer_pop_address =
         desc->CodeEnd() + kFramePointerPopOffset;
 
-#ifdef DEBUG
-    static const uint8_t kFramePointerPushInstruction = 0x48;  // push ebp
-    static const uint16_t kFramePointerSetInstruction = 0x5756;  // mov ebp, esp
-    static const uint8_t kFramePointerPopInstruction = 0xBE;  // pop ebp
-
-    ASSERT(*reinterpret_cast<uint8_t*>(frame_pointer_push_address) ==
-           kFramePointerPushInstruction);
-    ASSERT(*reinterpret_cast<uint16_t*>(frame_pointer_set_address) ==
-           kFramePointerSetInstruction);
-    ASSERT(*reinterpret_cast<uint8_t*>(frame_pointer_pop_address) ==
-           kFramePointerPopInstruction);
-#endif
-
     desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
                                     frame_pointer_push_address);
     desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
@@ -1398,7 +1451,7 @@
   if (!FLAG_gdbjit) return;
   AssertNoAllocation no_gc;
 
-  HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true);
+  HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
   if (e->value != NULL && !IsLineInfoTagged(e->value)) return;
 
   GDBJITLineInfo* lineinfo = UntagLineInfo(e->value);
@@ -1411,7 +1464,7 @@
 
   if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
     delete lineinfo;
-    entries.Remove(code, HashForCodeObject(code));
+    GetEntries()->Remove(code, HashForCodeObject(code));
     return;
   }
 
@@ -1464,7 +1517,9 @@
 void GDBJITInterface::RemoveCode(Code* code) {
   if (!FLAG_gdbjit) return;
 
-  HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), false);
+  HashMap::Entry* e = GetEntries()->Lookup(code,
+                                           HashForCodeObject(code),
+                                           false);
   if (e == NULL) return;
 
   if (IsLineInfoTagged(e->value)) {
@@ -1475,14 +1530,14 @@
     DestroyCodeEntry(entry);
   }
   e->value = NULL;
-  entries.Remove(code, HashForCodeObject(code));
+  GetEntries()->Remove(code, HashForCodeObject(code));
 }
 
 
 void GDBJITInterface::RegisterDetailedLineInfo(Code* code,
                                                GDBJITLineInfo* line_info) {
   ASSERT(!IsLineInfoTagged(line_info));
-  HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true);
+  HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
   ASSERT(e->value == NULL);
   e->value = TagLineInfo(line_info);
 }
diff --git a/src/handles-inl.h b/src/handles-inl.h
index b313512..c0f2fda 100644
--- a/src/handles-inl.h
+++ b/src/handles-inl.h
@@ -36,14 +36,14 @@
 namespace v8 {
 namespace internal {
 
-template<class T>
+template<typename T>
 Handle<T>::Handle(T* obj) {
   ASSERT(!obj->IsFailure());
   location_ = HandleScope::CreateHandle(obj);
 }
 
 
-template <class T>
+template <typename T>
 inline T* Handle<T>::operator*() const {
   ASSERT(location_ != NULL);
   ASSERT(reinterpret_cast<Address>(*location_) != kHandleZapValue);
diff --git a/src/handles.cc b/src/handles.cc
index d625d64..efef095 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -242,17 +242,21 @@
 Handle<Object> SetProperty(Handle<JSObject> object,
                            Handle<String> key,
                            Handle<Object> value,
-                           PropertyAttributes attributes) {
-  CALL_HEAP_FUNCTION(object->SetProperty(*key, *value, attributes), Object);
+                           PropertyAttributes attributes,
+                           StrictModeFlag strict_mode) {
+  CALL_HEAP_FUNCTION(object->SetProperty(*key, *value, attributes, strict_mode),
+                     Object);
 }
 
 
 Handle<Object> SetProperty(Handle<Object> object,
                            Handle<Object> key,
                            Handle<Object> value,
-                           PropertyAttributes attributes) {
+                           PropertyAttributes attributes,
+                           StrictModeFlag strict_mode) {
   CALL_HEAP_FUNCTION(
-      Runtime::SetObjectProperty(object, key, value, attributes), Object);
+      Runtime::SetObjectProperty(object, key, value, attributes, strict_mode),
+      Object);
 }
 
 
@@ -261,7 +265,9 @@
                                 Handle<Object> value,
                                 PropertyAttributes attributes) {
   CALL_HEAP_FUNCTION(
-      Runtime::ForceSetObjectProperty(object, key, value, attributes), Object);
+      Runtime::ForceSetObjectProperty(
+          object, key, value, attributes),
+      Object);
 }
 
 
@@ -304,10 +310,12 @@
 Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object,
                                           Handle<String> key,
                                           Handle<Object> value,
-                                          PropertyAttributes attributes) {
+                                          PropertyAttributes attributes,
+                                          StrictModeFlag strict_mode) {
   CALL_HEAP_FUNCTION(object->SetPropertyWithInterceptor(*key,
                                                         *value,
-                                                        attributes),
+                                                        attributes,
+                                                        strict_mode),
                      Object);
 }
 
@@ -420,7 +428,8 @@
 
 Handle<Object> SetElement(Handle<JSObject> object,
                           uint32_t index,
-                          Handle<Object> value) {
+                          Handle<Object> value,
+                          StrictModeFlag strict_mode) {
   if (object->HasPixelElements() || object->HasExternalArrayElements()) {
     if (!value->IsSmi() && !value->IsHeapNumber() && !value->IsUndefined()) {
       bool has_exception;
@@ -429,16 +438,18 @@
       value = number;
     }
   }
-  CALL_HEAP_FUNCTION(object->SetElement(index, *value), Object);
+  CALL_HEAP_FUNCTION(object->SetElement(index, *value, strict_mode), Object);
 }
 
 
 Handle<Object> SetOwnElement(Handle<JSObject> object,
                              uint32_t index,
-                             Handle<Object> value) {
+                             Handle<Object> value,
+                             StrictModeFlag strict_mode) {
   ASSERT(!object->HasPixelElements());
   ASSERT(!object->HasExternalArrayElements());
-  CALL_HEAP_FUNCTION(object->SetElement(index, *value, false), Object);
+  CALL_HEAP_FUNCTION(object->SetElement(index, *value, strict_mode, false),
+                     Object);
 }
 
 
@@ -834,49 +845,41 @@
 }
 
 
-bool CompileLazy(Handle<JSFunction> function,
-                 ClearExceptionFlag flag) {
+static bool CompileLazyFunction(Handle<JSFunction> function,
+                                ClearExceptionFlag flag,
+                                InLoopFlag in_loop_flag) {
   bool result = true;
   if (function->shared()->is_compiled()) {
     function->ReplaceCode(function->shared()->code());
     function->shared()->set_code_age(0);
   } else {
     CompilationInfo info(function);
+    if (in_loop_flag == IN_LOOP) info.MarkAsInLoop();
     result = CompileLazyHelper(&info, flag);
     ASSERT(!result || function->is_compiled());
   }
-  if (result && function->is_compiled()) {
-    PROFILE(FunctionCreateEvent(*function));
-  }
   return result;
 }
 
 
+bool CompileLazy(Handle<JSFunction> function,
+                 ClearExceptionFlag flag) {
+  return CompileLazyFunction(function, flag, NOT_IN_LOOP);
+}
+
+
 bool CompileLazyInLoop(Handle<JSFunction> function,
                        ClearExceptionFlag flag) {
-  bool result = true;
-  if (function->shared()->is_compiled()) {
-    function->ReplaceCode(function->shared()->code());
-    function->shared()->set_code_age(0);
-  } else {
-    CompilationInfo info(function);
-    info.MarkAsInLoop();
-    result = CompileLazyHelper(&info, flag);
-    ASSERT(!result || function->is_compiled());
-  }
-  if (result && function->is_compiled()) {
-    PROFILE(FunctionCreateEvent(*function));
-  }
-  return result;
+  return CompileLazyFunction(function, flag, IN_LOOP);
 }
 
 
-bool CompileOptimized(Handle<JSFunction> function, int osr_ast_id) {
+bool CompileOptimized(Handle<JSFunction> function,
+                      int osr_ast_id,
+                      ClearExceptionFlag flag) {
   CompilationInfo info(function);
   info.SetOptimizing(osr_ast_id);
-  bool result = CompileLazyHelper(&info, KEEP_EXCEPTION);
-  if (result) PROFILE(FunctionCreateEvent(*function));
-  return result;
+  return CompileLazyHelper(&info, flag);
 }
 
 
diff --git a/src/handles.h b/src/handles.h
index d95ca91..bb51968 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -39,7 +39,7 @@
 // Handles are only valid within a HandleScope.
 // When a handle is created for an object a cell is allocated in the heap.
 
-template<class T>
+template<typename T>
 class Handle {
  public:
   INLINE(explicit Handle(T** location)) { location_ = location; }
@@ -112,15 +112,7 @@
   }
 
   ~HandleScope() {
-    current_.next = prev_next_;
-    current_.level--;
-    if (current_.limit != prev_limit_) {
-      current_.limit = prev_limit_;
-      DeleteExtensions();
-    }
-#ifdef DEBUG
-    ZapRange(prev_next_, prev_limit_);
-#endif
+    CloseScope();
   }
 
   // Counts the number of allocated handles.
@@ -148,6 +140,26 @@
   static Address current_limit_address();
   static Address current_level_address();
 
+  // Closes the HandleScope (invalidating all handles
+  // created in the scope of the HandleScope) and returns
+  // a Handle backed by the parent scope holding the
+  // value of the argument handle.
+  template <typename T>
+  Handle<T> CloseAndEscape(Handle<T> handle_value) {
+    T* value = *handle_value;
+    // Throw away all handles in the current scope.
+    CloseScope();
+    // Allocate one handle in the parent scope.
+    ASSERT(current_.level > 0);
+    Handle<T> result(CreateHandle<T>(value));
+    // Reinitialize the current scope (so that it's ready
+    // to be used or closed again).
+    prev_next_ = current_.next;
+    prev_limit_ = current_.limit;
+    current_.level++;
+    return result;
+  }
+
  private:
   // Prevent heap allocation or illegal handle scopes.
   HandleScope(const HandleScope&);
@@ -155,9 +167,23 @@
   void* operator new(size_t size);
   void operator delete(void* size_t);
 
+  inline void CloseScope() {
+    current_.next = prev_next_;
+    current_.level--;
+    if (current_.limit != prev_limit_) {
+      current_.limit = prev_limit_;
+      DeleteExtensions();
+    }
+#ifdef DEBUG
+    ZapRange(prev_next_, prev_limit_);
+#endif
+  }
+
   static v8::ImplementationUtilities::HandleScopeData current_;
-  Object** const prev_next_;
-  Object** const prev_limit_;
+  // Holds values on entry. The prev_next_ value is never NULL
+  // on_entry, but is set to NULL when this scope is closed.
+  Object** prev_next_;
+  Object** prev_limit_;
 
   // Extend the handle scope making room for more handles.
   static internal::Object** Extend();
@@ -197,12 +223,14 @@
 Handle<Object> SetProperty(Handle<JSObject> object,
                            Handle<String> key,
                            Handle<Object> value,
-                           PropertyAttributes attributes);
+                           PropertyAttributes attributes,
+                           StrictModeFlag strict_mode);
 
 Handle<Object> SetProperty(Handle<Object> object,
                            Handle<Object> key,
                            Handle<Object> value,
-                           PropertyAttributes attributes);
+                           PropertyAttributes attributes,
+                           StrictModeFlag strict_mode);
 
 Handle<Object> ForceSetProperty(Handle<JSObject> object,
                                 Handle<Object> key,
@@ -233,15 +261,18 @@
 Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object,
                                           Handle<String> key,
                                           Handle<Object> value,
-                                          PropertyAttributes attributes);
+                                          PropertyAttributes attributes,
+                                          StrictModeFlag strict_mode);
 
 Handle<Object> SetElement(Handle<JSObject> object,
                           uint32_t index,
-                          Handle<Object> value);
+                          Handle<Object> value,
+                          StrictModeFlag strict_mode);
 
 Handle<Object> SetOwnElement(Handle<JSObject> object,
                              uint32_t index,
-                             Handle<Object> value);
+                             Handle<Object> value,
+                             StrictModeFlag strict_mode);
 
 Handle<Object> GetProperty(Handle<JSObject> obj,
                            const char* name);
@@ -354,7 +385,9 @@
 
 bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag flag);
 
-bool CompileOptimized(Handle<JSFunction> function, int osr_ast_id);
+bool CompileOptimized(Handle<JSFunction> function,
+                      int osr_ast_id,
+                      ClearExceptionFlag flag);
 
 class NoHandleAllocation BASE_EMBEDDED {
  public:
diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc
index 732d2f4..07b631f 100644
--- a/src/heap-profiler.cc
+++ b/src/heap-profiler.cc
@@ -911,22 +911,27 @@
 class CountingRetainersIterator {
  public:
   CountingRetainersIterator(const JSObjectsCluster& child_cluster,
+                            HeapEntriesAllocator* allocator,
                             HeapEntriesMap* map)
-      : child_(ClusterAsHeapObject(child_cluster)), map_(map) {
+      : child_(ClusterAsHeapObject(child_cluster)),
+        allocator_(allocator),
+        map_(map) {
     if (map_->Map(child_) == NULL)
-      map_->Pair(child_, HeapEntriesMap::kHeapEntryPlaceholder);
+      map_->Pair(child_, allocator_, HeapEntriesMap::kHeapEntryPlaceholder);
   }
 
   void Call(const JSObjectsCluster& cluster,
             const NumberAndSizeInfo& number_and_size) {
     if (map_->Map(ClusterAsHeapObject(cluster)) == NULL)
       map_->Pair(ClusterAsHeapObject(cluster),
+                 allocator_,
                  HeapEntriesMap::kHeapEntryPlaceholder);
     map_->CountReference(ClusterAsHeapObject(cluster), child_);
   }
 
  private:
   HeapObject* child_;
+  HeapEntriesAllocator* allocator_;
   HeapEntriesMap* map_;
 };
 
@@ -934,6 +939,7 @@
 class AllocatingRetainersIterator {
  public:
   AllocatingRetainersIterator(const JSObjectsCluster& child_cluster,
+                              HeapEntriesAllocator*,
                               HeapEntriesMap* map)
       : child_(ClusterAsHeapObject(child_cluster)), map_(map) {
     child_entry_ = map_->Map(child_);
@@ -966,8 +972,9 @@
 class AggregatingRetainerTreeIterator {
  public:
   explicit AggregatingRetainerTreeIterator(ClustersCoarser* coarser,
+                                           HeapEntriesAllocator* allocator,
                                            HeapEntriesMap* map)
-      : coarser_(coarser), map_(map) {
+      : coarser_(coarser), allocator_(allocator), map_(map) {
   }
 
   void Call(const JSObjectsCluster& cluster, JSObjectsClusterTree* tree) {
@@ -981,25 +988,28 @@
       tree->ForEach(&retainers_aggregator);
       tree_to_iterate = &dest_tree_;
     }
-    RetainersIterator iterator(cluster, map_);
+    RetainersIterator iterator(cluster, allocator_, map_);
     tree_to_iterate->ForEach(&iterator);
   }
 
  private:
   ClustersCoarser* coarser_;
+  HeapEntriesAllocator* allocator_;
   HeapEntriesMap* map_;
 };
 
 
-class AggregatedRetainerTreeAllocator {
+class AggregatedRetainerTreeAllocator : public HeapEntriesAllocator {
  public:
   AggregatedRetainerTreeAllocator(HeapSnapshot* snapshot,
                                   int* root_child_index)
       : snapshot_(snapshot), root_child_index_(root_child_index) {
   }
+  ~AggregatedRetainerTreeAllocator() { }
 
-  HeapEntry* GetEntry(
-      HeapObject* obj, int children_count, int retainers_count) {
+  HeapEntry* AllocateEntry(
+      HeapThing ptr, int children_count, int retainers_count) {
+    HeapObject* obj = reinterpret_cast<HeapObject*>(ptr);
     JSObjectsCluster cluster = HeapObjectAsCluster(obj);
     const char* name = cluster.GetSpecialCaseName();
     if (name == NULL) {
@@ -1018,12 +1028,13 @@
 
 template<class Iterator>
 void AggregatedHeapSnapshotGenerator::IterateRetainers(
-    HeapEntriesMap* entries_map) {
+    HeapEntriesAllocator* allocator, HeapEntriesMap* entries_map) {
   RetainerHeapProfile* p = agg_snapshot_->js_retainer_profile();
   AggregatingRetainerTreeIterator<Iterator> agg_ret_iter_1(
-      p->coarser(), entries_map);
+      p->coarser(), allocator, entries_map);
   p->retainers_tree()->ForEach(&agg_ret_iter_1);
-  AggregatingRetainerTreeIterator<Iterator> agg_ret_iter_2(NULL, entries_map);
+  AggregatingRetainerTreeIterator<Iterator> agg_ret_iter_2(
+      NULL, allocator, entries_map);
   p->aggregator()->output_tree().ForEach(&agg_ret_iter_2);
 }
 
@@ -1042,7 +1053,9 @@
   agg_snapshot_->js_cons_profile()->ForEach(&counting_cons_iter);
   histogram_entities_count += counting_cons_iter.entities_count();
   HeapEntriesMap entries_map;
-  IterateRetainers<CountingRetainersIterator>(&entries_map);
+  int root_child_index = 0;
+  AggregatedRetainerTreeAllocator allocator(snapshot, &root_child_index);
+  IterateRetainers<CountingRetainersIterator>(&allocator, &entries_map);
   histogram_entities_count += entries_map.entries_count();
   histogram_children_count += entries_map.total_children_count();
   histogram_retainers_count += entries_map.total_retainers_count();
@@ -1056,10 +1069,7 @@
   snapshot->AllocateEntries(histogram_entities_count,
                             histogram_children_count,
                             histogram_retainers_count);
-  snapshot->AddEntry(HeapSnapshot::kInternalRootObject,
-                     root_children_count,
-                     0);
-  int root_child_index = 0;
+  snapshot->AddRootEntry(root_children_count);
   for (int i = FIRST_NONSTRING_TYPE; i <= kAllStringsType; ++i) {
     if (agg_snapshot_->info()[i].bytes() > 0) {
       AddEntryFromAggregatedSnapshot(snapshot,
@@ -1075,11 +1085,10 @@
   AllocatingConstructorHeapProfileIterator alloc_cons_iter(
       snapshot, &root_child_index);
   agg_snapshot_->js_cons_profile()->ForEach(&alloc_cons_iter);
-  AggregatedRetainerTreeAllocator allocator(snapshot, &root_child_index);
-  entries_map.UpdateEntries(&allocator);
+  entries_map.AllocateEntries();
 
   // Fill up references.
-  IterateRetainers<AllocatingRetainersIterator>(&entries_map);
+  IterateRetainers<AllocatingRetainersIterator>(&allocator, &entries_map);
 
   snapshot->SetDominatorsToSelf();
 }
diff --git a/src/heap-profiler.h b/src/heap-profiler.h
index 90c664e..20ba457 100644
--- a/src/heap-profiler.h
+++ b/src/heap-profiler.h
@@ -340,6 +340,7 @@
 
 
 class HeapEntriesMap;
+class HeapEntriesAllocator;
 class HeapSnapshot;
 
 class AggregatedHeapSnapshotGenerator {
@@ -354,7 +355,8 @@
   void CalculateStringsStats();
   void CollectStats(HeapObject* obj);
   template<class Iterator>
-  void IterateRetainers(HeapEntriesMap* entries_map);
+  void IterateRetainers(
+      HeapEntriesAllocator* allocator, HeapEntriesMap* entries_map);
 
   AggregatedHeapSnapshot* agg_snapshot_;
 };
diff --git a/src/heap.cc b/src/heap.cc
index f88ebda..34ab9aa 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -134,7 +134,7 @@
 
 int Heap::mc_count_ = 0;
 int Heap::ms_count_ = 0;
-int Heap::gc_count_ = 0;
+unsigned int Heap::gc_count_ = 0;
 
 GCTracer* Heap::tracer_ = NULL;
 
@@ -515,7 +515,6 @@
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
   if (FLAG_log_gc) HeapProfiler::WriteSample();
-  if (CpuProfiler::is_profiling()) CpuProfiler::ProcessMovedFunctions();
 #endif
 
   return next_gc_likely_to_collect_more;
@@ -845,8 +844,6 @@
   ContextSlotCache::Clear();
   DescriptorLookupCache::Clear();
 
-  RuntimeProfiler::MarkCompactPrologue(is_compacting);
-
   CompilationCache::MarkCompactPrologue();
 
   CompletelyClearInstanceofCache();
@@ -1057,20 +1054,13 @@
   // Scavenge object reachable from the global contexts list directly.
   scavenge_visitor.VisitPointer(BitCast<Object**>(&global_contexts_list_));
 
-  // Scavenge objects reachable from the runtime-profiler sampler
-  // window directly.
-  Object** sampler_window_address = RuntimeProfiler::SamplerWindowAddress();
-  int sampler_window_size = RuntimeProfiler::SamplerWindowSize();
-  scavenge_visitor.VisitPointers(
-      sampler_window_address,
-      sampler_window_address + sampler_window_size);
-
   new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
 
   UpdateNewSpaceReferencesInExternalStringTable(
       &UpdateNewSpaceReferenceInExternalStringTableEntry);
 
   LiveObjectList::UpdateReferencesForScavengeGC();
+  RuntimeProfiler::UpdateSamplesAfterScavenge();
 
   ASSERT(new_space_front == new_space_.top());
 
@@ -1350,9 +1340,8 @@
     HEAP_PROFILE(ObjectMoveEvent(source->address(), target->address()));
 #if defined(ENABLE_LOGGING_AND_PROFILING)
     if (Logger::is_logging() || CpuProfiler::is_profiling()) {
-      if (target->IsJSFunction()) {
-        PROFILE(FunctionMoveEvent(source->address(), target->address()));
-        PROFILE(FunctionCreateEventFromMove(JSFunction::cast(target)));
+      if (target->IsSharedFunctionInfo()) {
+        PROFILE(SFIMoveEvent(source->address(), target->address()));
       }
     }
 #endif
@@ -2924,9 +2913,8 @@
   // constructor to the function.
   Object* result;
   { MaybeObject* maybe_result =
-        JSObject::cast(prototype)->SetProperty(constructor_symbol(),
-                                               function,
-                                               DONT_ENUM);
+        JSObject::cast(prototype)->SetLocalPropertyIgnoreAttributes(
+            constructor_symbol(), function, DONT_ENUM);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
   return prototype;
@@ -3797,9 +3785,9 @@
   static const int kIdlesBeforeMarkSweep = 7;
   static const int kIdlesBeforeMarkCompact = 8;
   static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1;
-  static const int kGCsBetweenCleanup = 4;
+  static const unsigned int kGCsBetweenCleanup = 4;
   static int number_idle_notifications = 0;
-  static int last_gc_count = gc_count_;
+  static unsigned int last_gc_count = gc_count_;
 
   bool uncommit = true;
   bool finished = false;
@@ -3808,7 +3796,7 @@
   // GCs have taken place. This allows another round of cleanup based
   // on idle notifications if enough work has been carried out to
   // provoke a number of garbage collections.
-  if (gc_count_ < last_gc_count + kGCsBetweenCleanup) {
+  if (gc_count_ - last_gc_count < kGCsBetweenCleanup) {
     number_idle_notifications =
         Min(number_idle_notifications + 1, kMaxIdleCount);
   } else {
@@ -5182,32 +5170,77 @@
 }
 
 
-#ifdef DEBUG
+#if defined(DEBUG) || defined(LIVE_OBJECT_LIST)
 
-static bool search_for_any_global;
-static Object* search_target;
-static bool found_target;
-static List<Object*> object_stack(20);
+Object* const PathTracer::kAnyGlobalObject = reinterpret_cast<Object*>(NULL);
 
-
-// Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject.
-static const int kMarkTag = 2;
-
-static void MarkObjectRecursively(Object** p);
-class MarkObjectVisitor : public ObjectVisitor {
+class PathTracer::MarkVisitor: public ObjectVisitor {
  public:
+  explicit MarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
   void VisitPointers(Object** start, Object** end) {
-    // Copy all HeapObject pointers in [start, end)
-    for (Object** p = start; p < end; p++) {
+    // Scan all HeapObject pointers in [start, end)
+    for (Object** p = start; !tracer_->found() && (p < end); p++) {
       if ((*p)->IsHeapObject())
-        MarkObjectRecursively(p);
+        tracer_->MarkRecursively(p, this);
     }
   }
+
+ private:
+  PathTracer* tracer_;
 };
 
-static MarkObjectVisitor mark_visitor;
 
-static void MarkObjectRecursively(Object** p) {
+class PathTracer::UnmarkVisitor: public ObjectVisitor {
+ public:
+  explicit UnmarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
+  void VisitPointers(Object** start, Object** end) {
+    // Scan all HeapObject pointers in [start, end)
+    for (Object** p = start; p < end; p++) {
+      if ((*p)->IsHeapObject())
+        tracer_->UnmarkRecursively(p, this);
+    }
+  }
+
+ private:
+  PathTracer* tracer_;
+};
+
+
+void PathTracer::VisitPointers(Object** start, Object** end) {
+  bool done = ((what_to_find_ == FIND_FIRST) && found_target_);
+  // Visit all HeapObject pointers in [start, end)
+  for (Object** p = start; !done && (p < end); p++) {
+    if ((*p)->IsHeapObject()) {
+      TracePathFrom(p);
+      done = ((what_to_find_ == FIND_FIRST) && found_target_);
+    }
+  }
+}
+
+
+void PathTracer::Reset() {
+  found_target_ = false;
+  object_stack_.Clear();
+}
+
+
+void PathTracer::TracePathFrom(Object** root) {
+  ASSERT((search_target_ == kAnyGlobalObject) ||
+         search_target_->IsHeapObject());
+  found_target_in_trace_ = false;
+  object_stack_.Clear();
+
+  MarkVisitor mark_visitor(this);
+  MarkRecursively(root, &mark_visitor);
+
+  UnmarkVisitor unmark_visitor(this);
+  UnmarkRecursively(root, &unmark_visitor);
+
+  ProcessResults();
+}
+
+
+void PathTracer::MarkRecursively(Object** p, MarkVisitor* mark_visitor) {
   if (!(*p)->IsHeapObject()) return;
 
   HeapObject* obj = HeapObject::cast(*p);
@@ -5216,14 +5249,17 @@
 
   if (!map->IsHeapObject()) return;  // visited before
 
-  if (found_target) return;  // stop if target found
-  object_stack.Add(obj);
-  if ((search_for_any_global && obj->IsJSGlobalObject()) ||
-      (!search_for_any_global && (obj == search_target))) {
-    found_target = true;
+  if (found_target_in_trace_) return;  // stop if target found
+  object_stack_.Add(obj);
+  if (((search_target_ == kAnyGlobalObject) && obj->IsJSGlobalObject()) ||
+      (obj == search_target_)) {
+    found_target_in_trace_ = true;
+    found_target_ = true;
     return;
   }
 
+  bool is_global_context = obj->IsGlobalContext();
+
   // not visited yet
   Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map));
 
@@ -5231,31 +5267,30 @@
 
   obj->set_map(reinterpret_cast<Map*>(map_addr + kMarkTag));
 
-  MarkObjectRecursively(&map);
+  // Scan the object body.
+  if (is_global_context && (visit_mode_ == VISIT_ONLY_STRONG)) {
+    // This is specialized to scan Context's properly.
+    Object** start = reinterpret_cast<Object**>(obj->address() +
+                                                Context::kHeaderSize);
+    Object** end = reinterpret_cast<Object**>(obj->address() +
+        Context::kHeaderSize + Context::FIRST_WEAK_SLOT * kPointerSize);
+    mark_visitor->VisitPointers(start, end);
+  } else {
+    obj->IterateBody(map_p->instance_type(),
+                     obj->SizeFromMap(map_p),
+                     mark_visitor);
+  }
 
-  obj->IterateBody(map_p->instance_type(), obj->SizeFromMap(map_p),
-                   &mark_visitor);
+  // Scan the map after the body because the body is a lot more interesting
+  // when doing leak detection.
+  MarkRecursively(&map, mark_visitor);
 
-  if (!found_target)  // don't pop if found the target
-    object_stack.RemoveLast();
+  if (!found_target_in_trace_)  // don't pop if found the target
+    object_stack_.RemoveLast();
 }
 
 
-static void UnmarkObjectRecursively(Object** p);
-class UnmarkObjectVisitor : public ObjectVisitor {
- public:
-  void VisitPointers(Object** start, Object** end) {
-    // Copy all HeapObject pointers in [start, end)
-    for (Object** p = start; p < end; p++) {
-      if ((*p)->IsHeapObject())
-        UnmarkObjectRecursively(p);
-    }
-  }
-};
-
-static UnmarkObjectVisitor unmark_visitor;
-
-static void UnmarkObjectRecursively(Object** p) {
+void PathTracer::UnmarkRecursively(Object** p, UnmarkVisitor* unmark_visitor) {
   if (!(*p)->IsHeapObject()) return;
 
   HeapObject* obj = HeapObject::cast(*p);
@@ -5274,63 +5309,42 @@
 
   obj->set_map(reinterpret_cast<Map*>(map_p));
 
-  UnmarkObjectRecursively(reinterpret_cast<Object**>(&map_p));
+  UnmarkRecursively(reinterpret_cast<Object**>(&map_p), unmark_visitor);
 
   obj->IterateBody(Map::cast(map_p)->instance_type(),
                    obj->SizeFromMap(Map::cast(map_p)),
-                   &unmark_visitor);
+                   unmark_visitor);
 }
 
 
-static void MarkRootObjectRecursively(Object** root) {
-  if (search_for_any_global) {
-    ASSERT(search_target == NULL);
-  } else {
-    ASSERT(search_target->IsHeapObject());
-  }
-  found_target = false;
-  object_stack.Clear();
-
-  MarkObjectRecursively(root);
-  UnmarkObjectRecursively(root);
-
-  if (found_target) {
+void PathTracer::ProcessResults() {
+  if (found_target_) {
     PrintF("=====================================\n");
     PrintF("====        Path to object       ====\n");
     PrintF("=====================================\n\n");
 
-    ASSERT(!object_stack.is_empty());
-    for (int i = 0; i < object_stack.length(); i++) {
+    ASSERT(!object_stack_.is_empty());
+    for (int i = 0; i < object_stack_.length(); i++) {
       if (i > 0) PrintF("\n     |\n     |\n     V\n\n");
-      Object* obj = object_stack[i];
+      Object* obj = object_stack_[i];
+#ifdef OBJECT_PRINT
       obj->Print();
+#else
+      obj->ShortPrint();
+#endif
     }
     PrintF("=====================================\n");
   }
 }
+#endif  // DEBUG || LIVE_OBJECT_LIST
 
 
-// Helper class for visiting HeapObjects recursively.
-class MarkRootVisitor: public ObjectVisitor {
- public:
-  void VisitPointers(Object** start, Object** end) {
-    // Visit all HeapObject pointers in [start, end)
-    for (Object** p = start; p < end; p++) {
-      if ((*p)->IsHeapObject())
-        MarkRootObjectRecursively(p);
-    }
-  }
-};
-
-
+#ifdef DEBUG
 // Triggers a depth-first traversal of reachable objects from roots
 // and finds a path to a specific heap object and prints it.
 void Heap::TracePathToObject(Object* target) {
-  search_target = target;
-  search_for_any_global = false;
-
-  MarkRootVisitor root_visitor;
-  IterateRoots(&root_visitor, VISIT_ONLY_STRONG);
+  PathTracer tracer(target, PathTracer::FIND_ALL, VISIT_ALL);
+  IterateRoots(&tracer, VISIT_ONLY_STRONG);
 }
 
 
@@ -5338,11 +5352,10 @@
 // and finds a path to any global object and prints it. Useful for
 // determining the source for leaks of global objects.
 void Heap::TracePathToGlobal() {
-  search_target = NULL;
-  search_for_any_global = true;
-
-  MarkRootVisitor root_visitor;
-  IterateRoots(&root_visitor, VISIT_ONLY_STRONG);
+  PathTracer tracer(PathTracer::kAnyGlobalObject,
+                    PathTracer::FIND_ALL,
+                    VISIT_ALL);
+  IterateRoots(&tracer, VISIT_ONLY_STRONG);
 }
 #endif
 
diff --git a/src/heap.h b/src/heap.h
index dcd813b..6aa8339 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -30,6 +30,8 @@
 
 #include <math.h>
 
+#include "globals.h"
+#include "list.h"
 #include "spaces.h"
 #include "splay-tree-inl.h"
 #include "v8-counters.h"
@@ -47,7 +49,6 @@
   V(Map, one_pointer_filler_map, OnePointerFillerMap)                          \
   V(Map, two_pointer_filler_map, TwoPointerFillerMap)                          \
   /* Cluster the most popular ones in a few cache lines here at the top.    */ \
-  V(Smi, stack_limit, StackLimit)                                              \
   V(Object, undefined_value, UndefinedValue)                                   \
   V(Object, the_hole_value, TheHoleValue)                                      \
   V(Object, null_value, NullValue)                                             \
@@ -60,21 +61,29 @@
   V(Map, fixed_cow_array_map, FixedCOWArrayMap)                                \
   V(Object, no_interceptor_result_sentinel, NoInterceptorResultSentinel)       \
   V(Map, meta_map, MetaMap)                                                    \
-  V(Object, termination_exception, TerminationException)                       \
   V(Map, hash_table_map, HashTableMap)                                         \
+  V(Smi, stack_limit, StackLimit)                                              \
+  V(FixedArray, number_string_cache, NumberStringCache)                        \
+  V(Object, instanceof_cache_function, InstanceofCacheFunction)                \
+  V(Object, instanceof_cache_map, InstanceofCacheMap)                          \
+  V(Object, instanceof_cache_answer, InstanceofCacheAnswer)                    \
+  V(FixedArray, single_character_string_cache, SingleCharacterStringCache)     \
+  V(Object, termination_exception, TerminationException)                       \
   V(FixedArray, empty_fixed_array, EmptyFixedArray)                            \
   V(ByteArray, empty_byte_array, EmptyByteArray)                               \
+  V(String, empty_string, EmptyString)                                         \
+  V(DescriptorArray, empty_descriptor_array, EmptyDescriptorArray)             \
   V(Map, string_map, StringMap)                                                \
   V(Map, ascii_string_map, AsciiStringMap)                                     \
   V(Map, symbol_map, SymbolMap)                                                \
+  V(Map, cons_string_map, ConsStringMap)                                       \
+  V(Map, cons_ascii_string_map, ConsAsciiStringMap)                            \
   V(Map, ascii_symbol_map, AsciiSymbolMap)                                     \
   V(Map, cons_symbol_map, ConsSymbolMap)                                       \
   V(Map, cons_ascii_symbol_map, ConsAsciiSymbolMap)                            \
   V(Map, external_symbol_map, ExternalSymbolMap)                               \
   V(Map, external_symbol_with_ascii_data_map, ExternalSymbolWithAsciiDataMap)  \
   V(Map, external_ascii_symbol_map, ExternalAsciiSymbolMap)                    \
-  V(Map, cons_string_map, ConsStringMap)                                       \
-  V(Map, cons_ascii_string_map, ConsAsciiStringMap)                            \
   V(Map, external_string_map, ExternalStringMap)                               \
   V(Map, external_string_with_ascii_data_map, ExternalStringWithAsciiDataMap)  \
   V(Map, external_ascii_string_map, ExternalAsciiStringMap)                    \
@@ -98,11 +107,6 @@
   V(Map, proxy_map, ProxyMap)                                                  \
   V(Object, nan_value, NanValue)                                               \
   V(Object, minus_zero_value, MinusZeroValue)                                  \
-  V(Object, instanceof_cache_function, InstanceofCacheFunction)                \
-  V(Object, instanceof_cache_map, InstanceofCacheMap)                          \
-  V(Object, instanceof_cache_answer, InstanceofCacheAnswer)                    \
-  V(String, empty_string, EmptyString)                                         \
-  V(DescriptorArray, empty_descriptor_array, EmptyDescriptorArray)             \
   V(Map, neander_map, NeanderMap)                                              \
   V(JSObject, message_listeners, MessageListeners)                             \
   V(Proxy, prototype_accessors, PrototypeAccessors)                            \
@@ -111,8 +115,6 @@
   V(Code, js_entry_code, JsEntryCode)                                          \
   V(Code, js_construct_entry_code, JsConstructEntryCode)                       \
   V(Code, c_entry_code, CEntryCode)                                            \
-  V(FixedArray, number_string_cache, NumberStringCache)                        \
-  V(FixedArray, single_character_string_cache, SingleCharacterStringCache)     \
   V(FixedArray, natives_source_cache, NativesSourceCache)                      \
   V(Object, last_script_id, LastScriptId)                                      \
   V(Script, empty_script, EmptyScript)                                         \
@@ -184,6 +186,7 @@
   V(KeyedLoadSpecialized_symbol, "KeyedLoadSpecialized")                 \
   V(KeyedStoreSpecialized_symbol, "KeyedStoreSpecialized")               \
   V(KeyedLoadPixelArray_symbol, "KeyedLoadPixelArray")                   \
+  V(KeyedStorePixelArray_symbol, "KeyedStorePixelArray")                 \
   V(stack_overflow_symbol, "kStackOverflowBoilerplate")                  \
   V(illegal_access_symbol, "illegal access")                             \
   V(out_of_memory_symbol, "out-of-memory")                               \
@@ -215,7 +218,6 @@
   V(KeyedLoadExternalArray_symbol, "KeyedLoadExternalArray")             \
   V(KeyedStoreExternalArray_symbol, "KeyedStoreExternalArray")
 
-
 // Forward declarations.
 class GCTracer;
 class HeapStats;
@@ -1179,7 +1181,7 @@
 
   static int mc_count_;  // how many mark-compact collections happened
   static int ms_count_;  // how many mark-sweep collections happened
-  static int gc_count_;  // how many gc happened
+  static unsigned int gc_count_;  // how many gc happened
 
   // Total length of the strings we failed to flatten since the last GC.
   static int unflattened_strings_length_;
@@ -1906,7 +1908,7 @@
   void set_collector(GarbageCollector collector) { collector_ = collector; }
 
   // Sets the GC count.
-  void set_gc_count(int count) { gc_count_ = count; }
+  void set_gc_count(unsigned int count) { gc_count_ = count; }
 
   // Sets the full GC count.
   void set_full_gc_count(int count) { full_gc_count_ = count; }
@@ -1949,7 +1951,7 @@
 
   // A count (including this one, eg, the first collection is 1) of the
   // number of garbage collections.
-  int gc_count_;
+  unsigned int gc_count_;
 
   // A count (including this one) of the number of full garbage collections.
   int full_gc_count_;
@@ -2151,6 +2153,65 @@
 };
 
 
+#if defined(DEBUG) || defined(LIVE_OBJECT_LIST)
+// Helper class for tracing paths to a search target Object from all roots.
+// The TracePathFrom() method can be used to trace paths from a specific
+// object to the search target object.
+class PathTracer : public ObjectVisitor {
+ public:
+  enum WhatToFind {
+    FIND_ALL,   // Will find all matches.
+    FIND_FIRST  // Will stop the search after first match.
+  };
+
+  // For the WhatToFind arg, if FIND_FIRST is specified, tracing will stop
+  // after the first match.  If FIND_ALL is specified, then tracing will be
+  // done for all matches.
+  PathTracer(Object* search_target,
+             WhatToFind what_to_find,
+             VisitMode visit_mode)
+      : search_target_(search_target),
+        found_target_(false),
+        found_target_in_trace_(false),
+        what_to_find_(what_to_find),
+        visit_mode_(visit_mode),
+        object_stack_(20),
+        no_alloc() {}
+
+  virtual void VisitPointers(Object** start, Object** end);
+
+  void Reset();
+  void TracePathFrom(Object** root);
+
+  bool found() const { return found_target_; }
+
+  static Object* const kAnyGlobalObject;
+
+ protected:
+  class MarkVisitor;
+  class UnmarkVisitor;
+
+  void MarkRecursively(Object** p, MarkVisitor* mark_visitor);
+  void UnmarkRecursively(Object** p, UnmarkVisitor* unmark_visitor);
+  virtual void ProcessResults();
+
+  // Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject.
+  static const int kMarkTag = 2;
+
+  Object* search_target_;
+  bool found_target_;
+  bool found_target_in_trace_;
+  WhatToFind what_to_find_;
+  VisitMode visit_mode_;
+  List<Object*> object_stack_;
+
+  AssertNoAllocation no_alloc;  // i.e. no gc allowed.
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(PathTracer);
+};
+#endif  // DEBUG || LIVE_OBJECT_LIST
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_HEAP_H_
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 16100e4..c2e5c8b 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -57,10 +57,13 @@
     case kTagged: return "t";
     case kDouble: return "d";
     case kInteger32: return "i";
-    default:
+    case kExternal: return "x";
+    case kNumRepresentations:
       UNREACHABLE();
       return NULL;
   }
+  UNREACHABLE();
+  return NULL;
 }
 
 
@@ -117,6 +120,44 @@
 }
 
 
+void Range::Intersect(Range* other) {
+  upper_ = Min(upper_, other->upper_);
+  lower_ = Max(lower_, other->lower_);
+  bool b = CanBeMinusZero() && other->CanBeMinusZero();
+  set_can_be_minus_zero(b);
+}
+
+
+void Range::Union(Range* other) {
+  upper_ = Max(upper_, other->upper_);
+  lower_ = Min(lower_, other->lower_);
+  bool b = CanBeMinusZero() || other->CanBeMinusZero();
+  set_can_be_minus_zero(b);
+}
+
+
+void Range::Sar(int32_t value) {
+  int32_t bits = value & 0x1F;
+  lower_ = lower_ >> bits;
+  upper_ = upper_ >> bits;
+  set_can_be_minus_zero(false);
+}
+
+
+void Range::Shl(int32_t value) {
+  int32_t bits = value & 0x1F;
+  int old_lower = lower_;
+  int old_upper = upper_;
+  lower_ = lower_ << bits;
+  upper_ = upper_ << bits;
+  if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
+    upper_ = kMaxInt;
+    lower_ = kMinInt;
+  }
+  set_can_be_minus_zero(false);
+}
+
+
 bool Range::AddAndCheckOverflow(Range* other) {
   bool may_overflow = false;
   lower_ = AddWithoutOverflow(lower_, other->lower(), &may_overflow);
@@ -221,7 +262,7 @@
 }
 
 
-int HValue::LookupOperandIndex(int occurrence_index, HValue* op) const {
+int HValue::LookupOperandIndex(int occurrence_index, HValue* op) {
   for (int i = 0; i < OperandCount(); ++i) {
     if (OperandAt(i) == op) {
       if (occurrence_index == 0) return i;
@@ -237,7 +278,7 @@
 }
 
 
-bool HValue::UsesMultipleTimes(HValue* op) const {
+bool HValue::UsesMultipleTimes(HValue* op) {
   bool seen = false;
   for (int i = 0; i < OperandCount(); ++i) {
     if (OperandAt(i) == op) {
@@ -249,7 +290,7 @@
 }
 
 
-bool HValue::Equals(HValue* other) const {
+bool HValue::Equals(HValue* other) {
   if (other->opcode() != opcode()) return false;
   if (!other->representation().Equals(representation())) return false;
   if (!other->type_.Equals(type_)) return false;
@@ -264,7 +305,7 @@
 }
 
 
-intptr_t HValue::Hashcode() const {
+intptr_t HValue::Hashcode() {
   intptr_t result = opcode();
   int count = OperandCount();
   for (int i = 0; i < count; ++i) {
@@ -281,52 +322,20 @@
 }
 
 
-void HLoadKeyedGeneric::InternalSetOperandAt(int index, HValue* value) {
-  if (index < 2) {
-    operands_[index] = value;
-  } else {
-    context_ = value;
-  }
-}
-
-
-void HStoreKeyedGeneric::InternalSetOperandAt(int index, HValue* value) {
-  if (index < 3) {
-    operands_[index] = value;
-  } else {
-    context_ = value;
-  }
-}
-
-
-void HStoreNamedGeneric::InternalSetOperandAt(int index, HValue* value) {
-  if (index < 2) {
-    operands_[index] = value;
-  } else {
-    context_ = value;
-  }
-}
-
-
 void HValue::ReplaceAndDelete(HValue* other) {
-  ReplaceValue(other);
+  if (other != NULL) ReplaceValue(other);
   Delete();
 }
 
 
 void HValue::ReplaceValue(HValue* other) {
-  ZoneList<HValue*> start_uses(2);
   for (int i = 0; i < uses_.length(); ++i) {
-    HValue* use = uses_.at(i);
-    if (!use->block()->IsStartBlock()) {
-      InternalReplaceAtUse(use, other);
-      other->uses_.Add(use);
-    } else {
-      start_uses.Add(use);
-    }
+    HValue* use = uses_[i];
+    ASSERT(!use->block()->IsStartBlock());
+    InternalReplaceAtUse(use, other);
+    other->uses_.Add(use);
   }
-  uses_.Clear();
-  uses_.AddAll(start_uses);
+  uses_.Rewind(0);
 }
 
 
@@ -438,13 +447,15 @@
 }
 
 
-void HInstruction::PrintTo(StringStream* stream) const {
+void HInstruction::PrintTo(StringStream* stream) {
   stream->Add("%s", Mnemonic());
   if (HasSideEffects()) stream->Add("*");
   stream->Add(" ");
   PrintDataTo(stream);
 
-  if (range() != NULL) {
+  if (range() != NULL &&
+      !range()->IsMostGeneric() &&
+      !range()->CanBeMinusZero()) {
     stream->Add(" range[%d,%d,m0=%d]",
                 range()->lower(),
                 range()->upper(),
@@ -465,9 +476,16 @@
 void HInstruction::Unlink() {
   ASSERT(IsLinked());
   ASSERT(!IsControlInstruction());  // Must never move control instructions.
+  ASSERT(!IsBlockEntry());  // Doesn't make sense to delete these.
+  ASSERT(previous_ != NULL);
+  previous_->next_ = next_;
+  if (next_ == NULL) {
+    ASSERT(block()->last() == this);
+    block()->set_last(previous_);
+  } else {
+    next_->previous_ = previous_;
+  }
   clear_block();
-  if (previous_ != NULL) previous_->next_ = next_;
-  if (next_ != NULL) next_->previous_ = previous_;
 }
 
 
@@ -554,69 +572,64 @@
 #endif
 
 
-void HCall::PrintDataTo(StringStream* stream) const {
+void HUnaryCall::PrintDataTo(StringStream* stream) {
+  value()->PrintNameTo(stream);
+  stream->Add(" ");
   stream->Add("#%d", argument_count());
 }
 
 
-void HUnaryCall::PrintDataTo(StringStream* stream) const {
-  value()->PrintNameTo(stream);
-  stream->Add(" ");
-  HCall::PrintDataTo(stream);
-}
-
-
-void HBinaryCall::PrintDataTo(StringStream* stream) const {
+void HBinaryCall::PrintDataTo(StringStream* stream) {
   first()->PrintNameTo(stream);
   stream->Add(" ");
   second()->PrintNameTo(stream);
   stream->Add(" ");
-  HCall::PrintDataTo(stream);
+  stream->Add("#%d", argument_count());
 }
 
 
-void HCallConstantFunction::PrintDataTo(StringStream* stream) const {
+void HCallConstantFunction::PrintDataTo(StringStream* stream) {
   if (IsApplyFunction()) {
     stream->Add("optimized apply ");
   } else {
     stream->Add("%o ", function()->shared()->DebugName());
   }
-  HCall::PrintDataTo(stream);
+  stream->Add("#%d", argument_count());
 }
 
 
-void HCallNamed::PrintDataTo(StringStream* stream) const {
+void HCallNamed::PrintDataTo(StringStream* stream) {
   stream->Add("%o ", *name());
   HUnaryCall::PrintDataTo(stream);
 }
 
 
-void HCallGlobal::PrintDataTo(StringStream* stream) const {
+void HCallGlobal::PrintDataTo(StringStream* stream) {
   stream->Add("%o ", *name());
   HUnaryCall::PrintDataTo(stream);
 }
 
 
-void HCallKnownGlobal::PrintDataTo(StringStream* stream) const {
+void HCallKnownGlobal::PrintDataTo(StringStream* stream) {
   stream->Add("o ", target()->shared()->DebugName());
-  HCall::PrintDataTo(stream);
+  stream->Add("#%d", argument_count());
 }
 
 
-void HCallRuntime::PrintDataTo(StringStream* stream) const {
+void HCallRuntime::PrintDataTo(StringStream* stream) {
   stream->Add("%o ", *name());
-  HCall::PrintDataTo(stream);
+  stream->Add("#%d", argument_count());
 }
 
 
-void HClassOfTest::PrintDataTo(StringStream* stream) const {
+void HClassOfTest::PrintDataTo(StringStream* stream) {
   stream->Add("class_of_test(");
   value()->PrintNameTo(stream);
   stream->Add(", \"%o\")", *class_name());
 }
 
 
-void HAccessArgumentsAt::PrintDataTo(StringStream* stream) const {
+void HAccessArgumentsAt::PrintDataTo(StringStream* stream) {
   arguments()->PrintNameTo(stream);
   stream->Add("[");
   index()->PrintNameTo(stream);
@@ -625,7 +638,7 @@
 }
 
 
-void HControlInstruction::PrintDataTo(StringStream* stream) const {
+void HControlInstruction::PrintDataTo(StringStream* stream) {
   if (FirstSuccessor() != NULL) {
     int first_id = FirstSuccessor()->block_id();
     if (SecondSuccessor() == NULL) {
@@ -638,13 +651,13 @@
 }
 
 
-void HUnaryControlInstruction::PrintDataTo(StringStream* stream) const {
+void HUnaryControlInstruction::PrintDataTo(StringStream* stream) {
   value()->PrintNameTo(stream);
   HControlInstruction::PrintDataTo(stream);
 }
 
 
-void HCompareMap::PrintDataTo(StringStream* stream) const {
+void HCompareMap::PrintDataTo(StringStream* stream) {
   value()->PrintNameTo(stream);
   stream->Add(" (%p)", *map());
   HControlInstruction::PrintDataTo(stream);
@@ -672,19 +685,19 @@
 }
 
 
-void HUnaryMathOperation::PrintDataTo(StringStream* stream) const {
+void HUnaryMathOperation::PrintDataTo(StringStream* stream) {
   const char* name = OpName();
   stream->Add("%s ", name);
   value()->PrintNameTo(stream);
 }
 
 
-void HUnaryOperation::PrintDataTo(StringStream* stream) const {
+void HUnaryOperation::PrintDataTo(StringStream* stream) {
   value()->PrintNameTo(stream);
 }
 
 
-void HHasInstanceType::PrintDataTo(StringStream* stream) const {
+void HHasInstanceType::PrintDataTo(StringStream* stream) {
   value()->PrintNameTo(stream);
   switch (from_) {
     case FIRST_JS_OBJECT_TYPE:
@@ -705,14 +718,14 @@
 }
 
 
-void HTypeofIs::PrintDataTo(StringStream* stream) const {
+void HTypeofIs::PrintDataTo(StringStream* stream) {
   value()->PrintNameTo(stream);
   stream->Add(" == ");
   stream->Add(type_literal_->ToAsciiVector());
 }
 
 
-void HChange::PrintDataTo(StringStream* stream) const {
+void HChange::PrintDataTo(StringStream* stream) {
   HUnaryOperation::PrintDataTo(stream);
   stream->Add(" %s to %s", from_.Mnemonic(), to_.Mnemonic());
 
@@ -728,26 +741,26 @@
 }
 
 
-void HCheckMap::PrintDataTo(StringStream* stream) const {
+void HCheckMap::PrintDataTo(StringStream* stream) {
   value()->PrintNameTo(stream);
   stream->Add(" %p", *map());
 }
 
 
-void HCheckFunction::PrintDataTo(StringStream* stream) const {
+void HCheckFunction::PrintDataTo(StringStream* stream) {
   value()->PrintNameTo(stream);
   stream->Add(" %p", *target());
 }
 
 
-void HCallStub::PrintDataTo(StringStream* stream) const {
+void HCallStub::PrintDataTo(StringStream* stream) {
   stream->Add("%s ",
               CodeStub::MajorName(major_key_, false));
   HUnaryCall::PrintDataTo(stream);
 }
 
 
-void HInstanceOf::PrintDataTo(StringStream* stream) const {
+void HInstanceOf::PrintDataTo(StringStream* stream) {
   left()->PrintNameTo(stream);
   stream->Add(" ");
   right()->PrintNameTo(stream);
@@ -766,6 +779,8 @@
   } else if (representation().IsNone()) {
     return NULL;
   } else {
+    // Untagged integer32 cannot be -0 and we don't compute ranges for
+    // untagged doubles.
     return new Range();
   }
 }
@@ -777,7 +792,7 @@
     result->set_can_be_minus_zero(false);
     return result;
   }
-  return HInstruction::InferRange();
+  return HValue::InferRange();
 }
 
 
@@ -811,7 +826,7 @@
     res->set_can_be_minus_zero(m0);
     return res;
   } else {
-    return HArithmeticBinaryOperation::InferRange();
+    return HValue::InferRange();
   }
 }
 
@@ -827,7 +842,7 @@
     res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero());
     return res;
   } else {
-    return HArithmeticBinaryOperation::InferRange();
+    return HValue::InferRange();
   }
 }
 
@@ -845,7 +860,7 @@
     res->set_can_be_minus_zero(m0);
     return res;
   } else {
-    return HArithmeticBinaryOperation::InferRange();
+    return HValue::InferRange();
   }
 }
 
@@ -870,7 +885,7 @@
     }
     return result;
   } else {
-    return HArithmeticBinaryOperation::InferRange();
+    return HValue::InferRange();
   }
 }
 
@@ -887,12 +902,12 @@
     }
     return result;
   } else {
-    return HArithmeticBinaryOperation::InferRange();
+    return HValue::InferRange();
   }
 }
 
 
-void HPhi::PrintTo(StringStream* stream) const {
+void HPhi::PrintTo(StringStream* stream) {
   stream->Add("[");
   for (int i = 0; i < OperandCount(); ++i) {
     HValue* value = OperandAt(i);
@@ -918,7 +933,7 @@
 }
 
 
-HValue* HPhi::GetRedundantReplacement() const {
+HValue* HPhi::GetRedundantReplacement() {
   HValue* candidate = NULL;
   int count = OperandCount();
   int position = 0;
@@ -970,7 +985,7 @@
 }
 
 
-void HSimulate::PrintDataTo(StringStream* stream) const {
+void HSimulate::PrintDataTo(StringStream* stream) {
   stream->Add("id=%d ", ast_id());
   if (pop_count_ > 0) stream->Add("pop %d", pop_count_);
   if (values_.length() > 0) {
@@ -987,7 +1002,7 @@
 }
 
 
-void HEnterInlined::PrintDataTo(StringStream* stream) const {
+void HEnterInlined::PrintDataTo(StringStream* stream) {
   SmartPointer<char> name = function()->debug_name()->ToCString();
   stream->Add("%s, id=%d", *name, function()->id());
 }
@@ -1028,7 +1043,7 @@
 }
 
 
-void HConstant::PrintDataTo(StringStream* stream) const {
+void HConstant::PrintDataTo(StringStream* stream) {
   handle()->ShortPrint(stream);
 }
 
@@ -1038,7 +1053,7 @@
 }
 
 
-void HBinaryOperation::PrintDataTo(StringStream* stream) const {
+void HBinaryOperation::PrintDataTo(StringStream* stream) {
   left()->PrintNameTo(stream);
   stream->Add(" ");
   right()->PrintNameTo(stream);
@@ -1048,34 +1063,30 @@
 
 
 Range* HBitAnd::InferRange() {
-  Range* a = left()->range();
-  Range* b = right()->range();
-  int32_t a_mask = 0xffffffff;
-  int32_t b_mask = 0xffffffff;
-  if (a != NULL) a_mask = a->Mask();
-  if (b != NULL) b_mask = b->Mask();
-  int32_t result_mask = a_mask & b_mask;
-  if (result_mask >= 0) {
-    return new Range(0, result_mask);
-  } else {
-    return HBinaryOperation::InferRange();
-  }
+  int32_t left_mask = (left()->range() != NULL)
+      ? left()->range()->Mask()
+      : 0xffffffff;
+  int32_t right_mask = (right()->range() != NULL)
+      ? right()->range()->Mask()
+      : 0xffffffff;
+  int32_t result_mask = left_mask & right_mask;
+  return (result_mask >= 0)
+      ? new Range(0, result_mask)
+      : HValue::InferRange();
 }
 
 
 Range* HBitOr::InferRange() {
-  Range* a = left()->range();
-  Range* b = right()->range();
-  int32_t a_mask = 0xffffffff;
-  int32_t b_mask = 0xffffffff;
-  if (a != NULL) a_mask = a->Mask();
-  if (b != NULL) b_mask = b->Mask();
-  int32_t result_mask = a_mask | b_mask;
-  if (result_mask >= 0) {
-    return new Range(0, result_mask);
-  } else {
-    return HBinaryOperation::InferRange();
-  }
+  int32_t left_mask = (left()->range() != NULL)
+      ? left()->range()->Mask()
+      : 0xffffffff;
+  int32_t right_mask = (right()->range() != NULL)
+      ? right()->range()->Mask()
+      : 0xffffffff;
+  int32_t result_mask = left_mask | right_mask;
+  return (result_mask >= 0)
+      ? new Range(0, result_mask)
+      : HValue::InferRange();
 }
 
 
@@ -1083,20 +1094,14 @@
   if (right()->IsConstant()) {
     HConstant* c = HConstant::cast(right());
     if (c->HasInteger32Value()) {
-      int32_t val = c->Integer32Value();
-      Range* result = NULL;
-      Range* left_range = left()->range();
-      if (left_range == NULL) {
-        result = new Range();
-      } else {
-        result = left_range->Copy();
-      }
-      result->Sar(val);
+      Range* result = (left()->range() != NULL)
+          ? left()->range()->Copy()
+          : new Range();
+      result->Sar(c->Integer32Value());
       return result;
     }
   }
-
-  return HBinaryOperation::InferRange();
+  return HValue::InferRange();
 }
 
 
@@ -1104,25 +1109,19 @@
   if (right()->IsConstant()) {
     HConstant* c = HConstant::cast(right());
     if (c->HasInteger32Value()) {
-      int32_t val = c->Integer32Value();
-      Range* result = NULL;
-      Range* left_range = left()->range();
-      if (left_range == NULL) {
-        result = new Range();
-      } else {
-        result = left_range->Copy();
-      }
-      result->Shl(val);
+      Range* result = (left()->range() != NULL)
+          ? left()->range()->Copy()
+          : new Range();
+      result->Shl(c->Integer32Value());
       return result;
     }
   }
-
-  return HBinaryOperation::InferRange();
+  return HValue::InferRange();
 }
 
 
 
-void HCompare::PrintDataTo(StringStream* stream) const {
+void HCompare::PrintDataTo(StringStream* stream) {
   stream->Add(Token::Name(token()));
   stream->Add(" ");
   HBinaryOperation::PrintDataTo(stream);
@@ -1141,18 +1140,18 @@
 }
 
 
-void HParameter::PrintDataTo(StringStream* stream) const {
+void HParameter::PrintDataTo(StringStream* stream) {
   stream->Add("%u", index());
 }
 
 
-void HLoadNamedField::PrintDataTo(StringStream* stream) const {
+void HLoadNamedField::PrintDataTo(StringStream* stream) {
   object()->PrintNameTo(stream);
   stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
 }
 
 
-void HLoadKeyed::PrintDataTo(StringStream* stream) const {
+void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
   object()->PrintNameTo(stream);
   stream->Add("[");
   key()->PrintNameTo(stream);
@@ -1160,7 +1159,15 @@
 }
 
 
-void HLoadPixelArrayElement::PrintDataTo(StringStream* stream) const {
+void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) {
+  object()->PrintNameTo(stream);
+  stream->Add("[");
+  key()->PrintNameTo(stream);
+  stream->Add("]");
+}
+
+
+void HLoadPixelArrayElement::PrintDataTo(StringStream* stream) {
   external_pointer()->PrintNameTo(stream);
   stream->Add("[");
   key()->PrintNameTo(stream);
@@ -1168,7 +1175,7 @@
 }
 
 
-void HStoreNamed::PrintDataTo(StringStream* stream) const {
+void HStoreNamedGeneric::PrintDataTo(StringStream* stream) {
   object()->PrintNameTo(stream);
   stream->Add(".");
   ASSERT(name()->IsString());
@@ -1178,15 +1185,20 @@
 }
 
 
-void HStoreNamedField::PrintDataTo(StringStream* stream) const {
-  HStoreNamed::PrintDataTo(stream);
+void HStoreNamedField::PrintDataTo(StringStream* stream) {
+  object()->PrintNameTo(stream);
+  stream->Add(".");
+  ASSERT(name()->IsString());
+  stream->Add(*String::cast(*name())->ToCString());
+  stream->Add(" = ");
+  value()->PrintNameTo(stream);
   if (!transition().is_null()) {
     stream->Add(" (transition map %p)", *transition());
   }
 }
 
 
-void HStoreKeyed::PrintDataTo(StringStream* stream) const {
+void HStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
   object()->PrintNameTo(stream);
   stream->Add("[");
   key()->PrintNameTo(stream);
@@ -1195,25 +1207,43 @@
 }
 
 
-void HLoadGlobal::PrintDataTo(StringStream* stream) const {
+void HStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
+  object()->PrintNameTo(stream);
+  stream->Add("[");
+  key()->PrintNameTo(stream);
+  stream->Add("] = ");
+  value()->PrintNameTo(stream);
+}
+
+
+void HStorePixelArrayElement::PrintDataTo(StringStream* stream) {
+  external_pointer()->PrintNameTo(stream);
+  stream->Add("[");
+  key()->PrintNameTo(stream);
+  stream->Add("] = ");
+  value()->PrintNameTo(stream);
+}
+
+
+void HLoadGlobal::PrintDataTo(StringStream* stream) {
   stream->Add("[%p]", *cell());
   if (check_hole_value()) stream->Add(" (deleteable/read-only)");
 }
 
 
-void HStoreGlobal::PrintDataTo(StringStream* stream) const {
+void HStoreGlobal::PrintDataTo(StringStream* stream) {
   stream->Add("[%p] = ", *cell());
   value()->PrintNameTo(stream);
 }
 
 
-void HLoadContextSlot::PrintDataTo(StringStream* stream) const {
+void HLoadContextSlot::PrintDataTo(StringStream* stream) {
   value()->PrintNameTo(stream);
   stream->Add("[%d]", slot_index());
 }
 
 
-void HStoreContextSlot::PrintDataTo(StringStream* stream) const {
+void HStoreContextSlot::PrintDataTo(StringStream* stream) {
   context()->PrintNameTo(stream);
   stream->Add("[%d] = ", slot_index());
   value()->PrintNameTo(stream);
@@ -1223,33 +1253,33 @@
 // Implementation of type inference and type conversions. Calculates
 // the inferred type of this instruction based on the input operands.
 
-HType HValue::CalculateInferredType() const {
+HType HValue::CalculateInferredType() {
   return type_;
 }
 
 
-HType HCheckMap::CalculateInferredType() const {
+HType HCheckMap::CalculateInferredType() {
   return value()->type();
 }
 
 
-HType HCheckFunction::CalculateInferredType() const {
+HType HCheckFunction::CalculateInferredType() {
   return value()->type();
 }
 
 
-HType HCheckNonSmi::CalculateInferredType() const {
+HType HCheckNonSmi::CalculateInferredType() {
   // TODO(kasperl): Is there any way to signal that this isn't a smi?
   return HType::Tagged();
 }
 
 
-HType HCheckSmi::CalculateInferredType() const {
+HType HCheckSmi::CalculateInferredType() {
   return HType::Smi();
 }
 
 
-HType HPhi::CalculateInferredType() const {
+HType HPhi::CalculateInferredType() {
   HType result = HType::Uninitialized();
   for (int i = 0; i < OperandCount(); ++i) {
     HType current = OperandAt(i)->type();
@@ -1259,77 +1289,77 @@
 }
 
 
-HType HConstant::CalculateInferredType() const {
+HType HConstant::CalculateInferredType() {
   return constant_type_;
 }
 
 
-HType HCompare::CalculateInferredType() const {
+HType HCompare::CalculateInferredType() {
   return HType::Boolean();
 }
 
 
-HType HCompareJSObjectEq::CalculateInferredType() const {
+HType HCompareJSObjectEq::CalculateInferredType() {
   return HType::Boolean();
 }
 
 
-HType HUnaryPredicate::CalculateInferredType() const {
+HType HUnaryPredicate::CalculateInferredType() {
   return HType::Boolean();
 }
 
 
-HType HBitwiseBinaryOperation::CalculateInferredType() const {
+HType HBitwiseBinaryOperation::CalculateInferredType() {
   return HType::TaggedNumber();
 }
 
 
-HType HArithmeticBinaryOperation::CalculateInferredType() const {
+HType HArithmeticBinaryOperation::CalculateInferredType() {
   return HType::TaggedNumber();
 }
 
 
-HType HAdd::CalculateInferredType() const {
+HType HAdd::CalculateInferredType() {
   return HType::Tagged();
 }
 
 
-HType HBitAnd::CalculateInferredType() const {
+HType HBitAnd::CalculateInferredType() {
   return HType::TaggedNumber();
 }
 
 
-HType HBitXor::CalculateInferredType() const {
+HType HBitXor::CalculateInferredType() {
   return HType::TaggedNumber();
 }
 
 
-HType HBitOr::CalculateInferredType() const {
+HType HBitOr::CalculateInferredType() {
   return HType::TaggedNumber();
 }
 
 
-HType HBitNot::CalculateInferredType() const {
+HType HBitNot::CalculateInferredType() {
   return HType::TaggedNumber();
 }
 
 
-HType HUnaryMathOperation::CalculateInferredType() const {
+HType HUnaryMathOperation::CalculateInferredType() {
   return HType::TaggedNumber();
 }
 
 
-HType HShl::CalculateInferredType() const {
+HType HShl::CalculateInferredType() {
   return HType::TaggedNumber();
 }
 
 
-HType HShr::CalculateInferredType() const {
+HType HShr::CalculateInferredType() {
   return HType::TaggedNumber();
 }
 
 
-HType HSar::CalculateInferredType() const {
+HType HSar::CalculateInferredType() {
   return HType::TaggedNumber();
 }
 
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index a0d932f..cc75354 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -51,14 +51,9 @@
   V(BinaryCall)                                \
   V(BinaryOperation)                           \
   V(BitwiseBinaryOperation)                    \
-  V(Call)                                      \
   V(ControlInstruction)                        \
   V(Instruction)                               \
-  V(LoadKeyed)                                 \
-  V(MaterializedLiteral)                       \
   V(Phi)                                       \
-  V(StoreKeyed)                                \
-  V(StoreNamed)                                \
   V(UnaryCall)                                 \
   V(UnaryControlInstruction)                   \
   V(UnaryOperation)                            \
@@ -107,6 +102,7 @@
   V(EnterInlined)                              \
   V(FixedArrayLength)                          \
   V(FunctionLiteral)                           \
+  V(GetCachedArrayIndex)                       \
   V(GlobalObject)                              \
   V(GlobalReceiver)                            \
   V(Goto)                                      \
@@ -150,6 +146,7 @@
   V(StoreContextSlot)                          \
   V(StoreGlobal)                               \
   V(StoreKeyedFastElement)                     \
+  V(StorePixelArrayElement)                    \
   V(StoreKeyedGeneric)                         \
   V(StoreNamedField)                           \
   V(StoreNamedGeneric)                         \
@@ -191,91 +188,50 @@
   DECLARE_INSTRUCTION(type)
 
 
-
-template<int kSize>
-class HOperandVector : public EmbeddedVector<HValue*, kSize> {
- public:
-  HOperandVector() : EmbeddedVector<HValue*, kSize>(NULL) { }
-};
-
-
 class Range: public ZoneObject {
  public:
-  Range() : lower_(kMinInt),
-            upper_(kMaxInt),
-            next_(NULL),
-            can_be_minus_zero_(false) { }
+  Range()
+      : lower_(kMinInt),
+        upper_(kMaxInt),
+        next_(NULL),
+        can_be_minus_zero_(false) { }
 
   Range(int32_t lower, int32_t upper)
-      : lower_(lower), upper_(upper), next_(NULL), can_be_minus_zero_(false) { }
+      : lower_(lower),
+        upper_(upper),
+        next_(NULL),
+        can_be_minus_zero_(false) { }
 
-  bool IsInSmiRange() const {
-    return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
-  }
-  void KeepOrder();
-  void Verify() const;
   int32_t upper() const { return upper_; }
   int32_t lower() const { return lower_; }
   Range* next() const { return next_; }
   Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
   Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
-  void ClearLower() { lower_ = kMinInt; }
-  void ClearUpper() { upper_ = kMaxInt; }
   Range* Copy() const { return new Range(lower_, upper_); }
-  bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
   int32_t Mask() const;
   void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
   bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
   bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
   bool CanBeNegative() const { return lower_ < 0; }
-  bool Includes(int value) const {
-    return lower_ <= value && upper_ >= value;
+  bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
+  bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
+  bool IsInSmiRange() const {
+    return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
   }
-
-  void Sar(int32_t value) {
-    int32_t bits = value & 0x1F;
-    lower_ = lower_ >> bits;
-    upper_ = upper_ >> bits;
-    set_can_be_minus_zero(false);
-  }
-
-  void Shl(int32_t value) {
-    int32_t bits = value & 0x1F;
-    int old_lower = lower_;
-    int old_upper = upper_;
-    lower_ = lower_ << bits;
-    upper_ = upper_ << bits;
-    if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
-      upper_ = kMaxInt;
-      lower_ = kMinInt;
-    }
-    set_can_be_minus_zero(false);
-  }
-
-  // Adds a constant to the lower and upper bound of the range.
-  void AddConstant(int32_t value);
+  void KeepOrder();
+  void Verify() const;
 
   void StackUpon(Range* other) {
     Intersect(other);
     next_ = other;
   }
 
-  void Intersect(Range* other) {
-    upper_ = Min(upper_, other->upper_);
-    lower_ = Max(lower_, other->lower_);
-    bool b = CanBeMinusZero() && other->CanBeMinusZero();
-    set_can_be_minus_zero(b);
-  }
+  void Intersect(Range* other);
+  void Union(Range* other);
 
-  void Union(Range* other) {
-    upper_ = Max(upper_, other->upper_);
-    lower_ = Min(lower_, other->lower_);
-    bool b = CanBeMinusZero() || other->CanBeMinusZero();
-    set_can_be_minus_zero(b);
-  }
-
-  // Compute a new result range and return true, if the operation
-  // can overflow.
+  void AddConstant(int32_t value);
+  void Sar(int32_t value);
+  void Shl(int32_t value);
   bool AddAndCheckOverflow(Range* other);
   bool SubAndCheckOverflow(Range* other);
   bool MulAndCheckOverflow(Range* other);
@@ -307,7 +263,7 @@
   static Representation Double() { return Representation(kDouble); }
   static Representation External() { return Representation(kExternal); }
 
-  bool Equals(const Representation& other) const {
+  bool Equals(const Representation& other) {
     return kind_ == other.kind_;
   }
 
@@ -542,15 +498,12 @@
   bool IsDefinedAfter(HBasicBlock* other) const;
 
   // Operands.
-  virtual int OperandCount() const { return 0; }
-  virtual HValue* OperandAt(int index) const {
-    UNREACHABLE();
-    return NULL;
-  }
+  virtual int OperandCount() = 0;
+  virtual HValue* OperandAt(int index) = 0;
   void SetOperandAt(int index, HValue* value);
 
-  int LookupOperandIndex(int occurrence_index, HValue* op) const;
-  bool UsesMultipleTimes(HValue* op) const;
+  int LookupOperandIndex(int occurrence_index, HValue* op);
+  bool UsesMultipleTimes(HValue* op);
 
   void ReplaceAndDelete(HValue* other);
   void ReplaceValue(HValue* other);
@@ -576,10 +529,9 @@
   void ComputeInitialRange();
 
   // Representation helpers.
-  virtual Representation RequiredInputRepresentation(int index) const {
-    return Representation::None();
-  }
-  virtual Representation InferredRepresentation() const {
+  virtual Representation RequiredInputRepresentation(int index) const = 0;
+
+  virtual Representation InferredRepresentation() {
     return representation();
   }
 
@@ -594,11 +546,11 @@
   HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
 #undef DECLARE_DO
 
-  bool Equals(HValue* other) const;
-  virtual intptr_t Hashcode() const;
+  bool Equals(HValue* other);
+  virtual intptr_t Hashcode();
 
   // Printing support.
-  virtual void PrintTo(StringStream* stream) const = 0;
+  virtual void PrintTo(StringStream* stream) = 0;
   void PrintNameTo(StringStream* stream);
   static void PrintTypeTo(HType type, StringStream* stream);
 
@@ -609,7 +561,7 @@
   // it has changed.
   bool UpdateInferredType();
 
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 
 #ifdef DEBUG
   virtual void Verify() = 0;
@@ -618,14 +570,14 @@
  protected:
   // This function must be overridden for instructions with flag kUseGVN, to
   // compare the non-Operand parts of the instruction.
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     UNREACHABLE();
     return false;
   }
   virtual void RepresentationChanged(Representation to) { }
   virtual Range* InferRange();
   virtual void DeleteFromGraph() = 0;
-  virtual void InternalSetOperandAt(int index, HValue* value) { UNREACHABLE(); }
+  virtual void InternalSetOperandAt(int index, HValue* value) = 0;
   void clear_block() {
     ASSERT(block_ != NULL);
     block_ = NULL;
@@ -667,8 +619,8 @@
   HInstruction* next() const { return next_; }
   HInstruction* previous() const { return previous_; }
 
-  void PrintTo(StringStream* stream) const;
-  virtual void PrintDataTo(StringStream* stream) const {}
+  virtual void PrintTo(StringStream* stream);
+  virtual void PrintDataTo(StringStream* stream) { }
 
   bool IsLinked() const { return block() != NULL; }
   void Unlink();
@@ -689,6 +641,8 @@
   // instruction.
   virtual bool IsCheckInstruction() const { return false; }
 
+  virtual bool IsCall() { return false; }
+
   DECLARE_INSTRUCTION(Instruction)
 
  protected:
@@ -715,12 +669,6 @@
 };
 
 
-class HBlockEntry: public HInstruction {
- public:
-  DECLARE_CONCRETE_INSTRUCTION(BlockEntry, "block_entry")
-};
-
-
 class HControlInstruction: public HInstruction {
  public:
   HControlInstruction(HBasicBlock* first, HBasicBlock* second)
@@ -730,7 +678,7 @@
   HBasicBlock* FirstSuccessor() const { return first_successor_; }
   HBasicBlock* SecondSuccessor() const { return second_successor_; }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_INSTRUCTION(ControlInstruction)
 
@@ -740,25 +688,101 @@
 };
 
 
-class HDeoptimize: public HControlInstruction {
+template<int NumElements>
+class HOperandContainer {
  public:
-  HDeoptimize() : HControlInstruction(NULL, NULL) { }
+  HOperandContainer() : elems_() { }
+
+  int length() { return NumElements; }
+  HValue*& operator[](int i) {
+    ASSERT(i < length());
+    return elems_[i];
+  }
+
+ private:
+  HValue* elems_[NumElements];
+};
+
+
+template<>
+class HOperandContainer<0> {
+ public:
+  int length() { return 0; }
+  HValue*& operator[](int i) {
+    UNREACHABLE();
+    static HValue* t = 0;
+    return t;
+  }
+};
+
+
+template<int V>
+class HTemplateInstruction : public HInstruction {
+ public:
+  int OperandCount() { return V; }
+  HValue* OperandAt(int i) { return inputs_[i]; }
+
+ protected:
+  void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
+
+ private:
+  HOperandContainer<V> inputs_;
+};
+
+
+template<int V>
+class HTemplateControlInstruction : public HControlInstruction {
+ public:
+  HTemplateControlInstruction<V>(HBasicBlock* first, HBasicBlock* second)
+    : HControlInstruction(first, second) { }
+  int OperandCount() { return V; }
+  HValue* OperandAt(int i) { return inputs_[i]; }
+
+ protected:
+  void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
+
+ private:
+  HOperandContainer<V> inputs_;
+};
+
+
+class HBlockEntry: public HTemplateInstruction<0> {
+ public:
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(BlockEntry, "block_entry")
+};
+
+
+class HDeoptimize: public HTemplateControlInstruction<0> {
+ public:
+  HDeoptimize() : HTemplateControlInstruction<0>(NULL, NULL) { }
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
 };
 
 
-class HGoto: public HControlInstruction {
+class HGoto: public HTemplateControlInstruction<0> {
  public:
   explicit HGoto(HBasicBlock* target)
-      : HControlInstruction(target, NULL), include_stack_check_(false) {
-  }
+      : HTemplateControlInstruction<0>(target, NULL),
+        include_stack_check_(false) { }
 
   void set_include_stack_check(bool include_stack_check) {
     include_stack_check_ = include_stack_check;
   }
   bool include_stack_check() const { return include_stack_check_; }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
 
  private:
@@ -766,34 +790,20 @@
 };
 
 
-class HUnaryControlInstruction: public HControlInstruction {
+class HUnaryControlInstruction: public HTemplateControlInstruction<1> {
  public:
   explicit HUnaryControlInstruction(HValue* value,
                                     HBasicBlock* true_target,
                                     HBasicBlock* false_target)
-      : HControlInstruction(true_target, false_target) {
+      : HTemplateControlInstruction<1>(true_target, false_target) {
     SetOperandAt(0, value);
   }
 
-  virtual Representation RequiredInputRepresentation(int index) const {
-    return Representation::Tagged();
-  }
+  virtual void PrintDataTo(StringStream* stream);
 
-  virtual void PrintDataTo(StringStream* stream) const;
-
-  HValue* value() const { return OperandAt(0); }
-  virtual int OperandCount() const { return 1; }
-  virtual HValue* OperandAt(int index) const { return operands_[index]; }
+  HValue* value() { return OperandAt(0); }
 
   DECLARE_INSTRUCTION(UnaryControlInstruction)
-
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value) {
-    operands_[index] = value;
-  }
-
- private:
-  HOperandVector<1> operands_;
 };
 
 
@@ -825,10 +835,14 @@
     ASSERT(!map.is_null());
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   Handle<Map> map() const { return map_; }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(CompareMap, "compare_map")
 
  private:
@@ -842,38 +856,36 @@
       : HUnaryControlInstruction(value, NULL, NULL) {
   }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(Return, "return")
 };
 
 
-class HAbnormalExit: public HControlInstruction {
+class HAbnormalExit: public HTemplateControlInstruction<0> {
  public:
-  HAbnormalExit() : HControlInstruction(NULL, NULL) { }
+  HAbnormalExit() : HTemplateControlInstruction<0>(NULL, NULL) { }
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(AbnormalExit, "abnormal_exit")
 };
 
 
-class HUnaryOperation: public HInstruction {
+class HUnaryOperation: public HTemplateInstruction<1> {
  public:
   explicit HUnaryOperation(HValue* value) {
     SetOperandAt(0, value);
   }
 
-  HValue* value() const { return OperandAt(0); }
-  virtual void PrintDataTo(StringStream* stream) const;
-  virtual int OperandCount() const { return 1; }
-  virtual HValue* OperandAt(int index) const { return operands_[index]; }
+  HValue* value() { return OperandAt(0); }
+  virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_INSTRUCTION(UnaryOperation)
-
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value) {
-    operands_[index] = value;
-  }
-
- private:
-  HOperandVector<1> operands_;
 };
 
 
@@ -895,13 +907,14 @@
  public:
   HChange(HValue* value,
           Representation from,
-          Representation to)
+          Representation to,
+          bool is_truncating)
       : HUnaryOperation(value), from_(from), to_(to) {
     ASSERT(!from.IsNone() && !to.IsNone());
     ASSERT(!from.Equals(to));
     set_representation(to);
     SetFlag(kUseGVN);
-
+    if (is_truncating) SetFlag(kTruncatingToInt32);
     if (from.IsInteger32() && to.IsTagged() && value->range() != NULL &&
         value->range()->IsInSmiRange()) {
       set_type(HType::Smi());
@@ -916,25 +929,19 @@
     return from_;
   }
 
-  bool CanTruncateToInt32() const {
-    for (int i = 0; i < uses()->length(); ++i) {
-      if (!uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) return false;
-    }
-    return true;
-  }
+  bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_CONCRETE_INSTRUCTION(Change,
                                CanTruncateToInt32() ? "truncate" : "change")
 
  protected:
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     if (!other->IsChange()) return false;
     HChange* change = HChange::cast(other);
     return value() == change->value()
-        && to().Equals(change->to())
-        && CanTruncateToInt32() == change->CanTruncateToInt32();
+        && to().Equals(change->to());
   }
 
  private:
@@ -953,7 +960,7 @@
         assigned_indexes_(2) {}
   virtual ~HSimulate() {}
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
   int ast_id() const { return ast_id_; }
@@ -978,8 +985,12 @@
   void AddPushedValue(HValue* value) {
     AddValue(kNoIndex, value);
   }
-  virtual int OperandCount() const { return values_.length(); }
-  virtual HValue* OperandAt(int index) const { return values_[index]; }
+  virtual int OperandCount() { return values_.length(); }
+  virtual HValue* OperandAt(int index) { return values_[index]; }
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(Simulate, "simulate")
 
@@ -1010,25 +1021,33 @@
 };
 
 
-class HStackCheck: public HInstruction {
+class HStackCheck: public HTemplateInstruction<0> {
  public:
   HStackCheck() { }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack_check")
 };
 
 
-class HEnterInlined: public HInstruction {
+class HEnterInlined: public HTemplateInstruction<0> {
  public:
   HEnterInlined(Handle<JSFunction> closure, FunctionLiteral* function)
       : closure_(closure), function_(function) {
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   Handle<JSFunction> closure() const { return closure_; }
   FunctionLiteral* function() const { return function_; }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(EnterInlined, "enter_inlined")
 
  private:
@@ -1037,39 +1056,49 @@
 };
 
 
-class HLeaveInlined: public HInstruction {
+class HLeaveInlined: public HTemplateInstruction<0> {
  public:
   HLeaveInlined() {}
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(LeaveInlined, "leave_inlined")
 };
 
 
 class HPushArgument: public HUnaryOperation {
  public:
-  explicit HPushArgument(HValue* value) : HUnaryOperation(value) { }
+  explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
+    set_representation(Representation::Tagged());
+  }
 
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
 
-  HValue* argument() const { return OperandAt(0); }
+  HValue* argument() { return OperandAt(0); }
 
   DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument")
 };
 
 
-class HContext: public HInstruction {
+class HContext: public HTemplateInstruction<0> {
  public:
   HContext() {
     set_representation(Representation::Tagged());
     SetFlag(kUseGVN);
   }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(Context, "context");
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -1082,8 +1111,12 @@
 
   DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer_context");
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -1096,8 +1129,12 @@
 
   DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global_object")
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -1111,94 +1148,79 @@
 
   DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global_receiver")
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
-class HCall: public HInstruction {
+template <int V>
+class HCall: public HTemplateInstruction<V> {
  public:
   // The argument count includes the receiver.
-  explicit HCall(int argument_count) : argument_count_(argument_count) {
-    set_representation(Representation::Tagged());
-    SetAllSideEffects();
+  explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
+    this->set_representation(Representation::Tagged());
+    this->SetAllSideEffects();
   }
 
-  virtual HType CalculateInferredType() const { return HType::Tagged(); }
+  virtual HType CalculateInferredType() { return HType::Tagged(); }
 
   virtual int argument_count() const { return argument_count_; }
 
-  virtual void PrintDataTo(StringStream* stream) const;
-
-  DECLARE_INSTRUCTION(Call)
+  virtual bool IsCall() { return true; }
 
  private:
   int argument_count_;
 };
 
 
-class HUnaryCall: public HCall {
+class HUnaryCall: public HCall<1> {
  public:
   HUnaryCall(HValue* value, int argument_count)
-      : HCall(argument_count), value_(NULL) {
+      : HCall<1>(argument_count) {
     SetOperandAt(0, value);
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
-
-  HValue* value() const { return value_; }
-
-  virtual int OperandCount() const { return 1; }
-  virtual HValue* OperandAt(int index) const {
-    ASSERT(index == 0);
-    return value_;
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
   }
 
+  virtual void PrintDataTo(StringStream* stream);
+
+  HValue* value() { return OperandAt(0); }
+
   DECLARE_INSTRUCTION(UnaryCall)
-
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value) {
-    ASSERT(index == 0);
-    value_ = value;
-  }
-
- private:
-  HValue* value_;
 };
 
 
-class HBinaryCall: public HCall {
+class HBinaryCall: public HCall<2> {
  public:
   HBinaryCall(HValue* first, HValue* second, int argument_count)
-      : HCall(argument_count) {
+      : HCall<2>(argument_count) {
     SetOperandAt(0, first);
     SetOperandAt(1, second);
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
-  HValue* first() const { return operands_[0]; }
-  HValue* second() const { return operands_[1]; }
-
-  virtual int OperandCount() const { return 2; }
-  virtual HValue* OperandAt(int index) const { return operands_[index]; }
-
-  DECLARE_INSTRUCTION(BinaryCall)
-
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value) {
-    operands_[index] = value;
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
   }
 
- private:
-  HOperandVector<2> operands_;
+  HValue* first() { return OperandAt(0); }
+  HValue* second() { return OperandAt(1); }
+
+  DECLARE_INSTRUCTION(BinaryCall)
 };
 
 
-class HCallConstantFunction: public HCall {
+class HCallConstantFunction: public HCall<0> {
  public:
   HCallConstantFunction(Handle<JSFunction> function, int argument_count)
-      : HCall(argument_count), function_(function) { }
+      : HCall<0>(argument_count), function_(function) { }
 
   Handle<JSFunction> function() const { return function_; }
 
@@ -1206,7 +1228,11 @@
     return function_->code() == Builtins::builtin(Builtins::FunctionApply);
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call_constant_function")
 
@@ -1225,8 +1251,8 @@
     return Representation::Tagged();
   }
 
-  HValue* context() const { return first(); }
-  HValue* key() const { return second(); }
+  HValue* context() { return first(); }
+  HValue* key() { return second(); }
 
   DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
 };
@@ -1238,13 +1264,17 @@
       : HUnaryCall(context, argument_count), name_(name) {
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
-  HValue* context() const { return value(); }
+  HValue* context() { return value(); }
   Handle<String> name() const { return name_; }
 
   DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
  private:
   Handle<String> name_;
 };
@@ -1256,7 +1286,11 @@
       : HUnaryCall(context, argument_count) {
   }
 
-  HValue* context() const { return value(); }
+  HValue* context() { return value(); }
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
 };
@@ -1268,11 +1302,15 @@
       : HUnaryCall(context, argument_count), name_(name) {
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
-  HValue* context() const { return value(); }
+  HValue* context() { return value(); }
   Handle<String> name() const { return name_; }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")
 
  private:
@@ -1280,15 +1318,19 @@
 };
 
 
-class HCallKnownGlobal: public HCall {
+class HCallKnownGlobal: public HCall<0> {
  public:
   HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
-      : HCall(argument_count), target_(target) { }
+      : HCall<0>(argument_count), target_(target) { }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   Handle<JSFunction> target() const { return target_; }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")
 
  private:
@@ -1306,24 +1348,28 @@
     return Representation::Tagged();
   }
 
-  HValue* context() const { return first(); }
-  HValue* constructor() const { return second(); }
+  HValue* context() { return first(); }
+  HValue* constructor() { return second(); }
 
   DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
 };
 
 
-class HCallRuntime: public HCall {
+class HCallRuntime: public HCall<0> {
  public:
   HCallRuntime(Handle<String> name,
                Runtime::Function* c_function,
                int argument_count)
-      : HCall(argument_count), c_function_(c_function), name_(name) { }
-  virtual void PrintDataTo(StringStream* stream) const;
+      : HCall<0>(argument_count), c_function_(c_function), name_(name) { }
+  virtual void PrintDataTo(StringStream* stream);
 
   Runtime::Function* function() const { return c_function_; }
   Handle<String> name() const { return name_; }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call_runtime")
 
  private:
@@ -1350,7 +1396,7 @@
   DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js_array_length")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -1369,7 +1415,7 @@
   DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed_array_length")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -1390,7 +1436,7 @@
   DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel_array_length")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -1405,12 +1451,12 @@
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Integer32();
   }
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 
   DECLARE_CONCRETE_INSTRUCTION(BitNot, "bit_not")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -1441,9 +1487,9 @@
     SetFlag(kUseGVN);
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 
   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
 
@@ -1458,11 +1504,10 @@
       case kMathSin:
       case kMathCos:
         return Representation::Double();
-        break;
       case kMathAbs:
         return representation();
-        break;
       default:
+        UNREACHABLE();
         return Representation::None();
     }
   }
@@ -1483,7 +1528,7 @@
   DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary_math_operation")
 
  protected:
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
     return op_ == b->op();
   }
@@ -1508,7 +1553,7 @@
   DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -1532,7 +1577,7 @@
                                "load-pixel-array-external-pointer")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -1550,8 +1595,8 @@
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
-  virtual void PrintDataTo(StringStream* stream) const;
-  virtual HType CalculateInferredType() const;
+  virtual void PrintDataTo(StringStream* stream);
+  virtual HType CalculateInferredType();
 
 #ifdef DEBUG
   virtual void Verify();
@@ -1562,7 +1607,7 @@
   DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check_map")
 
  protected:
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     HCheckMap* b = HCheckMap::cast(other);
     return map_.is_identical_to(b->map());
   }
@@ -1585,8 +1630,8 @@
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
-  virtual void PrintDataTo(StringStream* stream) const;
-  virtual HType CalculateInferredType() const;
+  virtual void PrintDataTo(StringStream* stream);
+  virtual HType CalculateInferredType();
 
 #ifdef DEBUG
   virtual void Verify();
@@ -1597,7 +1642,7 @@
   DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check_function")
 
  protected:
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     HCheckFunction* b = HCheckFunction::cast(other);
     return target_.is_identical_to(b->target());
   }
@@ -1645,7 +1690,7 @@
   // TODO(ager): It could be nice to allow the ommision of instance
   // type checks if we have already performed an instance type check
   // with a larger range.
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     HCheckInstanceType* b = HCheckInstanceType::cast(other);
     return (first_ == b->first()) && (last_ == b->last());
   }
@@ -1669,7 +1714,7 @@
     return Representation::Tagged();
   }
 
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 
 #ifdef DEBUG
   virtual void Verify();
@@ -1678,11 +1723,11 @@
   DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check_non_smi")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
-class HCheckPrototypeMaps: public HInstruction {
+class HCheckPrototypeMaps: public HTemplateInstruction<0> {
  public:
   HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
       : prototype_(prototype), holder_(holder) {
@@ -1701,7 +1746,11 @@
 
   DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check_prototype_maps")
 
-  virtual intptr_t Hashcode() const {
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
+  virtual intptr_t Hashcode() {
     ASSERT(!Heap::IsAllocationAllowed());
     intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
     hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
@@ -1709,7 +1758,7 @@
   }
 
  protected:
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
     return prototype_.is_identical_to(b->prototype()) &&
         holder_.is_identical_to(b->holder());
@@ -1733,7 +1782,7 @@
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 
 #ifdef DEBUG
   virtual void Verify();
@@ -1742,7 +1791,7 @@
   DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check_smi")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -1761,7 +1810,7 @@
     SetFlag(kFlexibleRepresentation);
   }
 
-  virtual Representation InferredRepresentation() const {
+  virtual Representation InferredRepresentation() {
     bool double_occurred = false;
     bool int32_occurred = false;
     for (int i = 0; i < OperandCount(); ++i) {
@@ -1780,10 +1829,10 @@
   virtual Representation RequiredInputRepresentation(int index) const {
     return representation();
   }
-  virtual HType CalculateInferredType() const;
-  virtual int OperandCount() const { return inputs_.length(); }
-  virtual HValue* OperandAt(int index) const { return inputs_[index]; }
-  HValue* GetRedundantReplacement() const;
+  virtual HType CalculateInferredType();
+  virtual int OperandCount() { return inputs_.length(); }
+  virtual HValue* OperandAt(int index) { return inputs_[index]; }
+  HValue* GetRedundantReplacement();
   void AddInput(HValue* value);
 
   bool IsReceiver() { return merged_index_ == 0; }
@@ -1792,7 +1841,7 @@
 
   virtual const char* Mnemonic() const { return "phi"; }
 
-  virtual void PrintTo(StringStream* stream) const;
+  virtual void PrintTo(StringStream* stream);
 
 #ifdef DEBUG
   virtual void Verify();
@@ -1840,18 +1889,22 @@
 };
 
 
-class HArgumentsObject: public HInstruction {
+class HArgumentsObject: public HTemplateInstruction<0> {
  public:
   HArgumentsObject() {
     set_representation(Representation::Tagged());
     SetFlag(kIsArguments);
   }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject, "arguments-object")
 };
 
 
-class HConstant: public HInstruction {
+class HConstant: public HTemplateInstruction<0> {
  public:
   HConstant(Handle<Object> handle, Representation r);
 
@@ -1859,9 +1912,13 @@
 
   bool InOldSpace() const { return !Heap::InNewSpace(*handle_); }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   virtual bool EmitAtUses() const { return !representation().IsDouble(); }
-  virtual void PrintDataTo(StringStream* stream) const;
-  virtual HType CalculateInferredType() const;
+  virtual void PrintDataTo(StringStream* stream);
+  virtual HType CalculateInferredType();
   bool IsInteger() const { return handle_->IsSmi(); }
   HConstant* CopyToRepresentation(Representation r) const;
   HConstant* CopyToTruncatedInt32() const;
@@ -1877,7 +1934,7 @@
   }
   bool HasStringValue() const { return handle_->IsString(); }
 
-  virtual intptr_t Hashcode() const {
+  virtual intptr_t Hashcode() {
     ASSERT(!Heap::allow_allocation(false));
     return reinterpret_cast<intptr_t>(*handle());
   }
@@ -1891,7 +1948,7 @@
  protected:
   virtual Range* InferRange();
 
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     HConstant* other_constant = HConstant::cast(other);
     return handle().is_identical_to(other_constant->handle());
   }
@@ -1910,7 +1967,7 @@
 };
 
 
-class HBinaryOperation: public HInstruction {
+class HBinaryOperation: public HTemplateInstruction<2> {
  public:
   HBinaryOperation(HValue* left, HValue* right) {
     ASSERT(left != NULL && right != NULL);
@@ -1918,38 +1975,29 @@
     SetOperandAt(1, right);
   }
 
-  HValue* left() const { return OperandAt(0); }
-  HValue* right() const { return OperandAt(1); }
+  HValue* left() { return OperandAt(0); }
+  HValue* right() { return OperandAt(1); }
 
   // TODO(kasperl): Move these helpers to the IA-32 Lithium
   // instruction sequence builder.
-  HValue* LeastConstantOperand() const {
+  HValue* LeastConstantOperand() {
     if (IsCommutative() && left()->IsConstant()) return right();
     return left();
   }
-  HValue* MostConstantOperand() const {
+  HValue* MostConstantOperand() {
     if (IsCommutative() && left()->IsConstant()) return left();
     return right();
   }
 
   virtual bool IsCommutative() const { return false; }
 
-  virtual void PrintDataTo(StringStream* stream) const;
-  virtual int OperandCount() const { return operands_.length(); }
-  virtual HValue* OperandAt(int index) const { return operands_[index]; }
+  virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_INSTRUCTION(BinaryOperation)
-
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value) {
-    operands_[index] = value;
-  }
-
-  HOperandVector<2> operands_;
 };
 
 
-class HApplyArguments: public HInstruction {
+class HApplyArguments: public HTemplateInstruction<4> {
  public:
   HApplyArguments(HValue* function,
                   HValue* receiver,
@@ -1970,27 +2018,16 @@
         : Representation::Tagged();
   }
 
-  HValue* function() const { return OperandAt(0); }
-  HValue* receiver() const { return OperandAt(1); }
-  HValue* length() const { return OperandAt(2); }
-  HValue* elements() const { return OperandAt(3); }
-
-  virtual int OperandCount() const { return operands_.length(); }
-  virtual HValue* OperandAt(int index) const { return operands_[index]; }
+  HValue* function() { return OperandAt(0); }
+  HValue* receiver() { return OperandAt(1); }
+  HValue* length() { return OperandAt(2); }
+  HValue* elements() { return OperandAt(3); }
 
   DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")
-
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value) {
-    operands_[index] = value;
-  }
-
- private:
-  HOperandVector<4> operands_;
 };
 
 
-class HArgumentsElements: public HInstruction {
+class HArgumentsElements: public HTemplateInstruction<0> {
  public:
   HArgumentsElements() {
     // The value produced by this instruction is a pointer into the stack
@@ -2001,8 +2038,12 @@
 
   DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments_elements")
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -2013,14 +2054,18 @@
     SetFlag(kUseGVN);
   }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments_length")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
-class HAccessArgumentsAt: public HInstruction {
+class HAccessArgumentsAt: public HTemplateInstruction<3> {
  public:
   HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
     set_representation(Representation::Tagged());
@@ -2030,7 +2075,7 @@
     SetOperandAt(2, index);
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   virtual Representation RequiredInputRepresentation(int index) const {
     // The arguments elements is considered tagged.
@@ -2039,24 +2084,13 @@
         : Representation::Integer32();
   }
 
-  HValue* arguments() const { return operands_[0]; }
-  HValue* length() const { return operands_[1]; }
-  HValue* index() const { return operands_[2]; }
-
-  virtual int OperandCount() const { return operands_.length(); }
-  virtual HValue* OperandAt(int index) const { return operands_[index]; }
+  HValue* arguments() { return OperandAt(0); }
+  HValue* length() { return OperandAt(1); }
+  HValue* index() { return OperandAt(2); }
 
   DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access_arguments_at")
 
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value) {
-    operands_[index] = value;
-  }
-
-  virtual bool DataEquals(HValue* other) const { return true; }
-
- private:
-  HOperandVector<3> operands_;
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -2077,13 +2111,13 @@
   virtual void Verify();
 #endif
 
-  HValue* index() const { return left(); }
-  HValue* length() const { return right(); }
+  HValue* index() { return left(); }
+  HValue* length() { return right(); }
 
   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds_check")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -2109,7 +2143,7 @@
     }
   }
 
-  HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 
   DECLARE_INSTRUCTION(BitwiseBinaryOperation)
 };
@@ -2131,11 +2165,11 @@
     }
   }
 
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
   virtual Representation RequiredInputRepresentation(int index) const {
     return representation();
   }
-  virtual Representation InferredRepresentation() const {
+  virtual Representation InferredRepresentation() {
     if (left()->representation().Equals(right()->representation())) {
       return left()->representation();
     }
@@ -2168,18 +2202,18 @@
     return input_representation_;
   }
   Token::Value token() const { return token_; }
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 
-  virtual intptr_t Hashcode() const {
+  virtual intptr_t Hashcode() {
     return HValue::Hashcode() * 7 + token_;
   }
 
   DECLARE_CONCRETE_INSTRUCTION(Compare, "compare")
 
  protected:
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     HCompare* comp = HCompare::cast(other);
     return token_ == comp->token();
   }
@@ -2205,12 +2239,12 @@
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 
   DECLARE_CONCRETE_INSTRUCTION(CompareJSObjectEq, "compare-js-object-eq")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -2228,7 +2262,7 @@
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 };
 
 
@@ -2242,7 +2276,7 @@
   DECLARE_CONCRETE_INSTRUCTION(IsNull, "is_null")
 
  protected:
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     HIsNull* b = HIsNull::cast(other);
     return is_strict_ == b->is_strict();
   }
@@ -2259,7 +2293,7 @@
   DECLARE_CONCRETE_INSTRUCTION(IsObject, "is_object")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -2270,11 +2304,11 @@
   DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is_smi")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
-class HIsConstructCall: public HInstruction {
+class HIsConstructCall: public HTemplateInstruction<0> {
  public:
   HIsConstructCall() {
     set_representation(Representation::Tagged());
@@ -2285,10 +2319,14 @@
     return !HasSideEffects() && (uses()->length() <= 1);
   }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(IsConstructCall, "is_construct_call")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -2304,12 +2342,12 @@
   InstanceType from() { return from_; }
   InstanceType to() { return to_; }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has_instance_type")
 
  protected:
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     HHasInstanceType* b = HHasInstanceType::cast(other);
     return (from_ == b->from()) && (to_ == b->to());
   }
@@ -2327,7 +2365,18 @@
   DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has_cached_array_index")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
+};
+
+
+class HGetCachedArrayIndex: public HUnaryPredicate {
+ public:
+  explicit HGetCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { }
+
+  DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get_cached_array_index")
+
+ protected:
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -2338,12 +2387,12 @@
 
   DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class_of_test")
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   Handle<String> class_name() const { return class_name_; }
 
  protected:
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     HClassOfTest* b = HClassOfTest::cast(other);
     return class_name_.is_identical_to(b->class_name_);
   }
@@ -2359,12 +2408,12 @@
       : HUnaryPredicate(value), type_literal_(type_literal) { }
 
   Handle<String> type_literal() { return type_literal_; }
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof_is")
 
  protected:
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     HTypeofIs* b = HTypeofIs::cast(other);
     return type_literal_.is_identical_to(b->type_literal_);
   }
@@ -2374,7 +2423,7 @@
 };
 
 
-class HInstanceOf: public HInstruction {
+class HInstanceOf: public HTemplateInstruction<3> {
  public:
   HInstanceOf(HValue* context, HValue* left, HValue* right) {
     SetOperandAt(0, context);
@@ -2384,9 +2433,9 @@
     SetAllSideEffects();
   }
 
-  HValue* context() const { return operands_[0]; }
-  HValue* left() const { return operands_[1]; }
-  HValue* right() const { return operands_[2]; }
+  HValue* context() { return OperandAt(0); }
+  HValue* left() { return OperandAt(1); }
+  HValue* right() { return OperandAt(2); }
 
   virtual bool EmitAtUses() const {
     return !HasSideEffects() && (uses()->length() <= 1);
@@ -2396,20 +2445,9 @@
     return Representation::Tagged();
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
-
-  virtual int OperandCount() const { return 3; }
-  virtual HValue* OperandAt(int index) const { return operands_[index]; }
+  virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of")
-
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value) {
-    operands_[index] = value;
-  }
-
- private:
-  HOperandVector<3> operands_;
 };
 
 
@@ -2450,7 +2488,7 @@
   DECLARE_CONCRETE_INSTRUCTION(Power, "power")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -2468,12 +2506,12 @@
 
   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
 
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 
   DECLARE_CONCRETE_INSTRUCTION(Add, "add")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 
   virtual Range* InferRange();
 };
@@ -2490,7 +2528,7 @@
   DECLARE_CONCRETE_INSTRUCTION(Sub, "sub")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 
   virtual Range* InferRange();
 };
@@ -2512,7 +2550,7 @@
   DECLARE_CONCRETE_INSTRUCTION(Mul, "mul")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 
   virtual Range* InferRange();
 };
@@ -2529,7 +2567,7 @@
   DECLARE_CONCRETE_INSTRUCTION(Mod, "mod")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 
   virtual Range* InferRange();
 };
@@ -2547,7 +2585,7 @@
   DECLARE_CONCRETE_INSTRUCTION(Div, "div")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 
   virtual Range* InferRange();
 };
@@ -2559,12 +2597,12 @@
       : HBitwiseBinaryOperation(left, right) { }
 
   virtual bool IsCommutative() const { return true; }
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 
   DECLARE_CONCRETE_INSTRUCTION(BitAnd, "bit_and")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 
   virtual Range* InferRange();
 };
@@ -2576,12 +2614,12 @@
       : HBitwiseBinaryOperation(left, right) { }
 
   virtual bool IsCommutative() const { return true; }
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 
   DECLARE_CONCRETE_INSTRUCTION(BitXor, "bit_xor")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -2591,12 +2629,12 @@
       : HBitwiseBinaryOperation(left, right) { }
 
   virtual bool IsCommutative() const { return true; }
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 
   DECLARE_CONCRETE_INSTRUCTION(BitOr, "bit_or")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 
   virtual Range* InferRange();
 };
@@ -2608,12 +2646,12 @@
       : HBitwiseBinaryOperation(left, right) { }
 
   virtual Range* InferRange();
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 
   DECLARE_CONCRETE_INSTRUCTION(Shl, "shl")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -2622,12 +2660,12 @@
   HShr(HValue* left, HValue* right)
       : HBitwiseBinaryOperation(left, right) { }
 
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 
   DECLARE_CONCRETE_INSTRUCTION(Shr, "shr")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -2637,16 +2675,16 @@
       : HBitwiseBinaryOperation(left, right) { }
 
   virtual Range* InferRange();
-  virtual HType CalculateInferredType() const;
+  virtual HType CalculateInferredType();
 
   DECLARE_CONCRETE_INSTRUCTION(Sar, "sar")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
-class HOsrEntry: public HInstruction {
+class HOsrEntry: public HTemplateInstruction<0> {
  public:
   explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
     SetFlag(kChangesOsrEntries);
@@ -2654,6 +2692,10 @@
 
   int ast_id() const { return ast_id_; }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr_entry")
 
  private:
@@ -2661,7 +2703,7 @@
 };
 
 
-class HParameter: public HInstruction {
+class HParameter: public HTemplateInstruction<0> {
  public:
   explicit HParameter(unsigned index) : index_(index) {
     set_representation(Representation::Tagged());
@@ -2669,7 +2711,11 @@
 
   unsigned index() const { return index_; }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
 
@@ -2688,7 +2734,7 @@
 
   CodeStub::Major major_key() { return major_key_; }
 
-  HValue* context() const { return value(); }
+  HValue* context() { return value(); }
 
   void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
     transcendental_type_ = transcendental_type;
@@ -2697,7 +2743,11 @@
     return transcendental_type_;
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")
 
@@ -2707,15 +2757,19 @@
 };
 
 
-class HUnknownOSRValue: public HInstruction {
+class HUnknownOSRValue: public HTemplateInstruction<0> {
  public:
   HUnknownOSRValue() { set_representation(Representation::Tagged()); }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown_osr_value")
 };
 
 
-class HLoadGlobal: public HInstruction {
+class HLoadGlobal: public HTemplateInstruction<0> {
  public:
   HLoadGlobal(Handle<JSGlobalPropertyCell> cell, bool check_hole_value)
       : cell_(cell), check_hole_value_(check_hole_value) {
@@ -2727,20 +2781,21 @@
   Handle<JSGlobalPropertyCell>  cell() const { return cell_; }
   bool check_hole_value() const { return check_hole_value_; }
 
-  virtual Representation RequiredInputRepresentation(int index) const {
-    return Representation::Tagged();
-  }
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
-  virtual intptr_t Hashcode() const {
+  virtual intptr_t Hashcode() {
     ASSERT(!Heap::allow_allocation(false));
     return reinterpret_cast<intptr_t>(*cell_);
   }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load_global")
 
  protected:
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     HLoadGlobal* b = HLoadGlobal::cast(other);
     return cell_.is_identical_to(b->cell());
   }
@@ -2768,7 +2823,7 @@
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_CONCRETE_INSTRUCTION(StoreGlobal, "store_global")
 
@@ -2793,12 +2848,12 @@
     return Representation::Tagged();
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load_context_slot")
 
  protected:
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     HLoadContextSlot* b = HLoadContextSlot::cast(other);
     return (slot_index() == b->slot_index());
   }
@@ -2821,11 +2876,11 @@
     SetFlag(kChangesContextSlots);
   }
 
-  HValue* context() const { return OperandAt(0); }
-  HValue* value() const { return OperandAt(1); }
+  HValue* context() { return OperandAt(0); }
+  HValue* value() { return OperandAt(1); }
   int slot_index() const { return slot_index_; }
 
-  bool NeedsWriteBarrier() const {
+  bool NeedsWriteBarrier() {
     return StoringValueNeedsWriteBarrier(value());
   }
 
@@ -2833,7 +2888,7 @@
     return Representation::Tagged();
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store_context_slot")
 
@@ -2857,19 +2912,19 @@
     }
   }
 
-  HValue* object() const { return OperandAt(0); }
+  HValue* object() { return OperandAt(0); }
   bool is_in_object() const { return is_in_object_; }
   int offset() const { return offset_; }
 
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load_named_field")
 
  protected:
-  virtual bool DataEquals(HValue* other) const {
+  virtual bool DataEquals(HValue* other) {
     HLoadNamedField* b = HLoadNamedField::cast(other);
     return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
   }
@@ -2888,8 +2943,8 @@
     SetAllSideEffects();
   }
 
-  HValue* context() const { return OperandAt(0); }
-  HValue* object() const { return OperandAt(1); }
+  HValue* context() { return OperandAt(0); }
+  HValue* object() { return OperandAt(1); }
   Handle<Object> name() const { return name_; }
 
   virtual Representation RequiredInputRepresentation(int index) const {
@@ -2912,7 +2967,7 @@
     SetFlag(kDependsOnCalls);
   }
 
-  HValue* function() const { return OperandAt(0); }
+  HValue* function() { return OperandAt(0); }
 
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
@@ -2921,46 +2976,34 @@
   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load_function_prototype")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
-class HLoadKeyed: public HBinaryOperation {
+class HLoadKeyedFastElement: public HBinaryOperation {
  public:
-  HLoadKeyed(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
+  HLoadKeyedFastElement(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
     set_representation(Representation::Tagged());
-  }
-
-  virtual void PrintDataTo(StringStream* stream) const;
-
-  virtual Representation RequiredInputRepresentation(int index) const {
-    return Representation::Tagged();
-  }
-  HValue* object() const { return OperandAt(0); }
-  HValue* key() const { return OperandAt(1); }
-
-  DECLARE_INSTRUCTION(LoadKeyed)
-};
-
-
-class HLoadKeyedFastElement: public HLoadKeyed {
- public:
-  HLoadKeyedFastElement(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
     SetFlag(kDependsOnArrayElements);
     SetFlag(kUseGVN);
   }
 
+  HValue* object() { return OperandAt(0); }
+  HValue* key() { return OperandAt(1); }
+
   virtual Representation RequiredInputRepresentation(int index) const {
     // The key is supposed to be Integer32.
     return (index == 1) ? Representation::Integer32()
         : Representation::Tagged();
   }
 
+  virtual void PrintDataTo(StringStream* stream);
+
   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement,
                                "load_keyed_fast_element")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
@@ -2975,7 +3018,7 @@
     SetFlag(kUseGVN);
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   virtual Representation RequiredInputRepresentation(int index) const {
     // The key is supposed to be Integer32, but the base pointer
@@ -2984,76 +3027,50 @@
         : Representation::External();
   }
 
-  HValue* external_pointer() const { return OperandAt(0); }
-  HValue* key() const { return OperandAt(1); }
+  HValue* external_pointer() { return OperandAt(0); }
+  HValue* key() { return OperandAt(1); }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayElement,
                                "load_pixel_array_element")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 };
 
 
-class HLoadKeyedGeneric: public HLoadKeyed {
+class HLoadKeyedGeneric: public HTemplateInstruction<3> {
  public:
-  HLoadKeyedGeneric(HContext* context, HValue* obj, HValue* key)
-      : HLoadKeyed(obj, key), context_(NULL) {
+  HLoadKeyedGeneric(HContext* context, HValue* obj, HValue* key) {
+    set_representation(Representation::Tagged());
+    SetOperandAt(0, obj);
+    SetOperandAt(1, key);
     SetOperandAt(2, context);
     SetAllSideEffects();
   }
 
-  HValue* context() const { return context_; }
-  HValue* object() const { return operands_[0]; }
-  HValue* key() const { return operands_[1]; }
+  HValue* object() { return OperandAt(0); }
+  HValue* key() { return OperandAt(1); }
+  HValue* context() { return OperandAt(2); }
 
-  virtual int OperandCount() const { return 3; }
-  virtual HValue* OperandAt(int index) const {
-    return (index < 2) ? operands_[index] : context_;
-  }
-
-  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
-
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value);
-
- private:
-  HValue* context_;
-};
-
-
-class HStoreNamed: public HBinaryOperation {
- public:
-  HStoreNamed(HValue* obj, Handle<String> name, HValue* val)
-      : HBinaryOperation(obj, val), name_(name) {
-  }
+  virtual void PrintDataTo(StringStream* stream);
 
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
 
-  virtual void PrintDataTo(StringStream* stream) const;
-
-  HValue* object() const { return OperandAt(0); }
-  Handle<String> name() const { return name_; }
-  HValue* value() const { return OperandAt(1); }
-  void set_value(HValue* value) { SetOperandAt(1, value); }
-
-  DECLARE_INSTRUCTION(StoreNamed)
-
- private:
-  Handle<String> name_;
+  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
 };
 
 
-class HStoreNamedField: public HStoreNamed {
+class HStoreNamedField: public HBinaryOperation {
  public:
   HStoreNamedField(HValue* obj,
                    Handle<String> name,
                    HValue* val,
                    bool in_object,
                    int offset)
-      : HStoreNamed(obj, name, val),
+      : HBinaryOperation(obj, val),
+        name_(name),
         is_in_object_(in_object),
         offset_(offset) {
     if (is_in_object_) {
@@ -3068,94 +3085,66 @@
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
+  HValue* object() { return OperandAt(0); }
+  HValue* value() { return OperandAt(1); }
+
+  Handle<String> name() const { return name_; }
   bool is_in_object() const { return is_in_object_; }
   int offset() const { return offset_; }
   Handle<Map> transition() const { return transition_; }
   void set_transition(Handle<Map> map) { transition_ = map; }
 
-  bool NeedsWriteBarrier() const {
+  bool NeedsWriteBarrier() {
     return StoringValueNeedsWriteBarrier(value());
   }
 
  private:
+  Handle<String> name_;
   bool is_in_object_;
   int offset_;
   Handle<Map> transition_;
 };
 
 
-class HStoreNamedGeneric: public HStoreNamed {
+class HStoreNamedGeneric: public HTemplateInstruction<3> {
  public:
   HStoreNamedGeneric(HValue* context,
                      HValue* object,
                      Handle<String> name,
                      HValue* value)
-      : HStoreNamed(object, name, value), context_(NULL) {
+      : name_(name) {
+    SetOperandAt(0, object);
+    SetOperandAt(1, value);
     SetOperandAt(2, context);
     SetAllSideEffects();
   }
 
-  HValue* context() const { return context_; }
-  HValue* object() const { return operands_[0]; }
-  HValue* value() const { return operands_[1]; }
+  HValue* object() { return OperandAt(0); }
+  HValue* value() { return OperandAt(1); }
+  HValue* context() { return OperandAt(2); }
+  Handle<String> name() { return name_; }
 
-  virtual int OperandCount() const { return 3; }
-
-  virtual HValue* OperandAt(int index) const {
-    return (index < 2) ? operands_[index] : context_;
-  }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
-
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value);
-
- private:
-  HValue* context_;
-};
-
-
-class HStoreKeyed: public HInstruction {
- public:
-  HStoreKeyed(HValue* obj, HValue* key, HValue* val) {
-    SetOperandAt(0, obj);
-    SetOperandAt(1, key);
-    SetOperandAt(2, val);
-  }
-
-  virtual void PrintDataTo(StringStream* stream) const;
-  virtual int OperandCount() const { return operands_.length(); }
-  virtual HValue* OperandAt(int index) const { return operands_[index]; }
+  virtual void PrintDataTo(StringStream* stream);
 
   virtual Representation RequiredInputRepresentation(int index) const {
     return Representation::Tagged();
   }
 
-  HValue* object() const { return OperandAt(0); }
-  HValue* key() const { return OperandAt(1); }
-  HValue* value() const { return OperandAt(2); }
+  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
 
-  bool NeedsWriteBarrier() const {
-    return StoringValueNeedsWriteBarrier(value());
-  }
-
-  DECLARE_INSTRUCTION(StoreKeyed)
-
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value) {
-    operands_[index] = value;
-  }
-
-  HOperandVector<3> operands_;
+ private:
+  Handle<String> name_;
 };
 
 
-class HStoreKeyedFastElement: public HStoreKeyed {
+class HStoreKeyedFastElement: public HTemplateInstruction<3> {
  public:
-  HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val)
-      : HStoreKeyed(obj, key, val) {
+  HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val) {
+    SetOperandAt(0, obj);
+    SetOperandAt(1, key);
+    SetOperandAt(2, val);
     SetFlag(kChangesArrayElements);
   }
 
@@ -3165,40 +3154,74 @@
         : Representation::Tagged();
   }
 
+  HValue* object() { return OperandAt(0); }
+  HValue* key() { return OperandAt(1); }
+  HValue* value() { return OperandAt(2); }
+
+  bool NeedsWriteBarrier() {
+    return StoringValueNeedsWriteBarrier(value());
+  }
+
+  virtual void PrintDataTo(StringStream* stream);
+
   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
                                "store_keyed_fast_element")
 };
 
 
-class HStoreKeyedGeneric: public HStoreKeyed {
+class HStorePixelArrayElement: public HTemplateInstruction<3> {
+ public:
+  HStorePixelArrayElement(HValue* external_elements, HValue* key, HValue* val) {
+    SetFlag(kChangesPixelArrayElements);
+    SetOperandAt(0, external_elements);
+    SetOperandAt(1, key);
+    SetOperandAt(2, val);
+  }
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    if (index == 0) {
+      return Representation::External();
+    } else {
+      return Representation::Integer32();
+    }
+  }
+
+  HValue* external_pointer() { return OperandAt(0); }
+  HValue* key() { return OperandAt(1); }
+  HValue* value() { return OperandAt(2); }
+
+  DECLARE_CONCRETE_INSTRUCTION(StorePixelArrayElement,
+                               "store_pixel_array_element")
+};
+
+
+class HStoreKeyedGeneric: public HTemplateInstruction<4> {
  public:
   HStoreKeyedGeneric(HValue* context,
                      HValue* object,
                      HValue* key,
-                     HValue* value)
-      : HStoreKeyed(object, key, value), context_(NULL) {
+                     HValue* value) {
+    SetOperandAt(0, object);
+    SetOperandAt(1, key);
+    SetOperandAt(2, value);
     SetOperandAt(3, context);
     SetAllSideEffects();
   }
 
-  HValue* context() const { return context_; }
-  HValue* object() const { return operands_[0]; }
-  HValue* key() const { return operands_[1]; }
-  HValue* value() const { return operands_[2]; }
+  HValue* object() { return OperandAt(0); }
+  HValue* key() { return OperandAt(1); }
+  HValue* value() { return OperandAt(2); }
+  HValue* context() { return OperandAt(3); }
 
-  virtual int OperandCount() const { return 4; }
-
-  virtual HValue* OperandAt(int index) const {
-    return (index < 3) ? operands_[index] : context_;
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
   }
 
+  virtual void PrintDataTo(StringStream* stream);
+
   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
-
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value);
-
- private:
-  HValue* context_;
 };
 
 
@@ -3216,13 +3239,13 @@
         : Representation::Tagged();
   }
 
-  HValue* string() const { return OperandAt(0); }
-  HValue* index() const { return OperandAt(1); }
+  HValue* string() { return OperandAt(0); }
+  HValue* index() { return OperandAt(1); }
 
   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string_char_code_at")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 
   virtual Range* InferRange() {
     return new Range(0, String::kMaxUC16CharCode);
@@ -3241,7 +3264,7 @@
     return Representation::Tagged();
   }
 
-  virtual HType CalculateInferredType() const {
+  virtual HType CalculateInferredType() {
     STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
     return HType::Smi();
   }
@@ -3249,7 +3272,7 @@
   DECLARE_CONCRETE_INSTRUCTION(StringLength, "string_length")
 
  protected:
-  virtual bool DataEquals(HValue* other) const { return true; }
+  virtual bool DataEquals(HValue* other) { return true; }
 
   virtual Range* InferRange() {
     return new Range(0, String::kMaxLength);
@@ -3257,31 +3280,30 @@
 };
 
 
-class HMaterializedLiteral: public HInstruction {
+template <int V>
+class HMaterializedLiteral: public HTemplateInstruction<V> {
  public:
-  HMaterializedLiteral(int index, int depth)
+  HMaterializedLiteral<V>(int index, int depth)
       : literal_index_(index), depth_(depth) {
-    set_representation(Representation::Tagged());
+    this->set_representation(Representation::Tagged());
   }
 
   int literal_index() const { return literal_index_; }
   int depth() const { return depth_; }
 
-  DECLARE_INSTRUCTION(MaterializedLiteral)
-
  private:
   int literal_index_;
   int depth_;
 };
 
 
-class HArrayLiteral: public HMaterializedLiteral {
+class HArrayLiteral: public HMaterializedLiteral<0> {
  public:
   HArrayLiteral(Handle<FixedArray> constant_elements,
                 int length,
                 int literal_index,
                 int depth)
-      : HMaterializedLiteral(literal_index, depth),
+      : HMaterializedLiteral<0>(literal_index, depth),
         length_(length),
         constant_elements_(constant_elements) {}
 
@@ -3290,6 +3312,10 @@
 
   bool IsCopyOnWrite() const;
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array_literal")
 
  private:
@@ -3298,55 +3324,53 @@
 };
 
 
-class HObjectLiteral: public HMaterializedLiteral {
+class HObjectLiteral: public HMaterializedLiteral<1> {
  public:
   HObjectLiteral(HValue* context,
                  Handle<FixedArray> constant_properties,
                  bool fast_elements,
                  int literal_index,
                  int depth)
-      : HMaterializedLiteral(literal_index, depth),
-        context_(NULL),
+      : HMaterializedLiteral<1>(literal_index, depth),
         constant_properties_(constant_properties),
         fast_elements_(fast_elements) {
     SetOperandAt(0, context);
   }
 
-  HValue* context() const { return context_; }
+  HValue* context() { return OperandAt(0); }
   Handle<FixedArray> constant_properties() const {
     return constant_properties_;
   }
   bool fast_elements() const { return fast_elements_; }
 
-  virtual int OperandCount() const { return 1; }
-  virtual HValue* OperandAt(int index) const { return context_; }
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal")
 
- protected:
-  virtual void InternalSetOperandAt(int index, HValue* value) {
-    context_ = value;
-  }
-
  private:
-  HValue* context_;
   Handle<FixedArray> constant_properties_;
   bool fast_elements_;
 };
 
 
-class HRegExpLiteral: public HMaterializedLiteral {
+class HRegExpLiteral: public HMaterializedLiteral<0> {
  public:
   HRegExpLiteral(Handle<String> pattern,
                  Handle<String> flags,
                  int literal_index)
-      : HMaterializedLiteral(literal_index, 0),
+      : HMaterializedLiteral<0>(literal_index, 0),
         pattern_(pattern),
         flags_(flags) { }
 
   Handle<String> pattern() { return pattern_; }
   Handle<String> flags() { return flags_; }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp_literal")
 
  private:
@@ -3355,13 +3379,17 @@
 };
 
 
-class HFunctionLiteral: public HInstruction {
+class HFunctionLiteral: public HTemplateInstruction<0> {
  public:
   HFunctionLiteral(Handle<SharedFunctionInfo> shared, bool pretenure)
       : shared_info_(shared), pretenure_(pretenure) {
     set_representation(Representation::Tagged());
   }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function_literal")
 
   Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
@@ -3393,6 +3421,10 @@
     set_representation(Representation::Tagged());
   }
 
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value_of")
 };
 
@@ -3411,8 +3443,8 @@
 
   DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete_property")
 
-  HValue* object() const { return left(); }
-  HValue* key() const { return right(); }
+  HValue* object() { return left(); }
+  HValue* key() { return right(); }
 };
 
 #undef DECLARE_INSTRUCTION
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 9be3176..158bfbe 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -106,18 +106,10 @@
   if (first_ == NULL) {
     HBlockEntry* entry = new HBlockEntry();
     entry->InitializeAsFirst(this);
-    first_ = entry;
+    first_ = last_ = entry;
   }
-  instr->InsertAfter(GetLastInstruction());
-}
-
-
-HInstruction* HBasicBlock::GetLastInstruction() {
-  if (end_ != NULL) return end_->previous();
-  if (first_ == NULL) return NULL;
-  if (last_ == NULL) last_ = first_;
-  while (last_->next() != NULL) last_ = last_->next();
-  return last_;
+  instr->InsertAfter(last_);
+  last_ = instr;
 }
 
 
@@ -178,7 +170,7 @@
   for (int i = 0; i < length; i++) {
     HBasicBlock* predecessor = predecessors_[i];
     ASSERT(predecessor->end()->IsGoto());
-    HSimulate* simulate = HSimulate::cast(predecessor->GetLastInstruction());
+    HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
     // We only need to verify the ID once.
     ASSERT(i != 0 ||
            predecessor->last_environment()->closure()->shared()
@@ -490,179 +482,60 @@
 }
 
 
-void HSubgraph::AppendOptional(HSubgraph* graph,
-                               bool on_true_branch,
-                               HValue* value) {
-  ASSERT(HasExit() && graph->HasExit());
-  HBasicBlock* other_block = graph_->CreateBasicBlock();
-  HBasicBlock* join_block = graph_->CreateBasicBlock();
-
-  HTest* test = on_true_branch
-      ? new HTest(value, graph->entry_block(), other_block)
-      : new HTest(value, other_block, graph->entry_block());
-  exit_block_->Finish(test);
-  other_block->Goto(join_block);
-  graph->exit_block()->Goto(join_block);
-  exit_block_ = join_block;
-}
-
-
-void HSubgraph::AppendJoin(HSubgraph* then_graph,
-                           HSubgraph* else_graph,
-                           AstNode* node) {
-  if (then_graph->HasExit() && else_graph->HasExit()) {
-    // We need to merge, create new merge block.
+HBasicBlock* HGraphBuilder::CreateJoin(HBasicBlock* first,
+                                       HBasicBlock* second,
+                                       int join_id) {
+  if (first == NULL) {
+    return second;
+  } else if (second == NULL) {
+    return first;
+  } else {
     HBasicBlock* join_block = graph_->CreateBasicBlock();
-    then_graph->exit_block()->Goto(join_block);
-    else_graph->exit_block()->Goto(join_block);
-    join_block->SetJoinId(node->id());
-    exit_block_ = join_block;
-  } else if (then_graph->HasExit()) {
-    exit_block_ = then_graph->exit_block_;
-  } else if (else_graph->HasExit()) {
-    exit_block_ = else_graph->exit_block_;
-  } else {
-    exit_block_ = NULL;
+    first->Goto(join_block);
+    second->Goto(join_block);
+    join_block->SetJoinId(join_id);
+    return join_block;
   }
 }
 
 
-void HSubgraph::ResolveContinue(IterationStatement* statement) {
-  HBasicBlock* continue_block = BundleContinue(statement);
+HBasicBlock* HGraphBuilder::JoinContinue(IterationStatement* statement,
+                                         HBasicBlock* exit_block,
+                                         HBasicBlock* continue_block) {
   if (continue_block != NULL) {
-    exit_block_ = JoinBlocks(exit_block(),
-                             continue_block,
-                             statement->ContinueId());
+    if (exit_block != NULL) exit_block->Goto(continue_block);
+    continue_block->SetJoinId(statement->ContinueId());
+    return continue_block;
   }
+  return exit_block;
 }
 
 
-HBasicBlock* HSubgraph::BundleBreak(BreakableStatement* statement) {
-  return BundleBreakContinue(statement, false, statement->ExitId());
-}
-
-
-HBasicBlock* HSubgraph::BundleContinue(IterationStatement* statement) {
-  return BundleBreakContinue(statement, true, statement->ContinueId());
-}
-
-
-HBasicBlock* HSubgraph::BundleBreakContinue(BreakableStatement* statement,
-                                            bool is_continue,
-                                            int join_id) {
-  HBasicBlock* result = NULL;
-  const ZoneList<BreakContinueInfo*>* infos = break_continue_info();
-  for (int i = 0; i < infos->length(); ++i) {
-    BreakContinueInfo* info = infos->at(i);
-    if (info->is_continue() == is_continue &&
-        info->target() == statement &&
-        !info->IsResolved()) {
-      if (result == NULL) {
-        result = graph_->CreateBasicBlock();
-      }
-      info->block()->Goto(result);
-      info->Resolve();
-    }
+HBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement,
+                                       HBasicBlock* loop_entry,
+                                       HBasicBlock* body_exit,
+                                       HBasicBlock* loop_successor,
+                                       HBasicBlock* break_block) {
+  if (body_exit != NULL) body_exit->Goto(loop_entry, true);
+  loop_entry->PostProcessLoopHeader(statement);
+  if (break_block != NULL) {
+    if (loop_successor != NULL) loop_successor->Goto(break_block);
+    break_block->SetJoinId(statement->ExitId());
+    return break_block;
   }
-
-  if (result != NULL) result->SetJoinId(join_id);
-
-  return result;
+  return loop_successor;
 }
 
 
-HBasicBlock* HSubgraph::JoinBlocks(HBasicBlock* a, HBasicBlock* b, int id) {
-  if (a == NULL) return b;
-  if (b == NULL) return a;
-  HBasicBlock* target = graph_->CreateBasicBlock();
-  a->Goto(target);
-  b->Goto(target);
-  target->SetJoinId(id);
-  return target;
-}
-
-
-void HSubgraph::AppendEndless(HSubgraph* body, IterationStatement* statement) {
-  ConnectExitTo(body->entry_block());
-  body->ResolveContinue(statement);
-  body->ConnectExitTo(body->entry_block(), true);
-  exit_block_ = body->BundleBreak(statement);
-  body->entry_block()->PostProcessLoopHeader(statement);
-}
-
-
-void HSubgraph::AppendDoWhile(HSubgraph* body,
-                              IterationStatement* statement,
-                              HSubgraph* go_back,
-                              HSubgraph* exit) {
-  ConnectExitTo(body->entry_block());
-  go_back->ConnectExitTo(body->entry_block(), true);
-
-  HBasicBlock* break_block = body->BundleBreak(statement);
-  exit_block_ =
-      JoinBlocks(exit->exit_block(), break_block, statement->ExitId());
-  body->entry_block()->PostProcessLoopHeader(statement);
-}
-
-
-void HSubgraph::AppendWhile(HSubgraph* condition,
-                            HSubgraph* body,
-                            IterationStatement* statement,
-                            HSubgraph* continue_subgraph,
-                            HSubgraph* exit) {
-  ConnectExitTo(condition->entry_block());
-
-  HBasicBlock* break_block = body->BundleBreak(statement);
-  exit_block_ =
-      JoinBlocks(exit->exit_block(), break_block, statement->ExitId());
-
-  if (continue_subgraph != NULL) {
-    body->ConnectExitTo(continue_subgraph->entry_block(), true);
-    continue_subgraph->entry_block()->SetJoinId(statement->EntryId());
-    exit_block_ = JoinBlocks(exit_block_,
-                             continue_subgraph->exit_block(),
-                             statement->ExitId());
-  } else {
-    body->ConnectExitTo(condition->entry_block(), true);
-  }
-  condition->entry_block()->PostProcessLoopHeader(statement);
-}
-
-
-void HSubgraph::Append(HSubgraph* next, BreakableStatement* stmt) {
-  exit_block_->Goto(next->entry_block());
-  exit_block_ = next->exit_block_;
-
-  if (stmt != NULL) {
-    next->entry_block()->SetJoinId(stmt->EntryId());
-    HBasicBlock* break_block = next->BundleBreak(stmt);
-    exit_block_ = JoinBlocks(exit_block(), break_block, stmt->ExitId());
-  }
-}
-
-
-void HSubgraph::FinishExit(HControlInstruction* instruction) {
-  ASSERT(HasExit());
-  exit_block_->Finish(instruction);
-  exit_block_->ClearEnvironment();
-  exit_block_ = NULL;
-}
-
-
-void HSubgraph::FinishBreakContinue(BreakableStatement* target,
-                                    bool is_continue) {
-  ASSERT(!exit_block_->IsFinished());
-  BreakContinueInfo* info = new BreakContinueInfo(target, exit_block_,
-                                                  is_continue);
-  break_continue_info_.Add(info);
-  exit_block_ = NULL;
+void HBasicBlock::FinishExit(HControlInstruction* instruction) {
+  Finish(instruction);
+  ClearEnvironment();
 }
 
 
 HGraph::HGraph(CompilationInfo* info)
     : HSubgraph(this),
       next_block_id_(0),
-      info_(info),
       blocks_(8),
       values_(16),
       phi_list_(NULL) {
@@ -671,12 +544,7 @@
 }
 
 
-bool HGraph::AllowCodeMotion() const {
-  return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount;
-}
-
-
-Handle<Code> HGraph::Compile() {
+Handle<Code> HGraph::Compile(CompilationInfo* info) {
   int values = GetMaximumValueID();
   if (values > LAllocator::max_initial_value_ids()) {
     if (FLAG_trace_bailout) PrintF("Function is too big\n");
@@ -684,7 +552,7 @@
   }
 
   LAllocator allocator(values, this);
-  LChunkBuilder builder(this, &allocator);
+  LChunkBuilder builder(info, this, &allocator);
   LChunk* chunk = builder.Build();
   if (chunk == NULL) return Handle<Code>::null();
 
@@ -695,7 +563,7 @@
   if (!FLAG_use_lithium) return Handle<Code>::null();
 
   MacroAssembler assembler(NULL, 0);
-  LCodeGen generator(chunk, &assembler, info());
+  LCodeGen generator(chunk, &assembler, info);
 
   if (FLAG_eliminate_empty_blocks) {
     chunk->MarkEmptyBlocks();
@@ -705,13 +573,13 @@
     if (FLAG_trace_codegen) {
       PrintF("Crankshaft Compiler - ");
     }
-    CodeGenerator::MakeCodePrologue(info());
+    CodeGenerator::MakeCodePrologue(info);
     Code::Flags flags =
         Code::ComputeFlags(Code::OPTIMIZED_FUNCTION, NOT_IN_LOOP);
     Handle<Code> code =
-        CodeGenerator::MakeCodeEpilogue(&assembler, flags, info());
+        CodeGenerator::MakeCodeEpilogue(&assembler, flags, info);
     generator.FinishCode(code);
-    CodeGenerator::PrintCode(code, info());
+    CodeGenerator::PrintCode(code, info);
     return code;
   }
   return Handle<Code>::null();
@@ -726,20 +594,14 @@
 
 
 void HGraph::Canonicalize() {
+  if (!FLAG_use_canonicalizing) return;
   HPhase phase("Canonicalize", this);
-  if (FLAG_use_canonicalizing) {
-    for (int i = 0; i < blocks()->length(); ++i) {
-      HBasicBlock* b = blocks()->at(i);
-      for (HInstruction* insn = b->first(); insn != NULL; insn = insn->next()) {
-        HValue* value = insn->Canonicalize();
-        if (value != insn) {
-          if (value != NULL) {
-            insn->ReplaceAndDelete(value);
-          } else {
-            insn->Delete();
-          }
-        }
-      }
+  for (int i = 0; i < blocks()->length(); ++i) {
+    HInstruction* instr = blocks()->at(i)->first();
+    while (instr != NULL) {
+      HValue* value = instr->Canonicalize();
+      if (value != instr) instr->ReplaceAndDelete(value);
+      instr = instr->next();
     }
   }
 }
@@ -999,8 +861,8 @@
 void HRangeAnalysis::InferControlFlowRange(Token::Value op,
                                            HValue* value,
                                            HValue* other) {
-  Range* range = other->range();
-  if (range == NULL) range = new Range();
+  Range temp_range;
+  Range* range = other->range() != NULL ? other->range() : &temp_range;
   Range* new_range = NULL;
 
   TraceRange("Control flow range infer %d %s %d\n",
@@ -1308,8 +1170,9 @@
 
 class HGlobalValueNumberer BASE_EMBEDDED {
  public:
-  explicit HGlobalValueNumberer(HGraph* graph)
+  explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info)
       : graph_(graph),
+        info_(info),
         block_side_effects_(graph_->blocks()->length()),
         loop_side_effects_(graph_->blocks()->length()) {
     ASSERT(Heap::allow_allocation(false));
@@ -1329,9 +1192,14 @@
   void ProcessLoopBlock(HBasicBlock* block,
                         HBasicBlock* before_loop,
                         int loop_kills);
+  bool AllowCodeMotion();
   bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);
 
+  HGraph* graph() { return graph_; }
+  CompilationInfo* info() { return info_; }
+
   HGraph* graph_;
+  CompilationInfo* info_;
 
   // A map of block IDs to their side effects.
   ZoneList<int> block_side_effects_;
@@ -1432,10 +1300,15 @@
 }
 
 
+bool HGlobalValueNumberer::AllowCodeMotion() {
+  return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount;
+}
+
+
 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
                                       HBasicBlock* loop_header) {
   // If we've disabled code motion, don't move any instructions.
-  if (!graph_->AllowCodeMotion()) return false;
+  if (!AllowCodeMotion()) return false;
 
   // If --aggressive-loop-invariant-motion, move everything except change
   // instructions.
@@ -1495,8 +1368,7 @@
                  instr->Mnemonic(),
                  other->id(),
                  other->Mnemonic());
-        instr->ReplaceValue(other);
-        instr->Delete();
+        instr->ReplaceAndDelete(other);
       } else {
         map->Add(instr);
       }
@@ -1796,8 +1668,7 @@
 
 void HGraph::InsertRepresentationChangeForUse(HValue* value,
                                               HValue* use,
-                                              Representation to,
-                                              bool is_truncating) {
+                                              Representation to) {
   // Insert the representation change right before its use. For phi-uses we
   // insert at the end of the corresponding predecessor.
   HInstruction* next = NULL;
@@ -1814,6 +1685,7 @@
   // information we treat constants like normal instructions and insert the
   // change instructions for them.
   HInstruction* new_value = NULL;
+  bool is_truncating = use->CheckFlag(HValue::kTruncatingToInt32);
   if (value->IsConstant()) {
     HConstant* constant = HConstant::cast(value);
     // Try to create a new copy of the constant with the new representation.
@@ -1823,7 +1695,7 @@
   }
 
   if (new_value == NULL) {
-    new_value = new HChange(value, value->representation(), to);
+    new_value = new HChange(value, value->representation(), to, is_truncating);
   }
 
   new_value->InsertBefore(next);
@@ -1898,8 +1770,7 @@
   for (int i = 0; i < to_convert.length(); ++i) {
     HValue* use = to_convert[i];
     Representation r_to = to_convert_reps[i];
-    bool is_truncating = use->CheckFlag(HValue::kTruncatingToInt32);
-    InsertRepresentationChangeForUse(current, use, r_to, is_truncating);
+    InsertRepresentationChangeForUse(current, use, r_to);
   }
 
   if (current->uses()->is_empty()) {
@@ -1982,6 +1853,47 @@
 }
 
 
+// Implementation of utility class to encapsulate the translation state for
+// a (possibly inlined) function.
+FunctionState::FunctionState(HGraphBuilder* owner,
+                             CompilationInfo* info,
+                             TypeFeedbackOracle* oracle)
+    : owner_(owner),
+      compilation_info_(info),
+      oracle_(oracle),
+      call_context_(NULL),
+      function_return_(NULL),
+      test_context_(NULL),
+      outer_(owner->function_state()) {
+  if (outer_ != NULL) {
+    // State for an inline function.
+    if (owner->ast_context()->IsTest()) {
+      HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
+      HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
+      if_true->MarkAsInlineReturnTarget();
+      if_false->MarkAsInlineReturnTarget();
+      // The AstContext constructor pushed on the context stack.  This newed
+      // instance is the reason that AstContext can't be BASE_EMBEDDED.
+      test_context_ = new TestContext(owner, if_true, if_false);
+    } else {
+      function_return_ = owner->graph()->CreateBasicBlock();
+      function_return()->MarkAsInlineReturnTarget();
+    }
+    // Set this after possibly allocating a new TestContext above.
+    call_context_ = owner->ast_context();
+  }
+
+  // Push on the state stack.
+  owner->set_function_state(this);
+}
+
+
+FunctionState::~FunctionState() {
+  delete test_context_;
+  owner_->set_function_state(outer_);
+}
+
+
 // Implementation of utility classes to represent an expression's context in
 // the AST.
 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
@@ -2000,14 +1912,14 @@
 
 EffectContext::~EffectContext() {
   ASSERT(owner()->HasStackOverflow() ||
-         !owner()->subgraph()->HasExit() ||
+         owner()->current_block() == NULL ||
          owner()->environment()->length() == original_length_);
 }
 
 
 ValueContext::~ValueContext() {
   ASSERT(owner()->HasStackOverflow() ||
-         !owner()->subgraph()->HasExit() ||
+         owner()->current_block() == NULL ||
          owner()->environment()->length() == original_length_ + 1);
 }
 
@@ -2065,7 +1977,7 @@
   HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
   HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
   HTest* test = new HTest(value, empty_true, empty_false);
-  builder->CurrentBlock()->Finish(test);
+  builder->current_block()->Finish(test);
 
   HValue* const no_return_value = NULL;
   HBasicBlock* true_target = if_true();
@@ -2081,7 +1993,7 @@
   } else {
     empty_false->Goto(false_target);
   }
-  builder->subgraph()->set_exit_block(NULL);
+  builder->set_current_block(NULL);
 }
 
 
@@ -2138,7 +2050,6 @@
   }
 
   ~SubgraphScope() {
-    old_subgraph_->AddBreakContinueInfo(subgraph_);
     builder_->current_subgraph_ = old_subgraph_;
   }
 
@@ -2153,8 +2064,8 @@
 
 void HGraphBuilder::Bailout(const char* reason) {
   if (FLAG_trace_bailout) {
-    SmartPointer<char> debug_name = graph()->debug_name()->ToCString();
-    PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *debug_name, reason);
+    SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
+    PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *name, reason);
   }
   SetStackOverflow();
 }
@@ -2181,78 +2092,107 @@
 
 
 void HGraphBuilder::VisitArgument(Expression* expr) {
-  VisitForValue(expr);
+  VISIT_FOR_VALUE(expr);
+  Push(AddInstruction(new HPushArgument(Pop())));
 }
 
 
 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) {
   for (int i = 0; i < arguments->length(); i++) {
     VisitArgument(arguments->at(i));
-    if (HasStackOverflow() || !current_subgraph_->HasExit()) return;
+    if (HasStackOverflow() || current_block() == NULL) return;
   }
 }
 
 
-HGraph* HGraphBuilder::CreateGraph(CompilationInfo* info) {
-  ASSERT(current_subgraph_ == NULL);
-  graph_ = new HGraph(info);
+void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) {
+  for (int i = 0; i < exprs->length(); ++i) {
+    VISIT_FOR_VALUE(exprs->at(i));
+  }
+}
+
+
+HGraph* HGraphBuilder::CreateGraph() {
+  ASSERT(subgraph() == NULL);
+  graph_ = new HGraph(info());
 
   {
     HPhase phase("Block building");
-    graph_->Initialize(CreateBasicBlock(graph_->start_environment()));
-    current_subgraph_ = graph_;
+    graph()->Initialize(CreateBasicBlock(graph()->start_environment()));
+    current_subgraph_ = graph();
 
-    Scope* scope = info->scope();
+    Scope* scope = info()->scope();
+    if (scope->HasIllegalRedeclaration()) {
+      Bailout("function with illegal redeclaration");
+      return NULL;
+    }
     SetupScope(scope);
     VisitDeclarations(scope->declarations());
-
     AddInstruction(new HStackCheck());
 
-    ZoneList<Statement*>* stmts = info->function()->body();
-    HSubgraph* body = CreateGotoSubgraph(environment());
-    AddToSubgraph(body, stmts);
+    // Add an edge to the body entry.  This is warty: the graph's start
+    // environment will be used by the Lithium translation as the initial
+    // environment on graph entry, but it has now been mutated by the
+    // Hydrogen translation of the instructions in the start block.  This
+    // environment uses values which have not been defined yet.  These
+    // Hydrogen instructions will then be replayed by the Lithium
+    // translation, so they cannot have an environment effect.  The edge to
+    // the body's entry block (along with some special logic for the start
+    // block in HInstruction::InsertAfter) seals the start block from
+    // getting unwanted instructions inserted.
+    //
+    // TODO(kmillikin): Fix this.  Stop mutating the initial environment.
+    // Make the Hydrogen instructions in the initial block into Hydrogen
+    // values (but not instructions), present in the initial environment and
+    // not replayed by the Lithium translation.
+    HEnvironment* initial_env = environment()->CopyWithoutHistory();
+    HBasicBlock* body_entry = CreateBasicBlock(initial_env);
+    current_block()->Goto(body_entry);
+    body_entry->SetJoinId(info()->function()->id());
+    set_current_block(body_entry);
+    VisitStatements(info()->function()->body());
     if (HasStackOverflow()) return NULL;
-    current_subgraph_->Append(body, NULL);
-    body->entry_block()->SetJoinId(info->function()->id());
 
-    if (graph_->HasExit()) {
-      graph_->FinishExit(new HReturn(graph_->GetConstantUndefined()));
+    if (current_block() != NULL) {
+      HReturn* instr = new HReturn(graph()->GetConstantUndefined());
+      current_block()->FinishExit(instr);
+      set_current_block(NULL);
     }
   }
 
-  graph_->OrderBlocks();
-  graph_->AssignDominators();
-  graph_->EliminateRedundantPhis();
-  if (!graph_->CollectPhis()) {
+  graph()->OrderBlocks();
+  graph()->AssignDominators();
+  graph()->EliminateRedundantPhis();
+  if (!graph()->CollectPhis()) {
     Bailout("Phi-use of arguments object");
     return NULL;
   }
 
-  HInferRepresentation rep(graph_);
+  HInferRepresentation rep(graph());
   rep.Analyze();
 
   if (FLAG_use_range) {
-    HRangeAnalysis rangeAnalysis(graph_);
+    HRangeAnalysis rangeAnalysis(graph());
     rangeAnalysis.Analyze();
   }
 
-  graph_->InitializeInferredTypes();
-  graph_->Canonicalize();
-  graph_->InsertRepresentationChanges();
-  graph_->ComputeMinusZeroChecks();
+  graph()->InitializeInferredTypes();
+  graph()->Canonicalize();
+  graph()->InsertRepresentationChanges();
+  graph()->ComputeMinusZeroChecks();
 
   // Eliminate redundant stack checks on backwards branches.
-  HStackCheckEliminator sce(graph_);
+  HStackCheckEliminator sce(graph());
   sce.Process();
 
   // Perform common subexpression elimination and loop-invariant code motion.
   if (FLAG_use_gvn) {
-    HPhase phase("Global value numbering", graph_);
-    HGlobalValueNumberer gvn(graph_);
+    HPhase phase("Global value numbering", graph());
+    HGlobalValueNumberer gvn(graph(), info());
     gvn.Analyze();
   }
 
-  return graph_;
+  return graph();
 }
 
 
@@ -2276,21 +2216,21 @@
 
 
 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
-  ASSERT(current_subgraph_->HasExit());
-  current_subgraph_->exit_block()->AddInstruction(instr);
+  ASSERT(current_block() != NULL);
+  current_block()->AddInstruction(instr);
   return instr;
 }
 
 
 void HGraphBuilder::AddSimulate(int id) {
-  ASSERT(current_subgraph_->HasExit());
-  current_subgraph_->exit_block()->AddSimulate(id);
+  ASSERT(current_block() != NULL);
+  current_block()->AddSimulate(id);
 }
 
 
 void HGraphBuilder::AddPhi(HPhi* instr) {
-  ASSERT(current_subgraph_->HasExit());
-  current_subgraph_->exit_block()->AddPhi(instr);
+  ASSERT(current_block() != NULL);
+  current_block()->AddPhi(instr);
 }
 
 
@@ -2300,7 +2240,8 @@
 }
 
 
-void HGraphBuilder::PreProcessCall(HCall* call) {
+template <int V>
+HInstruction* HGraphBuilder::PreProcessCall(HCall<V>* call) {
   int count = call->argument_count();
   ZoneList<HValue*> arguments(count);
   for (int i = 0; i < count; ++i) {
@@ -2310,6 +2251,7 @@
   while (!arguments.is_empty()) {
     AddInstruction(new HPushArgument(arguments.RemoveLast()));
   }
+  return call;
 }
 
 
@@ -2317,9 +2259,6 @@
   // We don't yet handle the function name for named function expressions.
   if (scope->function() != NULL) BAILOUT("named function expression");
 
-  // We can't handle heap-allocated locals.
-  if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals");
-
   HConstant* undefined_constant =
       new HConstant(Factory::undefined_value(), Representation::Tagged());
   AddInstruction(undefined_constant);
@@ -2341,6 +2280,10 @@
   // Handle the arguments and arguments shadow variables specially (they do
   // not have declarations).
   if (scope->arguments() != NULL) {
+    if (!scope->arguments()->IsStackAllocated() ||
+        !scope->arguments_shadow()->IsStackAllocated()) {
+      BAILOUT("context-allocated arguments");
+    }
     HArgumentsObject* object = new HArgumentsObject;
     AddInstruction(object);
     graph()->SetArgumentsObject(object);
@@ -2353,7 +2296,7 @@
 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
   for (int i = 0; i < statements->length(); i++) {
     Visit(statements->at(i));
-    if (HasStackOverflow() || !current_subgraph_->HasExit()) break;
+    if (HasStackOverflow() || current_block() == NULL) break;
   }
 }
 
@@ -2377,14 +2320,6 @@
 }
 
 
-HSubgraph* HGraphBuilder::CreateGotoSubgraph(HEnvironment* env) {
-  HSubgraph* subgraph = new HSubgraph(graph());
-  HEnvironment* new_env = env->CopyWithoutHistory();
-  subgraph->Initialize(CreateBasicBlock(new_env));
-  return subgraph;
-}
-
-
 HSubgraph* HGraphBuilder::CreateEmptySubgraph() {
   HSubgraph* subgraph = new HSubgraph(graph());
   subgraph->Initialize(graph()->CreateBasicBlock());
@@ -2400,24 +2335,26 @@
 }
 
 
-HSubgraph* HGraphBuilder::CreateLoopHeaderSubgraph(HEnvironment* env) {
-  HSubgraph* subgraph = new HSubgraph(graph());
-  HBasicBlock* block = graph()->CreateBasicBlock();
-  HEnvironment* new_env = env->CopyAsLoopHeader(block);
-  block->SetInitialEnvironment(new_env);
-  subgraph->Initialize(block);
-  subgraph->entry_block()->AttachLoopInformation();
-  return subgraph;
+HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
+  HBasicBlock* header = graph()->CreateBasicBlock();
+  HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
+  header->SetInitialEnvironment(entry_env);
+  header->AttachLoopInformation();
+  return header;
 }
 
 
 void HGraphBuilder::VisitBlock(Block* stmt) {
-  if (stmt->labels() != NULL) {
-    HSubgraph* block_graph = CreateGotoSubgraph(environment());
-    ADD_TO_SUBGRAPH(block_graph, stmt->statements());
-    current_subgraph_->Append(block_graph, stmt);
-  } else {
+  BreakAndContinueInfo break_info(stmt);
+  { BreakAndContinueScope push(&break_info, this);
     VisitStatements(stmt->statements());
+    CHECK_BAILOUT;
+  }
+  HBasicBlock* break_block = break_info.break_block();
+  if (break_block != NULL) {
+    if (current_block() != NULL) current_block()->Goto(break_block);
+    break_block->SetJoinId(stmt->ExitId());
+    set_current_block(break_block);
   }
 }
 
@@ -2439,30 +2376,69 @@
     AddSimulate(stmt->ElseId());
     Visit(stmt->else_statement());
   } else {
-    HSubgraph* then_graph = CreateEmptySubgraph();
-    HSubgraph* else_graph = CreateEmptySubgraph();
-    VISIT_FOR_CONTROL(stmt->condition(),
-                      then_graph->entry_block(),
-                      else_graph->entry_block());
+    HBasicBlock* cond_true = graph()->CreateBasicBlock();
+    HBasicBlock* cond_false = graph()->CreateBasicBlock();
+    VISIT_FOR_CONTROL(stmt->condition(), cond_true, cond_false);
+    cond_true->SetJoinId(stmt->ThenId());
+    cond_false->SetJoinId(stmt->ElseId());
 
-    then_graph->entry_block()->SetJoinId(stmt->ThenId());
-    ADD_TO_SUBGRAPH(then_graph, stmt->then_statement());
+    set_current_block(cond_true);
+    Visit(stmt->then_statement());
+    CHECK_BAILOUT;
+    HBasicBlock* other = current_block();
 
-    else_graph->entry_block()->SetJoinId(stmt->ElseId());
-    ADD_TO_SUBGRAPH(else_graph, stmt->else_statement());
+    set_current_block(cond_false);
+    Visit(stmt->else_statement());
+    CHECK_BAILOUT;
 
-    current_subgraph_->AppendJoin(then_graph, else_graph, stmt);
+    HBasicBlock* join = CreateJoin(other, current_block(), stmt->id());
+    set_current_block(join);
   }
 }
 
 
+HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get(
+    BreakableStatement* stmt,
+    BreakType type) {
+  BreakAndContinueScope* current = this;
+  while (current != NULL && current->info()->target() != stmt) {
+    current = current->next();
+  }
+  ASSERT(current != NULL);  // Always found (unless stack is malformed).
+  HBasicBlock* block = NULL;
+  switch (type) {
+    case BREAK:
+      block = current->info()->break_block();
+      if (block == NULL) {
+        block = current->owner()->graph()->CreateBasicBlock();
+        current->info()->set_break_block(block);
+      }
+      break;
+
+    case CONTINUE:
+      block = current->info()->continue_block();
+      if (block == NULL) {
+        block = current->owner()->graph()->CreateBasicBlock();
+        current->info()->set_continue_block(block);
+      }
+      break;
+  }
+
+  return block;
+}
+
+
 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
-  current_subgraph_->FinishBreakContinue(stmt->target(), true);
+  HBasicBlock* continue_block = break_scope()->Get(stmt->target(), CONTINUE);
+  current_block()->Goto(continue_block);
+  set_current_block(NULL);
 }
 
 
 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
-  current_subgraph_->FinishBreakContinue(stmt->target(), false);
+  HBasicBlock* break_block = break_scope()->Get(stmt->target(), BREAK);
+  current_block()->Goto(break_block);
+  set_current_block(NULL);
 }
 
 
@@ -2472,7 +2448,8 @@
     // Not an inlined return, so an actual one.
     VISIT_FOR_VALUE(stmt->expression());
     HValue* result = environment()->Pop();
-    subgraph()->FinishExit(new HReturn(result));
+    current_block()->FinishExit(new HReturn(result));
+    set_current_block(NULL);
   } else {
     // Return from an inlined function, visit the subexpression in the
     // expression context of the call.
@@ -2491,9 +2468,9 @@
         VISIT_FOR_VALUE(stmt->expression());
         return_value = environment()->Pop();
       }
-      subgraph()->exit_block()->AddLeaveInlined(return_value,
-                                                function_return_);
-      subgraph()->set_exit_block(NULL);
+      current_block()->AddLeaveInlined(return_value,
+                                       function_return());
+      set_current_block(NULL);
     }
   }
 }
@@ -2514,7 +2491,7 @@
                                             CaseClause* clause) {
   AddToSubgraph(subgraph, clause->label());
   if (HasStackOverflow()) return NULL;
-  HValue* clause_value = subgraph->environment()->Pop();
+  HValue* clause_value = subgraph->exit_block()->last_environment()->Pop();
   HCompare* compare = new HCompare(switch_value,
                                    clause_value,
                                    Token::EQ_STRICT);
@@ -2595,7 +2572,7 @@
   // last_false_block is the (empty) false-block of the last comparison. If
   // there are no comparisons at all (a single default clause), it is just
   // the last block of the current subgraph.
-  HBasicBlock* last_false_block = current_subgraph_->exit_block();
+  HBasicBlock* last_false_block = current_block();
   if (prev_graph != current_subgraph_) {
     last_false_block = graph()->CreateBasicBlock();
     HBasicBlock* empty = graph()->CreateBasicBlock();
@@ -2638,17 +2615,20 @@
     }
 
     // Check for fall-through from previous statement block.
-    if (previous_subgraph != NULL && previous_subgraph->HasExit()) {
+    if (previous_subgraph != NULL && previous_subgraph->exit_block() != NULL) {
       if (subgraph == NULL) subgraph = CreateEmptySubgraph();
       previous_subgraph->exit_block()->
           Finish(new HGoto(subgraph->entry_block()));
     }
 
     if (subgraph != NULL) {
-      ADD_TO_SUBGRAPH(subgraph, clause->statements());
-      HBasicBlock* break_block = subgraph->BundleBreak(stmt);
-      if (break_block != NULL) {
-        break_block->Finish(new HGoto(single_exit_block));
+      BreakAndContinueInfo break_info(stmt);
+      { BreakAndContinueScope push(&break_info, this);
+        ADD_TO_SUBGRAPH(subgraph, clause->statements());
+      }
+      if (break_info.break_block() != NULL) {
+        break_info.break_block()->SetJoinId(stmt->ExitId());
+        break_info.break_block()->Finish(new HGoto(single_exit_block));
       }
     }
 
@@ -2657,7 +2637,7 @@
 
   // If the last statement block has a fall-through, connect it to the
   // single exit block.
-  if (previous_subgraph != NULL && previous_subgraph->HasExit()) {
+  if (previous_subgraph != NULL && previous_subgraph->exit_block() != NULL) {
     previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block));
   }
 
@@ -2667,181 +2647,160 @@
   }
 
   if (single_exit_block->HasPredecessor()) {
-    current_subgraph_->set_exit_block(single_exit_block);
+    set_current_block(single_exit_block);
   } else {
-    current_subgraph_->set_exit_block(NULL);
+    set_current_block(NULL);
   }
 }
 
-bool HGraph::HasOsrEntryAt(IterationStatement* statement) {
+bool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
   return statement->OsrEntryId() == info()->osr_ast_id();
 }
 
 
-void HSubgraph::PreProcessOsrEntry(IterationStatement* statement) {
-  if (!graph()->HasOsrEntryAt(statement)) return;
+void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
+  if (!HasOsrEntryAt(statement)) return;
 
   HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
   HBasicBlock* osr_entry = graph()->CreateBasicBlock();
   HValue* true_value = graph()->GetConstantTrue();
   HTest* test = new HTest(true_value, non_osr_entry, osr_entry);
-  exit_block()->Finish(test);
+  current_block()->Finish(test);
 
   HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
   non_osr_entry->Goto(loop_predecessor);
 
+  set_current_block(osr_entry);
   int osr_entry_id = statement->OsrEntryId();
   // We want the correct environment at the OsrEntry instruction.  Build
   // it explicitly.  The expression stack should be empty.
-  int count = osr_entry->last_environment()->length();
-  ASSERT(count == (osr_entry->last_environment()->parameter_count() +
-                   osr_entry->last_environment()->local_count()));
+  int count = environment()->length();
+  ASSERT(count ==
+         (environment()->parameter_count() + environment()->local_count()));
   for (int i = 0; i < count; ++i) {
     HUnknownOSRValue* unknown = new HUnknownOSRValue;
-    osr_entry->AddInstruction(unknown);
-    osr_entry->last_environment()->Bind(i, unknown);
+    AddInstruction(unknown);
+    environment()->Bind(i, unknown);
   }
 
-  osr_entry->AddSimulate(osr_entry_id);
-  osr_entry->AddInstruction(new HOsrEntry(osr_entry_id));
-  osr_entry->Goto(loop_predecessor);
+  AddSimulate(osr_entry_id);
+  AddInstruction(new HOsrEntry(osr_entry_id));
+  current_block()->Goto(loop_predecessor);
   loop_predecessor->SetJoinId(statement->EntryId());
-  set_exit_block(loop_predecessor);
+  set_current_block(loop_predecessor);
 }
 
 
 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
-  ASSERT(subgraph()->HasExit());
-  subgraph()->PreProcessOsrEntry(stmt);
+  ASSERT(current_block() != NULL);
+  PreProcessOsrEntry(stmt);
+  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
+  current_block()->Goto(loop_entry, false);
+  set_current_block(loop_entry);
 
-  HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment());
-  ADD_TO_SUBGRAPH(body_graph, stmt->body());
-  body_graph->ResolveContinue(stmt);
-
-  if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) {
-    current_subgraph_->AppendEndless(body_graph, stmt);
-  } else {
-    HSubgraph* go_back = CreateEmptySubgraph();
-    HSubgraph* exit = CreateEmptySubgraph();
-    {
-      SubgraphScope scope(this, body_graph);
-      VISIT_FOR_CONTROL(stmt->cond(),
-                        go_back->entry_block(),
-                        exit->entry_block());
-      go_back->entry_block()->SetJoinId(stmt->BackEdgeId());
-      exit->entry_block()->SetJoinId(stmt->ExitId());
-    }
-    current_subgraph_->AppendDoWhile(body_graph, stmt, go_back, exit);
+  BreakAndContinueInfo break_info(stmt);
+  { BreakAndContinueScope push(&break_info, this);
+    Visit(stmt->body());
+    CHECK_BAILOUT;
   }
-}
-
-
-bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) {
-  return FLAG_use_peeling;
+  HBasicBlock* body_exit =
+      JoinContinue(stmt, current_block(), break_info.continue_block());
+  HBasicBlock* loop_successor = NULL;
+  if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
+    set_current_block(body_exit);
+    // The block for a true condition, the actual predecessor block of the
+    // back edge.
+    body_exit = graph()->CreateBasicBlock();
+    loop_successor = graph()->CreateBasicBlock();
+    VISIT_FOR_CONTROL(stmt->cond(), body_exit, loop_successor);
+    body_exit->SetJoinId(stmt->BackEdgeId());
+    loop_successor->SetJoinId(stmt->ExitId());
+  }
+  HBasicBlock* loop_exit = CreateLoop(stmt,
+                                      loop_entry,
+                                      body_exit,
+                                      loop_successor,
+                                      break_info.break_block());
+  set_current_block(loop_exit);
 }
 
 
 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
-  ASSERT(subgraph()->HasExit());
-  subgraph()->PreProcessOsrEntry(stmt);
+  ASSERT(current_block() != NULL);
+  PreProcessOsrEntry(stmt);
+  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
+  current_block()->Goto(loop_entry, false);
+  set_current_block(loop_entry);
 
-  HSubgraph* cond_graph = NULL;
-  HSubgraph* body_graph = NULL;
-  HSubgraph* exit_graph = NULL;
-
-  // If the condition is constant true, do not generate a condition subgraph.
-  if (stmt->cond()->ToBooleanIsTrue()) {
-    body_graph = CreateLoopHeaderSubgraph(environment());
-    ADD_TO_SUBGRAPH(body_graph, stmt->body());
-  } else {
-    cond_graph = CreateLoopHeaderSubgraph(environment());
-    body_graph = CreateEmptySubgraph();
-    exit_graph = CreateEmptySubgraph();
-    {
-      SubgraphScope scope(this, cond_graph);
-      VISIT_FOR_CONTROL(stmt->cond(),
-                        body_graph->entry_block(),
-                        exit_graph->entry_block());
-      body_graph->entry_block()->SetJoinId(stmt->BodyId());
-      exit_graph->entry_block()->SetJoinId(stmt->ExitId());
-    }
-    ADD_TO_SUBGRAPH(body_graph, stmt->body());
+  // If the condition is constant true, do not generate a branch.
+  HBasicBlock* loop_successor = NULL;
+  if (!stmt->cond()->ToBooleanIsTrue()) {
+    HBasicBlock* body_entry = graph()->CreateBasicBlock();
+    loop_successor = graph()->CreateBasicBlock();
+    VISIT_FOR_CONTROL(stmt->cond(), body_entry, loop_successor);
+    body_entry->SetJoinId(stmt->BodyId());
+    loop_successor->SetJoinId(stmt->ExitId());
+    set_current_block(body_entry);
   }
 
-  body_graph->ResolveContinue(stmt);
-
-  if (cond_graph != NULL) {
-    AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph);
-  } else {
-    // TODO(fschneider): Implement peeling for endless loops as well.
-    current_subgraph_->AppendEndless(body_graph, stmt);
+  BreakAndContinueInfo break_info(stmt);
+  { BreakAndContinueScope push(&break_info, this);
+    Visit(stmt->body());
+    CHECK_BAILOUT;
   }
-}
-
-
-void HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt,
-                                      HSubgraph* cond_graph,
-                                      HSubgraph* body_graph,
-                                      HSubgraph* exit_graph) {
-  HSubgraph* loop = NULL;
-  if (body_graph->HasExit() && stmt != peeled_statement_ &&
-      ShouldPeel(cond_graph, body_graph)) {
-    // Save the last peeled iteration statement to prevent infinite recursion.
-    IterationStatement* outer_peeled_statement = peeled_statement_;
-    peeled_statement_ = stmt;
-    loop = CreateGotoSubgraph(body_graph->environment());
-    ADD_TO_SUBGRAPH(loop, stmt);
-    peeled_statement_ = outer_peeled_statement;
-  }
-  current_subgraph_->AppendWhile(cond_graph, body_graph, stmt, loop,
-                                 exit_graph);
+  HBasicBlock* body_exit =
+      JoinContinue(stmt, current_block(), break_info.continue_block());
+  HBasicBlock* loop_exit = CreateLoop(stmt,
+                                      loop_entry,
+                                      body_exit,
+                                      loop_successor,
+                                      break_info.break_block());
+  set_current_block(loop_exit);
 }
 
 
 void HGraphBuilder::VisitForStatement(ForStatement* stmt) {
-  // Only visit the init statement in the peeled part of the loop.
-  if (stmt->init() != NULL && peeled_statement_ != stmt) {
+  if (stmt->init() != NULL) {
     Visit(stmt->init());
     CHECK_BAILOUT;
   }
-  ASSERT(subgraph()->HasExit());
-  subgraph()->PreProcessOsrEntry(stmt);
+  ASSERT(current_block() != NULL);
+  PreProcessOsrEntry(stmt);
+  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
+  current_block()->Goto(loop_entry, false);
+  set_current_block(loop_entry);
 
-  HSubgraph* cond_graph = NULL;
-  HSubgraph* body_graph = NULL;
-  HSubgraph* exit_graph = NULL;
+  HBasicBlock* loop_successor = NULL;
   if (stmt->cond() != NULL) {
-    cond_graph = CreateLoopHeaderSubgraph(environment());
-    body_graph = CreateEmptySubgraph();
-    exit_graph = CreateEmptySubgraph();
-    {
-      SubgraphScope scope(this, cond_graph);
-      VISIT_FOR_CONTROL(stmt->cond(),
-                        body_graph->entry_block(),
-                        exit_graph->entry_block());
-      body_graph->entry_block()->SetJoinId(stmt->BodyId());
-      exit_graph->entry_block()->SetJoinId(stmt->ExitId());
-    }
-  } else {
-    body_graph = CreateLoopHeaderSubgraph(environment());
-  }
-  ADD_TO_SUBGRAPH(body_graph, stmt->body());
-
-  HSubgraph* next_graph = NULL;
-  body_graph->ResolveContinue(stmt);
-
-  if (stmt->next() != NULL && body_graph->HasExit()) {
-    next_graph = CreateGotoSubgraph(body_graph->environment());
-    ADD_TO_SUBGRAPH(next_graph, stmt->next());
-    body_graph->Append(next_graph, NULL);
-    next_graph->entry_block()->SetJoinId(stmt->ContinueId());
+    HBasicBlock* body_entry = graph()->CreateBasicBlock();
+    loop_successor = graph()->CreateBasicBlock();
+    VISIT_FOR_CONTROL(stmt->cond(), body_entry, loop_successor);
+    body_entry->SetJoinId(stmt->BodyId());
+    loop_successor->SetJoinId(stmt->ExitId());
+    set_current_block(body_entry);
   }
 
-  if (cond_graph != NULL) {
-    AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph);
-  } else {
-    current_subgraph_->AppendEndless(body_graph, stmt);
+  BreakAndContinueInfo break_info(stmt);
+  { BreakAndContinueScope push(&break_info, this);
+    Visit(stmt->body());
+    CHECK_BAILOUT;
   }
+  HBasicBlock* body_exit =
+      JoinContinue(stmt, current_block(), break_info.continue_block());
+
+  if (stmt->next() != NULL && body_exit != NULL) {
+    set_current_block(body_exit);
+    Visit(stmt->next());
+    CHECK_BAILOUT;
+    body_exit = current_block();
+  }
+
+  HBasicBlock* loop_exit = CreateLoop(stmt,
+                                      loop_entry,
+                                      body_exit,
+                                      loop_successor,
+                                      break_info.break_block());
+  set_current_block(loop_exit);
 }
 
 
@@ -2867,7 +2826,7 @@
 
 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
   Handle<SharedFunctionInfo> shared_info =
-      Compiler::BuildFunctionInfo(expr, graph_->info()->script());
+      Compiler::BuildFunctionInfo(expr, info()->script());
   CHECK_BAILOUT;
   HFunctionLiteral* instr =
       new HFunctionLiteral(shared_info, expr->pretenure());
@@ -2882,19 +2841,23 @@
 
 
 void HGraphBuilder::VisitConditional(Conditional* expr) {
-  HSubgraph* then_graph = CreateEmptySubgraph();
-  HSubgraph* else_graph = CreateEmptySubgraph();
-  VISIT_FOR_CONTROL(expr->condition(),
-                    then_graph->entry_block(),
-                    else_graph->entry_block());
+  HBasicBlock* cond_true = graph()->CreateBasicBlock();
+  HBasicBlock* cond_false = graph()->CreateBasicBlock();
+  VISIT_FOR_CONTROL(expr->condition(), cond_true, cond_false);
+  cond_true->SetJoinId(expr->ThenId());
+  cond_false->SetJoinId(expr->ElseId());
 
-  then_graph->entry_block()->SetJoinId(expr->ThenId());
-  ADD_TO_SUBGRAPH(then_graph, expr->then_expression());
+  // TOOD(kmillikin): Visit the subexpressions in the same AST context as
+  // the whole expression.
+  set_current_block(cond_true);
+  VISIT_FOR_VALUE(expr->then_expression());
+  HBasicBlock* other = current_block();
 
-  else_graph->entry_block()->SetJoinId(expr->ElseId());
-  ADD_TO_SUBGRAPH(else_graph, expr->else_expression());
+  set_current_block(cond_false);
+  VISIT_FOR_VALUE(expr->else_expression());
 
-  current_subgraph_->AppendJoin(then_graph, else_graph, expr);
+  HBasicBlock* join = CreateJoin(other, current_block(), expr->id());
+  set_current_block(join);
   ast_context()->ReturnValue(Pop());
 }
 
@@ -2905,10 +2868,10 @@
   if (var->is_this()) {
     BAILOUT("global this reference");
   }
-  if (!graph()->info()->has_global_object()) {
+  if (!info()->has_global_object()) {
     BAILOUT("no global object to optimize VariableProxy");
   }
-  Handle<GlobalObject> global(graph()->info()->global_object());
+  Handle<GlobalObject> global(info()->global_object());
   global->Lookup(*var->name(), lookup);
   if (!lookup->IsProperty()) {
     BAILOUT("global variable cell not yet introduced");
@@ -2929,7 +2892,7 @@
   ASSERT(var->IsContextSlot());
   HInstruction* context = new HContext;
   AddInstruction(context);
-  int length = graph()->info()->scope()->ContextChainLength(var->scope());
+  int length = info()->scope()->ContextChainLength(var->scope());
   while (length-- > 0) {
     context = new HOuterContext(context);
     AddInstruction(context);
@@ -2960,7 +2923,7 @@
     LookupGlobalPropertyCell(variable, &lookup, false);
     CHECK_BAILOUT;
 
-    Handle<GlobalObject> global(graph()->info()->global_object());
+    Handle<GlobalObject> global(info()->global_object());
     // TODO(3039103): Handle global property load through an IC call when access
     // checks are enabled.
     if (global->IsAccessCheckNeeded()) {
@@ -3086,53 +3049,47 @@
 }
 
 
-HBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps,
-                                            ZoneList<HSubgraph*>* subgraphs,
-                                            HValue* receiver,
+HBasicBlock* HGraphBuilder::BuildTypeSwitch(HValue* receiver,
+                                            ZoneMapList* maps,
+                                            ZoneList<HSubgraph*>* body_graphs,
+                                            HSubgraph* default_graph,
                                             int join_id) {
-  ASSERT(subgraphs->length() == (maps->length() + 1));
-
-  // Build map compare subgraphs for all but the first map.
-  ZoneList<HSubgraph*> map_compare_subgraphs(maps->length() - 1);
-  for (int i = maps->length() - 1; i > 0; --i) {
-    HSubgraph* subgraph = CreateBranchSubgraph(environment());
-    SubgraphScope scope(this, subgraph);
-    HSubgraph* else_subgraph =
-        (i == (maps->length() - 1))
-        ? subgraphs->last()
-        : map_compare_subgraphs.last();
-    HCompareMap* compare = new HCompareMap(receiver,
-                                           maps->at(i),
-                                           subgraphs->at(i)->entry_block(),
-                                           else_subgraph->entry_block());
-    current_subgraph_->exit_block()->Finish(compare);
-    map_compare_subgraphs.Add(subgraph);
-  }
-
-  // Generate first map check to end the current block.
+  ASSERT(maps->length() == body_graphs->length());
+  HBasicBlock* join_block = graph()->CreateBasicBlock();
   AddInstruction(new HCheckNonSmi(receiver));
-  HSubgraph* else_subgraph =
-      (maps->length() == 1) ? subgraphs->at(1) : map_compare_subgraphs.last();
-  HCompareMap* compare = new HCompareMap(receiver,
-                                         Handle<Map>(maps->first()),
-                                         subgraphs->first()->entry_block(),
-                                         else_subgraph->entry_block());
-  current_subgraph_->exit_block()->Finish(compare);
 
-  // Join all the call subgraphs in a new basic block and make
-  // this basic block the current basic block.
-  HBasicBlock* join_block = graph_->CreateBasicBlock();
-  for (int i = 0; i < subgraphs->length(); ++i) {
-    HSubgraph* subgraph = subgraphs->at(i);
-    if (subgraph->HasExit()) {
+  for (int i = 0; i < maps->length(); ++i) {
+    // Build the branches, connect all the target subgraphs to the join
+    // block.  Use the default as a target of the last branch.
+    HSubgraph* if_true = body_graphs->at(i);
+    HSubgraph* if_false = (i == maps->length() - 1)
+        ? default_graph
+        : CreateBranchSubgraph(environment());
+    HCompareMap* compare =
+        new HCompareMap(receiver,
+                        maps->at(i),
+                        if_true->entry_block(),
+                        if_false->entry_block());
+    current_block()->Finish(compare);
+
+    if (if_true->exit_block() != NULL) {
       // In an effect context the value of the type switch is not needed.
       // There is no need to merge it at the join block only to discard it.
-      HBasicBlock* subgraph_exit = subgraph->exit_block();
       if (ast_context()->IsEffect()) {
-        subgraph_exit->last_environment()->Drop(1);
+        if_true->exit_block()->last_environment()->Drop(1);
       }
-      subgraph_exit->Goto(join_block);
+      if_true->exit_block()->Goto(join_block);
     }
+
+    set_current_block(if_false->exit_block());
+  }
+
+  // Connect the default if necessary.
+  if (current_block() != NULL) {
+    if (ast_context()->IsEffect()) {
+      environment()->Drop(1);
+    }
+    current_block()->Goto(join_block);
   }
 
   if (join_block->predecessors()->is_empty()) return NULL;
@@ -3236,68 +3193,73 @@
                                                      HValue* value,
                                                      ZoneMapList* types,
                                                      Handle<String> name) {
-  int number_of_types = Min(types->length(), kMaxStorePolymorphism);
-  ZoneMapList maps(number_of_types);
-  ZoneList<HSubgraph*> subgraphs(number_of_types + 1);
-  bool needs_generic = (types->length() > kMaxStorePolymorphism);
-
-  // Build subgraphs for each of the specific maps.
-  //
-  // TODO(ager): We should recognize when the prototype chains for
-  // different maps are identical. In that case we can avoid
-  // repeatedly generating the same prototype map checks.
-  for (int i = 0; i < number_of_types; ++i) {
+  // TODO(ager): We should recognize when the prototype chains for different
+  // maps are identical. In that case we can avoid repeatedly generating the
+  // same prototype map checks.
+  int count = 0;
+  HBasicBlock* join = NULL;
+  for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
     Handle<Map> map = types->at(i);
     LookupResult lookup;
     if (ComputeStoredField(map, name, &lookup)) {
-      maps.Add(map);
-      HSubgraph* subgraph = CreateBranchSubgraph(environment());
-      SubgraphScope scope(this, subgraph);
+      if (count == 0) {
+        AddInstruction(new HCheckNonSmi(object));  // Only needed once.
+        join = graph()->CreateBasicBlock();
+      }
+      ++count;
+      HBasicBlock* if_true = graph()->CreateBasicBlock();
+      HBasicBlock* if_false = graph()->CreateBasicBlock();
+      HCompareMap* compare = new HCompareMap(object, map, if_true, if_false);
+      current_block()->Finish(compare);
+
+      set_current_block(if_true);
       HInstruction* instr =
           BuildStoreNamedField(object, name, value, map, &lookup, false);
-      Push(value);
       instr->set_position(expr->position());
+      // Goto will add the HSimulate for the store.
       AddInstruction(instr);
-      subgraphs.Add(subgraph);
-    } else {
-      needs_generic = true;
+      if (!ast_context()->IsEffect()) Push(value);
+      current_block()->Goto(join);
+
+      set_current_block(if_false);
     }
   }
 
-  // If none of the properties were named fields we generate a
-  // generic store.
-  if (maps.length() == 0) {
+  // Finish up.  Unconditionally deoptimize if we've handled all the maps we
+  // know about and do not want to handle ones we've never seen.  Otherwise
+  // use a generic IC.
+  if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
+    current_block()->FinishExit(new HDeoptimize);
+  } else {
     HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
-    Push(value);
     instr->set_position(expr->position());
     AddInstruction(instr);
-    if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
-    ast_context()->ReturnValue(Pop());
-  } else {
-    // Build subgraph for generic store through IC.
-    {
-      HSubgraph* subgraph = CreateBranchSubgraph(environment());
-      SubgraphScope scope(this, subgraph);
-      if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
-        subgraph->FinishExit(new HDeoptimize());
-      } else {
-        HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
-        Push(value);
-        instr->set_position(expr->position());
-        AddInstruction(instr);
-      }
-      subgraphs.Add(subgraph);
-    }
 
-    HBasicBlock* new_exit_block =
-        BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
-    subgraph()->set_exit_block(new_exit_block);
-    // In an effect context, we did not materialized the value in the
-    // predecessor environments so there's no need to handle it here.
-    if (subgraph()->HasExit() && !ast_context()->IsEffect()) {
-      ast_context()->ReturnValue(Pop());
+    if (join != NULL) {
+      if (!ast_context()->IsEffect()) Push(value);
+      current_block()->Goto(join);
+    } else {
+      // The HSimulate for the store should not see the stored value in
+      // effect contexts (it is not materialized at expr->id() in the
+      // unoptimized code).
+      if (instr->HasSideEffects()) {
+        if (ast_context()->IsEffect()) {
+          AddSimulate(expr->id());
+        } else {
+          Push(value);
+          AddSimulate(expr->id());
+          Drop(1);
+        }
+      }
+      ast_context()->ReturnValue(value);
+      return;
     }
   }
+
+  ASSERT(join != NULL);
+  join->SetJoinId(expr->id());
+  set_current_block(join);
+  if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
 }
 
 
@@ -3342,12 +3304,20 @@
     HValue* key = Pop();
     HValue* object = Pop();
 
-    bool is_fast_elements = expr->IsMonomorphic() &&
-        expr->GetMonomorphicReceiverType()->has_fast_elements();
-
-    instr = is_fast_elements
-        ? BuildStoreKeyedFastElement(object, key, value, expr)
-        : BuildStoreKeyedGeneric(object, key, value);
+    if (expr->IsMonomorphic()) {
+      Handle<Map> receiver_type(expr->GetMonomorphicReceiverType());
+      // An object has either fast elements or pixel array elements, but never
+      // both. Pixel array maps that are assigned to pixel array elements are
+      // always created with the fast elements flag cleared.
+      if (receiver_type->has_pixel_array_elements()) {
+        instr = BuildStoreKeyedPixelArrayElement(object, key, value, expr);
+      } else if (receiver_type->has_fast_elements()) {
+        instr = BuildStoreKeyedFastElement(object, key, value, expr);
+      }
+    }
+    if (instr == NULL) {
+      instr = BuildStoreKeyedGeneric(object, key, value);
+    }
   }
 
   Push(value);
@@ -3370,7 +3340,7 @@
   CHECK_BAILOUT;
 
   bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
-  Handle<GlobalObject> global(graph()->info()->global_object());
+  Handle<GlobalObject> global(info()->global_object());
   Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
   HInstruction* instr = new HStoreGlobal(value, cell, check_hole);
   instr->set_position(position);
@@ -3391,10 +3361,6 @@
   BinaryOperation* operation = expr->binary_operation();
 
   if (var != NULL) {
-    if (!var->is_global() && !var->IsStackAllocated()) {
-      BAILOUT("non-stack/non-global in compound assignment");
-    }
-
     VISIT_FOR_VALUE(operation);
 
     if (var->is_global()) {
@@ -3402,8 +3368,16 @@
                                      Top(),
                                      expr->position(),
                                      expr->AssignmentId());
-    } else {
+    } else if (var->IsStackAllocated()) {
       Bind(var, Top());
+    } else if (var->IsContextSlot()) {
+      HValue* context = BuildContextChainWalk(var);
+      int index = var->AsSlot()->index();
+      HStoreContextSlot* instr = new HStoreContextSlot(context, index, Top());
+      AddInstruction(instr);
+      if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
+    } else {
+      BAILOUT("compound assignment to lookup slot");
     }
     ast_context()->ReturnValue(Pop());
 
@@ -3555,7 +3529,8 @@
   instr->set_position(expr->position());
   AddInstruction(instr);
   AddSimulate(expr->id());
-  current_subgraph_->FinishExit(new HAbnormalExit);
+  current_block()->FinishExit(new HAbnormalExit);
+  set_current_block(NULL);
 }
 
 
@@ -3563,65 +3538,62 @@
                                                     HValue* object,
                                                     ZoneMapList* types,
                                                     Handle<String> name) {
-  int number_of_types = Min(types->length(), kMaxLoadPolymorphism);
-  ZoneMapList maps(number_of_types);
-  ZoneList<HSubgraph*> subgraphs(number_of_types + 1);
-  bool needs_generic = (types->length() > kMaxLoadPolymorphism);
-
-  // Build subgraphs for each of the specific maps.
-  //
-  // TODO(ager): We should recognize when the prototype chains for
-  // different maps are identical. In that case we can avoid
-  // repeatedly generating the same prototype map checks.
-  for (int i = 0; i < number_of_types; ++i) {
+  // TODO(ager): We should recognize when the prototype chains for different
+  // maps are identical. In that case we can avoid repeatedly generating the
+  // same prototype map checks.
+  int count = 0;
+  HBasicBlock* join = NULL;
+  for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
     Handle<Map> map = types->at(i);
     LookupResult lookup;
     map->LookupInDescriptors(NULL, *name, &lookup);
     if (lookup.IsProperty() && lookup.type() == FIELD) {
-      maps.Add(map);
-      HSubgraph* subgraph = CreateBranchSubgraph(environment());
-      SubgraphScope scope(this, subgraph);
+      if (count == 0) {
+        AddInstruction(new HCheckNonSmi(object));  // Only needed once.
+        join = graph()->CreateBasicBlock();
+      }
+      ++count;
+      HBasicBlock* if_true = graph()->CreateBasicBlock();
+      HBasicBlock* if_false = graph()->CreateBasicBlock();
+      HCompareMap* compare = new HCompareMap(object, map, if_true, if_false);
+      current_block()->Finish(compare);
+
+      set_current_block(if_true);
       HLoadNamedField* instr =
           BuildLoadNamedField(object, expr, map, &lookup, false);
       instr->set_position(expr->position());
-      instr->ClearFlag(HValue::kUseGVN);  // Don't do GVN on polymorphic loads.
-      PushAndAdd(instr);
-      subgraphs.Add(subgraph);
-    } else {
-      needs_generic = true;
+      instr->ClearFlag(HValue::kUseGVN);
+      AddInstruction(instr);
+      if (!ast_context()->IsEffect()) Push(instr);
+      current_block()->Goto(join);
+
+      set_current_block(if_false);
     }
   }
 
-  // If none of the properties were named fields we generate a
-  // generic load.
-  if (maps.length() == 0) {
+  // Finish up.  Unconditionally deoptimize if we've handled all the maps we
+  // know about and do not want to handle ones we've never seen.  Otherwise
+  // use a generic IC.
+  if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
+    current_block()->FinishExit(new HDeoptimize);
+  } else {
     HInstruction* instr = BuildLoadNamedGeneric(object, expr);
     instr->set_position(expr->position());
-    ast_context()->ReturnInstruction(instr, expr->id());
-  } else {
-    // Build subgraph for generic load through IC.
-    {
-      HSubgraph* subgraph = CreateBranchSubgraph(environment());
-      SubgraphScope scope(this, subgraph);
-      if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
-        subgraph->FinishExit(new HDeoptimize());
-      } else {
-        HInstruction* instr = BuildLoadNamedGeneric(object, expr);
-        instr->set_position(expr->position());
-        PushAndAdd(instr);
-      }
-      subgraphs.Add(subgraph);
-    }
 
-    HBasicBlock* new_exit_block =
-        BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
-    subgraph()->set_exit_block(new_exit_block);
-    // In an effect context, we did not materialized the value in the
-    // predecessor environments so there's no need to handle it here.
-    if (subgraph()->HasExit() && !ast_context()->IsEffect()) {
-      ast_context()->ReturnValue(Pop());
+    if (join != NULL) {
+      AddInstruction(instr);
+      if (!ast_context()->IsEffect()) Push(instr);
+      current_block()->Goto(join);
+    } else {
+      ast_context()->ReturnInstruction(instr, expr->id());
+      return;
     }
   }
+
+  ASSERT(join != NULL);
+  join->SetJoinId(expr->id());
+  set_current_block(join);
+  if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
 }
 
 
@@ -3725,7 +3697,8 @@
   AddInstruction(new HCheckMap(object, map));
   HLoadElements* elements = new HLoadElements(object);
   AddInstruction(elements);
-  HInstruction* length = AddInstruction(new HPixelArrayLength(elements));
+  HInstruction* length = new HPixelArrayLength(elements);
+  AddInstruction(length);
   AddInstruction(new HBoundsCheck(key, length));
   HLoadPixelArrayExternalPointer* external_elements =
       new HLoadPixelArrayExternalPointer(elements);
@@ -3768,6 +3741,28 @@
 }
 
 
+HInstruction* HGraphBuilder::BuildStoreKeyedPixelArrayElement(
+    HValue* object,
+    HValue* key,
+    HValue* val,
+    Expression* expr) {
+  ASSERT(expr->IsMonomorphic());
+  AddInstruction(new HCheckNonSmi(object));
+  Handle<Map> map = expr->GetMonomorphicReceiverType();
+  ASSERT(!map->has_fast_elements());
+  ASSERT(map->has_pixel_array_elements());
+  AddInstruction(new HCheckMap(object, map));
+  HLoadElements* elements = new HLoadElements(object);
+  AddInstruction(elements);
+  HInstruction* length = AddInstruction(new HPixelArrayLength(elements));
+  AddInstruction(new HBoundsCheck(key, length));
+  HLoadPixelArrayExternalPointer* external_elements =
+      new HLoadPixelArrayExternalPointer(elements);
+  AddInstruction(external_elements);
+  return new HStorePixelArrayElement(external_elements, key, val);
+}
+
+
 bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
   VariableProxy* proxy = expr->obj()->AsVariableProxy();
   if (proxy == NULL) return false;
@@ -3783,9 +3778,11 @@
     HInstruction* elements = AddInstruction(new HArgumentsElements);
     result = new HArgumentsLength(elements);
   } else {
+    Push(graph()->GetArgumentsObject());
     VisitForValue(expr->key());
     if (HasStackOverflow()) return false;
     HValue* key = Pop();
+    Drop(1);  // Arguments object.
     HInstruction* elements = AddInstruction(new HArgumentsElements);
     HInstruction* length = AddInstruction(new HArgumentsLength(elements));
     AddInstruction(new HBoundsCheck(key, length));
@@ -3891,7 +3888,7 @@
   int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
   int number_of_types = Min(types->length(), kMaxCallPolymorphism);
   ZoneMapList maps(number_of_types);
-  ZoneList<HSubgraph*> subgraphs(number_of_types + 1);
+  ZoneList<HSubgraph*> subgraphs(number_of_types);
   bool needs_generic = (types->length() > kMaxCallPolymorphism);
 
   // Build subgraphs for each of the specific maps.
@@ -3902,7 +3899,6 @@
   for (int i = 0; i < number_of_types; ++i) {
     Handle<Map> map = types->at(i);
     if (expr->ComputeTarget(map, name)) {
-      maps.Add(map);
       HSubgraph* subgraph = CreateBranchSubgraph(environment());
       SubgraphScope scope(this, subgraph);
       AddCheckConstantFunction(expr, receiver, map, false);
@@ -3914,11 +3910,13 @@
         // Check for bailout, as trying to inline might fail due to bailout
         // during hydrogen processing.
         CHECK_BAILOUT;
-        HCall* call = new HCallConstantFunction(expr->target(), argument_count);
+        HCallConstantFunction* call =
+          new HCallConstantFunction(expr->target(), argument_count);
         call->set_position(expr->position());
         PreProcessCall(call);
         PushAndAdd(call);
       }
+      maps.Add(map);
       subgraphs.Add(subgraph);
     } else {
       needs_generic = true;
@@ -3930,31 +3928,30 @@
   if (maps.length() == 0) {
     HContext* context = new HContext;
     AddInstruction(context);
-    HCall* call = new HCallNamed(context, name, argument_count);
+    HCallNamed* call = new HCallNamed(context, name, argument_count);
     call->set_position(expr->position());
     PreProcessCall(call);
     ast_context()->ReturnInstruction(call, expr->id());
   } else {
     // Build subgraph for generic call through IC.
-    {
-      HSubgraph* subgraph = CreateBranchSubgraph(environment());
-      SubgraphScope scope(this, subgraph);
+    HSubgraph* default_graph = CreateBranchSubgraph(environment());
+    { SubgraphScope scope(this, default_graph);
       if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
-        subgraph->FinishExit(new HDeoptimize());
+        default_graph->exit_block()->FinishExit(new HDeoptimize());
+        default_graph->set_exit_block(NULL);
       } else {
         HContext* context = new HContext;
         AddInstruction(context);
-        HCall* call = new HCallNamed(context, name, argument_count);
+        HCallNamed* call = new HCallNamed(context, name, argument_count);
         call->set_position(expr->position());
         PreProcessCall(call);
         PushAndAdd(call);
       }
-      subgraphs.Add(subgraph);
     }
 
     HBasicBlock* new_exit_block =
-        BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id());
-    subgraph()->set_exit_block(new_exit_block);
+        BuildTypeSwitch(receiver, &maps, &subgraphs, default_graph, expr->id());
+    set_current_block(new_exit_block);
     // In an effect context, we did not materialized the value in the
     // predecessor environments so there's no need to handle it here.
     if (new_exit_block != NULL && !ast_context()->IsEffect()) {
@@ -3964,14 +3961,17 @@
 }
 
 
-void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) {
-  SmartPointer<char> callee = target->shared()->DebugName()->ToCString();
-  SmartPointer<char> caller =
-      graph()->info()->function()->debug_name()->ToCString();
-  if (result) {
-    PrintF("Inlined %s called from %s.\n", *callee, *caller);
-  } else {
-    PrintF("Do not inline %s called from %s.\n", *callee, *caller);
+void HGraphBuilder::TraceInline(Handle<JSFunction> target, const char* reason) {
+  if (FLAG_trace_inlining) {
+    SmartPointer<char> callee = target->shared()->DebugName()->ToCString();
+    SmartPointer<char> caller =
+        info()->function()->debug_name()->ToCString();
+    if (reason == NULL) {
+      PrintF("Inlined %s called from %s.\n", *callee, *caller);
+    } else {
+      PrintF("Did not inline %s called from %s (%s).\n",
+             *callee, *caller, reason);
+    }
   }
 }
 
@@ -3986,123 +3986,122 @@
   // Do a quick check on source code length to avoid parsing large
   // inlining candidates.
   if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) {
-    if (FLAG_trace_inlining) TraceInline(target, false);
+    TraceInline(target, "target text too big");
     return false;
   }
 
   // Target must be inlineable.
-  if (!target->IsInlineable()) return false;
+  if (!target->IsInlineable()) {
+    TraceInline(target, "target not inlineable");
+    return false;
+  }
 
   // No context change required.
-  CompilationInfo* outer_info = graph()->info();
+  CompilationInfo* outer_info = info();
   if (target->context() != outer_info->closure()->context() ||
       outer_info->scope()->contains_with() ||
       outer_info->scope()->num_heap_slots() > 0) {
+    TraceInline(target, "target requires context change");
     return false;
   }
 
   // Don't inline deeper than two calls.
   HEnvironment* env = environment();
-  if (env->outer() != NULL && env->outer()->outer() != NULL) return false;
+  if (env->outer() != NULL && env->outer()->outer() != NULL) {
+    TraceInline(target, "inline depth limit reached");
+    return false;
+  }
 
   // Don't inline recursive functions.
-  if (target->shared() == outer_info->closure()->shared()) return false;
+  if (target->shared() == outer_info->closure()->shared()) {
+    TraceInline(target, "target is recursive");
+    return false;
+  }
 
   // We don't want to add more than a certain number of nodes from inlining.
   if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) {
-    if (FLAG_trace_inlining) TraceInline(target, false);
+    TraceInline(target, "cumulative AST node limit reached");
     return false;
   }
 
   int count_before = AstNode::Count();
 
   // Parse and allocate variables.
-  CompilationInfo inner_info(target);
-  if (!ParserApi::Parse(&inner_info) ||
-      !Scope::Analyze(&inner_info)) {
+  CompilationInfo target_info(target);
+  if (!ParserApi::Parse(&target_info) ||
+      !Scope::Analyze(&target_info)) {
     if (Top::has_pending_exception()) {
+      // Parse or scope error, never optimize this function.
       SetStackOverflow();
+      target->shared()->set_optimization_disabled(true);
     }
+    TraceInline(target, "parse failure");
     return false;
   }
-  FunctionLiteral* function = inner_info.function();
+
+  if (target_info.scope()->num_heap_slots() > 0) {
+    TraceInline(target, "target has context-allocated variables");
+    return false;
+  }
+  FunctionLiteral* function = target_info.function();
 
   // Count the number of AST nodes added by inlining this call.
   int nodes_added = AstNode::Count() - count_before;
   if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) {
-    if (FLAG_trace_inlining) TraceInline(target, false);
+    TraceInline(target, "target AST is too large");
     return false;
   }
 
   // Check if we can handle all declarations in the inlined functions.
-  VisitDeclarations(inner_info.scope()->declarations());
+  VisitDeclarations(target_info.scope()->declarations());
   if (HasStackOverflow()) {
+    TraceInline(target, "target has non-trivial declaration");
     ClearStackOverflow();
     return false;
   }
 
   // Don't inline functions that uses the arguments object or that
   // have a mismatching number of parameters.
-  Handle<SharedFunctionInfo> shared(target->shared());
+  Handle<SharedFunctionInfo> target_shared(target->shared());
   int arity = expr->arguments()->length();
   if (function->scope()->arguments() != NULL ||
-      arity != shared->formal_parameter_count()) {
+      arity != target_shared->formal_parameter_count()) {
+    TraceInline(target, "target requires special argument handling");
     return false;
   }
 
   // All statements in the body must be inlineable.
   for (int i = 0, count = function->body()->length(); i < count; ++i) {
-    if (!function->body()->at(i)->IsInlineable()) return false;
+    if (!function->body()->at(i)->IsInlineable()) {
+      TraceInline(target, "target contains unsupported syntax");
+      return false;
+    }
   }
 
   // Generate the deoptimization data for the unoptimized version of
   // the target function if we don't already have it.
-  if (!shared->has_deoptimization_support()) {
+  if (!target_shared->has_deoptimization_support()) {
     // Note that we compile here using the same AST that we will use for
     // generating the optimized inline code.
-    inner_info.EnableDeoptimizationSupport();
-    if (!FullCodeGenerator::MakeCode(&inner_info)) return false;
-    shared->EnableDeoptimizationSupport(*inner_info.code());
-    Compiler::RecordFunctionCompilation(
-        Logger::FUNCTION_TAG,
-        Handle<String>(shared->DebugName()),
-        shared->start_position(),
-        &inner_info);
+    target_info.EnableDeoptimizationSupport();
+    if (!FullCodeGenerator::MakeCode(&target_info)) {
+      TraceInline(target, "could not generate deoptimization info");
+      return false;
+    }
+    target_shared->EnableDeoptimizationSupport(*target_info.code());
+    Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG,
+                                        &target_info,
+                                        target_shared);
   }
 
+  // ----------------------------------------------------------------
   // Save the pending call context and type feedback oracle. Set up new ones
   // for the inlined function.
-  ASSERT(shared->has_deoptimization_support());
-  AstContext* saved_call_context = call_context();
-  HBasicBlock* saved_function_return = function_return();
-  TypeFeedbackOracle* saved_oracle = oracle();
-  // On-stack replacement cannot target inlined functions.  Since we don't
-  // use a separate CompilationInfo structure for the inlined function, we
-  // save and restore the AST ID in the original compilation info.
-  int saved_osr_ast_id = graph()->info()->osr_ast_id();
-
-  TestContext* test_context = NULL;
-  if (ast_context()->IsTest()) {
-    // Inlined body is treated as if it occurs in an 'inlined' call context
-    // with true and false blocks that will forward to the real ones.
-    HBasicBlock* if_true = graph()->CreateBasicBlock();
-    HBasicBlock* if_false = graph()->CreateBasicBlock();
-    if_true->MarkAsInlineReturnTarget();
-    if_false->MarkAsInlineReturnTarget();
-    // AstContext constructor pushes on the context stack.
-    test_context = new TestContext(this, if_true, if_false);
-    function_return_ = NULL;
-  } else {
-    // Inlined body is treated as if it occurs in the original call context.
-    function_return_ = graph()->CreateBasicBlock();
-    function_return_->MarkAsInlineReturnTarget();
-  }
-  call_context_ = ast_context();
-  TypeFeedbackOracle new_oracle(
-      Handle<Code>(shared->code()),
+  ASSERT(target_shared->has_deoptimization_support());
+  TypeFeedbackOracle target_oracle(
+      Handle<Code>(target_shared->code()),
       Handle<Context>(target->context()->global_context()));
-  oracle_ = &new_oracle;
-  graph()->info()->SetOsrAstId(AstNode::kNoNumber);
+  FunctionState target_state(this, &target_info, &target_oracle);
 
   HSubgraph* body = CreateInlinedSubgraph(env, target, function);
   body->exit_block()->AddInstruction(new HEnterInlined(target, function));
@@ -4110,26 +4109,22 @@
   if (HasStackOverflow()) {
     // Bail out if the inline function did, as we cannot residualize a call
     // instead.
-    delete test_context;
-    call_context_ = saved_call_context;
-    function_return_ = saved_function_return;
-    oracle_ = saved_oracle;
-    graph()->info()->SetOsrAstId(saved_osr_ast_id);
+    TraceInline(target, "inline graph construction failed");
     return false;
   }
 
   // Update inlined nodes count.
   inlined_count_ += nodes_added;
 
-  if (FLAG_trace_inlining) TraceInline(target, true);
+  TraceInline(target, NULL);
 
-  if (body->HasExit()) {
+  if (body->exit_block() != NULL) {
     // Add a return of undefined if control can fall off the body.  In a
     // test context, undefined is false.
     HValue* return_value = graph()->GetConstantUndefined();
-    if (test_context == NULL) {
-      ASSERT(function_return_ != NULL);
-      body->exit_block()->AddLeaveInlined(return_value, function_return_);
+    if (inlined_test_context() == NULL) {
+      ASSERT(function_return() != NULL);
+      body->exit_block()->AddLeaveInlined(return_value, function_return());
     } else {
       // The graph builder assumes control can reach both branches of a
       // test, so we materialize the undefined value and test it rather than
@@ -4142,8 +4137,10 @@
       body->exit_block()->Finish(test);
 
       HValue* const no_return_value = NULL;
-      empty_true->AddLeaveInlined(no_return_value, test_context->if_true());
-      empty_false->AddLeaveInlined(no_return_value, test_context->if_false());
+      empty_true->AddLeaveInlined(no_return_value,
+                                  inlined_test_context()->if_true());
+      empty_false->AddLeaveInlined(no_return_value,
+                                   inlined_test_context()->if_false());
     }
     body->set_exit_block(NULL);
   }
@@ -4152,16 +4149,17 @@
   AddSimulate(expr->ReturnId());
 
   // Jump to the function entry (without re-recording the environment).
-  subgraph()->exit_block()->Finish(new HGoto(body->entry_block()));
+  current_block()->Finish(new HGoto(body->entry_block()));
 
   // Fix up the function exits.
-  if (test_context != NULL) {
-    HBasicBlock* if_true = test_context->if_true();
-    HBasicBlock* if_false = test_context->if_false();
+  if (inlined_test_context() != NULL) {
+    HBasicBlock* if_true = inlined_test_context()->if_true();
+    HBasicBlock* if_false = inlined_test_context()->if_false();
     if_true->SetJoinId(expr->id());
     if_false->SetJoinId(expr->id());
-    ASSERT(ast_context() == test_context);
-    delete test_context;  // Destructor pops from expression context stack.
+    ASSERT(ast_context() == inlined_test_context());
+    // Pop the return test context from the expression context stack.
+    ClearInlinedTestContext();
 
     // Forward to the real test context.
     HValue* const no_return_value = NULL;
@@ -4182,18 +4180,13 @@
     // TODO(kmillikin): Come up with a better way to handle this. It is too
     // subtle. NULL here indicates that the enclosing context has no control
     // flow to handle.
-    subgraph()->set_exit_block(NULL);
+    set_current_block(NULL);
 
   } else {
-    function_return_->SetJoinId(expr->id());
-    subgraph()->set_exit_block(function_return_);
+    function_return()->SetJoinId(expr->id());
+    set_current_block(function_return());
   }
 
-  call_context_ = saved_call_context;
-  function_return_ = saved_function_return;
-  oracle_ = saved_oracle;
-  graph()->info()->SetOsrAstId(saved_osr_ast_id);
-
   return true;
 }
 
@@ -4301,7 +4294,7 @@
   Property* prop = callee->AsProperty();
   ASSERT(prop != NULL);
 
-  if (graph()->info()->scope()->arguments() == NULL) return false;
+  if (info()->scope()->arguments() == NULL) return false;
 
   Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
   if (!name->IsEqualTo(CStrVector("apply"))) return false;
@@ -4348,14 +4341,13 @@
 void HGraphBuilder::VisitCall(Call* expr) {
   Expression* callee = expr->expression();
   int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
-  HCall* call = NULL;
+  HInstruction* call = NULL;
 
   Property* prop = callee->AsProperty();
   if (prop != NULL) {
     if (!prop->key()->IsPropertyName()) {
       // Keyed function call.
-      VisitArgument(prop->obj());
-      CHECK_BAILOUT;
+      VISIT_FOR_VALUE(prop->obj());
 
       VISIT_FOR_VALUE(prop->key());
       // Push receiver and key like the non-optimized code generator expects it.
@@ -4364,14 +4356,13 @@
       Push(key);
       Push(receiver);
 
-      VisitArgumentList(expr->arguments());
+      VisitExpressions(expr->arguments());
       CHECK_BAILOUT;
 
       HContext* context = new HContext;
       AddInstruction(context);
-      call = new HCallKeyed(context, key, argument_count);
+      call = PreProcessCall(new HCallKeyed(context, key, argument_count));
       call->set_position(expr->position());
-      PreProcessCall(call);
       Drop(1);  // Key.
       ast_context()->ReturnInstruction(call, expr->id());
       return;
@@ -4383,9 +4374,8 @@
     if (TryCallApply(expr)) return;
     CHECK_BAILOUT;
 
-    VisitArgument(prop->obj());
-    CHECK_BAILOUT;
-    VisitArgumentList(expr->arguments());
+    VISIT_FOR_VALUE(prop->obj());
+    VisitExpressions(expr->arguments());
     CHECK_BAILOUT;
 
     Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
@@ -4412,12 +4402,12 @@
         // IC when a primitive receiver check is required.
         HContext* context = new HContext;
         AddInstruction(context);
-        call = new HCallNamed(context, name, argument_count);
+        call = PreProcessCall(new HCallNamed(context, name, argument_count));
       } else {
         AddCheckConstantFunction(expr, receiver, receiver_map, true);
 
         if (TryInline(expr)) {
-          if (subgraph()->HasExit()) {
+          if (current_block() != NULL) {
             HValue* return_value = Pop();
             // If we inlined a function in a test context then we need to emit
             // a simulate here to shadow the ones at the end of the
@@ -4432,7 +4422,8 @@
           // Check for bailout, as the TryInline call in the if condition above
           // might return false due to bailout during hydrogen processing.
           CHECK_BAILOUT;
-          call = new HCallConstantFunction(expr->target(), argument_count);
+          call = PreProcessCall(new HCallConstantFunction(expr->target(),
+                                                          argument_count));
         }
       }
     } else if (types != NULL && types->length() > 1) {
@@ -4443,7 +4434,7 @@
     } else {
       HContext* context = new HContext;
       AddInstruction(context);
-      call = new HCallNamed(context, name, argument_count);
+      call = PreProcessCall(new HCallNamed(context, name, argument_count));
     }
 
   } else {
@@ -4452,19 +4443,19 @@
 
     if (!global_call) {
       ++argument_count;
-      VisitArgument(expr->expression());
-      CHECK_BAILOUT;
+      VISIT_FOR_VALUE(expr->expression());
     }
 
     if (global_call) {
+      bool known_global_function = false;
       // If there is a global property cell for the name at compile time and
       // access check is not enabled we assume that the function will not change
       // and generate optimized code for calling the function.
-      CompilationInfo* info = graph()->info();
-      bool known_global_function = info->has_global_object() &&
-          !info->global_object()->IsAccessCheckNeeded() &&
-          expr->ComputeGlobalTarget(Handle<GlobalObject>(info->global_object()),
-                                    var->name());
+      if (info()->has_global_object() &&
+          !info()->global_object()->IsAccessCheckNeeded()) {
+        Handle<GlobalObject> global(info()->global_object());
+        known_global_function = expr->ComputeGlobalTarget(global, var->name());
+      }
       if (known_global_function) {
         // Push the global object instead of the global receiver because
         // code generated by the full code generator expects it.
@@ -4472,7 +4463,7 @@
         HGlobalObject* global_object = new HGlobalObject(context);
         AddInstruction(context);
         PushAndAdd(global_object);
-        VisitArgumentList(expr->arguments());
+        VisitExpressions(expr->arguments());
         CHECK_BAILOUT;
 
         VISIT_FOR_VALUE(expr->expression());
@@ -4489,7 +4480,7 @@
         environment()->SetExpressionStackAt(receiver_index, global_receiver);
 
         if (TryInline(expr)) {
-          if (subgraph()->HasExit()) {
+          if (current_block() != NULL) {
             HValue* return_value = Pop();
             // If we inlined a function in a test context then we need to
             // emit a simulate here to shadow the ones at the end of the
@@ -4505,15 +4496,18 @@
         // during hydrogen processing.
         CHECK_BAILOUT;
 
-        call = new HCallKnownGlobal(expr->target(), argument_count);
+        call = PreProcessCall(new HCallKnownGlobal(expr->target(),
+                                                   argument_count));
       } else {
         HContext* context = new HContext;
         AddInstruction(context);
         PushAndAdd(new HGlobalObject(context));
-        VisitArgumentList(expr->arguments());
+        VisitExpressions(expr->arguments());
         CHECK_BAILOUT;
 
-        call = new HCallGlobal(context, var->name(), argument_count);
+        call = PreProcessCall(new HCallGlobal(context,
+                                              var->name(),
+                                              argument_count));
       }
 
     } else {
@@ -4522,15 +4516,14 @@
       AddInstruction(context);
       AddInstruction(global_object);
       PushAndAdd(new HGlobalReceiver(global_object));
-      VisitArgumentList(expr->arguments());
+      VisitExpressions(expr->arguments());
       CHECK_BAILOUT;
 
-      call = new HCallFunction(context, argument_count);
+      call = PreProcessCall(new HCallFunction(context, argument_count));
     }
   }
 
   call->set_position(expr->position());
-  PreProcessCall(call);
   ast_context()->ReturnInstruction(call, expr->id());
 }
 
@@ -4538,9 +4531,8 @@
 void HGraphBuilder::VisitCallNew(CallNew* expr) {
   // The constructor function is also used as the receiver argument to the
   // JS construct call builtin.
-  VisitArgument(expr->expression());
-  CHECK_BAILOUT;
-  VisitArgumentList(expr->arguments());
+  VISIT_FOR_VALUE(expr->expression());
+  VisitExpressions(expr->arguments());
   CHECK_BAILOUT;
 
   HContext* context = new HContext;
@@ -4550,7 +4542,7 @@
   // to the construct call.
   int arg_count = expr->arguments()->length() + 1;  // Plus constructor.
   HValue* constructor = environment()->ExpressionStackAt(arg_count - 1);
-  HCall* call = new HCallNew(context, constructor, arg_count);
+  HCallNew* call = new HCallNew(context, constructor, arg_count);
   call->set_position(expr->position());
   PreProcessCall(call);
   ast_context()->ReturnInstruction(call, expr->id());
@@ -4573,25 +4565,15 @@
 
 
 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
-  Handle<String> name = expr->name();
-  if (name->IsEqualTo(CStrVector("_Log"))) {
-    ast_context()->ReturnValue(graph()->GetConstantUndefined());
-    return;
-  }
-
-  Runtime::Function* function = expr->function();
   if (expr->is_jsruntime()) {
     BAILOUT("call to a JavaScript runtime function");
   }
+
+  Runtime::Function* function = expr->function();
   ASSERT(function != NULL);
-
-  VisitArgumentList(expr->arguments());
-  CHECK_BAILOUT;
-
-  int argument_count = expr->arguments()->length();
   if (function->intrinsic_type == Runtime::INLINE) {
-    ASSERT(name->length() > 0);
-    ASSERT(name->Get(0) == '_');
+    ASSERT(expr->name()->length() > 0);
+    ASSERT(expr->name()->Get(0) == '_');
     // Call to an inline function.
     int lookup_index = static_cast<int>(function->function_id) -
         static_cast<int>(Runtime::kFirstInlineFunction);
@@ -4601,12 +4583,17 @@
     InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
 
     // Call the inline code generator using the pointer-to-member.
-    (this->*generator)(argument_count, expr->id());
+    (this->*generator)(expr);
   } else {
     ASSERT(function->intrinsic_type == Runtime::RUNTIME);
-    HCall* call = new HCallRuntime(name, expr->function(), argument_count);
+    VisitArgumentList(expr->arguments());
+    CHECK_BAILOUT;
+
+    Handle<String> name = expr->name();
+    int argument_count = expr->arguments()->length();
+    HCallRuntime* call = new HCallRuntime(name, function, argument_count);
     call->set_position(RelocInfo::kNoPosition);
-    PreProcessCall(call);
+    Drop(argument_count);
     ast_context()->ReturnInstruction(call, expr->id());
   }
 }
@@ -4656,21 +4643,29 @@
       VisitForControl(expr->expression(),
                       context->if_false(),
                       context->if_true());
-    } else {
-      HSubgraph* true_graph = CreateEmptySubgraph();
-      HSubgraph* false_graph = CreateEmptySubgraph();
+    } else if (ast_context()->IsValue()) {
+      HBasicBlock* materialize_false = graph()->CreateBasicBlock();
+      HBasicBlock* materialize_true = graph()->CreateBasicBlock();
       VISIT_FOR_CONTROL(expr->expression(),
-                        false_graph->entry_block(),
-                        true_graph->entry_block());
-      true_graph->entry_block()->SetJoinId(expr->expression()->id());
-      true_graph->environment()->Push(graph_->GetConstantTrue());
+                        materialize_false,
+                        materialize_true);
+      materialize_false->SetJoinId(expr->expression()->id());
+      materialize_true->SetJoinId(expr->expression()->id());
 
-      false_graph->entry_block()->SetJoinId(expr->expression()->id());
-      false_graph->environment()->Push(graph_->GetConstantFalse());
+      set_current_block(materialize_false);
+      Push(graph()->GetConstantFalse());
+      set_current_block(materialize_true);
+      Push(graph()->GetConstantTrue());
 
-      current_subgraph_->AppendJoin(true_graph, false_graph, expr);
+      HBasicBlock* join =
+          CreateJoin(materialize_false, materialize_true, expr->id());
+      set_current_block(join);
       ast_context()->ReturnValue(Pop());
+    } else {
+      ASSERT(ast_context()->IsEffect());
+      VisitForEffect(expr->expression());
     }
+
   } else if (op == Token::BIT_NOT || op == Token::SUB) {
     VISIT_FOR_VALUE(expr->expression());
     HValue* value = Pop();
@@ -4724,10 +4719,6 @@
   bool inc = expr->op() == Token::INC;
 
   if (var != NULL) {
-    if (!var->is_global() && !var->IsStackAllocated()) {
-      BAILOUT("non-stack/non-global variable in count operation");
-    }
-
     VISIT_FOR_VALUE(target);
 
     // Match the full code generator stack by simulating an extra stack
@@ -4743,9 +4734,16 @@
                                      after,
                                      expr->position(),
                                      expr->AssignmentId());
-    } else {
-      ASSERT(var->IsStackAllocated());
+    } else if (var->IsStackAllocated()) {
       Bind(var, after);
+    } else if (var->IsContextSlot()) {
+      HValue* context = BuildContextChainWalk(var);
+      int index = var->AsSlot()->index();
+      HStoreContextSlot* instr = new HStoreContextSlot(context, index, after);
+      AddInstruction(instr);
+      if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
+    } else {
+      BAILOUT("lookup variable in count operation");
     }
     Drop(has_extra ? 2 : 1);
     ast_context()->ReturnValue(expr->is_postfix() ? before : after);
@@ -4956,22 +4954,59 @@
 
       // Translate right subexpression by visiting it in the same AST
       // context as the entire expression.
-      subgraph()->set_exit_block(eval_right);
+      set_current_block(eval_right);
       Visit(expr->right());
 
-    } else {
+    } else if (ast_context()->IsValue()) {
       VISIT_FOR_VALUE(expr->left());
-      ASSERT(current_subgraph_->HasExit());
+      ASSERT(current_block() != NULL);
 
-      HValue* left = Top();
-      HEnvironment* environment_copy = environment()->Copy();
-      environment_copy->Pop();
-      HSubgraph* right_subgraph;
-      right_subgraph = CreateBranchSubgraph(environment_copy);
-      ADD_TO_SUBGRAPH(right_subgraph, expr->right());
-      current_subgraph_->AppendOptional(right_subgraph, is_logical_and, left);
-      current_subgraph_->exit_block()->SetJoinId(expr->id());
+      // We need an extra block to maintain edge-split form.
+      HBasicBlock* empty_block = graph()->CreateBasicBlock();
+      HBasicBlock* eval_right = graph()->CreateBasicBlock();
+      HTest* test = is_logical_and
+          ? new HTest(Top(), eval_right, empty_block)
+          : new HTest(Top(), empty_block, eval_right);
+      current_block()->Finish(test);
+
+      set_current_block(eval_right);
+      Drop(1);  // Value of the left subexpression.
+      VISIT_FOR_VALUE(expr->right());
+
+      HBasicBlock* join_block =
+          CreateJoin(empty_block, current_block(), expr->id());
+      set_current_block(join_block);
       ast_context()->ReturnValue(Pop());
+
+    } else {
+      ASSERT(ast_context()->IsEffect());
+      // In an effect context, we don't need the value of the left
+      // subexpression, only its control flow and side effects.  We need an
+      // extra block to maintain edge-split form.
+      HBasicBlock* empty_block = graph()->CreateBasicBlock();
+      HBasicBlock* right_block = graph()->CreateBasicBlock();
+      HBasicBlock* join_block = graph()->CreateBasicBlock();
+      if (is_logical_and) {
+        VISIT_FOR_CONTROL(expr->left(), right_block, empty_block);
+      } else {
+        VISIT_FOR_CONTROL(expr->left(), empty_block, right_block);
+      }
+      // TODO(kmillikin): Find a way to fix this.  It's ugly that there are
+      // actually two empty blocks (one here and one inserted by
+      // TestContext::BuildBranch, and that they both have an HSimulate
+      // though the second one is not a merge node, and that we really have
+      // no good AST ID to put on that first HSimulate.
+      empty_block->SetJoinId(expr->id());
+      right_block->SetJoinId(expr->RightId());
+      set_current_block(right_block);
+      VISIT_FOR_EFFECT(expr->right());
+
+      empty_block->Goto(join_block);
+      current_block()->Goto(join_block);
+      join_block->SetJoinId(expr->id());
+      set_current_block(join_block);
+      // We did not materialize any value in the predecessor environments,
+      // so there is no need to handle it here.
     }
 
   } else {
@@ -5049,7 +5084,7 @@
   HValue* left = Pop();
   Token::Value op = expr->op();
 
-  TypeInfo info = oracle()->CompareType(expr);
+  TypeInfo type_info = oracle()->CompareType(expr);
   HInstruction* instr = NULL;
   if (op == Token::INSTANCEOF) {
     // Check to see if the rhs of the instanceof is a global function not
@@ -5058,12 +5093,11 @@
     Handle<JSFunction> target = Handle<JSFunction>::null();
     Variable* var = expr->right()->AsVariableProxy()->AsVariable();
     bool global_function = (var != NULL) && var->is_global() && !var->is_this();
-    CompilationInfo* info = graph()->info();
     if (global_function &&
-        info->has_global_object() &&
-        !info->global_object()->IsAccessCheckNeeded()) {
+        info()->has_global_object() &&
+        !info()->global_object()->IsAccessCheckNeeded()) {
       Handle<String> name = var->name();
-      Handle<GlobalObject> global(info->global_object());
+      Handle<GlobalObject> global(info()->global_object());
       LookupResult lookup;
       global->Lookup(*name, &lookup);
       if (lookup.IsProperty() &&
@@ -5090,7 +5124,7 @@
     }
   } else if (op == Token::IN) {
     BAILOUT("Unsupported comparison: in");
-  } else if (info.IsNonPrimitive()) {
+  } else if (type_info.IsNonPrimitive()) {
     switch (op) {
       case Token::EQ:
       case Token::EQ_STRICT: {
@@ -5107,7 +5141,7 @@
     }
   } else {
     HCompare* compare = new HCompare(left, right, op);
-    Representation r = ToRepresentation(info);
+    Representation r = ToRepresentation(type_info);
     compare->SetInputRepresentation(r);
     instr = compare;
   }
@@ -5148,340 +5182,361 @@
 
 // Generators for inline runtime functions.
 // Support for types.
-void HGraphBuilder::GenerateIsSmi(int argument_count, int ast_id) {
-  ASSERT(argument_count == 1);
+void HGraphBuilder::GenerateIsSmi(CallRuntime* call) {
+  ASSERT(call->arguments()->length() == 1);
+  VISIT_FOR_VALUE(call->arguments()->at(0));
   HValue* value = Pop();
   HIsSmi* result = new HIsSmi(value);
-  ast_context()->ReturnInstruction(result, ast_id);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
-void HGraphBuilder::GenerateIsSpecObject(int argument_count, int ast_id) {
-  ASSERT(argument_count == 1);
+void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
+  ASSERT(call->arguments()->length() == 1);
+  VISIT_FOR_VALUE(call->arguments()->at(0));
   HValue* value = Pop();
   HHasInstanceType* result =
       new HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE);
-  ast_context()->ReturnInstruction(result, ast_id);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
-void HGraphBuilder::GenerateIsFunction(int argument_count, int ast_id) {
-  ASSERT(argument_count == 1);
+void HGraphBuilder::GenerateIsFunction(CallRuntime* call) {
+  ASSERT(call->arguments()->length() == 1);
+  VISIT_FOR_VALUE(call->arguments()->at(0));
   HValue* value = Pop();
   HHasInstanceType* result = new HHasInstanceType(value, JS_FUNCTION_TYPE);
-  ast_context()->ReturnInstruction(result, ast_id);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
-void HGraphBuilder::GenerateHasCachedArrayIndex(int argument_count,
-                                                int ast_id) {
-  ASSERT(argument_count == 1);
+void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
+  ASSERT(call->arguments()->length() == 1);
+  VISIT_FOR_VALUE(call->arguments()->at(0));
   HValue* value = Pop();
   HHasCachedArrayIndex* result = new HHasCachedArrayIndex(value);
-  ast_context()->ReturnInstruction(result, ast_id);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
-void HGraphBuilder::GenerateIsArray(int argument_count, int ast_id) {
-  ASSERT(argument_count == 1);
+void HGraphBuilder::GenerateIsArray(CallRuntime* call) {
+  ASSERT(call->arguments()->length() == 1);
+  VISIT_FOR_VALUE(call->arguments()->at(0));
   HValue* value = Pop();
   HHasInstanceType* result = new HHasInstanceType(value, JS_ARRAY_TYPE);
-  ast_context()->ReturnInstruction(result, ast_id);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
-void HGraphBuilder::GenerateIsRegExp(int argument_count, int ast_id) {
-  ASSERT(argument_count == 1);
+void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
+  ASSERT(call->arguments()->length() == 1);
+  VISIT_FOR_VALUE(call->arguments()->at(0));
   HValue* value = Pop();
   HHasInstanceType* result = new HHasInstanceType(value, JS_REGEXP_TYPE);
-  ast_context()->ReturnInstruction(result, ast_id);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
-void HGraphBuilder::GenerateIsObject(int argument_count, int ast_id) {
-  ASSERT(argument_count == 1);
-
+void HGraphBuilder::GenerateIsObject(CallRuntime* call) {
+  ASSERT(call->arguments()->length() == 1);
+  VISIT_FOR_VALUE(call->arguments()->at(0));
   HValue* value = Pop();
   HIsObject* test = new HIsObject(value);
-  ast_context()->ReturnInstruction(test, ast_id);
+  ast_context()->ReturnInstruction(test, call->id());
 }
 
 
-void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count,
-                                             int ast_id) {
+void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
   BAILOUT("inlined runtime function: IsNonNegativeSmi");
 }
 
 
-void HGraphBuilder::GenerateIsUndetectableObject(int argument_count,
-                                                 int ast_id) {
+void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
   BAILOUT("inlined runtime function: IsUndetectableObject");
 }
 
 
 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
-    int argument_count,
-    int ast_id) {
+    CallRuntime* call) {
   BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
 }
 
 
 // Support for construct call checks.
-void HGraphBuilder::GenerateIsConstructCall(int argument_count, int ast_id) {
-  ASSERT(argument_count == 0);
-  ast_context()->ReturnInstruction(new HIsConstructCall, ast_id);
+void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
+  ASSERT(call->arguments()->length() == 0);
+  ast_context()->ReturnInstruction(new HIsConstructCall, call->id());
 }
 
 
 // Support for arguments.length and arguments[?].
-void HGraphBuilder::GenerateArgumentsLength(int argument_count, int ast_id) {
-  ASSERT(argument_count == 0);
+void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
+  ASSERT(call->arguments()->length() == 0);
   HInstruction* elements = AddInstruction(new HArgumentsElements);
   HArgumentsLength* result = new HArgumentsLength(elements);
-  ast_context()->ReturnInstruction(result, ast_id);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
-void HGraphBuilder::GenerateArguments(int argument_count, int ast_id) {
-  ASSERT(argument_count == 1);
+void HGraphBuilder::GenerateArguments(CallRuntime* call) {
+  ASSERT(call->arguments()->length() == 1);
+  VISIT_FOR_VALUE(call->arguments()->at(0));
   HValue* index = Pop();
   HInstruction* elements = AddInstruction(new HArgumentsElements);
   HInstruction* length = AddInstruction(new HArgumentsLength(elements));
   HAccessArgumentsAt* result = new HAccessArgumentsAt(elements, length, index);
-  ast_context()->ReturnInstruction(result, ast_id);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
 // Support for accessing the class and value fields of an object.
-void HGraphBuilder::GenerateClassOf(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateClassOf(CallRuntime* call) {
   // The special form detected by IsClassOfTest is detected before we get here
   // and does not cause a bailout.
   BAILOUT("inlined runtime function: ClassOf");
 }
 
 
-void HGraphBuilder::GenerateValueOf(int argument_count, int ast_id) {
-  ASSERT(argument_count == 1);
+void HGraphBuilder::GenerateValueOf(CallRuntime* call) {
+  ASSERT(call->arguments()->length() == 1);
+  VISIT_FOR_VALUE(call->arguments()->at(0));
   HValue* value = Pop();
   HValueOf* result = new HValueOf(value);
-  ast_context()->ReturnInstruction(result, ast_id);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
-void HGraphBuilder::GenerateSetValueOf(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
   BAILOUT("inlined runtime function: SetValueOf");
 }
 
 
 // Fast support for charCodeAt(n).
-void HGraphBuilder::GenerateStringCharCodeAt(int argument_count, int ast_id) {
-  ASSERT(argument_count == 2);
+void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
+  ASSERT(call->arguments()->length() == 2);
+  VISIT_FOR_VALUE(call->arguments()->at(0));
+  VISIT_FOR_VALUE(call->arguments()->at(1));
   HValue* index = Pop();
   HValue* string = Pop();
   HStringCharCodeAt* result = BuildStringCharCodeAt(string, index);
-  ast_context()->ReturnInstruction(result, ast_id);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
 // Fast support for string.charAt(n) and string[n].
-void HGraphBuilder::GenerateStringCharFromCode(int argument_count,
-                                               int ast_id) {
+void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
   BAILOUT("inlined runtime function: StringCharFromCode");
 }
 
 
 // Fast support for string.charAt(n) and string[n].
-void HGraphBuilder::GenerateStringCharAt(int argument_count, int ast_id) {
-  ASSERT_EQ(2, argument_count);
+void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
+  ASSERT_EQ(2, call->arguments()->length());
+  VisitArgumentList(call->arguments());
+  CHECK_BAILOUT;
   HContext* context = new HContext;
   AddInstruction(context);
-  HCallStub* result =
-      new HCallStub(context, CodeStub::StringCharAt, argument_count);
-  PreProcessCall(result);
-  ast_context()->ReturnInstruction(result, ast_id);
+  HCallStub* result = new HCallStub(context, CodeStub::StringCharAt, 2);
+  Drop(2);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
 // Fast support for object equality testing.
-void HGraphBuilder::GenerateObjectEquals(int argument_count, int ast_id) {
-  ASSERT(argument_count == 2);
+void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
+  ASSERT(call->arguments()->length() == 2);
+  VISIT_FOR_VALUE(call->arguments()->at(0));
+  VISIT_FOR_VALUE(call->arguments()->at(1));
   HValue* right = Pop();
   HValue* left = Pop();
   HCompareJSObjectEq* result = new HCompareJSObjectEq(left, right);
-  ast_context()->ReturnInstruction(result, ast_id);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
-void HGraphBuilder::GenerateLog(int argument_count, int ast_id) {
-  UNREACHABLE();  // We caught this in VisitCallRuntime.
+void HGraphBuilder::GenerateLog(CallRuntime* call) {
+  // %_Log is ignored in optimized code.
+  ast_context()->ReturnValue(graph()->GetConstantUndefined());
 }
 
 
 // Fast support for Math.random().
-void HGraphBuilder::GenerateRandomHeapNumber(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
   BAILOUT("inlined runtime function: RandomHeapNumber");
 }
 
 
 // Fast support for StringAdd.
-void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) {
-  ASSERT_EQ(2, argument_count);
+void HGraphBuilder::GenerateStringAdd(CallRuntime* call) {
+  ASSERT_EQ(2, call->arguments()->length());
+  VisitArgumentList(call->arguments());
+  CHECK_BAILOUT;
   HContext* context = new HContext;
   AddInstruction(context);
-  HCallStub* result =
-      new HCallStub(context, CodeStub::StringAdd, argument_count);
-  PreProcessCall(result);
-  ast_context()->ReturnInstruction(result, ast_id);
+  HCallStub* result = new HCallStub(context, CodeStub::StringAdd, 2);
+  Drop(2);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
 // Fast support for SubString.
-void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) {
-  ASSERT_EQ(3, argument_count);
+void HGraphBuilder::GenerateSubString(CallRuntime* call) {
+  ASSERT_EQ(3, call->arguments()->length());
+  VisitArgumentList(call->arguments());
+  CHECK_BAILOUT;
   HContext* context = new HContext;
   AddInstruction(context);
-  HCallStub* result =
-      new HCallStub(context, CodeStub::SubString, argument_count);
-  PreProcessCall(result);
-  ast_context()->ReturnInstruction(result, ast_id);
+  HCallStub* result = new HCallStub(context, CodeStub::SubString, 3);
+  Drop(3);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
 // Fast support for StringCompare.
-void HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) {
-  ASSERT_EQ(2, argument_count);
+void HGraphBuilder::GenerateStringCompare(CallRuntime* call) {
+  ASSERT_EQ(2, call->arguments()->length());
+  VisitArgumentList(call->arguments());
+  CHECK_BAILOUT;
   HContext* context = new HContext;
   AddInstruction(context);
-  HCallStub* result =
-      new HCallStub(context, CodeStub::StringCompare, argument_count);
-  PreProcessCall(result);
-  ast_context()->ReturnInstruction(result, ast_id);
+  HCallStub* result = new HCallStub(context, CodeStub::StringCompare, 2);
+  Drop(2);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
 // Support for direct calls from JavaScript to native RegExp code.
-void HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) {
-  ASSERT_EQ(4, argument_count);
+void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
+  ASSERT_EQ(4, call->arguments()->length());
+  VisitArgumentList(call->arguments());
+  CHECK_BAILOUT;
   HContext* context = new HContext;
   AddInstruction(context);
-  HCallStub* result =
-      new HCallStub(context, CodeStub::RegExpExec, argument_count);
-  PreProcessCall(result);
-  ast_context()->ReturnInstruction(result, ast_id);
+  HCallStub* result = new HCallStub(context, CodeStub::RegExpExec, 4);
+  Drop(4);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
 // Construct a RegExp exec result with two in-object properties.
-void HGraphBuilder::GenerateRegExpConstructResult(int argument_count,
-                                                  int ast_id) {
-  ASSERT_EQ(3, argument_count);
+void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
+  ASSERT_EQ(3, call->arguments()->length());
+  VisitArgumentList(call->arguments());
+  CHECK_BAILOUT;
   HContext* context = new HContext;
   AddInstruction(context);
   HCallStub* result =
-      new HCallStub(context, CodeStub::RegExpConstructResult, argument_count);
-  PreProcessCall(result);
-  ast_context()->ReturnInstruction(result, ast_id);
+      new HCallStub(context, CodeStub::RegExpConstructResult, 3);
+  Drop(3);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
 // Support for fast native caches.
-void HGraphBuilder::GenerateGetFromCache(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
   BAILOUT("inlined runtime function: GetFromCache");
 }
 
 
 // Fast support for number to string.
-void HGraphBuilder::GenerateNumberToString(int argument_count, int ast_id) {
-  ASSERT_EQ(1, argument_count);
+void HGraphBuilder::GenerateNumberToString(CallRuntime* call) {
+  ASSERT_EQ(1, call->arguments()->length());
+  VisitArgumentList(call->arguments());
+  CHECK_BAILOUT;
   HContext* context = new HContext;
   AddInstruction(context);
-  HCallStub* result =
-      new HCallStub(context, CodeStub::NumberToString, argument_count);
-  PreProcessCall(result);
-  ast_context()->ReturnInstruction(result, ast_id);
+  HCallStub* result = new HCallStub(context, CodeStub::NumberToString, 1);
+  Drop(1);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
 // Fast swapping of elements. Takes three expressions, the object and two
 // indices. This should only be used if the indices are known to be
 // non-negative and within bounds of the elements array at the call site.
-void HGraphBuilder::GenerateSwapElements(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateSwapElements(CallRuntime* call) {
   BAILOUT("inlined runtime function: SwapElements");
 }
 
 
 // Fast call for custom callbacks.
-void HGraphBuilder::GenerateCallFunction(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateCallFunction(CallRuntime* call) {
   BAILOUT("inlined runtime function: CallFunction");
 }
 
 
 // Fast call to math functions.
-void HGraphBuilder::GenerateMathPow(int argument_count, int ast_id) {
-  ASSERT_EQ(2, argument_count);
+void HGraphBuilder::GenerateMathPow(CallRuntime* call) {
+  ASSERT_EQ(2, call->arguments()->length());
+  VISIT_FOR_VALUE(call->arguments()->at(0));
+  VISIT_FOR_VALUE(call->arguments()->at(1));
   HValue* right = Pop();
   HValue* left = Pop();
   HPower* result = new HPower(left, right);
-  ast_context()->ReturnInstruction(result, ast_id);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
-void HGraphBuilder::GenerateMathSin(int argument_count, int ast_id) {
-  ASSERT_EQ(1, argument_count);
+void HGraphBuilder::GenerateMathSin(CallRuntime* call) {
+  ASSERT_EQ(1, call->arguments()->length());
+  VisitArgumentList(call->arguments());
+  CHECK_BAILOUT;
   HContext* context = new HContext;
   AddInstruction(context);
-  HCallStub* result =
-      new HCallStub(context, CodeStub::TranscendentalCache, argument_count);
+  HCallStub* result = new HCallStub(context, CodeStub::TranscendentalCache, 1);
   result->set_transcendental_type(TranscendentalCache::SIN);
-  PreProcessCall(result);
-  ast_context()->ReturnInstruction(result, ast_id);
+  Drop(1);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
-void HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) {
-  ASSERT_EQ(1, argument_count);
+void HGraphBuilder::GenerateMathCos(CallRuntime* call) {
+  ASSERT_EQ(1, call->arguments()->length());
+  VisitArgumentList(call->arguments());
+  CHECK_BAILOUT;
   HContext* context = new HContext;
   AddInstruction(context);
-  HCallStub* result =
-      new HCallStub(context, CodeStub::TranscendentalCache, argument_count);
+  HCallStub* result = new HCallStub(context, CodeStub::TranscendentalCache, 1);
   result->set_transcendental_type(TranscendentalCache::COS);
-  PreProcessCall(result);
-  ast_context()->ReturnInstruction(result, ast_id);
+  Drop(1);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
-void HGraphBuilder::GenerateMathLog(int argument_count, int ast_id) {
-  ASSERT_EQ(1, argument_count);
+void HGraphBuilder::GenerateMathLog(CallRuntime* call) {
+  ASSERT_EQ(1, call->arguments()->length());
+  VisitArgumentList(call->arguments());
+  CHECK_BAILOUT;
   HContext* context = new HContext;
   AddInstruction(context);
-  HCallStub* result =
-      new HCallStub(context, CodeStub::TranscendentalCache, argument_count);
+  HCallStub* result = new HCallStub(context, CodeStub::TranscendentalCache, 1);
   result->set_transcendental_type(TranscendentalCache::LOG);
-  PreProcessCall(result);
-  ast_context()->ReturnInstruction(result, ast_id);
+  Drop(1);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
-void HGraphBuilder::GenerateMathSqrt(int argument_count, int ast_id) {
+void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
   BAILOUT("inlined runtime function: MathSqrt");
 }
 
 
 // Check whether two RegExps are equivalent
-void HGraphBuilder::GenerateIsRegExpEquivalent(int argument_count,
-                                               int ast_id) {
+void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) {
   BAILOUT("inlined runtime function: IsRegExpEquivalent");
 }
 
 
-void HGraphBuilder::GenerateGetCachedArrayIndex(int argument_count,
-                                                int ast_id) {
-  BAILOUT("inlined runtime function: GetCachedArrayIndex");
+void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
+  ASSERT(call->arguments()->length() == 1);
+  VISIT_FOR_VALUE(call->arguments()->at(0));
+  HValue* value = Pop();
+  HGetCachedArrayIndex* result = new HGetCachedArrayIndex(value);
+  ast_context()->ReturnInstruction(result, call->id());
 }
 
 
-void HGraphBuilder::GenerateFastAsciiArrayJoin(int argument_count,
-                                               int ast_id) {
+void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
   BAILOUT("inlined runtime function: FastAsciiArrayJoin");
 }
 
@@ -5882,7 +5937,7 @@
     if (op != NULL && op->IsUnallocated()) hint_index = op->VirtualRegister();
     trace_.Add(" %d %d", parent_index, hint_index);
     UseInterval* cur_interval = range->first_interval();
-    while (cur_interval != NULL) {
+    while (cur_interval != NULL && range->Covers(cur_interval->start())) {
       trace_.Add(" [%d, %d[",
                  cur_interval->start().Value(),
                  cur_interval->end().Value());
@@ -5891,7 +5946,7 @@
 
     UsePosition* current_pos = range->first_pos();
     while (current_pos != NULL) {
-      if (current_pos->RegisterIsBeneficial()) {
+      if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
         trace_.Add(" %d M", current_pos->pos().Value());
       }
       current_pos = current_pos->next();
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 6f41ee6..d8b1cfb 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -60,6 +60,8 @@
   HGraph* graph() const { return graph_; }
   const ZoneList<HPhi*>* phis() const { return &phis_; }
   HInstruction* first() const { return first_; }
+  HInstruction* last() const { return last_; }
+  void set_last(HInstruction* instr) { last_ = instr; }
   HInstruction* GetLastInstruction();
   HControlInstruction* end() const { return end_; }
   HLoopInformation* loop_information() const { return loop_information_; }
@@ -115,6 +117,7 @@
   void SetJoinId(int id);
 
   void Finish(HControlInstruction* last);
+  void FinishExit(HControlInstruction* instruction);
   void Goto(HBasicBlock* block, bool include_stack_check = false);
 
   int PredecessorIndexOf(HBasicBlock* predecessor) const;
@@ -148,7 +151,7 @@
   HGraph* graph_;
   ZoneList<HPhi*> phis_;
   HInstruction* first_;
-  HInstruction* last_;  // Last non-control instruction of the block.
+  HInstruction* last_;
   HControlInstruction* end_;
   HLoopInformation* loop_information_;
   ZoneList<HBasicBlock*> predecessors_;
@@ -194,94 +197,26 @@
   explicit HSubgraph(HGraph* graph)
       : graph_(graph),
         entry_block_(NULL),
-        exit_block_(NULL),
-        break_continue_info_(4) {
+        exit_block_(NULL) {
   }
 
   HGraph* graph() const { return graph_; }
-  HEnvironment* environment() const {
-    ASSERT(HasExit());
-    return exit_block_->last_environment();
-  }
-
-  bool HasExit() const { return exit_block_ != NULL; }
-
-  void PreProcessOsrEntry(IterationStatement* statement);
-
-  void AppendOptional(HSubgraph* graph,
-                      bool on_true_branch,
-                      HValue* boolean_value);
-  void AppendJoin(HSubgraph* then_graph, HSubgraph* else_graph, AstNode* node);
-  void AppendWhile(HSubgraph* condition,
-                   HSubgraph* body,
-                   IterationStatement* statement,
-                   HSubgraph* continue_subgraph,
-                   HSubgraph* exit);
-  void AppendDoWhile(HSubgraph* body,
-                     IterationStatement* statement,
-                     HSubgraph* go_back,
-                     HSubgraph* exit);
-  void AppendEndless(HSubgraph* body, IterationStatement* statement);
-  void Append(HSubgraph* next, BreakableStatement* statement);
-  void ResolveContinue(IterationStatement* statement);
-  HBasicBlock* BundleBreak(BreakableStatement* statement);
-  HBasicBlock* BundleContinue(IterationStatement* statement);
-  HBasicBlock* BundleBreakContinue(BreakableStatement* statement,
-                                   bool is_continue,
-                                   int join_id);
-  HBasicBlock* JoinBlocks(HBasicBlock* a, HBasicBlock* b, int id);
-
-  void FinishExit(HControlInstruction* instruction);
-  void FinishBreakContinue(BreakableStatement* target, bool is_continue);
-  void Initialize(HBasicBlock* block) {
-    ASSERT(entry_block_ == NULL);
-    entry_block_ = block;
-    exit_block_ = block;
-  }
   HBasicBlock* entry_block() const { return entry_block_; }
   HBasicBlock* exit_block() const { return exit_block_; }
   void set_exit_block(HBasicBlock* block) {
     exit_block_ = block;
   }
 
-  void ConnectExitTo(HBasicBlock* other, bool include_stack_check = false) {
-    if (HasExit()) {
-      exit_block()->Goto(other, include_stack_check);
-    }
-  }
-
-  void AddBreakContinueInfo(HSubgraph* other) {
-    break_continue_info_.AddAll(other->break_continue_info_);
+  void Initialize(HBasicBlock* block) {
+    ASSERT(entry_block_ == NULL);
+    entry_block_ = block;
+    exit_block_ = block;
   }
 
  protected:
-  class BreakContinueInfo: public ZoneObject {
-   public:
-    BreakContinueInfo(BreakableStatement* target, HBasicBlock* block,
-                      bool is_continue)
-      : target_(target), block_(block), continue_(is_continue) {}
-    BreakableStatement* target() const { return target_; }
-    HBasicBlock* block() const { return block_; }
-    bool is_continue() const { return continue_; }
-    bool IsResolved() const { return block_ == NULL; }
-    void Resolve() { block_ = NULL; }
-
-   private:
-    BreakableStatement* target_;
-    HBasicBlock* block_;
-    bool continue_;
-  };
-
-  const ZoneList<BreakContinueInfo*>* break_continue_info() const {
-    return &break_continue_info_;
-  }
-
   HGraph* graph_;  // The graph this is a subgraph of.
   HBasicBlock* entry_block_;
   HBasicBlock* exit_block_;
-
- private:
-  ZoneList<BreakContinueInfo*> break_continue_info_;
 };
 
 
@@ -289,13 +224,8 @@
  public:
   explicit HGraph(CompilationInfo* info);
 
-  CompilationInfo* info() const { return info_; }
-
-  bool AllowCodeMotion() const;
-
   const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
   const ZoneList<HPhi*>* phi_list() const { return phi_list_; }
-  Handle<String> debug_name() const { return info_->function()->debug_name(); }
   HEnvironment* start_environment() const { return start_environment_; }
 
   void InitializeInferredTypes();
@@ -312,7 +242,7 @@
   // which are not supported by the optimizing compiler.
   bool CollectPhis();
 
-  Handle<Code> Compile();
+  Handle<Code> Compile(CompilationInfo* info);
 
   void set_undefined_constant(HConstant* constant) {
     undefined_constant_.set(constant);
@@ -333,9 +263,6 @@
     arguments_object_.set(object);
   }
 
-  // True iff. we are compiling for OSR and the statement is the entry.
-  bool HasOsrEntryAt(IterationStatement* statement);
-
   int GetMaximumValueID() const { return values_.length(); }
   int GetNextBlockID() { return next_block_id_++; }
   int GetNextValueID(HValue* value) {
@@ -367,15 +294,13 @@
   void PropagateMinusZeroChecks(HValue* value, BitVector* visited);
   void InsertRepresentationChangeForUse(HValue* value,
                                         HValue* use,
-                                        Representation to,
-                                        bool truncating);
+                                        Representation to);
   void InsertRepresentationChanges(HValue* current);
   void InferTypes(ZoneList<HValue*>* worklist);
   void InitializeInferredTypes(int from_inclusive, int to_inclusive);
   void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor);
 
   int next_block_id_;
-  CompilationInfo* info_;
   HEnvironment* start_environment_;
   ZoneList<HBasicBlock*> blocks_;
   ZoneList<HValue*> values_;
@@ -526,6 +451,8 @@
 
 class HGraphBuilder;
 
+// This class is not BASE_EMBEDDED because our inlining implementation uses
+// new and delete.
 class AstContext {
  public:
   bool IsEffect() const { return kind_ == Expression::kEffect; }
@@ -617,26 +544,125 @@
 };
 
 
+class FunctionState BASE_EMBEDDED {
+ public:
+  FunctionState(HGraphBuilder* owner,
+                CompilationInfo* info,
+                TypeFeedbackOracle* oracle);
+  ~FunctionState();
+
+  CompilationInfo* compilation_info() { return compilation_info_; }
+  TypeFeedbackOracle* oracle() { return oracle_; }
+  AstContext* call_context() { return call_context_; }
+  HBasicBlock* function_return() { return function_return_; }
+  TestContext* test_context() { return test_context_; }
+  void ClearInlinedTestContext() {
+    delete test_context_;
+    test_context_ = NULL;
+  }
+
+ private:
+  HGraphBuilder* owner_;
+
+  CompilationInfo* compilation_info_;
+  TypeFeedbackOracle* oracle_;
+
+  // During function inlining, expression context of the call being
+  // inlined. NULL when not inlining.
+  AstContext* call_context_;
+
+  // When inlining in an effect of value context, this is the return block.
+  // It is NULL otherwise.  When inlining in a test context, there are a
+  // pair of return blocks in the context.  When not inlining, there is no
+  // local return point.
+  HBasicBlock* function_return_;
+
+  // When inlining a call in a test context, a context containing a pair of
+  // return blocks.  NULL in all other cases.
+  TestContext* test_context_;
+
+  FunctionState* outer_;
+};
+
+
 class HGraphBuilder: public AstVisitor {
  public:
-  explicit HGraphBuilder(TypeFeedbackOracle* oracle)
-      : oracle_(oracle),
+  enum BreakType { BREAK, CONTINUE };
+
+  // A class encapsulating (lazily-allocated) break and continue blocks for
+  // a breakable statement.  Separated from BreakAndContinueScope so that it
+  // can have a separate lifetime.
+  class BreakAndContinueInfo BASE_EMBEDDED {
+   public:
+    explicit BreakAndContinueInfo(BreakableStatement* target)
+      : target_(target), break_block_(NULL), continue_block_(NULL) {
+    }
+
+    BreakableStatement* target() { return target_; }
+    HBasicBlock* break_block() { return break_block_; }
+    void set_break_block(HBasicBlock* block) { break_block_ = block; }
+    HBasicBlock* continue_block() { return continue_block_; }
+    void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
+
+   private:
+    BreakableStatement* target_;
+    HBasicBlock* break_block_;
+    HBasicBlock* continue_block_;
+  };
+
+  // A helper class to maintain a stack of current BreakAndContinueInfo
+  // structures mirroring BreakableStatement nesting.
+  class BreakAndContinueScope BASE_EMBEDDED {
+   public:
+    BreakAndContinueScope(BreakAndContinueInfo* info, HGraphBuilder* owner)
+        : info_(info), owner_(owner), next_(owner->break_scope()) {
+      owner->set_break_scope(this);
+    }
+
+    ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
+
+    BreakAndContinueInfo* info() { return info_; }
+    HGraphBuilder* owner() { return owner_; }
+    BreakAndContinueScope* next() { return next_; }
+
+    // Search the break stack for a break or continue target.
+    HBasicBlock* Get(BreakableStatement* stmt, BreakType type);
+
+   private:
+    BreakAndContinueInfo* info_;
+    HGraphBuilder* owner_;
+    BreakAndContinueScope* next_;
+  };
+
+  HGraphBuilder(CompilationInfo* info, TypeFeedbackOracle* oracle)
+      : function_state_(NULL),
+        initial_function_state_(this, info, oracle),
+        ast_context_(NULL),
+        break_scope_(NULL),
         graph_(NULL),
         current_subgraph_(NULL),
-        peeled_statement_(NULL),
-        ast_context_(NULL),
-        call_context_(NULL),
-        function_return_(NULL),
-        inlined_count_(0) { }
+        inlined_count_(0) {
+    // This is not initialized in the initializer list because the
+    // constructor for the initial state relies on function_state_ == NULL
+    // to know it's the initial state.
+    function_state_= &initial_function_state_;
+  }
 
-  HGraph* CreateGraph(CompilationInfo* info);
+  HGraph* CreateGraph();
 
   // Simple accessors.
   HGraph* graph() const { return graph_; }
   HSubgraph* subgraph() const { return current_subgraph_; }
+  BreakAndContinueScope* break_scope() const { return break_scope_; }
+  void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
 
-  HEnvironment* environment() const { return subgraph()->environment(); }
-  HBasicBlock* CurrentBlock() const { return subgraph()->exit_block(); }
+  HBasicBlock* current_block() const { return subgraph()->exit_block(); }
+  void set_current_block(HBasicBlock* block) {
+    subgraph()->set_exit_block(block);
+  }
+  HEnvironment* environment() const {
+    return current_block()->last_environment();
+  }
 
   // Adding instructions.
   HInstruction* AddInstruction(HInstruction* instr);
@@ -648,8 +674,7 @@
 
  private:
   // Type of a member function that generates inline code for a native function.
-  typedef void (HGraphBuilder::*InlineFunctionGenerator)(int argument_count,
-                                                         int ast_id);
+  typedef void (HGraphBuilder::*InlineFunctionGenerator)(CallRuntime* call);
 
   // Forward declarations for inner scope classes.
   class SubgraphScope;
@@ -665,15 +690,34 @@
   static const int kMaxSourceSize = 600;
 
   // Simple accessors.
-  TypeFeedbackOracle* oracle() const { return oracle_; }
+  FunctionState* function_state() const { return function_state_; }
+  void set_function_state(FunctionState* state) { function_state_ = state; }
+
   AstContext* ast_context() const { return ast_context_; }
   void set_ast_context(AstContext* context) { ast_context_ = context; }
-  AstContext* call_context() const { return call_context_; }
-  HBasicBlock* function_return() const { return function_return_; }
+
+  // Accessors forwarded to the function state.
+  CompilationInfo* info() const {
+    return function_state()->compilation_info();
+  }
+  TypeFeedbackOracle* oracle() const { return function_state()->oracle(); }
+
+  AstContext* call_context() const {
+    return function_state()->call_context();
+  }
+  HBasicBlock* function_return() const {
+    return function_state()->function_return();
+  }
+  TestContext* inlined_test_context() const {
+    return function_state()->test_context();
+  }
+  void ClearInlinedTestContext() {
+    function_state()->ClearInlinedTestContext();
+  }
 
   // Generators for inline runtime functions.
 #define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize)      \
-  void Generate##Name(int argument_count, int ast_id);
+  void Generate##Name(CallRuntime* call);
 
   INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
   INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
@@ -681,10 +725,30 @@
 
   void Bailout(const char* reason);
 
-  void AppendPeeledWhile(IterationStatement* stmt,
-                         HSubgraph* cond_graph,
-                         HSubgraph* body_graph,
-                         HSubgraph* exit_graph);
+  void PreProcessOsrEntry(IterationStatement* statement);
+  // True iff. we are compiling for OSR and the statement is the entry.
+  bool HasOsrEntryAt(IterationStatement* statement);
+
+  HBasicBlock* CreateJoin(HBasicBlock* first,
+                          HBasicBlock* second,
+                          int join_id);
+
+  // Create a back edge in the flow graph.  body_exit is the predecessor
+  // block and loop_entry is the successor block.  loop_successor is the
+  // block where control flow exits the loop normally (e.g., via failure of
+  // the condition) and break_block is the block where control flow breaks
+  // from the loop.  All blocks except loop_entry can be NULL.  The return
+  // value is the new successor block which is the join of loop_successor
+  // and break_block, or NULL.
+  HBasicBlock* CreateLoop(IterationStatement* statement,
+                          HBasicBlock* loop_entry,
+                          HBasicBlock* body_exit,
+                          HBasicBlock* loop_successor,
+                          HBasicBlock* break_block);
+
+  HBasicBlock* JoinContinue(IterationStatement* statement,
+                            HBasicBlock* exit_block,
+                            HBasicBlock* continue_block);
 
   void AddToSubgraph(HSubgraph* graph, ZoneList<Statement*>* stmts);
   void AddToSubgraph(HSubgraph* graph, Statement* stmt);
@@ -700,17 +764,21 @@
                        HBasicBlock* true_block,
                        HBasicBlock* false_block);
 
-  // Visit an argument subexpression.
+  // Visit an argument subexpression and emit a push to the outgoing
+  // arguments.
   void VisitArgument(Expression* expr);
   void VisitArgumentList(ZoneList<Expression*>* arguments);
 
+  // Visit a list of expressions from left to right, each in a value context.
+  void VisitExpressions(ZoneList<Expression*>* exprs);
+
   void AddPhi(HPhi* phi);
 
   void PushAndAdd(HInstruction* instr);
 
   // Remove the arguments from the bailout environment and emit instructions
   // to push them as outgoing parameters.
-  void PreProcessCall(HCall* call);
+  template <int V> HInstruction* PreProcessCall(HCall<V>* call);
 
   void AssumeRepresentation(HValue* value, Representation r);
   static Representation ToRepresentation(TypeInfo info);
@@ -722,13 +790,10 @@
   AST_NODE_LIST(DECLARE_VISIT)
 #undef DECLARE_VISIT
 
-  bool ShouldPeel(HSubgraph* cond, HSubgraph* body);
-
   HBasicBlock* CreateBasicBlock(HEnvironment* env);
   HSubgraph* CreateEmptySubgraph();
-  HSubgraph* CreateGotoSubgraph(HEnvironment* env);
   HSubgraph* CreateBranchSubgraph(HEnvironment* env);
-  HSubgraph* CreateLoopHeaderSubgraph(HEnvironment* env);
+  HBasicBlock* CreateLoopHeaderBlock();
   HSubgraph* CreateInlinedSubgraph(HEnvironment* outer,
                                    Handle<JSFunction> target,
                                    FunctionLiteral* function);
@@ -745,7 +810,11 @@
                                 HValue* receiver,
                                 Handle<Map> receiver_map,
                                 CheckType check_type);
-  void TraceInline(Handle<JSFunction> target, bool result);
+
+  // If --trace-inlining, print a line of the inlining trace.  Inlining
+  // succeeded if the reason string is NULL and failed if there is a
+  // non-NULL reason string.
+  void TraceInline(Handle<JSFunction> target, const char* failure_reason);
 
   void HandleGlobalVariableAssignment(Variable* var,
                                       HValue* value,
@@ -814,6 +883,11 @@
                                            HValue* val,
                                            Expression* expr);
 
+  HInstruction* BuildStoreKeyedPixelArrayElement(HValue* object,
+                                                 HValue* key,
+                                                 HValue* val,
+                                                 Expression* expr);
+
   HCompare* BuildSwitchCompare(HSubgraph* subgraph,
                                HValue* switch_value,
                                CaseClause* clause);
@@ -826,30 +900,31 @@
                                 bool smi_and_map_check);
 
 
-  HBasicBlock* BuildTypeSwitch(ZoneMapList* maps,
-                               ZoneList<HSubgraph*>* subgraphs,
-                               HValue* receiver,
+  HBasicBlock* BuildTypeSwitch(HValue* receiver,
+                               ZoneMapList* maps,
+                               ZoneList<HSubgraph*>* body_graphs,
+                               HSubgraph* default_graph,
                                int join_id);
 
-  TypeFeedbackOracle* oracle_;
-  HGraph* graph_;
-  HSubgraph* current_subgraph_;
-  IterationStatement* peeled_statement_;
+  // The translation state of the currently-being-translated function.
+  FunctionState* function_state_;
+
+  // The base of the function state stack.
+  FunctionState initial_function_state_;
+
   // Expression context of the currently visited subexpression. NULL when
   // visiting statements.
   AstContext* ast_context_;
 
-  // During function inlining, expression context of the call being
-  // inlined. NULL when not inlining.
-  AstContext* call_context_;
+  // A stack of breakable statements entered.
+  BreakAndContinueScope* break_scope_;
 
-  // When inlining a call in an effect or value context, the return
-  // block. NULL otherwise. When inlining a call in a test context, there
-  // are a pair of target blocks in the call context.
-  HBasicBlock* function_return_;
+  HGraph* graph_;
+  HSubgraph* current_subgraph_;
 
   int inlined_count_;
 
+  friend class FunctionState;  // Pushes and pops the state stack.
   friend class AstContext;  // Pushes and pops the AST context stack.
 
   DISALLOW_COPY_AND_ASSIGN(HGraphBuilder);
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index e4d09f2..6652df2 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -2607,8 +2607,8 @@
 }
 
 
-void Assembler::RecordComment(const char* msg) {
-  if (FLAG_code_comments) {
+void Assembler::RecordComment(const char* msg, bool force) {
+  if (FLAG_code_comments || force) {
     EnsureSpace ensure_space(this);
     RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
   }
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index 11f324e..b60157c 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -183,13 +183,6 @@
 typedef XMMRegister DoubleRegister;
 
 
-// Index of register used in pusha/popa.
-// Order of pushed registers: EAX, ECX, EDX, EBX, ESP, EBP, ESI, and EDI
-inline int EspIndexForPushAll(Register reg) {
-  return Register::kNumRegisters - 1 - reg.code();
-}
-
-
 enum Condition {
   // any value < 0 is considered no_condition
   no_condition  = -1,
@@ -957,8 +950,9 @@
   void RecordDebugBreakSlot();
 
   // Record a comment relocation entry that can be used by a disassembler.
-  // Use --code-comments to enable.
-  void RecordComment(const char* msg);
+  // Use --code-comments to enable, or provide "force = true" flag to always
+  // write a comment.
+  void RecordComment(const char* msg, bool force = false);
 
   // Writes a single byte or word of data in the code stream.  Used for
   // inline tables, e.g., jump-tables.
@@ -979,6 +973,10 @@
 
   PositionsRecorder* positions_recorder() { return &positions_recorder_; }
 
+  int relocation_writer_size() {
+    return (buffer_ + buffer_size_) - reloc_info_writer.pos();
+  }
+
   // Avoid overflows for displacements etc.
   static const int kMaximalBufferSize = 512*MB;
   static const int kMinimalBufferSize = 4*KB;
diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
index 0a3e093..c7e5527 100644
--- a/src/ia32/builtins-ia32.cc
+++ b/src/ia32/builtins-ia32.cc
@@ -589,6 +589,13 @@
     // Change context eagerly in case we need the global receiver.
     __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
 
+    // Do not transform the receiver for strict mode functions.
+    __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+    __ test_b(FieldOperand(ebx, SharedFunctionInfo::kStrictModeByteOffset),
+              1 << SharedFunctionInfo::kStrictModeBitWithinByte);
+    __ j(not_equal, &shift_arguments);
+
+    // Compute the receiver in non-strict mode.
     __ mov(ebx, Operand(esp, eax, times_4, 0));  // First argument.
     __ test(ebx, Immediate(kSmiTagMask));
     __ j(zero, &convert_to_object);
@@ -736,6 +743,14 @@
   // Compute the receiver.
   Label call_to_object, use_global_receiver, push_receiver;
   __ mov(ebx, Operand(ebp, 3 * kPointerSize));
+
+  // Do not transform the receiver for strict mode functions.
+  __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+  __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset),
+            1 << SharedFunctionInfo::kStrictModeBitWithinByte);
+  __ j(not_equal, &push_receiver);
+
+  // Compute the receiver in non-strict mode.
   __ test(ebx, Immediate(kSmiTagMask));
   __ j(zero, &call_to_object);
   __ cmp(ebx, Factory::null_value());
@@ -1233,11 +1248,9 @@
   Label generic_constructor;
 
   if (FLAG_debug_code) {
-    // The array construct code is only set for the builtin Array function which
-    // does always have a map.
-    __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ebx);
-    __ cmp(edi, Operand(ebx));
-    __ Assert(equal, "Unexpected Array function");
+    // The array construct code is only set for the global and natives
+    // builtin Array functions which always have maps.
+
     // Initial map for the builtin Array function should be a map.
     __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
     // Will both indicate a NULL and a Smi.
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 7d70ac3..7efa934 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -2385,14 +2385,14 @@
 
 
 void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
-  NearLabel call_runtime;
+  ASSERT(op_ == Token::ADD);
+  NearLabel left_not_string, call_runtime;
 
   // Registers containing left and right operands respectively.
   Register left = edx;
   Register right = eax;
 
   // Test if left operand is a string.
-  NearLabel left_not_string;
   __ test(left, Immediate(kSmiTagMask));
   __ j(zero, &left_not_string);
   __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx);
@@ -3399,7 +3399,7 @@
   __ test(edx, Immediate(kSmiTagMask));
   __ j(not_zero, &base_nonsmi);
 
-  // Optimized version when both exponent and base is a smi.
+  // Optimized version when both exponent and base are smis.
   Label powi;
   __ SmiUntag(edx);
   __ cvtsi2sd(xmm0, Operand(edx));
@@ -3438,7 +3438,6 @@
   __ j(not_carry, &no_multiply);
   __ mulsd(xmm1, xmm0);
   __ bind(&no_multiply);
-  __ test(eax, Operand(eax));
   __ mulsd(xmm0, xmm0);
   __ j(not_zero, &while_true);
 
@@ -3525,7 +3524,7 @@
   __ AllocateHeapNumber(ecx, eax, edx, &call_runtime);
   __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm1);
   __ mov(eax, ecx);
-  __ ret(2);
+  __ ret(2 * kPointerSize);
 
   __ bind(&call_runtime);
   __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1);
@@ -3887,7 +3886,7 @@
   __ IncrementCounter(&Counters::regexp_entry_native, 1);
 
   static const int kRegExpExecuteArguments = 7;
-  __ PrepareCallCFunction(kRegExpExecuteArguments, ecx);
+  __ EnterApiExitFrame(kRegExpExecuteArguments);
 
   // Argument 7: Indicate that this is a direct call from JavaScript.
   __ mov(Operand(esp, 6 * kPointerSize), Immediate(1));
@@ -3932,7 +3931,10 @@
 
   // Locate the code entry and call it.
   __ add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag));
-  __ CallCFunction(edx, kRegExpExecuteArguments);
+  __ call(Operand(edx));
+
+  // Drop arguments and come back to JS mode.
+  __ LeaveApiExitFrame();
 
   // Check the result.
   Label success;
@@ -3949,12 +3951,30 @@
   // haven't created the exception yet. Handle that in the runtime system.
   // TODO(592): Rerunning the RegExp to get the stack overflow exception.
   ExternalReference pending_exception(Top::k_pending_exception_address);
-  __ mov(eax,
+  __ mov(edx,
          Operand::StaticVariable(ExternalReference::the_hole_value_location()));
-  __ cmp(eax, Operand::StaticVariable(pending_exception));
+  __ mov(eax, Operand::StaticVariable(pending_exception));
+  __ cmp(edx, Operand(eax));
   __ j(equal, &runtime);
+  // For exception, throw the exception again.
+
+  // Clear the pending exception variable.
+  __ mov(Operand::StaticVariable(pending_exception), edx);
+
+  // Special handling of termination exceptions which are uncatchable
+  // by javascript code.
+  __ cmp(eax, Factory::termination_exception());
+  Label throw_termination_exception;
+  __ j(equal, &throw_termination_exception);
+
+  // Handle normal exception by following handler chain.
+  __ Throw(eax);
+
+  __ bind(&throw_termination_exception);
+  __ ThrowUncatchable(TERMINATION, eax);
+
   __ bind(&failure);
-  // For failure and exception return null.
+  // For failure to match, return null.
   __ mov(Operand(eax), Factory::null_value());
   __ ret(4 * kPointerSize);
 
@@ -4628,34 +4648,7 @@
 
 
 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
-  // eax holds the exception.
-
-  // Adjust this code if not the case.
-  STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
-
-  // Drop the sp to the top of the handler.
-  ExternalReference handler_address(Top::k_handler_address);
-  __ mov(esp, Operand::StaticVariable(handler_address));
-
-  // Restore next handler and frame pointer, discard handler state.
-  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
-  __ pop(Operand::StaticVariable(handler_address));
-  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize);
-  __ pop(ebp);
-  __ pop(edx);  // Remove state.
-
-  // Before returning we restore the context from the frame pointer if
-  // not NULL.  The frame pointer is NULL in the exception handler of
-  // a JS entry frame.
-  __ Set(esi, Immediate(0));  // Tentatively set context pointer to NULL.
-  NearLabel skip;
-  __ cmp(ebp, 0);
-  __ j(equal, &skip, not_taken);
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-  __ bind(&skip);
-
-  STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
-  __ ret(0);
+  __ Throw(eax);
 }
 
 
@@ -4778,52 +4771,7 @@
 
 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm,
                                           UncatchableExceptionType type) {
-  // Adjust this code if not the case.
-  STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
-
-  // Drop sp to the top stack handler.
-  ExternalReference handler_address(Top::k_handler_address);
-  __ mov(esp, Operand::StaticVariable(handler_address));
-
-  // Unwind the handlers until the ENTRY handler is found.
-  NearLabel loop, done;
-  __ bind(&loop);
-  // Load the type of the current stack handler.
-  const int kStateOffset = StackHandlerConstants::kStateOffset;
-  __ cmp(Operand(esp, kStateOffset), Immediate(StackHandler::ENTRY));
-  __ j(equal, &done);
-  // Fetch the next handler in the list.
-  const int kNextOffset = StackHandlerConstants::kNextOffset;
-  __ mov(esp, Operand(esp, kNextOffset));
-  __ jmp(&loop);
-  __ bind(&done);
-
-  // Set the top handler address to next handler past the current ENTRY handler.
-  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
-  __ pop(Operand::StaticVariable(handler_address));
-
-  if (type == OUT_OF_MEMORY) {
-    // Set external caught exception to false.
-    ExternalReference external_caught(Top::k_external_caught_exception_address);
-    __ mov(eax, false);
-    __ mov(Operand::StaticVariable(external_caught), eax);
-
-    // Set pending exception and eax to out of memory exception.
-    ExternalReference pending_exception(Top::k_pending_exception_address);
-    __ mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
-    __ mov(Operand::StaticVariable(pending_exception), eax);
-  }
-
-  // Clear the context pointer.
-  __ Set(esi, Immediate(0));
-
-  // Restore fp from handler and discard handler state.
-  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize);
-  __ pop(ebp);
-  __ pop(edx);  // State.
-
-  STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
-  __ ret(0);
+  __ ThrowUncatchable(type, eax);
 }
 
 
@@ -6559,9 +6507,19 @@
   __ mov(untagged_key, key);
   __ SmiUntag(untagged_key);
 
-  // Verify that the receiver has pixel array elements.
   __ mov(elements, FieldOperand(receiver, JSObject::kElementsOffset));
-  __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true);
+  // By passing NULL as not_pixel_array, callers signal that they have already
+  // verified that the receiver has pixel array elements.
+  if (not_pixel_array != NULL) {
+    __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true);
+  } else {
+    if (FLAG_debug_code) {
+      // Map check should have already made sure that elements is a pixel array.
+      __ cmp(FieldOperand(elements, HeapObject::kMapOffset),
+             Immediate(Factory::pixel_array_map()));
+      __ Assert(equal, "Elements isn't a pixel array");
+    }
+  }
 
   // Key must be in range.
   __ cmp(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset));
@@ -6575,6 +6533,90 @@
 }
 
 
+// Stores an indexed element into a pixel array, clamping the stored value.
+void GenerateFastPixelArrayStore(MacroAssembler* masm,
+                                 Register receiver,
+                                 Register key,
+                                 Register value,
+                                 Register elements,
+                                 Register scratch1,
+                                 bool load_elements_from_receiver,
+                                 Label* key_not_smi,
+                                 Label* value_not_smi,
+                                 Label* not_pixel_array,
+                                 Label* out_of_range) {
+  // Register use:
+  //   receiver - holds the receiver and is unchanged unless the
+  //              store succeeds.
+  //   key - holds the key (must be a smi) and is unchanged.
+  //   value - holds the value (must be a smi) and is unchanged.
+  //   elements - holds the element object of the receiver on entry if
+  //              load_elements_from_receiver is false, otherwise used
+  //              internally to store the pixel arrays elements and
+  //              external array pointer.
+  //
+  // receiver, key and value remain unmodified until it's guaranteed that the
+  // store will succeed.
+  Register external_pointer = elements;
+  Register untagged_key = scratch1;
+  Register untagged_value = receiver;  // Only set once success guaranteed.
+
+  // Fetch the receiver's elements if the caller hasn't already done so.
+  if (load_elements_from_receiver) {
+    __ mov(elements, FieldOperand(receiver, JSObject::kElementsOffset));
+  }
+
+  // By passing NULL as not_pixel_array, callers signal that they have already
+  // verified that the receiver has pixel array elements.
+  if (not_pixel_array != NULL) {
+    __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true);
+  } else {
+    if (FLAG_debug_code) {
+      // Map check should have already made sure that elements is a pixel array.
+      __ cmp(FieldOperand(elements, HeapObject::kMapOffset),
+             Immediate(Factory::pixel_array_map()));
+      __ Assert(equal, "Elements isn't a pixel array");
+    }
+  }
+
+  // Some callers already have verified that the key is a smi.  key_not_smi is
+  // set to NULL as a sentinel for that case.  Otherwise, add an explicit check
+  // to ensure the key is a smi must be added.
+  if (key_not_smi != NULL) {
+    __ JumpIfNotSmi(key, key_not_smi);
+  } else {
+    if (FLAG_debug_code) {
+      __ AbortIfNotSmi(key);
+    }
+  }
+
+  // Key must be a smi and it must be in range.
+  __ mov(untagged_key, key);
+  __ SmiUntag(untagged_key);
+  __ cmp(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset));
+  __ j(above_equal, out_of_range);  // unsigned check handles negative keys.
+
+  // Value must be a smi.
+  __ JumpIfNotSmi(value, value_not_smi);
+  __ mov(untagged_value, value);
+  __ SmiUntag(untagged_value);
+
+  {  // Clamp the value to [0..255].
+    NearLabel done;
+    __ test(untagged_value, Immediate(0xFFFFFF00));
+    __ j(zero, &done);
+    __ setcc(negative, untagged_value);  // 1 if negative, 0 if positive.
+    __ dec_b(untagged_value);  // 0 if negative, 255 if positive.
+    __ bind(&done);
+  }
+
+  __ mov(external_pointer,
+         FieldOperand(elements, PixelArray::kExternalPointerOffset));
+  __ mov_b(Operand(external_pointer, untagged_key, times_1, 0), untagged_value);
+  __ ret(0);  // Return value in eax.
+}
+
+
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/ia32/code-stubs-ia32.h b/src/ia32/code-stubs-ia32.h
index 2064574..4a1119a 100644
--- a/src/ia32/code-stubs-ia32.h
+++ b/src/ia32/code-stubs-ia32.h
@@ -45,8 +45,8 @@
     UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits
   };
 
-  explicit TranscendentalCacheStub(TranscendentalCache::Type type,
-                                   ArgumentType argument_type)
+  TranscendentalCacheStub(TranscendentalCache::Type type,
+                          ArgumentType argument_type)
       : type_(type), argument_type_(argument_type) {}
   void Generate(MacroAssembler* masm);
  private:
@@ -490,14 +490,14 @@
 };
 
 
-// Generate code the to load an element from a pixel array. The receiver is
-// assumed to not be a smi and to have elements, the caller must guarantee this
-// precondition. If the receiver does not have elements that are pixel arrays,
-// the generated code jumps to not_pixel_array. If key is not a smi, then the
-// generated code branches to key_not_smi. Callers can specify NULL for
-// key_not_smi to signal that a smi check has already been performed on key so
-// that the smi check is not generated . If key is not a valid index within the
-// bounds of the pixel array, the generated code jumps to out_of_range.
+// Generate code to load an element from a pixel array. The receiver is assumed
+// to not be a smi and to have elements, the caller must guarantee this
+// precondition. If key is not a smi, then the generated code branches to
+// key_not_smi. Callers can specify NULL for key_not_smi to signal that a smi
+// check has already been performed on key so that the smi check is not
+// generated. If key is not a valid index within the bounds of the pixel array,
+// the generated code jumps to out_of_range. receiver, key and elements are
+// unchanged throughout the generated code sequence.
 void GenerateFastPixelArrayLoad(MacroAssembler* masm,
                                 Register receiver,
                                 Register key,
@@ -508,6 +508,28 @@
                                 Label* key_not_smi,
                                 Label* out_of_range);
 
+// Generate code to store an element into a pixel array, clamping values between
+// [0..255]. The receiver is assumed to not be a smi and to have elements, the
+// caller must guarantee this precondition. If key is not a smi, then the
+// generated code branches to key_not_smi. Callers can specify NULL for
+// key_not_smi to signal that a smi check has already been performed on key so
+// that the smi check is not generated. If the value is not a smi, the generated
+// code will branch to value_not_smi.  If the receiver doesn't have pixel array
+// elements, the generated code will branch to not_pixel_array, unless
+// not_pixel_array is NULL, in which case the caller must ensure that the
+// receiver has pixel array elements.  If key is not a valid index within the
+// bounds of the pixel array, the generated code jumps to out_of_range.
+void GenerateFastPixelArrayStore(MacroAssembler* masm,
+                                 Register receiver,
+                                 Register key,
+                                 Register value,
+                                 Register elements,
+                                 Register scratch1,
+                                 bool load_elements_from_receiver,
+                                 Label* key_not_smi,
+                                 Label* value_not_smi,
+                                 Label* not_pixel_array,
+                                 Label* out_of_range);
 
 } }  // namespace v8::internal
 
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index b977db8..3a2753d 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -3526,7 +3526,8 @@
   frame_->EmitPush(esi);  // The context is the first argument.
   frame_->EmitPush(Immediate(pairs));
   frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
-  Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
+  frame_->EmitPush(Immediate(Smi::FromInt(strict_mode_flag())));
+  Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 4);
   // Return value is ignored.
 }
 
@@ -5259,7 +5260,8 @@
       // by initialization.
       value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
     } else {
-      value = frame_->CallRuntime(Runtime::kStoreContextSlot, 3);
+      frame_->Push(Smi::FromInt(strict_mode_flag()));
+      value = frame_->CallRuntime(Runtime::kStoreContextSlot, 4);
     }
     // Storing a variable must keep the (new) value on the expression
     // stack. This is necessary for compiling chained assignment
@@ -5360,10 +5362,20 @@
 
 void CodeGenerator::VisitLiteral(Literal* node) {
   Comment cmnt(masm_, "[ Literal");
-  if (in_safe_int32_mode()) {
-    frame_->PushUntaggedElement(node->handle());
+  if (frame_->ConstantPoolOverflowed()) {
+    Result temp = allocator_->Allocate();
+    ASSERT(temp.is_valid());
+    if (in_safe_int32_mode()) {
+      temp.set_untagged_int32(true);
+    }
+    __ Set(temp.reg(), Immediate(node->handle()));
+    frame_->Push(&temp);
   } else {
-    frame_->Push(node->handle());
+    if (in_safe_int32_mode()) {
+      frame_->PushUntaggedElement(node->handle());
+    } else {
+      frame_->Push(node->handle());
+    }
   }
 }
 
@@ -5608,8 +5620,9 @@
           Load(property->key());
           Load(property->value());
           if (property->emit_store()) {
+            frame_->Push(Smi::FromInt(NONE));   // PropertyAttributes
             // Ignore the result.
-            Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3);
+            Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 4);
           } else {
             frame_->Drop(3);
           }
@@ -8225,21 +8238,25 @@
     if (property != NULL) {
       Load(property->obj());
       Load(property->key());
-      Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2);
+      frame_->Push(Smi::FromInt(strict_mode_flag()));
+      Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 3);
       frame_->Push(&answer);
       return;
     }
 
     Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
     if (variable != NULL) {
+      // Delete of an unqualified identifier is disallowed in strict mode
+      // but "delete this" is.
+      ASSERT(strict_mode_flag() == kNonStrictMode || variable->is_this());
       Slot* slot = variable->AsSlot();
       if (variable->is_global()) {
         LoadGlobal();
         frame_->Push(variable->name());
+        frame_->Push(Smi::FromInt(kNonStrictMode));
         Result answer = frame_->InvokeBuiltin(Builtins::DELETE,
-                                              CALL_FUNCTION, 2);
+                                              CALL_FUNCTION, 3);
         frame_->Push(&answer);
-        return;
 
       } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
         // Call the runtime to delete from the context holding the named
@@ -8250,13 +8267,11 @@
         frame_->EmitPush(Immediate(variable->name()));
         Result answer = frame_->CallRuntime(Runtime::kDeleteContextSlot, 2);
         frame_->Push(&answer);
-        return;
+      } else {
+        // Default: Result of deleting non-global, not dynamically
+        // introduced variables is false.
+        frame_->Push(Factory::false_value());
       }
-
-      // Default: Result of deleting non-global, not dynamically
-      // introduced variables is false.
-      frame_->Push(Factory::false_value());
-
     } else {
       // Default: Result of deleting expressions is true.
       Load(node->expression());  // may have side-effects
@@ -8298,6 +8313,7 @@
       switch (op) {
         case Token::SUB: {
           __ neg(value.reg());
+          frame_->Push(&value);
           if (node->no_negative_zero()) {
             // -MIN_INT is MIN_INT with the overflow flag set.
             unsafe_bailout_->Branch(overflow);
@@ -8310,17 +8326,18 @@
         }
         case Token::BIT_NOT: {
           __ not_(value.reg());
+          frame_->Push(&value);
           break;
         }
         case Token::ADD: {
           // Unary plus has no effect on int32 values.
+          frame_->Push(&value);
           break;
         }
         default:
           UNREACHABLE();
           break;
       }
-      frame_->Push(&value);
     } else {
       Load(node->expression());
       bool can_overwrite = node->expression()->ResultOverwriteAllowed();
@@ -9456,11 +9473,13 @@
   DeferredReferenceSetKeyedValue(Register value,
                                  Register key,
                                  Register receiver,
-                                 Register scratch)
+                                 Register scratch,
+                                 StrictModeFlag strict_mode)
       : value_(value),
         key_(key),
         receiver_(receiver),
-        scratch_(scratch) {
+        scratch_(scratch),
+        strict_mode_(strict_mode) {
     set_comment("[ DeferredReferenceSetKeyedValue");
   }
 
@@ -9474,6 +9493,7 @@
   Register receiver_;
   Register scratch_;
   Label patch_site_;
+  StrictModeFlag strict_mode_;
 };
 
 
@@ -9532,7 +9552,9 @@
   }
 
   // Call the IC stub.
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
+                                    : Builtins::KeyedStoreIC_Initialize));
   __ call(ic, RelocInfo::CODE_TARGET);
   // The delta from the start of the map-compare instruction to the
   // test instruction.  We use masm_-> directly here instead of the
@@ -9894,7 +9916,8 @@
         new DeferredReferenceSetKeyedValue(result.reg(),
                                            key.reg(),
                                            receiver.reg(),
-                                           tmp.reg());
+                                           tmp.reg(),
+                                           strict_mode_flag());
 
     // Check that the receiver is not a smi.
     __ test(receiver.reg(), Immediate(kSmiTagMask));
@@ -9949,7 +9972,7 @@
 
     deferred->BindExit();
   } else {
-    result = frame()->CallKeyedStoreIC();
+    result = frame()->CallKeyedStoreIC(strict_mode_flag());
     // Make sure that we do not have a test instruction after the
     // call.  A test instruction after the call is used to
     // indicate that we have generated an inline version of the
diff --git a/src/ia32/deoptimizer-ia32.cc b/src/ia32/deoptimizer-ia32.cc
index a646052..5f4d944 100644
--- a/src/ia32/deoptimizer-ia32.cc
+++ b/src/ia32/deoptimizer-ia32.cc
@@ -80,6 +80,7 @@
   Address prev_address = code_start_address;
   for (unsigned i = 0; i < table.length(); ++i) {
     Address curr_address = code_start_address + table.GetPcOffset(i);
+    ASSERT_GE(curr_address, prev_address);
     ZapCodeRange(prev_address, curr_address);
 
     SafepointEntry safepoint_entry = table.GetEntry(i);
@@ -97,7 +98,8 @@
                       RelocInfo::RUNTIME_ENTRY,
                       reinterpret_cast<intptr_t>(deopt_entry));
       reloc_info_writer.Write(&rinfo);
-
+      ASSERT_GE(reloc_info_writer.pos(),
+                reloc_info->address() + ByteArray::kHeaderSize);
       curr_address += patch_size();
     }
     prev_address = curr_address;
@@ -137,39 +139,39 @@
 void Deoptimizer::PatchStackCheckCodeAt(Address pc_after,
                                         Code* check_code,
                                         Code* replacement_code) {
-    Address call_target_address = pc_after - kPointerSize;
-    ASSERT(check_code->entry() ==
-           Assembler::target_address_at(call_target_address));
-    // The stack check code matches the pattern:
-    //
-    //     cmp esp, <limit>
-    //     jae ok
-    //     call <stack guard>
-    //     test eax, <loop nesting depth>
-    // ok: ...
-    //
-    // We will patch away the branch so the code is:
-    //
-    //     cmp esp, <limit>  ;; Not changed
-    //     nop
-    //     nop
-    //     call <on-stack replacment>
-    //     test eax, <loop nesting depth>
-    // ok:
-    ASSERT(*(call_target_address - 3) == 0x73 &&  // jae
-           *(call_target_address - 2) == 0x07 &&  // offset
-           *(call_target_address - 1) == 0xe8);   // call
-    *(call_target_address - 3) = 0x90;  // nop
-    *(call_target_address - 2) = 0x90;  // nop
-    Assembler::set_target_address_at(call_target_address,
-                                     replacement_code->entry());
+  Address call_target_address = pc_after - kIntSize;
+  ASSERT(check_code->entry() ==
+         Assembler::target_address_at(call_target_address));
+  // The stack check code matches the pattern:
+  //
+  //     cmp esp, <limit>
+  //     jae ok
+  //     call <stack guard>
+  //     test eax, <loop nesting depth>
+  // ok: ...
+  //
+  // We will patch away the branch so the code is:
+  //
+  //     cmp esp, <limit>  ;; Not changed
+  //     nop
+  //     nop
+  //     call <on-stack replacment>
+  //     test eax, <loop nesting depth>
+  // ok:
+  ASSERT(*(call_target_address - 3) == 0x73 &&  // jae
+         *(call_target_address - 2) == 0x07 &&  // offset
+         *(call_target_address - 1) == 0xe8);   // call
+  *(call_target_address - 3) = 0x90;  // nop
+  *(call_target_address - 2) = 0x90;  // nop
+  Assembler::set_target_address_at(call_target_address,
+                                   replacement_code->entry());
 }
 
 
 void Deoptimizer::RevertStackCheckCodeAt(Address pc_after,
                                          Code* check_code,
                                          Code* replacement_code) {
-  Address call_target_address = pc_after - kPointerSize;
+  Address call_target_address = pc_after - kIntSize;
   ASSERT(replacement_code->entry() ==
          Assembler::target_address_at(call_target_address));
   // Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to
@@ -429,14 +431,16 @@
            fp_value, output_offset, value);
   }
 
-  // The context can be gotten from the function so long as we don't
-  // optimize functions that need local contexts.
+  // For the bottommost output frame the context can be gotten from the input
+  // frame. For all subsequent output frames it can be gotten from the function
+  // so long as we don't inline functions that need local contexts.
   output_offset -= kPointerSize;
   input_offset -= kPointerSize;
-  value = reinterpret_cast<uint32_t>(function->context());
-  // The context for the bottommost output frame should also agree with the
-  // input frame.
-  ASSERT(!is_bottommost || input_->GetFrameSlot(input_offset) == value);
+  if (is_bottommost) {
+    value = input_->GetFrameSlot(input_offset);
+  } else {
+    value = reinterpret_cast<uint32_t>(function->context());
+  }
   output_frame->SetFrameSlot(output_offset, value);
   if (is_topmost) output_frame->SetRegister(esi.code(), value);
   if (FLAG_trace_deopt) {
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 18c9319..9a7d41a 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -322,22 +322,6 @@
 }
 
 
-FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand(
-    Token::Value op, Expression* left, Expression* right) {
-  ASSERT(ShouldInlineSmiCase(op));
-  if (op == Token::DIV || op == Token::MOD || op == Token::MUL) {
-    // We never generate inlined constant smi operations for these.
-    return kNoConstants;
-  } else if (right->IsSmiLiteral()) {
-    return kRightConstant;
-  } else if (left->IsSmiLiteral() && !Token::IsShiftOp(op)) {
-    return kLeftConstant;
-  } else {
-    return kNoConstants;
-  }
-}
-
-
 void FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
 }
 
@@ -547,7 +531,7 @@
   __ j(equal, if_true);
   __ cmp(result_register(), Factory::false_value());
   __ j(equal, if_false);
-  ASSERT_EQ(0, kSmiTag);
+  STATIC_ASSERT(kSmiTag == 0);
   __ test(result_register(), Operand(result_register()));
   __ j(zero, if_false);
   __ test(result_register(), Immediate(kSmiTagMask));
@@ -654,6 +638,7 @@
   ASSERT(variable != NULL);  // Must have been resolved.
   Slot* slot = variable->AsSlot();
   Property* prop = variable->AsProperty();
+
   if (slot != NULL) {
     switch (slot->type()) {
       case Slot::PARAMETER:
@@ -739,7 +724,9 @@
              prop->key()->AsLiteral()->handle()->IsSmi());
       __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle()));
 
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(is_strict()
+          ? Builtins::KeyedStoreIC_Initialize_Strict
+          : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
     }
   }
@@ -756,7 +743,8 @@
   __ push(esi);  // The context is the first argument.
   __ push(Immediate(pairs));
   __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
-  __ CallRuntime(Runtime::kDeclareGlobals, 3);
+  __ push(Immediate(Smi::FromInt(strict_mode_flag())));
+  __ CallRuntime(Runtime::kDeclareGlobals, 4);
   // Return value is ignored.
 }
 
@@ -813,7 +801,6 @@
     SetSourcePosition(clause->position());
     Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
     EmitCallIC(ic, &patch_site);
-
     __ test(eax, Operand(eax));
     __ j(not_equal, &next_test);
     __ Drop(1);  // Switch value is no longer needed.
@@ -894,7 +881,7 @@
   __ cmp(edx, Factory::empty_descriptor_array());
   __ j(equal, &call_runtime);
 
-  // Check that there in an enum cache in the non-empty instance
+  // Check that there is an enum cache in the non-empty instance
   // descriptors (edx).  This is the case if the next enumeration
   // index field does not contain a smi.
   __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset));
@@ -1379,7 +1366,9 @@
             VisitForAccumulatorValue(value);
             __ mov(ecx, Immediate(key->handle()));
             __ mov(edx, Operand(esp, 0));
-            Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+            Handle<Code> ic(Builtins::builtin(
+                is_strict() ? Builtins::StoreIC_Initialize_Strict
+                            : Builtins::StoreIC_Initialize));
             EmitCallIC(ic, RelocInfo::CODE_TARGET);
             PrepareForBailoutForId(key->id(), NO_REGISTERS);
           } else {
@@ -1393,7 +1382,8 @@
         VisitForStackValue(key);
         VisitForStackValue(value);
         if (property->emit_store()) {
-          __ CallRuntime(Runtime::kSetProperty, 3);
+          __ push(Immediate(Smi::FromInt(NONE)));  // PropertyAttributes
+          __ CallRuntime(Runtime::kSetProperty, 4);
         } else {
           __ Drop(3);
         }
@@ -1571,14 +1561,8 @@
     }
 
     Token::Value op = expr->binary_op();
-    ConstantOperand constant = ShouldInlineSmiCase(op)
-        ? GetConstantOperand(op, expr->target(), expr->value())
-        : kNoConstants;
-    ASSERT(constant == kRightConstant || constant == kNoConstants);
-    if (constant == kNoConstants) {
-      __ push(eax);  // Left operand goes on the stack.
-      VisitForAccumulatorValue(expr->value());
-    }
+    __ push(eax);  // Left operand goes on the stack.
+    VisitForAccumulatorValue(expr->value());
 
     OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
         ? OVERWRITE_RIGHT
@@ -1590,8 +1574,7 @@
                             op,
                             mode,
                             expr->target(),
-                            expr->value(),
-                            constant);
+                            expr->value());
     } else {
       EmitBinaryOp(op, mode);
     }
@@ -1639,214 +1622,11 @@
 }
 
 
-void FullCodeGenerator::EmitConstantSmiAdd(Expression* expr,
-                                           OverwriteMode mode,
-                                           bool left_is_constant_smi,
-                                           Smi* value) {
-  NearLabel call_stub, done;
-  __ add(Operand(eax), Immediate(value));
-  __ j(overflow, &call_stub);
-  JumpPatchSite patch_site(masm_);
-  patch_site.EmitJumpIfSmi(eax, &done);
-
-  // Undo the optimistic add operation and call the shared stub.
-  __ bind(&call_stub);
-  __ sub(Operand(eax), Immediate(value));
-  Token::Value op = Token::ADD;
-  TypeRecordingBinaryOpStub stub(op, mode);
-  if (left_is_constant_smi) {
-    __ mov(edx, Immediate(value));
-  } else {
-    __ mov(edx, eax);
-    __ mov(eax, Immediate(value));
-  }
-  EmitCallIC(stub.GetCode(), &patch_site);
-
-  __ bind(&done);
-  context()->Plug(eax);
-}
-
-
-void FullCodeGenerator::EmitConstantSmiSub(Expression* expr,
-                                           OverwriteMode mode,
-                                           bool left_is_constant_smi,
-                                           Smi* value) {
-  NearLabel call_stub, done;
-  if (left_is_constant_smi) {
-    __ mov(ecx, eax);
-    __ mov(eax, Immediate(value));
-    __ sub(Operand(eax), ecx);
-  } else {
-    __ sub(Operand(eax), Immediate(value));
-  }
-  __ j(overflow, &call_stub);
-  JumpPatchSite patch_site(masm_);
-  patch_site.EmitJumpIfSmi(eax, &done);
-
-  __ bind(&call_stub);
-  if (left_is_constant_smi) {
-    __ mov(edx, Immediate(value));
-    __ mov(eax, ecx);
-  } else {
-    __ add(Operand(eax), Immediate(value));  // Undo the subtraction.
-    __ mov(edx, eax);
-    __ mov(eax, Immediate(value));
-  }
-  Token::Value op = Token::SUB;
-  TypeRecordingBinaryOpStub stub(op, mode);
-  EmitCallIC(stub.GetCode(), &patch_site);
-
-  __ bind(&done);
-  context()->Plug(eax);
-}
-
-
-void FullCodeGenerator::EmitConstantSmiShiftOp(Expression* expr,
-                                               Token::Value op,
-                                               OverwriteMode mode,
-                                               Smi* value) {
-  NearLabel call_stub, smi_case, done;
-  int shift_value = value->value() & 0x1f;
-
-  JumpPatchSite patch_site(masm_);
-  patch_site.EmitJumpIfSmi(eax, &smi_case);
-
-  // Call stub.
-  __ bind(&call_stub);
-  __ mov(edx, eax);
-  __ mov(eax, Immediate(value));
-  TypeRecordingBinaryOpStub stub(op, mode);
-  EmitCallIC(stub.GetCode(), &patch_site);
-  __ jmp(&done);
-
-  // Smi case.
-  __ bind(&smi_case);
-  switch (op) {
-    case Token::SHL:
-      if (shift_value != 0) {
-        __ mov(edx, eax);
-        if (shift_value > 1) {
-          __ shl(edx, shift_value - 1);
-        }
-        // Convert int result to smi, checking that it is in int range.
-        ASSERT(kSmiTagSize == 1);  // Adjust code if not the case.
-        __ add(edx, Operand(edx));
-        __ j(overflow, &call_stub);
-        __ mov(eax, edx);  // Put result back into eax.
-      }
-      break;
-    case Token::SAR:
-      if (shift_value != 0) {
-        __ sar(eax, shift_value);
-        __ and_(eax, ~kSmiTagMask);
-      }
-      break;
-    case Token::SHR:
-      if (shift_value < 2) {
-        __ mov(edx, eax);
-        __ SmiUntag(edx);
-        __ shr(edx, shift_value);
-        __ test(edx, Immediate(0xc0000000));
-        __ j(not_zero, &call_stub);
-        __ SmiTag(edx);
-        __ mov(eax, edx);  // Put result back into eax.
-      } else {
-        __ SmiUntag(eax);
-        __ shr(eax, shift_value);
-        __ SmiTag(eax);
-      }
-      break;
-    default:
-      UNREACHABLE();
-  }
-
-  __ bind(&done);
-  context()->Plug(eax);
-}
-
-
-void FullCodeGenerator::EmitConstantSmiBitOp(Expression* expr,
-                                             Token::Value op,
-                                             OverwriteMode mode,
-                                             Smi* value) {
-  NearLabel smi_case, done;
-
-  JumpPatchSite patch_site(masm_);
-  patch_site.EmitJumpIfSmi(eax, &smi_case);
-
-  // The order of the arguments does not matter for bit-ops with a
-  // constant operand.
-  __ mov(edx, Immediate(value));
-  TypeRecordingBinaryOpStub stub(op, mode);
-  EmitCallIC(stub.GetCode(), &patch_site);
-  __ jmp(&done);
-
-  // Smi case.
-  __ bind(&smi_case);
-  switch (op) {
-    case Token::BIT_OR:
-      __ or_(Operand(eax), Immediate(value));
-      break;
-    case Token::BIT_XOR:
-      __ xor_(Operand(eax), Immediate(value));
-      break;
-    case Token::BIT_AND:
-      __ and_(Operand(eax), Immediate(value));
-      break;
-    default:
-      UNREACHABLE();
-  }
-
-  __ bind(&done);
-  context()->Plug(eax);
-}
-
-
-void FullCodeGenerator::EmitConstantSmiBinaryOp(Expression* expr,
-                                                Token::Value op,
-                                                OverwriteMode mode,
-                                                bool left_is_constant_smi,
-                                                Smi* value) {
-  switch (op) {
-    case Token::BIT_OR:
-    case Token::BIT_XOR:
-    case Token::BIT_AND:
-      EmitConstantSmiBitOp(expr, op, mode, value);
-      break;
-    case Token::SHL:
-    case Token::SAR:
-    case Token::SHR:
-      ASSERT(!left_is_constant_smi);
-      EmitConstantSmiShiftOp(expr, op, mode, value);
-      break;
-    case Token::ADD:
-      EmitConstantSmiAdd(expr, mode, left_is_constant_smi, value);
-      break;
-    case Token::SUB:
-      EmitConstantSmiSub(expr, mode, left_is_constant_smi, value);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
                                               Token::Value op,
                                               OverwriteMode mode,
                                               Expression* left,
-                                              Expression* right,
-                                              ConstantOperand constant) {
-  if (constant == kRightConstant) {
-    Smi* value =  Smi::cast(*right->AsLiteral()->handle());
-    EmitConstantSmiBinaryOp(expr, op, mode, false, value);
-    return;
-  } else if (constant == kLeftConstant) {
-    Smi* value =  Smi::cast(*left->AsLiteral()->handle());
-    EmitConstantSmiBinaryOp(expr, op, mode, true, value);
-    return;
-  }
-
+                                              Expression* right) {
   // Do combined smi check of the operands. Left operand is on the
   // stack. Right operand is in eax.
   NearLabel done, smi_case, stub_call;
@@ -1978,18 +1758,32 @@
       __ mov(edx, eax);
       __ pop(eax);  // Restore value.
       __ mov(ecx, prop->key()->AsLiteral()->handle());
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::StoreIC_Initialize_Strict
+                      : Builtins::StoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
     case KEYED_PROPERTY: {
       __ push(eax);  // Preserve value.
-      VisitForStackValue(prop->obj());
-      VisitForAccumulatorValue(prop->key());
-      __ mov(ecx, eax);
-      __ pop(edx);
+      if (prop->is_synthetic()) {
+        ASSERT(prop->obj()->AsVariableProxy() != NULL);
+        ASSERT(prop->key()->AsLiteral() != NULL);
+        { AccumulatorValueContext for_object(this);
+          EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
+        }
+        __ mov(edx, eax);
+        __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle()));
+      } else {
+        VisitForStackValue(prop->obj());
+        VisitForAccumulatorValue(prop->key());
+        __ mov(ecx, eax);
+        __ pop(edx);
+      }
       __ pop(eax);  // Restore value.
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                      : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
@@ -2084,7 +1878,8 @@
         __ push(eax);  // Value.
         __ push(esi);  // Context.
         __ push(Immediate(var->name()));
-        __ CallRuntime(Runtime::kStoreContextSlot, 3);
+        __ push(Immediate(Smi::FromInt(strict_mode_flag())));
+        __ CallRuntime(Runtime::kStoreContextSlot, 4);
         break;
     }
   }
@@ -2115,7 +1910,9 @@
   } else {
     __ pop(edx);
   }
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      is_strict() ? Builtins::StoreIC_Initialize_Strict
+                  : Builtins::StoreIC_Initialize));
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -2153,7 +1950,9 @@
   }
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                  : Builtins::KeyedStoreIC_Initialize));
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -2266,6 +2065,27 @@
 }
 
 
+void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
+                                                      int arg_count) {
+  // Push copy of the first argument or undefined if it doesn't exist.
+  if (arg_count > 0) {
+    __ push(Operand(esp, arg_count * kPointerSize));
+  } else {
+    __ push(Immediate(Factory::undefined_value()));
+  }
+
+  // Push the receiver of the enclosing function.
+  __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
+
+  // Push the strict mode flag.
+  __ push(Immediate(Smi::FromInt(strict_mode_flag())));
+
+  __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
+                 ? Runtime::kResolvePossiblyDirectEvalNoLookup
+                 : Runtime::kResolvePossiblyDirectEval, 4);
+}
+
+
 void FullCodeGenerator::VisitCall(Call* expr) {
 #ifdef DEBUG
   // We want to verify that RecordJSReturnSite gets called on all paths
@@ -2294,21 +2114,30 @@
         VisitForStackValue(args->at(i));
       }
 
-      // Push copy of the function - found below the arguments.
-      __ push(Operand(esp, (arg_count + 1) * kPointerSize));
-
-      // Push copy of the first argument or undefined if it doesn't exist.
-      if (arg_count > 0) {
-        __ push(Operand(esp, arg_count * kPointerSize));
-      } else {
-        __ push(Immediate(Factory::undefined_value()));
+      // If we know that eval can only be shadowed by eval-introduced
+      // variables we attempt to load the global eval function directly
+      // in generated code. If we succeed, there is no need to perform a
+      // context lookup in the runtime system.
+      Label done;
+      if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
+        Label slow;
+        EmitLoadGlobalSlotCheckExtensions(var->AsSlot(),
+                                          NOT_INSIDE_TYPEOF,
+                                          &slow);
+        // Push the function and resolve eval.
+        __ push(eax);
+        EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count);
+        __ jmp(&done);
+        __ bind(&slow);
       }
 
-      // Push the receiver of the enclosing function and do runtime call.
-      __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
-      // Push the strict mode flag.
-      __ push(Immediate(Smi::FromInt(strict_mode_flag())));
-      __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
+      // Push copy of the function (found below the arguments) and
+      // resolve eval.
+      __ push(Operand(esp, (arg_count + 1) * kPointerSize));
+      EmitResolvePossiblyDirectEval(PERFORM_CONTEXT_LOOKUP, arg_count);
+      if (done.is_linked()) {
+        __ bind(&done);
+      }
 
       // The runtime call returns a pair of values in eax (function) and
       // edx (receiver). Touch up the stack with the right values.
@@ -2373,7 +2202,9 @@
     Literal* key = prop->key()->AsLiteral();
     if (key != NULL && key->handle()->IsSymbol()) {
       // Call to a named property, use call IC.
-      VisitForStackValue(prop->obj());
+      { PreservePositionScope scope(masm()->positions_recorder());
+        VisitForStackValue(prop->obj());
+      }
       EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
     } else {
       // Call to a keyed property.
@@ -3384,7 +3215,6 @@
 
 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
   ASSERT(args->length() == 1);
-
   VisitForAccumulatorValue(args->at(0));
 
   if (FLAG_debug_code) {
@@ -3400,7 +3230,7 @@
 
 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
   Label bailout, done, one_char_separator, long_separator,
-      non_trivial_array, not_size_one_array, loop, loop_condition,
+      non_trivial_array, not_size_one_array, loop,
       loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
 
   ASSERT(args->length() == 2);
@@ -3442,7 +3272,7 @@
 
   // If the array has length zero, return the empty string.
   __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset));
-  __ sar(array_length, 1);
+  __ SmiUntag(array_length);
   __ j(not_zero, &non_trivial_array);
   __ mov(result_operand, Factory::empty_string());
   __ jmp(&done);
@@ -3465,14 +3295,15 @@
   // Loop condition: while (index < length).
   // Live loop registers: index, array_length, string,
   //                      scratch, string_length, elements.
-  __ jmp(&loop_condition);
+  if (FLAG_debug_code) {
+    __ cmp(index, Operand(array_length));
+    __ Assert(less, "No empty arrays here in EmitFastAsciiArrayJoin");
+  }
   __ bind(&loop);
-  __ cmp(index, Operand(array_length));
-  __ j(greater_equal, &done);
-
-  __ mov(string, FieldOperand(elements, index,
-                                      times_pointer_size,
-                                      FixedArray::kHeaderSize));
+  __ mov(string, FieldOperand(elements,
+                              index,
+                              times_pointer_size,
+                              FixedArray::kHeaderSize));
   __ test(string, Immediate(kSmiTagMask));
   __ j(zero, &bailout);
   __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
@@ -3485,7 +3316,6 @@
          FieldOperand(string, SeqAsciiString::kLengthOffset));
   __ j(overflow, &bailout);
   __ add(Operand(index), Immediate(1));
-  __ bind(&loop_condition);
   __ cmp(index, Operand(array_length));
   __ j(less, &loop);
 
@@ -3514,7 +3344,7 @@
   __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
   __ and_(scratch, Immediate(
       kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
-  __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
+  __ cmp(scratch, ASCII_STRING_TYPE);
   __ j(not_equal, &bailout);
 
   // Add (separator length times array_length) - separator length
@@ -3711,19 +3541,8 @@
       Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
       Property* prop = expr->expression()->AsProperty();
       Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
-      if (prop == NULL && var == NULL) {
-        // Result of deleting non-property, non-variable reference is true.
-        // The subexpression may have side effects.
-        VisitForEffect(expr->expression());
-        context()->Plug(true);
-      } else if (var != NULL &&
-                 !var->is_global() &&
-                 var->AsSlot() != NULL &&
-                 var->AsSlot()->type() != Slot::LOOKUP) {
-        // Result of deleting non-global, non-dynamic variables is false.
-        // The subexpression does not have side effects.
-        context()->Plug(false);
-      } else if (prop != NULL) {
+
+      if (prop != NULL) {
         if (prop->is_synthetic()) {
           // Result of deleting parameters is false, even when they rewrite
           // to accesses on the arguments object.
@@ -3731,21 +3550,38 @@
         } else {
           VisitForStackValue(prop->obj());
           VisitForStackValue(prop->key());
+          __ push(Immediate(Smi::FromInt(strict_mode_flag())));
           __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
           context()->Plug(eax);
         }
-      } else if (var->is_global()) {
-        __ push(GlobalObjectOperand());
-        __ push(Immediate(var->name()));
-        __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
-        context()->Plug(eax);
+      } else if (var != NULL) {
+        // Delete of an unqualified identifier is disallowed in strict mode
+        // but "delete this" is.
+        ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
+        if (var->is_global()) {
+          __ push(GlobalObjectOperand());
+          __ push(Immediate(var->name()));
+          __ push(Immediate(Smi::FromInt(kNonStrictMode)));
+          __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
+          context()->Plug(eax);
+        } else if (var->AsSlot() != NULL &&
+                   var->AsSlot()->type() != Slot::LOOKUP) {
+          // Result of deleting non-global, non-dynamic variables is false.
+          // The subexpression does not have side effects.
+          context()->Plug(false);
+        } else {
+          // Non-global variable.  Call the runtime to try to delete from the
+          // context where the variable was introduced.
+          __ push(context_register());
+          __ push(Immediate(var->name()));
+          __ CallRuntime(Runtime::kDeleteContextSlot, 2);
+          context()->Plug(eax);
+        }
       } else {
-        // Non-global variable.  Call the runtime to try to delete from the
-        // context where the variable was introduced.
-        __ push(context_register());
-        __ push(Immediate(var->name()));
-        __ CallRuntime(Runtime::kDeleteContextSlot, 2);
-        context()->Plug(eax);
+        // Result of deleting non-property, non-variable reference is true.
+        // The subexpression may have side effects.
+        VisitForEffect(expr->expression());
+        context()->Plug(true);
       }
       break;
     }
@@ -3759,17 +3595,23 @@
 
     case Token::NOT: {
       Comment cmnt(masm_, "[ UnaryOperation (NOT)");
+      if (context()->IsEffect()) {
+        // Unary NOT has no side effects so it's only necessary to visit the
+        // subexpression.  Match the optimizing compiler by not branching.
+        VisitForEffect(expr->expression());
+      } else {
+        Label materialize_true, materialize_false;
+        Label* if_true = NULL;
+        Label* if_false = NULL;
+        Label* fall_through = NULL;
 
-      Label materialize_true, materialize_false;
-      Label* if_true = NULL;
-      Label* if_false = NULL;
-      Label* fall_through = NULL;
-      // Notice that the labels are swapped.
-      context()->PrepareTest(&materialize_true, &materialize_false,
-                             &if_false, &if_true, &fall_through);
-      if (context()->IsTest()) ForwardBailoutToChild(expr);
-      VisitForControl(expr->expression(), if_true, if_false, fall_through);
-      context()->Plug(if_false, if_true);  // Labels swapped.
+        // Notice that the labels are swapped.
+        context()->PrepareTest(&materialize_true, &materialize_false,
+                               &if_false, &if_true, &fall_through);
+        if (context()->IsTest()) ForwardBailoutToChild(expr);
+        VisitForControl(expr->expression(), if_true, if_false, fall_through);
+        context()->Plug(if_false, if_true);  // Labels swapped.
+      }
       break;
     }
 
@@ -3995,7 +3837,9 @@
     case NAMED_PROPERTY: {
       __ mov(ecx, prop->key()->AsLiteral()->handle());
       __ pop(edx);
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::StoreIC_Initialize_Strict
+                      : Builtins::StoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -4010,7 +3854,9 @@
     case KEYED_PROPERTY: {
       __ pop(ecx);
       __ pop(edx);
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                      : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -4090,21 +3936,18 @@
   PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
 
   if (check->Equals(Heap::number_symbol())) {
-    __ test(eax, Immediate(kSmiTagMask));
-    __ j(zero, if_true);
+    __ JumpIfSmi(eax, if_true);
     __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
            Factory::heap_number_map());
     Split(equal, if_true, if_false, fall_through);
   } else if (check->Equals(Heap::string_symbol())) {
-    __ test(eax, Immediate(kSmiTagMask));
-    __ j(zero, if_false);
+    __ JumpIfSmi(eax, if_false);
+    __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
+    __ j(above_equal, if_false);
     // Check for undetectable objects => false.
-    __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
-    __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
-    __ test(ecx, Immediate(1 << Map::kIsUndetectable));
-    __ j(not_zero, if_false);
-    __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE);
-    Split(below, if_true, if_false, fall_through);
+    __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
+              1 << Map::kIsUndetectable);
+    Split(zero, if_true, if_false, fall_through);
   } else if (check->Equals(Heap::boolean_symbol())) {
     __ cmp(eax, Factory::true_value());
     __ j(equal, if_true);
@@ -4113,39 +3956,28 @@
   } else if (check->Equals(Heap::undefined_symbol())) {
     __ cmp(eax, Factory::undefined_value());
     __ j(equal, if_true);
-    __ test(eax, Immediate(kSmiTagMask));
-    __ j(zero, if_false);
+    __ JumpIfSmi(eax, if_false);
     // Check for undetectable objects => true.
     __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
     __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
     __ test(ecx, Immediate(1 << Map::kIsUndetectable));
     Split(not_zero, if_true, if_false, fall_through);
   } else if (check->Equals(Heap::function_symbol())) {
-    __ test(eax, Immediate(kSmiTagMask));
-    __ j(zero, if_false);
-    __ CmpObjectType(eax, JS_FUNCTION_TYPE, edx);
-    __ j(equal, if_true);
-    // Regular expressions => 'function' (they are callable).
-    __ CmpInstanceType(edx, JS_REGEXP_TYPE);
-    Split(equal, if_true, if_false, fall_through);
+    __ JumpIfSmi(eax, if_false);
+    __ CmpObjectType(eax, FIRST_FUNCTION_CLASS_TYPE, edx);
+    Split(above_equal, if_true, if_false, fall_through);
   } else if (check->Equals(Heap::object_symbol())) {
-    __ test(eax, Immediate(kSmiTagMask));
-    __ j(zero, if_false);
+    __ JumpIfSmi(eax, if_false);
     __ cmp(eax, Factory::null_value());
     __ j(equal, if_true);
-    // Regular expressions => 'function', not 'object'.
-    __ CmpObjectType(eax, JS_REGEXP_TYPE, edx);
-    __ j(equal, if_false);
+    __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, edx);
+    __ j(below, if_false);
+    __ CmpInstanceType(edx, FIRST_FUNCTION_CLASS_TYPE);
+    __ j(above_equal, if_false);
     // Check for undetectable objects => false.
-    __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
-    __ test(ecx, Immediate(1 << Map::kIsUndetectable));
-    __ j(not_zero, if_false);
-    // Check for JS objects => true.
-    __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset));
-    __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
-    __ j(less, if_false);
-    __ cmp(ecx, LAST_JS_OBJECT_TYPE);
-    Split(less_equal, if_true, if_false, fall_through);
+    __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
+              1 << Map::kIsUndetectable);
+    Split(zero, if_true, if_false, fall_through);
   } else {
     if (if_false != fall_through) __ jmp(if_false);
   }
@@ -4358,6 +4190,22 @@
 
 
 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) {
+  switch (ic->kind()) {
+    case Code::LOAD_IC:
+      __ IncrementCounter(&Counters::named_load_full, 1);
+      break;
+    case Code::KEYED_LOAD_IC:
+      __ IncrementCounter(&Counters::keyed_load_full, 1);
+      break;
+    case Code::STORE_IC:
+      __ IncrementCounter(&Counters::named_store_full, 1);
+      break;
+    case Code::KEYED_STORE_IC:
+      __ IncrementCounter(&Counters::keyed_store_full, 1);
+    default:
+      break;
+  }
+
   __ call(ic, RelocInfo::CODE_TARGET);
   if (patch_site != NULL && patch_site->is_bound()) {
     patch_site->EmitPatchInfo();
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index 76681ce..6b9e749 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -108,6 +108,9 @@
                                            Register name,
                                            Register r0,
                                            Register r1) {
+  // Assert that name contains a string.
+  if (FLAG_debug_code) __ AbortIfNotString(name);
+
   // Compute the capacity mask.
   const int kCapacityOffset =
       StringDictionary::kHeaderSize +
@@ -758,7 +761,8 @@
 }
 
 
-void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
+                                   StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : key
@@ -798,7 +802,7 @@
 
   // Slow case: call runtime.
   __ bind(&slow);
-  GenerateRuntimeSetProperty(masm);
+  GenerateRuntimeSetProperty(masm, strict_mode);
 
   // Check whether the elements is a pixel array.
   __ bind(&check_pixel_array);
@@ -806,28 +810,17 @@
   // ecx: key (a smi)
   // edx: receiver
   // edi: elements array
-  __ CheckMap(edi, Factory::pixel_array_map(), &slow, true);
-  // Check that the value is a smi. If a conversion is needed call into the
-  // runtime to convert and clamp.
-  __ test(eax, Immediate(kSmiTagMask));
-  __ j(not_zero, &slow);
-  __ mov(ebx, ecx);
-  __ SmiUntag(ebx);
-  __ cmp(ebx, FieldOperand(edi, PixelArray::kLengthOffset));
-  __ j(above_equal, &slow);
-  __ mov(ecx, eax);  // Save the value. Key is not longer needed.
-  __ SmiUntag(ecx);
-  {  // Clamp the value to [0..255].
-    Label done;
-    __ test(ecx, Immediate(0xFFFFFF00));
-    __ j(zero, &done);
-    __ setcc(negative, ecx);  // 1 if negative, 0 if positive.
-    __ dec_b(ecx);  // 0 if negative, 255 if positive.
-    __ bind(&done);
-  }
-  __ mov(edi, FieldOperand(edi, PixelArray::kExternalPointerOffset));
-  __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
-  __ ret(0);  // Return value in eax.
+  GenerateFastPixelArrayStore(masm,
+                              edx,
+                              ecx,
+                              eax,
+                              edi,
+                              ebx,
+                              false,
+                              NULL,
+                              &slow,
+                              &slow,
+                              &slow);
 
   // Extra capacity case: Check if there is extra capacity to
   // perform the store and update the length. Used for adding one
@@ -1208,7 +1201,14 @@
   //  -- esp[(argc + 1) * 4] : receiver
   // -----------------------------------
 
+  // Check if the name is a string.
+  Label miss;
+  __ test(ecx, Immediate(kSmiTagMask));
+  __ j(zero, &miss);
+  Condition cond = masm->IsObjectStringType(ecx, eax, eax);
+  __ j(NegateCondition(cond), &miss);
   GenerateCallNormal(masm, argc);
+  __ bind(&miss);
   GenerateMiss(masm, argc);
 }
 
@@ -1489,7 +1489,7 @@
 
 
 void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
-                                  Code::ExtraICState extra_ic_state) {
+                                  StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : name
@@ -1500,7 +1500,7 @@
   Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
                                          NOT_IN_LOOP,
                                          MONOMORPHIC,
-                                         extra_ic_state);
+                                         strict_mode);
   StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
 
   // Cache miss: Jump to runtime.
@@ -1618,7 +1618,8 @@
 }
 
 
-void StoreIC::GenerateGlobalProxy(MacroAssembler* masm) {
+void StoreIC::GenerateGlobalProxy(MacroAssembler* masm,
+                                  StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : name
@@ -1629,14 +1630,17 @@
   __ push(edx);
   __ push(ecx);
   __ push(eax);
-  __ push(ebx);
+  __ push(Immediate(Smi::FromInt(NONE)));  // PropertyAttributes
+  __ push(Immediate(Smi::FromInt(strict_mode)));
+  __ push(ebx);  // return address
 
   // Do tail-call to runtime routine.
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 }
 
 
-void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
+                                              StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : key
@@ -1648,10 +1652,12 @@
   __ push(edx);
   __ push(ecx);
   __ push(eax);
-  __ push(ebx);
+  __ push(Immediate(Smi::FromInt(NONE)));         // PropertyAttributes
+  __ push(Immediate(Smi::FromInt(strict_mode)));  // Strict mode.
+  __ push(ebx);   // return address
 
   // Do tail-call to runtime routine.
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 }
 
 
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 7724f1b..9dcca9e 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -43,13 +43,20 @@
  public:
   SafepointGenerator(LCodeGen* codegen,
                      LPointerMap* pointers,
-                     int deoptimization_index)
+                     int deoptimization_index,
+                     bool ensure_reloc_space = false)
       : codegen_(codegen),
         pointers_(pointers),
-        deoptimization_index_(deoptimization_index) { }
+        deoptimization_index_(deoptimization_index),
+        ensure_reloc_space_(ensure_reloc_space) { }
   virtual ~SafepointGenerator() { }
 
   virtual void Generate() {
+    // Ensure that we have enough space in the reloc info to patch
+    // this with calls when doing deoptimization.
+    if (ensure_reloc_space_) {
+      codegen_->EnsureRelocSpaceForDeoptimization();
+    }
     codegen_->RecordSafepoint(pointers_, deoptimization_index_);
   }
 
@@ -57,6 +64,7 @@
   LCodeGen* codegen_;
   LPointerMap* pointers_;
   int deoptimization_index_;
+  bool ensure_reloc_space_;
 };
 
 
@@ -70,6 +78,7 @@
   return GeneratePrologue() &&
       GenerateBody() &&
       GenerateDeferredCode() &&
+      GenerateRelocPadding() &&
       GenerateSafepointTable();
 }
 
@@ -84,8 +93,8 @@
 
 void LCodeGen::Abort(const char* format, ...) {
   if (FLAG_trace_bailout) {
-    SmartPointer<char> debug_name = graph()->debug_name()->ToCString();
-    PrintF("Aborting LCodeGen in @\"%s\": ", *debug_name);
+    SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
+    PrintF("Aborting LCodeGen in @\"%s\": ", *name);
     va_list arguments;
     va_start(arguments, format);
     OS::VPrint(format, arguments);
@@ -114,6 +123,16 @@
 }
 
 
+bool LCodeGen::GenerateRelocPadding() {
+  int reloc_size = masm()->relocation_writer_size();
+  while (reloc_size < deoptimization_reloc_size.min_size) {
+    __ RecordComment(RelocInfo::kFillerCommentString, true);
+    reloc_size += RelocInfo::kMinRelocCommentSize;
+  }
+  return !is_aborted();
+}
+
+
 bool LCodeGen::GeneratePrologue() {
   ASSERT(is_generating());
 
@@ -155,6 +174,45 @@
     }
   }
 
+  // Possibly allocate a local context.
+  int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+  if (heap_slots > 0) {
+    Comment(";;; Allocate local context");
+    // Argument to NewContext is the function, which is still in edi.
+    __ push(edi);
+    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+      FastNewContextStub stub(heap_slots);
+      __ CallStub(&stub);
+    } else {
+      __ CallRuntime(Runtime::kNewContext, 1);
+    }
+    RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
+    // Context is returned in both eax and esi.  It replaces the context
+    // passed to us.  It's saved in the stack and kept live in esi.
+    __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
+
+    // Copy parameters into context if necessary.
+    int num_parameters = scope()->num_parameters();
+    for (int i = 0; i < num_parameters; i++) {
+      Slot* slot = scope()->parameter(i)->AsSlot();
+      if (slot != NULL && slot->type() == Slot::CONTEXT) {
+        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
+            (num_parameters - 1 - i) * kPointerSize;
+        // Load parameter from stack.
+        __ mov(eax, Operand(ebp, parameter_offset));
+        // Store it in the context.
+        int context_offset = Context::SlotOffset(slot->index());
+        __ mov(Operand(esi, context_offset), eax);
+        // Update the write barrier. This clobbers all involved
+        // registers, so we have to use a third register to avoid
+        // clobbering esi.
+        __ mov(ecx, esi);
+        __ RecordWrite(ecx, context_offset, eax, ebx);
+      }
+    }
+    Comment(";;; End allocate local context");
+  }
+
   // Trace the call.
   if (FLAG_trace) {
     // We have not executed any compiled code yet, so esi still holds the
@@ -327,6 +385,22 @@
 }
 
 
+void LCodeGen::EnsureRelocSpaceForDeoptimization() {
+  // Since we patch the reloc info with RUNTIME_ENTRY calls every patch
+  // site will take up 2 bytes + any pc-jumps.
+  // We are conservative and always reserver 6 bytes in case where a
+  // simple pc-jump is not enough.
+  uint32_t pc_delta =
+      masm()->pc_offset() - deoptimization_reloc_size.last_pc_offset;
+  if (is_uintn(pc_delta, 6)) {
+    deoptimization_reloc_size.min_size += 2;
+  } else {
+    deoptimization_reloc_size.min_size += 6;
+  }
+  deoptimization_reloc_size.last_pc_offset = masm()->pc_offset();
+}
+
+
 void LCodeGen::AddToTranslation(Translation* translation,
                                 LOperand* op,
                                 bool is_tagged) {
@@ -374,10 +448,13 @@
   ASSERT(instr != NULL);
   LPointerMap* pointers = instr->pointer_map();
   RecordPosition(pointers->position());
+
   if (!adjusted) {
     __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
   }
   __ call(code, mode);
+
+  EnsureRelocSpaceForDeoptimization();
   RegisterLazyDeoptimization(instr);
 
   // Signal that we don't inline smi code before these stubs in the
@@ -511,7 +588,8 @@
   Handle<DeoptimizationInputData> data =
       Factory::NewDeoptimizationInputData(length, TENURED);
 
-  data->SetTranslationByteArray(*translations_.CreateByteArray());
+  Handle<ByteArray> translations = translations_.CreateByteArray();
+  data->SetTranslationByteArray(*translations);
   data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
 
   Handle<FixedArray> literals =
@@ -587,6 +665,12 @@
 }
 
 
+void LCodeGen::RecordSafepoint(int deoptimization_index) {
+  LPointerMap empty_pointers(RelocInfo::kNoPosition);
+  RecordSafepoint(&empty_pointers, deoptimization_index);
+}
+
+
 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
                                             int arguments,
                                             int deoptimization_index) {
@@ -1064,35 +1148,36 @@
 
 
 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
-  LOperand* left = instr->InputAt(0);
-  LOperand* right = instr->InputAt(1);
+  XMMRegister left = ToDoubleRegister(instr->InputAt(0));
+  XMMRegister right = ToDoubleRegister(instr->InputAt(1));
+  XMMRegister result = ToDoubleRegister(instr->result());
   // Modulo uses a fixed result register.
-  ASSERT(instr->op() == Token::MOD || left->Equals(instr->result()));
+  ASSERT(instr->op() == Token::MOD || left.is(result));
   switch (instr->op()) {
     case Token::ADD:
-      __ addsd(ToDoubleRegister(left), ToDoubleRegister(right));
+      __ addsd(left, right);
       break;
     case Token::SUB:
-       __ subsd(ToDoubleRegister(left), ToDoubleRegister(right));
+       __ subsd(left, right);
        break;
     case Token::MUL:
-      __ mulsd(ToDoubleRegister(left), ToDoubleRegister(right));
+      __ mulsd(left, right);
       break;
     case Token::DIV:
-      __ divsd(ToDoubleRegister(left), ToDoubleRegister(right));
+      __ divsd(left, right);
       break;
     case Token::MOD: {
       // Pass two doubles as arguments on the stack.
       __ PrepareCallCFunction(4, eax);
-      __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left));
-      __ movdbl(Operand(esp, 1 * kDoubleSize), ToDoubleRegister(right));
+      __ movdbl(Operand(esp, 0 * kDoubleSize), left);
+      __ movdbl(Operand(esp, 1 * kDoubleSize), right);
       __ CallCFunction(ExternalReference::double_fp_operation(Token::MOD), 4);
 
       // Return value is in st(0) on ia32.
       // Store it into the (fixed) result register.
       __ sub(Operand(esp), Immediate(kDoubleSize));
       __ fstp_d(Operand(esp, 0));
-      __ movdbl(ToDoubleRegister(instr->result()), Operand(esp, 0));
+      __ movdbl(result, Operand(esp, 0));
       __ add(Operand(esp), Immediate(kDoubleSize));
       break;
     }
@@ -1569,6 +1654,19 @@
 }
 
 
+void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
+  Register input = ToRegister(instr->InputAt(0));
+  Register result = ToRegister(instr->result());
+
+  if (FLAG_debug_code) {
+    __ AbortIfNotString(input);
+  }
+
+  __ mov(result, FieldOperand(input, String::kHashFieldOffset));
+  __ IndexFromHash(result, result);
+}
+
+
 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
   Register input = ToRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
@@ -1578,7 +1676,7 @@
   __ test(FieldOperand(input, String::kHashFieldOffset),
           Immediate(String::kContainsCachedArrayIndexMask));
   NearLabel done;
-  __ j(not_zero, &done);
+  __ j(zero, &done);
   __ mov(result, Factory::false_value());
   __ bind(&done);
 }
@@ -1593,7 +1691,7 @@
 
   __ test(FieldOperand(input, String::kHashFieldOffset),
           Immediate(String::kContainsCachedArrayIndexMask));
-  EmitBranch(true_block, false_block, not_equal);
+  EmitBranch(true_block, false_block, equal);
 }
 
 
@@ -1764,11 +1862,11 @@
   Register object = ToRegister(instr->InputAt(0));
   Register temp = ToRegister(instr->TempAt(0));
 
-  // A Smi is not instance of anything.
+  // A Smi is not an instance of anything.
   __ test(object, Immediate(kSmiTagMask));
   __ j(zero, &false_result, not_taken);
 
-  // This is the inlined call site instanceof cache. The two occourences of the
+  // This is the inlined call site instanceof cache. The two occurences of the
   // hole value will be patched to the last map/result pair generated by the
   // instanceof stub.
   NearLabel cache_miss;
@@ -1780,10 +1878,10 @@
   __ mov(eax, Factory::the_hole_value());  // Patched to either true or false.
   __ jmp(&done);
 
-  // The inlined call site cache did not match. Check null and string before
-  // calling the deferred code.
+  // The inlined call site cache did not match. Check for null and string
+  // before calling the deferred code.
   __ bind(&cache_miss);
-  // Null is not instance of anything.
+  // Null is not an instance of anything.
   __ cmp(object, Factory::null_value());
   __ j(equal, &false_result);
 
@@ -1825,19 +1923,11 @@
   __ mov(InstanceofStub::right(), Immediate(instr->function()));
   static const int kAdditionalDelta = 16;
   int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
-  Label before_push_delta;
-  __ bind(&before_push_delta);
   __ mov(temp, Immediate(delta));
-  __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp);
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-  __ call(stub.GetCode(), RelocInfo::CODE_TARGET);
-  ASSERT_EQ(kAdditionalDelta,
-            masm_->SizeOfCodeGeneratedSince(&before_push_delta));
-  RecordSafepointWithRegisters(
-      instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
+  __ StoreToSafepointRegisterSlot(temp, temp);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false);
   // Put the result value into the eax slot and restore all registers.
-  __ mov(Operand(esp, EspIndexForPushAll(eax) * kPointerSize), eax);
-
+  __ StoreToSafepointRegisterSlot(eax, eax);
   __ PopSafepointRegisters();
 }
 
@@ -2092,13 +2182,13 @@
 
 
 void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) {
-  Register external_elements = ToRegister(instr->external_pointer());
+  Register external_pointer = ToRegister(instr->external_pointer());
   Register key = ToRegister(instr->key());
   Register result = ToRegister(instr->result());
-  ASSERT(result.is(external_elements));
+  ASSERT(result.is(external_pointer));
 
   // Load the result.
-  __ movzx_b(result, Operand(external_elements, key, times_1, 0));
+  __ movzx_b(result, Operand(external_pointer, key, times_1, 0));
 }
 
 
@@ -2221,7 +2311,8 @@
   RegisterEnvironmentForDeoptimization(env);
   SafepointGenerator safepoint_generator(this,
                                          pointers,
-                                         env->deoptimization_index());
+                                         env->deoptimization_index(),
+                                         true);
   v8::internal::ParameterCount actual(eax);
   __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
 }
@@ -2270,7 +2361,7 @@
                                  LInstruction* instr) {
   // Change context if needed.
   bool change_context =
-      (graph()->info()->closure()->context() != function->context()) ||
+      (info()->closure()->context() != function->context()) ||
       scope()->contains_with() ||
       (scope()->num_heap_slots() > 0);
   if (change_context) {
@@ -2289,10 +2380,11 @@
   RecordPosition(pointers->position());
 
   // Invoke function.
-  if (*function == *graph()->info()->closure()) {
+  if (*function == *info()->closure()) {
     __ CallSelf();
   } else {
     __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
+    EnsureRelocSpaceForDeoptimization();
   }
 
   // Setup deoptimization.
@@ -2347,7 +2439,7 @@
   if (!tmp.is(eax)) __ mov(tmp, eax);
 
   // Restore input_reg after call to runtime.
-  __ mov(input_reg, Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize));
+  __ LoadFromSafepointRegisterSlot(input_reg, input_reg);
 
   __ bind(&allocated);
   __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset));
@@ -2355,7 +2447,7 @@
   __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2);
   __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
   __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2);
-  __ mov(Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize), tmp);
+  __ StoreToSafepointRegisterSlot(input_reg, tmp);
 
   __ bind(&done);
   __ PopSafepointRegisters();
@@ -2480,11 +2572,6 @@
   XMMRegister xmm_scratch = xmm0;
   XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
   ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
-  ExternalReference negative_infinity =
-      ExternalReference::address_of_negative_infinity();
-  __ movdbl(xmm_scratch, Operand::StaticVariable(negative_infinity));
-  __ ucomisd(xmm_scratch, input_reg);
-  DeoptimizeIf(equal, instr->environment());
   __ xorpd(xmm_scratch, xmm_scratch);
   __ addsd(input_reg, xmm_scratch);  // Convert -0 to +0.
   __ sqrtsd(input_reg, input_reg);
@@ -2707,7 +2794,9 @@
   ASSERT(ToRegister(instr->value()).is(eax));
 
   __ mov(ecx, instr->name());
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      info_->is_strict() ? Builtins::StoreIC_Initialize_Strict
+                         : Builtins::StoreIC_Initialize));
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2718,6 +2807,25 @@
 }
 
 
+void LCodeGen::DoStorePixelArrayElement(LStorePixelArrayElement* instr) {
+  Register external_pointer = ToRegister(instr->external_pointer());
+  Register key = ToRegister(instr->key());
+  Register value = ToRegister(instr->value());
+  ASSERT(ToRegister(instr->TempAt(0)).is(eax));
+
+  __ mov(eax, value);
+  {  // Clamp the value to [0..255].
+    NearLabel done;
+    __ test(eax, Immediate(0xFFFFFF00));
+    __ j(zero, &done);
+    __ setcc(negative, eax);  // 1 if negative, 0 if positive.
+    __ dec_b(eax);  // 0 if negative, 255 if positive.
+    __ bind(&done);
+  }
+  __ mov_b(Operand(external_pointer, key, times_1, 0), eax);
+}
+
+
 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
   Register value = ToRegister(instr->value());
   Register elements = ToRegister(instr->object());
@@ -2756,7 +2864,9 @@
   ASSERT(ToRegister(instr->key()).is(ecx));
   ASSERT(ToRegister(instr->value()).is(eax));
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      info_->is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                         : Builtins::KeyedStoreIC_Initialize));
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2827,19 +2937,20 @@
   __ test(result, Immediate(kStringRepresentationMask));
   __ j(not_zero, deferred->entry());
 
-  // Check for 1-byte or 2-byte string.
+  // Check for ASCII or two-byte string.
   __ bind(&flat_string);
   STATIC_ASSERT(kAsciiStringTag != 0);
   __ test(result, Immediate(kStringEncodingMask));
   __ j(not_zero, &ascii_string);
 
-  // 2-byte string.
-  // Load the 2-byte character code into the result register.
+  // Two-byte string.
+  // Load the two-byte character code into the result register.
   STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
   if (instr->index()->IsConstantOperand()) {
     __ movzx_w(result,
                FieldOperand(string,
-                            SeqTwoByteString::kHeaderSize + 2 * const_index));
+                            SeqTwoByteString::kHeaderSize +
+                            (kUC16Size * const_index)));
   } else {
     __ movzx_w(result, FieldOperand(string,
                                     index,
@@ -2895,7 +3006,7 @@
     __ AbortIfNotSmi(eax);
   }
   __ SmiUntag(eax);
-  __ mov(Operand(esp, EspIndexForPushAll(result) * kPointerSize), eax);
+  __ StoreToSafepointRegisterSlot(result, eax);
   __ PopSafepointRegisters();
 }
 
@@ -2963,7 +3074,7 @@
   // TODO(3095996): Put a valid pointer value in the stack slot where the result
   // register is stored, as this register is in the pointer map, but contains an
   // integer value.
-  __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), Immediate(0));
+  __ StoreToSafepointRegisterSlot(reg, Immediate(0));
 
   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
   __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
@@ -2975,7 +3086,7 @@
   // number.
   __ bind(&done);
   __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0);
-  __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), reg);
+  __ StoreToSafepointRegisterSlot(reg, reg);
   __ PopSafepointRegisters();
 }
 
@@ -3017,7 +3128,7 @@
   __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
   RecordSafepointWithRegisters(
       instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
-  __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), eax);
+  __ StoreToSafepointRegisterSlot(reg, eax);
   __ PopSafepointRegisters();
 }
 
@@ -3589,21 +3700,18 @@
                                  Handle<String> type_name) {
   Condition final_branch_condition = no_condition;
   if (type_name->Equals(Heap::number_symbol())) {
-    __ test(input, Immediate(kSmiTagMask));
-    __ j(zero, true_label);
+    __ JumpIfSmi(input, true_label);
     __ cmp(FieldOperand(input, HeapObject::kMapOffset),
            Factory::heap_number_map());
     final_branch_condition = equal;
 
   } else if (type_name->Equals(Heap::string_symbol())) {
-    __ test(input, Immediate(kSmiTagMask));
-    __ j(zero, false_label);
-    __ mov(input, FieldOperand(input, HeapObject::kMapOffset));
+    __ JumpIfSmi(input, false_label);
+    __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
+    __ j(above_equal, false_label);
     __ test_b(FieldOperand(input, Map::kBitFieldOffset),
               1 << Map::kIsUndetectable);
-    __ j(not_zero, false_label);
-    __ CmpInstanceType(input, FIRST_NONSTRING_TYPE);
-    final_branch_condition = below;
+    final_branch_condition = zero;
 
   } else if (type_name->Equals(Heap::boolean_symbol())) {
     __ cmp(input, Factory::true_value());
@@ -3614,8 +3722,7 @@
   } else if (type_name->Equals(Heap::undefined_symbol())) {
     __ cmp(input, Factory::undefined_value());
     __ j(equal, true_label);
-    __ test(input, Immediate(kSmiTagMask));
-    __ j(zero, false_label);
+    __ JumpIfSmi(input, false_label);
     // Check for undetectable objects => true.
     __ mov(input, FieldOperand(input, HeapObject::kMapOffset));
     __ test_b(FieldOperand(input, Map::kBitFieldOffset),
@@ -3623,8 +3730,7 @@
     final_branch_condition = not_zero;
 
   } else if (type_name->Equals(Heap::function_symbol())) {
-    __ test(input, Immediate(kSmiTagMask));
-    __ j(zero, false_label);
+    __ JumpIfSmi(input, false_label);
     __ CmpObjectType(input, JS_FUNCTION_TYPE, input);
     __ j(equal, true_label);
     // Regular expressions => 'function' (they are callable).
@@ -3632,22 +3738,18 @@
     final_branch_condition = equal;
 
   } else if (type_name->Equals(Heap::object_symbol())) {
-    __ test(input, Immediate(kSmiTagMask));
-    __ j(zero, false_label);
+    __ JumpIfSmi(input, false_label);
     __ cmp(input, Factory::null_value());
     __ j(equal, true_label);
     // Regular expressions => 'function', not 'object'.
-    __ CmpObjectType(input, JS_REGEXP_TYPE, input);
-    __ j(equal, false_label);
+    __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, input);
+    __ j(below, false_label);
+    __ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE);
+    __ j(above_equal, false_label);
     // Check for undetectable objects => false.
     __ test_b(FieldOperand(input, Map::kBitFieldOffset),
               1 << Map::kIsUndetectable);
-    __ j(not_zero, false_label);
-    // Check for JS objects => true.
-    __ CmpInstanceType(input, FIRST_JS_OBJECT_TYPE);
-    __ j(below, false_label);
-    __ CmpInstanceType(input, LAST_JS_OBJECT_TYPE);
-    final_branch_condition = below_equal;
+    final_branch_condition = zero;
 
   } else {
     final_branch_condition = not_equal;
@@ -3731,10 +3833,15 @@
   LEnvironment* env = instr->deoptimization_environment();
   RecordPosition(pointers->position());
   RegisterEnvironmentForDeoptimization(env);
+  // Create safepoint generator that will also ensure enough space in the
+  // reloc info for patching in deoptimization (since this is invoking a
+  // builtin)
   SafepointGenerator safepoint_generator(this,
                                          pointers,
-                                         env->deoptimization_index());
+                                         env->deoptimization_index(),
+                                         true);
   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  __ push(Immediate(Smi::FromInt(strict_mode_flag())));
   __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, &safepoint_generator);
 }
 
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index 3ac3a41..ecd6caa 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -56,16 +56,18 @@
         deoptimizations_(4),
         deoptimization_literals_(8),
         inlined_function_count_(0),
-        scope_(chunk->graph()->info()->scope()),
+        scope_(info->scope()),
         status_(UNUSED),
         deferred_(8),
         osr_pc_offset_(-1),
+        deoptimization_reloc_size(),
         resolver_(this) {
     PopulateDeoptimizationLiteralsWithInlinedFunctions();
   }
 
   // Simple accessors.
   MacroAssembler* masm() const { return masm_; }
+  CompilationInfo* info() const { return info_; }
 
   // Support for converting LOperands to assembler types.
   Operand ToOperand(LOperand* op) const;
@@ -102,6 +104,8 @@
   // Emit frame translation commands for an environment.
   void WriteTranslation(LEnvironment* environment, Translation* translation);
 
+  void EnsureRelocSpaceForDeoptimization();
+
   // Declare methods that deal with the individual node types.
 #define DECLARE_DO(type) void Do##type(L##type* node);
   LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
@@ -120,6 +124,10 @@
   bool is_done() const { return status_ == DONE; }
   bool is_aborted() const { return status_ == ABORTED; }
 
+  int strict_mode_flag() const {
+    return info()->is_strict() ? kStrictMode : kNonStrictMode;
+  }
+
   LChunk* chunk() const { return chunk_; }
   Scope* scope() const { return scope_; }
   HGraph* graph() const { return chunk_->graph(); }
@@ -147,6 +155,9 @@
   bool GeneratePrologue();
   bool GenerateBody();
   bool GenerateDeferredCode();
+  // Pad the reloc info to ensure that we have enough space to patch during
+  // deoptimization.
+  bool GenerateRelocPadding();
   bool GenerateSafepointTable();
 
   void CallCode(Handle<Code> code, RelocInfo::Mode mode, LInstruction* instr,
@@ -200,6 +211,7 @@
                        int arguments,
                        int deoptimization_index);
   void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
+  void RecordSafepoint(int deoptimization_index);
   void RecordSafepointWithRegisters(LPointerMap* pointers,
                                     int arguments,
                                     int deoptimization_index);
@@ -247,6 +259,13 @@
   ZoneList<LDeferredCode*> deferred_;
   int osr_pc_offset_;
 
+  struct DeoptimizationRelocSize {
+    int min_size;
+    int last_pc_offset;
+  };
+
+  DeoptimizationRelocSize deoptimization_reloc_size;
+
   // Builder that keeps track of safepoints in the code. The table
   // itself is emitted at the end of the generated code.
   SafepointTableBuilder safepoints_;
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 0ad3819..4440cdf 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -404,7 +404,7 @@
 }
 
 
-void LStoreNamed::PrintDataTo(StringStream* stream) {
+void LStoreNamedField::PrintDataTo(StringStream* stream) {
   object()->PrintTo(stream);
   stream->Add(".");
   stream->Add(*String::cast(*name())->ToCString());
@@ -413,7 +413,25 @@
 }
 
 
-void LStoreKeyed::PrintDataTo(StringStream* stream) {
+void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
+  object()->PrintTo(stream);
+  stream->Add(".");
+  stream->Add(*String::cast(*name())->ToCString());
+  stream->Add(" <- ");
+  value()->PrintTo(stream);
+}
+
+
+void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
+  object()->PrintTo(stream);
+  stream->Add("[");
+  key()->PrintTo(stream);
+  stream->Add("] <- ");
+  value()->PrintTo(stream);
+}
+
+
+void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
   object()->PrintTo(stream);
   stream->Add("[");
   key()->PrintTo(stream);
@@ -451,7 +469,7 @@
   // shift all parameter indexes down by the number of parameters, and
   // make sure they end up negative so they are distinguishable from
   // spill slots.
-  int result = index - graph()->info()->scope()->num_parameters() - 1;
+  int result = index - info()->scope()->num_parameters() - 1;
   ASSERT(result < 0);
   return result;
 }
@@ -459,7 +477,7 @@
 // A parameter relative to ebp in the arguments stub.
 int LChunk::ParameterAt(int index) {
   ASSERT(-1 <= index);  // -1 is the receiver.
-  return (1 + graph()->info()->scope()->num_parameters() - index) *
+  return (1 + info()->scope()->num_parameters() - index) *
       kPointerSize;
 }
 
@@ -498,7 +516,7 @@
 
 LChunk* LChunkBuilder::Build() {
   ASSERT(is_unused());
-  chunk_ = new LChunk(graph());
+  chunk_ = new LChunk(info(), graph());
   HPhase phase("Building chunk", chunk_);
   status_ = BUILDING;
   const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
@@ -515,8 +533,8 @@
 
 void LChunkBuilder::Abort(const char* format, ...) {
   if (FLAG_trace_bailout) {
-    SmartPointer<char> debug_name = graph()->debug_name()->ToCString();
-    PrintF("Aborting LChunk building in @\"%s\": ", *debug_name);
+    SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
+    PrintF("Aborting LChunk building in @\"%s\": ", *name);
     va_list arguments;
     va_start(arguments, format);
     OS::VPrint(format, arguments);
@@ -852,6 +870,7 @@
   ASSERT(instr->representation().IsDouble());
   ASSERT(instr->left()->representation().IsDouble());
   ASSERT(instr->right()->representation().IsDouble());
+  ASSERT(op != Token::MOD);
   LOperand* left = UseRegisterAtStart(instr->left());
   LOperand* right = UseRegisterAtStart(instr->right());
   LArithmeticD* result = new LArithmeticD(op, left, right);
@@ -1147,8 +1166,7 @@
       new LInstanceOfKnownGlobal(
           UseFixed(instr->value(), InstanceofStub::left()),
           FixedTemp(edi));
-  MarkAsSaveDoubles(result);
-  return AssignEnvironment(AssignPointerMap(DefineFixed(result, eax)));
+  return MarkAsCall(DefineFixed(result, eax), instr);
 }
 
 
@@ -1223,7 +1241,7 @@
       case kMathSqrt:
         return DefineSameAsFirst(result);
       case kMathPowHalf:
-        return AssignEnvironment(DefineSameAsFirst(result));
+        return DefineSameAsFirst(result);
       default:
         UNREACHABLE();
         return NULL;
@@ -1366,8 +1384,8 @@
     // We call a C function for double modulo. It can't trigger a GC.
     // We need to use fixed result register for the call.
     // TODO(fschneider): Allow any register as input registers.
-    LOperand* left = UseFixedDouble(instr->left(), xmm1);
-    LOperand* right = UseFixedDouble(instr->right(), xmm2);
+    LOperand* left = UseFixedDouble(instr->left(), xmm2);
+    LOperand* right = UseFixedDouble(instr->right(), xmm1);
     LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
     return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
   }
@@ -1521,6 +1539,15 @@
 }
 
 
+LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
+    HGetCachedArrayIndex* instr)  {
+  ASSERT(instr->value()->representation().IsTagged());
+  LOperand* value = UseRegisterAtStart(instr->value());
+
+  return DefineAsRegister(new LGetCachedArrayIndex(value));
+}
+
+
 LInstruction* LChunkBuilder::DoHasCachedArrayIndex(
     HHasCachedArrayIndex* instr) {
   ASSERT(instr->value()->representation().IsTagged());
@@ -1833,6 +1860,23 @@
 }
 
 
+LInstruction* LChunkBuilder::DoStorePixelArrayElement(
+    HStorePixelArrayElement* instr) {
+  ASSERT(instr->value()->representation().IsInteger32());
+  ASSERT(instr->external_pointer()->representation().IsExternal());
+  ASSERT(instr->key()->representation().IsInteger32());
+
+  LOperand* external_pointer = UseRegister(instr->external_pointer());
+  LOperand* val = UseRegister(instr->value());
+  LOperand* key = UseRegister(instr->key());
+  // The generated code requires that the clamped value is in a byte
+  // register. eax is an arbitrary choice to satisfy this requirement.
+  LOperand* clamped = FixedTemp(eax);
+
+  return new LStorePixelArrayElement(external_pointer, key, val, clamped);
+}
+
+
 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), esi);
   LOperand* object = UseFixed(instr->object(), edx);
@@ -1916,8 +1960,8 @@
 
 
 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
-  LDeleteProperty* result = new LDeleteProperty(Use(instr->object()),
-                                                UseOrConstant(instr->key()));
+  LDeleteProperty* result =
+      new LDeleteProperty(Use(instr->object()), UseOrConstant(instr->key()));
   return MarkAsCall(DefineFixed(result, eax), instr);
 }
 
@@ -1950,8 +1994,10 @@
 
 
 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
-  // There are no real uses of the arguments object (we bail out in all other
-  // cases).
+  // There are no real uses of the arguments object.
+  // arguments.length and element access are supported directly on
+  // stack arguments, and any real arguments object use causes a bailout.
+  // So this value is never used.
   return NULL;
 }
 
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index f1b9ffc..f8cb871 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -42,8 +42,6 @@
 #define LITHIUM_ALL_INSTRUCTION_LIST(V)         \
   V(ControlInstruction)                         \
   V(Call)                                       \
-  V(StoreKeyed)                                 \
-  V(StoreNamed)                                 \
   LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
 
 
@@ -94,6 +92,7 @@
   V(FixedArrayLength)                           \
   V(FunctionLiteral)                            \
   V(Gap)                                        \
+  V(GetCachedArrayIndex)                        \
   V(GlobalObject)                               \
   V(GlobalReceiver)                             \
   V(Goto)                                       \
@@ -150,6 +149,7 @@
   V(StoreKeyedGeneric)                          \
   V(StoreNamedField)                            \
   V(StoreNamedGeneric)                          \
+  V(StorePixelArrayElement)                     \
   V(StringCharCodeAt)                           \
   V(StringLength)                               \
   V(SubI)                                       \
@@ -744,6 +744,17 @@
 };
 
 
+class LGetCachedArrayIndex: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LGetCachedArrayIndex(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index")
+  DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex)
+};
+
+
 class LHasCachedArrayIndex: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LHasCachedArrayIndex(LOperand* value) {
@@ -1580,34 +1591,23 @@
 };
 
 
-class LStoreNamed: public LTemplateInstruction<0, 2, 1> {
+class LStoreNamedField: public LTemplateInstruction<0, 2, 1> {
  public:
-  LStoreNamed(LOperand* obj, LOperand* val) {
+  LStoreNamedField(LOperand* obj, LOperand* val, LOperand* temp) {
     inputs_[0] = obj;
     inputs_[1] = val;
-  }
-
-  DECLARE_INSTRUCTION(StoreNamed)
-  DECLARE_HYDROGEN_ACCESSOR(StoreNamed)
-
-  virtual void PrintDataTo(StringStream* stream);
-
-  LOperand* object() { return inputs_[0]; }
-  LOperand* value() { return inputs_[1]; }
-  Handle<Object> name() const { return hydrogen()->name(); }
-};
-
-
-class LStoreNamedField: public LStoreNamed {
- public:
-  LStoreNamedField(LOperand* obj, LOperand* val, LOperand* temp)
-      : LStoreNamed(obj, val) {
     temps_[0] = temp;
   }
 
   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
   DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
 
+  virtual void PrintDataTo(StringStream* stream);
+
+  LOperand* object() { return inputs_[0]; }
+  LOperand* value() { return inputs_[1]; }
+
+  Handle<Object> name() const { return hydrogen()->name(); }
   bool is_in_object() { return hydrogen()->is_in_object(); }
   int offset() { return hydrogen()->offset(); }
   bool needs_write_barrier() { return hydrogen()->NeedsWriteBarrier(); }
@@ -1626,6 +1626,8 @@
   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
   DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
 
+  virtual void PrintDataTo(StringStream* stream);
+
   LOperand* context() { return inputs_[0]; }
   LOperand* object() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
@@ -1633,15 +1635,17 @@
 };
 
 
-class LStoreKeyed: public LTemplateInstruction<0, 3, 0> {
+class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
  public:
-  LStoreKeyed(LOperand* obj, LOperand* key, LOperand* val) {
+  LStoreKeyedFastElement(LOperand* obj, LOperand* key, LOperand* val) {
     inputs_[0] = obj;
     inputs_[1] = key;
     inputs_[2] = val;
   }
 
-  DECLARE_INSTRUCTION(StoreKeyed)
+  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
+                               "store-keyed-fast-element")
+  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastElement)
 
   virtual void PrintDataTo(StringStream* stream);
 
@@ -1651,14 +1655,25 @@
 };
 
 
-class LStoreKeyedFastElement: public LStoreKeyed {
+class LStorePixelArrayElement: public LTemplateInstruction<0, 3, 1> {
  public:
-  LStoreKeyedFastElement(LOperand* obj, LOperand* key, LOperand* val)
-      : LStoreKeyed(obj, key, val) {}
+  LStorePixelArrayElement(LOperand* external_pointer,
+                          LOperand* key,
+                          LOperand* val,
+                          LOperand* clamped) {
+    inputs_[0] = external_pointer;
+    inputs_[1] = key;
+    inputs_[2] = val;
+    temps_[0] = clamped;
+  }
 
-  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
-                               "store-keyed-fast-element")
-  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastElement)
+  DECLARE_CONCRETE_INSTRUCTION(StorePixelArrayElement,
+                               "store-pixel-array-element")
+  DECLARE_HYDROGEN_ACCESSOR(StorePixelArrayElement)
+
+  LOperand* external_pointer() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
+  LOperand* value() { return inputs_[2]; }
 };
 
 
@@ -1676,6 +1691,8 @@
 
   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
 
+  virtual void PrintDataTo(StringStream* stream);
+
   LOperand* context() { return inputs_[0]; }
   LOperand* object() { return inputs_[1]; }
   LOperand* key() { return inputs_[2]; }
@@ -1900,8 +1917,9 @@
 class LChunkBuilder;
 class LChunk: public ZoneObject {
  public:
-  explicit LChunk(HGraph* graph)
+  explicit LChunk(CompilationInfo* info, HGraph* graph)
     : spill_slot_count_(0),
+      info_(info),
       graph_(graph),
       instructions_(32),
       pointer_maps_(8),
@@ -1918,6 +1936,7 @@
   int ParameterAt(int index);
   int GetParameterStackSlot(int index) const;
   int spill_slot_count() const { return spill_slot_count_; }
+  CompilationInfo* info() const { return info_; }
   HGraph* graph() const { return graph_; }
   const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
   void AddGapMove(int index, LOperand* from, LOperand* to);
@@ -1954,6 +1973,7 @@
 
  private:
   int spill_slot_count_;
+  CompilationInfo* info_;
   HGraph* const graph_;
   ZoneList<LInstruction*> instructions_;
   ZoneList<LPointerMap*> pointer_maps_;
@@ -1963,8 +1983,9 @@
 
 class LChunkBuilder BASE_EMBEDDED {
  public:
-  LChunkBuilder(HGraph* graph, LAllocator* allocator)
+  LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator)
       : chunk_(NULL),
+        info_(info),
         graph_(graph),
         status_(UNUSED),
         current_instruction_(NULL),
@@ -1993,6 +2014,7 @@
   };
 
   LChunk* chunk() const { return chunk_; }
+  CompilationInfo* info() const { return info_; }
   HGraph* graph() const { return graph_; }
 
   bool is_unused() const { return status_ == UNUSED; }
@@ -2099,6 +2121,7 @@
                               HArithmeticBinaryOperation* instr);
 
   LChunk* chunk_;
+  CompilationInfo* info_;
   HGraph* const graph_;
   Status status_;
   HInstruction* current_instruction_;
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index cd612b5..91b6651 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -448,6 +448,97 @@
 }
 
 
+void MacroAssembler::Throw(Register value) {
+  // Adjust this code if not the case.
+  STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
+
+  // eax must hold the exception.
+  if (!value.is(eax)) {
+    mov(eax, value);
+  }
+
+  // Drop the sp to the top of the handler.
+  ExternalReference handler_address(Top::k_handler_address);
+  mov(esp, Operand::StaticVariable(handler_address));
+
+  // Restore next handler and frame pointer, discard handler state.
+  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
+  pop(Operand::StaticVariable(handler_address));
+  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize);
+  pop(ebp);
+  pop(edx);  // Remove state.
+
+  // Before returning we restore the context from the frame pointer if
+  // not NULL.  The frame pointer is NULL in the exception handler of
+  // a JS entry frame.
+  Set(esi, Immediate(0));  // Tentatively set context pointer to NULL.
+  NearLabel skip;
+  cmp(ebp, 0);
+  j(equal, &skip, not_taken);
+  mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  bind(&skip);
+
+  STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
+  ret(0);
+}
+
+
+void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
+                                      Register value) {
+  // Adjust this code if not the case.
+  STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
+
+  // eax must hold the exception.
+  if (!value.is(eax)) {
+    mov(eax, value);
+  }
+
+  // Drop sp to the top stack handler.
+  ExternalReference handler_address(Top::k_handler_address);
+  mov(esp, Operand::StaticVariable(handler_address));
+
+  // Unwind the handlers until the ENTRY handler is found.
+  NearLabel loop, done;
+  bind(&loop);
+  // Load the type of the current stack handler.
+  const int kStateOffset = StackHandlerConstants::kStateOffset;
+  cmp(Operand(esp, kStateOffset), Immediate(StackHandler::ENTRY));
+  j(equal, &done);
+  // Fetch the next handler in the list.
+  const int kNextOffset = StackHandlerConstants::kNextOffset;
+  mov(esp, Operand(esp, kNextOffset));
+  jmp(&loop);
+  bind(&done);
+
+  // Set the top handler address to next handler past the current ENTRY handler.
+  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
+  pop(Operand::StaticVariable(handler_address));
+
+  if (type == OUT_OF_MEMORY) {
+    // Set external caught exception to false.
+    ExternalReference external_caught(Top::k_external_caught_exception_address);
+    mov(eax, false);
+    mov(Operand::StaticVariable(external_caught), eax);
+
+    // Set pending exception and eax to out of memory exception.
+    ExternalReference pending_exception(Top::k_pending_exception_address);
+    mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
+    mov(Operand::StaticVariable(pending_exception), eax);
+  }
+
+  // Clear the context pointer.
+  Set(esi, Immediate(0));
+
+  // Restore fp from handler and discard handler state.
+  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize);
+  pop(ebp);
+  pop(edx);  // State.
+
+  STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
+  ret(0);
+}
+
+
 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
                                             Register scratch,
                                             Label* miss) {
@@ -1192,7 +1283,7 @@
 // If false, it is returned as a pointer to a preallocated by caller memory
 // region. Pointer to this region should be passed to a function as an
 // implicit first argument.
-#if defined(USING_BSD_ABI) || defined(__MINGW32__)
+#if defined(USING_BSD_ABI) || defined(__MINGW32__) || defined(__CYGWIN__)
 static const bool kReturnHandlesDirectly = true;
 #else
 static const bool kReturnHandlesDirectly = false;
@@ -1563,6 +1654,28 @@
 }
 
 
+// Store the value in register src in the safepoint register stack
+// slot for register dst.
+void MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
+  mov(SafepointRegisterSlot(dst), src);
+}
+
+
+void MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Immediate src) {
+  mov(SafepointRegisterSlot(dst), src);
+}
+
+
+void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
+  mov(dst, SafepointRegisterSlot(src));
+}
+
+
+Operand MacroAssembler::SafepointRegisterSlot(Register reg) {
+  return Operand(esp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
+}
+
+
 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
   // The registers are pushed starting with the lowest encoding,
   // which means that lowest encodings are furthest away from
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index 09584f7..62bb0f3 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -143,7 +143,11 @@
   // Push and pop the registers that can hold pointers.
   void PushSafepointRegisters() { pushad(); }
   void PopSafepointRegisters() { popad(); }
-  static int SafepointRegisterStackIndex(int reg_code);
+  // Store the value in register/immediate src in the safepoint
+  // register stack slot for register dst.
+  void StoreToSafepointRegisterSlot(Register dst, Register src);
+  void StoreToSafepointRegisterSlot(Register dst, Immediate src);
+  void LoadFromSafepointRegisterSlot(Register dst, Register src);
 
   // ---------------------------------------------------------------------------
   // JavaScript invokes
@@ -304,6 +308,11 @@
   // Unlink the stack handler on top of the stack from the try handler chain.
   void PopTryHandler();
 
+  // Activate the top handler in the try hander chain.
+  void Throw(Register value);
+
+  void ThrowUncatchable(UncatchableExceptionType type, Register value);
+
   // ---------------------------------------------------------------------------
   // Inline caching support
 
@@ -662,6 +671,15 @@
   MUST_USE_RESULT MaybeObject* PopHandleScopeHelper(Register saved,
                                                     Register scratch,
                                                     bool gc_allowed);
+
+
+  // Compute memory operands for safepoint stack slots.
+  Operand SafepointRegisterSlot(Register reg);
+  static int SafepointRegisterStackIndex(int reg_code);
+
+  // Needs access to SafepointRegisterStackIndex for optimized frame
+  // traversal.
+  friend class OptimizedFrame;
 };
 
 
diff --git a/src/ia32/simulator-ia32.h b/src/ia32/simulator-ia32.h
index 88d0b61..43b7ea3 100644
--- a/src/ia32/simulator-ia32.h
+++ b/src/ia32/simulator-ia32.h
@@ -38,10 +38,15 @@
 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
   (entry(p0, p1, p2, p3, p4))
 
-// Call the generated regexp code directly. The entry function pointer should
+
+typedef int (*regexp_matcher)(String*, int, const byte*,
+                              const byte*, int*, Address, int);
+
+// Call the generated regexp code directly. The code at the entry address should
 // expect seven int/pointer sized arguments and return an int.
 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
-  (entry(p0, p1, p2, p3, p4, p5, p6))
+  (FUNCTION_CAST<regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6))
+
 
 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
   (reinterpret_cast<TryCatch*>(try_catch_address))
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index f96ef5c..633097a 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -2204,8 +2204,9 @@
       break;
 
     case STRING_CHECK:
-      if (!function->IsBuiltin()) {
-        // Calling non-builtins with a value as receiver requires boxing.
+      if (!function->IsBuiltin() && !function_info->strict_mode()) {
+        // Calling non-strict non-builtins with a value as the receiver
+        // requires boxing.
         __ jmp(&miss);
       } else {
         // Check that the object is a string or a symbol.
@@ -2220,8 +2221,9 @@
       break;
 
     case NUMBER_CHECK: {
-      if (!function->IsBuiltin()) {
-        // Calling non-builtins with a value as receiver requires boxing.
+      if (!function->IsBuiltin() && !function_info->strict_mode()) {
+        // Calling non-strict non-builtins with a value as the receiver
+        // requires boxing.
         __ jmp(&miss);
       } else {
         Label fast;
@@ -2241,8 +2243,9 @@
     }
 
     case BOOLEAN_CHECK: {
-      if (!function->IsBuiltin()) {
-        // Calling non-builtins with a value as receiver requires boxing.
+      if (!function->IsBuiltin() && !function_info->strict_mode()) {
+        // Calling non-strict non-builtins with a value as the receiver
+        // requires boxing.
         __ jmp(&miss);
       } else {
         Label fast;
@@ -2549,12 +2552,13 @@
   __ push(edx);  // receiver
   __ push(ecx);  // name
   __ push(eax);  // value
+  __ push(Immediate(Smi::FromInt(strict_mode_)));
   __ push(ebx);  // restore return address
 
   // Do tail-call to the runtime system.
   ExternalReference store_ic_property =
       ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
-  __ TailCallExternalReference(store_ic_property, 3, 1);
+  __ TailCallExternalReference(store_ic_property, 4, 1);
 
   // Handle store cache miss.
   __ bind(&miss);
@@ -2586,8 +2590,8 @@
   // Compute the cell operand to use.
   Operand cell_operand = Operand::Cell(Handle<JSGlobalPropertyCell>(cell));
   if (Serializer::enabled()) {
-    __ mov(ecx, Immediate(Handle<JSGlobalPropertyCell>(cell)));
-    cell_operand = FieldOperand(ecx, JSGlobalPropertyCell::kValueOffset);
+    __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell)));
+    cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset);
   }
 
   // Check that the value in the cell is not the hole. If it is, this
@@ -2709,6 +2713,42 @@
 }
 
 
+MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray(
+    JSObject* receiver) {
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  //  -- ecx    : key
+  //  -- edx    : receiver
+  //  -- esp[0] : return address
+  // -----------------------------------
+  Label miss;
+
+  // Check that the map matches.
+  __ CheckMap(edx, Handle<Map>(receiver->map()), &miss, false);
+
+  // Do the load.
+  GenerateFastPixelArrayStore(masm(),
+                              edx,
+                              ecx,
+                              eax,
+                              edi,
+                              ebx,
+                              true,
+                              &miss,
+                              &miss,
+                              NULL,
+                              &miss);
+
+  // Handle store cache miss.
+  __ bind(&miss);
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
+  __ jmp(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(NORMAL, NULL);
+}
+
+
 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
                                                       JSObject* object,
                                                       JSObject* last) {
@@ -3673,10 +3713,13 @@
   __ push(edx);
   __ push(ecx);
   __ push(eax);
-  __ push(ebx);
+  __ push(Immediate(Smi::FromInt(NONE)));   // PropertyAttributes
+  __ push(Immediate(Smi::FromInt(
+      Code::ExtractExtraICStateFromFlags(flags) & kStrictMode)));
+  __ push(ebx);   // return address
 
   // Do tail-call to runtime routine.
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 
   return GetCode(flags);
 }
diff --git a/src/ia32/virtual-frame-ia32.cc b/src/ia32/virtual-frame-ia32.cc
index 1cc91a9..93d711e 100644
--- a/src/ia32/virtual-frame-ia32.cc
+++ b/src/ia32/virtual-frame-ia32.cc
@@ -1038,9 +1038,9 @@
                                  StrictModeFlag strict_mode) {
   // Value and (if not contextual) receiver are on top of the frame.
   // The IC expects name in ecx, value in eax, and receiver in edx.
-  Handle<Code> ic(Builtins::builtin(strict_mode == kStrictMode
-      ? Builtins::StoreIC_Initialize_Strict
-      : Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode == kStrictMode) ? Builtins::StoreIC_Initialize_Strict
+                                   : Builtins::StoreIC_Initialize));
 
   Result value = Pop();
   RelocInfo::Mode mode;
@@ -1061,7 +1061,7 @@
 }
 
 
-Result VirtualFrame::CallKeyedStoreIC() {
+Result VirtualFrame::CallKeyedStoreIC(StrictModeFlag strict_mode) {
   // Value, key, and receiver are on the top of the frame.  The IC
   // expects value in eax, key in ecx, and receiver in edx.
   Result value = Pop();
@@ -1105,7 +1105,9 @@
     receiver.Unuse();
   }
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
+                                   : Builtins::KeyedStoreIC_Initialize));
   return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
 }
 
@@ -1306,6 +1308,7 @@
 
 
 void VirtualFrame::PushUntaggedElement(Handle<Object> value) {
+  ASSERT(!ConstantPoolOverflowed());
   elements_.Add(FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED));
   elements_[element_count() - 1].set_untagged_int32(true);
 }
@@ -1336,6 +1339,20 @@
 }
 
 
+void VirtualFrame::Push(Handle<Object> value) {
+  if (ConstantPoolOverflowed()) {
+    Result temp = cgen()->allocator()->Allocate();
+    ASSERT(temp.is_valid());
+    __ Set(temp.reg(), Immediate(value));
+    Push(&temp);
+  } else {
+    FrameElement element =
+        FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED);
+    elements_.Add(element);
+  }
+}
+
+
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/ia32/virtual-frame-ia32.h b/src/ia32/virtual-frame-ia32.h
index 729469f..5187430 100644
--- a/src/ia32/virtual-frame-ia32.h
+++ b/src/ia32/virtual-frame-ia32.h
@@ -370,7 +370,7 @@
 
   // Call keyed store IC.  Value, key, and receiver are found on top
   // of the frame.  All three are dropped.
-  Result CallKeyedStoreIC();
+  Result CallKeyedStoreIC(StrictModeFlag strict_mode);
 
   // Call call IC.  Function name, arguments, and receiver are found on top
   // of the frame and dropped by the call.  The argument count does not
@@ -419,9 +419,11 @@
   void EmitPush(Immediate immediate,
                 TypeInfo info = TypeInfo::Unknown());
 
+  inline bool ConstantPoolOverflowed();
+
   // Push an element on the virtual frame.
+  void Push(Handle<Object> value);
   inline void Push(Register reg, TypeInfo info = TypeInfo::Unknown());
-  inline void Push(Handle<Object> value);
   inline void Push(Smi* value);
 
   void PushUntaggedElement(Handle<Object> value);
diff --git a/src/ic-inl.h b/src/ic-inl.h
index 8fbc184..9d358ed 100644
--- a/src/ic-inl.h
+++ b/src/ic-inl.h
@@ -76,6 +76,15 @@
 
 void IC::SetTargetAtAddress(Address address, Code* target) {
   ASSERT(target->is_inline_cache_stub() || target->is_compare_ic_stub());
+#ifdef DEBUG
+  // STORE_IC and KEYED_STORE_IC use Code::extra_ic_state() to mark
+  // ICs as strict mode. The strict-ness of the IC must be preserved.
+  Code* old_target = GetTargetAtAddress(address);
+  if (old_target->kind() == Code::STORE_IC ||
+      old_target->kind() == Code::KEYED_STORE_IC) {
+    ASSERT(old_target->extra_ic_state() == target->extra_ic_state());
+  }
+#endif
   Assembler::set_target_address_at(address, target->instruction_start());
 }
 
diff --git a/src/ic.cc b/src/ic.cc
index 62ab0f2..087a959 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -343,7 +343,7 @@
   if (target->ic_state() == UNINITIALIZED) return;
   ClearInlinedVersion(address);
   SetTargetAtAddress(address,
-      target->extra_ic_state() == kStoreICStrict
+      (target->extra_ic_state() == kStrictMode)
         ? initialize_stub_strict()
         : initialize_stub());
 }
@@ -366,7 +366,10 @@
 
 void KeyedStoreIC::Clear(Address address, Code* target) {
   if (target->ic_state() == UNINITIALIZED) return;
-  SetTargetAtAddress(address, initialize_stub());
+  SetTargetAtAddress(address,
+      (target->extra_ic_state() == kStrictMode)
+        ? initialize_stub_strict()
+        : initialize_stub());
 }
 
 
@@ -435,16 +438,25 @@
 }
 
 
-void CallICBase::ReceiverToObject(Handle<Object> object) {
-  HandleScope scope;
-  Handle<Object> receiver(object);
+void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee,
+                                            Handle<Object> object) {
+  if (callee->IsJSFunction()) {
+    Handle<JSFunction> function = Handle<JSFunction>::cast(callee);
+    if (function->shared()->strict_mode() || function->IsBuiltin()) {
+      // Do not wrap receiver for strict mode functions or for builtins.
+      return;
+    }
+  }
 
-  // Change the receiver to the result of calling ToObject on it.
-  const int argc = this->target()->arguments_count();
-  StackFrameLocator locator;
-  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
-  int index = frame->ComputeExpressionsCount() - (argc + 1);
-  frame->SetExpression(index, *Factory::ToObject(object));
+  // And only wrap string, number or boolean.
+  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
+    // Change the receiver to the result of calling ToObject on it.
+    const int argc = this->target()->arguments_count();
+    StackFrameLocator locator;
+    JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
+    int index = frame->ComputeExpressionsCount() - (argc + 1);
+    frame->SetExpression(index, *Factory::ToObject(object));
+  }
 }
 
 
@@ -458,10 +470,6 @@
     return TypeError("non_object_property_call", object, name);
   }
 
-  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
-    ReceiverToObject(object);
-  }
-
   // Check if the name is trivially convertible to an index and get
   // the element if so.
   uint32_t index;
@@ -505,6 +513,7 @@
         object->GetProperty(*object, &lookup, *name, &attr);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
+
   if (lookup.type() == INTERCEPTOR) {
     // If the object does not have the requested property, check which
     // exception we need to throw.
@@ -516,31 +525,37 @@
     }
   }
 
-  ASSERT(result != Heap::the_hole_value());
+  ASSERT(!result->IsTheHole());
 
-  if (result->IsJSFunction()) {
+  HandleScope scope;
+  // Wrap result in a handle because ReceiverToObjectIfRequired may allocate
+  // new object and cause GC.
+  Handle<Object> result_handle(result);
+  // Make receiver an object if the callee requires it. Strict mode or builtin
+  // functions do not wrap the receiver, non-strict functions and objects
+  // called as functions do.
+  ReceiverToObjectIfRequired(result_handle, object);
+
+  if (result_handle->IsJSFunction()) {
 #ifdef ENABLE_DEBUGGER_SUPPORT
     // Handle stepping into a function if step into is active.
     if (Debug::StepInActive()) {
       // Protect the result in a handle as the debugger can allocate and might
       // cause GC.
-      HandleScope scope;
-      Handle<JSFunction> function(JSFunction::cast(result));
+      Handle<JSFunction> function(JSFunction::cast(*result_handle));
       Debug::HandleStepIn(function, object, fp(), false);
       return *function;
     }
 #endif
 
-    return result;
+    return *result_handle;
   }
 
   // Try to find a suitable function delegate for the object at hand.
-  result = TryCallAsFunction(result);
-  MaybeObject* answer = result;
-  if (!result->IsJSFunction()) {
-    answer = TypeError("property_not_function", object, name);
-  }
-  return answer;
+  result_handle = Handle<Object>(TryCallAsFunction(*result_handle));
+  if (result_handle->IsJSFunction()) return *result_handle;
+
+  return TypeError("property_not_function", object, name);
 }
 
 
@@ -565,8 +580,8 @@
     case kStringCharAt:
       if (object->IsString()) {
         String* string = String::cast(*object);
-        // Check that there's the right wrapper in the receiver slot.
-        ASSERT(string == JSValue::cast(args[0])->value());
+        // Check there's the right string value or wrapper in the receiver slot.
+        ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
         // If we're in the default (fastest) state and the index is
         // out of bounds, update the state to record this fact.
         if (*extra_ic_state == DEFAULT_STRING_STUB &&
@@ -775,10 +790,6 @@
     return TypeError("non_object_property_call", object, key);
   }
 
-  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
-    ReceiverToObject(object);
-  }
-
   if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) {
     int argc = target()->arguments_count();
     InLoopFlag in_loop = target()->ic_in_loop();
@@ -793,17 +804,21 @@
 #endif
     }
   }
-  Object* result;
-  { MaybeObject* maybe_result = Runtime::GetObjectProperty(object, key);
-    if (!maybe_result->ToObject(&result)) return maybe_result;
-  }
-  if (result->IsJSFunction()) return result;
-  result = TryCallAsFunction(result);
-  MaybeObject* answer = result;
-  if (!result->IsJSFunction()) {
-    answer = TypeError("property_not_function", object, key);
-  }
-  return answer;
+
+  HandleScope scope;
+  Handle<Object> result = GetProperty(object, key);
+  RETURN_IF_EMPTY_HANDLE(result);
+
+  // Make receiver an object if the callee requires it. Strict mode or builtin
+  // functions do not wrap the receiver, non-strict functions and objects
+  // called as functions do.
+  ReceiverToObjectIfRequired(result, object);
+
+  if (result->IsJSFunction()) return *result;
+  result = Handle<Object>(TryCallAsFunction(*result));
+  if (result->IsJSFunction()) return *result;
+
+  return TypeError("property_not_function", object, key);
 }
 
 
@@ -1215,7 +1230,8 @@
         if (receiver->HasExternalArrayElements()) {
           MaybeObject* probe =
               StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver,
-                                                              false);
+                                                              false,
+                                                              kNonStrictMode);
           stub = probe->IsFailure() ?
               NULL : Code::cast(probe->ToObjectUnchecked());
         } else if (receiver->HasIndexedInterceptor()) {
@@ -1371,7 +1387,7 @@
 
 
 MaybeObject* StoreIC::Store(State state,
-                            Code::ExtraICState extra_ic_state,
+                            StrictModeFlag strict_mode,
                             Handle<Object> object,
                             Handle<String> name,
                             Handle<Object> value) {
@@ -1381,15 +1397,23 @@
     return TypeError("non_object_property_store", object, name);
   }
 
-  // Ignore stores where the receiver is not a JSObject.
-  if (!object->IsJSObject()) return *value;
+  if (!object->IsJSObject()) {
+    // The length property of string values is read-only. Throw in strict mode.
+    if (strict_mode == kStrictMode && object->IsString() &&
+        name->Equals(Heap::length_symbol())) {
+      return TypeError("strict_read_only_property", object, name);
+    }
+    // Ignore stores where the receiver is not a JSObject.
+    return *value;
+  }
+
   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
 
   // Check if the given name is an array index.
   uint32_t index;
   if (name->AsArrayIndex(&index)) {
     HandleScope scope;
-    Handle<Object> result = SetElement(receiver, index, value);
+    Handle<Object> result = SetElement(receiver, index, value, strict_mode);
     if (result.is_null()) return Failure::Exception();
     return *value;
   }
@@ -1401,11 +1425,11 @@
 #ifdef DEBUG
     if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
 #endif
-    Builtins::Name target = (extra_ic_state == kStoreICStrict)
+    Builtins::Name target = (strict_mode == kStrictMode)
         ? Builtins::StoreIC_ArrayLength_Strict
         : Builtins::StoreIC_ArrayLength;
     set_target(Builtins::builtin(target));
-    return receiver->SetProperty(*name, *value, NONE);
+    return receiver->SetProperty(*name, *value, NONE, strict_mode);
   }
 
   // Lookup the property locally in the receiver.
@@ -1429,13 +1453,15 @@
           // Index is an offset from the end of the object.
           int offset = map->instance_size() + (index * kPointerSize);
           if (PatchInlinedStore(address(), map, offset)) {
-            set_target(megamorphic_stub());
+            set_target((strict_mode == kStrictMode)
+                         ? megamorphic_stub_strict()
+                         : megamorphic_stub());
 #ifdef DEBUG
             if (FLAG_trace_ic) {
               PrintF("[StoreIC : inline patch %s]\n", *name->ToCString());
             }
 #endif
-            return receiver->SetProperty(*name, *value, NONE);
+            return receiver->SetProperty(*name, *value, NONE, strict_mode);
 #ifdef DEBUG
 
           } else {
@@ -1462,11 +1488,16 @@
 
       // If no inlined store ic was patched, generate a stub for this
       // store.
-      UpdateCaches(&lookup, state, extra_ic_state, receiver, name, value);
+      UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
     } else {
-      // Strict mode doesn't allow setting non-existent global property.
-      if (extra_ic_state == kStoreICStrict && IsContextual(object)) {
-        return ReferenceError("not_defined", name);
+      // Strict mode doesn't allow setting non-existent global property
+      // or an assignment to a read only property.
+      if (strict_mode == kStrictMode) {
+        if (lookup.IsFound() && lookup.IsReadOnly()) {
+          return TypeError("strict_read_only_property", object, name);
+        } else if (IsContextual(object)) {
+          return ReferenceError("not_defined", name);
+        }
       }
     }
   }
@@ -1474,7 +1505,7 @@
   if (receiver->IsJSGlobalProxy()) {
     // Generate a generic stub that goes to the runtime when we see a global
     // proxy as receiver.
-    Code* stub = (extra_ic_state == kStoreICStrict)
+    Code* stub = (strict_mode == kStrictMode)
         ? global_proxy_stub_strict()
         : global_proxy_stub();
     if (target() != stub) {
@@ -1486,13 +1517,13 @@
   }
 
   // Set the property.
-  return receiver->SetProperty(*name, *value, NONE);
+  return receiver->SetProperty(*name, *value, NONE, strict_mode);
 }
 
 
 void StoreIC::UpdateCaches(LookupResult* lookup,
                            State state,
-                           Code::ExtraICState extra_ic_state,
+                           StrictModeFlag strict_mode,
                            Handle<JSObject> receiver,
                            Handle<String> name,
                            Handle<Object> value) {
@@ -1514,7 +1545,7 @@
   switch (type) {
     case FIELD: {
       maybe_code = StubCache::ComputeStoreField(
-          *name, *receiver, lookup->GetFieldIndex(), NULL, extra_ic_state);
+          *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
       break;
     }
     case MAP_TRANSITION: {
@@ -1524,7 +1555,7 @@
       Handle<Map> transition(lookup->GetTransitionMap());
       int index = transition->PropertyIndexFor(*name);
       maybe_code = StubCache::ComputeStoreField(
-          *name, *receiver, index, *transition, extra_ic_state);
+          *name, *receiver, index, *transition, strict_mode);
       break;
     }
     case NORMAL: {
@@ -1536,10 +1567,10 @@
         JSGlobalPropertyCell* cell =
             JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
         maybe_code = StubCache::ComputeStoreGlobal(
-            *name, *global, cell, extra_ic_state);
+            *name, *global, cell, strict_mode);
       } else {
         if (lookup->holder() != *receiver) return;
-        maybe_code = StubCache::ComputeStoreNormal(extra_ic_state);
+        maybe_code = StubCache::ComputeStoreNormal(strict_mode);
       }
       break;
     }
@@ -1548,13 +1579,13 @@
       AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
       if (v8::ToCData<Address>(callback->setter()) == 0) return;
       maybe_code = StubCache::ComputeStoreCallback(
-          *name, *receiver, callback, extra_ic_state);
+          *name, *receiver, callback, strict_mode);
       break;
     }
     case INTERCEPTOR: {
       ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
       maybe_code = StubCache::ComputeStoreInterceptor(
-          *name, *receiver, extra_ic_state);
+          *name, *receiver, strict_mode);
       break;
     }
     default:
@@ -1571,7 +1602,7 @@
   } else if (state == MONOMORPHIC) {
     // Only move to megamorphic if the target changes.
     if (target() != Code::cast(code)) {
-      set_target(extra_ic_state == kStoreICStrict
+      set_target((strict_mode == kStrictMode)
                    ? megamorphic_stub_strict()
                    : megamorphic_stub());
     }
@@ -1587,6 +1618,7 @@
 
 
 MaybeObject* KeyedStoreIC::Store(State state,
+                                 StrictModeFlag strict_mode,
                                  Handle<Object> object,
                                  Handle<Object> key,
                                  Handle<Object> value) {
@@ -1607,7 +1639,7 @@
     uint32_t index;
     if (name->AsArrayIndex(&index)) {
       HandleScope scope;
-      Handle<Object> result = SetElement(receiver, index, value);
+      Handle<Object> result = SetElement(receiver, index, value, strict_mode);
       if (result.is_null()) return Failure::Exception();
       return *value;
     }
@@ -1618,11 +1650,11 @@
 
     // Update inline cache and stub cache.
     if (FLAG_use_ic) {
-      UpdateCaches(&lookup, state, receiver, name, value);
+      UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
     }
 
     // Set the property.
-    return receiver->SetProperty(*name, *value, NONE);
+    return receiver->SetProperty(*name, *value, NONE, strict_mode);
   }
 
   // Do not use ICs for objects that require access checks (including
@@ -1631,32 +1663,41 @@
   ASSERT(!(use_ic && object->IsJSGlobalProxy()));
 
   if (use_ic) {
-    Code* stub = generic_stub();
-    if (object->IsJSObject()) {
-      Handle<JSObject> receiver = Handle<JSObject>::cast(object);
-      if (receiver->HasExternalArrayElements()) {
-        MaybeObject* probe =
-            StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver, true);
-        stub =
-            probe->IsFailure() ? NULL : Code::cast(probe->ToObjectUnchecked());
-      } else if (state == UNINITIALIZED &&
-                 key->IsSmi() &&
-                 receiver->map()->has_fast_elements()) {
-        MaybeObject* probe = StubCache::ComputeKeyedStoreSpecialized(*receiver);
-        stub =
-            probe->IsFailure() ? NULL : Code::cast(probe->ToObjectUnchecked());
+    Code* stub =
+        (strict_mode == kStrictMode) ? generic_stub_strict() : generic_stub();
+    if (state == UNINITIALIZED) {
+      if (object->IsJSObject()) {
+        Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+        if (receiver->HasExternalArrayElements()) {
+          MaybeObject* probe =
+              StubCache::ComputeKeyedLoadOrStoreExternalArray(
+                  *receiver, true, strict_mode);
+          stub = probe->IsFailure() ?
+              NULL : Code::cast(probe->ToObjectUnchecked());
+        } else if (receiver->HasPixelElements()) {
+          MaybeObject* probe =
+              StubCache::ComputeKeyedStorePixelArray(*receiver, strict_mode);
+          stub = probe->IsFailure() ?
+              NULL : Code::cast(probe->ToObjectUnchecked());
+        } else if (key->IsSmi() && receiver->map()->has_fast_elements()) {
+          MaybeObject* probe =
+              StubCache::ComputeKeyedStoreSpecialized(*receiver, strict_mode);
+          stub = probe->IsFailure() ?
+              NULL : Code::cast(probe->ToObjectUnchecked());
+        }
       }
     }
     if (stub != NULL) set_target(stub);
   }
 
   // Set the property.
-  return Runtime::SetObjectProperty(object, key, value, NONE);
+  return Runtime::SetObjectProperty(object, key, value, NONE, strict_mode);
 }
 
 
 void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
                                 State state,
+                                StrictModeFlag strict_mode,
                                 Handle<JSObject> receiver,
                                 Handle<String> name,
                                 Handle<Object> value) {
@@ -1683,8 +1724,8 @@
 
   switch (type) {
     case FIELD: {
-      maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver,
-                                                     lookup->GetFieldIndex());
+      maybe_code = StubCache::ComputeKeyedStoreField(
+          *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
       break;
     }
     case MAP_TRANSITION: {
@@ -1693,8 +1734,8 @@
         ASSERT(type == MAP_TRANSITION);
         Handle<Map> transition(lookup->GetTransitionMap());
         int index = transition->PropertyIndexFor(*name);
-        maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver,
-                                                       index, *transition);
+        maybe_code = StubCache::ComputeKeyedStoreField(
+            *name, *receiver, index, *transition, strict_mode);
         break;
       }
       // fall through.
@@ -1702,7 +1743,9 @@
     default: {
       // Always rewrite to the generic case so that we do not
       // repeatedly try to rewrite.
-      maybe_code = generic_stub();
+      maybe_code = (strict_mode == kStrictMode)
+          ? generic_stub_strict()
+          : generic_stub();
       break;
     }
   }
@@ -1717,7 +1760,9 @@
   if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
     set_target(Code::cast(code));
   } else if (state == MONOMORPHIC) {
-    set_target(megamorphic_stub());
+    set_target((strict_mode == kStrictMode)
+                 ? megamorphic_stub_strict()
+                 : megamorphic_stub());
   }
 
 #ifdef DEBUG
@@ -1818,8 +1863,11 @@
   StoreIC ic;
   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
-  return ic.Store(state, extra_ic_state, args.at<Object>(0),
-                  args.at<String>(1), args.at<Object>(2));
+  return ic.Store(state,
+                  static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
+                  args.at<Object>(0),
+                  args.at<String>(1),
+                  args.at<Object>(2));
 }
 
 
@@ -1883,7 +1931,11 @@
   ASSERT(args.length() == 3);
   KeyedStoreIC ic;
   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
-  return ic.Store(state, args.at<Object>(0), args.at<Object>(1),
+  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
+  return ic.Store(state,
+                  static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
+                  args.at<Object>(0),
+                  args.at<Object>(1),
                   args.at<Object>(2));
 }
 
diff --git a/src/ic.h b/src/ic.h
index 3b10d06..e12cbaf 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -224,7 +224,7 @@
   // Otherwise, it returns the undefined value.
   Object* TryCallAsFunction(Object* object);
 
-  void ReceiverToObject(Handle<Object> object);
+  void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
 
   static void Clear(Address address, Code* target);
   friend class IC;
@@ -398,16 +398,10 @@
 
 class StoreIC: public IC {
  public:
-
-  enum StoreICStrictMode {
-    kStoreICNonStrict = kNonStrictMode,
-    kStoreICStrict = kStrictMode
-  };
-
   StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); }
 
   MUST_USE_RESULT MaybeObject* Store(State state,
-                                     Code::ExtraICState extra_ic_state,
+                                     StrictModeFlag strict_mode,
                                      Handle<Object> object,
                                      Handle<String> name,
                                      Handle<Object> value);
@@ -416,10 +410,11 @@
   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
   static void GenerateMiss(MacroAssembler* masm);
   static void GenerateMegamorphic(MacroAssembler* masm,
-                                  Code::ExtraICState extra_ic_state);
+                                  StrictModeFlag strict_mode);
   static void GenerateArrayLength(MacroAssembler* masm);
   static void GenerateNormal(MacroAssembler* masm);
-  static void GenerateGlobalProxy(MacroAssembler* masm);
+  static void GenerateGlobalProxy(MacroAssembler* masm,
+                                  StrictModeFlag strict_mode);
 
   // Clear the use of an inlined version.
   static void ClearInlinedVersion(Address address);
@@ -433,11 +428,18 @@
   // lookup result.
   void UpdateCaches(LookupResult* lookup,
                     State state,
-                    Code::ExtraICState extra_ic_state,
+                    StrictModeFlag strict_mode,
                     Handle<JSObject> receiver,
                     Handle<String> name,
                     Handle<Object> value);
 
+  void set_target(Code* code) {
+    // Strict mode must be preserved across IC patching.
+    ASSERT((code->extra_ic_state() & kStrictMode) ==
+           (target()->extra_ic_state() & kStrictMode));
+    IC::set_target(code);
+  }
+
   // Stub accessors.
   static Code* megamorphic_stub() {
     return Builtins::builtin(Builtins::StoreIC_Megamorphic);
@@ -473,6 +475,7 @@
   KeyedStoreIC() : IC(NO_EXTRA_FRAME) { }
 
   MUST_USE_RESULT MaybeObject* Store(State state,
+                                     StrictModeFlag strict_mode,
                                      Handle<Object> object,
                                      Handle<Object> name,
                                      Handle<Object> value);
@@ -480,8 +483,9 @@
   // Code generators for stub routines.  Only called once at startup.
   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
   static void GenerateMiss(MacroAssembler* masm);
-  static void GenerateRuntimeSetProperty(MacroAssembler* masm);
-  static void GenerateGeneric(MacroAssembler* masm);
+  static void GenerateRuntimeSetProperty(MacroAssembler* masm,
+                                         StrictModeFlag strict_mode);
+  static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
 
   // Clear the inlined version so the IC is always hit.
   static void ClearInlinedVersion(Address address);
@@ -493,20 +497,37 @@
   // Update the inline cache.
   void UpdateCaches(LookupResult* lookup,
                     State state,
+                    StrictModeFlag strict_mode,
                     Handle<JSObject> receiver,
                     Handle<String> name,
                     Handle<Object> value);
 
+  void set_target(Code* code) {
+    // Strict mode must be preserved across IC patching.
+    ASSERT((code->extra_ic_state() & kStrictMode) ==
+           (target()->extra_ic_state() & kStrictMode));
+    IC::set_target(code);
+  }
+
   // Stub accessors.
   static Code* initialize_stub() {
     return Builtins::builtin(Builtins::KeyedStoreIC_Initialize);
   }
+  static Code* initialize_stub_strict() {
+    return Builtins::builtin(Builtins::KeyedStoreIC_Initialize_Strict);
+  }
   static Code* megamorphic_stub() {
     return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
   }
+  static Code* megamorphic_stub_strict() {
+    return Builtins::builtin(Builtins::KeyedStoreIC_Generic_Strict);
+  }
   static Code* generic_stub() {
     return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
   }
+  static Code* generic_stub_strict() {
+    return Builtins::builtin(Builtins::KeyedStoreIC_Generic_Strict);
+  }
 
   static void Clear(Address address, Code* target);
 
diff --git a/src/json.js b/src/json.js
index e6ada51..7a6189c 100644
--- a/src/json.js
+++ b/src/json.js
@@ -49,7 +49,7 @@
       }
     }
   }
-  return reviver.call(holder, name, val);
+  return %_CallFunction(holder, name, val, reviver);
 }
 
 function JSONParse(text, reviver) {
@@ -63,11 +63,11 @@
 
 function SerializeArray(value, replacer, stack, indent, gap) {
   if (!%PushIfAbsent(stack, value)) {
-    throw MakeTypeError('circular_structure', []);
+    throw MakeTypeError('circular_structure', $Array());
   }
   var stepback = indent;
   indent += gap;
-  var partial = [];
+  var partial = new InternalArray();
   var len = value.length;
   for (var i = 0; i < len; i++) {
     var strP = JSONSerialize($String(i), value, replacer, stack,
@@ -93,11 +93,11 @@
 
 function SerializeObject(value, replacer, stack, indent, gap) {
   if (!%PushIfAbsent(stack, value)) {
-    throw MakeTypeError('circular_structure', []);
+    throw MakeTypeError('circular_structure', $Array());
   }
   var stepback = indent;
   indent += gap;
-  var partial = [];
+  var partial = new InternalArray();
   if (IS_ARRAY(replacer)) {
     var length = replacer.length;
     for (var i = 0; i < length; i++) {
@@ -185,7 +185,7 @@
     return;
   }
   if (!%PushIfAbsent(stack, value)) {
-    throw MakeTypeError('circular_structure', []);
+    throw MakeTypeError('circular_structure', $Array());
   }
   builder.push("[");
   var val = value[0];
@@ -238,7 +238,7 @@
 
 function BasicSerializeObject(value, stack, builder) {
   if (!%PushIfAbsent(stack, value)) {
-    throw MakeTypeError('circular_structure', []);
+    throw MakeTypeError('circular_structure', $Array());
   }
   builder.push("{");
   var first = true;
@@ -301,8 +301,8 @@
 
 function JSONStringify(value, replacer, space) {
   if (%_ArgumentsLength() == 1) {
-    var builder = [];
-    BasicJSONSerialize('', value, [], builder);
+    var builder = new InternalArray();
+    BasicJSONSerialize('', value, new InternalArray(), builder);
     if (builder.length == 0) return;
     var result = %_FastAsciiArrayJoin(builder, "");
     if (!IS_UNDEFINED(result)) return result;
@@ -329,7 +329,7 @@
   } else {
     gap = "";
   }
-  return JSONSerialize('', {'': value}, replacer, [], "", gap);
+  return JSONSerialize('', {'': value}, replacer, new InternalArray(), "", gap);
 }
 
 function SetupJSON() {
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index 8e7c35f..b271b02 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -97,9 +97,10 @@
                                         Handle<String> pattern,
                                         Handle<String> error_text,
                                         const char* message) {
-  Handle<JSArray> array = Factory::NewJSArray(2);
-  SetElement(array, 0, pattern);
-  SetElement(array, 1, error_text);
+  Handle<FixedArray> elements = Factory::NewFixedArray(2);
+  elements->set(0, *pattern);
+  elements->set(1, *error_text);
+  Handle<JSArray> array = Factory::NewJSArrayWithElements(elements);
   Handle<Object> regexp_err = Factory::NewSyntaxError(message, array);
   Top::Throw(*regexp_err);
 }
@@ -325,11 +326,12 @@
                             is_ascii);
   if (result.error_message != NULL) {
     // Unable to compile regexp.
-    Handle<JSArray> array = Factory::NewJSArray(2);
-    SetElement(array, 0, pattern);
-    SetElement(array,
-               1,
-               Factory::NewStringFromUtf8(CStrVector(result.error_message)));
+    Handle<FixedArray> elements = Factory::NewFixedArray(2);
+    elements->set(0, *pattern);
+    Handle<String> error_message =
+        Factory::NewStringFromUtf8(CStrVector(result.error_message));
+    elements->set(1, *error_message);
+    Handle<JSArray> array = Factory::NewJSArrayWithElements(elements);
     Handle<Object> regexp_err =
         Factory::NewSyntaxError("malformed_regexp", array);
     Top::Throw(*regexp_err);
diff --git a/src/lithium-allocator.cc b/src/lithium-allocator.cc
index 9f5f1b9..5755bb2 100644
--- a/src/lithium-allocator.cc
+++ b/src/lithium-allocator.cc
@@ -478,11 +478,6 @@
 }
 
 
-UsePosition* LiveRange::AddUsePosition(LifetimePosition pos) {
-  return AddUsePosition(pos, CreateAssignedOperand());
-}
-
-
 bool LiveRange::CanCover(LifetimePosition position) const {
   if (IsEmpty()) return false;
   return Start().Value() <= position.Value() &&
@@ -1098,6 +1093,21 @@
       } else {
         ASSERT(pred->end()->SecondSuccessor() == NULL);
         gap = GetLastGap(pred);
+
+        // We are going to insert a move before the branch instruction.
+        // Some branch instructions (e.g. loops' back edges)
+        // can potentially cause a GC so they have a pointer map.
+        // By insterting a move we essentially create a copy of a
+        // value which is invisible to PopulatePointerMaps(), because we store
+        // it into a location different from the operand of a live range
+        // covering a branch instruction.
+        // Thus we need to manually record a pointer.
+        if (HasTaggedValue(range->id())) {
+          LInstruction* branch = InstructionAt(pred->last_instruction_index());
+          if (branch->HasPointerMap()) {
+            branch->pointer_map()->RecordPointer(cur_op);
+          }
+        }
       }
       gap->GetOrCreateParallelMove(LGap::START)->AddMove(pred_op, cur_op);
     }
@@ -1264,7 +1274,7 @@
         found = true;
         int operand_index = iterator.Current();
         PrintF("Function: %s\n",
-               *graph_->info()->function()->debug_name()->ToCString());
+               *chunk_->info()->function()->debug_name()->ToCString());
         PrintF("Value %d used before first definition!\n", operand_index);
         LiveRange* range = LiveRangeFor(operand_index);
         PrintF("First use is at %d\n", range->first_pos()->pos().Value());
diff --git a/src/lithium-allocator.h b/src/lithium-allocator.h
index 914a5b6..d53ea78 100644
--- a/src/lithium-allocator.h
+++ b/src/lithium-allocator.h
@@ -286,7 +286,6 @@
   LiveRange* TopLevel() { return (parent_ == NULL) ? this : parent_; }
   LiveRange* next() const { return next_; }
   bool IsChild() const { return parent() != NULL; }
-  bool IsParent() const { return parent() == NULL; }
   int id() const { return id_; }
   bool IsFixed() const { return id_ < 0; }
   bool IsEmpty() const { return first_interval() == NULL; }
@@ -360,7 +359,6 @@
   void EnsureInterval(LifetimePosition start, LifetimePosition end);
   void AddUseInterval(LifetimePosition start, LifetimePosition end);
   UsePosition* AddUsePosition(LifetimePosition pos, LOperand* operand);
-  UsePosition* AddUsePosition(LifetimePosition pos);
 
   // Shorten the most recently added interval by setting a new start.
   void ShortenTo(LifetimePosition start);
diff --git a/src/lithium.h b/src/lithium.h
index a2f9df0..d85a87c 100644
--- a/src/lithium.h
+++ b/src/lithium.h
@@ -536,10 +536,12 @@
   inline LEnvironment* env() { return env_; }
 
  private:
+  inline bool ShouldSkip(LOperand* op) {
+    return op == NULL || op->IsConstantOperand() || op->IsArgument();
+  }
+
   inline int AdvanceToNext(int start) {
-    while (start < limit_ &&
-           (env_->values()->at(start) == NULL ||
-            env_->values()->at(start)->IsConstantOperand())) {
+    while (start < limit_ && ShouldSkip(env_->values()->at(start))) {
       start++;
     }
     return start;
diff --git a/src/liveedit.cc b/src/liveedit.cc
index a395c51..744ed49 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -286,11 +286,18 @@
   }
 
   void WriteChunk(int char_pos1, int char_pos2, int char_len1, int char_len2) {
-    SetElement(array_, current_size_, Handle<Object>(Smi::FromInt(char_pos1)));
-    SetElement(array_, current_size_ + 1,
-               Handle<Object>(Smi::FromInt(char_pos1 + char_len1)));
-    SetElement(array_, current_size_ + 2,
-               Handle<Object>(Smi::FromInt(char_pos2 + char_len2)));
+    SetElement(array_,
+               current_size_,
+               Handle<Object>(Smi::FromInt(char_pos1)),
+               kNonStrictMode);
+    SetElement(array_,
+               current_size_ + 1,
+               Handle<Object>(Smi::FromInt(char_pos1 + char_len1)),
+               kNonStrictMode);
+    SetElement(array_,
+               current_size_ + 2,
+               Handle<Object>(Smi::FromInt(char_pos2 + char_len2)),
+               kNonStrictMode);
     current_size_ += 3;
   }
 
@@ -545,10 +552,13 @@
 
  protected:
   void SetField(int field_position, Handle<Object> value) {
-    SetElement(array_, field_position, value);
+    SetElement(array_, field_position, value, kNonStrictMode);
   }
   void SetSmiValueField(int field_position, int value) {
-    SetElement(array_, field_position, Handle<Smi>(Smi::FromInt(value)));
+    SetElement(array_,
+               field_position,
+               Handle<Smi>(Smi::FromInt(value)),
+               kNonStrictMode);
   }
   Object* GetField(int field_position) {
     return array_->GetElementNoExceptionThrown(field_position);
@@ -687,7 +697,7 @@
                               fun->end_position(), fun->num_parameters(),
                               current_parent_index_);
     current_parent_index_ = len_;
-    SetElement(result_, len_, info.GetJSArray());
+    SetElement(result_, len_, info.GetJSArray(), kNonStrictMode);
     len_++;
   }
 
@@ -767,14 +777,16 @@
         list[k] = list[l];
       }
       for (int i = 0; i < j; i++) {
-        SetElement(scope_info_list, scope_info_length, list[i]->name());
+        SetElement(scope_info_list, scope_info_length,
+                   list[i]->name(), kNonStrictMode);
         scope_info_length++;
         SetElement(scope_info_list, scope_info_length,
-                   Handle<Smi>(Smi::FromInt(list[i]->AsSlot()->index())));
+                   Handle<Smi>(Smi::FromInt(list[i]->AsSlot()->index())),
+                   kNonStrictMode);
         scope_info_length++;
       }
       SetElement(scope_info_list, scope_info_length,
-                 Handle<Object>(Heap::null_value()));
+                 Handle<Object>(Heap::null_value()), kNonStrictMode);
       scope_info_length++;
 
       outer_scope = outer_scope->outer_scope();
@@ -817,7 +829,7 @@
     Handle<String> name_handle(String::cast(info->name()));
     info_wrapper.SetProperties(name_handle, info->start_position(),
                                info->end_position(), info);
-    SetElement(array, i, info_wrapper.GetJSArray());
+    SetElement(array, i, info_wrapper.GetJSArray(), kNonStrictMode);
   }
 }
 
@@ -1315,7 +1327,7 @@
         SharedFunctionInfo::cast(wrapper->value()));
 
     if (function->shared() == *shared || IsInlined(*function, *shared)) {
-      SetElement(result, i, Handle<Smi>(Smi::FromInt(status)));
+      SetElement(result, i, Handle<Smi>(Smi::FromInt(status)), kNonStrictMode);
       return true;
     }
   }
@@ -1520,7 +1532,7 @@
         Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
       Handle<Object> replaced(
           Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK));
-      SetElement(result, i, replaced);
+      SetElement(result, i, replaced, kNonStrictMode);
     }
   }
   return NULL;
@@ -1561,7 +1573,8 @@
   // Fill the default values.
   for (int i = 0; i < len; i++) {
     SetElement(result, i,
-               Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH)));
+               Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH)),
+               kNonStrictMode);
   }
 
 
@@ -1580,7 +1593,7 @@
     // Add error message as an array extra element.
     Vector<const char> vector_message(error_message, StrLength(error_message));
     Handle<String> str = Factory::NewStringFromAscii(vector_message);
-    SetElement(result, len, str);
+    SetElement(result, len, str, kNonStrictMode);
   }
   return result;
 }
diff --git a/src/liveobjectlist-inl.h b/src/liveobjectlist-inl.h
index 997da4e..f742de3 100644
--- a/src/liveobjectlist-inl.h
+++ b/src/liveobjectlist-inl.h
@@ -32,5 +32,95 @@
 
 #include "liveobjectlist.h"
 
+namespace v8 {
+namespace internal {
+
+#ifdef LIVE_OBJECT_LIST
+
+void LiveObjectList::GCEpilogue() {
+  if (!NeedLOLProcessing()) return;
+  GCEpiloguePrivate();
+}
+
+
+void LiveObjectList::GCPrologue() {
+  if (!NeedLOLProcessing()) return;
+#ifdef VERIFY_LOL
+  if (FLAG_verify_lol) {
+    Verify();
+  }
+#endif
+}
+
+
+void LiveObjectList::IterateElements(ObjectVisitor* v) {
+  if (!NeedLOLProcessing()) return;
+  IterateElementsPrivate(v);
+}
+
+
+void LiveObjectList::ProcessNonLive(HeapObject *obj) {
+  // Only do work if we have at least one list to process.
+  if (last()) DoProcessNonLive(obj);
+}
+
+
+void LiveObjectList::UpdateReferencesForScavengeGC() {
+  if (LiveObjectList::NeedLOLProcessing()) {
+    UpdateLiveObjectListVisitor update_visitor;
+    LiveObjectList::IterateElements(&update_visitor);
+  }
+}
+
+
+LiveObjectList* LiveObjectList::FindLolForId(int id,
+                                             LiveObjectList* start_lol) {
+  if (id != 0) {
+    LiveObjectList* lol = start_lol;
+    while (lol != NULL) {
+      if (lol->id() == id) {
+        return lol;
+      }
+      lol = lol->prev_;
+    }
+  }
+  return NULL;
+}
+
+
+// Iterates the elements in every lol and returns the one that matches the
+// specified key.  If no matching element is found, then it returns NULL.
+template <typename T>
+inline LiveObjectList::Element*
+LiveObjectList::FindElementFor(T (*GetValue)(LiveObjectList::Element*), T key) {
+  LiveObjectList *lol = last();
+  while (lol != NULL) {
+    Element* elements = lol->elements_;
+    for (int i = 0; i < lol->obj_count_; i++) {
+      Element* element = &elements[i];
+      if (GetValue(element) == key) {
+        return element;
+      }
+    }
+    lol = lol->prev_;
+  }
+  return NULL;
+}
+
+
+inline int LiveObjectList::GetElementId(LiveObjectList::Element* element) {
+  return element->id_;
+}
+
+
+inline HeapObject*
+LiveObjectList::GetElementObj(LiveObjectList::Element* element) {
+  return element->obj_;
+}
+
+#endif  // LIVE_OBJECT_LIST
+
+} }  // namespace v8::internal
+
 #endif  // V8_LIVEOBJECTLIST_INL_H_
 
diff --git a/src/liveobjectlist.cc b/src/liveobjectlist.cc
index 28a3d6d..5795a6b 100644
--- a/src/liveobjectlist.cc
+++ b/src/liveobjectlist.cc
@@ -37,7 +37,7 @@
 #include "heap.h"
 #include "inspector.h"
 #include "list-inl.h"
-#include "liveobjectlist.h"
+#include "liveobjectlist-inl.h"
 #include "string-stream.h"
 #include "top.h"
 #include "v8utils.h"
@@ -46,6 +46,2542 @@
 namespace internal {
 
 
+typedef int (*RawComparer)(const void*, const void*);
+
+
+#ifdef CHECK_ALL_OBJECT_TYPES
+
+#define DEBUG_LIVE_OBJECT_TYPES(v) \
+  v(Smi, "unexpected: Smi") \
+  \
+  v(CodeCache, "unexpected: CodeCache") \
+  v(BreakPointInfo, "unexpected: BreakPointInfo") \
+  v(DebugInfo, "unexpected: DebugInfo") \
+  v(TypeSwitchInfo, "unexpected: TypeSwitchInfo") \
+  v(SignatureInfo, "unexpected: SignatureInfo") \
+  v(Script, "unexpected: Script") \
+  v(ObjectTemplateInfo, "unexpected: ObjectTemplateInfo") \
+  v(FunctionTemplateInfo, "unexpected: FunctionTemplateInfo") \
+  v(CallHandlerInfo, "unexpected: CallHandlerInfo") \
+  v(InterceptorInfo, "unexpected: InterceptorInfo") \
+  v(AccessCheckInfo, "unexpected: AccessCheckInfo") \
+  v(AccessorInfo, "unexpected: AccessorInfo") \
+  v(ExternalTwoByteString, "unexpected: ExternalTwoByteString") \
+  v(ExternalAsciiString, "unexpected: ExternalAsciiString") \
+  v(ExternalString, "unexpected: ExternalString") \
+  v(SeqTwoByteString, "unexpected: SeqTwoByteString") \
+  v(SeqAsciiString, "unexpected: SeqAsciiString") \
+  v(SeqString, "unexpected: SeqString") \
+  v(JSFunctionResultCache, "unexpected: JSFunctionResultCache") \
+  v(GlobalContext, "unexpected: GlobalContext") \
+  v(MapCache, "unexpected: MapCache") \
+  v(CodeCacheHashTable, "unexpected: CodeCacheHashTable") \
+  v(CompilationCacheTable, "unexpected: CompilationCacheTable") \
+  v(SymbolTable, "unexpected: SymbolTable") \
+  v(Dictionary, "unexpected: Dictionary") \
+  v(HashTable, "unexpected: HashTable") \
+  v(DescriptorArray, "unexpected: DescriptorArray") \
+  v(ExternalFloatArray, "unexpected: ExternalFloatArray") \
+  v(ExternalUnsignedIntArray, "unexpected: ExternalUnsignedIntArray") \
+  v(ExternalIntArray, "unexpected: ExternalIntArray") \
+  v(ExternalUnsignedShortArray, "unexpected: ExternalUnsignedShortArray") \
+  v(ExternalShortArray, "unexpected: ExternalShortArray") \
+  v(ExternalUnsignedByteArray, "unexpected: ExternalUnsignedByteArray") \
+  v(ExternalByteArray, "unexpected: ExternalByteArray") \
+  v(JSValue, "unexpected: JSValue")
+
+#else
+#define DEBUG_LIVE_OBJECT_TYPES(v)
+#endif
+
+
+#define FOR_EACH_LIVE_OBJECT_TYPE(v) \
+  DEBUG_LIVE_OBJECT_TYPES(v) \
+  \
+  v(JSArray, "JSArray") \
+  v(JSRegExp, "JSRegExp") \
+  v(JSFunction, "JSFunction") \
+  v(JSGlobalObject, "JSGlobal") \
+  v(JSBuiltinsObject, "JSBuiltins") \
+  v(GlobalObject, "Global") \
+  v(JSGlobalProxy, "JSGlobalProxy") \
+  v(JSObject, "JSObject") \
+  \
+  v(Context, "meta: Context") \
+  v(ByteArray, "meta: ByteArray") \
+  v(PixelArray, "meta: PixelArray") \
+  v(ExternalArray, "meta: ExternalArray") \
+  v(FixedArray, "meta: FixedArray") \
+  v(String, "String") \
+  v(HeapNumber, "HeapNumber") \
+  \
+  v(Code, "meta: Code") \
+  v(Map, "meta: Map") \
+  v(Oddball, "Oddball") \
+  v(Proxy, "meta: Proxy") \
+  v(SharedFunctionInfo, "meta: SharedFunctionInfo") \
+  v(Struct, "meta: Struct") \
+  \
+  v(HeapObject, "HeapObject")
+
+
+enum /* LiveObjectType */ {
+#define DECLARE_OBJECT_TYPE_ENUM(type, name) kType##type,
+  FOR_EACH_LIVE_OBJECT_TYPE(DECLARE_OBJECT_TYPE_ENUM)
+  kInvalidLiveObjType,
+  kNumberOfTypes
+#undef DECLARE_OBJECT_TYPE_ENUM
+};
+
+
+LiveObjectType GetObjectType(HeapObject* heap_obj) {
+  // TODO(mlam): investigate usint Map::instance_type() instead.
+#define CHECK_FOR_OBJECT_TYPE(type, name) \
+  if (heap_obj->Is##type()) return kType##type;
+  FOR_EACH_LIVE_OBJECT_TYPE(CHECK_FOR_OBJECT_TYPE)
+#undef CHECK_FOR_OBJECT_TYPE
+
+  UNREACHABLE();
+  return kInvalidLiveObjType;
+}
+
+
+inline const char* GetObjectTypeDesc(LiveObjectType type) {
+  static const char* const name[kNumberOfTypes] = {
+  #define DEFINE_OBJECT_TYPE_NAME(type, name) name,
+    FOR_EACH_LIVE_OBJECT_TYPE(DEFINE_OBJECT_TYPE_NAME)
+    "invalid"
+  #undef DEFINE_OBJECT_TYPE_NAME
+  };
+  ASSERT(type < kNumberOfTypes);
+  return name[type];
+}
+
+
+const char* GetObjectTypeDesc(HeapObject* heap_obj) {
+  LiveObjectType type = GetObjectType(heap_obj);
+  return GetObjectTypeDesc(type);
+}
+
+
+bool IsOfType(LiveObjectType type, HeapObject *obj) {
+  // Note: there are types that are more general (e.g. JSObject) that would
+  // have passed the Is##type_() test for more specialized types (e.g.
+  // JSFunction).  If we find a more specialized match but we're looking for
+  // the general type, then we should reject the ones that matches the
+  // specialized type.
+#define CHECK_OBJECT_TYPE(type_, name) \
+  if (obj->Is##type_()) return (type == kType##type_);
+
+  FOR_EACH_LIVE_OBJECT_TYPE(CHECK_OBJECT_TYPE)
+#undef CHECK_OBJECT_TYPE
+
+  return false;
+}
+
+
+const AllocationSpace kInvalidSpace = static_cast<AllocationSpace>(-1);
+
+static AllocationSpace FindSpaceFor(String* space_str) {
+  SmartPointer<char> s =
+      space_str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+
+  const char* key_str = *s;
+  switch (key_str[0]) {
+    case 'c':
+      if (strcmp(key_str, "cell") == 0) return CELL_SPACE;
+      if (strcmp(key_str, "code") == 0) return CODE_SPACE;
+      break;
+    case 'l':
+      if (strcmp(key_str, "lo") == 0) return LO_SPACE;
+      break;
+    case 'm':
+      if (strcmp(key_str, "map") == 0) return MAP_SPACE;
+      break;
+    case 'n':
+      if (strcmp(key_str, "new") == 0) return NEW_SPACE;
+      break;
+    case 'o':
+      if (strcmp(key_str, "old-pointer") == 0) return OLD_POINTER_SPACE;
+      if (strcmp(key_str, "old-data") == 0) return OLD_DATA_SPACE;
+      break;
+  }
+  return kInvalidSpace;
+}
+
+
+static bool InSpace(AllocationSpace space, HeapObject *heap_obj) {
+  if (space != LO_SPACE) {
+    return Heap::InSpace(heap_obj, space);
+  }
+
+  // This is an optimization to speed up the check for an object in the LO
+  // space by exclusion because we know that all object pointers passed in
+  // here are guaranteed to be in the heap.  Hence, it is safe to infer
+  // using an exclusion test.
+  // Note: calling Heap::InSpace(heap_obj, LO_SPACE) is too slow for our
+  // filters.
+  int first_space = static_cast<int>(FIRST_SPACE);
+  int last_space = static_cast<int>(LO_SPACE);
+  for (int sp = first_space; sp < last_space; sp++) {
+    if (Heap::InSpace(heap_obj, static_cast<AllocationSpace>(sp))) {
+      return false;
+    }
+  }
+  SLOW_ASSERT(Heap::InSpace(heap_obj, LO_SPACE));
+  return true;
+}
+
+
+static LiveObjectType FindTypeFor(String* type_str) {
+  SmartPointer<char> s =
+      type_str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+
+#define CHECK_OBJECT_TYPE(type_, name) { \
+    const char* type_desc = GetObjectTypeDesc(kType##type_); \
+    const char* key_str = *s; \
+    if (strstr(type_desc, key_str) != NULL) return kType##type_; \
+  }
+  FOR_EACH_LIVE_OBJECT_TYPE(CHECK_OBJECT_TYPE)
+#undef CHECK_OBJECT_TYPE
+
+  return kInvalidLiveObjType;
+}
+
+
+class LolFilter {
+ public:
+  explicit LolFilter(Handle<JSObject> filter_obj);
+
+  inline bool is_active() const { return is_active_; }
+  inline bool Matches(HeapObject* obj) {
+    return !is_active() || MatchesSlow(obj);
+  }
+
+ private:
+  void InitTypeFilter(Handle<JSObject> filter_obj);
+  void InitSpaceFilter(Handle<JSObject> filter_obj);
+  void InitPropertyFilter(Handle<JSObject> filter_obj);
+  bool MatchesSlow(HeapObject* obj);
+
+  bool is_active_;
+  LiveObjectType type_;
+  AllocationSpace space_;
+  Handle<String> prop_;
+};
+
+
+LolFilter::LolFilter(Handle<JSObject> filter_obj)
+    : is_active_(false),
+      type_(kInvalidLiveObjType),
+      space_(kInvalidSpace),
+      prop_() {
+  if (filter_obj.is_null()) return;
+
+  InitTypeFilter(filter_obj);
+  InitSpaceFilter(filter_obj);
+  InitPropertyFilter(filter_obj);
+}
+
+
+void LolFilter::InitTypeFilter(Handle<JSObject> filter_obj) {
+  Handle<String> type_sym = Factory::LookupAsciiSymbol("type");
+  MaybeObject* maybe_result = filter_obj->GetProperty(*type_sym);
+  Object* type_obj;
+  if (maybe_result->ToObject(&type_obj)) {
+    if (type_obj->IsString()) {
+      String* type_str = String::cast(type_obj);
+      type_ = FindTypeFor(type_str);
+      if (type_ != kInvalidLiveObjType) {
+        is_active_ = true;
+      }
+    }
+  }
+}
+
+
+void LolFilter::InitSpaceFilter(Handle<JSObject> filter_obj) {
+  Handle<String> space_sym = Factory::LookupAsciiSymbol("space");
+  MaybeObject* maybe_result = filter_obj->GetProperty(*space_sym);
+  Object* space_obj;
+  if (maybe_result->ToObject(&space_obj)) {
+    if (space_obj->IsString()) {
+      String* space_str = String::cast(space_obj);
+      space_ = FindSpaceFor(space_str);
+      if (space_ != kInvalidSpace) {
+        is_active_ = true;
+      }
+    }
+  }
+}
+
+
+void LolFilter::InitPropertyFilter(Handle<JSObject> filter_obj) {
+  Handle<String> prop_sym = Factory::LookupAsciiSymbol("prop");
+  MaybeObject* maybe_result = filter_obj->GetProperty(*prop_sym);
+  Object* prop_obj;
+  if (maybe_result->ToObject(&prop_obj)) {
+    if (prop_obj->IsString()) {
+      prop_ = Handle<String>(String::cast(prop_obj));
+      is_active_ = true;
+    }
+  }
+}
+
+
+bool LolFilter::MatchesSlow(HeapObject* obj) {
+  if ((type_ != kInvalidLiveObjType) && !IsOfType(type_, obj)) {
+    return false;  // Fail because obj is not of the type of interest.
+  }
+  if ((space_ != kInvalidSpace) && !InSpace(space_, obj)) {
+    return false;  // Fail because obj is not in the space of interest.
+  }
+  if (!prop_.is_null() && obj->IsJSObject()) {
+    LookupResult result;
+    obj->Lookup(*prop_, &result);
+    if (!result.IsProperty()) {
+      return false;  // Fail because obj does not have the property of interest.
+    }
+  }
+  return true;
+}
+
+
+class LolIterator {
+ public:
+  LolIterator(LiveObjectList* older, LiveObjectList* newer)
+      : older_(older),
+        newer_(newer),
+        curr_(0),
+        elements_(0),
+        count_(0),
+        index_(0) { }
+
+  inline void Init() {
+    SetCurrent(newer_);
+    // If the elements_ list is empty, then move on to the next list as long
+    // as we're not at the last list (indicated by done()).
+    while ((elements_ == NULL) && !Done()) {
+      SetCurrent(curr_->prev_);
+    }
+  }
+
+  inline bool Done() const {
+    return (curr_ == older_);
+  }
+
+  // Object level iteration.
+  inline void Next() {
+    index_++;
+    if (index_ >= count_) {
+      // Iterate backwards until we get to the oldest list.
+      while (!Done()) {
+        SetCurrent(curr_->prev_);
+        // If we have elements to process, we're good to go.
+        if (elements_ != NULL) break;
+
+        // Else, we should advance to the next older list.
+      }
+    }
+  }
+
+  inline int Id() const {
+    return elements_[index_].id_;
+  }
+  inline HeapObject* Obj() const {
+    return elements_[index_].obj_;
+  }
+
+  inline int LolObjCount() const {
+    if (curr_ != NULL) return curr_->obj_count_;
+    return 0;
+  }
+
+ protected:
+  inline void SetCurrent(LiveObjectList* new_curr) {
+    curr_ = new_curr;
+    if (curr_ != NULL) {
+      elements_ = curr_->elements_;
+      count_ = curr_->obj_count_;
+      index_ = 0;
+    }
+  }
+
+  LiveObjectList* older_;
+  LiveObjectList* newer_;
+  LiveObjectList* curr_;
+  LiveObjectList::Element* elements_;
+  int count_;
+  int index_;
+};
+
+
+class LolForwardIterator : public LolIterator {
+ public:
+  LolForwardIterator(LiveObjectList* first, LiveObjectList* last)
+      : LolIterator(first, last) {
+  }
+
+  inline void Init() {
+    SetCurrent(older_);
+    // If the elements_ list is empty, then move on to the next list as long
+    // as we're not at the last list (indicated by Done()).
+    while ((elements_ == NULL) && !Done()) {
+      SetCurrent(curr_->next_);
+    }
+  }
+
+  inline bool Done() const {
+    return (curr_ == newer_);
+  }
+
+  // Object level iteration.
+  inline void Next() {
+    index_++;
+    if (index_ >= count_) {
+      // Done with current list.  Move on to the next.
+      while (!Done()) {  // If not at the last list already, ...
+        SetCurrent(curr_->next_);
+        // If we have elements to process, we're good to go.
+        if (elements_ != NULL) break;
+
+        // Else, we should advance to the next list.
+      }
+    }
+  }
+};
+
+
+// Minimizes the white space in a string.  Tabs and newlines are replaced
+// with a space where appropriate.
+static int CompactString(char* str) {
+  char* src = str;
+  char* dst = str;
+  char prev_ch = 0;
+  while (*dst != '\0') {
+    char ch = *src++;
+    // We will treat non-ascii chars as '?'.
+    if ((ch & 0x80) != 0) {
+      ch = '?';
+    }
+    // Compact contiguous whitespace chars into a single ' '.
+    if (isspace(ch)) {
+      if (prev_ch != ' ') *dst++ = ' ';
+      prev_ch = ' ';
+      continue;
+    }
+    *dst++ = ch;
+    prev_ch = ch;
+  }
+  return (dst - str);
+}
+
+
+// Generates a custom description based on the specific type of
+// object we're looking at.  We only generate specialized
+// descriptions where we can.  In all other cases, we emit the
+// generic info.
+static void GenerateObjectDesc(HeapObject* obj,
+                               char* buffer,
+                               int buffer_size) {
+  Vector<char> buffer_v(buffer, buffer_size);
+  ASSERT(obj != NULL);
+  if (obj->IsJSArray()) {
+    JSArray* jsarray = JSArray::cast(obj);
+    double length = jsarray->length()->Number();
+    OS::SNPrintF(buffer_v,
+                 "%p <%s> len %g",
+                 reinterpret_cast<void*>(obj),
+                 GetObjectTypeDesc(obj),
+                 length);
+
+  } else if (obj->IsString()) {
+    String *str = String::cast(obj);
+    // Only grab up to 160 chars in case they are double byte.
+    // We'll only dump 80 of them after we compact them.
+    const int kMaxCharToDump = 80;
+    const int kMaxBufferSize = kMaxCharToDump * 2;
+    SmartPointer<char> str_sp = str->ToCString(DISALLOW_NULLS,
+                                               ROBUST_STRING_TRAVERSAL,
+                                               0,
+                                               kMaxBufferSize);
+    char* str_cstr = *str_sp;
+    int length = CompactString(str_cstr);
+    OS::SNPrintF(buffer_v,
+                 "%p <%s> '%.80s%s'",
+                 reinterpret_cast<void*>(obj),
+                 GetObjectTypeDesc(obj),
+                 str_cstr,
+                 (length > kMaxCharToDump) ? "..." : "");
+
+  } else if (obj->IsJSFunction() || obj->IsSharedFunctionInfo()) {
+    SharedFunctionInfo* sinfo;
+    if (obj->IsJSFunction()) {
+      JSFunction* func = JSFunction::cast(obj);
+      sinfo = func->shared();
+    } else {
+      sinfo = SharedFunctionInfo::cast(obj);
+    }
+
+    String* name = sinfo->DebugName();
+    SmartPointer<char> name_sp =
+        name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+    char* name_cstr = *name_sp;
+
+    HeapStringAllocator string_allocator;
+    StringStream stream(&string_allocator);
+    sinfo->SourceCodePrint(&stream, 50);
+    SmartPointer<const char> source_sp = stream.ToCString();
+    const char* source_cstr = *source_sp;
+
+    OS::SNPrintF(buffer_v,
+                 "%p <%s> '%s' %s",
+                 reinterpret_cast<void*>(obj),
+                 GetObjectTypeDesc(obj),
+                 name_cstr,
+                 source_cstr);
+
+  } else if (obj->IsFixedArray()) {
+    FixedArray* fixed = FixedArray::cast(obj);
+
+    OS::SNPrintF(buffer_v,
+                 "%p <%s> len %d",
+                 reinterpret_cast<void*>(obj),
+                 GetObjectTypeDesc(obj),
+                 fixed->length());
+
+  } else {
+    OS::SNPrintF(buffer_v,
+                 "%p <%s>",
+                 reinterpret_cast<void*>(obj),
+                 GetObjectTypeDesc(obj));
+  }
+}
+
+
+// Utility function for filling in a line of detail in a verbose dump.
+static bool AddObjDetail(Handle<FixedArray> arr,
+                         int index,
+                         int obj_id,
+                         Handle<HeapObject> target,
+                         const char* desc_str,
+                         Handle<String> id_sym,
+                         Handle<String> desc_sym,
+                         Handle<String> size_sym,
+                         Handle<JSObject> detail,
+                         Handle<String> desc,
+                         Handle<Object> error) {
+  detail = Factory::NewJSObject(Top::object_function());
+  if (detail->IsFailure()) {
+    error = detail;
+    return false;
+  }
+
+  int size = 0;
+  char buffer[512];
+  if (desc_str == NULL) {
+    ASSERT(!target.is_null());
+    HeapObject* obj = *target;
+    GenerateObjectDesc(obj, buffer, sizeof(buffer));
+    desc_str = buffer;
+    size = obj->Size();
+  }
+  desc = Factory::NewStringFromAscii(CStrVector(desc_str));
+  if (desc->IsFailure()) {
+    error = desc;
+    return false;
+  }
+
+  { MaybeObject* maybe_result = detail->SetProperty(*id_sym,
+                                                    Smi::FromInt(obj_id),
+                                                    NONE,
+                                                    kNonStrictMode);
+    if (maybe_result->IsFailure()) return false;
+  }
+  { MaybeObject* maybe_result = detail->SetProperty(*desc_sym,
+                                                    *desc,
+                                                    NONE,
+                                                    kNonStrictMode);
+    if (maybe_result->IsFailure()) return false;
+  }
+  { MaybeObject* maybe_result = detail->SetProperty(*size_sym,
+                                                    Smi::FromInt(size),
+                                                    NONE,
+                                                    kNonStrictMode);
+    if (maybe_result->IsFailure()) return false;
+  }
+
+  arr->set(index, *detail);
+  return true;
+}
+
+
+class DumpWriter {
+ public:
+  virtual ~DumpWriter() {}
+
+  virtual void ComputeTotalCountAndSize(LolFilter* filter,
+                                        int* count,
+                                        int* size) = 0;
+  virtual bool Write(Handle<FixedArray> elements_arr,
+                     int start,
+                     int dump_limit,
+                     LolFilter* filter,
+                     Handle<Object> error) = 0;
+};
+
+
+class LolDumpWriter: public DumpWriter {
+ public:
+  LolDumpWriter(LiveObjectList* older, LiveObjectList* newer)
+      : older_(older), newer_(newer) {
+  }
+
+  void ComputeTotalCountAndSize(LolFilter* filter, int* count, int* size) {
+    *count = 0;
+    *size = 0;
+
+    LolIterator it(older_, newer_);
+    for (it.Init(); !it.Done(); it.Next()) {
+      HeapObject* heap_obj = it.Obj();
+      if (!filter->Matches(heap_obj)) {
+        continue;
+      }
+
+      *size += heap_obj->Size();
+      (*count)++;
+    }
+  }
+
+  bool Write(Handle<FixedArray> elements_arr,
+             int start,
+             int dump_limit,
+             LolFilter* filter,
+             Handle<Object> error) {
+    // The lols are listed in latest to earliest.  We want to dump from
+    // earliest to latest.  So, compute the last element to start with.
+    int index = 0;
+    int count = 0;
+
+    // Prefetch some needed symbols.
+    Handle<String> id_sym = Factory::LookupAsciiSymbol("id");
+    Handle<String> desc_sym = Factory::LookupAsciiSymbol("desc");
+    Handle<String> size_sym = Factory::LookupAsciiSymbol("size");
+
+    // Fill the array with the lol object details.
+    Handle<JSObject> detail;
+    Handle<String> desc;
+    Handle<HeapObject> target;
+
+    LiveObjectList* first_lol = (older_ != NULL) ?
+                                older_->next_ : LiveObjectList::first_;
+    LiveObjectList* last_lol = (newer_ != NULL) ? newer_->next_ : NULL;
+
+    LolForwardIterator it(first_lol, last_lol);
+    for (it.Init(); !it.Done() && (index < dump_limit); it.Next()) {
+      HeapObject* heap_obj = it.Obj();
+
+      // Skip objects that have been filtered out.
+      if (!filter->Matches(heap_obj)) {
+        continue;
+      }
+
+      // Only report objects that are in the section of interest.
+      if (count >= start) {
+        target = Handle<HeapObject>(heap_obj);
+        bool success = AddObjDetail(elements_arr,
+                                    index++,
+                                    it.Id(),
+                                    target,
+                                    NULL,
+                                    id_sym,
+                                    desc_sym,
+                                    size_sym,
+                                    detail,
+                                    desc,
+                                    error);
+        if (!success) return false;
+      }
+      count++;
+    }
+    return true;
+  }
+
+ private:
+  LiveObjectList* older_;
+  LiveObjectList* newer_;
+};
+
+
+class RetainersDumpWriter: public DumpWriter {
+ public:
+  RetainersDumpWriter(Handle<HeapObject> target,
+                      Handle<JSObject> instance_filter,
+                      Handle<JSFunction> args_function)
+      : target_(target),
+        instance_filter_(instance_filter),
+        args_function_(args_function) {
+  }
+
+  void ComputeTotalCountAndSize(LolFilter* filter, int* count, int* size) {
+    Handle<FixedArray> retainers_arr;
+    Handle<Object> error;
+
+    *size = -1;
+    LiveObjectList::GetRetainers(target_,
+                                 instance_filter_,
+                                 retainers_arr,
+                                 0,
+                                 Smi::kMaxValue,
+                                 count,
+                                 filter,
+                                 NULL,
+                                 *args_function_,
+                                 error);
+  }
+
+  bool Write(Handle<FixedArray> elements_arr,
+             int start,
+             int dump_limit,
+             LolFilter* filter,
+             Handle<Object> error) {
+    int dummy;
+    int count;
+
+    // Fill the retainer objects.
+    count = LiveObjectList::GetRetainers(target_,
+                                         instance_filter_,
+                                         elements_arr,
+                                         start,
+                                         dump_limit,
+                                         &dummy,
+                                         filter,
+                                         NULL,
+                                         *args_function_,
+                                         error);
+    if (count < 0) {
+        return false;
+    }
+    return true;
+  }
+
+ private:
+  Handle<HeapObject> target_;
+  Handle<JSObject> instance_filter_;
+  Handle<JSFunction> args_function_;
+};
+
+
+class LiveObjectSummary {
+ public:
+  explicit LiveObjectSummary(LolFilter* filter)
+      : total_count_(0),
+        total_size_(0),
+        found_root_(false),
+        found_weak_root_(false),
+        filter_(filter) {
+    memset(counts_, 0, sizeof(counts_[0]) * kNumberOfEntries);
+    memset(sizes_, 0, sizeof(sizes_[0]) * kNumberOfEntries);
+  }
+
+  void Add(HeapObject* heap_obj) {
+    int size = heap_obj->Size();
+    LiveObjectType type = GetObjectType(heap_obj);
+    ASSERT(type != kInvalidLiveObjType);
+    counts_[type]++;
+    sizes_[type] += size;
+    total_count_++;
+    total_size_ += size;
+  }
+
+  void set_found_root() { found_root_ = true; }
+  void set_found_weak_root() { found_weak_root_ = true; }
+
+  inline int Count(LiveObjectType type) {
+    return counts_[type];
+  }
+  inline int Size(LiveObjectType type) {
+    return sizes_[type];
+  }
+  inline int total_count() {
+    return total_count_;
+  }
+  inline int total_size() {
+    return total_size_;
+  }
+  inline bool found_root() {
+    return found_root_;
+  }
+  inline bool found_weak_root() {
+    return found_weak_root_;
+  }
+  int GetNumberOfEntries() {
+    int entries = 0;
+    for (int i = 0; i < kNumberOfEntries; i++) {
+      if (counts_[i]) entries++;
+    }
+    return entries;
+  }
+
+  inline LolFilter* filter() { return filter_; }
+
+  static const int kNumberOfEntries = kNumberOfTypes;
+
+ private:
+  int counts_[kNumberOfEntries];
+  int sizes_[kNumberOfEntries];
+  int total_count_;
+  int total_size_;
+  bool found_root_;
+  bool found_weak_root_;
+
+  LolFilter *filter_;
+};
+
+
+// Abstraction for a summary writer.
+class SummaryWriter {
+ public:
+  virtual ~SummaryWriter() {}
+  virtual void Write(LiveObjectSummary* summary) = 0;
+};
+
+
+// A summary writer for filling in a summary of lol lists and diffs.
+class LolSummaryWriter: public SummaryWriter {
+ public:
+  LolSummaryWriter(LiveObjectList *older_lol,
+                   LiveObjectList *newer_lol)
+      : older_(older_lol), newer_(newer_lol) {
+  }
+
+  void Write(LiveObjectSummary* summary) {
+    LolFilter* filter = summary->filter();
+
+    // Fill the summary with the lol object details.
+    LolIterator it(older_, newer_);
+    for (it.Init(); !it.Done(); it.Next()) {
+      HeapObject* heap_obj = it.Obj();
+      if (!filter->Matches(heap_obj)) {
+        continue;
+      }
+      summary->Add(heap_obj);
+    }
+  }
+
+ private:
+  LiveObjectList* older_;
+  LiveObjectList* newer_;
+};
+
+
+// A summary writer for filling in a retainers list.
+class RetainersSummaryWriter: public SummaryWriter {
+ public:
+  RetainersSummaryWriter(Handle<HeapObject> target,
+                         Handle<JSObject> instance_filter,
+                         Handle<JSFunction> args_function)
+      : target_(target),
+        instance_filter_(instance_filter),
+        args_function_(args_function) {
+  }
+
+  void Write(LiveObjectSummary* summary) {
+    Handle<FixedArray> retainers_arr;
+    Handle<Object> error;
+    int dummy_total_count;
+    LiveObjectList::GetRetainers(target_,
+                                 instance_filter_,
+                                 retainers_arr,
+                                 0,
+                                 Smi::kMaxValue,
+                                 &dummy_total_count,
+                                 summary->filter(),
+                                 summary,
+                                 *args_function_,
+                                 error);
+  }
+
+ private:
+  Handle<HeapObject> target_;
+  Handle<JSObject> instance_filter_;
+  Handle<JSFunction> args_function_;
+};
+
+
+uint32_t LiveObjectList::next_element_id_ = 1;
+int LiveObjectList::list_count_ = 0;
+int LiveObjectList::last_id_ = 0;
+LiveObjectList* LiveObjectList::first_ = NULL;
+LiveObjectList* LiveObjectList::last_ = NULL;
+
+
+LiveObjectList::LiveObjectList(LiveObjectList* prev, int capacity)
+    : prev_(prev),
+      next_(NULL),
+      capacity_(capacity),
+      obj_count_(0) {
+  elements_ = NewArray<Element>(capacity);
+  id_ = ++last_id_;
+
+  list_count_++;
+}
+
+
+LiveObjectList::~LiveObjectList() {
+  DeleteArray<Element>(elements_);
+  delete prev_;
+}
+
+
+int LiveObjectList::GetTotalObjCountAndSize(int* size_p) {
+  int size = 0;
+  int count = 0;
+  LiveObjectList *lol = this;
+  do {
+    // Only compute total size if requested i.e. when size_p is not null.
+    if (size_p != NULL) {
+      Element* elements = lol->elements_;
+      for (int i = 0; i < lol->obj_count_; i++) {
+        HeapObject* heap_obj = elements[i].obj_;
+        size += heap_obj->Size();
+      }
+    }
+    count += lol->obj_count_;
+    lol = lol->prev_;
+  } while (lol != NULL);
+
+  if (size_p != NULL) {
+    *size_p = size;
+  }
+  return count;
+}
+
+
+// Adds an object to the lol.
+// Returns true if successful, else returns false.
+bool LiveObjectList::Add(HeapObject* obj) {
+  // If the object is already accounted for in the prev list which we inherit
+  // from, then no need to add it to this list.
+  if ((prev() != NULL) && (prev()->Find(obj) != NULL)) {
+    return true;
+  }
+  ASSERT(obj_count_ <= capacity_);
+  if (obj_count_ == capacity_) {
+    // The heap must have grown and we have more objects than capacity to store
+    // them.
+    return false;  // Fail this addition.
+  }
+  Element& element = elements_[obj_count_++];
+  element.id_ = next_element_id_++;
+  element.obj_ = obj;
+  return true;
+}
+
+
+// Comparator used for sorting and searching the lol.
+int LiveObjectList::CompareElement(const Element* a, const Element* b) {
+  const HeapObject* obj1 = a->obj_;
+  const HeapObject* obj2 = b->obj_;
+  // For lol elements, it doesn't matter which comes first if 2 elements point
+  // to the same object (which gets culled later).  Hence, we only care about
+  // the the greater than / less than relationships.
+  return (obj1 > obj2) ? 1 : (obj1 == obj2) ? 0 : -1;
+}
+
+
+// Looks for the specified object in the lol, and returns its element if found.
+LiveObjectList::Element* LiveObjectList::Find(HeapObject* obj) {
+  LiveObjectList* lol = this;
+  Element key;
+  Element* result = NULL;
+
+  key.obj_ = obj;
+  // Iterate through the chain of lol's to look for the object.
+  while ((result == NULL) && (lol != NULL)) {
+    result = reinterpret_cast<Element*>(
+        bsearch(&key, lol->elements_, lol->obj_count_,
+                sizeof(Element),
+                reinterpret_cast<RawComparer>(CompareElement)));
+    lol = lol->prev_;
+  }
+  return result;
+}
+
+
+// "Nullifies" (convert the HeapObject* into an SMI) so that it will get cleaned
+// up in the GCEpilogue, while preserving the sort order of the lol.
+// NOTE: the lols need to be already sorted before NullifyMostRecent() is
+// called.
+void LiveObjectList::NullifyMostRecent(HeapObject* obj) {
+  LiveObjectList* lol = last();
+  Element key;
+  Element* result = NULL;
+
+  key.obj_ = obj;
+  // Iterate through the chain of lol's to look for the object.
+  while (lol != NULL) {
+    result = reinterpret_cast<Element*>(
+        bsearch(&key, lol->elements_, lol->obj_count_,
+                sizeof(Element),
+                reinterpret_cast<RawComparer>(CompareElement)));
+    if (result != NULL) {
+      // Since there may be more than one (we are nullifying dup's after all),
+      // find the first in the current lol, and nullify that.  The lol should
+      // be sorted already to make this easy (see the use of SortAll()).
+      int i = result - lol->elements_;
+
+      // NOTE: we sort the lol in increasing order.  So, if an object has been
+      // "nullified" (its lowest bit will be cleared to make it look like an
+      // SMI), it would/should show up before the equivalent dups that have not
+      // yet been "nullified".  Hence, we should be searching backwards for the
+      // first occurence of a matching object and nullify that instance.  This
+      // will ensure that we preserve the expected sorting order.
+      for (i--; i > 0; i--) {
+        Element* element = &lol->elements_[i];
+        HeapObject* curr_obj = element->obj_;
+        if (curr_obj != obj) {
+            break;  // No more matches.  Let's move on.
+        }
+        result = element;  // Let this earlier match be the result.
+      }
+
+      // Nullify the object.
+      NullifyNonLivePointer(&result->obj_);
+      return;
+    }
+    lol = lol->prev_;
+  }
+}
+
+
+// Sorts the lol.
+void LiveObjectList::Sort() {
+  if (obj_count_ > 0) {
+    Vector<Element> elements_v(elements_, obj_count_);
+    elements_v.Sort(CompareElement);
+  }
+}
+
+
+// Sorts all captured lols starting from the latest.
+void LiveObjectList::SortAll() {
+  LiveObjectList* lol = last();
+  while (lol != NULL) {
+    lol->Sort();
+    lol = lol->prev_;
+  }
+}
+
+
+// Counts the number of objects in the heap.
+static int CountHeapObjects() {
+  int count = 0;
+  // Iterate over all the heap spaces and count the number of objects.
+  HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
+  HeapObject* heap_obj = NULL;
+  while ((heap_obj = iterator.next()) != NULL) {
+    count++;
+  }
+  return count;
+}
+
+
+// Captures a current snapshot of all objects in the heap.
+MaybeObject* LiveObjectList::Capture() {
+  HandleScope scope;
+
+  // Count the number of objects in the heap.
+  int total_count = CountHeapObjects();
+  int count = total_count;
+  int size = 0;
+
+  LiveObjectList* last_lol = last();
+  if (last_lol != NULL) {
+    count -= last_lol->TotalObjCount();
+  }
+
+  LiveObjectList* lol;
+
+  // Create a lol large enough to track all the objects.
+  lol = new LiveObjectList(last_lol, count);
+  if (lol == NULL) {
+    return NULL;  // No memory to proceed.
+  }
+
+  // The HeapIterator needs to be in its own scope because it disables
+  // allocation, and we need allocate below.
+  {
+    // Iterate over all the heap spaces and add the objects.
+    HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
+    HeapObject* heap_obj = NULL;
+    bool failed = false;
+    while (!failed && (heap_obj = iterator.next()) != NULL) {
+      failed = !lol->Add(heap_obj);
+      size += heap_obj->Size();
+    }
+    ASSERT(!failed);
+
+    lol->Sort();
+
+    // Add the current lol to the list of lols.
+    if (last_ != NULL) {
+      last_->next_ = lol;
+    } else {
+      first_ = lol;
+    }
+    last_ = lol;
+
+#ifdef VERIFY_LOL
+    if (FLAG_verify_lol) {
+      Verify(true);
+    }
+#endif
+  }
+
+  Handle<String> id_sym = Factory::LookupAsciiSymbol("id");
+  Handle<String> count_sym = Factory::LookupAsciiSymbol("count");
+  Handle<String> size_sym = Factory::LookupAsciiSymbol("size");
+
+  Handle<JSObject> result = Factory::NewJSObject(Top::object_function());
+  if (result->IsFailure()) return Object::cast(*result);
+
+  { MaybeObject* maybe_result = result->SetProperty(*id_sym,
+                                                    Smi::FromInt(lol->id()),
+                                                    NONE,
+                                                    kNonStrictMode);
+    if (maybe_result->IsFailure()) return maybe_result;
+  }
+  { MaybeObject* maybe_result = result->SetProperty(*count_sym,
+                                                    Smi::FromInt(total_count),
+                                                    NONE,
+                                                    kNonStrictMode);
+    if (maybe_result->IsFailure()) return maybe_result;
+  }
+  { MaybeObject* maybe_result = result->SetProperty(*size_sym,
+                                                    Smi::FromInt(size),
+                                                    NONE,
+                                                    kNonStrictMode);
+    if (maybe_result->IsFailure()) return maybe_result;
+  }
+
+  return *result;
+}
+
+
+// Delete doesn't actually deletes an lol.  It just marks it as invisible since
+// its contents are considered to be part of subsequent lists as well.  The
+// only time we'll actually delete the lol is when we Reset() or if the lol is
+// invisible, and its element count reaches 0.
+bool LiveObjectList::Delete(int id) {
+  LiveObjectList *lol = last();
+  while (lol != NULL) {
+    if (lol->id() == id) {
+      break;
+    }
+    lol = lol->prev_;
+  }
+
+  // If no lol is found for this id, then we fail to delete.
+  if (lol == NULL) return false;
+
+  // Else, mark the lol as invisible i.e. id == 0.
+  lol->id_ = 0;
+  list_count_--;
+  ASSERT(list_count_ >= 0);
+  if (lol->obj_count_ == 0) {
+    // Point the next lol's prev to this lol's prev.
+    LiveObjectList* next = lol->next_;
+    LiveObjectList* prev = lol->prev_;
+    // Point next's prev to prev.
+    if (next != NULL) {
+      next->prev_ = lol->prev_;
+    } else {
+      last_ = lol->prev_;
+    }
+    // Point prev's next to next.
+    if (prev != NULL) {
+      prev->next_ = lol->next_;
+    } else {
+      first_ = lol->next_;
+    }
+
+    lol->prev_ = NULL;
+    lol->next_ = NULL;
+
+    // Delete this now empty and invisible lol.
+    delete lol;
+  }
+
+  // Just in case we've marked everything invisible, then clean up completely.
+  if (list_count_ == 0) {
+    Reset();
+  }
+
+  return true;
+}
+
+
+MaybeObject* LiveObjectList::Dump(int older_id,
+                                  int newer_id,
+                                  int start_idx,
+                                  int dump_limit,
+                                  Handle<JSObject> filter_obj) {
+  if ((older_id < 0) || (newer_id < 0) || (last() == NULL)) {
+    return Failure::Exception();  // Fail: 0 is not a valid lol id.
+  }
+  if (newer_id < older_id) {
+    // They are not in the expected order.  Swap them.
+    int temp = older_id;
+    older_id = newer_id;
+    newer_id = temp;
+  }
+
+  LiveObjectList *newer_lol = FindLolForId(newer_id, last());
+  LiveObjectList *older_lol = FindLolForId(older_id, newer_lol);
+
+  // If the id is defined, and we can't find a LOL for it, then we have an
+  // invalid id.
+  if ((newer_id != 0) && (newer_lol == NULL)) {
+    return Failure::Exception();  // Fail: the newer lol id is invalid.
+  }
+  if ((older_id != 0) && (older_lol == NULL)) {
+    return Failure::Exception();  // Fail: the older lol id is invalid.
+  }
+
+  LolFilter filter(filter_obj);
+  LolDumpWriter writer(older_lol, newer_lol);
+  return DumpPrivate(&writer, start_idx, dump_limit, &filter);
+}
+
+
+MaybeObject* LiveObjectList::DumpPrivate(DumpWriter* writer,
+                                         int start,
+                                         int dump_limit,
+                                         LolFilter* filter) {
+  HandleScope scope;
+
+  // Calculate the number of entries of the dump.
+  int count = -1;
+  int size = -1;
+  writer->ComputeTotalCountAndSize(filter, &count, &size);
+
+  // Adjust for where to start the dump.
+  if ((start < 0) || (start >= count)) {
+    return Failure::Exception();  // invalid start.
+  }
+
+  int remaining_count = count - start;
+  if (dump_limit > remaining_count) {
+    dump_limit = remaining_count;
+  }
+
+  // Allocate an array to hold the result.
+  Handle<FixedArray> elements_arr = Factory::NewFixedArray(dump_limit);
+  if (elements_arr->IsFailure()) return Object::cast(*elements_arr);
+
+  // Fill in the dump.
+  Handle<Object> error;
+  bool success = writer->Write(elements_arr,
+                               start,
+                               dump_limit,
+                               filter,
+                               error);
+  if (!success) return Object::cast(*error);
+
+  MaybeObject* maybe_result;
+
+  // Allocate the result body.
+  Handle<JSObject> body = Factory::NewJSObject(Top::object_function());
+  if (body->IsFailure()) return Object::cast(*body);
+
+  // Set the updated body.count.
+  Handle<String> count_sym = Factory::LookupAsciiSymbol("count");
+  maybe_result = body->SetProperty(*count_sym,
+                                   Smi::FromInt(count),
+                                   NONE,
+                                   kNonStrictMode);
+  if (maybe_result->IsFailure()) return maybe_result;
+
+  // Set the updated body.size if appropriate.
+  if (size >= 0) {
+    Handle<String> size_sym = Factory::LookupAsciiSymbol("size");
+    maybe_result = body->SetProperty(*size_sym,
+                                     Smi::FromInt(size),
+                                     NONE,
+                                     kNonStrictMode);
+    if (maybe_result->IsFailure()) return maybe_result;
+  }
+
+  // Set body.first_index.
+  Handle<String> first_sym = Factory::LookupAsciiSymbol("first_index");
+  maybe_result = body->SetProperty(*first_sym,
+                                   Smi::FromInt(start),
+                                   NONE,
+                                   kNonStrictMode);
+  if (maybe_result->IsFailure()) return maybe_result;
+
+  // Allocate the JSArray of the elements.
+  Handle<JSObject> elements = Factory::NewJSObject(Top::array_function());
+  if (elements->IsFailure()) return Object::cast(*elements);
+  Handle<JSArray>::cast(elements)->SetContent(*elements_arr);
+
+  // Set body.elements.
+  Handle<String> elements_sym = Factory::LookupAsciiSymbol("elements");
+  maybe_result = body->SetProperty(*elements_sym,
+                                   *elements,
+                                   NONE,
+                                   kNonStrictMode);
+  if (maybe_result->IsFailure()) return maybe_result;
+
+  return *body;
+}
+
+
+MaybeObject* LiveObjectList::Summarize(int older_id,
+                                       int newer_id,
+                                       Handle<JSObject> filter_obj) {
+  if ((older_id < 0) || (newer_id < 0) || (last() == NULL)) {
+    return Failure::Exception();  // Fail: 0 is not a valid lol id.
+  }
+  if (newer_id < older_id) {
+    // They are not in the expected order.  Swap them.
+    int temp = older_id;
+    older_id = newer_id;
+    newer_id = temp;
+  }
+
+  LiveObjectList *newer_lol = FindLolForId(newer_id, last());
+  LiveObjectList *older_lol = FindLolForId(older_id, newer_lol);
+
+  // If the id is defined, and we can't find a LOL for it, then we have an
+  // invalid id.
+  if ((newer_id != 0) && (newer_lol == NULL)) {
+    return Failure::Exception();  // Fail: the newer lol id is invalid.
+  }
+  if ((older_id != 0) && (older_lol == NULL)) {
+    return Failure::Exception();  // Fail: the older lol id is invalid.
+  }
+
+  LolFilter filter(filter_obj);
+  LolSummaryWriter writer(older_lol, newer_lol);
+  return SummarizePrivate(&writer, &filter, false);
+}
+
+
+// Creates a summary report for the debugger.
+// Note: the SummaryWriter takes care of iterating over objects and filling in
+// the summary.
+MaybeObject* LiveObjectList::SummarizePrivate(SummaryWriter* writer,
+                                              LolFilter* filter,
+                                              bool is_tracking_roots) {
+  HandleScope scope;
+  MaybeObject* maybe_result;
+
+  LiveObjectSummary summary(filter);
+  writer->Write(&summary);
+
+  // The result body will look like this:
+  // body: {
+  //   count: <total_count>,
+  //   size: <total_size>,
+  //   found_root: <boolean>,       // optional.
+  //   found_weak_root: <boolean>,  // optional.
+  //   summary: [
+  //     {
+  //       desc: "<object type name>",
+  //       count: <count>,
+  //       size: size
+  //     },
+  //     ...
+  //   ]
+  // }
+
+  // Prefetch some needed symbols.
+  Handle<String> desc_sym = Factory::LookupAsciiSymbol("desc");
+  Handle<String> count_sym = Factory::LookupAsciiSymbol("count");
+  Handle<String> size_sym = Factory::LookupAsciiSymbol("size");
+  Handle<String> summary_sym = Factory::LookupAsciiSymbol("summary");
+
+  // Allocate the summary array.
+  int entries_count = summary.GetNumberOfEntries();
+  Handle<FixedArray> summary_arr =
+      Factory::NewFixedArray(entries_count);
+  if (summary_arr->IsFailure()) return Object::cast(*summary_arr);
+
+  int idx = 0;
+  for (int i = 0; i < LiveObjectSummary::kNumberOfEntries; i++) {
+    // Allocate the summary record.
+    Handle<JSObject> detail = Factory::NewJSObject(Top::object_function());
+    if (detail->IsFailure()) return Object::cast(*detail);
+
+    // Fill in the summary record.
+    LiveObjectType type = static_cast<LiveObjectType>(i);
+    int count = summary.Count(type);
+    if (count) {
+      const char* desc_cstr = GetObjectTypeDesc(type);
+      Handle<String> desc = Factory::LookupAsciiSymbol(desc_cstr);
+      int size = summary.Size(type);
+
+      maybe_result = detail->SetProperty(*desc_sym,
+                                         *desc,
+                                         NONE,
+                                         kNonStrictMode);
+      if (maybe_result->IsFailure()) return maybe_result;
+      maybe_result = detail->SetProperty(*count_sym,
+                                         Smi::FromInt(count),
+                                         NONE,
+                                         kNonStrictMode);
+      if (maybe_result->IsFailure()) return maybe_result;
+      maybe_result = detail->SetProperty(*size_sym,
+                                         Smi::FromInt(size),
+                                         NONE,
+                                         kNonStrictMode);
+      if (maybe_result->IsFailure()) return maybe_result;
+
+      summary_arr->set(idx++, *detail);
+    }
+  }
+
+  // Wrap the summary fixed array in a JS array.
+  Handle<JSObject> summary_obj = Factory::NewJSObject(Top::array_function());
+  if (summary_obj->IsFailure()) return Object::cast(*summary_obj);
+  Handle<JSArray>::cast(summary_obj)->SetContent(*summary_arr);
+
+  // Create the body object.
+  Handle<JSObject> body = Factory::NewJSObject(Top::object_function());
+  if (body->IsFailure()) return Object::cast(*body);
+
+  // Fill out the body object.
+  int total_count = summary.total_count();
+  int total_size = summary.total_size();
+  maybe_result = body->SetProperty(*count_sym,
+                                   Smi::FromInt(total_count),
+                                   NONE,
+                                   kNonStrictMode);
+  if (maybe_result->IsFailure()) return maybe_result;
+
+  maybe_result = body->SetProperty(*size_sym,
+                                   Smi::FromInt(total_size),
+                                   NONE,
+                                   kNonStrictMode);
+  if (maybe_result->IsFailure()) return maybe_result;
+
+  if (is_tracking_roots) {
+    int found_root = summary.found_root();
+    int found_weak_root = summary.found_weak_root();
+    Handle<String> root_sym = Factory::LookupAsciiSymbol("found_root");
+    Handle<String> weak_root_sym =
+        Factory::LookupAsciiSymbol("found_weak_root");
+    maybe_result = body->SetProperty(*root_sym,
+                                     Smi::FromInt(found_root),
+                                     NONE,
+                                     kNonStrictMode);
+    if (maybe_result->IsFailure()) return maybe_result;
+    maybe_result = body->SetProperty(*weak_root_sym,
+                                     Smi::FromInt(found_weak_root),
+                                     NONE,
+                                     kNonStrictMode);
+    if (maybe_result->IsFailure()) return maybe_result;
+  }
+
+  maybe_result = body->SetProperty(*summary_sym,
+                                   *summary_obj,
+                                   NONE,
+                                   kNonStrictMode);
+  if (maybe_result->IsFailure()) return maybe_result;
+
+  return *body;
+}
+
+
+// Returns an array listing the captured lols.
+// Note: only dumps the section starting at start_idx and only up to
+// dump_limit entries.
+MaybeObject* LiveObjectList::Info(int start_idx, int dump_limit) {
+  HandleScope scope;
+  MaybeObject* maybe_result;
+
+  int total_count = LiveObjectList::list_count();
+  int dump_count = total_count;
+
+  // Adjust for where to start the dump.
+  if (total_count == 0) {
+      start_idx = 0;  // Ensure this to get an empty list.
+  } else if ((start_idx < 0) || (start_idx >= total_count)) {
+    return Failure::Exception();  // invalid start.
+  }
+  dump_count -= start_idx;
+
+  // Adjust for the dump limit.
+  if (dump_count > dump_limit) {
+    dump_count = dump_limit;
+  }
+
+  // Allocate an array to hold the result.
+  Handle<FixedArray> list = Factory::NewFixedArray(dump_count);
+  if (list->IsFailure()) return Object::cast(*list);
+
+  // Prefetch some needed symbols.
+  Handle<String> id_sym = Factory::LookupAsciiSymbol("id");
+  Handle<String> count_sym = Factory::LookupAsciiSymbol("count");
+  Handle<String> size_sym = Factory::LookupAsciiSymbol("size");
+
+  // Fill the array with the lol details.
+  int idx = 0;
+  LiveObjectList* lol = first_;
+  while ((lol != NULL) && (idx < start_idx)) {  // Skip tail entries.
+    if (lol->id() != 0) {
+      idx++;
+    }
+    lol = lol->next();
+  }
+  idx = 0;
+  while ((lol != NULL) && (dump_limit != 0)) {
+    if (lol->id() != 0) {
+      int count;
+      int size;
+      count = lol->GetTotalObjCountAndSize(&size);
+
+      Handle<JSObject> detail = Factory::NewJSObject(Top::object_function());
+      if (detail->IsFailure()) return Object::cast(*detail);
+
+      maybe_result = detail->SetProperty(*id_sym,
+                                         Smi::FromInt(lol->id()),
+                                         NONE,
+                                         kNonStrictMode);
+      if (maybe_result->IsFailure()) return maybe_result;
+      maybe_result = detail->SetProperty(*count_sym,
+                                         Smi::FromInt(count),
+                                         NONE,
+                                         kNonStrictMode);
+      if (maybe_result->IsFailure()) return maybe_result;
+      maybe_result = detail->SetProperty(*size_sym,
+                                         Smi::FromInt(size),
+                                         NONE,
+                                         kNonStrictMode);
+      if (maybe_result->IsFailure()) return maybe_result;
+      list->set(idx++, *detail);
+      dump_limit--;
+    }
+    lol = lol->next();
+  }
+
+  // Return the result as a JS array.
+  Handle<JSObject> lols = Factory::NewJSObject(Top::array_function());
+  Handle<JSArray>::cast(lols)->SetContent(*list);
+
+  Handle<JSObject> result = Factory::NewJSObject(Top::object_function());
+  if (result->IsFailure()) return Object::cast(*result);
+
+  maybe_result = result->SetProperty(*count_sym,
+                                     Smi::FromInt(total_count),
+                                     NONE,
+                                     kNonStrictMode);
+  if (maybe_result->IsFailure()) return maybe_result;
+
+  Handle<String> first_sym = Factory::LookupAsciiSymbol("first_index");
+  maybe_result = result->SetProperty(*first_sym,
+                                     Smi::FromInt(start_idx),
+                                     NONE,
+                                     kNonStrictMode);
+  if (maybe_result->IsFailure()) return maybe_result;
+
+  Handle<String> lists_sym = Factory::LookupAsciiSymbol("lists");
+  maybe_result = result->SetProperty(*lists_sym,
+                                     *lols,
+                                     NONE,
+                                     kNonStrictMode);
+  if (maybe_result->IsFailure()) return maybe_result;
+
+  return *result;
+}
+
+
+// Deletes all captured lols.
+void LiveObjectList::Reset() {
+  LiveObjectList *lol = last();
+  // Just delete the last.  Each lol will delete it's prev automatically.
+  delete lol;
+
+  next_element_id_ = 1;
+  list_count_ = 0;
+  last_id_ = 0;
+  first_ = NULL;
+  last_ = NULL;
+}
+
+
+// Gets the object for the specified obj id.
+Object* LiveObjectList::GetObj(int obj_id) {
+  Element* element = FindElementFor<int>(GetElementId, obj_id);
+  if (element != NULL) {
+    return Object::cast(element->obj_);
+  }
+  return Heap::undefined_value();
+}
+
+
+// Gets the obj id for the specified address if valid.
+int LiveObjectList::GetObjId(Object* obj) {
+  // Make a heap object pointer from the address.
+  HeapObject* hobj = HeapObject::cast(obj);
+  Element* element = FindElementFor<HeapObject*>(GetElementObj, hobj);
+  if (element != NULL) {
+    return element->id_;
+  }
+  return 0;  // Invalid address.
+}
+
+
+// Gets the obj id for the specified address if valid.
+Object* LiveObjectList::GetObjId(Handle<String> address) {
+  SmartPointer<char> addr_str =
+      address->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+
+  // Extract the address value from the string.
+  int value = static_cast<int>(StringToInt(*address, 16));
+  Object* obj = reinterpret_cast<Object*>(value);
+  return Smi::FromInt(GetObjId(obj));
+}
+
+
+// Helper class for copying HeapObjects.
+class LolVisitor: public ObjectVisitor {
+ public:
+
+  LolVisitor(HeapObject* target, Handle<HeapObject> handle_to_skip)
+      : target_(target), handle_to_skip_(handle_to_skip), found_(false) {}
+
+  void VisitPointer(Object** p) { CheckPointer(p); }
+
+  void VisitPointers(Object** start, Object** end) {
+    // Check all HeapObject pointers in [start, end).
+    for (Object** p = start; !found() && p < end; p++) CheckPointer(p);
+  }
+
+  inline bool found() const { return found_; }
+  inline bool reset() { return found_ = false; }
+
+ private:
+  inline void CheckPointer(Object** p) {
+    Object* object = *p;
+    if (HeapObject::cast(object) == target_) {
+      // We may want to skip this handle because the handle may be a local
+      // handle in a handle scope in one of our callers.  Once we return,
+      // that handle will be popped.  Hence, we don't want to count it as
+      // a root that would have kept the target object alive.
+      if (!handle_to_skip_.is_null() &&
+          handle_to_skip_.location() == reinterpret_cast<HeapObject**>(p)) {
+        return;  // Skip this handle.
+      }
+      found_ = true;
+    }
+  }
+
+  HeapObject* target_;
+  Handle<HeapObject> handle_to_skip_;
+  bool found_;
+};
+
+
+inline bool AddRootRetainerIfFound(const LolVisitor& visitor,
+                                   LolFilter* filter,
+                                   LiveObjectSummary *summary,
+                                   void (*SetRootFound)(LiveObjectSummary *s),
+                                   int start,
+                                   int dump_limit,
+                                   int* total_count,
+                                   Handle<FixedArray> retainers_arr,
+                                   int* count,
+                                   int* index,
+                                   const char* root_name,
+                                   Handle<String> id_sym,
+                                   Handle<String> desc_sym,
+                                   Handle<String> size_sym,
+                                   Handle<Object> error) {
+  HandleScope scope;
+
+  // Scratch handles.
+  Handle<JSObject> detail;
+  Handle<String> desc;
+  Handle<HeapObject> retainer;
+
+  if (visitor.found()) {
+    if (!filter->is_active()) {
+      (*total_count)++;
+      if (summary) {
+        SetRootFound(summary);
+      } else if ((*total_count > start) && ((*index) < dump_limit)) {
+        (*count)++;
+        if (!retainers_arr.is_null()) {
+          return AddObjDetail(retainers_arr,
+                              (*index)++,
+                              0,
+                              retainer,
+                              root_name,
+                              id_sym,
+                              desc_sym,
+                              size_sym,
+                              detail,
+                              desc,
+                              error);
+        }
+      }
+    }
+  }
+  return true;
+}
+
+
+inline void SetFoundRoot(LiveObjectSummary *summary) {
+  summary->set_found_root();
+}
+
+
+inline void SetFoundWeakRoot(LiveObjectSummary *summary) {
+  summary->set_found_weak_root();
+}
+
+
+int LiveObjectList::GetRetainers(Handle<HeapObject> target,
+                                 Handle<JSObject> instance_filter,
+                                 Handle<FixedArray> retainers_arr,
+                                 int start,
+                                 int dump_limit,
+                                 int* total_count,
+                                 LolFilter* filter,
+                                 LiveObjectSummary *summary,
+                                 JSFunction* arguments_function,
+                                 Handle<Object> error) {
+  HandleScope scope;
+
+  // Scratch handles.
+  Handle<JSObject> detail;
+  Handle<String> desc;
+  Handle<HeapObject> retainer;
+
+  // Prefetch some needed symbols.
+  Handle<String> id_sym = Factory::LookupAsciiSymbol("id");
+  Handle<String> desc_sym = Factory::LookupAsciiSymbol("desc");
+  Handle<String> size_sym = Factory::LookupAsciiSymbol("size");
+
+  NoHandleAllocation ha;
+  int count = 0;
+  int index = 0;
+  Handle<JSObject> last_obj;
+
+  *total_count = 0;
+
+  // Iterate roots.
+  LolVisitor lol_visitor(*target, target);
+  Heap::IterateStrongRoots(&lol_visitor, VISIT_ALL);
+  if (!AddRootRetainerIfFound(lol_visitor,
+                              filter,
+                              summary,
+                              SetFoundRoot,
+                              start,
+                              dump_limit,
+                              total_count,
+                              retainers_arr,
+                              &count,
+                              &index,
+                              "<root>",
+                              id_sym,
+                              desc_sym,
+                              size_sym,
+                              error)) {
+    return -1;
+  }
+
+  lol_visitor.reset();
+  Heap::IterateWeakRoots(&lol_visitor, VISIT_ALL);
+  if (!AddRootRetainerIfFound(lol_visitor,
+                              filter,
+                              summary,
+                              SetFoundWeakRoot,
+                              start,
+                              dump_limit,
+                              total_count,
+                              retainers_arr,
+                              &count,
+                              &index,
+                              "<weak root>",
+                              id_sym,
+                              desc_sym,
+                              size_sym,
+                              error)) {
+    return -1;
+  }
+
+  // Iterate the live object lists.
+  LolIterator it(NULL, last());
+  for (it.Init(); !it.Done() && (index < dump_limit); it.Next()) {
+    HeapObject* heap_obj = it.Obj();
+
+    // Only look at all JSObjects.
+    if (heap_obj->IsJSObject()) {
+      // Skip context extension objects and argument arrays as these are
+      // checked in the context of functions using them.
+      JSObject* obj = JSObject::cast(heap_obj);
+      if (obj->IsJSContextExtensionObject() ||
+          obj->map()->constructor() == arguments_function) {
+        continue;
+      }
+
+      // Check if the JS object has a reference to the object looked for.
+      if (obj->ReferencesObject(*target)) {
+        // Check instance filter if supplied. This is normally used to avoid
+        // references from mirror objects (see Runtime_IsInPrototypeChain).
+        if (!instance_filter->IsUndefined()) {
+          Object* V = obj;
+          while (true) {
+            Object* prototype = V->GetPrototype();
+            if (prototype->IsNull()) {
+              break;
+            }
+            if (*instance_filter == prototype) {
+              obj = NULL;  // Don't add this object.
+              break;
+            }
+            V = prototype;
+          }
+        }
+
+        if (obj != NULL) {
+          // Skip objects that have been filtered out.
+          if (filter->Matches(heap_obj)) {
+            continue;
+          }
+
+          // Valid reference found add to instance array if supplied an update
+          // count.
+          last_obj = Handle<JSObject>(obj);
+          (*total_count)++;
+
+          if (summary != NULL) {
+            summary->Add(heap_obj);
+          } else if ((*total_count > start) && (index < dump_limit)) {
+            count++;
+            if (!retainers_arr.is_null()) {
+              retainer = Handle<HeapObject>(heap_obj);
+              bool success = AddObjDetail(retainers_arr,
+                                          index++,
+                                          it.Id(),
+                                          retainer,
+                                          NULL,
+                                          id_sym,
+                                          desc_sym,
+                                          size_sym,
+                                          detail,
+                                          desc,
+                                          error);
+              if (!success) return -1;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  // Check for circular reference only. This can happen when the object is only
+  // referenced from mirrors and has a circular reference in which case the
+  // object is not really alive and would have been garbage collected if not
+  // referenced from the mirror.
+
+  if (*total_count == 1 && !last_obj.is_null() && *last_obj == *target) {
+    count = 0;
+    *total_count = 0;
+  }
+
+  return count;
+}
+
+
+MaybeObject* LiveObjectList::GetObjRetainers(int obj_id,
+                                             Handle<JSObject> instance_filter,
+                                             bool verbose,
+                                             int start,
+                                             int dump_limit,
+                                             Handle<JSObject> filter_obj) {
+  HandleScope scope;
+
+  // Get the target object.
+  HeapObject* heap_obj = HeapObject::cast(GetObj(obj_id));
+  if (heap_obj == Heap::undefined_value()) {
+    return heap_obj;
+  }
+
+  Handle<HeapObject> target = Handle<HeapObject>(heap_obj);
+
+  // Get the constructor function for context extension and arguments array.
+  JSObject* arguments_boilerplate =
+      Top::context()->global_context()->arguments_boilerplate();
+  JSFunction* arguments_function =
+      JSFunction::cast(arguments_boilerplate->map()->constructor());
+
+  Handle<JSFunction> args_function = Handle<JSFunction>(arguments_function);
+  LolFilter filter(filter_obj);
+
+  if (!verbose) {
+    RetainersSummaryWriter writer(target, instance_filter, args_function);
+    return SummarizePrivate(&writer, &filter, true);
+
+  } else {
+    RetainersDumpWriter writer(target, instance_filter, args_function);
+    Object* body_obj;
+    MaybeObject* maybe_result =
+        DumpPrivate(&writer, start, dump_limit, &filter);
+    if (!maybe_result->ToObject(&body_obj)) {
+      return maybe_result;
+    }
+
+    // Set body.id.
+    Handle<JSObject> body = Handle<JSObject>(JSObject::cast(body_obj));
+    Handle<String> id_sym = Factory::LookupAsciiSymbol("id");
+    maybe_result = body->SetProperty(*id_sym,
+                                     Smi::FromInt(obj_id),
+                                     NONE,
+                                     kNonStrictMode);
+    if (maybe_result->IsFailure()) return maybe_result;
+
+    return *body;
+  }
+}
+
+
+Object* LiveObjectList::PrintObj(int obj_id) {
+  Object* obj = GetObj(obj_id);
+  if (!obj) {
+    return Heap::undefined_value();
+  }
+
+  EmbeddedVector<char, 128> temp_filename;
+  static int temp_count = 0;
+  const char* path_prefix = ".";
+
+  if (FLAG_lol_workdir) {
+    path_prefix = FLAG_lol_workdir;
+  }
+  OS::SNPrintF(temp_filename, "%s/lol-print-%d", path_prefix, ++temp_count);
+
+  FILE* f = OS::FOpen(temp_filename.start(), "w+");
+
+  PrintF(f, "@%d ", LiveObjectList::GetObjId(obj));
+#ifdef OBJECT_PRINT
+#ifdef INSPECTOR
+  Inspector::DumpObjectType(f, obj);
+#endif  // INSPECTOR
+  PrintF(f, "\n");
+  obj->Print(f);
+#else  // !OBJECT_PRINT
+  obj->ShortPrint(f);
+#endif  // !OBJECT_PRINT
+  PrintF(f, "\n");
+  Flush(f);
+  fclose(f);
+
+  // Create a string from the temp_file.
+  // Note: the mmapped resource will take care of closing the file.
+  MemoryMappedExternalResource* resource =
+      new MemoryMappedExternalResource(temp_filename.start(), true);
+  if (resource->exists() && !resource->is_empty()) {
+    ASSERT(resource->IsAscii());
+    Handle<String> dump_string =
+        Factory::NewExternalStringFromAscii(resource);
+    ExternalStringTable::AddString(*dump_string);
+    return *dump_string;
+  } else {
+    delete resource;
+  }
+  return Heap::undefined_value();
+}
+
+
+class LolPathTracer: public PathTracer {
+ public:
+  LolPathTracer(FILE* out,
+                Object* search_target,
+                WhatToFind what_to_find)
+      : PathTracer(search_target, what_to_find, VISIT_ONLY_STRONG), out_(out) {}
+
+ private:
+  void ProcessResults();
+
+  FILE* out_;
+};
+
+
+void LolPathTracer::ProcessResults() {
+  if (found_target_) {
+    PrintF(out_, "=====================================\n");
+    PrintF(out_, "====        Path to object       ====\n");
+    PrintF(out_, "=====================================\n\n");
+
+    ASSERT(!object_stack_.is_empty());
+    Object* prev = NULL;
+    for (int i = 0, index = 0; i < object_stack_.length(); i++) {
+      Object* obj = object_stack_[i];
+
+      // Skip this object if it is basically the internals of the
+      // previous object (which would have dumped its details already).
+      if (prev && prev->IsJSObject() &&
+          (obj != search_target_)) {
+        JSObject* jsobj = JSObject::cast(prev);
+        if (obj->IsFixedArray() &&
+            jsobj->properties() == FixedArray::cast(obj)) {
+          // Skip this one because it would have been printed as the
+          // properties of the last object already.
+          continue;
+        } else if (obj->IsHeapObject() &&
+                   jsobj->elements() == HeapObject::cast(obj)) {
+          // Skip this one because it would have been printed as the
+          // elements of the last object already.
+          continue;
+        }
+      }
+
+      // Print a connecting arrow.
+      if (i > 0) PrintF(out_, "\n     |\n     |\n     V\n\n");
+
+      // Print the object index.
+      PrintF(out_, "[%d] ", ++index);
+
+      // Print the LOL object ID:
+      int id = LiveObjectList::GetObjId(obj);
+      if (id > 0) PrintF(out_, "@%d ", id);
+
+#ifdef OBJECT_PRINT
+#ifdef INSPECTOR
+      Inspector::DumpObjectType(out_, obj);
+#endif  // INSPECTOR
+      PrintF(out_, "\n");
+      obj->Print(out_);
+#else  // !OBJECT_PRINT
+      obj->ShortPrint(out_);
+      PrintF(out_, "\n");
+#endif  // !OBJECT_PRINT
+      Flush(out_);
+    }
+    PrintF(out_, "\n");
+    PrintF(out_, "=====================================\n\n");
+    Flush(out_);
+  }
+}
+
+
+Object* LiveObjectList::GetPathPrivate(HeapObject* obj1, HeapObject* obj2) {
+  EmbeddedVector<char, 128> temp_filename;
+  static int temp_count = 0;
+  const char* path_prefix = ".";
+
+  if (FLAG_lol_workdir) {
+    path_prefix = FLAG_lol_workdir;
+  }
+  OS::SNPrintF(temp_filename, "%s/lol-getpath-%d", path_prefix, ++temp_count);
+
+  FILE* f = OS::FOpen(temp_filename.start(), "w+");
+
+  // Save the previous verbosity.
+  bool prev_verbosity = FLAG_use_verbose_printer;
+  FLAG_use_verbose_printer = false;
+
+  // Dump the paths.
+  {
+    // The tracer needs to be scoped because its usage asserts no allocation,
+    // and we need to allocate the result string below.
+    LolPathTracer tracer(f, obj2, LolPathTracer::FIND_FIRST);
+
+    bool found = false;
+    if (obj1 == NULL) {
+      // Check for ObjectGroups that references this object.
+      // TODO(mlam): refactor this to be more modular.
+      {
+        List<ObjectGroup*>* groups = GlobalHandles::ObjectGroups();
+        for (int i = 0; i < groups->length(); i++) {
+          ObjectGroup* group = groups->at(i);
+          if (group == NULL) continue;
+
+          bool found_group = false;
+          List<Object**>& objects = group->objects_;
+          for (int j = 0; j < objects.length(); j++) {
+            Object* object = *objects[j];
+            HeapObject* hobj = HeapObject::cast(object);
+            if (obj2 == hobj) {
+              found_group = true;
+              break;
+            }
+          }
+
+          if (found_group) {
+            PrintF(f,
+                   "obj %p is a member of object group %p {\n",
+                   reinterpret_cast<void*>(obj2),
+                   reinterpret_cast<void*>(group));
+            for (int j = 0; j < objects.length(); j++) {
+              Object* object = *objects[j];
+              if (!object->IsHeapObject()) continue;
+
+              HeapObject* hobj = HeapObject::cast(object);
+              int id = GetObjId(hobj);
+              if (id != 0) {
+                PrintF(f, "  @%d:", id);
+              } else {
+                PrintF(f, "  <no id>:");
+              }
+
+              char buffer[512];
+              GenerateObjectDesc(hobj, buffer, sizeof(buffer));
+              PrintF(f, " %s", buffer);
+              if (hobj == obj2) {
+                PrintF(f, " <===");
+              }
+              PrintF(f, "\n");
+            }
+            PrintF(f, "}\n");
+          }
+        }
+      }
+
+      PrintF(f, "path from roots to obj %p\n", reinterpret_cast<void*>(obj2));
+      Heap::IterateRoots(&tracer, VISIT_ONLY_STRONG);
+      found = tracer.found();
+
+      if (!found) {
+        PrintF(f, "  No paths found. Checking symbol tables ...\n");
+        SymbolTable* symbol_table = Heap::raw_unchecked_symbol_table();
+        tracer.VisitPointers(reinterpret_cast<Object**>(&symbol_table),
+                             reinterpret_cast<Object**>(&symbol_table)+1);
+        found = tracer.found();
+        if (!found) {
+          symbol_table->IteratePrefix(&tracer);
+          found = tracer.found();
+        }
+      }
+
+      if (!found) {
+        PrintF(f, "  No paths found. Checking weak roots ...\n");
+        // Check weak refs next.
+        GlobalHandles::IterateWeakRoots(&tracer);
+        found = tracer.found();
+      }
+
+    } else {
+      PrintF(f, "path from obj %p to obj %p:\n",
+             reinterpret_cast<void*>(obj1), reinterpret_cast<void*>(obj2));
+      tracer.TracePathFrom(reinterpret_cast<Object**>(&obj1));
+      found = tracer.found();
+    }
+
+    if (!found) {
+      PrintF(f, "  No paths found\n\n");
+    }
+  }
+
+  // Flush and clean up the dumped file.
+  Flush(f);
+  fclose(f);
+
+  // Restore the previous verbosity.
+  FLAG_use_verbose_printer = prev_verbosity;
+
+  // Create a string from the temp_file.
+  // Note: the mmapped resource will take care of closing the file.
+  MemoryMappedExternalResource* resource =
+      new MemoryMappedExternalResource(temp_filename.start(), true);
+  if (resource->exists() && !resource->is_empty()) {
+    ASSERT(resource->IsAscii());
+    Handle<String> path_string =
+        Factory::NewExternalStringFromAscii(resource);
+    ExternalStringTable::AddString(*path_string);
+    return *path_string;
+  } else {
+    delete resource;
+  }
+  return Heap::undefined_value();
+}
+
+
+Object* LiveObjectList::GetPath(int obj_id1,
+                                int obj_id2,
+                                Handle<JSObject> instance_filter) {
+  HandleScope scope;
+
+  // Get the target object.
+  HeapObject* obj1 = NULL;
+  if (obj_id1 != 0) {
+    obj1 = HeapObject::cast(GetObj(obj_id1));
+    if (obj1 == Heap::undefined_value()) {
+      return obj1;
+    }
+  }
+
+  HeapObject* obj2 = HeapObject::cast(GetObj(obj_id2));
+  if (obj2 == Heap::undefined_value()) {
+    return obj2;
+  }
+
+  return GetPathPrivate(obj1, obj2);
+}
+
+
+void LiveObjectList::DoProcessNonLive(HeapObject *obj) {
+  // We should only be called if we have at least one lol to search.
+  ASSERT(last() != NULL);
+  Element* element = last()->Find(obj);
+  if (element != NULL) {
+    NullifyNonLivePointer(&element->obj_);
+  }
+}
+
+
+void LiveObjectList::IterateElementsPrivate(ObjectVisitor* v) {
+  LiveObjectList* lol = last();
+  while (lol != NULL) {
+    Element* elements = lol->elements_;
+    int count = lol->obj_count_;
+    for (int i = 0; i < count; i++) {
+      HeapObject** p = &elements[i].obj_;
+      v->VisitPointer(reinterpret_cast<Object **>(p));
+    }
+    lol = lol->prev_;
+  }
+}
+
+
+// Purpose: Called by GCEpilogue to purge duplicates.  Not to be called by
+// anyone else.
+void LiveObjectList::PurgeDuplicates() {
+  bool is_sorted = false;
+  LiveObjectList* lol = last();
+  if (!lol) {
+    return;  // Nothing to purge.
+  }
+
+  int total_count = lol->TotalObjCount();
+  if (!total_count) {
+    return;  // Nothing to purge.
+  }
+
+  Element* elements = NewArray<Element>(total_count);
+  int count = 0;
+
+  // Copy all the object elements into a consecutive array.
+  while (lol) {
+    memcpy(&elements[count], lol->elements_, lol->obj_count_ * sizeof(Element));
+    count += lol->obj_count_;
+    lol = lol->prev_;
+  }
+  qsort(elements, total_count, sizeof(Element),
+        reinterpret_cast<RawComparer>(CompareElement));
+
+  ASSERT(count == total_count);
+
+  // Iterate over all objects in the consolidated list and check for dups.
+  total_count--;
+  for (int i = 0; i < total_count; ) {
+    Element* curr = &elements[i];
+    HeapObject* curr_obj = curr->obj_;
+    int j = i+1;
+    bool done = false;
+
+    while (!done && (j < total_count)) {
+      // Process if the element's object is still live after the current GC.
+      // Non-live objects will be converted to SMIs i.e. not HeapObjects.
+      if (curr_obj->IsHeapObject()) {
+        Element* next = &elements[j];
+        HeapObject* next_obj = next->obj_;
+        if (next_obj->IsHeapObject()) {
+          if (curr_obj != next_obj) {
+            done = true;
+            continue;  // Live object but no match.  Move on.
+          }
+
+          // NOTE: we've just GCed the LOLs.  Hence, they are no longer sorted.
+          // Since we detected at least one need to search for entries, we'll
+          // sort it to enable the use of NullifyMostRecent() below.  We only
+          // need to sort it once (except for one exception ... see below).
+          if (!is_sorted) {
+            SortAll();
+            is_sorted = true;
+          }
+
+          // We have a match.  Need to nullify the most recent ref to this
+          // object.  We'll keep the oldest ref:
+          // Note: we will nullify the element record in the LOL
+          // database, not in the local sorted copy of the elements.
+          NullifyMostRecent(curr_obj);
+        }
+      }
+      // Either the object was already marked for purging, or we just marked
+      // it.  Either way, if there's more than one dup, then we need to check
+      // the next element for another possible dup against the current as well
+      // before we move on.  So, here we go.
+      j++;
+    }
+
+    // We can move on to checking the match on the next element.
+    i = j;
+  }
+
+  DeleteArray<Element>(elements);
+}
+
+
+// Purpose: Purges dead objects and resorts the LOLs.
+void LiveObjectList::GCEpiloguePrivate() {
+  // Note: During the GC, ConsStrings may be collected and pointers may be
+  // forwarded to its constituent string.  As a result, we may find dupes of
+  // objects references in the LOL list.
+  // Another common way we get dups is that free chunks that have been swept
+  // in the oldGen heap may be kept as ByteArray objects in a free list.
+  //
+  // When we promote live objects from the youngGen, the object may be moved
+  // to the start of these free chunks.  Since there is no free or move event
+  // for the free chunks, their addresses will show up 2 times: once for their
+  // original free ByteArray selves, and once for the newly promoted youngGen
+  // object.  Hence, we can get a duplicate address in the LOL again.
+  //
+  // We need to eliminate these dups because the LOL implementation expects to
+  // only have at most one unique LOL reference to any object at any time.
+  PurgeDuplicates();
+
+  // After the GC, sweep away all free'd Elements and compact.
+  LiveObjectList *prev = NULL;
+  LiveObjectList *next = NULL;
+
+  // Iterating from the youngest lol to the oldest lol.
+  for (LiveObjectList *lol = last(); lol; lol = prev) {
+    Element* elements = lol->elements_;
+    prev = lol->prev();  // Save the prev.
+
+    // Remove any references to collected objects.
+    int i = 0;
+    while (i < lol->obj_count_) {
+      Element& element = elements[i];
+      if (!element.obj_->IsHeapObject()) {
+        // If the HeapObject address was converted into a SMI, then this
+        // is a dead object.  Copy the last element over this one.
+        element = elements[lol->obj_count_ - 1];
+        lol->obj_count_--;
+        // We've just moved the last element into this index.  We'll revisit
+        // this index again.  Hence, no need to increment the iterator.
+      } else {
+        i++;  // Look at the next element next.
+      }
+    }
+
+    int new_count = lol->obj_count_;
+
+    // Check if there are any more elements to keep after purging the dead ones.
+    if (new_count == 0) {
+      DeleteArray<Element>(elements);
+      lol->elements_ = NULL;
+      lol->capacity_ = 0;
+      ASSERT(lol->obj_count_ == 0);
+
+      // If the list is also invisible, the clean up the list as well.
+      if (lol->id_ == 0) {
+        // Point the next lol's prev to this lol's prev.
+        if (next) {
+          next->prev_ = lol->prev_;
+        } else {
+          last_ = lol->prev_;
+        }
+
+        // Delete this now empty and invisible lol.
+        delete lol;
+
+        // Don't point the next to this lol since it is now deleted.
+        // Leave the next pointer pointing to the current lol.
+        continue;
+      }
+
+    } else {
+      // If the obj_count_ is less than the capacity and the difference is
+      // greater than a specified threshold, then we should shrink the list.
+      int diff = lol->capacity_ - new_count;
+      const int kMaxUnusedSpace = 64;
+      if (diff > kMaxUnusedSpace) {  // Threshold for shrinking.
+        // Shrink the list.
+        Element *new_elements = NewArray<Element>(new_count);
+        memcpy(new_elements, elements, new_count * sizeof(Element));
+
+        DeleteArray<Element>(elements);
+        lol->elements_ = new_elements;
+        lol->capacity_ = new_count;
+      }
+      ASSERT(lol->obj_count_ == new_count);
+
+      lol->Sort();  // We've moved objects.  Re-sort in case.
+    }
+
+    // Save the next (for the previous link) in case we need it later.
+    next = lol;
+  }
+
+#ifdef VERIFY_LOL
+  if (FLAG_verify_lol) {
+    Verify();
+  }
+#endif
+}
+
+
+#ifdef VERIFY_LOL
+void LiveObjectList::Verify(bool match_heap_exactly) {
+  OS::Print("Verifying the LiveObjectList database:\n");
+
+  LiveObjectList* lol = last();
+  if (lol == NULL) {
+    OS::Print("  No lol database to verify\n");
+    return;
+  }
+
+  OS::Print("  Preparing the lol database ...\n");
+  int total_count = lol->TotalObjCount();
+
+  Element* elements = NewArray<Element>(total_count);
+  int count = 0;
+
+  // Copy all the object elements into a consecutive array.
+  OS::Print("  Copying the lol database ...\n");
+  while (lol != NULL) {
+    memcpy(&elements[count], lol->elements_, lol->obj_count_ * sizeof(Element));
+    count += lol->obj_count_;
+    lol = lol->prev_;
+  }
+  qsort(elements, total_count, sizeof(Element),
+        reinterpret_cast<RawComparer>(CompareElement));
+
+  ASSERT(count == total_count);
+
+  // Iterate over all objects in the heap and check for:
+  // 1. object in LOL but not in heap i.e. error.
+  // 2. object in heap but not in LOL (possibly not an error).  Usually
+  //    just means that we don't have the a capture of the latest heap.
+  //    That is unless we did this verify immediately after a capture,
+  //    and specified match_heap_exactly = true.
+
+  int number_of_heap_objects = 0;
+  int number_of_matches = 0;
+  int number_not_in_heap = total_count;
+  int number_not_in_lol = 0;
+
+  OS::Print("  Start verify ...\n");
+  OS::Print("  Verifying ...");
+  Flush();
+  HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
+  HeapObject* heap_obj = NULL;
+  while ((heap_obj = iterator.next()) != NULL) {
+    number_of_heap_objects++;
+
+    // Check if the heap_obj is in the lol.
+    Element key;
+    key.obj_ = heap_obj;
+
+    Element* result = reinterpret_cast<Element*>(
+        bsearch(&key, elements, total_count, sizeof(Element),
+                reinterpret_cast<RawComparer>(CompareElement)));
+
+    if (result != NULL) {
+      number_of_matches++;
+      number_not_in_heap--;
+      // Mark it as found by changing it into a SMI (mask off low bit).
+      // Note: we cannot use HeapObject::cast() here because it asserts that
+      // the HeapObject bit is set on the address, but we're unsetting it on
+      // purpose here for our marking.
+      result->obj_ = reinterpret_cast<HeapObject*>(heap_obj->address());
+
+    } else {
+      number_not_in_lol++;
+      if (match_heap_exactly) {
+        OS::Print("heap object %p NOT in lol database\n", heap_obj);
+      }
+    }
+    // Show some sign of life.
+    if (number_of_heap_objects % 1000 == 0) {
+      OS::Print(".");
+      fflush(stdout);
+    }
+  }
+  OS::Print("\n");
+
+  // Reporting lol objects not found in the heap.
+  if (number_not_in_heap) {
+    int found = 0;
+    for (int i = 0; (i < total_count) && (found < number_not_in_heap); i++) {
+      Element& element = elements[i];
+      if (element.obj_->IsHeapObject()) {
+        OS::Print("lol database object [%d of %d] %p NOT in heap\n",
+                  i, total_count, element.obj_);
+        found++;
+      }
+    }
+  }
+
+  DeleteArray<Element>(elements);
+
+  OS::Print("number of objects in lol database %d\n", total_count);
+  OS::Print("number of heap objects .......... %d\n", number_of_heap_objects);
+  OS::Print("number of matches ............... %d\n", number_of_matches);
+  OS::Print("number NOT in heap .............. %d\n", number_not_in_heap);
+  OS::Print("number NOT in lol database ...... %d\n", number_not_in_lol);
+
+  if (number_of_matches != total_count) {
+    OS::Print("  *** ERROR: "
+              "NOT all lol database objects match heap objects.\n");
+  }
+  if (number_not_in_heap != 0) {
+    OS::Print("  *** ERROR: %d lol database objects not found in heap.\n",
+              number_not_in_heap);
+  }
+  if (match_heap_exactly) {
+    if (!(number_not_in_lol == 0)) {
+      OS::Print("  *** ERROR: %d heap objects NOT found in lol database.\n",
+                number_not_in_lol);
+    }
+  }
+
+  ASSERT(number_of_matches == total_count);
+  ASSERT(number_not_in_heap == 0);
+  ASSERT(number_not_in_lol == (number_of_heap_objects - total_count));
+  if (match_heap_exactly) {
+    ASSERT(total_count == number_of_heap_objects);
+    ASSERT(number_not_in_lol == 0);
+  }
+
+  OS::Print("  Verify the lol database is sorted ...\n");
+  lol = last();
+  while (lol != NULL) {
+    Element* elements = lol->elements_;
+    for (int i = 0; i < lol->obj_count_ - 1; i++) {
+      if (elements[i].obj_ >= elements[i+1].obj_) {
+        OS::Print("  *** ERROR: lol %p obj[%d] %p > obj[%d] %p\n",
+                  lol, i, elements[i].obj_, i+1, elements[i+1].obj_);
+      }
+    }
+    lol = lol->prev_;
+  }
+
+  OS::Print("  DONE verifying.\n\n\n");
+}
+
+
+void LiveObjectList::VerifyNotInFromSpace() {
+  OS::Print("VerifyNotInFromSpace() ...\n");
+  LolIterator it(NULL, last());
+  int i = 0;
+  for (it.Init(); !it.Done(); it.Next()) {
+    HeapObject* heap_obj = it.Obj();
+    if (Heap::InFromSpace(heap_obj)) {
+      OS::Print(" ERROR: VerifyNotInFromSpace: [%d] obj %p in From space %p\n",
+                i++, heap_obj, Heap::new_space()->FromSpaceLow());
+    }
+  }
+}
+#endif  // VERIFY_LOL
+
 
 } }  // namespace v8::internal
 
diff --git a/src/liveobjectlist.h b/src/liveobjectlist.h
index 11f5c45..423f8f0 100644
--- a/src/liveobjectlist.h
+++ b/src/liveobjectlist.h
@@ -40,54 +40,225 @@
 
 #ifdef LIVE_OBJECT_LIST
 
+#ifdef DEBUG
+// The following symbol when defined enables thorough verification of lol data.
+// FLAG_verify_lol will also need to set to true to enable the verification.
+#define VERIFY_LOL
+#endif
 
-// Temporary stubbed out LiveObjectList implementation.
+
+typedef int LiveObjectType;
+class LolFilter;
+class LiveObjectSummary;
+class DumpWriter;
+class SummaryWriter;
+
+
+// The LiveObjectList is both a mechanism for tracking a live capture of
+// objects in the JS heap, as well as is the data structure which represents
+// each of those captures.  Unlike a snapshot, the lol is live.  For example,
+// if an object in a captured lol dies and is collected by the GC, the lol
+// will reflect that the object is no longer available.  The term
+// LiveObjectList (and lol) is used to describe both the mechanism and the
+// data structure depending on context of use.
+//
+// In captured lols, objects are tracked using their address and an object id.
+// The object id is unique.  Once assigned to an object, the object id can never
+// be assigned to another object.  That is unless all captured lols are deleted
+// which allows the user to start over with a fresh set of lols and object ids.
+// The uniqueness of the object ids allows the user to track specific objects
+// and inspect its longevity while debugging JS code in execution.
+//
+// The lol comes with utility functions to capture, dump, summarize, and diff
+// captured lols amongst other functionality.  These functionality are
+// accessible via the v8 debugger interface.
 class LiveObjectList {
  public:
-  inline static void GCEpilogue() {}
-  inline static void GCPrologue() {}
-  inline static void IterateElements(ObjectVisitor* v) {}
-  inline static void ProcessNonLive(HeapObject *obj) {}
-  inline static void UpdateReferencesForScavengeGC() {}
+  inline static void GCEpilogue();
+  inline static void GCPrologue();
+  inline static void IterateElements(ObjectVisitor* v);
+  inline static void ProcessNonLive(HeapObject *obj);
+  inline static void UpdateReferencesForScavengeGC();
 
-  static MaybeObject* Capture() { return Heap::undefined_value(); }
-  static bool Delete(int id) { return false; }
+  // Note: LOLs can be listed by calling Dump(0, <lol id>), and 2 LOLs can be
+  // compared/diff'ed using Dump(<lol id1>, <lol id2>, ...).  This will yield
+  // a verbose dump of all the objects in the resultant lists.
+  //   Similarly, a summarized result of a LOL listing or a diff can be
+  // attained using the Summarize(0, <lol id>) and Summarize(<lol id1,
+  // <lol id2>, ...) respectively.
+
+  static MaybeObject* Capture();
+  static bool Delete(int id);
   static MaybeObject* Dump(int id1,
                            int id2,
                            int start_idx,
                            int dump_limit,
-                           Handle<JSObject> filter_obj) {
-    return Heap::undefined_value();
-  }
-  static MaybeObject* Info(int start_idx, int dump_limit) {
-    return Heap::undefined_value();
-  }
-  static MaybeObject* Summarize(int id1,
-                                int id2,
-                                Handle<JSObject> filter_obj) {
-    return Heap::undefined_value();
-  }
+                           Handle<JSObject> filter_obj);
+  static MaybeObject* Info(int start_idx, int dump_limit);
+  static MaybeObject* Summarize(int id1, int id2, Handle<JSObject> filter_obj);
 
-  static void Reset() {}
-  static Object* GetObj(int obj_id) { return Heap::undefined_value(); }
-  static Object* GetObjId(Handle<String> address) {
-    return Heap::undefined_value();
-  }
+  static void Reset();
+  static Object* GetObj(int obj_id);
+  static int GetObjId(Object* obj);
+  static Object* GetObjId(Handle<String> address);
   static MaybeObject* GetObjRetainers(int obj_id,
                                       Handle<JSObject> instance_filter,
                                       bool verbose,
                                       int start,
                                       int count,
-                                      Handle<JSObject> filter_obj) {
-    return Heap::undefined_value();
-  }
+                                      Handle<JSObject> filter_obj);
 
   static Object* GetPath(int obj_id1,
                          int obj_id2,
-                         Handle<JSObject> instance_filter) {
-    return Heap::undefined_value();
+                         Handle<JSObject> instance_filter);
+  static Object* PrintObj(int obj_id);
+
+ private:
+
+  struct Element {
+    int id_;
+    HeapObject* obj_;
+  };
+
+  explicit LiveObjectList(LiveObjectList* prev, int capacity);
+  ~LiveObjectList();
+
+  static void GCEpiloguePrivate();
+  static void IterateElementsPrivate(ObjectVisitor* v);
+
+  static void DoProcessNonLive(HeapObject *obj);
+
+  static int CompareElement(const Element* a, const Element* b);
+
+  static Object* GetPathPrivate(HeapObject* obj1, HeapObject* obj2);
+
+  static int GetRetainers(Handle<HeapObject> target,
+                          Handle<JSObject> instance_filter,
+                          Handle<FixedArray> retainers_arr,
+                          int start,
+                          int dump_limit,
+                          int* total_count,
+                          LolFilter* filter,
+                          LiveObjectSummary *summary,
+                          JSFunction* arguments_function,
+                          Handle<Object> error);
+
+  static MaybeObject* DumpPrivate(DumpWriter* writer,
+                                  int start,
+                                  int dump_limit,
+                                  LolFilter* filter);
+  static MaybeObject* SummarizePrivate(SummaryWriter* writer,
+                                       LolFilter* filter,
+                                       bool is_tracking_roots);
+
+  static bool NeedLOLProcessing() { return (last() != NULL); }
+  static void NullifyNonLivePointer(HeapObject **p) {
+    // Mask out the low bit that marks this as a heap object.  We'll use this
+    // cleared bit as an indicator that this pointer needs to be collected.
+    //
+    // Meanwhile, we still preserve its approximate value so that we don't
+    // have to resort the elements list all the time.
+    //
+    // Note: Doing so also makes this HeapObject* look like an SMI.  Hence,
+    // GC pointer updater will ignore it when it gets scanned.
+    *p = reinterpret_cast<HeapObject*>((*p)->address());
   }
-  static Object* PrintObj(int obj_id) { return Heap::undefined_value(); }
+
+  LiveObjectList* prev() { return prev_; }
+  LiveObjectList* next() { return next_; }
+  int id() { return id_; }
+
+  static int list_count() { return list_count_; }
+  static LiveObjectList* last() { return last_; }
+
+  inline static LiveObjectList* FindLolForId(int id, LiveObjectList* start_lol);
+  int TotalObjCount() { return GetTotalObjCountAndSize(NULL); }
+  int GetTotalObjCountAndSize(int* size_p);
+
+  bool Add(HeapObject* obj);
+  Element* Find(HeapObject* obj);
+  static void NullifyMostRecent(HeapObject* obj);
+  void Sort();
+  static void SortAll();
+
+  static void PurgeDuplicates();  // Only to be called by GCEpilogue.
+
+#ifdef VERIFY_LOL
+  static void Verify(bool match_heap_exactly = false);
+  static void VerifyNotInFromSpace();
+#endif
+
+  // Iterates the elements in every lol and returns the one that matches the
+  // specified key.  If no matching element is found, then it returns NULL.
+  template <typename T>
+  inline static LiveObjectList::Element*
+      FindElementFor(T (*GetValue)(LiveObjectList::Element*), T key);
+
+  inline static int GetElementId(Element* element);
+  inline static HeapObject* GetElementObj(Element* element);
+
+  // Instance fields.
+  LiveObjectList* prev_;
+  LiveObjectList* next_;
+  int id_;
+  int capacity_;
+  int obj_count_;
+  Element *elements_;
+
+  // Statics for managing all the lists.
+  static uint32_t next_element_id_;
+  static int list_count_;
+  static int last_id_;
+  static LiveObjectList* first_;
+  static LiveObjectList* last_;
+
+  friend class LolIterator;
+  friend class LolForwardIterator;
+  friend class LolDumpWriter;
+  friend class RetainersDumpWriter;
+  friend class RetainersSummaryWriter;
+  friend class UpdateLiveObjectListVisitor;
+};
+
+
+// Helper class for updating the LiveObjectList HeapObject pointers.
+class UpdateLiveObjectListVisitor: public ObjectVisitor {
+ public:
+
+  void VisitPointer(Object** p) { UpdatePointer(p); }
+
+  void VisitPointers(Object** start, Object** end) {
+    // Copy all HeapObject pointers in [start, end).
+    for (Object** p = start; p < end; p++) UpdatePointer(p);
+  }
+
+ private:
+  // Based on Heap::ScavengeObject() but only does forwarding of pointers
+  // to live new space objects, and not actually keep them alive.
+  void UpdatePointer(Object** p) {
+    Object* object = *p;
+    if (!Heap::InNewSpace(object)) return;
+
+    HeapObject* heap_obj = HeapObject::cast(object);
+    ASSERT(Heap::InFromSpace(heap_obj));
+
+    // We use the first word (where the map pointer usually is) of a heap
+    // object to record the forwarding pointer.  A forwarding pointer can
+    // point to an old space, the code space, or the to space of the new
+    // generation.
+    MapWord first_word = heap_obj->map_word();
+
+    // If the first word is a forwarding address, the object has already been
+    // copied.
+    if (first_word.IsForwardingAddress()) {
+      *p = first_word.ToForwardingAddress();
+      return;
+
+    // Else, it's a dead object.
+    } else {
+      LiveObjectList::NullifyNonLivePointer(reinterpret_cast<HeapObject**>(p));
+    }
+  }
 };
 
 
@@ -96,11 +267,50 @@
 
 class LiveObjectList {
  public:
-  static void GCEpilogue() {}
-  static void GCPrologue() {}
-  static void IterateElements(ObjectVisitor* v) {}
-  static void ProcessNonLive(HeapObject *obj) {}
-  static void UpdateReferencesForScavengeGC() {}
+  inline static void GCEpilogue() {}
+  inline static void GCPrologue() {}
+  inline static void IterateElements(ObjectVisitor* v) {}
+  inline static void ProcessNonLive(HeapObject* obj) {}
+  inline static void UpdateReferencesForScavengeGC() {}
+
+  inline static MaybeObject* Capture() { return Heap::undefined_value(); }
+  inline static bool Delete(int id) { return false; }
+  inline static MaybeObject* Dump(int id1,
+                                  int id2,
+                                  int start_idx,
+                                  int dump_limit,
+                                  Handle<JSObject> filter_obj) {
+    return Heap::undefined_value();
+  }
+  inline static MaybeObject* Info(int start_idx, int dump_limit) {
+    return Heap::undefined_value();
+  }
+  inline static MaybeObject* Summarize(int id1,
+                                       int id2,
+                                       Handle<JSObject> filter_obj) {
+    return Heap::undefined_value();
+  }
+
+  inline static void Reset() {}
+  inline static Object* GetObj(int obj_id) { return Heap::undefined_value(); }
+  inline static Object* GetObjId(Handle<String> address) {
+    return Heap::undefined_value();
+  }
+  inline static MaybeObject* GetObjRetainers(int obj_id,
+                                             Handle<JSObject> instance_filter,
+                                             bool verbose,
+                                             int start,
+                                             int count,
+                                             Handle<JSObject> filter_obj) {
+    return Heap::undefined_value();
+  }
+
+  inline static Object* GetPath(int obj_id1,
+                                int obj_id2,
+                                Handle<JSObject> instance_filter) {
+    return Heap::undefined_value();
+  }
+  inline static Object* PrintObj(int obj_id) { return Heap::undefined_value(); }
 };
 
 
diff --git a/src/log-utils.cc b/src/log-utils.cc
index c7b7567..9a498ec 100644
--- a/src/log-utils.cc
+++ b/src/log-utils.cc
@@ -300,6 +300,8 @@
       Append("\\,");
     } else if (c == '\\') {
       Append("\\\\");
+    } else if (c == '\"') {
+      Append("\"\"");
     } else {
       Append("%lc", c);
     }
diff --git a/src/log.cc b/src/log.cc
index 6eb3c9b..16aeadb 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -147,7 +147,7 @@
 // StackTracer implementation
 //
 void StackTracer::Trace(TickSample* sample) {
-  sample->function = NULL;
+  sample->tos = NULL;
   sample->frames_count = 0;
 
   // Avoid collecting traces while doing GC.
@@ -159,15 +159,9 @@
     return;
   }
 
-  const Address function_address =
-      sample->fp + JavaScriptFrameConstants::kFunctionOffset;
-  if (SafeStackFrameIterator::IsWithinBounds(sample->sp, js_entry_sp,
-                                             function_address)) {
-    Object* object = Memory::Object_at(function_address);
-    if (object->IsHeapObject()) {
-      sample->function = HeapObject::cast(object)->address();
-    }
-  }
+  // Sample potential return address value for frameless invocation of
+  // stubs (we'll figure out later, if this value makes sense).
+  sample->tos = Memory::Address_at(sample->sp);
 
   int i = 0;
   const Address callback = Top::external_callback();
@@ -181,10 +175,7 @@
   SafeStackTraceFrameIterator it(sample->fp, sample->sp,
                                  sample->sp, js_entry_sp);
   while (!it.done() && i < TickSample::kMaxFramesCount) {
-    Object* object = it.frame()->function_slot_object();
-    if (object->IsHeapObject()) {
-      sample->stack[i++] = HeapObject::cast(object)->address();
-    }
+    sample->stack[i++] = it.frame()->pc();
     it.Advance();
   }
   sample->frames_count = i;
@@ -710,17 +701,6 @@
 }
 
 
-#ifdef ENABLE_LOGGING_AND_PROFILING
-static const char* ComputeMarker(Code* code) {
-  switch (code->kind()) {
-    case Code::FUNCTION: return code->optimizable() ? "~" : "";
-    case Code::OPTIMIZED_FUNCTION: return "*";
-    default: return "";
-  }
-}
-#endif
-
-
 void Logger::CodeCreateEvent(LogEventsAndTags tag,
                              Code* code,
                              const char* comment) {
@@ -731,7 +711,7 @@
              kLogEventsNames[CODE_CREATION_EVENT],
              kLogEventsNames[tag]);
   msg.AppendAddress(code->address());
-  msg.Append(",%d,\"%s", code->ExecutableSize(), ComputeMarker(code));
+  msg.Append(",%d,\"", code->ExecutableSize());
   for (const char* p = comment; *p != '\0'; p++) {
     if (*p == '"') {
       msg.Append('\\');
@@ -746,9 +726,40 @@
 }
 
 
-void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, String* name) {
+void Logger::CodeCreateEvent(LogEventsAndTags tag,
+                             Code* code,
+                             String* name) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (name != NULL) {
+    SmartPointer<char> str =
+        name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+    CodeCreateEvent(tag, code, *str);
+  } else {
+    CodeCreateEvent(tag, code, "");
+  }
+#endif
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+// ComputeMarker must only be used when SharedFunctionInfo is known.
+static const char* ComputeMarker(Code* code) {
+  switch (code->kind()) {
+    case Code::FUNCTION: return code->optimizable() ? "~" : "";
+    case Code::OPTIMIZED_FUNCTION: return "*";
+    default: return "";
+  }
+}
+#endif
+
+
+void Logger::CodeCreateEvent(LogEventsAndTags tag,
+                             Code* code,
+                             SharedFunctionInfo* shared,
+                             String* name) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
   if (!Log::IsEnabled() || !FLAG_log_code) return;
+  if (code == Builtins::builtin(Builtins::LazyCompile)) return;
   LogMessageBuilder msg;
   SmartPointer<char> str =
       name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
@@ -756,7 +767,9 @@
              kLogEventsNames[CODE_CREATION_EVENT],
              kLogEventsNames[tag]);
   msg.AppendAddress(code->address());
-  msg.Append(",%d,\"%s%s\"", code->ExecutableSize(), ComputeMarker(code), *str);
+  msg.Append(",%d,\"%s\",", code->ExecutableSize(), *str);
+  msg.AppendAddress(shared->address());
+  msg.Append(",%s", ComputeMarker(code));
   LowLevelCodeCreateEvent(code, &msg);
   msg.Append('\n');
   msg.WriteToLogFile();
@@ -764,26 +777,31 @@
 }
 
 
+// Although, it is possible to extract source and line from
+// the SharedFunctionInfo object, we left it to caller
+// to leave logging functions free from heap allocations.
 void Logger::CodeCreateEvent(LogEventsAndTags tag,
-                             Code* code, String* name,
+                             Code* code,
+                             SharedFunctionInfo* shared,
                              String* source, int line) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
   if (!Log::IsEnabled() || !FLAG_log_code) return;
   LogMessageBuilder msg;
-  SmartPointer<char> str =
-      name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+  SmartPointer<char> name =
+      shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
   SmartPointer<char> sourcestr =
       source->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
   msg.Append("%s,%s,",
              kLogEventsNames[CODE_CREATION_EVENT],
              kLogEventsNames[tag]);
   msg.AppendAddress(code->address());
-  msg.Append(",%d,\"%s%s %s:%d\"",
+  msg.Append(",%d,\"%s %s:%d\",",
              code->ExecutableSize(),
-             ComputeMarker(code),
-             *str,
+             *name,
              *sourcestr,
              line);
+  msg.AppendAddress(shared->address());
+  msg.Append(",%s", ComputeMarker(code));
   LowLevelCodeCreateEvent(code, &msg);
   msg.Append('\n');
   msg.WriteToLogFile();
@@ -863,42 +881,9 @@
 }
 
 
-void Logger::FunctionCreateEvent(JSFunction* function) {
+void Logger::SFIMoveEvent(Address from, Address to) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
-  // This function can be called from GC iterators (during Scavenge,
-  // MC, and MS), so marking bits can be set on objects. That's
-  // why unchecked accessors are used here.
-  if (!Log::IsEnabled() || !FLAG_log_code) return;
-  LogMessageBuilder msg;
-  msg.Append("%s,", kLogEventsNames[FUNCTION_CREATION_EVENT]);
-  msg.AppendAddress(function->address());
-  msg.Append(',');
-  msg.AppendAddress(function->unchecked_code()->address());
-  msg.Append('\n');
-  msg.WriteToLogFile();
-#endif
-}
-
-
-void Logger::FunctionCreateEventFromMove(JSFunction* function) {
-#ifdef ENABLE_LOGGING_AND_PROFILING
-  if (function->unchecked_code() != Builtins::builtin(Builtins::LazyCompile)) {
-    FunctionCreateEvent(function);
-  }
-#endif
-}
-
-
-void Logger::FunctionMoveEvent(Address from, Address to) {
-#ifdef ENABLE_LOGGING_AND_PROFILING
-  MoveEventInternal(FUNCTION_MOVE_EVENT, from, to);
-#endif
-}
-
-
-void Logger::FunctionDeleteEvent(Address from) {
-#ifdef ENABLE_LOGGING_AND_PROFILING
-  DeleteEventInternal(FUNCTION_DELETE_EVENT, from);
+  MoveEventInternal(SFI_MOVE_EVENT, from, to);
 #endif
 }
 
@@ -1118,7 +1103,7 @@
   msg.Append(',');
   msg.AppendAddress(sample->sp);
   msg.Append(',');
-  msg.AppendAddress(sample->function);
+  msg.AppendAddress(sample->tos);
   msg.Append(",%d", static_cast<int>(sample->state));
   if (overflow) {
     msg.Append(",overflow");
@@ -1187,7 +1172,6 @@
         LOG(UncheckedStringEvent("profiler", "resume"));
         FLAG_log_code = true;
         LogCompiledFunctions();
-        LogFunctionObjects();
         LogAccessorCallbacks();
         if (!FLAG_sliding_state_window && !ticker_->IsActive()) {
           ticker_->Start();
@@ -1388,10 +1372,9 @@
   // During iteration, there can be heap allocation due to
   // GetScriptLineNumber call.
   for (int i = 0; i < compiled_funcs_count; ++i) {
+    if (*code_objects[i] == Builtins::builtin(Builtins::LazyCompile)) continue;
     Handle<SharedFunctionInfo> shared = sfis[i];
-    Handle<String> name(String::cast(shared->name()));
-    Handle<String> func_name(name->length() > 0 ?
-                             *name : shared->inferred_name());
+    Handle<String> func_name(shared->DebugName());
     if (shared->script()->IsScript()) {
       Handle<Script> script(Script::cast(shared->script()));
       if (script->name()->IsString()) {
@@ -1400,18 +1383,18 @@
         if (line_num > 0) {
           PROFILE(CodeCreateEvent(
               Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
-              *code_objects[i], *func_name,
+              *code_objects[i], *shared,
               *script_name, line_num + 1));
         } else {
           // Can't distinguish eval and script here, so always use Script.
           PROFILE(CodeCreateEvent(
               Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
-              *code_objects[i], *script_name));
+              *code_objects[i], *shared, *script_name));
         }
       } else {
         PROFILE(CodeCreateEvent(
             Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
-            *code_objects[i], *func_name));
+            *code_objects[i], *shared, *func_name));
       }
     } else if (shared->IsApiFunction()) {
       // API function.
@@ -1425,24 +1408,12 @@
       }
     } else {
       PROFILE(CodeCreateEvent(
-          Logger::LAZY_COMPILE_TAG, *code_objects[i], *func_name));
+          Logger::LAZY_COMPILE_TAG, *code_objects[i], *shared, *func_name));
     }
   }
 }
 
 
-void Logger::LogFunctionObjects() {
-  AssertNoAllocation no_alloc;
-  HeapIterator iterator;
-  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
-    if (!obj->IsJSFunction()) continue;
-    JSFunction* jsf = JSFunction::cast(obj);
-    if (!jsf->is_compiled()) continue;
-    PROFILE(FunctionCreateEvent(jsf));
-  }
-}
-
-
 void Logger::LogAccessorCallbacks() {
   AssertNoAllocation no_alloc;
   HeapIterator iterator;
diff --git a/src/log.h b/src/log.h
index 771709c..a808cd1 100644
--- a/src/log.h
+++ b/src/log.h
@@ -91,9 +91,7 @@
   V(CODE_MOVE_EVENT,                "code-move")                \
   V(CODE_DELETE_EVENT,              "code-delete")              \
   V(CODE_MOVING_GC,                 "code-moving-gc")           \
-  V(FUNCTION_CREATION_EVENT,        "function-creation")        \
-  V(FUNCTION_MOVE_EVENT,            "function-move")            \
-  V(FUNCTION_DELETE_EVENT,          "function-delete")          \
+  V(SFI_MOVE_EVENT,                 "sfi-move")                 \
   V(SNAPSHOT_POSITION_EVENT,        "snapshot-pos")             \
   V(TICK_EVENT,                     "tick")                     \
   V(REPEAT_META_EVENT,              "repeat")                   \
@@ -205,8 +203,15 @@
   // Emits a code create event.
   static void CodeCreateEvent(LogEventsAndTags tag,
                               Code* code, const char* source);
-  static void CodeCreateEvent(LogEventsAndTags tag, Code* code, String* name);
-  static void CodeCreateEvent(LogEventsAndTags tag, Code* code, String* name,
+  static void CodeCreateEvent(LogEventsAndTags tag,
+                              Code* code, String* name);
+  static void CodeCreateEvent(LogEventsAndTags tag,
+                              Code* code,
+                              SharedFunctionInfo* shared,
+                              String* name);
+  static void CodeCreateEvent(LogEventsAndTags tag,
+                              Code* code,
+                              SharedFunctionInfo* shared,
                               String* source, int line);
   static void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count);
   static void CodeMovingGCEvent();
@@ -216,13 +221,8 @@
   static void CodeMoveEvent(Address from, Address to);
   // Emits a code delete event.
   static void CodeDeleteEvent(Address from);
-  // Emits a function object create event.
-  static void FunctionCreateEvent(JSFunction* function);
-  static void FunctionCreateEventFromMove(JSFunction* function);
-  // Emits a function move event.
-  static void FunctionMoveEvent(Address from, Address to);
-  // Emits a function delete event.
-  static void FunctionDeleteEvent(Address from);
+
+  static void SFIMoveEvent(Address from, Address to);
 
   static void SnapshotPositionEvent(Address addr, int pos);
 
@@ -273,8 +273,6 @@
 
   // Logs all compiled functions found in the heap.
   static void LogCompiledFunctions();
-  // Logs all compiled JSFunction objects found in the heap.
-  static void LogFunctionObjects();
   // Logs all accessor callbacks found in the heap.
   static void LogAccessorCallbacks();
   // Used for logging stubs found in the snapshot.
diff --git a/src/macro-assembler.h b/src/macro-assembler.h
index d261f57..30838bd 100644
--- a/src/macro-assembler.h
+++ b/src/macro-assembler.h
@@ -50,6 +50,13 @@
 };
 
 
+// Types of uncatchable exceptions.
+enum UncatchableExceptionType {
+  OUT_OF_MEMORY,
+  TERMINATION
+};
+
+
 // Invalid depth in prototype chain.
 const int kInvalidProtoDepth = -1;
 
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 5c649d1..a4c782c 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -1353,6 +1353,9 @@
 
   // Flush code from collected candidates.
   FlushCode::ProcessCandidates();
+
+  // Clean up dead objects from the runtime profiler.
+  RuntimeProfiler::RemoveDeadSamples();
 }
 
 
@@ -1937,6 +1940,9 @@
   // All pointers were updated. Update auxiliary allocation info.
   Heap::IncrementYoungSurvivorsCounter(survivors_size);
   space->set_age_mark(space->top());
+
+  // Update JSFunction pointers from the runtime profiler.
+  RuntimeProfiler::UpdateSamplesAfterScavenge();
 }
 
 
@@ -2535,6 +2541,7 @@
   state_ = UPDATE_POINTERS;
 #endif
   UpdatingVisitor updating_visitor;
+  RuntimeProfiler::UpdateSamplesAfterCompact(&updating_visitor);
   Heap::IterateRoots(&updating_visitor, VISIT_ONLY_STRONG);
   GlobalHandles::IterateWeakRoots(&updating_visitor);
 
@@ -2819,9 +2826,8 @@
   ASSERT(!HeapObject::FromAddress(new_addr)->IsCode());
 
   HeapObject* copied_to = HeapObject::FromAddress(new_addr);
-  if (copied_to->IsJSFunction()) {
-    PROFILE(FunctionMoveEvent(old_addr, new_addr));
-    PROFILE(FunctionCreateEventFromMove(JSFunction::cast(copied_to)));
+  if (copied_to->IsSharedFunctionInfo()) {
+    PROFILE(SFIMoveEvent(old_addr, new_addr));
   }
   HEAP_PROFILE(ObjectMoveEvent(old_addr, new_addr));
 
@@ -2912,9 +2918,8 @@
 #endif
 
   HeapObject* copied_to = HeapObject::FromAddress(new_addr);
-  if (copied_to->IsJSFunction()) {
-    PROFILE(FunctionMoveEvent(old_addr, new_addr));
-    PROFILE(FunctionCreateEventFromMove(JSFunction::cast(copied_to)));
+  if (copied_to->IsSharedFunctionInfo()) {
+    PROFILE(SFIMoveEvent(old_addr, new_addr));
   }
   HEAP_PROFILE(ObjectMoveEvent(old_addr, new_addr));
 
@@ -2931,8 +2936,6 @@
 #ifdef ENABLE_LOGGING_AND_PROFILING
   if (obj->IsCode()) {
     PROFILE(CodeDeleteEvent(obj->address()));
-  } else if (obj->IsJSFunction()) {
-    PROFILE(FunctionDeleteEvent(obj->address()));
   }
 #endif
 }
diff --git a/src/messages.js b/src/messages.js
index 1e41b17..2c94912 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -224,6 +224,12 @@
       strict_lhs_postfix:           ["Postfix increment/decrement may not have eval or arguments operand in strict mode"],
       strict_lhs_prefix:            ["Prefix increment/decrement may not have eval or arguments operand in strict mode"],
       strict_reserved_word:         ["Use of future reserved word in strict mode"],
+      strict_delete:                ["Delete of an unqualified identifier in strict mode."],
+      strict_delete_property:       ["Cannot delete property '", "%0", "' of ", "%1"],
+      strict_const:                 ["Use of const in strict mode."],
+      strict_function:              ["In strict mode code, functions can only be declared at top level or immediately within another function." ],
+      strict_read_only_property:    ["Cannot assign to read only property '", "%0", "' of ", "%1"],
+      strict_cannot_assign:         ["Cannot assign to read only '", "%0", "' in strict mode"],
     };
   }
   var message_type = %MessageGetType(message);
@@ -1057,8 +1063,8 @@
   }
 }
 
-%FunctionSetName(errorToString, 'toString');
-%SetProperty($Error.prototype, 'toString', errorToString, DONT_ENUM);
+
+InstallFunctions($Error.prototype, DONT_ENUM, ['toString', errorToString]);
 
 // Boilerplate for exceptions for stack overflows. Used from
 // Top::StackOverflow().
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 24887a0..dedb199 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -769,6 +769,10 @@
 
 
 MaybeObject* Object::GetElement(uint32_t index) {
+  // GetElement can trigger a getter which can cause allocation.
+  // This was not always the case. This ASSERT is here to catch
+  // leftover incorrect uses.
+  ASSERT(Heap::IsAllocationAllowed());
   return GetElementWithReceiver(this, index);
 }
 
@@ -2615,7 +2619,8 @@
   ASSERT(extra_ic_state == kNoExtraICState ||
          (kind == CALL_IC && (ic_state == MONOMORPHIC ||
                               ic_state == MONOMORPHIC_PROTOTYPE_FAILURE)) ||
-         (kind == STORE_IC));
+         (kind == STORE_IC) ||
+         (kind == KEYED_STORE_IC));
   // Compute the bit mask.
   int bits = kind << kFlagsKindShift;
   if (in_loop) bits |= kFlagsICInLoopMask;
@@ -3737,7 +3742,8 @@
   ASSERT(!IsJSGlobalProxy());
   return SetPropertyPostInterceptor(Heap::hidden_symbol(),
                                     hidden_obj,
-                                    DONT_ENUM);
+                                    DONT_ENUM,
+                                    kNonStrictMode);
 }
 
 
diff --git a/src/objects.cc b/src/objects.cc
index 5003b4f..4c00591 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -531,10 +531,25 @@
 
 
 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
-  // Non-JS objects do not have integer indexed properties.
-  if (!IsJSObject()) return Heap::undefined_value();
-  return JSObject::cast(this)->GetElementWithReceiver(JSObject::cast(receiver),
-                                                      index);
+  if (IsJSObject()) {
+    return JSObject::cast(this)->GetElementWithReceiver(receiver, index);
+  }
+
+  Object* holder = NULL;
+  Context* global_context = Top::context()->global_context();
+  if (IsString()) {
+    holder = global_context->string_function()->instance_prototype();
+  } else if (IsNumber()) {
+    holder = global_context->number_function()->instance_prototype();
+  } else if (IsBoolean()) {
+    holder = global_context->boolean_function()->instance_prototype();
+  } else {
+    // Undefined and null have no indexed properties.
+    ASSERT(IsUndefined() || IsNull());
+    return Heap::undefined_value();
+  }
+
+  return JSObject::cast(holder)->GetElementWithReceiver(receiver, index);
 }
 
 
@@ -1399,7 +1414,7 @@
   if (!map()->is_extensible()) {
     Handle<Object> args[1] = {Handle<String>(name)};
     return Top::Throw(*Factory::NewTypeError("object_not_extensible",
-                                               HandleVector(args, 1)));
+                                             HandleVector(args, 1)));
   }
   if (HasFastProperties()) {
     // Ensure the descriptor array does not get too big.
@@ -1429,14 +1444,15 @@
 MaybeObject* JSObject::SetPropertyPostInterceptor(
     String* name,
     Object* value,
-    PropertyAttributes attributes) {
+    PropertyAttributes attributes,
+    StrictModeFlag strict_mode) {
   // Check local property, ignore interceptor.
   LookupResult result;
   LocalLookupRealNamedProperty(name, &result);
   if (result.IsFound()) {
     // An existing property, a map transition or a null descriptor was
     // found.  Use set property to handle all these cases.
-    return SetProperty(&result, name, value, attributes);
+    return SetProperty(&result, name, value, attributes, strict_mode);
   }
   // Add a new real property.
   return AddProperty(name, value, attributes);
@@ -1561,7 +1577,8 @@
 MaybeObject* JSObject::SetPropertyWithInterceptor(
     String* name,
     Object* value,
-    PropertyAttributes attributes) {
+    PropertyAttributes attributes,
+    StrictModeFlag strict_mode) {
   HandleScope scope;
   Handle<JSObject> this_handle(this);
   Handle<String> name_handle(name);
@@ -1590,7 +1607,8 @@
   MaybeObject* raw_result =
       this_handle->SetPropertyPostInterceptor(*name_handle,
                                               *value_handle,
-                                              attributes);
+                                              attributes,
+                                              strict_mode);
   RETURN_IF_SCHEDULED_EXCEPTION();
   return raw_result;
 }
@@ -1598,10 +1616,11 @@
 
 MaybeObject* JSObject::SetProperty(String* name,
                                    Object* value,
-                                   PropertyAttributes attributes) {
+                                   PropertyAttributes attributes,
+                                   StrictModeFlag strict_mode) {
   LookupResult result;
   LocalLookup(name, &result);
-  return SetProperty(&result, name, value, attributes);
+  return SetProperty(&result, name, value, attributes, strict_mode);
 }
 
 
@@ -1881,7 +1900,8 @@
 MaybeObject* JSObject::SetProperty(LookupResult* result,
                                    String* name,
                                    Object* value,
-                                   PropertyAttributes attributes) {
+                                   PropertyAttributes attributes,
+                                   StrictModeFlag strict_mode) {
   // Make sure that the top context does not change when doing callbacks or
   // interceptor calls.
   AssertNoContextChange ncc;
@@ -1908,7 +1928,8 @@
     Object* proto = GetPrototype();
     if (proto->IsNull()) return value;
     ASSERT(proto->IsJSGlobalObject());
-    return JSObject::cast(proto)->SetProperty(result, name, value, attributes);
+    return JSObject::cast(proto)->SetProperty(
+        result, name, value, attributes, strict_mode);
   }
 
   if (!result->IsProperty() && !IsJSContextExtensionObject()) {
@@ -1927,7 +1948,18 @@
     // Neither properties nor transitions found.
     return AddProperty(name, value, attributes);
   }
-  if (result->IsReadOnly() && result->IsProperty()) return value;
+  if (result->IsReadOnly() && result->IsProperty()) {
+    if (strict_mode == kStrictMode) {
+      HandleScope scope;
+      Handle<String> key(name);
+      Handle<Object> holder(this);
+      Handle<Object> args[2] = { key, holder };
+      return Top::Throw(*Factory::NewTypeError("strict_read_only_property",
+                                                HandleVector(args, 2)));
+    } else {
+      return value;
+    }
+  }
   // This is a real property that is not read-only, or it is a
   // transition or null descriptor and there are no setters in the prototypes.
   switch (result->type()) {
@@ -1955,7 +1987,7 @@
                                      value,
                                      result->holder());
     case INTERCEPTOR:
-      return SetPropertyWithInterceptor(name, value, attributes);
+      return SetPropertyWithInterceptor(name, value, attributes, strict_mode);
     case CONSTANT_TRANSITION: {
       // If the same constant function is being added we can simply
       // transition to the target map.
@@ -2620,7 +2652,17 @@
       NumberDictionary* dictionary = element_dictionary();
       int entry = dictionary->FindEntry(index);
       if (entry != NumberDictionary::kNotFound) {
-        return dictionary->DeleteProperty(entry, mode);
+        Object* result = dictionary->DeleteProperty(entry, mode);
+        if (mode == STRICT_DELETION && result == Heap::false_value()) {
+          // In strict mode, deleting a non-configurable property throws
+          // exception. dictionary->DeleteProperty will return false_value()
+          // if a non-configurable property is being deleted.
+          HandleScope scope;
+          Handle<Object> i = Factory::NewNumberFromUint(index);
+          Handle<Object> args[2] = { i, Handle<Object>(this) };
+          return Top::Throw(*Factory::NewTypeError("strict_delete_property",
+                                                   HandleVector(args, 2)));
+        }
       }
       break;
     }
@@ -2659,6 +2701,13 @@
     if (!result.IsProperty()) return Heap::true_value();
     // Ignore attributes if forcing a deletion.
     if (result.IsDontDelete() && mode != FORCE_DELETION) {
+      if (mode == STRICT_DELETION) {
+        // Deleting a non-configurable property in strict mode.
+        HandleScope scope;
+        Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) };
+        return Top::Throw(*Factory::NewTypeError("strict_delete_property",
+                                                 HandleVector(args, 2)));
+      }
       return Heap::false_value();
     }
     // Check for interceptor.
@@ -2781,6 +2830,12 @@
 
 
 MaybeObject* JSObject::PreventExtensions() {
+  if (IsAccessCheckNeeded() &&
+      !Top::MayNamedAccess(this, Heap::undefined_value(), v8::ACCESS_KEYS)) {
+    Top::ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
+    return Heap::false_value();
+  }
+
   if (IsJSGlobalProxy()) {
     Object* proto = GetPrototype();
     if (proto->IsNull()) return this;
@@ -5438,9 +5493,11 @@
 
 bool JSFunction::IsInlineable() {
   if (IsBuiltin()) return false;
+  SharedFunctionInfo* shared_info = shared();
   // Check that the function has a script associated with it.
-  if (!shared()->script()->IsScript()) return false;
-  Code* code = shared()->code();
+  if (!shared_info->script()->IsScript()) return false;
+  if (shared_info->optimization_disabled()) return false;
+  Code* code = shared_info->code();
   if (code->kind() == Code::OPTIMIZED_FUNCTION) return true;
   // If we never ran this (unlikely) then lets try to optimize it.
   if (code->kind() != Code::FUNCTION) return true;
@@ -5494,6 +5551,10 @@
 
 
 Object* JSFunction::RemovePrototype() {
+  if (map() == context()->global_context()->function_without_prototype_map()) {
+    // Be idempotent.
+    return this;
+  }
   ASSERT(map() == context()->global_context()->function_map());
   set_map(context()->global_context()->function_without_prototype_map());
   set_prototype_or_initial_map(Heap::the_hole_value());
@@ -6247,7 +6308,8 @@
       }
       break;
     case STORE_IC:
-      if (extra == StoreIC::kStoreICStrict) {
+    case KEYED_STORE_IC:
+      if (extra == kStrictMode) {
         name = "STRICT";
       }
       break;
@@ -6463,13 +6525,6 @@
 }
 
 
-// Computes the new capacity when expanding the elements of a JSObject.
-static int NewElementsCapacity(int old_capacity) {
-  // (old_capacity + 50%) + 16
-  return old_capacity + (old_capacity >> 1) + 16;
-}
-
-
 static Failure* ArrayLengthRangeError() {
   HandleScope scope;
   return Top::Throw(*Factory::NewRangeError("invalid_array_length",
@@ -6628,7 +6683,6 @@
       break;
     }
     case PIXEL_ELEMENTS: {
-      // TODO(iposva): Add testcase.
       PixelArray* pixels = PixelArray::cast(elements());
       if (index < static_cast<uint32_t>(pixels->length())) {
         return true;
@@ -6642,7 +6696,6 @@
     case EXTERNAL_INT_ELEMENTS:
     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
     case EXTERNAL_FLOAT_ELEMENTS: {
-      // TODO(kbr): Add testcase.
       ExternalArray* array = ExternalArray::cast(elements());
       if (index < static_cast<uint32_t>(array->length())) {
         return true;
@@ -6846,6 +6899,7 @@
 
 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
                                                  Object* value,
+                                                 StrictModeFlag strict_mode,
                                                  bool check_prototype) {
   // Make sure that the top context does not change when doing
   // callbacks or interceptor calls.
@@ -6872,6 +6926,7 @@
   MaybeObject* raw_result =
       this_handle->SetElementWithoutInterceptor(index,
                                                 *value_handle,
+                                                strict_mode,
                                                 check_prototype);
   RETURN_IF_SCHEDULED_EXCEPTION();
   return raw_result;
@@ -6985,6 +7040,7 @@
 // elements.
 MaybeObject* JSObject::SetFastElement(uint32_t index,
                                       Object* value,
+                                      StrictModeFlag strict_mode,
                                       bool check_prototype) {
   ASSERT(HasFastElements());
 
@@ -7041,12 +7097,13 @@
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
   ASSERT(HasDictionaryElements());
-  return SetElement(index, value, check_prototype);
+  return SetElement(index, value, strict_mode, check_prototype);
 }
 
 
 MaybeObject* JSObject::SetElement(uint32_t index,
                                   Object* value,
+                                  StrictModeFlag strict_mode,
                                   bool check_prototype) {
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
@@ -7061,25 +7118,35 @@
     Object* proto = GetPrototype();
     if (proto->IsNull()) return value;
     ASSERT(proto->IsJSGlobalObject());
-    return JSObject::cast(proto)->SetElement(index, value, check_prototype);
+    return JSObject::cast(proto)->SetElement(index,
+                                             value,
+                                             strict_mode,
+                                             check_prototype);
   }
 
   // Check for lookup interceptor
   if (HasIndexedInterceptor()) {
-    return SetElementWithInterceptor(index, value, check_prototype);
+    return SetElementWithInterceptor(index,
+                                     value,
+                                     strict_mode,
+                                     check_prototype);
   }
 
-  return SetElementWithoutInterceptor(index, value, check_prototype);
+  return SetElementWithoutInterceptor(index,
+                                      value,
+                                      strict_mode,
+                                      check_prototype);
 }
 
 
 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
                                                     Object* value,
+                                                    StrictModeFlag strict_mode,
                                                     bool check_prototype) {
   switch (GetElementsKind()) {
     case FAST_ELEMENTS:
       // Fast case.
-      return SetFastElement(index, value, check_prototype);
+      return SetFastElement(index, value, strict_mode, check_prototype);
     case PIXEL_ELEMENTS: {
       PixelArray* pixels = PixelArray::cast(elements());
       return pixels->SetValue(index, value);
@@ -7128,13 +7195,23 @@
           return SetElementWithCallback(element, index, value, this);
         } else {
           dictionary->UpdateMaxNumberKey(index);
-          dictionary->ValueAtPut(entry, value);
+          // If put fails instrict mode, throw exception.
+          if (!dictionary->ValueAtPut(entry, value) &&
+              strict_mode == kStrictMode) {
+            Handle<Object> number(Factory::NewNumberFromUint(index));
+            Handle<Object> holder(this);
+            Handle<Object> args[2] = { number, holder };
+            return Top::Throw(
+                *Factory::NewTypeError("strict_read_only_property",
+                                       HandleVector(args, 2)));
+          }
         }
       } else {
         // Index not already used. Look for an accessor in the prototype chain.
         if (check_prototype) {
           bool found;
           MaybeObject* result =
+              // Strict mode not needed. No-setter case already handled.
               SetElementWithCallbackSetterInPrototypes(index, value, &found);
           if (found) return result;
         }
@@ -7220,7 +7297,7 @@
 }
 
 
-MaybeObject* JSObject::GetElementPostInterceptor(JSObject* receiver,
+MaybeObject* JSObject::GetElementPostInterceptor(Object* receiver,
                                                  uint32_t index) {
   // Get element works for both JSObject and JSArray since
   // JSArray::length cannot change.
@@ -7233,11 +7310,7 @@
       }
       break;
     }
-    case PIXEL_ELEMENTS: {
-      // TODO(iposva): Add testcase and implement.
-      UNIMPLEMENTED();
-      break;
-    }
+    case PIXEL_ELEMENTS:
     case EXTERNAL_BYTE_ELEMENTS:
     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
     case EXTERNAL_SHORT_ELEMENTS:
@@ -7245,8 +7318,10 @@
     case EXTERNAL_INT_ELEMENTS:
     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
     case EXTERNAL_FLOAT_ELEMENTS: {
-      // TODO(kbr): Add testcase and implement.
-      UNIMPLEMENTED();
+      MaybeObject* maybe_value = GetExternalElement(index);
+      Object* value;
+      if (!maybe_value->ToObject(&value)) return maybe_value;
+      if (!value->IsUndefined()) return value;
       break;
     }
     case DICTIONARY_ELEMENTS: {
@@ -7277,14 +7352,14 @@
 }
 
 
-MaybeObject* JSObject::GetElementWithInterceptor(JSObject* receiver,
+MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver,
                                                  uint32_t index) {
   // Make sure that the top context does not change when doing
   // callbacks or interceptor calls.
   AssertNoContextChange ncc;
   HandleScope scope;
   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
-  Handle<JSObject> this_handle(receiver);
+  Handle<Object> this_handle(receiver);
   Handle<JSObject> holder_handle(this);
 
   if (!interceptor->getter()->IsUndefined()) {
@@ -7310,7 +7385,7 @@
 }
 
 
-MaybeObject* JSObject::GetElementWithReceiver(JSObject* receiver,
+MaybeObject* JSObject::GetElementWithReceiver(Object* receiver,
                                               uint32_t index) {
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
@@ -7334,6 +7409,48 @@
       }
       break;
     }
+    case 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: {
+      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;
+    }
+  }
+
+  Object* pt = 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 PIXEL_ELEMENTS: {
       PixelArray* pixels = PixelArray::cast(elements());
       if (index < static_cast<uint32_t>(pixels->length())) {
@@ -7401,27 +7518,12 @@
       }
       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;
-      }
+    case FAST_ELEMENTS:
+    case DICTIONARY_ELEMENTS:
+      UNREACHABLE();
       break;
-    }
   }
-
-  Object* pt = GetPrototype();
-  if (pt == Heap::null_value()) return Heap::undefined_value();
-  return pt->GetElementWithReceiver(receiver, index);
+  return Heap::undefined_value();
 }
 
 
@@ -9345,7 +9447,7 @@
                                                JSObject::DeleteMode mode) {
   PropertyDetails details = DetailsAt(entry);
   // Ignore attributes if forcing a deletion.
-  if (details.IsDontDelete() && mode == JSObject::NORMAL_DELETION) {
+  if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) {
     return Heap::false_value();
   }
   SetEntry(entry, Heap::null_value(), Heap::null_value(), Smi::FromInt(0));
diff --git a/src/objects.h b/src/objects.h
index 264cc0b..d7b87c6 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1286,7 +1286,12 @@
 // caching.
 class JSObject: public HeapObject {
  public:
-  enum DeleteMode { NORMAL_DELETION, FORCE_DELETION };
+  enum DeleteMode {
+    NORMAL_DELETION,
+    STRICT_DELETION,
+    FORCE_DELETION
+  };
+
   enum ElementsKind {
     // The only "fast" kind.
     FAST_ELEMENTS,
@@ -1356,11 +1361,13 @@
 
   MUST_USE_RESULT MaybeObject* SetProperty(String* key,
                                            Object* value,
-                                           PropertyAttributes attributes);
+                                           PropertyAttributes attributes,
+                                           StrictModeFlag strict_mode);
   MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result,
                                            String* key,
                                            Object* value,
-                                           PropertyAttributes attributes);
+                                           PropertyAttributes attributes,
+                                           StrictModeFlag strict_mode);
   MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck(
       LookupResult* result,
       String* name,
@@ -1375,11 +1382,13 @@
   MUST_USE_RESULT MaybeObject* SetPropertyWithInterceptor(
       String* name,
       Object* value,
-      PropertyAttributes attributes);
+      PropertyAttributes attributes,
+      StrictModeFlag strict_mode);
   MUST_USE_RESULT MaybeObject* SetPropertyPostInterceptor(
       String* name,
       Object* value,
-      PropertyAttributes attributes);
+      PropertyAttributes attributes,
+      StrictModeFlag strict_mode);
   MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes(
       String* key,
       Object* value,
@@ -1506,6 +1515,12 @@
   inline bool HasElement(uint32_t index);
   bool HasElementWithReceiver(JSObject* receiver, uint32_t index);
 
+  // Computes the new capacity when expanding the elements of a JSObject.
+  static int NewElementsCapacity(int old_capacity) {
+    // (old_capacity + 50%) + 16
+    return old_capacity + (old_capacity >> 1) + 16;
+  }
+
   // Tells whether the index'th element is present and how it is stored.
   enum LocalElementType {
     // There is no element with given index.
@@ -1531,18 +1546,25 @@
 
   MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index,
                                               Object* value,
+                                              StrictModeFlag strict_mode,
                                               bool check_prototype = true);
 
   // Set the index'th array element.
   // A Failure object is returned if GC is needed.
   MUST_USE_RESULT MaybeObject* SetElement(uint32_t index,
                                           Object* value,
+                                          StrictModeFlag strict_mode,
                                           bool check_prototype = true);
 
   // Returns the index'th element.
   // The undefined object if index is out of bounds.
-  MaybeObject* GetElementWithReceiver(JSObject* receiver, uint32_t index);
-  MaybeObject* GetElementWithInterceptor(JSObject* receiver, uint32_t index);
+  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);
 
   MUST_USE_RESULT MaybeObject* SetFastElementsCapacityAndLength(int capacity,
                                                                 int length);
@@ -1791,15 +1813,18 @@
                                       uint32_t index,
                                       Object* value,
                                       JSObject* holder);
-  MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(uint32_t index,
-                                                         Object* value,
-                                                         bool check_prototype);
+  MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(
+      uint32_t index,
+      Object* value,
+      StrictModeFlag strict_mode,
+      bool check_prototype);
   MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(
       uint32_t index,
       Object* value,
+      StrictModeFlag strict_mode,
       bool check_prototype);
 
-  MaybeObject* GetElementPostInterceptor(JSObject* receiver, uint32_t index);
+  MaybeObject* GetElementPostInterceptor(Object* receiver, uint32_t index);
 
   MUST_USE_RESULT MaybeObject* DeletePropertyPostInterceptor(String* name,
                                                              DeleteMode mode);
@@ -2433,13 +2458,18 @@
   }
 
   // Set the value for entry.
-  void ValueAtPut(int entry, Object* value) {
+  // Returns false if the put wasn't performed due to property being read only.
+  // Returns true on successful put.
+  bool ValueAtPut(int entry, Object* value) {
     // Check that this value can actually be written.
     PropertyDetails details = DetailsAt(entry);
     // If a value has not been initilized we allow writing to it even if
     // it is read only (a declared const that has not been initialized).
-    if (details.IsReadOnly() && !ValueAt(entry)->IsTheHole()) return;
-    this->set(HashTable<Shape, Key>::EntryToIndex(entry)+1, value);
+    if (details.IsReadOnly() && !ValueAt(entry)->IsTheHole()) {
+      return false;
+    }
+    this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 1, value);
+    return true;
   }
 
   // Returns the property details for the property at entry.
@@ -4365,7 +4395,6 @@
                               kThisPropertyAssignmentsOffset + kPointerSize,
                               kSize> BodyDescriptor;
 
- private:
   // Bit positions in start_position_and_type.
   // The source code start position is in the 30 most significant bits of
   // the start_position_and_type field.
@@ -4384,6 +4413,35 @@
   static const int kOptimizationDisabled = 7;
   static const int kStrictModeFunction = 8;
 
+ private:
+#if V8_HOST_ARCH_32_BIT
+  // On 32 bit platforms, compiler hints is a smi.
+  static const int kCompilerHintsSmiTagSize = kSmiTagSize;
+  static const int kCompilerHintsSize = kPointerSize;
+#else
+  // On 64 bit platforms, compiler hints is not a smi, see comment above.
+  static const int kCompilerHintsSmiTagSize = 0;
+  static const int kCompilerHintsSize = kIntSize;
+#endif
+
+ public:
+  // Constants for optimizing codegen for strict mode function tests.
+  // Allows to use byte-widgh instructions.
+  static const int kStrictModeBitWithinByte =
+      (kStrictModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte;
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+  static const int kStrictModeByteOffset = kCompilerHintsOffset +
+    (kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+  static const int kStrictModeByteOffset = kCompilerHintsOffset +
+    (kCompilerHintsSize - 1) -
+    ((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
+#else
+#error Unknown byte ordering
+#endif
+
+ private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
 };
 
diff --git a/src/parser.cc b/src/parser.cc
index 04d510f..3c361a7 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -803,10 +803,12 @@
   MessageLocation location(script_,
                            source_location.beg_pos,
                            source_location.end_pos);
-  Handle<JSArray> array = Factory::NewJSArray(args.length());
+  Handle<FixedArray> elements = Factory::NewFixedArray(args.length());
   for (int i = 0; i < args.length(); i++) {
-    SetElement(array, i, Factory::NewStringFromUtf8(CStrVector(args[i])));
+    Handle<String> arg_string = Factory::NewStringFromUtf8(CStrVector(args[i]));
+    elements->set(i, *arg_string);
   }
+  Handle<JSArray> array = Factory::NewJSArrayWithElements(elements);
   Handle<Object> result = Factory::NewSyntaxError(type, array);
   Top::Throw(*result, &location);
 }
@@ -818,10 +820,11 @@
   MessageLocation location(script_,
                            source_location.beg_pos,
                            source_location.end_pos);
-  Handle<JSArray> array = Factory::NewJSArray(args.length());
+  Handle<FixedArray> elements = Factory::NewFixedArray(args.length());
   for (int i = 0; i < args.length(); i++) {
-    SetElement(array, i, args[i]);
+    elements->set(i, *args[i]);
   }
+  Handle<JSArray> array = Factory::NewJSArrayWithElements(elements);
   Handle<Object> result = Factory::NewSyntaxError(type, array);
   Top::Throw(*result, &location);
 }
@@ -1106,7 +1109,20 @@
     }
 
     Scanner::Location token_loc = scanner().peek_location();
-    Statement* stat = ParseStatement(NULL, CHECK_OK);
+
+    Statement* stat;
+    if (peek() == Token::FUNCTION) {
+      // FunctionDeclaration is only allowed in the context of SourceElements
+      // (Ecma 262 5th Edition, clause 14):
+      // SourceElement:
+      //    Statement
+      //    FunctionDeclaration
+      // Common language extension is to allow function declaration in place
+      // of any statement. This language extension is disabled in strict mode.
+      stat = ParseFunctionDeclaration(CHECK_OK);
+    } else {
+      stat = ParseStatement(NULL, CHECK_OK);
+    }
 
     if (stat == NULL || stat->IsEmpty()) {
       directive_prologue = false;   // End of directive prologue.
@@ -1263,8 +1279,17 @@
       return result;
     }
 
-    case Token::FUNCTION:
+    case Token::FUNCTION: {
+      // In strict mode, FunctionDeclaration is only allowed in the context
+      // of SourceElements.
+      if (temp_scope_->StrictMode()) {
+        ReportMessageAt(scanner().peek_location(), "strict_function",
+                        Vector<const char*>::empty());
+        *ok = false;
+        return NULL;
+      }
       return ParseFunctionDeclaration(ok);
+    }
 
     case Token::NATIVE:
       return ParseNativeDeclaration(ok);
@@ -1515,6 +1540,11 @@
     Consume(Token::VAR);
   } else if (peek() == Token::CONST) {
     Consume(Token::CONST);
+    if (temp_scope_->StrictMode()) {
+      ReportMessage("strict_const", Vector<const char*>::empty());
+      *ok = false;
+      return NULL;
+    }
     mode = Variable::CONST;
     is_const = true;
   } else {
@@ -1634,34 +1664,49 @@
 
     if (top_scope_->is_global_scope()) {
       // Compute the arguments for the runtime call.
-      ZoneList<Expression*>* arguments = new ZoneList<Expression*>(2);
-      // Be careful not to assign a value to the global variable if
-      // we're in a with. The initialization value should not
-      // necessarily be stored in the global object in that case,
-      // which is why we need to generate a separate assignment node.
+      ZoneList<Expression*>* arguments = new ZoneList<Expression*>(3);
       arguments->Add(new Literal(name));  // we have at least 1 parameter
-      if (is_const || (value != NULL && !inside_with())) {
+      CallRuntime* initialize;
+
+      if (is_const) {
         arguments->Add(value);
         value = NULL;  // zap the value to avoid the unnecessary assignment
-      }
-      // Construct the call to Runtime::DeclareGlobal{Variable,Const}Locally
-      // and add it to the initialization statement block. Note that
-      // this function does different things depending on if we have
-      // 1 or 2 parameters.
-      CallRuntime* initialize;
-      if (is_const) {
+
+        // Construct the call to Runtime_InitializeConstGlobal
+        // and add it to the initialization statement block.
+        // Note that the function does different things depending on
+        // the number of arguments (1 or 2).
         initialize =
-          new CallRuntime(
-            Factory::InitializeConstGlobal_symbol(),
-            Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
-            arguments);
+            new CallRuntime(
+              Factory::InitializeConstGlobal_symbol(),
+              Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
+              arguments);
       } else {
+        // Add strict mode.
+        // We may want to pass singleton to avoid Literal allocations.
+        arguments->Add(NewNumberLiteral(
+            temp_scope_->StrictMode() ? kStrictMode : kNonStrictMode));
+
+        // Be careful not to assign a value to the global variable if
+        // we're in a with. The initialization value should not
+        // necessarily be stored in the global object in that case,
+        // which is why we need to generate a separate assignment node.
+        if (value != NULL && !inside_with()) {
+          arguments->Add(value);
+          value = NULL;  // zap the value to avoid the unnecessary assignment
+        }
+
+        // Construct the call to Runtime_InitializeVarGlobal
+        // and add it to the initialization statement block.
+        // Note that the function does different things depending on
+        // the number of arguments (2 or 3).
         initialize =
-          new CallRuntime(
-            Factory::InitializeVarGlobal_symbol(),
-            Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
-            arguments);
+            new CallRuntime(
+              Factory::InitializeVarGlobal_symbol(),
+              Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
+              arguments);
       }
+
       block->AddStatement(new ExpressionStatement(initialize));
     }
 
@@ -2521,6 +2566,16 @@
       }
     }
 
+    // "delete identifier" is a syntax error in strict mode.
+    if (op == Token::DELETE && temp_scope_->StrictMode()) {
+      VariableProxy* operand = expression->AsVariableProxy();
+      if (operand != NULL && !operand->is_this()) {
+        ReportMessage("strict_delete", Vector<const char*>::empty());
+        *ok = false;
+        return NULL;
+      }
+    }
+
     return new UnaryOperation(op, expression);
 
   } else if (Token::IsCountOp(op)) {
@@ -3983,12 +4038,14 @@
       MessageLocation location(Factory::NewScript(script),
                                source_location.beg_pos,
                                source_location.end_pos);
-      int argc = (name_opt == NULL) ? 0 : 1;
-      Handle<JSArray> array = Factory::NewJSArray(argc);
-      if (name_opt != NULL) {
-        SetElement(array,
-                   0,
-                   Factory::NewStringFromUtf8(CStrVector(name_opt)));
+      Handle<JSArray> array;
+      if (name_opt == NULL) {
+        array = Factory::NewJSArray(0);
+      } else {
+        Handle<String> name = Factory::NewStringFromUtf8(CStrVector(name_opt));
+        Handle<FixedArray> element = Factory::NewFixedArray(1);
+        element->set(0, *name);
+        array = Factory::NewJSArrayWithElements(element);
       }
       Handle<Object> result = Factory::NewSyntaxError(message, array);
       Top::Throw(*result, &location);
@@ -4060,7 +4117,7 @@
       if (value.is_null()) return Handle<Object>::null();
       uint32_t index;
       if (key->AsArrayIndex(&index)) {
-        SetOwnElement(json_object, index, value);
+        SetOwnElement(json_object, index, value, kNonStrictMode);
       } else if (key->Equals(Heap::Proto_symbol())) {
         // We can't remove the __proto__ accessor since it's hardcoded
         // in several places. Instead go along and add the value as
@@ -4263,6 +4320,8 @@
                                    capture_index);
       }
       builder->AddAtom(body);
+      // For compatability with JSC and ES3, we allow quantifiers after
+      // lookaheads, and break in all cases.
       break;
     }
     case '|': {
@@ -4336,7 +4395,7 @@
                                            type,
                                            captures_started());
       builder = stored_state->builder();
-      break;
+      continue;
     }
     case '[': {
       RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
@@ -4359,11 +4418,11 @@
         builder->AddAssertion(
             new RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
         continue;
-        // AtomEscape ::
-        //   CharacterClassEscape
-        //
-        // CharacterClassEscape :: one of
-        //   d D s S w W
+      // AtomEscape ::
+      //   CharacterClassEscape
+      //
+      // CharacterClassEscape :: one of
+      //   d D s S w W
       case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
         uc32 c = Next();
         Advance(2);
diff --git a/src/platform-cygwin.cc b/src/platform-cygwin.cc
new file mode 100644
index 0000000..a7cc525
--- /dev/null
+++ b/src/platform-cygwin.cc
@@ -0,0 +1,745 @@
+// Copyright 2006-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.
+
+// Platform specific code for Cygwin goes here. For the POSIX comaptible parts
+// the implementation is in platform-posix.cc.
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdarg.h>
+#include <strings.h>    // index
+#include <sys/time.h>
+#include <sys/mman.h>   // mmap & munmap
+#include <unistd.h>     // sysconf
+
+#undef MAP_TYPE
+
+#include "v8.h"
+
+#include "platform.h"
+#include "top.h"
+#include "v8threads.h"
+#include "vm-state-inl.h"
+#include "win32-headers.h"
+
+namespace v8 {
+namespace internal {
+
+// 0 is never a valid thread id
+static const pthread_t kNoThread = (pthread_t) 0;
+
+
+double ceiling(double x) {
+  return ceil(x);
+}
+
+
+void OS::Setup() {
+  // Seed the random number generator.
+  // Convert the current time to a 64-bit integer first, before converting it
+  // to an unsigned. Going directly can cause an overflow and the seed to be
+  // set to all ones. The seed will be identical for different instances that
+  // call this setup code within the same millisecond.
+  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
+  srandom(static_cast<unsigned int>(seed));
+}
+
+
+uint64_t OS::CpuFeaturesImpliedByPlatform() {
+  return 0;  // Nothing special about Cygwin.
+}
+
+
+int OS::ActivationFrameAlignment() {
+  // With gcc 4.4 the tree vectorization optimizer can generate code
+  // that requires 16 byte alignment such as movdqa on x86.
+  return 16;
+}
+
+
+void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
+  __asm__ __volatile__("" : : : "memory");
+  // An x86 store acts as a release barrier.
+  *ptr = value;
+}
+
+const char* OS::LocalTimezone(double time) {
+  if (isnan(time)) return "";
+  time_t tv = static_cast<time_t>(floor(time/msPerSecond));
+  struct tm* t = localtime(&tv);
+  if (NULL == t) return "";
+  return tzname[0];  // The location of the timezone string on Cygwin.
+}
+
+
+double OS::LocalTimeOffset() {
+  // On Cygwin, struct tm does not contain a tm_gmtoff field.
+  time_t utc = time(NULL);
+  ASSERT(utc != -1);
+  struct tm* loc = localtime(&utc);
+  ASSERT(loc != NULL);
+  // time - localtime includes any daylight savings offset, so subtract it.
+  return static_cast<double>((mktime(loc) - utc) * msPerSecond -
+                             (loc->tm_isdst > 0 ? 3600 * msPerSecond : 0));
+}
+
+
+// We keep the lowest and highest addresses mapped as a quick way of
+// determining that pointers are outside the heap (used mostly in assertions
+// and verification).  The estimate is conservative, ie, not all addresses in
+// 'allocated' space are actually allocated to our heap.  The range is
+// [lowest, highest), inclusive on the low and and exclusive on the high end.
+static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
+static void* highest_ever_allocated = reinterpret_cast<void*>(0);
+
+
+static void UpdateAllocatedSpaceLimits(void* address, int size) {
+  lowest_ever_allocated = Min(lowest_ever_allocated, address);
+  highest_ever_allocated =
+      Max(highest_ever_allocated,
+          reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
+}
+
+
+bool OS::IsOutsideAllocatedSpace(void* address) {
+  return address < lowest_ever_allocated || address >= highest_ever_allocated;
+}
+
+
+size_t OS::AllocateAlignment() {
+  return sysconf(_SC_PAGESIZE);
+}
+
+
+void* OS::Allocate(const size_t requested,
+                   size_t* allocated,
+                   bool is_executable) {
+  const size_t msize = RoundUp(requested, sysconf(_SC_PAGESIZE));
+  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
+  void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  if (mbase == MAP_FAILED) {
+    LOG(StringEvent("OS::Allocate", "mmap failed"));
+    return NULL;
+  }
+  *allocated = msize;
+  UpdateAllocatedSpaceLimits(mbase, msize);
+  return mbase;
+}
+
+
+void OS::Free(void* address, const size_t size) {
+  // TODO(1240712): munmap has a return value which is ignored here.
+  int result = munmap(address, size);
+  USE(result);
+  ASSERT(result == 0);
+}
+
+
+#ifdef ENABLE_HEAP_PROTECTION
+
+void OS::Protect(void* address, size_t size) {
+  // TODO(1240712): mprotect has a return value which is ignored here.
+  mprotect(address, size, PROT_READ);
+}
+
+
+void OS::Unprotect(void* address, size_t size, bool is_executable) {
+  // TODO(1240712): mprotect has a return value which is ignored here.
+  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
+  mprotect(address, size, prot);
+}
+
+#endif
+
+
+void OS::Sleep(int milliseconds) {
+  unsigned int ms = static_cast<unsigned int>(milliseconds);
+  usleep(1000 * ms);
+}
+
+
+void OS::Abort() {
+  // Redirect to std abort to signal abnormal program termination.
+  abort();
+}
+
+
+void OS::DebugBreak() {
+  asm("int $3");
+}
+
+
+class PosixMemoryMappedFile : public OS::MemoryMappedFile {
+ public:
+  PosixMemoryMappedFile(FILE* file, void* memory, int size)
+    : file_(file), memory_(memory), size_(size) { }
+  virtual ~PosixMemoryMappedFile();
+  virtual void* memory() { return memory_; }
+  virtual int size() { return size_; }
+ private:
+  FILE* file_;
+  void* memory_;
+  int size_;
+};
+
+
+OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
+  FILE* file = fopen(name, "r+");
+  if (file == NULL) return NULL;
+
+  fseek(file, 0, SEEK_END);
+  int size = ftell(file);
+
+  void* memory =
+      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
+  return new PosixMemoryMappedFile(file, memory, size);
+}
+
+
+OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
+    void* initial) {
+  FILE* file = fopen(name, "w+");
+  if (file == NULL) return NULL;
+  int result = fwrite(initial, size, 1, file);
+  if (result < 1) {
+    fclose(file);
+    return NULL;
+  }
+  void* memory =
+      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
+  return new PosixMemoryMappedFile(file, memory, size);
+}
+
+
+PosixMemoryMappedFile::~PosixMemoryMappedFile() {
+  if (memory_) munmap(memory_, size_);
+  fclose(file_);
+}
+
+
+void OS::LogSharedLibraryAddresses() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  // This function assumes that the layout of the file is as follows:
+  // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name]
+  // If we encounter an unexpected situation we abort scanning further entries.
+  FILE* fp = fopen("/proc/self/maps", "r");
+  if (fp == NULL) return;
+
+  // Allocate enough room to be able to store a full file name.
+  const int kLibNameLen = FILENAME_MAX + 1;
+  char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
+
+  // This loop will terminate once the scanning hits an EOF.
+  while (true) {
+    uintptr_t start, end;
+    char attr_r, attr_w, attr_x, attr_p;
+    // Parse the addresses and permission bits at the beginning of the line.
+    if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break;
+    if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break;
+
+    int c;
+    if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') {
+      // Found a read-only executable entry. Skip characters until we reach
+      // the beginning of the filename or the end of the line.
+      do {
+        c = getc(fp);
+      } while ((c != EOF) && (c != '\n') && (c != '/'));
+      if (c == EOF) break;  // EOF: Was unexpected, just exit.
+
+      // Process the filename if found.
+      if (c == '/') {
+        ungetc(c, fp);  // Push the '/' back into the stream to be read below.
+
+        // Read to the end of the line. Exit if the read fails.
+        if (fgets(lib_name, kLibNameLen, fp) == NULL) break;
+
+        // Drop the newline character read by fgets. We do not need to check
+        // for a zero-length string because we know that we at least read the
+        // '/' character.
+        lib_name[strlen(lib_name) - 1] = '\0';
+      } else {
+        // No library name found, just record the raw address range.
+        snprintf(lib_name, kLibNameLen,
+                 "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end);
+      }
+      LOG(SharedLibraryEvent(lib_name, start, end));
+    } else {
+      // Entry not describing executable data. Skip to end of line to setup
+      // reading the next entry.
+      do {
+        c = getc(fp);
+      } while ((c != EOF) && (c != '\n'));
+      if (c == EOF) break;
+    }
+  }
+  free(lib_name);
+  fclose(fp);
+#endif
+}
+
+
+void OS::SignalCodeMovingGC() {
+  // Nothing to do on Cygwin.
+}
+
+
+int OS::StackWalk(Vector<OS::StackFrame> frames) {
+  // Not supported on Cygwin.
+  return 0;
+}
+
+
+// Constants used for mmap.
+static const int kMmapFd = -1;
+static const int kMmapFdOffset = 0;
+
+
+VirtualMemory::VirtualMemory(size_t size) {
+  address_ = mmap(NULL, size, PROT_NONE,
+                  MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
+                  kMmapFd, kMmapFdOffset);
+  size_ = size;
+}
+
+
+VirtualMemory::~VirtualMemory() {
+  if (IsReserved()) {
+    if (0 == munmap(address(), size())) address_ = MAP_FAILED;
+  }
+}
+
+
+bool VirtualMemory::IsReserved() {
+  return address_ != MAP_FAILED;
+}
+
+
+bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
+  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
+
+  if (mprotect(address, size, prot) != 0) {
+    return false;
+  }
+
+  UpdateAllocatedSpaceLimits(address, size);
+  return true;
+}
+
+
+bool VirtualMemory::Uncommit(void* address, size_t size) {
+  return mmap(address, size, PROT_NONE,
+              MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
+              kMmapFd, kMmapFdOffset) != MAP_FAILED;
+}
+
+
+class ThreadHandle::PlatformData : public Malloced {
+ public:
+  explicit PlatformData(ThreadHandle::Kind kind) {
+    Initialize(kind);
+  }
+
+  void Initialize(ThreadHandle::Kind kind) {
+    switch (kind) {
+      case ThreadHandle::SELF: thread_ = pthread_self(); break;
+      case ThreadHandle::INVALID: thread_ = kNoThread; break;
+    }
+  }
+
+  pthread_t thread_;  // Thread handle for pthread.
+};
+
+
+ThreadHandle::ThreadHandle(Kind kind) {
+  data_ = new PlatformData(kind);
+}
+
+
+void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
+  data_->Initialize(kind);
+}
+
+
+ThreadHandle::~ThreadHandle() {
+  delete data_;
+}
+
+
+bool ThreadHandle::IsSelf() const {
+  return pthread_equal(data_->thread_, pthread_self());
+}
+
+
+bool ThreadHandle::IsValid() const {
+  return data_->thread_ != kNoThread;
+}
+
+
+Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
+  set_name("v8:<unknown>");
+}
+
+
+Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+  set_name(name);
+}
+
+
+Thread::~Thread() {
+}
+
+
+static void* ThreadEntry(void* arg) {
+  Thread* thread = reinterpret_cast<Thread*>(arg);
+  // This is also initialized by the first argument to pthread_create() but we
+  // don't know which thread will run first (the original thread or the new
+  // one) so we initialize it here too.
+  thread->thread_handle_data()->thread_ = pthread_self();
+  ASSERT(thread->IsValid());
+  thread->Run();
+  return NULL;
+}
+
+
+void Thread::set_name(const char* name) {
+  strncpy(name_, name, sizeof(name_));
+  name_[sizeof(name_) - 1] = '\0';
+}
+
+
+void Thread::Start() {
+  pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
+  ASSERT(IsValid());
+}
+
+
+void Thread::Join() {
+  pthread_join(thread_handle_data()->thread_, NULL);
+}
+
+
+static inline Thread::LocalStorageKey PthreadKeyToLocalKey(
+    pthread_key_t pthread_key) {
+  // We need to cast pthread_key_t to Thread::LocalStorageKey in two steps
+  // because pthread_key_t is a pointer type on Cygwin. This will probably not
+  // work on 64-bit platforms, but Cygwin doesn't support 64-bit anyway.
+  STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t));
+  intptr_t ptr_key = reinterpret_cast<intptr_t>(pthread_key);
+  return static_cast<Thread::LocalStorageKey>(ptr_key);
+}
+
+
+static inline pthread_key_t LocalKeyToPthreadKey(
+    Thread::LocalStorageKey local_key) {
+  STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t));
+  intptr_t ptr_key = static_cast<intptr_t>(local_key);
+  return reinterpret_cast<pthread_key_t>(ptr_key);
+}
+
+
+Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
+  pthread_key_t key;
+  int result = pthread_key_create(&key, NULL);
+  USE(result);
+  ASSERT(result == 0);
+  return PthreadKeyToLocalKey(key);
+}
+
+
+void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
+  pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
+  int result = pthread_key_delete(pthread_key);
+  USE(result);
+  ASSERT(result == 0);
+}
+
+
+void* Thread::GetThreadLocal(LocalStorageKey key) {
+  pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
+  return pthread_getspecific(pthread_key);
+}
+
+
+void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
+  pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
+  pthread_setspecific(pthread_key, value);
+}
+
+
+void Thread::YieldCPU() {
+  sched_yield();
+}
+
+
+class CygwinMutex : public Mutex {
+ public:
+
+  CygwinMutex() {
+    pthread_mutexattr_t attrs;
+    memset(&attrs, 0, sizeof(attrs));
+
+    int result = pthread_mutexattr_init(&attrs);
+    ASSERT(result == 0);
+    result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE);
+    ASSERT(result == 0);
+    result = pthread_mutex_init(&mutex_, &attrs);
+    ASSERT(result == 0);
+  }
+
+  virtual ~CygwinMutex() { pthread_mutex_destroy(&mutex_); }
+
+  virtual int Lock() {
+    int result = pthread_mutex_lock(&mutex_);
+    return result;
+  }
+
+  virtual int Unlock() {
+    int result = pthread_mutex_unlock(&mutex_);
+    return result;
+  }
+
+  virtual bool TryLock() {
+    int result = pthread_mutex_trylock(&mutex_);
+    // Return false if the lock is busy and locking failed.
+    if (result == EBUSY) {
+      return false;
+    }
+    ASSERT(result == 0);  // Verify no other errors.
+    return true;
+  }
+
+ private:
+  pthread_mutex_t mutex_;   // Pthread mutex for POSIX platforms.
+};
+
+
+Mutex* OS::CreateMutex() {
+  return new CygwinMutex();
+}
+
+
+class CygwinSemaphore : public Semaphore {
+ public:
+  explicit CygwinSemaphore(int count) {  sem_init(&sem_, 0, count); }
+  virtual ~CygwinSemaphore() { sem_destroy(&sem_); }
+
+  virtual void Wait();
+  virtual bool Wait(int timeout);
+  virtual void Signal() { sem_post(&sem_); }
+ private:
+  sem_t sem_;
+};
+
+
+void CygwinSemaphore::Wait() {
+  while (true) {
+    int result = sem_wait(&sem_);
+    if (result == 0) return;  // Successfully got semaphore.
+    CHECK(result == -1 && errno == EINTR);  // Signal caused spurious wakeup.
+  }
+}
+
+
+#ifndef TIMEVAL_TO_TIMESPEC
+#define TIMEVAL_TO_TIMESPEC(tv, ts) do {                            \
+    (ts)->tv_sec = (tv)->tv_sec;                                    \
+    (ts)->tv_nsec = (tv)->tv_usec * 1000;                           \
+} while (false)
+#endif
+
+
+bool CygwinSemaphore::Wait(int timeout) {
+  const long kOneSecondMicros = 1000000;  // NOLINT
+
+  // Split timeout into second and nanosecond parts.
+  struct timeval delta;
+  delta.tv_usec = timeout % kOneSecondMicros;
+  delta.tv_sec = timeout / kOneSecondMicros;
+
+  struct timeval current_time;
+  // Get the current time.
+  if (gettimeofday(&current_time, NULL) == -1) {
+    return false;
+  }
+
+  // Calculate time for end of timeout.
+  struct timeval end_time;
+  timeradd(&current_time, &delta, &end_time);
+
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC(&end_time, &ts);
+  // Wait for semaphore signalled or timeout.
+  while (true) {
+    int result = sem_timedwait(&sem_, &ts);
+    if (result == 0) return true;  // Successfully got semaphore.
+    if (result == -1 && errno == ETIMEDOUT) return false;  // Timeout.
+    CHECK(result == -1 && errno == EINTR);  // Signal caused spurious wakeup.
+  }
+}
+
+
+Semaphore* OS::CreateSemaphore(int count) {
+  return new CygwinSemaphore(count);
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+// ----------------------------------------------------------------------------
+// Cygwin profiler support.
+//
+// On Cygwin we use the same sampler implementation as on win32.
+
+class Sampler::PlatformData : public Malloced {
+ public:
+  explicit PlatformData(Sampler* sampler) {
+    sampler_ = sampler;
+    sampler_thread_ = INVALID_HANDLE_VALUE;
+    profiled_thread_ = INVALID_HANDLE_VALUE;
+  }
+
+  Sampler* sampler_;
+  HANDLE sampler_thread_;
+  HANDLE profiled_thread_;
+  RuntimeProfilerRateLimiter rate_limiter_;
+
+  // Sampler thread handler.
+  void Runner() {
+    while (sampler_->IsActive()) {
+      if (rate_limiter_.SuspendIfNecessary()) continue;
+      Sample();
+      Sleep(sampler_->interval_);
+    }
+  }
+
+  void Sample() {
+    if (sampler_->IsProfiling()) {
+      // Context used for sampling the register state of the profiled thread.
+      CONTEXT context;
+      memset(&context, 0, sizeof(context));
+
+      TickSample sample_obj;
+      TickSample* sample = CpuProfiler::TickSampleEvent();
+      if (sample == NULL) sample = &sample_obj;
+
+      static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
+      if (SuspendThread(profiled_thread_) == kSuspendFailed) return;
+      sample->state = Top::current_vm_state();
+
+      context.ContextFlags = CONTEXT_FULL;
+      if (GetThreadContext(profiled_thread_, &context) != 0) {
+#if V8_HOST_ARCH_X64
+        sample->pc = reinterpret_cast<Address>(context.Rip);
+        sample->sp = reinterpret_cast<Address>(context.Rsp);
+        sample->fp = reinterpret_cast<Address>(context.Rbp);
+#else
+        sample->pc = reinterpret_cast<Address>(context.Eip);
+        sample->sp = reinterpret_cast<Address>(context.Esp);
+        sample->fp = reinterpret_cast<Address>(context.Ebp);
+#endif
+        sampler_->SampleStack(sample);
+        sampler_->Tick(sample);
+      }
+      ResumeThread(profiled_thread_);
+    }
+    if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
+  }
+};
+
+
+// Entry point for sampler thread.
+static DWORD __stdcall SamplerEntry(void* arg) {
+  Sampler::PlatformData* data =
+      reinterpret_cast<Sampler::PlatformData*>(arg);
+  data->Runner();
+  return 0;
+}
+
+
+// Initialize a profile sampler.
+Sampler::Sampler(int interval)
+    : interval_(interval),
+      profiling_(false),
+      active_(false),
+      samples_taken_(0) {
+  data_ = new PlatformData(this);
+}
+
+
+Sampler::~Sampler() {
+  delete data_;
+}
+
+
+// Start profiling.
+void Sampler::Start() {
+  // Do not start multiple threads for the same sampler.
+  ASSERT(!IsActive());
+
+  // Get a handle to the calling thread. This is the thread that we are
+  // going to profile. We need to make a copy of the handle because we are
+  // going to use it in the sampler thread. Using GetThreadHandle() will
+  // not work in this case. We're using OpenThread because DuplicateHandle
+  // for some reason doesn't work in Chrome's sandbox.
+  data_->profiled_thread_ = OpenThread(THREAD_GET_CONTEXT |
+                                       THREAD_SUSPEND_RESUME |
+                                       THREAD_QUERY_INFORMATION,
+                                       false,
+                                       GetCurrentThreadId());
+  BOOL ok = data_->profiled_thread_ != NULL;
+  if (!ok) return;
+
+  // Start sampler thread.
+  DWORD tid;
+  SetActive(true);
+  data_->sampler_thread_ = CreateThread(NULL, 0, SamplerEntry, data_, 0, &tid);
+  // Set thread to high priority to increase sampling accuracy.
+  SetThreadPriority(data_->sampler_thread_, THREAD_PRIORITY_TIME_CRITICAL);
+}
+
+
+// Stop profiling.
+void Sampler::Stop() {
+  // Seting active to false triggers termination of the sampler
+  // thread.
+  SetActive(false);
+
+  // Wait for sampler thread to terminate.
+  Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
+  WaitForSingleObject(data_->sampler_thread_, INFINITE);
+
+  // Release the thread handles
+  CloseHandle(data_->sampler_thread_);
+  CloseHandle(data_->profiled_thread_);
+}
+
+
+#endif  // ENABLE_LOGGING_AND_PROFILING
+
+} }  // namespace v8::internal
+
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index c18049f..21763b5 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -224,7 +224,7 @@
 
 
 OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
-  FILE* file = fopen(name, "w+");
+  FILE* file = fopen(name, "r+");
   if (file == NULL) return NULL;
 
   fseek(file, 0, SEEK_END);
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index 4a474b4..16aa7c8 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -327,7 +327,7 @@
 
 
 OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
-  FILE* file = fopen(name, "w+");
+  FILE* file = fopen(name, "r+");
   if (file == NULL) return NULL;
 
   fseek(file, 0, SEEK_END);
@@ -873,6 +873,7 @@
   }
 
   void SendProfilingSignal() {
+    if (!signal_handler_installed_) return;
     // Glibc doesn't provide a wrapper for tgkill(2).
     syscall(SYS_tgkill, vm_tgid_, vm_tid_, SIGPROF);
   }
@@ -939,8 +940,8 @@
   sa.sa_sigaction = ProfilerSignalHandler;
   sigemptyset(&sa.sa_mask);
   sa.sa_flags = SA_RESTART | SA_SIGINFO;
-  if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return;
-  data_->signal_handler_installed_ = true;
+  data_->signal_handler_installed_ =
+      sigaction(SIGPROF, &sa, &data_->old_signal_handler_) == 0;
 
   // Start a thread that sends SIGPROF signal to VM thread.
   // Sending the signal ourselves instead of relying on itimer provides
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index ea35c1b..35724c3 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -205,7 +205,7 @@
 
 
 OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
-  FILE* file = fopen(name, "w+");
+  FILE* file = fopen(name, "r+");
   if (file == NULL) return NULL;
 
   fseek(file, 0, SEEK_END);
diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc
index 0002dd7..e279629 100644
--- a/src/platform-openbsd.cc
+++ b/src/platform-openbsd.cc
@@ -222,7 +222,7 @@
 
 
 OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
-  FILE* file = fopen(name, "w+");
+  FILE* file = fopen(name, "r+");
   if (file == NULL) return NULL;
 
   fseek(file, 0, SEEK_END);
diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc
index 556e26b..ebe0475 100644
--- a/src/platform-solaris.cc
+++ b/src/platform-solaris.cc
@@ -235,7 +235,7 @@
 
 
 OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
-  FILE* file = fopen(name, "w+");
+  FILE* file = fopen(name, "r+");
   if (file == NULL) return NULL;
 
   fseek(file, 0, SEEK_END);
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index b5a85f6..f24994b 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -939,7 +939,7 @@
   // Open a physical file
   HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE,
       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
-  if (file == NULL) return NULL;
+  if (file == INVALID_HANDLE_VALUE) return NULL;
 
   int size = static_cast<int>(GetFileSize(file, NULL));
 
diff --git a/src/platform.h b/src/platform.h
index 0d7d2e9..88825e6 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -567,13 +567,13 @@
         pc(NULL),
         sp(NULL),
         fp(NULL),
-        function(NULL),
+        tos(NULL),
         frames_count(0) {}
   StateTag state;  // The state of the VM.
-  Address pc;  // Instruction pointer.
-  Address sp;  // Stack pointer.
-  Address fp;  // Frame pointer.
-  Address function;  // The last called JS function.
+  Address pc;   // Instruction pointer.
+  Address sp;   // Stack pointer.
+  Address fp;   // Frame pointer.
+  Address tos;  // Top stack value (*sp).
   static const int kMaxFramesCount = 64;
   Address stack[kMaxFramesCount];  // Call stack.
   int frames_count;  // Number of captured frames.
diff --git a/src/profile-generator-inl.h b/src/profile-generator-inl.h
index 3df6af0..747e5c7 100644
--- a/src/profile-generator-inl.h
+++ b/src/profile-generator-inl.h
@@ -45,16 +45,6 @@
 }
 
 
-CodeEntry::CodeEntry(int security_token_id)
-    : tag_(Logger::FUNCTION_TAG),
-      name_prefix_(kEmptyNamePrefix),
-      name_(""),
-      resource_name_(""),
-      line_number_(0),
-      security_token_id_(security_token_id) {
-}
-
-
 CodeEntry::CodeEntry(Logger::LogEventsAndTags tag,
                      const char* name_prefix,
                      const char* name,
@@ -66,6 +56,7 @@
       name_(name),
       resource_name_(resource_name),
       line_number_(line_number),
+      shared_id_(0),
       security_token_id_(security_token_id) {
 }
 
@@ -130,34 +121,6 @@
   return id_adaptor.returned_id;
 }
 
-
-template<class Visitor>
-void HeapEntriesMap::UpdateEntries(Visitor* visitor) {
-  for (HashMap::Entry* p = entries_.Start();
-       p != NULL;
-       p = entries_.Next(p)) {
-    EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value);
-    entry_info->entry = visitor->GetEntry(
-        reinterpret_cast<HeapObject*>(p->key),
-        entry_info->children_count,
-        entry_info->retainers_count);
-    entry_info->children_count = 0;
-    entry_info->retainers_count = 0;
-  }
-}
-
-
-bool HeapSnapshotGenerator::ReportProgress(bool force) {
-  const int kProgressReportGranularity = 10000;
-  if (control_ != NULL
-      && (force || progress_counter_ % kProgressReportGranularity == 0)) {
-      return
-          control_->ReportProgressValue(progress_counter_, progress_total_) ==
-          v8::ActivityControl::kContinue;
-  }
-  return true;
-}
-
 } }  // namespace v8::internal
 
 #endif  // ENABLE_LOGGING_AND_PROFILING
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 06ee333..7612eab 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -156,13 +156,18 @@
 
 uint32_t CodeEntry::GetCallUid() const {
   uint32_t hash = ComputeIntegerHash(tag_);
-  hash ^= ComputeIntegerHash(
-      static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_prefix_)));
-  hash ^= ComputeIntegerHash(
-      static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_)));
-  hash ^= ComputeIntegerHash(
-      static_cast<uint32_t>(reinterpret_cast<uintptr_t>(resource_name_)));
-  hash ^= ComputeIntegerHash(line_number_);
+  if (shared_id_ != 0) {
+    hash ^= ComputeIntegerHash(
+        static_cast<uint32_t>(shared_id_));
+  } else {
+    hash ^= ComputeIntegerHash(
+        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_prefix_)));
+    hash ^= ComputeIntegerHash(
+        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_)));
+    hash ^= ComputeIntegerHash(
+        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(resource_name_)));
+    hash ^= ComputeIntegerHash(line_number_);
+  }
   return hash;
 }
 
@@ -170,10 +175,12 @@
 bool CodeEntry::IsSameAs(CodeEntry* entry) const {
   return this == entry
       || (tag_ == entry->tag_
-          && name_prefix_ == entry->name_prefix_
-          && name_ == entry->name_
-          && resource_name_ == entry->resource_name_
-          && line_number_ == entry->line_number_);
+          && shared_id_ == entry->shared_id_
+          && (shared_id_ != 0
+              || (name_prefix_ == entry->name_prefix_
+                  && name_ == entry->name_
+                  && resource_name_ == entry->resource_name_
+                  && line_number_ == entry->line_number_)));
 }
 
 
@@ -458,23 +465,12 @@
 }
 
 
+CodeEntry* const CodeMap::kSfiCodeEntry = NULL;
 const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL;
 const CodeMap::CodeTreeConfig::Value CodeMap::CodeTreeConfig::kNoValue =
     CodeMap::CodeEntryInfo(NULL, 0);
 
 
-void CodeMap::AddAlias(Address start, CodeEntry* entry, Address code_start) {
-  CodeTree::Locator locator;
-  if (tree_.Find(code_start, &locator)) {
-    const CodeEntryInfo& code_info = locator.value();
-    if (tree_.Insert(start, &locator)) {
-      entry->CopyData(*code_info.entry);
-      locator.set_value(CodeEntryInfo(entry, code_info.size));
-    }
-  }
-}
-
-
 CodeEntry* CodeMap::FindEntry(Address addr) {
   CodeTree::Locator locator;
   if (tree_.FindGreatestLessThan(addr, &locator)) {
@@ -487,6 +483,22 @@
 }
 
 
+int CodeMap::GetSFITag(Address addr) {
+  CodeTree::Locator locator;
+  // For SFI entries, 'size' field is used to store their IDs.
+  if (tree_.Find(addr, &locator)) {
+    const CodeEntryInfo& entry = locator.value();
+    ASSERT(entry.entry == kSfiCodeEntry);
+    return entry.size;
+  } else {
+    tree_.Insert(addr, &locator);
+    int tag = next_sfi_tag_++;
+    locator.set_value(CodeEntryInfo(kSfiCodeEntry, tag));
+    return tag;
+  }
+}
+
+
 void CodeMap::CodeTreePrinter::Call(
     const Address& key, const CodeMap::CodeEntryInfo& value) {
   OS::Print("%p %5d %s\n", key, value.size, value.entry->name());
@@ -715,13 +727,6 @@
 }
 
 
-CodeEntry* CpuProfilesCollection::NewCodeEntry(int security_token_id) {
-  CodeEntry* entry = new CodeEntry(security_token_id);
-  code_entries_.Add(entry);
-  return entry;
-}
-
-
 void CpuProfilesCollection::AddPathToCurrentProfiles(
     const Vector<CodeEntry*>& path) {
   // As starting / stopping profiles is rare relatively to this
@@ -784,19 +789,10 @@
   if (sample.pc != NULL) {
     *entry++ = code_map_.FindEntry(sample.pc);
 
-    if (sample.function != NULL) {
-      *entry = code_map_.FindEntry(sample.function);
+    if (sample.tos != NULL) {
+      *entry = code_map_.FindEntry(sample.tos);
       if (*entry != NULL && !(*entry)->is_js_function()) {
         *entry = NULL;
-      } else {
-        CodeEntry* pc_entry = *entries.start();
-        if (pc_entry == NULL) {
-          *entry = NULL;
-        } else if (pc_entry->is_js_function()) {
-          // Use function entry in favor of pc entry, as function
-          // entry has security token.
-          *entries.start() = NULL;
-        }
       }
       entry++;
     }
@@ -1181,12 +1177,6 @@
 }
 
 
-HeapObject *const HeapSnapshot::kInternalRootObject =
-    reinterpret_cast<HeapObject*>(1);
-HeapObject *const HeapSnapshot::kGcRootsObject =
-    reinterpret_cast<HeapObject*>(2);
-
-
 // It is very important to keep objects that form a heap snapshot
 // as small as possible.
 namespace {  // Avoid littering the global namespace.
@@ -1257,96 +1247,6 @@
 }
 
 
-HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
-                                  int children_count,
-                                  int retainers_count) {
-  if (object == kInternalRootObject) {
-    ASSERT(root_entry_ == NULL);
-    ASSERT(retainers_count == 0);
-    return (root_entry_ = AddEntry(HeapEntry::kObject,
-                                   "",
-                                   HeapObjectsMap::kInternalRootObjectId,
-                                   0,
-                                   children_count,
-                                   retainers_count));
-  } else if (object == kGcRootsObject) {
-    ASSERT(gc_roots_entry_ == NULL);
-    return (gc_roots_entry_ = AddEntry(HeapEntry::kObject,
-                                       "(GC roots)",
-                                       HeapObjectsMap::kGcRootsObjectId,
-                                       0,
-                                       children_count,
-                                       retainers_count));
-  } else if (object->IsJSFunction()) {
-    JSFunction* func = JSFunction::cast(object);
-    SharedFunctionInfo* shared = func->shared();
-    return AddEntry(object,
-                    HeapEntry::kClosure,
-                    collection_->GetName(String::cast(shared->name())),
-                    children_count,
-                    retainers_count);
-  } else if (object->IsJSRegExp()) {
-    JSRegExp* re = JSRegExp::cast(object);
-    return AddEntry(object,
-                    HeapEntry::kRegExp,
-                    collection_->GetName(re->Pattern()),
-                    children_count,
-                    retainers_count);
-  } else if (object->IsJSObject()) {
-    return AddEntry(object,
-                    HeapEntry::kObject,
-                    collection_->GetName(GetConstructorNameForHeapProfile(
-                        JSObject::cast(object))),
-                    children_count,
-                    retainers_count);
-  } else if (object->IsString()) {
-    return AddEntry(object,
-                    HeapEntry::kString,
-                    collection_->GetName(String::cast(object)),
-                    children_count,
-                    retainers_count);
-  } else if (object->IsCode()) {
-    return AddEntry(object,
-                    HeapEntry::kCode,
-                    "",
-                    children_count,
-                    retainers_count);
-  } else if (object->IsSharedFunctionInfo()) {
-    SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
-    return AddEntry(object,
-                    HeapEntry::kCode,
-                    collection_->GetName(String::cast(shared->name())),
-                    children_count,
-                    retainers_count);
-  } else if (object->IsScript()) {
-    Script* script = Script::cast(object);
-    return AddEntry(object,
-                    HeapEntry::kCode,
-                    script->name()->IsString() ?
-                    collection_->GetName(String::cast(script->name())) : "",
-                    children_count,
-                    retainers_count);
-  } else if (object->IsFixedArray()) {
-    return AddEntry(object,
-                    HeapEntry::kArray,
-                    "",
-                    children_count,
-                    retainers_count);
-  } else if (object->IsHeapNumber()) {
-    return AddEntry(object,
-                    HeapEntry::kHeapNumber,
-                    "number",
-                    children_count,
-                    retainers_count);
-  }
-  return AddEntry(object,
-                  HeapEntry::kHidden,
-                  "system",
-                  children_count,
-                  retainers_count);
-}
-
-
 static void HeapEntryClearPaint(HeapEntry** entry_ptr) {
   (*entry_ptr)->clear_paint();
 }
@@ -1356,17 +1256,26 @@
 }
 
 
-HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
-                                  HeapEntry::Type type,
-                                  const char* name,
-                                  int children_count,
-                                  int retainers_count) {
-  return AddEntry(type,
-                  name,
-                  collection_->GetObjectId(object->address()),
-                  object->Size(),
-                  children_count,
-                  retainers_count);
+HeapEntry* HeapSnapshot::AddRootEntry(int children_count) {
+  ASSERT(root_entry_ == NULL);
+  return (root_entry_ = AddEntry(HeapEntry::kObject,
+                                 "",
+                                 HeapObjectsMap::kInternalRootObjectId,
+                                 0,
+                                 children_count,
+                                 0));
+}
+
+
+HeapEntry* HeapSnapshot::AddGcRootsEntry(int children_count,
+                                         int retainers_count) {
+  ASSERT(gc_roots_entry_ == NULL);
+  return (gc_roots_entry_ = AddEntry(HeapEntry::kObject,
+                                     "(GC roots)",
+                                     HeapObjectsMap::kGcRootsObjectId,
+                                     0,
+                                     children_count,
+                                     retainers_count));
 }
 
 
@@ -1619,7 +1528,7 @@
     reinterpret_cast<HeapEntry*>(1);
 
 HeapEntriesMap::HeapEntriesMap()
-    : entries_(HeapObjectsMatch),
+    : entries_(HeapThingsMatch),
       entries_count_(0),
       total_children_count_(0),
       total_retainers_count_(0) {
@@ -1633,8 +1542,23 @@
 }
 
 
-HeapEntry* HeapEntriesMap::Map(HeapObject* object) {
-  HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), false);
+void HeapEntriesMap::AllocateEntries() {
+  for (HashMap::Entry* p = entries_.Start();
+       p != NULL;
+       p = entries_.Next(p)) {
+    EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value);
+    entry_info->entry = entry_info->allocator->AllocateEntry(
+        p->key,
+        entry_info->children_count,
+        entry_info->retainers_count);
+    entry_info->children_count = 0;
+    entry_info->retainers_count = 0;
+  }
+}
+
+
+HeapEntry* HeapEntriesMap::Map(HeapThing thing) {
+  HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false);
   if (cache_entry != NULL) {
     EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value);
     return entry_info->entry;
@@ -1644,15 +1568,16 @@
 }
 
 
-void HeapEntriesMap::Pair(HeapObject* object, HeapEntry* entry) {
-  HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), true);
+void HeapEntriesMap::Pair(
+    HeapThing thing, HeapEntriesAllocator* allocator, HeapEntry* entry) {
+  HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), true);
   ASSERT(cache_entry->value == NULL);
-  cache_entry->value = new EntryInfo(entry);
+  cache_entry->value = new EntryInfo(entry, allocator);
   ++entries_count_;
 }
 
 
-void HeapEntriesMap::CountReference(HeapObject* from, HeapObject* to,
+void HeapEntriesMap::CountReference(HeapThing from, HeapThing to,
                                     int* prev_children_count,
                                     int* prev_retainers_count) {
   HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), false);
@@ -1675,7 +1600,7 @@
 
 
 HeapObjectsSet::HeapObjectsSet()
-    : entries_(HeapEntriesMap::HeapObjectsMatch) {
+    : entries_(HeapEntriesMap::HeapThingsMatch) {
 }
 
 
@@ -1704,206 +1629,144 @@
 }
 
 
-HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot,
-                                             v8::ActivityControl* control)
+HeapObject *const V8HeapExplorer::kInternalRootObject =
+    reinterpret_cast<HeapObject*>(1);
+HeapObject *const V8HeapExplorer::kGcRootsObject =
+    reinterpret_cast<HeapObject*>(2);
+
+
+V8HeapExplorer::V8HeapExplorer(
+    HeapSnapshot* snapshot,
+    SnapshottingProgressReportingInterface* progress)
     : snapshot_(snapshot),
-      control_(control),
-      collection_(snapshot->collection()),
+      collection_(snapshot_->collection()),
+      progress_(progress),
       filler_(NULL) {
 }
 
-class SnapshotCounter : public HeapSnapshotGenerator::SnapshotFillerInterface {
- public:
-  explicit SnapshotCounter(HeapEntriesMap* entries)
-      : entries_(entries) { }
-  HeapEntry* AddEntry(HeapObject* obj) {
-    entries_->Pair(obj, HeapEntriesMap::kHeapEntryPlaceholder);
-    return HeapEntriesMap::kHeapEntryPlaceholder;
-  }
-  void SetIndexedReference(HeapGraphEdge::Type,
-                           HeapObject* parent_obj,
-                           HeapEntry*,
-                           int,
-                           Object* child_obj,
-                           HeapEntry*) {
-    entries_->CountReference(parent_obj, HeapObject::cast(child_obj));
-  }
-  void SetNamedReference(HeapGraphEdge::Type,
-                         HeapObject* parent_obj,
-                         HeapEntry*,
-                         const char*,
-                         Object* child_obj,
-                         HeapEntry*) {
-    entries_->CountReference(parent_obj, HeapObject::cast(child_obj));
-  }
-  void SetRootShortcutReference(Object* child_obj, HeapEntry*) {
-    entries_->CountReference(
-        HeapSnapshot::kInternalRootObject, HeapObject::cast(child_obj));
-  }
-  void SetRootGcRootsReference() {
-    entries_->CountReference(
-        HeapSnapshot::kInternalRootObject, HeapSnapshot::kGcRootsObject);
-  }
-  void SetStrongRootReference(Object* child_obj, HeapEntry*) {
-    entries_->CountReference(
-        HeapSnapshot::kGcRootsObject, HeapObject::cast(child_obj));
-  }
- private:
-  HeapEntriesMap* entries_;
-};
 
-
-class SnapshotFiller : public HeapSnapshotGenerator::SnapshotFillerInterface {
- public:
-  explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
-      : snapshot_(snapshot),
-        collection_(snapshot->collection()),
-        entries_(entries) { }
-  HeapEntry* AddEntry(HeapObject* obj) {
-    UNREACHABLE();
-    return NULL;
-  }
-  void SetIndexedReference(HeapGraphEdge::Type type,
-                           HeapObject* parent_obj,
-                           HeapEntry* parent_entry,
-                           int index,
-                           Object* child_obj,
-                           HeapEntry* child_entry) {
-    int child_index, retainer_index;
-    entries_->CountReference(parent_obj,
-                             HeapObject::cast(child_obj),
-                             &child_index,
-                             &retainer_index);
-    parent_entry->SetIndexedReference(
-        type, child_index, index, child_entry, retainer_index);
-  }
-  void SetNamedReference(HeapGraphEdge::Type type,
-                         HeapObject* parent_obj,
-                         HeapEntry* parent_entry,
-                         const char* reference_name,
-                         Object* child_obj,
-                         HeapEntry* child_entry) {
-    int child_index, retainer_index;
-    entries_->CountReference(parent_obj, HeapObject::cast(child_obj),
-                             &child_index, &retainer_index);
-    parent_entry->SetNamedReference(type,
-                              child_index,
-                              reference_name,
-                              child_entry,
-                              retainer_index);
-  }
-  void SetRootGcRootsReference() {
-    int child_index, retainer_index;
-    entries_->CountReference(HeapSnapshot::kInternalRootObject,
-                             HeapSnapshot::kGcRootsObject,
-                             &child_index,
-                             &retainer_index);
-    snapshot_->root()->SetIndexedReference(HeapGraphEdge::kElement,
-                                           child_index,
-                                           child_index + 1,
-                                           snapshot_->gc_roots(),
-                                           retainer_index);
-  }
-  void SetRootShortcutReference(Object* child_obj,
-                                HeapEntry* child_entry) {
-    int child_index, retainer_index;
-    entries_->CountReference(HeapSnapshot::kInternalRootObject,
-                             HeapObject::cast(child_obj),
-                             &child_index,
-                             &retainer_index);
-    snapshot_->root()->SetNamedReference(HeapGraphEdge::kShortcut,
-                                         child_index,
-                                         collection_->GetName(child_index + 1),
-                                         child_entry,
-                                         retainer_index);
-  }
-  void SetStrongRootReference(Object* child_obj,
-                              HeapEntry* child_entry) {
-    int child_index, retainer_index;
-    entries_->CountReference(HeapSnapshot::kGcRootsObject,
-                             HeapObject::cast(child_obj),
-                             &child_index,
-                             &retainer_index);
-    snapshot_->gc_roots()->SetIndexedReference(HeapGraphEdge::kElement,
-                                               child_index,
-                                               child_index + 1,
-                                               child_entry,
-                                               retainer_index);
-  }
- private:
-  HeapSnapshot* snapshot_;
-  HeapSnapshotsCollection* collection_;
-  HeapEntriesMap* entries_;
-};
-
-class SnapshotAllocator {
- public:
-  explicit SnapshotAllocator(HeapSnapshot* snapshot)
-      : snapshot_(snapshot) { }
-  HeapEntry* GetEntry(
-      HeapObject* obj, int children_count, int retainers_count) {
-    HeapEntry* entry =
-        snapshot_->AddEntry(obj, children_count, retainers_count);
-    ASSERT(entry != NULL);
-    return entry;
-  }
- private:
-  HeapSnapshot* snapshot_;
-};
-
-class RootsReferencesExtractor : public ObjectVisitor {
- public:
-  explicit RootsReferencesExtractor(HeapSnapshotGenerator* generator)
-      : generator_(generator) {
-  }
-  void VisitPointers(Object** start, Object** end) {
-    for (Object** p = start; p < end; p++) generator_->SetGcRootsReference(*p);
-  }
- private:
-  HeapSnapshotGenerator* generator_;
-};
-
-
-bool HeapSnapshotGenerator::GenerateSnapshot() {
-  AssertNoAllocation no_alloc;
-
-  SetProgressTotal(4);  // 2 passes + dominators + sizes.
-
-  // Pass 1. Iterate heap contents to count entries and references.
-  if (!CountEntriesAndReferences()) return false;
-
-  // Allocate and fill entries in the snapshot, allocate references.
-  snapshot_->AllocateEntries(entries_.entries_count(),
-                             entries_.total_children_count(),
-                             entries_.total_retainers_count());
-  SnapshotAllocator allocator(snapshot_);
-  entries_.UpdateEntries(&allocator);
-
-  // Pass 2. Fill references.
-  if (!FillReferences()) return false;
-
-  if (!SetEntriesDominators()) return false;
-  if (!ApproximateRetainedSizes()) return false;
-
-  progress_counter_ = progress_total_;
-  if (!ReportProgress(true)) return false;
-  return true;
+V8HeapExplorer::~V8HeapExplorer() {
 }
 
 
-HeapEntry* HeapSnapshotGenerator::GetEntry(Object* obj) {
-  if (!obj->IsHeapObject()) return NULL;
-  HeapObject* object = HeapObject::cast(obj);
-  HeapEntry* entry = entries_.Map(object);
-  // A new entry.
-  if (entry == NULL) entry = filler_->AddEntry(object);
-  return entry;
+HeapEntry* V8HeapExplorer::AllocateEntry(
+    HeapThing ptr, int children_count, int retainers_count) {
+  return AddEntry(
+      reinterpret_cast<HeapObject*>(ptr), children_count, retainers_count);
+}
+
+
+HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
+                                    int children_count,
+                                    int retainers_count) {
+  if (object == kInternalRootObject) {
+    ASSERT(retainers_count == 0);
+    return snapshot_->AddRootEntry(children_count);
+  } else if (object == kGcRootsObject) {
+    return snapshot_->AddGcRootsEntry(children_count, retainers_count);
+  } else if (object->IsJSFunction()) {
+    JSFunction* func = JSFunction::cast(object);
+    SharedFunctionInfo* shared = func->shared();
+    return AddEntry(object,
+                    HeapEntry::kClosure,
+                    collection_->GetName(String::cast(shared->name())),
+                    children_count,
+                    retainers_count);
+  } else if (object->IsJSRegExp()) {
+    JSRegExp* re = JSRegExp::cast(object);
+    return AddEntry(object,
+                    HeapEntry::kRegExp,
+                    collection_->GetName(re->Pattern()),
+                    children_count,
+                    retainers_count);
+  } else if (object->IsJSObject()) {
+    return AddEntry(object,
+                    HeapEntry::kObject,
+                    collection_->GetName(GetConstructorNameForHeapProfile(
+                        JSObject::cast(object))),
+                    children_count,
+                    retainers_count);
+  } else if (object->IsString()) {
+    return AddEntry(object,
+                    HeapEntry::kString,
+                    collection_->GetName(String::cast(object)),
+                    children_count,
+                    retainers_count);
+  } else if (object->IsCode()) {
+    return AddEntry(object,
+                    HeapEntry::kCode,
+                    "",
+                    children_count,
+                    retainers_count);
+  } else if (object->IsSharedFunctionInfo()) {
+    SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
+    return AddEntry(object,
+                    HeapEntry::kCode,
+                    collection_->GetName(String::cast(shared->name())),
+                    children_count,
+                    retainers_count);
+  } else if (object->IsScript()) {
+    Script* script = Script::cast(object);
+    return AddEntry(object,
+                    HeapEntry::kCode,
+                    script->name()->IsString() ?
+                    collection_->GetName(String::cast(script->name())) : "",
+                    children_count,
+                    retainers_count);
+  } else if (object->IsFixedArray()) {
+    return AddEntry(object,
+                    HeapEntry::kArray,
+                    "",
+                    children_count,
+                    retainers_count);
+  } else if (object->IsHeapNumber()) {
+    return AddEntry(object,
+                    HeapEntry::kHeapNumber,
+                    "number",
+                    children_count,
+                    retainers_count);
+  }
+  return AddEntry(object,
+                  HeapEntry::kHidden,
+                  "system",
+                  children_count,
+                  retainers_count);
+}
+
+
+HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
+                                    HeapEntry::Type type,
+                                    const char* name,
+                                    int children_count,
+                                    int retainers_count) {
+  return snapshot_->AddEntry(type,
+                             name,
+                             collection_->GetObjectId(object->address()),
+                             object->Size(),
+                             children_count,
+                             retainers_count);
+}
+
+
+void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) {
+  filler->AddEntry(kInternalRootObject);
+  filler->AddEntry(kGcRootsObject);
+}
+
+
+int V8HeapExplorer::EstimateObjectsCount() {
+  HeapIterator iterator(HeapIterator::kFilterUnreachable);
+  int objects_count = 0;
+  for (HeapObject* obj = iterator.next();
+       obj != NULL;
+       obj = iterator.next(), ++objects_count) {}
+  return objects_count;
 }
 
 
 class IndexedReferencesExtractor : public ObjectVisitor {
  public:
-  IndexedReferencesExtractor(HeapSnapshotGenerator* generator,
+  IndexedReferencesExtractor(V8HeapExplorer* generator,
                              HeapObject* parent_obj,
                              HeapEntry* parent_entry,
                              HeapObjectsSet* known_references = NULL)
@@ -1921,7 +1784,7 @@
     }
   }
  private:
-  HeapSnapshotGenerator* generator_;
+  V8HeapExplorer* generator_;
   HeapObject* parent_obj_;
   HeapEntry* parent_;
   HeapObjectsSet* known_references_;
@@ -1929,7 +1792,7 @@
 };
 
 
-void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) {
+void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
   HeapEntry* entry = GetEntry(obj);
   if (entry == NULL) return;  // No interest in this object.
 
@@ -1973,8 +1836,8 @@
 }
 
 
-void HeapSnapshotGenerator::ExtractClosureReferences(JSObject* js_obj,
-                                                     HeapEntry* entry) {
+void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj,
+                                              HeapEntry* entry) {
   if (js_obj->IsJSFunction()) {
     HandleScope hs;
     JSFunction* func = JSFunction::cast(js_obj);
@@ -1996,8 +1859,8 @@
 }
 
 
-void HeapSnapshotGenerator::ExtractPropertyReferences(JSObject* js_obj,
-                                                      HeapEntry* entry) {
+void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj,
+                                               HeapEntry* entry) {
   if (js_obj->HasFastProperties()) {
     DescriptorArray* descs = js_obj->map()->instance_descriptors();
     for (int i = 0; i < descs->number_of_descriptors(); i++) {
@@ -2038,8 +1901,8 @@
 }
 
 
-void HeapSnapshotGenerator::ExtractElementReferences(JSObject* js_obj,
-                                                     HeapEntry* entry) {
+void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj,
+                                              HeapEntry* entry) {
   if (js_obj->HasFastElements()) {
     FixedArray* elements = FixedArray::cast(js_obj->elements());
     int length = js_obj->IsJSArray() ?
@@ -2065,8 +1928,8 @@
 }
 
 
-void HeapSnapshotGenerator::ExtractInternalReferences(JSObject* js_obj,
-                                                      HeapEntry* entry) {
+void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj,
+                                               HeapEntry* entry) {
   int length = js_obj->GetInternalFieldCount();
   for (int i = 0; i < length; ++i) {
     Object* o = js_obj->GetInternalField(i);
@@ -2075,10 +1938,55 @@
 }
 
 
-void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj,
-                                                HeapEntry* parent_entry,
-                                                String* reference_name,
-                                                Object* child_obj) {
+HeapEntry* V8HeapExplorer::GetEntry(Object* obj) {
+  if (!obj->IsHeapObject()) return NULL;
+  return filler_->FindOrAddEntry(obj);
+}
+
+
+class RootsReferencesExtractor : public ObjectVisitor {
+ public:
+  explicit RootsReferencesExtractor(V8HeapExplorer* explorer)
+      : explorer_(explorer) {
+  }
+  void VisitPointers(Object** start, Object** end) {
+    for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p);
+  }
+ private:
+  V8HeapExplorer* explorer_;
+};
+
+
+bool V8HeapExplorer::IterateAndExtractReferences(
+    SnapshotFillerInterface* filler) {
+  filler_ = filler;
+  HeapIterator iterator(HeapIterator::kFilterUnreachable);
+  bool interrupted = false;
+  // Heap iteration with filtering must be finished in any case.
+  for (HeapObject* obj = iterator.next();
+       obj != NULL;
+       obj = iterator.next(), progress_->ProgressStep()) {
+    if (!interrupted) {
+      ExtractReferences(obj);
+      if (!progress_->ProgressReport(false)) interrupted = true;
+    }
+  }
+  if (interrupted) {
+    filler_ = NULL;
+    return false;
+  }
+  SetRootGcRootsReference();
+  RootsReferencesExtractor extractor(this);
+  Heap::IterateRoots(&extractor, VISIT_ALL);
+  filler_ = NULL;
+  return progress_->ProgressReport(false);
+}
+
+
+void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj,
+                                         HeapEntry* parent_entry,
+                                         String* reference_name,
+                                         Object* child_obj) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
     filler_->SetNamedReference(HeapGraphEdge::kContextVariable,
@@ -2092,10 +2000,10 @@
 }
 
 
-void HeapSnapshotGenerator::SetElementReference(HeapObject* parent_obj,
-                                                HeapEntry* parent_entry,
-                                                int index,
-                                                Object* child_obj) {
+void V8HeapExplorer::SetElementReference(HeapObject* parent_obj,
+                                         HeapEntry* parent_entry,
+                                         int index,
+                                         Object* child_obj) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
     filler_->SetIndexedReference(HeapGraphEdge::kElement,
@@ -2109,10 +2017,10 @@
 }
 
 
-void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
-                                                 HeapEntry* parent_entry,
-                                                 const char* reference_name,
-                                                 Object* child_obj) {
+void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
+                                          HeapEntry* parent_entry,
+                                          const char* reference_name,
+                                          Object* child_obj) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
     filler_->SetNamedReference(HeapGraphEdge::kInternal,
@@ -2126,10 +2034,10 @@
 }
 
 
-void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
-                                                 HeapEntry* parent_entry,
-                                                 int index,
-                                                 Object* child_obj) {
+void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
+                                          HeapEntry* parent_entry,
+                                          int index,
+                                          Object* child_obj) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
     filler_->SetNamedReference(HeapGraphEdge::kInternal,
@@ -2143,10 +2051,10 @@
 }
 
 
-void HeapSnapshotGenerator::SetHiddenReference(HeapObject* parent_obj,
-                                               HeapEntry* parent_entry,
-                                               int index,
-                                               Object* child_obj) {
+void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj,
+                                        HeapEntry* parent_entry,
+                                        int index,
+                                        Object* child_obj) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
     filler_->SetIndexedReference(HeapGraphEdge::kHidden,
@@ -2159,10 +2067,10 @@
 }
 
 
-void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj,
-                                                 HeapEntry* parent_entry,
-                                                 String* reference_name,
-                                                 Object* child_obj) {
+void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
+                                          HeapEntry* parent_entry,
+                                          String* reference_name,
+                                          Object* child_obj) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
     HeapGraphEdge::Type type = reference_name->length() > 0 ?
@@ -2178,7 +2086,7 @@
 }
 
 
-void HeapSnapshotGenerator::SetPropertyShortcutReference(
+void V8HeapExplorer::SetPropertyShortcutReference(
     HeapObject* parent_obj,
     HeapEntry* parent_entry,
     String* reference_name,
@@ -2195,52 +2103,221 @@
 }
 
 
-void HeapSnapshotGenerator::SetRootGcRootsReference() {
-  filler_->SetRootGcRootsReference();
+void V8HeapExplorer::SetRootGcRootsReference() {
+  filler_->SetIndexedAutoIndexReference(
+      HeapGraphEdge::kElement,
+      kInternalRootObject, snapshot_->root(),
+      kGcRootsObject, snapshot_->gc_roots());
 }
 
 
-void HeapSnapshotGenerator::SetRootShortcutReference(Object* child_obj) {
+void V8HeapExplorer::SetRootShortcutReference(Object* child_obj) {
   HeapEntry* child_entry = GetEntry(child_obj);
   ASSERT(child_entry != NULL);
-  filler_->SetRootShortcutReference(child_obj, child_entry);
+  filler_->SetNamedAutoIndexReference(
+      HeapGraphEdge::kShortcut,
+      kInternalRootObject, snapshot_->root(),
+      child_obj, child_entry);
 }
 
 
-void HeapSnapshotGenerator::SetGcRootsReference(Object* child_obj) {
+void V8HeapExplorer::SetGcRootsReference(Object* child_obj) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
-    filler_->SetStrongRootReference(child_obj, child_entry);
+    filler_->SetIndexedAutoIndexReference(
+        HeapGraphEdge::kElement,
+        kGcRootsObject, snapshot_->gc_roots(),
+        child_obj, child_entry);
   }
 }
 
 
+HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot,
+                                             v8::ActivityControl* control)
+    : snapshot_(snapshot),
+      control_(control),
+      v8_heap_explorer_(snapshot_, this) {
+}
+
+
+class SnapshotCounter : public SnapshotFillerInterface {
+ public:
+  SnapshotCounter(HeapEntriesAllocator* allocator, HeapEntriesMap* entries)
+      : allocator_(allocator), entries_(entries) { }
+  HeapEntry* AddEntry(HeapThing ptr) {
+    entries_->Pair(ptr, allocator_, HeapEntriesMap::kHeapEntryPlaceholder);
+    return HeapEntriesMap::kHeapEntryPlaceholder;
+  }
+  HeapEntry* FindOrAddEntry(HeapThing ptr) {
+    HeapEntry* entry = entries_->Map(ptr);
+    return entry != NULL ? entry : AddEntry(ptr);
+  }
+  void SetIndexedReference(HeapGraphEdge::Type,
+                           HeapThing parent_ptr,
+                           HeapEntry*,
+                           int,
+                           HeapThing child_ptr,
+                           HeapEntry*) {
+    entries_->CountReference(parent_ptr, child_ptr);
+  }
+  void SetIndexedAutoIndexReference(HeapGraphEdge::Type,
+                                    HeapThing parent_ptr,
+                                    HeapEntry*,
+                                    HeapThing child_ptr,
+                                    HeapEntry*) {
+    entries_->CountReference(parent_ptr, child_ptr);
+  }
+  void SetNamedReference(HeapGraphEdge::Type,
+                         HeapThing parent_ptr,
+                         HeapEntry*,
+                         const char*,
+                         HeapThing child_ptr,
+                         HeapEntry*) {
+    entries_->CountReference(parent_ptr, child_ptr);
+  }
+  void SetNamedAutoIndexReference(HeapGraphEdge::Type,
+                                  HeapThing parent_ptr,
+                                  HeapEntry*,
+                                  HeapThing child_ptr,
+                                  HeapEntry*) {
+    entries_->CountReference(parent_ptr, child_ptr);
+  }
+ private:
+  HeapEntriesAllocator* allocator_;
+  HeapEntriesMap* entries_;
+};
+
+
+class SnapshotFiller : public SnapshotFillerInterface {
+ public:
+  explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
+      : snapshot_(snapshot),
+        collection_(snapshot->collection()),
+        entries_(entries) { }
+  HeapEntry* AddEntry(HeapThing ptr) {
+    UNREACHABLE();
+    return NULL;
+  }
+  HeapEntry* FindOrAddEntry(HeapThing ptr) {
+    HeapEntry* entry = entries_->Map(ptr);
+    return entry != NULL ? entry : AddEntry(ptr);
+  }
+  void SetIndexedReference(HeapGraphEdge::Type type,
+                           HeapThing parent_ptr,
+                           HeapEntry* parent_entry,
+                           int index,
+                           HeapThing child_ptr,
+                           HeapEntry* child_entry) {
+    int child_index, retainer_index;
+    entries_->CountReference(
+        parent_ptr, child_ptr, &child_index, &retainer_index);
+    parent_entry->SetIndexedReference(
+        type, child_index, index, child_entry, retainer_index);
+  }
+  void SetIndexedAutoIndexReference(HeapGraphEdge::Type type,
+                                    HeapThing parent_ptr,
+                                    HeapEntry* parent_entry,
+                                    HeapThing child_ptr,
+                                    HeapEntry* child_entry) {
+    int child_index, retainer_index;
+    entries_->CountReference(
+        parent_ptr, child_ptr, &child_index, &retainer_index);
+    parent_entry->SetIndexedReference(
+        type, child_index, child_index + 1, child_entry, retainer_index);
+  }
+  void SetNamedReference(HeapGraphEdge::Type type,
+                         HeapThing parent_ptr,
+                         HeapEntry* parent_entry,
+                         const char* reference_name,
+                         HeapThing child_ptr,
+                         HeapEntry* child_entry) {
+    int child_index, retainer_index;
+    entries_->CountReference(
+        parent_ptr, child_ptr, &child_index, &retainer_index);
+    parent_entry->SetNamedReference(
+        type, child_index, reference_name, child_entry, retainer_index);
+  }
+  void SetNamedAutoIndexReference(HeapGraphEdge::Type type,
+                                  HeapThing parent_ptr,
+                                  HeapEntry* parent_entry,
+                                  HeapThing child_ptr,
+                                  HeapEntry* child_entry) {
+    int child_index, retainer_index;
+    entries_->CountReference(
+        parent_ptr, child_ptr, &child_index, &retainer_index);
+    parent_entry->SetNamedReference(type,
+                              child_index,
+                              collection_->GetName(child_index + 1),
+                              child_entry,
+                              retainer_index);
+  }
+ private:
+  HeapSnapshot* snapshot_;
+  HeapSnapshotsCollection* collection_;
+  HeapEntriesMap* entries_;
+};
+
+
+bool HeapSnapshotGenerator::GenerateSnapshot() {
+  AssertNoAllocation no_alloc;
+
+  SetProgressTotal(4);  // 2 passes + dominators + sizes.
+
+  // Pass 1. Iterate heap contents to count entries and references.
+  if (!CountEntriesAndReferences()) return false;
+
+  // Allocate and fill entries in the snapshot, allocate references.
+  snapshot_->AllocateEntries(entries_.entries_count(),
+                             entries_.total_children_count(),
+                             entries_.total_retainers_count());
+  entries_.AllocateEntries();
+
+  // Pass 2. Fill references.
+  if (!FillReferences()) return false;
+
+  if (!SetEntriesDominators()) return false;
+  if (!ApproximateRetainedSizes()) return false;
+
+  progress_counter_ = progress_total_;
+  if (!ProgressReport(true)) return false;
+  return true;
+}
+
+
+void HeapSnapshotGenerator::ProgressStep() {
+  ++progress_counter_;
+}
+
+
+bool HeapSnapshotGenerator::ProgressReport(bool force) {
+  const int kProgressReportGranularity = 10000;
+  if (control_ != NULL
+      && (force || progress_counter_ % kProgressReportGranularity == 0)) {
+      return
+          control_->ReportProgressValue(progress_counter_, progress_total_) ==
+          v8::ActivityControl::kContinue;
+  }
+  return true;
+}
+
+
 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) {
   if (control_ == NULL) return;
-
-  HeapIterator iterator(HeapIterator::kFilterUnreachable);
-  int objects_count = 0;
-  for (HeapObject* obj = iterator.next();
-       obj != NULL;
-       obj = iterator.next(), ++objects_count) {}
-  progress_total_ = objects_count * iterations_count;
+  progress_total_ = v8_heap_explorer_.EstimateObjectsCount() * iterations_count;
   progress_counter_ = 0;
 }
 
 
 bool HeapSnapshotGenerator::CountEntriesAndReferences() {
-  SnapshotCounter counter(&entries_);
-  filler_ = &counter;
-  filler_->AddEntry(HeapSnapshot::kInternalRootObject);
-  filler_->AddEntry(HeapSnapshot::kGcRootsObject);
-  return IterateAndExtractReferences();
+  SnapshotCounter counter(&v8_heap_explorer_, &entries_);
+  v8_heap_explorer_.AddRootEntries(&counter);
+  return v8_heap_explorer_.IterateAndExtractReferences(&counter);
 }
 
 
 bool HeapSnapshotGenerator::FillReferences() {
   SnapshotFiller filler(snapshot_, &entries_);
-  filler_ = &filler;
-  return IterateAndExtractReferences();
+  return v8_heap_explorer_.IterateAndExtractReferences(&filler);
 }
 
 
@@ -2326,7 +2403,7 @@
     int remaining = entries_length - changed;
     if (remaining < 0) remaining = 0;
     progress_counter_ = base_progress_counter + remaining;
-    if (!ReportProgress(true)) return false;
+    if (!ProgressReport(true)) return false;
   }
   return true;
 }
@@ -2356,7 +2433,7 @@
   }
   for (int i = 0;
        i < snapshot_->entries()->length();
-       ++i, IncProgressCounter()) {
+       ++i, ProgressStep()) {
     HeapEntry* entry = snapshot_->entries()->at(i);
     int entry_size = entry->self_size();
     for (HeapEntry* dominator = entry->dominator();
@@ -2364,32 +2441,12 @@
          entry = dominator, dominator = entry->dominator()) {
       dominator->add_retained_size(entry_size);
     }
-    if (!ReportProgress()) return false;
+    if (!ProgressReport()) return false;
   }
   return true;
 }
 
 
-bool HeapSnapshotGenerator::IterateAndExtractReferences() {
-  HeapIterator iterator(HeapIterator::kFilterUnreachable);
-  bool interrupted = false;
-  // Heap iteration with filtering must be finished in any case.
-  for (HeapObject* obj = iterator.next();
-       obj != NULL;
-       obj = iterator.next(), IncProgressCounter()) {
-    if (!interrupted) {
-      ExtractReferences(obj);
-      if (!ReportProgress()) interrupted = true;
-    }
-  }
-  if (interrupted) return false;
-  SetRootGcRootsReference();
-  RootsReferencesExtractor extractor(this);
-  Heap::IterateRoots(&extractor, VISIT_ALL);
-  return ReportProgress();
-}
-
-
 void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) {
   raw_additions_root_ =
       NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0));
diff --git a/src/profile-generator.h b/src/profile-generator.h
index cacd27e..4762eb6 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -88,7 +88,6 @@
 
 class CodeEntry {
  public:
-  explicit INLINE(CodeEntry(int security_token_id));
   // CodeEntry doesn't own name strings, just references them.
   INLINE(CodeEntry(Logger::LogEventsAndTags tag,
                    const char* name_prefix,
@@ -103,6 +102,8 @@
   INLINE(const char* name() const) { return name_; }
   INLINE(const char* resource_name() const) { return resource_name_; }
   INLINE(int line_number() const) { return line_number_; }
+  INLINE(int shared_id() const) { return shared_id_; }
+  INLINE(void set_shared_id(int shared_id)) { shared_id_ = shared_id; }
   INLINE(int security_token_id() const) { return security_token_id_; }
 
   INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag));
@@ -119,6 +120,7 @@
   const char* name_;
   const char* resource_name_;
   int line_number_;
+  int shared_id_;
   int security_token_id_;
 
   DISALLOW_COPY_AND_ASSIGN(CodeEntry);
@@ -234,12 +236,12 @@
 
 class CodeMap {
  public:
-  CodeMap() { }
+  CodeMap() : next_sfi_tag_(1) { }
   INLINE(void AddCode(Address addr, CodeEntry* entry, unsigned size));
   INLINE(void MoveCode(Address from, Address to));
   INLINE(void DeleteCode(Address addr));
-  void AddAlias(Address start, CodeEntry* entry, Address code_start);
   CodeEntry* FindEntry(Address addr);
+  int GetSFITag(Address addr);
 
   void Print();
 
@@ -267,7 +269,11 @@
     void Call(const Address& key, const CodeEntryInfo& value);
   };
 
+  // Fake CodeEntry pointer to distinguish SFI entries.
+  static CodeEntry* const kSfiCodeEntry;
+
   CodeTree tree_;
+  int next_sfi_tag_;
 
   DISALLOW_COPY_AND_ASSIGN(CodeMap);
 };
@@ -675,14 +681,14 @@
 
   void AllocateEntries(
       int entries_count, int children_count, int retainers_count);
-  HeapEntry* AddEntry(
-      HeapObject* object, int children_count, int retainers_count);
   HeapEntry* AddEntry(HeapEntry::Type type,
                       const char* name,
                       uint64_t id,
                       int size,
                       int children_count,
                       int retainers_count);
+  HeapEntry* AddRootEntry(int children_count);
+  HeapEntry* AddGcRootsEntry(int children_count, int retainers_count);
   void ClearPaint();
   HeapSnapshotsDiff* CompareWith(HeapSnapshot* snapshot);
   HeapEntry* GetEntryById(uint64_t id);
@@ -695,15 +701,7 @@
   void Print(int max_depth);
   void PrintEntriesSize();
 
-  static HeapObject* const kInternalRootObject;
-  static HeapObject* const kGcRootsObject;
-
  private:
-  HeapEntry* AddEntry(HeapObject* object,
-                      HeapEntry::Type type,
-                      const char* name,
-                      int children_count,
-                      int retainers_count);
   HeapEntry* GetNextEntryToInit();
 
   HeapSnapshotsCollection* collection_;
@@ -867,6 +865,20 @@
 };
 
 
+// A typedef for referencing anything that can be snapshotted living
+// in any kind of heap memory.
+typedef void* HeapThing;
+
+
+// An interface that creates HeapEntries by HeapThings.
+class HeapEntriesAllocator {
+ public:
+  virtual ~HeapEntriesAllocator() { }
+  virtual HeapEntry* AllocateEntry(
+      HeapThing ptr, int children_count, int retainers_count) = 0;
+};
+
+
 // The HeapEntriesMap instance is used to track a mapping between
 // real heap objects and their representations in heap snapshots.
 class HeapEntriesMap {
@@ -874,13 +886,12 @@
   HeapEntriesMap();
   ~HeapEntriesMap();
 
-  HeapEntry* Map(HeapObject* object);
-  void Pair(HeapObject* object, HeapEntry* entry);
-  void CountReference(HeapObject* from, HeapObject* to,
+  void AllocateEntries();
+  HeapEntry* Map(HeapThing thing);
+  void Pair(HeapThing thing, HeapEntriesAllocator* allocator, HeapEntry* entry);
+  void CountReference(HeapThing from, HeapThing to,
                       int* prev_children_count = NULL,
                       int* prev_retainers_count = NULL);
-  template<class Visitor>
-  void UpdateEntries(Visitor* visitor);
 
   int entries_count() { return entries_count_; }
   int total_children_count() { return total_children_count_; }
@@ -890,18 +901,25 @@
 
  private:
   struct EntryInfo {
-    explicit EntryInfo(HeapEntry* entry)
-        : entry(entry), children_count(0), retainers_count(0) { }
+    EntryInfo(HeapEntry* entry, HeapEntriesAllocator* allocator)
+        : entry(entry),
+          allocator(allocator),
+          children_count(0),
+          retainers_count(0) {
+    }
     HeapEntry* entry;
+    HeapEntriesAllocator* allocator;
     int children_count;
     int retainers_count;
   };
 
-  static uint32_t Hash(HeapObject* object) {
+  static uint32_t Hash(HeapThing thing) {
     return ComputeIntegerHash(
-        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object)));
+        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(thing)));
   }
-  static bool HeapObjectsMatch(void* key1, void* key2) { return key1 == key2; }
+  static bool HeapThingsMatch(HeapThing key1, HeapThing key2) {
+    return key1 == key2;
+  }
 
   HashMap entries_;
   int entries_count_;
@@ -928,52 +946,70 @@
 };
 
 
-class HeapSnapshotGenerator {
+// An interface used to populate a snapshot with nodes and edges.
+class SnapshotFillerInterface {
  public:
-  class SnapshotFillerInterface {
-   public:
-    virtual ~SnapshotFillerInterface() { }
-    virtual HeapEntry* AddEntry(HeapObject* obj) = 0;
-    virtual void SetIndexedReference(HeapGraphEdge::Type type,
-                                     HeapObject* parent_obj,
-                                     HeapEntry* parent_entry,
-                                     int index,
-                                     Object* child_obj,
-                                     HeapEntry* child_entry) = 0;
-    virtual void SetNamedReference(HeapGraphEdge::Type type,
-                                   HeapObject* parent_obj,
+  virtual ~SnapshotFillerInterface() { }
+  virtual HeapEntry* AddEntry(HeapThing ptr) = 0;
+  virtual HeapEntry* FindOrAddEntry(HeapThing ptr) = 0;
+  virtual void SetIndexedReference(HeapGraphEdge::Type type,
+                                   HeapThing parent_ptr,
                                    HeapEntry* parent_entry,
-                                   const char* reference_name,
-                                   Object* child_obj,
+                                   int index,
+                                   HeapThing child_ptr,
                                    HeapEntry* child_entry) = 0;
-    virtual void SetRootGcRootsReference() = 0;
-    virtual void SetRootShortcutReference(Object* child_obj,
+  virtual void SetIndexedAutoIndexReference(HeapGraphEdge::Type type,
+                                            HeapThing parent_ptr,
+                                            HeapEntry* parent_entry,
+                                            HeapThing child_ptr,
+                                            HeapEntry* child_entry) = 0;
+  virtual void SetNamedReference(HeapGraphEdge::Type type,
+                                 HeapThing parent_ptr,
+                                 HeapEntry* parent_entry,
+                                 const char* reference_name,
+                                 HeapThing child_ptr,
+                                 HeapEntry* child_entry) = 0;
+  virtual void SetNamedAutoIndexReference(HeapGraphEdge::Type type,
+                                          HeapThing parent_ptr,
+                                          HeapEntry* parent_entry,
+                                          HeapThing child_ptr,
                                           HeapEntry* child_entry) = 0;
-    virtual void SetStrongRootReference(Object* child_obj,
-                                        HeapEntry* child_entry) = 0;
-  };
+};
 
-  HeapSnapshotGenerator(HeapSnapshot* snapshot,
-                        v8::ActivityControl* control);
-  bool GenerateSnapshot();
+
+class SnapshottingProgressReportingInterface {
+ public:
+  virtual ~SnapshottingProgressReportingInterface() { }
+  virtual void ProgressStep() = 0;
+  virtual bool ProgressReport(bool force) = 0;
+};
+
+
+// An implementation of V8 heap graph extractor.
+class V8HeapExplorer : public HeapEntriesAllocator {
+ public:
+  V8HeapExplorer(HeapSnapshot* snapshot,
+                 SnapshottingProgressReportingInterface* progress);
+  ~V8HeapExplorer();
+  virtual HeapEntry* AllocateEntry(
+      HeapThing ptr, int children_count, int retainers_count);
+  void AddRootEntries(SnapshotFillerInterface* filler);
+  int EstimateObjectsCount();
+  bool IterateAndExtractReferences(SnapshotFillerInterface* filler);
 
  private:
-  bool ApproximateRetainedSizes();
-  bool BuildDominatorTree(const Vector<HeapEntry*>& entries,
-                          Vector<HeapEntry*>* dominators);
-  bool CountEntriesAndReferences();
-  HeapEntry* GetEntry(Object* obj);
-  void IncProgressCounter() { ++progress_counter_; }
+  HeapEntry* AddEntry(
+      HeapObject* object, int children_count, int retainers_count);
+  HeapEntry* AddEntry(HeapObject* object,
+                      HeapEntry::Type type,
+                      const char* name,
+                      int children_count,
+                      int retainers_count);
   void ExtractReferences(HeapObject* obj);
   void ExtractClosureReferences(JSObject* js_obj, HeapEntry* entry);
   void ExtractPropertyReferences(JSObject* js_obj, HeapEntry* entry);
   void ExtractElementReferences(JSObject* js_obj, HeapEntry* entry);
   void ExtractInternalReferences(JSObject* js_obj, HeapEntry* entry);
-  bool FillReferences();
-  void FillReversePostorderIndexes(Vector<HeapEntry*>* entries);
-  bool IterateAndExtractReferences();
-  inline bool ReportProgress(bool force = false);
-  bool SetEntriesDominators();
   void SetClosureReference(HeapObject* parent_obj,
                            HeapEntry* parent,
                            String* reference_name,
@@ -1005,24 +1041,54 @@
   void SetRootShortcutReference(Object* child);
   void SetRootGcRootsReference();
   void SetGcRootsReference(Object* child);
+
+  HeapEntry* GetEntry(Object* obj);
+
+  HeapSnapshot* snapshot_;
+  HeapSnapshotsCollection* collection_;
+  SnapshottingProgressReportingInterface* progress_;
+  // Used during references extraction to mark heap objects that
+  // are references via non-hidden properties.
+  HeapObjectsSet known_references_;
+  SnapshotFillerInterface* filler_;
+
+  static HeapObject* const kInternalRootObject;
+  static HeapObject* const kGcRootsObject;
+
+  friend class IndexedReferencesExtractor;
+  friend class RootsReferencesExtractor;
+
+  DISALLOW_COPY_AND_ASSIGN(V8HeapExplorer);
+};
+
+
+class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface {
+ public:
+  HeapSnapshotGenerator(HeapSnapshot* snapshot,
+                        v8::ActivityControl* control);
+  bool GenerateSnapshot();
+
+ private:
+  bool ApproximateRetainedSizes();
+  bool BuildDominatorTree(const Vector<HeapEntry*>& entries,
+                          Vector<HeapEntry*>* dominators);
+  bool CountEntriesAndReferences();
+  bool FillReferences();
+  void FillReversePostorderIndexes(Vector<HeapEntry*>* entries);
+  void ProgressStep();
+  bool ProgressReport(bool force = false);
+  bool SetEntriesDominators();
   void SetProgressTotal(int iterations_count);
 
   HeapSnapshot* snapshot_;
   v8::ActivityControl* control_;
-  HeapSnapshotsCollection* collection_;
-  // Mapping from HeapObject* pointers to HeapEntry* pointers.
+  V8HeapExplorer v8_heap_explorer_;
+  // Mapping from HeapThing pointers to HeapEntry* pointers.
   HeapEntriesMap entries_;
-  SnapshotFillerInterface* filler_;
-  // Used during references extraction to mark heap objects that
-  // are references via non-hidden properties.
-  HeapObjectsSet known_references_;
   // Used during snapshot generation.
   int progress_counter_;
   int progress_total_;
 
-  friend class IndexedReferencesExtractor;
-  friend class RootsReferencesExtractor;
-
   DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator);
 };
 
diff --git a/src/regexp-macro-assembler.cc b/src/regexp-macro-assembler.cc
index 09797ca..51f4015 100644
--- a/src/regexp-macro-assembler.cc
+++ b/src/regexp-macro-assembler.cc
@@ -154,16 +154,12 @@
     const byte* input_start,
     const byte* input_end,
     int* output) {
-  typedef int (*matcher)(String*, int, const byte*,
-                         const byte*, int*, Address, int);
-  matcher matcher_func = FUNCTION_CAST<matcher>(code->entry());
-
   // Ensure that the minimum stack has been allocated.
   RegExpStack stack;
   Address stack_base = RegExpStack::stack_base();
 
   int direct_call = 0;
-  int result = CALL_GENERATED_REGEXP_CODE(matcher_func,
+  int result = CALL_GENERATED_REGEXP_CODE(code->entry(),
                                           input,
                                           start_offset,
                                           input_start,
diff --git a/src/regexp.js b/src/regexp.js
index 5b7e3a9..f68dee6 100644
--- a/src/regexp.js
+++ b/src/regexp.js
@@ -384,13 +384,13 @@
 // pairs for the match and all the captured substrings), the invariant is
 // that there are at least two capture indeces.  The array also contains
 // the subject string for the last successful match.
-var lastMatchInfo = [
+var lastMatchInfo = new InternalArray(
     2,                 // REGEXP_NUMBER_OF_CAPTURES
     "",                // Last subject.
     void 0,            // Last input - settable with RegExpSetInput.
     0,                 // REGEXP_FIRST_CAPTURE + 0
-    0,                 // REGEXP_FIRST_CAPTURE + 1
-];
+    0                  // REGEXP_FIRST_CAPTURE + 1
+);
 
 // Override last match info with an array of actual substrings.
 // Used internally by replace regexp with function.
diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc
index 3406cdc..df6471e 100644
--- a/src/runtime-profiler.cc
+++ b/src/runtime-profiler.cc
@@ -35,6 +35,7 @@
 #include "deoptimizer.h"
 #include "execution.h"
 #include "global-handles.h"
+#include "mark-compact.h"
 #include "scopeinfo.h"
 #include "top.h"
 
@@ -100,11 +101,6 @@
 // The ratio of ticks spent in JS code in percent.
 static Atomic32 js_ratio;
 
-// The JSFunctions in the sampler window are not GC safe. Old-space
-// pointers are not cleared during mark-sweep collection and therefore
-// the window might contain stale pointers. The window is updated on
-// scavenges and (parts of it) cleared on mark-sweep and
-// mark-sweep-compact.
 static Object* sampler_window[kSamplerWindowSize] = { NULL, };
 static int sampler_window_position = 0;
 static int sampler_window_weight[kSamplerWindowSize] = { 0, };
@@ -134,7 +130,6 @@
 
 
 static bool IsOptimizable(JSFunction* function) {
-  if (Heap::InNewSpace(function)) return false;
   Code* code = function->code();
   return code->kind() == Code::FUNCTION && code->optimizable();
 }
@@ -208,16 +203,6 @@
 }
 
 
-static void ClearSampleBufferNewSpaceEntries() {
-  for (int i = 0; i < kSamplerWindowSize; i++) {
-    if (Heap::InNewSpace(sampler_window[i])) {
-      sampler_window[i] = NULL;
-      sampler_window_weight[i] = 0;
-    }
-  }
-}
-
-
 static int LookupSample(JSFunction* function) {
   int weight = 0;
   for (int i = 0; i < kSamplerWindowSize; i++) {
@@ -372,24 +357,6 @@
 }
 
 
-void RuntimeProfiler::MarkCompactPrologue(bool is_compacting) {
-  if (is_compacting) {
-    // Clear all samples before mark-sweep-compact because every
-    // function might move.
-    ClearSampleBuffer();
-  } else {
-    // Clear only new space entries on mark-sweep since none of the
-    // old-space functions will move.
-    ClearSampleBufferNewSpaceEntries();
-  }
-}
-
-
-bool IsEqual(void* first, void* second) {
-  return first == second;
-}
-
-
 void RuntimeProfiler::Setup() {
   ClearSampleBuffer();
   // If the ticker hasn't already started, make sure to do so to get
@@ -411,13 +378,41 @@
 }
 
 
-Object** RuntimeProfiler::SamplerWindowAddress() {
-  return sampler_window;
+int RuntimeProfiler::SamplerWindowSize() {
+  return kSamplerWindowSize;
 }
 
 
-int RuntimeProfiler::SamplerWindowSize() {
-  return kSamplerWindowSize;
+// Update the pointers in the sampler window after a GC.
+void RuntimeProfiler::UpdateSamplesAfterScavenge() {
+  for (int i = 0; i < kSamplerWindowSize; i++) {
+    Object* function = sampler_window[i];
+    if (function != NULL && Heap::InNewSpace(function)) {
+      MapWord map_word = HeapObject::cast(function)->map_word();
+      if (map_word.IsForwardingAddress()) {
+        sampler_window[i] = map_word.ToForwardingAddress();
+      } else {
+        sampler_window[i] = NULL;
+      }
+    }
+  }
+}
+
+
+void RuntimeProfiler::RemoveDeadSamples() {
+  for (int i = 0; i < kSamplerWindowSize; i++) {
+    Object* function = sampler_window[i];
+    if (function != NULL && !HeapObject::cast(function)->IsMarked()) {
+      sampler_window[i] = NULL;
+    }
+  }
+}
+
+
+void RuntimeProfiler::UpdateSamplesAfterCompact(ObjectVisitor* visitor) {
+  for (int i = 0; i < kSamplerWindowSize; i++) {
+    visitor->VisitPointer(&sampler_window[i]);
+  }
 }
 
 
diff --git a/src/runtime-profiler.h b/src/runtime-profiler.h
index e041c05..02defc9 100644
--- a/src/runtime-profiler.h
+++ b/src/runtime-profiler.h
@@ -47,9 +47,10 @@
   static void Reset();
   static void TearDown();
 
-  static void MarkCompactPrologue(bool is_compacting);
-  static Object** SamplerWindowAddress();
   static int SamplerWindowSize();
+  static void UpdateSamplesAfterScavenge();
+  static void RemoveDeadSamples();
+  static void UpdateSamplesAfterCompact(ObjectVisitor* visitor);
 };
 
 
diff --git a/src/runtime.cc b/src/runtime.cc
index ef7a4ac..965a083 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -40,8 +40,10 @@
 #include "debug.h"
 #include "deoptimizer.h"
 #include "execution.h"
+#include "global-handles.h"
 #include "jsregexp.h"
 #include "liveedit.h"
+#include "liveobjectlist-inl.h"
 #include "parser.h"
 #include "platform.h"
 #include "runtime.h"
@@ -160,7 +162,8 @@
           if (!maybe_result->ToObject(&result)) return maybe_result;
         }
         { MaybeObject* maybe_result =
-              copy->SetProperty(key_string, result, NONE);
+              // Creating object copy for literals. No strict mode needed.
+              copy->SetProperty(key_string, result, NONE, kNonStrictMode);
           if (!maybe_result->ToObject(&result)) return maybe_result;
         }
       }
@@ -332,7 +335,10 @@
       if (key->IsSymbol()) {
         if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
           // Array index as string (uint32).
-          result = SetOwnElement(boilerplate, element_index, value);
+          result = SetOwnElement(boilerplate,
+                                 element_index,
+                                 value,
+                                 kNonStrictMode);
         } else {
           Handle<String> name(String::cast(*key));
           ASSERT(!name->AsArrayIndex(&element_index));
@@ -341,7 +347,10 @@
         }
       } else if (key->ToArrayIndex(&element_index)) {
         // Array index (uint32).
-        result = SetOwnElement(boilerplate, element_index, value);
+        result = SetOwnElement(boilerplate,
+                               element_index,
+                               value,
+                               kNonStrictMode);
       } else {
         // Non-uint32 number.
         ASSERT(key->IsNumber());
@@ -546,7 +555,9 @@
   // Assign the exception value to the catch variable and make sure
   // that the catch variable is DontDelete.
   { MaybeObject* maybe_value =
-        JSObject::cast(object)->SetProperty(key, value, DONT_DELETE);
+        // Passing non-strict per ECMA-262 5th Ed. 12.14. Catch, bullet #4.
+        JSObject::cast(object)->SetProperty(
+            key, value, DONT_DELETE, kNonStrictMode);
     if (!maybe_value->ToObject(&value)) return maybe_value;
   }
   return object;
@@ -783,7 +794,9 @@
       case JSObject::INTERCEPTED_ELEMENT:
       case JSObject::FAST_ELEMENT: {
         elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
-        elms->set(VALUE_INDEX, *GetElement(obj, index));
+        Handle<Object> value = GetElement(obj, index);
+        RETURN_IF_EMPTY_HANDLE(value);
+        elms->set(VALUE_INDEX, *value);
         elms->set(WRITABLE_INDEX, Heap::true_value());
         elms->set(ENUMERABLE_INDEX,  Heap::true_value());
         elms->set(CONFIGURABLE_INDEX, Heap::true_value());
@@ -816,12 +829,15 @@
             }
             break;
           }
-          case NORMAL:
+          case NORMAL: {
             // This is a data property.
             elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
-            elms->set(VALUE_INDEX, *GetElement(obj, index));
+            Handle<Object> value = GetElement(obj, index);
+            ASSERT(!value.is_null());
+            elms->set(VALUE_INDEX, *value);
             elms->set(WRITABLE_INDEX, Heap::ToBoolean(!details.IsReadOnly()));
             break;
+          }
           default:
             UNREACHABLE();
             break;
@@ -994,12 +1010,16 @@
 
 
 static MaybeObject* Runtime_DeclareGlobals(Arguments args) {
+  ASSERT(args.length() == 4);
   HandleScope scope;
   Handle<GlobalObject> global = Handle<GlobalObject>(Top::context()->global());
 
   Handle<Context> context = args.at<Context>(0);
   CONVERT_ARG_CHECKED(FixedArray, pairs, 1);
   bool is_eval = Smi::cast(args[2])->value() == 1;
+  StrictModeFlag strict_mode =
+      static_cast<StrictModeFlag>(Smi::cast(args[3])->value());
+  ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
 
   // Compute the property attributes. According to ECMA-262, section
   // 13, page 71, the property must be read-only and
@@ -1051,6 +1071,12 @@
           // Fall-through and introduce the absent property by using
           // SetProperty.
         } else {
+          // For const properties, we treat a callback with this name
+          // even in the prototype as a conflicting declaration.
+          if (is_const_property && (lookup.type() == CALLBACKS)) {
+            return ThrowRedeclarationError("const", name);
+          }
+          // Otherwise, we check for locally conflicting declarations.
           if (is_local && (is_read_only || is_const_property)) {
             const char* type = (is_read_only) ? "const" : "var";
             return ThrowRedeclarationError(type, name);
@@ -1076,29 +1102,43 @@
         ? static_cast<PropertyAttributes>(base | READ_ONLY)
         : base;
 
-    if (lookup.IsProperty()) {
-      // There's a local property that we need to overwrite because
-      // we're either declaring a function or there's an interceptor
-      // that claims the property is absent.
+    // There's a local property that we need to overwrite because
+    // we're either declaring a function or there's an interceptor
+    // that claims the property is absent.
+    //
+    // Check for conflicting re-declarations. We cannot have
+    // conflicting types in case of intercepted properties because
+    // they are absent.
+    if (lookup.IsProperty() &&
+        (lookup.type() != INTERCEPTOR) &&
+        (lookup.IsReadOnly() || is_const_property)) {
+      const char* type = (lookup.IsReadOnly()) ? "const" : "var";
+      return ThrowRedeclarationError(type, name);
+    }
 
-      // Check for conflicting re-declarations. We cannot have
-      // conflicting types in case of intercepted properties because
-      // they are absent.
-      if (lookup.type() != INTERCEPTOR &&
-          (lookup.IsReadOnly() || is_const_property)) {
-        const char* type = (lookup.IsReadOnly()) ? "const" : "var";
-        return ThrowRedeclarationError(type, name);
+    // Safari does not allow the invocation of callback setters for
+    // function declarations. To mimic this behavior, we do not allow
+    // the invocation of setters for function values. This makes a
+    // difference for global functions with the same names as event
+    // handlers such as "function onload() {}". Firefox does call the
+    // onload setter in those case and Safari does not. We follow
+    // Safari for compatibility.
+    if (value->IsJSFunction()) {
+      // Do not change DONT_DELETE to false from true.
+      if (lookup.IsProperty() && (lookup.type() != INTERCEPTOR)) {
+        attributes = static_cast<PropertyAttributes>(
+            attributes | (lookup.GetAttributes() & DONT_DELETE));
       }
-      RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, attributes));
+      RETURN_IF_EMPTY_HANDLE(SetLocalPropertyIgnoreAttributes(global,
+                                                              name,
+                                                              value,
+                                                              attributes));
     } else {
-      // If a property with this name does not already exist on the
-      // global object add the property locally.  We take special
-      // precautions to always add it as a local property even in case
-      // of callbacks in the prototype chain (this rules out using
-      // SetProperty).  Also, we must use the handle-based version to
-      // avoid GC issues.
-      RETURN_IF_EMPTY_HANDLE(
-          SetLocalPropertyIgnoreAttributes(global, name, value, attributes));
+      RETURN_IF_EMPTY_HANDLE(SetProperty(global,
+                                         name,
+                                         value,
+                                         attributes,
+                                         strict_mode));
     }
   }
 
@@ -1152,14 +1192,16 @@
         } else {
           // The holder is an arguments object.
           Handle<JSObject> arguments(Handle<JSObject>::cast(holder));
-          Handle<Object> result = SetElement(arguments, index, initial_value);
+          Handle<Object> result = SetElement(arguments, index, initial_value,
+                                             kNonStrictMode);
           if (result.is_null()) return Failure::Exception();
         }
       } else {
         // Slow case: The property is not in the FixedArray part of the context.
         Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
         RETURN_IF_EMPTY_HANDLE(
-            SetProperty(context_ext, name, initial_value, mode));
+            SetProperty(context_ext, name, initial_value,
+                        mode, kNonStrictMode));
       }
     }
 
@@ -1186,7 +1228,22 @@
     ASSERT(!context_ext->HasLocalProperty(*name));
     Handle<Object> value(Heap::undefined_value());
     if (*initial_value != NULL) value = initial_value;
-    RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, mode));
+    // Declaring a const context slot is a conflicting declaration if
+    // there is a callback with that name in a prototype. It is
+    // allowed to introduce const variables in
+    // JSContextExtensionObjects. They are treated specially in
+    // SetProperty and no setters are invoked for those since they are
+    // not real JSObjects.
+    if (initial_value->IsTheHole() &&
+        !context_ext->IsJSContextExtensionObject()) {
+      LookupResult lookup;
+      context_ext->Lookup(*name, &lookup);
+      if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) {
+        return ThrowRedeclarationError("const", name);
+      }
+    }
+    RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, mode,
+                                       kNonStrictMode));
   }
 
   return Heap::undefined_value();
@@ -1195,14 +1252,21 @@
 
 static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) {
   NoHandleAllocation nha;
+  // args[0] == name
+  // args[1] == strict_mode
+  // args[2] == value (optional)
 
   // Determine if we need to assign to the variable if it already
   // exists (based on the number of arguments).
-  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
-  bool assign = args.length() == 2;
+  RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
+  bool assign = args.length() == 3;
 
   CONVERT_ARG_CHECKED(String, name, 0);
   GlobalObject* global = Top::context()->global();
+  RUNTIME_ASSERT(args[1]->IsSmi());
+  StrictModeFlag strict_mode =
+      static_cast<StrictModeFlag>(Smi::cast(args[1])->value());
+  ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
 
   // According to ECMA-262, section 12.2, page 62, the property must
   // not be deletable.
@@ -1212,11 +1276,7 @@
   // there, there is a property with this name in the prototype chain.
   // We follow Safari and Firefox behavior and only set the property
   // locally if there is an explicit initialization value that we have
-  // to assign to the property. When adding the property we take
-  // special precautions to always add it as a local property even in
-  // case of callbacks in the prototype chain (this rules out using
-  // SetProperty).  We have SetLocalPropertyIgnoreAttributes for
-  // this.
+  // to assign to the property.
   // Note that objects can have hidden prototypes, so we need to traverse
   // the whole chain of hidden prototypes to do a 'local' lookup.
   JSObject* real_holder = global;
@@ -1262,8 +1322,9 @@
       }
 
       // Assign the value (or undefined) to the property.
-      Object* value = (assign) ? args[1] : Heap::undefined_value();
-      return real_holder->SetProperty(&lookup, *name, value, attributes);
+      Object* value = (assign) ? args[2] : Heap::undefined_value();
+      return real_holder->SetProperty(
+          &lookup, *name, value, attributes, strict_mode);
     }
 
     Object* proto = real_holder->GetPrototype();
@@ -1278,9 +1339,7 @@
 
   global = Top::context()->global();
   if (assign) {
-    return global->SetLocalPropertyIgnoreAttributes(*name,
-                                                    args[1],
-                                                    attributes);
+    return global->SetProperty(*name, args[2], attributes, strict_mode);
   }
   return Heap::undefined_value();
 }
@@ -1340,13 +1399,19 @@
     // BUG 1213575: Handle the case where we have to set a read-only
     // property through an interceptor and only do it if it's
     // uninitialized, e.g. the hole. Nirk...
-    RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, attributes));
+    // Passing non-strict mode because the property is writable.
+    RETURN_IF_EMPTY_HANDLE(SetProperty(global,
+                                       name,
+                                       value,
+                                       attributes,
+                                       kNonStrictMode));
     return *value;
   }
 
   // Set the value, but only we're assigning the initial value to a
   // constant. For now, we determine this by checking if the
   // current value is the hole.
+  // Strict mode handling not needed (const disallowed in strict mode).
   PropertyType type = lookup.type();
   if (type == FIELD) {
     FixedArray* properties = global->properties();
@@ -1413,7 +1478,8 @@
       // The holder is an arguments object.
       ASSERT((attributes & READ_ONLY) == 0);
       Handle<JSObject> arguments(Handle<JSObject>::cast(holder));
-      SetElement(arguments, index, value);
+      RETURN_IF_EMPTY_HANDLE(
+          SetElement(arguments, index, value, kNonStrictMode));
     }
     return *value;
   }
@@ -1422,7 +1488,9 @@
   // context.
   if (attributes == ABSENT) {
     Handle<JSObject> global = Handle<JSObject>(Top::context()->global());
-    RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, NONE));
+    // Strict mode not needed (const disallowed in strict mode).
+    RETURN_IF_EMPTY_HANDLE(
+        SetProperty(global, name, value, NONE, kNonStrictMode));
     return *value;
   }
 
@@ -1459,8 +1527,9 @@
     // The property was found in a different context extension object.
     // Set it if it is not a read-only property.
     if ((attributes & READ_ONLY) == 0) {
+      // Strict mode not needed (const disallowed in strict mode).
       RETURN_IF_EMPTY_HANDLE(
-          SetProperty(context_ext, name, value, attributes));
+          SetProperty(context_ext, name, value, attributes, kNonStrictMode));
     }
   }
 
@@ -1626,7 +1695,7 @@
                                                       code,
                                                       false);
   optimized->shared()->DontAdaptArguments();
-  SetProperty(holder, key, optimized, NONE);
+  SetProperty(holder, key, optimized, NONE, kStrictMode);
   return optimized;
 }
 
@@ -3673,6 +3742,8 @@
       is_element) {
     // Normalize the elements to enable attributes on the property.
     if (js_object->IsJSGlobalProxy()) {
+      // We do not need to do access checks here since these has already
+      // been performed by the call to GetOwnProperty.
       Handle<Object> proto(js_object->GetPrototype());
       // If proxy is detached, ignore the assignment. Alternatively,
       // we could throw an exception.
@@ -3713,14 +3784,15 @@
                                                        attr);
   }
 
-  return Runtime::SetObjectProperty(js_object, name, obj_value, attr);
+  return Runtime::ForceSetObjectProperty(js_object, name, obj_value, attr);
 }
 
 
 MaybeObject* Runtime::SetObjectProperty(Handle<Object> object,
                                         Handle<Object> key,
                                         Handle<Object> value,
-                                        PropertyAttributes attr) {
+                                        PropertyAttributes attr,
+                                        StrictModeFlag strict_mode) {
   HandleScope scope;
 
   if (object->IsUndefined() || object->IsNull()) {
@@ -3750,7 +3822,7 @@
       return *value;
     }
 
-    Handle<Object> result = SetElement(js_object, index, value);
+    Handle<Object> result = SetElement(js_object, index, value, strict_mode);
     if (result.is_null()) return Failure::Exception();
     return *value;
   }
@@ -3758,11 +3830,11 @@
   if (key->IsString()) {
     Handle<Object> result;
     if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
-      result = SetElement(js_object, index, value);
+      result = SetElement(js_object, index, value, strict_mode);
     } else {
       Handle<String> key_string = Handle<String>::cast(key);
       key_string->TryFlatten();
-      result = SetProperty(js_object, key_string, value, attr);
+      result = SetProperty(js_object, key_string, value, attr, strict_mode);
     }
     if (result.is_null()) return Failure::Exception();
     return *value;
@@ -3775,9 +3847,9 @@
   Handle<String> name = Handle<String>::cast(converted);
 
   if (name->AsArrayIndex(&index)) {
-    return js_object->SetElement(index, *value);
+    return js_object->SetElement(index, *value, strict_mode);
   } else {
-    return js_object->SetProperty(*name, *value, attr);
+    return js_object->SetProperty(*name, *value, attr, strict_mode);
   }
 }
 
@@ -3802,12 +3874,12 @@
       return *value;
     }
 
-    return js_object->SetElement(index, *value);
+    return js_object->SetElement(index, *value, kNonStrictMode);
   }
 
   if (key->IsString()) {
     if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
-      return js_object->SetElement(index, *value);
+      return js_object->SetElement(index, *value, kNonStrictMode);
     } else {
       Handle<String> key_string = Handle<String>::cast(key);
       key_string->TryFlatten();
@@ -3824,7 +3896,7 @@
   Handle<String> name = Handle<String>::cast(converted);
 
   if (name->AsArrayIndex(&index)) {
-    return js_object->SetElement(index, *value);
+    return js_object->SetElement(index, *value, kNonStrictMode);
   } else {
     return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
   }
@@ -3869,23 +3941,31 @@
 
 static MaybeObject* Runtime_SetProperty(Arguments args) {
   NoHandleAllocation ha;
-  RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
+  RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
 
   Handle<Object> object = args.at<Object>(0);
   Handle<Object> key = args.at<Object>(1);
   Handle<Object> value = args.at<Object>(2);
-
+  CONVERT_SMI_CHECKED(unchecked_attributes, args[3]);
+  RUNTIME_ASSERT(
+      (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
   // Compute attributes.
-  PropertyAttributes attributes = NONE;
-  if (args.length() == 4) {
-    CONVERT_CHECKED(Smi, value_obj, args[3]);
-    int unchecked_value = value_obj->value();
-    // Only attribute bits should be set.
-    RUNTIME_ASSERT(
-        (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
-    attributes = static_cast<PropertyAttributes>(unchecked_value);
+  PropertyAttributes attributes =
+      static_cast<PropertyAttributes>(unchecked_attributes);
+
+  StrictModeFlag strict_mode = kNonStrictMode;
+  if (args.length() == 5) {
+    CONVERT_SMI_CHECKED(strict_unchecked, args[4]);
+    RUNTIME_ASSERT(strict_unchecked == kStrictMode ||
+                   strict_unchecked == kNonStrictMode);
+    strict_mode = static_cast<StrictModeFlag>(strict_unchecked);
   }
-  return Runtime::SetObjectProperty(object, key, value, attributes);
+
+  return Runtime::SetObjectProperty(object,
+                                    key,
+                                    value,
+                                    attributes,
+                                    strict_mode);
 }
 
 
@@ -3914,11 +3994,14 @@
 
 static MaybeObject* Runtime_DeleteProperty(Arguments args) {
   NoHandleAllocation ha;
-  ASSERT(args.length() == 2);
+  ASSERT(args.length() == 3);
 
   CONVERT_CHECKED(JSObject, object, args[0]);
   CONVERT_CHECKED(String, key, args[1]);
-  return object->DeleteProperty(key, JSObject::NORMAL_DELETION);
+  CONVERT_SMI_CHECKED(strict, args[2]);
+  return object->DeleteProperty(key, (strict == kStrictMode)
+                                      ? JSObject::STRICT_DELETION
+                                      : JSObject::NORMAL_DELETION);
 }
 
 
@@ -4214,6 +4297,14 @@
   Handle<JSObject> object(raw_object);
 
   if (object->IsJSGlobalProxy()) {
+    // Do access checks before going to the global object.
+    if (object->IsAccessCheckNeeded() &&
+        !Top::MayNamedAccess(*object, Heap::undefined_value(),
+                             v8::ACCESS_KEYS)) {
+      Top::ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
+      return *Factory::NewJSArray(0);
+    }
+
     Handle<Object> proto(object->GetPrototype());
     // If proxy is detached we simply return an empty array.
     if (proto->IsNull()) return *Factory::NewJSArray(0);
@@ -5803,6 +5894,89 @@
 }
 
 
+static MaybeObject* Runtime_StringBuilderJoin(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 3);
+  CONVERT_CHECKED(JSArray, array, args[0]);
+  if (!args[1]->IsSmi()) {
+    Top::context()->mark_out_of_memory();
+    return Failure::OutOfMemoryException();
+  }
+  int array_length = Smi::cast(args[1])->value();
+  CONVERT_CHECKED(String, separator, args[2]);
+
+  if (!array->HasFastElements()) {
+    return Top::Throw(Heap::illegal_argument_symbol());
+  }
+  FixedArray* fixed_array = FixedArray::cast(array->elements());
+  if (fixed_array->length() < array_length) {
+    array_length = fixed_array->length();
+  }
+
+  if (array_length == 0) {
+    return Heap::empty_string();
+  } else if (array_length == 1) {
+    Object* first = fixed_array->get(0);
+    if (first->IsString()) return first;
+  }
+
+  int separator_length = separator->length();
+  int max_nof_separators =
+      (String::kMaxLength + separator_length - 1) / separator_length;
+  if (max_nof_separators < (array_length - 1)) {
+      Top::context()->mark_out_of_memory();
+      return Failure::OutOfMemoryException();
+  }
+  int length = (array_length - 1) * separator_length;
+  for (int i = 0; i < array_length; i++) {
+    Object* element_obj = fixed_array->get(i);
+    if (!element_obj->IsString()) {
+      // TODO(1161): handle this case.
+      return Top::Throw(Heap::illegal_argument_symbol());
+    }
+    String* element = String::cast(element_obj);
+    int increment = element->length();
+    if (increment > String::kMaxLength - length) {
+      Top::context()->mark_out_of_memory();
+      return Failure::OutOfMemoryException();
+    }
+    length += increment;
+  }
+
+  Object* object;
+  { MaybeObject* maybe_object = Heap::AllocateRawTwoByteString(length);
+    if (!maybe_object->ToObject(&object)) return maybe_object;
+  }
+  SeqTwoByteString* answer = SeqTwoByteString::cast(object);
+
+  uc16* sink = answer->GetChars();
+#ifdef DEBUG
+  uc16* end = sink + length;
+#endif
+
+  String* first = String::cast(fixed_array->get(0));
+  int first_length = first->length();
+  String::WriteToFlat(first, sink, 0, first_length);
+  sink += first_length;
+
+  for (int i = 1; i < array_length; i++) {
+    ASSERT(sink + separator_length <= end);
+    String::WriteToFlat(separator, sink, 0, separator_length);
+    sink += separator_length;
+
+    String* element = String::cast(fixed_array->get(i));
+    int element_length = element->length();
+    ASSERT(sink + element_length <= end);
+    String::WriteToFlat(element, sink, 0, element_length);
+    sink += element_length;
+  }
+  ASSERT(sink == end);
+
+  ASSERT(!answer->HasOnlyAsciiChars());  // Use %_FastAsciiArrayJoin instead.
+  return answer;
+}
+
+
 static MaybeObject* Runtime_NumberOr(Arguments args) {
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
@@ -6833,6 +7007,7 @@
 
   bool first_allocation = !shared->live_objects_may_exist();
   Handle<JSObject> result = Factory::NewJSObject(function);
+  RETURN_IF_EMPTY_HANDLE(result);
   // Delay setting the stub if inobject slack tracking is in progress.
   if (first_allocation && !shared->IsInobjectSlackTrackingInProgress()) {
     TrySettingInlineConstructStub(function);
@@ -6906,7 +7081,7 @@
     function->ReplaceCode(function->shared()->code());
     return function->code();
   }
-  if (CompileOptimized(function, AstNode::kNoNumber)) {
+  if (CompileOptimized(function, AstNode::kNoNumber, CLEAR_EXCEPTION)) {
     return function->code();
   }
   if (FLAG_trace_opt) {
@@ -6915,7 +7090,7 @@
     PrintF(": optimized compilation failed]\n");
   }
   function->ReplaceCode(function->shared()->code());
-  return Failure::Exception();
+  return function->code();
 }
 
 
@@ -7075,7 +7250,8 @@
     // Try to compile the optimized code.  A true return value from
     // CompileOptimized means that compilation succeeded, not necessarily
     // that optimization succeeded.
-    if (CompileOptimized(function, ast_id) && function->IsOptimized()) {
+    if (CompileOptimized(function, ast_id, CLEAR_EXCEPTION) &&
+        function->IsOptimized()) {
       DeoptimizationInputData* data = DeoptimizationInputData::cast(
           function->code()->deoptimization_data());
       if (data->OsrPcOffset()->value() >= 0) {
@@ -7118,6 +7294,9 @@
     ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
     return Smi::FromInt(ast_id);
   } else {
+    if (function->IsMarkedForLazyRecompilation()) {
+      function->ReplaceCode(function->shared()->code());
+    }
     return Smi::FromInt(-1);
   }
 }
@@ -7368,11 +7547,15 @@
 
 static MaybeObject* Runtime_StoreContextSlot(Arguments args) {
   HandleScope scope;
-  ASSERT(args.length() == 3);
+  ASSERT(args.length() == 4);
 
   Handle<Object> value(args[0]);
   CONVERT_ARG_CHECKED(Context, context, 1);
   CONVERT_ARG_CHECKED(String, name, 2);
+  CONVERT_SMI_CHECKED(strict_unchecked, args[3]);
+  RUNTIME_ASSERT(strict_unchecked == kStrictMode ||
+                 strict_unchecked == kNonStrictMode);
+  StrictModeFlag strict_mode = static_cast<StrictModeFlag>(strict_unchecked);
 
   int index;
   PropertyAttributes attributes;
@@ -7385,11 +7568,17 @@
       if ((attributes & READ_ONLY) == 0) {
         // Context is a fixed array and set cannot fail.
         Context::cast(*holder)->set(index, *value);
+      } else if (strict_mode == kStrictMode) {
+        // Setting read only property in strict mode.
+        Handle<Object> error =
+            Factory::NewTypeError("strict_cannot_assign",
+                                  HandleVector(&name, 1));
+        return Top::Throw(*error);
       }
     } else {
       ASSERT((attributes & READ_ONLY) == 0);
       Handle<Object> result =
-          SetElement(Handle<JSObject>::cast(holder), index, value);
+          SetElement(Handle<JSObject>::cast(holder), index, value, strict_mode);
       if (result.is_null()) {
         ASSERT(Top::has_pending_exception());
         return Failure::Exception();
@@ -7416,7 +7605,13 @@
   // extension object itself.
   if ((attributes & READ_ONLY) == 0 ||
       (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) {
-    RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, NONE));
+    RETURN_IF_EMPTY_HANDLE(
+        SetProperty(context_ext, name, value, NONE, strict_mode));
+  } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) {
+    // Setting read only property in strict mode.
+    Handle<Object> error =
+        Factory::NewTypeError("strict_cannot_assign", HandleVector(&name, 1));
+    return Top::Throw(*error);
   }
   return *value;
 }
@@ -7745,12 +7940,9 @@
 
 static ObjectPair Runtime_ResolvePossiblyDirectEval(Arguments args) {
   ASSERT(args.length() == 4);
-  if (!args[0]->IsJSFunction()) {
-    return MakePair(Top::ThrowIllegalOperation(), NULL);
-  }
 
   HandleScope scope;
-  Handle<JSFunction> callee = args.at<JSFunction>(0);
+  Handle<Object> callee = args.at<Object>(0);
   Handle<Object> receiver;  // Will be overwritten.
 
   // Compute the calling context.
@@ -7818,12 +8010,9 @@
 
 static ObjectPair Runtime_ResolvePossiblyDirectEvalNoLookup(Arguments args) {
   ASSERT(args.length() == 4);
-  if (!args[0]->IsJSFunction()) {
-    return MakePair(Top::ThrowIllegalOperation(), NULL);
-  }
 
   HandleScope scope;
-  Handle<JSFunction> callee = args.at<JSFunction>(0);
+  Handle<Object> callee = args.at<Object>(0);
 
   // 'eval' is bound in the global context, but it may have been overwritten.
   // Compare it to the builtin 'GlobalEval' function to make sure.
@@ -7893,7 +8082,9 @@
     if (elements->get(i) == element) return Heap::false_value();
   }
   Object* obj;
-  { MaybeObject* maybe_obj = array->SetFastElement(length, element);
+  // Strict not needed. Used for cycle detection in Array join implementation.
+  { MaybeObject* maybe_obj = array->SetFastElement(length, element,
+                                                   kNonStrictMode);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
   return Heap::true_value();
@@ -7914,398 +8105,494 @@
 class ArrayConcatVisitor {
  public:
   ArrayConcatVisitor(Handle<FixedArray> storage,
-                     uint32_t index_limit,
                      bool fast_elements) :
-      storage_(storage), index_limit_(index_limit),
-      index_offset_(0), fast_elements_(fast_elements) { }
+    storage_(Handle<FixedArray>::cast(GlobalHandles::Create(*storage))),
+      index_offset_(0u),
+      fast_elements_(fast_elements) { }
+
+  ~ArrayConcatVisitor() {
+    clear_storage();
+  }
 
   void visit(uint32_t i, Handle<Object> elm) {
-    if (i >= index_limit_ - index_offset_) return;
+    if (i >= JSObject::kMaxElementCount - index_offset_) return;
     uint32_t index = index_offset_ + i;
 
     if (fast_elements_) {
-      ASSERT(index < static_cast<uint32_t>(storage_->length()));
-      storage_->set(index, *elm);
-
-    } else {
-      Handle<NumberDictionary> dict = Handle<NumberDictionary>::cast(storage_);
-      Handle<NumberDictionary> result =
-          Factory::DictionaryAtNumberPut(dict, index, elm);
-      if (!result.is_identical_to(dict))
-        storage_ = result;
+      if (index < static_cast<uint32_t>(storage_->length())) {
+        storage_->set(index, *elm);
+        return;
+      }
+      // Our initial estimate of length was foiled, possibly by
+      // getters on the arrays increasing the length of later arrays
+      // during iteration.
+      // This shouldn't happen in anything but pathological cases.
+      SetDictionaryMode(index);
+      // Fall-through to dictionary mode.
     }
-  }
+    ASSERT(!fast_elements_);
+    Handle<NumberDictionary> dict(NumberDictionary::cast(*storage_));
+    Handle<NumberDictionary> result =
+        Factory::DictionaryAtNumberPut(dict, index, elm);
+    if (!result.is_identical_to(dict)) {
+      // Dictionary needed to grow.
+      clear_storage();
+      set_storage(*result);
+    }
+}
 
   void increase_index_offset(uint32_t delta) {
-    if (index_limit_ - index_offset_ < delta) {
-      index_offset_ = index_limit_;
+    if (JSObject::kMaxElementCount - index_offset_ < delta) {
+      index_offset_ = JSObject::kMaxElementCount;
     } else {
       index_offset_ += delta;
     }
   }
 
-  Handle<FixedArray> storage() { return storage_; }
+  Handle<JSArray> ToArray() {
+    Handle<JSArray> array = Factory::NewJSArray(0);
+    Handle<Object> length =
+        Factory::NewNumber(static_cast<double>(index_offset_));
+    Handle<Map> map;
+    if (fast_elements_) {
+      map = Factory::GetFastElementsMap(Handle<Map>(array->map()));
+    } else {
+      map = Factory::GetSlowElementsMap(Handle<Map>(array->map()));
+    }
+    array->set_map(*map);
+    array->set_length(*length);
+    array->set_elements(*storage_);
+    return array;
+  }
 
  private:
-  Handle<FixedArray> storage_;
-  // Limit on the accepted indices. Elements with indices larger than the
-  // limit are ignored by the visitor.
-  uint32_t index_limit_;
-  // Index after last seen index. Always less than or equal to index_limit_.
+  // Convert storage to dictionary mode.
+  void SetDictionaryMode(uint32_t index) {
+    ASSERT(fast_elements_);
+    Handle<FixedArray> current_storage(*storage_);
+    Handle<NumberDictionary> slow_storage(
+        Factory::NewNumberDictionary(current_storage->length()));
+    uint32_t current_length = static_cast<uint32_t>(current_storage->length());
+    for (uint32_t i = 0; i < current_length; i++) {
+      HandleScope loop_scope;
+      Handle<Object> element(current_storage->get(i));
+      if (!element->IsTheHole()) {
+        Handle<NumberDictionary> new_storage =
+          Factory::DictionaryAtNumberPut(slow_storage, i, element);
+        if (!new_storage.is_identical_to(slow_storage)) {
+          slow_storage = loop_scope.CloseAndEscape(new_storage);
+        }
+      }
+    }
+    clear_storage();
+    set_storage(*slow_storage);
+    fast_elements_ = false;
+  }
+
+  inline void clear_storage() {
+    GlobalHandles::Destroy(Handle<Object>::cast(storage_).location());
+  }
+
+  inline void set_storage(FixedArray* storage) {
+    storage_ = Handle<FixedArray>::cast(GlobalHandles::Create(storage));
+  }
+
+  Handle<FixedArray> storage_;  // Always a global handle.
+  // Index after last seen index. Always less than or equal to
+  // JSObject::kMaxElementCount.
   uint32_t index_offset_;
-  const bool fast_elements_;
+  bool fast_elements_;
 };
 
 
-template<class ExternalArrayClass, class ElementType>
-static uint32_t IterateExternalArrayElements(Handle<JSObject> receiver,
-                                             bool elements_are_ints,
-                                             bool elements_are_guaranteed_smis,
-                                             uint32_t range,
-                                             ArrayConcatVisitor* visitor) {
-  Handle<ExternalArrayClass> array(
-      ExternalArrayClass::cast(receiver->elements()));
-  uint32_t len = Min(static_cast<uint32_t>(array->length()), range);
-
-  if (visitor != NULL) {
-    if (elements_are_ints) {
-      if (elements_are_guaranteed_smis) {
-        for (uint32_t j = 0; j < len; j++) {
-          Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get(j))));
-          visitor->visit(j, e);
-        }
-      } else {
-        for (uint32_t j = 0; j < len; j++) {
-          int64_t val = static_cast<int64_t>(array->get(j));
-          if (Smi::IsValid(static_cast<intptr_t>(val))) {
-            Handle<Smi> e(Smi::FromInt(static_cast<int>(val)));
-            visitor->visit(j, e);
-          } else {
-            Handle<Object> e =
-                Factory::NewNumber(static_cast<ElementType>(val));
-            visitor->visit(j, e);
-          }
-        }
-      }
-    } else {
-      for (uint32_t j = 0; j < len; j++) {
-        Handle<Object> e = Factory::NewNumber(array->get(j));
-        visitor->visit(j, e);
-      }
-    }
-  }
-
-  return len;
-}
-
-/**
- * A helper function that visits elements of a JSObject. Only elements
- * whose index between 0 and range (exclusive) are visited.
- *
- * If the third parameter, visitor, is not NULL, the visitor is called
- * with parameters, 'visitor_index_offset + element index' and the element.
- *
- * It returns the number of visisted elements.
- */
-static uint32_t IterateElements(Handle<JSObject> receiver,
-                                uint32_t range,
-                                ArrayConcatVisitor* visitor) {
-  uint32_t num_of_elements = 0;
-
-  switch (receiver->GetElementsKind()) {
+static uint32_t EstimateElementCount(Handle<JSArray> array) {
+  uint32_t length = static_cast<uint32_t>(array->length()->Number());
+  int element_count = 0;
+  switch (array->GetElementsKind()) {
     case JSObject::FAST_ELEMENTS: {
-      Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
-      uint32_t len = elements->length();
-      if (range < len) {
-        len = range;
+      // Fast elements can't have lengths that are not representable by
+      // a 32-bit signed integer.
+      ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
+      int fast_length = static_cast<int>(length);
+      Handle<FixedArray> elements(FixedArray::cast(array->elements()));
+      for (int i = 0; i < fast_length; i++) {
+        if (!elements->get(i)->IsTheHole()) element_count++;
       }
-
-      for (uint32_t j = 0; j < len; j++) {
-        Handle<Object> e(elements->get(j));
-        if (!e->IsTheHole()) {
-          num_of_elements++;
-          if (visitor) {
-            visitor->visit(j, e);
-          }
-        }
-      }
-      break;
-    }
-    case JSObject::PIXEL_ELEMENTS: {
-      Handle<PixelArray> pixels(PixelArray::cast(receiver->elements()));
-      uint32_t len = pixels->length();
-      if (range < len) {
-        len = range;
-      }
-
-      for (uint32_t j = 0; j < len; j++) {
-        num_of_elements++;
-        if (visitor != NULL) {
-          Handle<Smi> e(Smi::FromInt(pixels->get(j)));
-          visitor->visit(j, e);
-        }
-      }
-      break;
-    }
-    case JSObject::EXTERNAL_BYTE_ELEMENTS: {
-      num_of_elements =
-          IterateExternalArrayElements<ExternalByteArray, int8_t>(
-              receiver, true, true, range, visitor);
-      break;
-    }
-    case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
-      num_of_elements =
-          IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
-              receiver, true, true, range, visitor);
-      break;
-    }
-    case JSObject::EXTERNAL_SHORT_ELEMENTS: {
-      num_of_elements =
-          IterateExternalArrayElements<ExternalShortArray, int16_t>(
-              receiver, true, true, range, visitor);
-      break;
-    }
-    case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
-      num_of_elements =
-          IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
-              receiver, true, true, range, visitor);
-      break;
-    }
-    case JSObject::EXTERNAL_INT_ELEMENTS: {
-      num_of_elements =
-          IterateExternalArrayElements<ExternalIntArray, int32_t>(
-              receiver, true, false, range, visitor);
-      break;
-    }
-    case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
-      num_of_elements =
-          IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
-              receiver, true, false, range, visitor);
-      break;
-    }
-    case JSObject::EXTERNAL_FLOAT_ELEMENTS: {
-      num_of_elements =
-          IterateExternalArrayElements<ExternalFloatArray, float>(
-              receiver, false, false, range, visitor);
       break;
     }
     case JSObject::DICTIONARY_ELEMENTS: {
-      Handle<NumberDictionary> dict(receiver->element_dictionary());
+      Handle<NumberDictionary> dictionary(
+          NumberDictionary::cast(array->elements()));
+      int capacity = dictionary->Capacity();
+      for (int i = 0; i < capacity; i++) {
+        Handle<Object> key(dictionary->KeyAt(i));
+        if (dictionary->IsKey(*key)) {
+          element_count++;
+        }
+      }
+      break;
+    }
+    default:
+      // External arrays are always dense.
+      return length;
+  }
+  // As an estimate, we assume that the prototype doesn't contain any
+  // inherited elements.
+  return element_count;
+}
+
+
+
+template<class ExternalArrayClass, class ElementType>
+static void IterateExternalArrayElements(Handle<JSObject> receiver,
+                                         bool elements_are_ints,
+                                         bool elements_are_guaranteed_smis,
+                                         ArrayConcatVisitor* visitor) {
+  Handle<ExternalArrayClass> array(
+      ExternalArrayClass::cast(receiver->elements()));
+  uint32_t len = static_cast<uint32_t>(array->length());
+
+  ASSERT(visitor != NULL);
+  if (elements_are_ints) {
+    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))));
+        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));
+        if (Smi::IsValid(static_cast<intptr_t>(val))) {
+          Handle<Smi> e(Smi::FromInt(static_cast<int>(val)));
+          visitor->visit(j, e);
+        } else {
+          Handle<Object> e =
+              Factory::NewNumber(static_cast<ElementType>(val));
+          visitor->visit(j, e);
+        }
+      }
+    }
+  } else {
+    for (uint32_t j = 0; j < len; j++) {
+      HandleScope loop_scope;
+      Handle<Object> e = Factory::NewNumber(array->get(j));
+      visitor->visit(j, e);
+    }
+  }
+}
+
+
+// Used for sorting indices in a List<uint32_t>.
+static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
+  uint32_t a = *ap;
+  uint32_t b = *bp;
+  return (a == b) ? 0 : (a < b) ? -1 : 1;
+}
+
+
+static void CollectElementIndices(Handle<JSObject> object,
+                                  uint32_t range,
+                                  List<uint32_t>* indices) {
+  JSObject::ElementsKind kind = object->GetElementsKind();
+  switch (kind) {
+    case JSObject::FAST_ELEMENTS: {
+      Handle<FixedArray> elements(FixedArray::cast(object->elements()));
+      uint32_t length = static_cast<uint32_t>(elements->length());
+      if (range < length) length = range;
+      for (uint32_t i = 0; i < length; i++) {
+        if (!elements->get(i)->IsTheHole()) {
+          indices->Add(i);
+        }
+      }
+      break;
+    }
+    case JSObject::DICTIONARY_ELEMENTS: {
+      Handle<NumberDictionary> dict(NumberDictionary::cast(object->elements()));
       uint32_t capacity = dict->Capacity();
       for (uint32_t j = 0; j < capacity; j++) {
+        HandleScope loop_scope;
         Handle<Object> k(dict->KeyAt(j));
         if (dict->IsKey(*k)) {
           ASSERT(k->IsNumber());
           uint32_t index = static_cast<uint32_t>(k->Number());
           if (index < range) {
-            num_of_elements++;
-            if (visitor) {
-              visitor->visit(index, Handle<Object>(dict->ValueAt(j)));
-            }
+            indices->Add(index);
           }
         }
       }
       break;
     }
+    default: {
+      int dense_elements_length;
+      switch (kind) {
+        case JSObject::PIXEL_ELEMENTS: {
+        dense_elements_length =
+            PixelArray::cast(object->elements())->length();
+          break;
+        }
+        case JSObject::EXTERNAL_BYTE_ELEMENTS: {
+        dense_elements_length =
+            ExternalByteArray::cast(object->elements())->length();
+          break;
+        }
+        case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
+        dense_elements_length =
+            ExternalUnsignedByteArray::cast(object->elements())->length();
+          break;
+        }
+        case JSObject::EXTERNAL_SHORT_ELEMENTS: {
+        dense_elements_length =
+            ExternalShortArray::cast(object->elements())->length();
+          break;
+        }
+        case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
+        dense_elements_length =
+            ExternalUnsignedShortArray::cast(object->elements())->length();
+          break;
+        }
+        case JSObject::EXTERNAL_INT_ELEMENTS: {
+        dense_elements_length =
+            ExternalIntArray::cast(object->elements())->length();
+          break;
+        }
+        case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
+        dense_elements_length =
+            ExternalUnsignedIntArray::cast(object->elements())->length();
+          break;
+        }
+        case JSObject::EXTERNAL_FLOAT_ELEMENTS: {
+        dense_elements_length =
+            ExternalFloatArray::cast(object->elements())->length();
+          break;
+        }
+        default:
+          UNREACHABLE();
+          dense_elements_length = 0;
+          break;
+      }
+      uint32_t length = static_cast<uint32_t>(dense_elements_length);
+      if (range <= length) {
+        length = range;
+        // We will add all indices, so we might as well clear it first
+        // and avoid duplicates.
+        indices->Clear();
+      }
+      for (uint32_t i = 0; i < length; i++) {
+        indices->Add(i);
+      }
+      if (length == range) return;  // All indices accounted for already.
+      break;
+    }
+  }
+
+  Handle<Object> prototype(object->GetPrototype());
+  if (prototype->IsJSObject()) {
+    // The prototype will usually have no inherited element indices,
+    // but we have to check.
+    CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices);
+  }
+}
+
+
+/**
+ * A helper function that visits elements of a JSArray in numerical
+ * order.
+ *
+ * The visitor argument called for each existing element in the array
+ * with the element index and the element's value.
+ * Afterwards it increments the base-index of the visitor by the array
+ * length.
+ * Returns false if any access threw an exception, otherwise true.
+ */
+static bool IterateElements(Handle<JSArray> receiver,
+                            ArrayConcatVisitor* visitor) {
+  uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
+  switch (receiver->GetElementsKind()) {
+    case JSObject::FAST_ELEMENTS: {
+      // Run through the elements FixedArray and use HasElement and GetElement
+      // to check the prototype for missing elements.
+      Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
+      int fast_length = static_cast<int>(length);
+      ASSERT(fast_length <= elements->length());
+      for (int j = 0; j < fast_length; j++) {
+        HandleScope loop_scope;
+        Handle<Object> element_value(elements->get(j));
+        if (!element_value->IsTheHole()) {
+          visitor->visit(j, element_value);
+        } else if (receiver->HasElement(j)) {
+          // Call GetElement on receiver, not its prototype, or getters won't
+          // have the correct receiver.
+          element_value = GetElement(receiver, j);
+          if (element_value.is_null()) return false;
+          visitor->visit(j, element_value);
+        }
+      }
+      break;
+    }
+    case JSObject::DICTIONARY_ELEMENTS: {
+      Handle<NumberDictionary> dict(receiver->element_dictionary());
+      List<uint32_t> indices(dict->Capacity() / 2);
+      // Collect all indices in the object and the prototypes less
+      // than length. This might introduce duplicates in the indices list.
+      CollectElementIndices(receiver, length, &indices);
+      indices.Sort(&compareUInt32);
+      int j = 0;
+      int n = indices.length();
+      while (j < n) {
+        HandleScope loop_scope;
+        uint32_t index = indices[j];
+        Handle<Object> element = GetElement(receiver, index);
+        if (element.is_null()) return false;
+        visitor->visit(index, element);
+        // Skip to next different index (i.e., omit duplicates).
+        do {
+          j++;
+        } while (j < n && indices[j] == index);
+      }
+      break;
+    }
+    case JSObject::PIXEL_ELEMENTS: {
+      Handle<PixelArray> pixels(PixelArray::cast(receiver->elements()));
+      for (uint32_t j = 0; j < length; j++) {
+        Handle<Smi> e(Smi::FromInt(pixels->get(j)));
+        visitor->visit(j, e);
+      }
+      break;
+    }
+    case JSObject::EXTERNAL_BYTE_ELEMENTS: {
+      IterateExternalArrayElements<ExternalByteArray, int8_t>(
+          receiver, true, true, visitor);
+      break;
+    }
+    case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
+      IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
+          receiver, true, true, visitor);
+      break;
+    }
+    case JSObject::EXTERNAL_SHORT_ELEMENTS: {
+      IterateExternalArrayElements<ExternalShortArray, int16_t>(
+          receiver, true, true, visitor);
+      break;
+    }
+    case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
+      IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
+          receiver, true, true, visitor);
+      break;
+    }
+    case JSObject::EXTERNAL_INT_ELEMENTS: {
+      IterateExternalArrayElements<ExternalIntArray, int32_t>(
+          receiver, true, false, visitor);
+      break;
+    }
+    case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
+      IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
+          receiver, true, false, visitor);
+      break;
+    }
+    case JSObject::EXTERNAL_FLOAT_ELEMENTS: {
+      IterateExternalArrayElements<ExternalFloatArray, float>(
+          receiver, false, false, visitor);
+      break;
+    }
     default:
       UNREACHABLE();
       break;
   }
-
-  return num_of_elements;
-}
-
-
-/**
- * A helper function that visits elements of an Array object, and elements
- * on its prototypes.
- *
- * Elements on prototypes are visited first, and only elements whose indices
- * less than Array length are visited.
- *
- * If a ArrayConcatVisitor object is given, the visitor is called with
- * parameters, element's index + visitor_index_offset and the element.
- *
- * The returned number of elements is an upper bound on the actual number
- * of elements added. If the same element occurs in more than one object
- * in the array's prototype chain, it will be counted more than once, but
- * will only occur once in the result.
- */
-static uint32_t IterateArrayAndPrototypeElements(Handle<JSArray> array,
-                                                 ArrayConcatVisitor* visitor) {
-  uint32_t range = static_cast<uint32_t>(array->length()->Number());
-  Handle<Object> obj = array;
-
-  static const int kEstimatedPrototypes = 3;
-  List< Handle<JSObject> > objects(kEstimatedPrototypes);
-
-  // Visit prototype first. If an element on the prototype is shadowed by
-  // the inheritor using the same index, the ArrayConcatVisitor visits
-  // the prototype element before the shadowing element.
-  // The visitor can simply overwrite the old value by new value using
-  // the same index.  This follows Array::concat semantics.
-  while (!obj->IsNull()) {
-    objects.Add(Handle<JSObject>::cast(obj));
-    obj = Handle<Object>(obj->GetPrototype());
-  }
-
-  uint32_t nof_elements = 0;
-  for (int i = objects.length() - 1; i >= 0; i--) {
-    Handle<JSObject> obj = objects[i];
-    uint32_t encountered_elements =
-        IterateElements(Handle<JSObject>::cast(obj), range, visitor);
-
-    if (encountered_elements > JSObject::kMaxElementCount - nof_elements) {
-      nof_elements = JSObject::kMaxElementCount;
-    } else {
-      nof_elements += encountered_elements;
-    }
-  }
-
-  return nof_elements;
-}
-
-
-/**
- * A helper function of Runtime_ArrayConcat.
- *
- * The first argument is an Array of arrays and objects. It is the
- * same as the arguments array of Array::concat JS function.
- *
- * If an argument is an Array object, the function visits array
- * elements.  If an argument is not an Array object, the function
- * visits the object as if it is an one-element array.
- *
- * If the result array index overflows 32-bit unsigned integer, the rounded
- * non-negative number is used as new length. For example, if one
- * array length is 2^32 - 1, second array length is 1, the
- * concatenated array length is 0.
- * TODO(lrn) Change length behavior to ECMAScript 5 specification (length
- * is one more than the last array index to get a value assigned).
- */
-static uint32_t IterateArguments(Handle<JSArray> arguments,
-                                 ArrayConcatVisitor* visitor) {
-  uint32_t visited_elements = 0;
-  uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number());
-
-  for (uint32_t i = 0; i < num_of_args; i++) {
-    Object *element;
-    MaybeObject* maybe_element = arguments->GetElement(i);
-    // This if() is not expected to fail, but we have the check in the
-    // interest of hardening the runtime calls.
-    if (maybe_element->ToObject(&element)) {
-      Handle<Object> obj(element);
-      if (obj->IsJSArray()) {
-        Handle<JSArray> array = Handle<JSArray>::cast(obj);
-        uint32_t len = static_cast<uint32_t>(array->length()->Number());
-        uint32_t nof_elements =
-            IterateArrayAndPrototypeElements(array, visitor);
-        // Total elements of array and its prototype chain can be more than
-        // the array length, but ArrayConcat can only concatenate at most
-        // the array length number of elements. We use the length as an estimate
-        // for the actual number of elements added.
-        uint32_t added_elements = (nof_elements > len) ? len : nof_elements;
-        if (JSArray::kMaxElementCount - visited_elements < added_elements) {
-          visited_elements = JSArray::kMaxElementCount;
-        } else {
-          visited_elements += added_elements;
-        }
-        if (visitor) visitor->increase_index_offset(len);
-      } else {
-        if (visitor) {
-          visitor->visit(0, obj);
-          visitor->increase_index_offset(1);
-        }
-        if (visited_elements < JSArray::kMaxElementCount) {
-          visited_elements++;
-        }
-      }
-    }
-  }
-  return visited_elements;
+  visitor->increase_index_offset(length);
+  return true;
 }
 
 
 /**
  * Array::concat implementation.
  * See ECMAScript 262, 15.4.4.4.
- * TODO(lrn): Fix non-compliance for very large concatenations and update to
+ * TODO(581): Fix non-compliance for very large concatenations and update to
  * following the ECMAScript 5 specification.
  */
 static MaybeObject* Runtime_ArrayConcat(Arguments args) {
   ASSERT(args.length() == 1);
   HandleScope handle_scope;
 
-  CONVERT_CHECKED(JSArray, arg_arrays, args[0]);
-  Handle<JSArray> arguments(arg_arrays);
+  CONVERT_ARG_CHECKED(JSArray, arguments, 0);
+  int argument_count = static_cast<int>(arguments->length()->Number());
+  RUNTIME_ASSERT(arguments->HasFastElements());
+  Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
 
-  // Pass 1: estimate the number of elements of the result
-  // (it could be more than real numbers if prototype has elements).
-  uint32_t result_length = 0;
-  uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number());
+  // Pass 1: estimate the length and number of elements of the result.
+  // The actual length can be larger if any of the arguments have getters
+  // that mutate other arguments (but will otherwise be precise).
+  // The number of elements is precise if there are no inherited elements.
 
-  { AssertNoAllocation nogc;
-    for (uint32_t i = 0; i < num_of_args; i++) {
-      Object* obj;
-      MaybeObject* maybe_object = arguments->GetElement(i);
-      // This if() is not expected to fail, but we have the check in the
-      // interest of hardening the runtime calls.
-      if (maybe_object->ToObject(&obj)) {
-        uint32_t length_estimate;
-        if (obj->IsJSArray()) {
-          length_estimate =
-              static_cast<uint32_t>(JSArray::cast(obj)->length()->Number());
-        } else {
-          length_estimate = 1;
-        }
-        if (JSObject::kMaxElementCount - result_length < length_estimate) {
-          result_length = JSObject::kMaxElementCount;
-          break;
-        }
-        result_length += length_estimate;
+  uint32_t estimate_result_length = 0;
+  uint32_t estimate_nof_elements = 0;
+  {
+    for (int i = 0; i < argument_count; i++) {
+      HandleScope loop_scope;
+      Handle<Object> obj(elements->get(i));
+      uint32_t length_estimate;
+      uint32_t element_estimate;
+      if (obj->IsJSArray()) {
+        Handle<JSArray> array(Handle<JSArray>::cast(obj));
+        length_estimate =
+            static_cast<uint32_t>(array->length()->Number());
+        element_estimate =
+            EstimateElementCount(array);
+      } else {
+        length_estimate = 1;
+        element_estimate = 1;
+      }
+      // Avoid overflows by capping at kMaxElementCount.
+      if (JSObject::kMaxElementCount - estimate_result_length <
+          length_estimate) {
+        estimate_result_length = JSObject::kMaxElementCount;
+      } else {
+        estimate_result_length += length_estimate;
+      }
+      if (JSObject::kMaxElementCount - estimate_nof_elements <
+          element_estimate) {
+        estimate_nof_elements = JSObject::kMaxElementCount;
+      } else {
+        estimate_nof_elements += element_estimate;
       }
     }
   }
 
-  // Allocate an empty array, will set length and content later.
-  Handle<JSArray> result = Factory::NewJSArray(0);
-
-  uint32_t estimate_nof_elements = IterateArguments(arguments, NULL);
   // If estimated number of elements is more than half of length, a
   // fixed array (fast case) is more time and space-efficient than a
   // dictionary.
-  bool fast_case = (estimate_nof_elements * 2) >= result_length;
+  bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
 
   Handle<FixedArray> storage;
   if (fast_case) {
     // The backing storage array must have non-existing elements to
     // preserve holes across concat operations.
-    storage = Factory::NewFixedArrayWithHoles(result_length);
-    Handle<Map> fast_map =
-        Factory::GetFastElementsMap(Handle<Map>(result->map()));
-    result->set_map(*fast_map);
+    storage = Factory::NewFixedArrayWithHoles(estimate_result_length);
   } else {
     // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
     uint32_t at_least_space_for = estimate_nof_elements +
                                   (estimate_nof_elements >> 2);
     storage = Handle<FixedArray>::cast(
-                  Factory::NewNumberDictionary(at_least_space_for));
-    Handle<Map> slow_map =
-        Factory::GetSlowElementsMap(Handle<Map>(result->map()));
-    result->set_map(*slow_map);
+        Factory::NewNumberDictionary(at_least_space_for));
   }
 
-  Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length));
+  ArrayConcatVisitor visitor(storage, fast_case);
 
-  ArrayConcatVisitor visitor(storage, result_length, fast_case);
+  for (int i = 0; i < argument_count; i++) {
+    Handle<Object> obj(elements->get(i));
+    if (obj->IsJSArray()) {
+      Handle<JSArray> array = Handle<JSArray>::cast(obj);
+      if (!IterateElements(array, &visitor)) {
+        return Failure::Exception();
+      }
+    } else {
+      visitor.visit(0, obj);
+      visitor.increase_index_offset(1);
+    }
+  }
 
-  IterateArguments(arguments, &visitor);
-
-  result->set_length(*len);
-  // Please note the storage might have changed in the visitor.
-  result->set_elements(*visitor.storage());
-
-  return *result;
+  return *visitor.ToArray();
 }
 
 
@@ -8396,10 +8683,12 @@
 
   Handle<JSObject> jsobject = Handle<JSObject>::cast(object);
   Handle<Object> tmp1 = GetElement(jsobject, index1);
+  RETURN_IF_EMPTY_HANDLE(tmp1);
   Handle<Object> tmp2 = GetElement(jsobject, index2);
+  RETURN_IF_EMPTY_HANDLE(tmp2);
 
-  SetElement(jsobject, index1, tmp2);
-  SetElement(jsobject, index2, tmp1);
+  RETURN_IF_EMPTY_HANDLE(SetElement(jsobject, index1, tmp2, kStrictMode));
+  RETURN_IF_EMPTY_HANDLE(SetElement(jsobject, index2, tmp1, kStrictMode));
 
   return Heap::undefined_value();
 }
@@ -9077,7 +9366,9 @@
       RETURN_IF_EMPTY_HANDLE_VALUE(
           SetProperty(scope_object,
                       scope_info.context_slot_name(i),
-                      Handle<Object>(context->get(context_index)), NONE),
+                      Handle<Object>(context->get(context_index)),
+                      NONE,
+                      kNonStrictMode),
           false);
     }
   }
@@ -9103,7 +9394,9 @@
     RETURN_IF_EMPTY_HANDLE_VALUE(
         SetProperty(local_scope,
                     scope_info.parameter_name(i),
-                    Handle<Object>(frame->GetParameter(i)), NONE),
+                    Handle<Object>(frame->GetParameter(i)),
+                    NONE,
+                    kNonStrictMode),
         Handle<JSObject>());
   }
 
@@ -9112,7 +9405,9 @@
     RETURN_IF_EMPTY_HANDLE_VALUE(
         SetProperty(local_scope,
                     scope_info.stack_slot_name(i),
-                    Handle<Object>(frame->GetExpression(i)), NONE),
+                    Handle<Object>(frame->GetExpression(i)),
+                    NONE,
+                    kNonStrictMode),
         Handle<JSObject>());
   }
 
@@ -9136,7 +9431,11 @@
         ASSERT(keys->get(i)->IsString());
         Handle<String> key(String::cast(keys->get(i)));
         RETURN_IF_EMPTY_HANDLE_VALUE(
-            SetProperty(local_scope, key, GetProperty(ext, key), NONE),
+            SetProperty(local_scope,
+                        key,
+                        GetProperty(ext, key),
+                        NONE,
+                        kNonStrictMode),
             Handle<JSObject>());
       }
     }
@@ -9174,7 +9473,8 @@
           SetProperty(closure_scope,
                       scope_info.parameter_name(i),
                       Handle<Object>(element),
-                      NONE),
+                      NONE,
+                      kNonStrictMode),
           Handle<JSObject>());
     }
   }
@@ -9195,7 +9495,11 @@
       ASSERT(keys->get(i)->IsString());
       Handle<String> key(String::cast(keys->get(i)));
       RETURN_IF_EMPTY_HANDLE_VALUE(
-          SetProperty(closure_scope, key, GetProperty(ext, key), NONE),
+          SetProperty(closure_scope,
+                      key,
+                      GetProperty(ext, key),
+                      NONE,
+                      kNonStrictMode),
           Handle<JSObject>());
     }
   }
@@ -10673,6 +10977,207 @@
   }
   return Smi::FromInt(usage);
 }
+
+
+// Captures a live object list from the present heap.
+static MaybeObject* Runtime_HasLOLEnabled(Arguments args) {
+#ifdef LIVE_OBJECT_LIST
+  return Heap::true_value();
+#else
+  return Heap::false_value();
+#endif
+}
+
+
+// Captures a live object list from the present heap.
+static MaybeObject* Runtime_CaptureLOL(Arguments args) {
+#ifdef LIVE_OBJECT_LIST
+  return LiveObjectList::Capture();
+#else
+  return Heap::undefined_value();
+#endif
+}
+
+
+// Deletes the specified live object list.
+static MaybeObject* Runtime_DeleteLOL(Arguments args) {
+#ifdef LIVE_OBJECT_LIST
+  CONVERT_SMI_CHECKED(id, args[0]);
+  bool success = LiveObjectList::Delete(id);
+  return success ? Heap::true_value() : Heap::false_value();
+#else
+  return Heap::undefined_value();
+#endif
+}
+
+
+// Generates the response to a debugger request for a dump of the objects
+// contained in the difference between the captured live object lists
+// specified by id1 and id2.
+// If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
+// dumped.
+static MaybeObject* Runtime_DumpLOL(Arguments args) {
+#ifdef LIVE_OBJECT_LIST
+  HandleScope scope;
+  CONVERT_SMI_CHECKED(id1, args[0]);
+  CONVERT_SMI_CHECKED(id2, args[1]);
+  CONVERT_SMI_CHECKED(start, args[2]);
+  CONVERT_SMI_CHECKED(count, args[3]);
+  CONVERT_ARG_CHECKED(JSObject, filter_obj, 4);
+  EnterDebugger enter_debugger;
+  return LiveObjectList::Dump(id1, id2, start, count, filter_obj);
+#else
+  return Heap::undefined_value();
+#endif
+}
+
+
+// Gets the specified object as requested by the debugger.
+// This is only used for obj ids shown in live object lists.
+static MaybeObject* Runtime_GetLOLObj(Arguments args) {
+#ifdef LIVE_OBJECT_LIST
+  CONVERT_SMI_CHECKED(obj_id, args[0]);
+  Object* result = LiveObjectList::GetObj(obj_id);
+  return result;
+#else
+  return Heap::undefined_value();
+#endif
+}
+
+
+// Gets the obj id for the specified address if valid.
+// This is only used for obj ids shown in live object lists.
+static MaybeObject* Runtime_GetLOLObjId(Arguments args) {
+#ifdef LIVE_OBJECT_LIST
+  HandleScope scope;
+  CONVERT_ARG_CHECKED(String, address, 0);
+  Object* result = LiveObjectList::GetObjId(address);
+  return result;
+#else
+  return Heap::undefined_value();
+#endif
+}
+
+
+// Gets the retainers that references the specified object alive.
+static MaybeObject* Runtime_GetLOLObjRetainers(Arguments args) {
+#ifdef LIVE_OBJECT_LIST
+  HandleScope scope;
+  CONVERT_SMI_CHECKED(obj_id, args[0]);
+  RUNTIME_ASSERT(args[1]->IsUndefined() || args[1]->IsJSObject());
+  RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsBoolean());
+  RUNTIME_ASSERT(args[3]->IsUndefined() || args[3]->IsSmi());
+  RUNTIME_ASSERT(args[4]->IsUndefined() || args[4]->IsSmi());
+  CONVERT_ARG_CHECKED(JSObject, filter_obj, 5);
+
+  Handle<JSObject> instance_filter;
+  if (args[1]->IsJSObject()) {
+    instance_filter = args.at<JSObject>(1);
+  }
+  bool verbose = false;
+  if (args[2]->IsBoolean()) {
+    verbose = args[2]->IsTrue();
+  }
+  int start = 0;
+  if (args[3]->IsSmi()) {
+    start = Smi::cast(args[3])->value();
+  }
+  int limit = Smi::kMaxValue;
+  if (args[4]->IsSmi()) {
+    limit = Smi::cast(args[4])->value();
+  }
+
+  return LiveObjectList::GetObjRetainers(obj_id,
+                                         instance_filter,
+                                         verbose,
+                                         start,
+                                         limit,
+                                         filter_obj);
+#else
+  return Heap::undefined_value();
+#endif
+}
+
+
+// Gets the reference path between 2 objects.
+static MaybeObject* Runtime_GetLOLPath(Arguments args) {
+#ifdef LIVE_OBJECT_LIST
+  HandleScope scope;
+  CONVERT_SMI_CHECKED(obj_id1, args[0]);
+  CONVERT_SMI_CHECKED(obj_id2, args[1]);
+  RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsJSObject());
+
+  Handle<JSObject> instance_filter;
+  if (args[2]->IsJSObject()) {
+    instance_filter = args.at<JSObject>(2);
+  }
+
+  Object* result =
+      LiveObjectList::GetPath(obj_id1, obj_id2, instance_filter);
+  return result;
+#else
+  return Heap::undefined_value();
+#endif
+}
+
+
+// Generates the response to a debugger request for a list of all
+// previously captured live object lists.
+static MaybeObject* Runtime_InfoLOL(Arguments args) {
+#ifdef LIVE_OBJECT_LIST
+  CONVERT_SMI_CHECKED(start, args[0]);
+  CONVERT_SMI_CHECKED(count, args[1]);
+  return LiveObjectList::Info(start, count);
+#else
+  return Heap::undefined_value();
+#endif
+}
+
+
+// Gets a dump of the specified object as requested by the debugger.
+// This is only used for obj ids shown in live object lists.
+static MaybeObject* Runtime_PrintLOLObj(Arguments args) {
+#ifdef LIVE_OBJECT_LIST
+  HandleScope scope;
+  CONVERT_SMI_CHECKED(obj_id, args[0]);
+  Object* result = LiveObjectList::PrintObj(obj_id);
+  return result;
+#else
+  return Heap::undefined_value();
+#endif
+}
+
+
+// Resets and releases all previously captured live object lists.
+static MaybeObject* Runtime_ResetLOL(Arguments args) {
+#ifdef LIVE_OBJECT_LIST
+  LiveObjectList::Reset();
+  return Heap::undefined_value();
+#else
+  return Heap::undefined_value();
+#endif
+}
+
+
+// Generates the response to a debugger request for a summary of the types
+// of objects in the difference between the captured live object lists
+// specified by id1 and id2.
+// If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
+// summarized.
+static MaybeObject* Runtime_SummarizeLOL(Arguments args) {
+#ifdef LIVE_OBJECT_LIST
+  HandleScope scope;
+  CONVERT_SMI_CHECKED(id1, args[0]);
+  CONVERT_SMI_CHECKED(id2, args[1]);
+  CONVERT_ARG_CHECKED(JSObject, filter_obj, 2);
+
+  EnterDebugger enter_debugger;
+  return LiveObjectList::Summarize(id1, id2, filter_obj);
+#else
+  return Heap::undefined_value();
+#endif
+}
+
 #endif  // ENABLE_DEBUGGER_SUPPORT
 
 
@@ -10789,7 +11294,8 @@
 
   limit = Max(limit, 0);  // Ensure that limit is not negative.
   int initial_size = Min(limit, 10);
-  Handle<JSArray> result = Factory::NewJSArray(initial_size * 4);
+  Handle<FixedArray> elements =
+      Factory::NewFixedArrayWithHoles(initial_size * 4);
 
   StackFrameIterator iter;
   // If the caller parameter is a function we skip frames until we're
@@ -10805,27 +11311,30 @@
       List<FrameSummary> frames(3);  // Max 2 levels of inlining.
       frame->Summarize(&frames);
       for (int i = frames.length() - 1; i >= 0; i--) {
+        if (cursor + 4 > elements->length()) {
+          int new_capacity = JSObject::NewElementsCapacity(elements->length());
+          Handle<FixedArray> new_elements =
+              Factory::NewFixedArrayWithHoles(new_capacity);
+          for (int i = 0; i < cursor; i++) {
+            new_elements->set(i, elements->get(i));
+          }
+          elements = new_elements;
+        }
+        ASSERT(cursor + 4 <= elements->length());
+
         Handle<Object> recv = frames[i].receiver();
         Handle<JSFunction> fun = frames[i].function();
         Handle<Code> code = frames[i].code();
         Handle<Smi> offset(Smi::FromInt(frames[i].offset()));
-        FixedArray* elements = FixedArray::cast(result->elements());
-        if (cursor + 3 < elements->length()) {
-          elements->set(cursor++, *recv);
-          elements->set(cursor++, *fun);
-          elements->set(cursor++, *code);
-          elements->set(cursor++, *offset);
-        } else {
-          SetElement(result, cursor++, recv);
-          SetElement(result, cursor++, fun);
-          SetElement(result, cursor++, code);
-          SetElement(result, cursor++, offset);
-        }
+        elements->set(cursor++, *recv);
+        elements->set(cursor++, *fun);
+        elements->set(cursor++, *code);
+        elements->set(cursor++, *offset);
       }
     }
     iter.Advance();
   }
-
+  Handle<JSArray> result = Factory::NewJSArrayWithElements(elements);
   result->set_length(Smi::FromInt(cursor));
   return *result;
 }
@@ -10990,7 +11499,13 @@
 static MaybeObject* Runtime_ListNatives(Arguments args) {
   ASSERT(args.length() == 0);
   HandleScope scope;
-  Handle<JSArray> result = Factory::NewJSArray(0);
+#define COUNT_ENTRY(Name, argc, ressize) + 1
+  int entry_count = 0
+      RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
+      INLINE_FUNCTION_LIST(COUNT_ENTRY)
+      INLINE_RUNTIME_FUNCTION_LIST(COUNT_ENTRY);
+#undef COUNT_ENTRY
+  Handle<FixedArray> elements = Factory::NewFixedArray(entry_count);
   int index = 0;
   bool inline_runtime_functions = false;
 #define ADD_ENTRY(Name, argc, ressize)                                       \
@@ -11005,10 +11520,11 @@
       name = Factory::NewStringFromAscii(                                    \
           Vector<const char>(#Name, StrLength(#Name)));                      \
     }                                                                        \
-    Handle<JSArray> pair = Factory::NewJSArray(0);                           \
-    SetElement(pair, 0, name);                                               \
-    SetElement(pair, 1, Handle<Smi>(Smi::FromInt(argc)));                    \
-    SetElement(result, index++, pair);                                       \
+    Handle<FixedArray> pair_elements = Factory::NewFixedArray(2);            \
+    pair_elements->set(0, *name);                                            \
+    pair_elements->set(1, Smi::FromInt(argc));                               \
+    Handle<JSArray> pair = Factory::NewJSArrayWithElements(pair_elements);   \
+    elements->set(index++, *pair);                                           \
   }
   inline_runtime_functions = false;
   RUNTIME_FUNCTION_LIST(ADD_ENTRY)
@@ -11016,6 +11532,8 @@
   INLINE_FUNCTION_LIST(ADD_ENTRY)
   INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
 #undef ADD_ENTRY
+  ASSERT_EQ(index, entry_count);
+  Handle<JSArray> result = Factory::NewJSArrayWithElements(elements);
   return *result;
 }
 #endif
diff --git a/src/runtime.h b/src/runtime.h
index fb2ff93..8e73d5c 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -45,7 +45,7 @@
   /* Property access */ \
   F(GetProperty, 2, 1) \
   F(KeyedGetProperty, 2, 1) \
-  F(DeleteProperty, 2, 1) \
+  F(DeleteProperty, 3, 1) \
   F(HasLocalProperty, 2, 1) \
   F(HasProperty, 2, 1) \
   F(HasElement, 2, 1) \
@@ -128,6 +128,7 @@
   \
   F(StringAdd, 2, 1) \
   F(StringBuilderConcat, 3, 1) \
+  F(StringBuilderJoin, 3, 1) \
   \
   /* Bit operations */ \
   F(NumberOr, 2, 1) \
@@ -240,7 +241,7 @@
   F(ResolvePossiblyDirectEval, 4, 2) \
   F(ResolvePossiblyDirectEvalNoLookup, 4, 2) \
   \
-  F(SetProperty, -1 /* 3 or 4 */, 1) \
+  F(SetProperty, -1 /* 4 or 5 */, 1) \
   F(DefineOrRedefineDataProperty, 4, 1) \
   F(DefineOrRedefineAccessorProperty, 5, 1) \
   F(IgnoreAttributesAndSetProperty, -1 /* 3 or 4 */, 1) \
@@ -287,12 +288,12 @@
   F(DeleteContextSlot, 2, 1) \
   F(LoadContextSlot, 2, 2) \
   F(LoadContextSlotNoReferenceError, 2, 2) \
-  F(StoreContextSlot, 3, 1) \
+  F(StoreContextSlot, 4, 1) \
   \
   /* Declarations and initialization */ \
-  F(DeclareGlobals, 3, 1) \
+  F(DeclareGlobals, 4, 1) \
   F(DeclareContextSlot, 4, 1) \
-  F(InitializeVarGlobal, -1 /* 1 or 2 */, 1) \
+  F(InitializeVarGlobal, -1 /* 2 or 3 */, 1) \
   F(InitializeConstGlobal, 2, 1) \
   F(InitializeConstContextSlot, 3, 1) \
   F(OptimizeObjectForAddingMultipleProperties, 2, 1) \
@@ -375,7 +376,21 @@
   \
   F(SetFlags, 1, 1) \
   F(CollectGarbage, 1, 1) \
-  F(GetHeapUsage, 0, 1)
+  F(GetHeapUsage, 0, 1) \
+  \
+  /* LiveObjectList support*/ \
+  F(HasLOLEnabled, 0, 1) \
+  F(CaptureLOL, 0, 1) \
+  F(DeleteLOL, 1, 1) \
+  F(DumpLOL, 5, 1) \
+  F(GetLOLObj, 1, 1) \
+  F(GetLOLObjId, 1, 1) \
+  F(GetLOLObjRetainers, 6, 1) \
+  F(GetLOLPath, 3, 1) \
+  F(InfoLOL, 2, 1) \
+  F(PrintLOLObj, 1, 1) \
+  F(ResetLOL, 0, 1) \
+  F(SummarizeLOL, 3, 1)
 
 #else
 #define RUNTIME_FUNCTION_LIST_DEBUGGER_SUPPORT(F)
@@ -537,7 +552,8 @@
       Handle<Object> object,
       Handle<Object> key,
       Handle<Object> value,
-      PropertyAttributes attr);
+      PropertyAttributes attr,
+      StrictModeFlag strict_mode);
 
   MUST_USE_RESULT static MaybeObject* ForceSetObjectProperty(
       Handle<JSObject> object,
diff --git a/src/runtime.js b/src/runtime.js
index 2cdbbde..66d839b 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -338,8 +338,8 @@
 */
 
 // ECMA-262, section 11.4.1, page 46.
-function DELETE(key) {
-  return %DeleteProperty(%ToObject(this), %ToString(key));
+function DELETE(key, strict) {
+  return %DeleteProperty(%ToObject(this), %ToString(key), strict);
 }
 
 
diff --git a/src/spaces.h b/src/spaces.h
index 4f2d07b..6165255 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -2121,6 +2121,12 @@
     accounting_stats_.DeallocateBytes(accounting_stats_.Size());
     accounting_stats_.AllocateBytes(new_size);
 
+    // Flush allocation watermarks.
+    for (Page* p = first_page_; p != top_page; p = p->next_page()) {
+      p->SetAllocationWatermark(p->AllocationTop());
+    }
+    top_page->SetAllocationWatermark(new_top);
+
 #ifdef DEBUG
     if (FLAG_enable_slow_asserts) {
       intptr_t actual_size = 0;
diff --git a/src/string.js b/src/string.js
index 2b73e0f..d8d402c 100644
--- a/src/string.js
+++ b/src/string.js
@@ -87,7 +87,7 @@
   if (len === 1) {
     return this_as_string + %_Arguments(0);
   }
-  var parts = new $Array(len + 1);
+  var parts = new InternalArray(len + 1);
   parts[0] = this_as_string;
   for (var i = 0; i < len; i++) {
     var part = %_Arguments(i);
@@ -357,7 +357,7 @@
 // TODO(lrn): This array will survive indefinitely if replace is never
 // called again. However, it will be empty, since the contents are cleared
 // in the finally block.
-var reusableReplaceArray = $Array(16);
+var reusableReplaceArray = new InternalArray(16);
 
 // Helper function for replacing regular expressions with the result of a
 // function application in String.prototype.replace.
@@ -370,7 +370,7 @@
     // of another replace) or we have failed to set the reusable array
     // back due to an exception in a replacement function. Create a new
     // array to use in the future, or until the original is written back.
-    resultArray = $Array(16);
+    resultArray = new InternalArray(16);
   }
   var res = %RegExpExecMultiple(regexp,
                                 subject,
@@ -386,7 +386,7 @@
   var i = 0;
   if (NUMBER_OF_CAPTURES(lastMatchInfo) == 2) {
     var match_start = 0;
-    var override = [null, 0, subject];
+    var override = new InternalArray(null, 0, subject);
     var receiver = %GetGlobalReceiver();
     while (i < len) {
       var elem = res[i];
@@ -447,7 +447,7 @@
     replacement =
         %_CallFunction(%GetGlobalReceiver(), s, index, subject, replace);
   } else {
-    var parameters = $Array(m + 2);
+    var parameters = new InternalArray(m + 2);
     for (var j = 0; j < m; j++) {
       parameters[j] = CaptureString(subject, matchInfo, j);
     }
@@ -720,7 +720,7 @@
   return %StringTrim(TO_STRING_INLINE(this), false, true);
 }
 
-var static_charcode_array = new $Array(4);
+var static_charcode_array = new InternalArray(4);
 
 // ECMA-262, section 15.5.3.2
 function StringFromCharCode(code) {
@@ -825,7 +825,7 @@
   if (%_ArgumentsLength() > 1) {
     this.elements = %_Arguments(1);
   } else {
-    this.elements = new $Array();
+    this.elements = new InternalArray();
   }
   this.special_string = str;
 }
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index f87728b..f23f382 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -498,13 +498,13 @@
                                           JSObject* receiver,
                                           int field_index,
                                           Map* transition,
-                                          Code::ExtraICState extra_ic_state) {
+                                          StrictModeFlag strict_mode) {
   PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
   Code::Flags flags = Code::ComputeMonomorphicFlags(
-      Code::STORE_IC, type, extra_ic_state);
+      Code::STORE_IC, type, strict_mode);
   Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
-    StoreStubCompiler compiler(extra_ic_state);
+    StoreStubCompiler compiler(strict_mode);
     { MaybeObject* maybe_code =
           compiler.CompileStoreField(receiver, field_index, transition, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
@@ -521,13 +521,15 @@
 }
 
 
-MaybeObject* StubCache::ComputeKeyedStoreSpecialized(JSObject* receiver) {
+MaybeObject* StubCache::ComputeKeyedStoreSpecialized(
+    JSObject* receiver,
+    StrictModeFlag strict_mode) {
   Code::Flags flags =
-      Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, NORMAL);
+      Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, NORMAL, strict_mode);
   String* name = Heap::KeyedStoreSpecialized_symbol();
   Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
-    KeyedStoreStubCompiler compiler;
+    KeyedStoreStubCompiler compiler(strict_mode);
     { MaybeObject* maybe_code = compiler.CompileStoreSpecialized(receiver);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
@@ -542,6 +544,35 @@
 }
 
 
+MaybeObject* StubCache::ComputeKeyedStorePixelArray(
+    JSObject* receiver,
+    StrictModeFlag strict_mode) {
+  // Using NORMAL as the PropertyType for array element stores is a misuse. The
+  // generated stub always accesses fast elements, not slow-mode fields, but
+  // some property type is required for the stub lookup. Note that overloading
+  // the NORMAL PropertyType is only safe as long as no stubs are generated for
+  // other keyed field stores. This is guaranteed to be the case since all field
+  // keyed stores that are not array elements go through a generic builtin stub.
+  Code::Flags flags =
+      Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, NORMAL, strict_mode);
+  String* name = Heap::KeyedStorePixelArray_symbol();
+  Object* code = receiver->map()->FindInCodeCache(name, flags);
+  if (code->IsUndefined()) {
+    KeyedStoreStubCompiler compiler(strict_mode);
+    { MaybeObject* maybe_code = compiler.CompileStorePixelArray(receiver);
+      if (!maybe_code->ToObject(&code)) return maybe_code;
+    }
+    PROFILE(CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, Code::cast(code), 0));
+    Object* result;
+    { MaybeObject* maybe_result =
+          receiver->UpdateMapCodeCache(name, Code::cast(code));
+      if (!maybe_result->ToObject(&result)) return maybe_result;
+    }
+  }
+  return code;
+}
+
+
 namespace {
 
 ExternalArrayType ElementsKindToExternalArrayType(JSObject::ElementsKind kind) {
@@ -571,11 +602,13 @@
 
 MaybeObject* StubCache::ComputeKeyedLoadOrStoreExternalArray(
     JSObject* receiver,
-    bool is_store) {
+    bool is_store,
+    StrictModeFlag strict_mode) {
   Code::Flags flags =
       Code::ComputeMonomorphicFlags(
           is_store ? Code::KEYED_STORE_IC : Code::KEYED_LOAD_IC,
-          NORMAL);
+          NORMAL,
+          strict_mode);
   ExternalArrayType array_type =
       ElementsKindToExternalArrayType(receiver->GetElementsKind());
   String* name =
@@ -588,9 +621,9 @@
   Object* code = map->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
     ExternalArrayStubCompiler compiler;
-    { MaybeObject* maybe_code =
-          is_store ? compiler.CompileKeyedStoreStub(array_type, flags) :
-          compiler.CompileKeyedLoadStub(array_type, flags);
+    { MaybeObject* maybe_code = is_store
+          ? compiler.CompileKeyedStoreStub(array_type, flags)
+          : compiler.CompileKeyedLoadStub(array_type, flags);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
     if (is_store) {
@@ -610,8 +643,8 @@
 }
 
 
-MaybeObject* StubCache::ComputeStoreNormal(Code::ExtraICState extra_ic_state) {
-  return Builtins::builtin(extra_ic_state == StoreIC::kStoreICStrict
+MaybeObject* StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
+  return Builtins::builtin((strict_mode == kStrictMode)
                             ? Builtins::StoreIC_Normal_Strict
                             : Builtins::StoreIC_Normal);
 }
@@ -620,12 +653,12 @@
 MaybeObject* StubCache::ComputeStoreGlobal(String* name,
                                            GlobalObject* receiver,
                                            JSGlobalPropertyCell* cell,
-                                           Code::ExtraICState extra_ic_state) {
+                                           StrictModeFlag strict_mode) {
   Code::Flags flags = Code::ComputeMonomorphicFlags(
-      Code::STORE_IC, NORMAL, extra_ic_state);
+      Code::STORE_IC, NORMAL, strict_mode);
   Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
-    StoreStubCompiler compiler(extra_ic_state);
+    StoreStubCompiler compiler(strict_mode);
     { MaybeObject* maybe_code =
           compiler.CompileStoreGlobal(receiver, cell, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
@@ -646,13 +679,13 @@
     String* name,
     JSObject* receiver,
     AccessorInfo* callback,
-    Code::ExtraICState extra_ic_state) {
+    StrictModeFlag strict_mode) {
   ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
   Code::Flags flags = Code::ComputeMonomorphicFlags(
-      Code::STORE_IC, CALLBACKS, extra_ic_state);
+      Code::STORE_IC, CALLBACKS, strict_mode);
   Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
-    StoreStubCompiler compiler(extra_ic_state);
+    StoreStubCompiler compiler(strict_mode);
     { MaybeObject* maybe_code =
           compiler.CompileStoreCallback(receiver, callback, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
@@ -672,12 +705,12 @@
 MaybeObject* StubCache::ComputeStoreInterceptor(
     String* name,
     JSObject* receiver,
-    Code::ExtraICState extra_ic_state) {
+    StrictModeFlag strict_mode) {
   Code::Flags flags = Code::ComputeMonomorphicFlags(
-      Code::STORE_IC, INTERCEPTOR, extra_ic_state);
+      Code::STORE_IC, INTERCEPTOR, strict_mode);
   Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
-    StoreStubCompiler compiler(extra_ic_state);
+    StoreStubCompiler compiler(strict_mode);
     { MaybeObject* maybe_code =
           compiler.CompileStoreInterceptor(receiver, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
@@ -697,12 +730,14 @@
 MaybeObject* StubCache::ComputeKeyedStoreField(String* name,
                                                JSObject* receiver,
                                                int field_index,
-                                               Map* transition) {
+                                               Map* transition,
+                                               StrictModeFlag strict_mode) {
   PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
-  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type);
+  Code::Flags flags = Code::ComputeMonomorphicFlags(
+      Code::KEYED_STORE_IC, type, strict_mode);
   Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
-    KeyedStoreStubCompiler compiler;
+    KeyedStoreStubCompiler compiler(strict_mode);
     { MaybeObject* maybe_code =
           compiler.CompileStoreField(receiver, field_index, transition, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
@@ -1390,12 +1425,17 @@
 
 
 MaybeObject* StoreInterceptorProperty(Arguments args) {
+  ASSERT(args.length() == 4);
   JSObject* recv = JSObject::cast(args[0]);
   String* name = String::cast(args[1]);
   Object* value = args[2];
+  StrictModeFlag strict_mode =
+      static_cast<StrictModeFlag>(Smi::cast(args[3])->value());
+  ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
   ASSERT(recv->HasNamedInterceptor());
   PropertyAttributes attr = NONE;
-  MaybeObject* result = recv->SetPropertyWithInterceptor(name, value, attr);
+  MaybeObject* result = recv->SetPropertyWithInterceptor(
+      name, value, attr, strict_mode);
   return result;
 }
 
@@ -1648,8 +1688,8 @@
 
 
 MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) {
-  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, type,
-                                                    extra_ic_state_);
+  Code::Flags flags = Code::ComputeMonomorphicFlags(
+      Code::STORE_IC, type, strict_mode_);
   MaybeObject* result = GetCodeWithFlags(flags, name);
   if (!result->IsFailure()) {
     PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG,
@@ -1664,7 +1704,8 @@
 
 
 MaybeObject* KeyedStoreStubCompiler::GetCode(PropertyType type, String* name) {
-  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type);
+  Code::Flags flags = Code::ComputeMonomorphicFlags(
+      Code::KEYED_STORE_IC, type, strict_mode_);
   MaybeObject* result = GetCodeWithFlags(flags, name);
   if (!result->IsFailure()) {
     PROFILE(CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 307939d..6927076 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -143,27 +143,27 @@
       JSObject* receiver,
       int field_index,
       Map* transition,
-      Code::ExtraICState extra_ic_state);
+      StrictModeFlag strict_mode);
 
   MUST_USE_RESULT static MaybeObject* ComputeStoreNormal(
-      Code::ExtraICState extra_ic_state);
+      StrictModeFlag strict_mode);
 
   MUST_USE_RESULT static MaybeObject* ComputeStoreGlobal(
       String* name,
       GlobalObject* receiver,
       JSGlobalPropertyCell* cell,
-      Code::ExtraICState extra_ic_state);
+      StrictModeFlag strict_mode);
 
   MUST_USE_RESULT static MaybeObject* ComputeStoreCallback(
       String* name,
       JSObject* receiver,
       AccessorInfo* callback,
-      Code::ExtraICState extra_ic_state);
+      StrictModeFlag strict_mode);
 
   MUST_USE_RESULT static MaybeObject* ComputeStoreInterceptor(
       String* name,
       JSObject* receiver,
-      Code::ExtraICState extra_ic_state);
+      StrictModeFlag strict_mode);
 
   // ---
 
@@ -171,14 +171,21 @@
       String* name,
       JSObject* receiver,
       int field_index,
-      Map* transition = NULL);
+      Map* transition,
+      StrictModeFlag strict_mode);
 
   MUST_USE_RESULT static MaybeObject* ComputeKeyedStoreSpecialized(
-      JSObject* receiver);
+      JSObject* receiver,
+      StrictModeFlag strict_mode);
+
+  MUST_USE_RESULT static MaybeObject* ComputeKeyedStorePixelArray(
+      JSObject* receiver,
+      StrictModeFlag strict_mode);
 
   MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadOrStoreExternalArray(
       JSObject* receiver,
-      bool is_store);
+      bool is_store,
+      StrictModeFlag strict_mode);
 
   // ---
 
@@ -625,8 +632,8 @@
 
 class StoreStubCompiler: public StubCompiler {
  public:
-  explicit StoreStubCompiler(Code::ExtraICState extra_ic_state)
-    : extra_ic_state_(extra_ic_state) { }
+  explicit StoreStubCompiler(StrictModeFlag strict_mode)
+    : strict_mode_(strict_mode) { }
 
   MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
                                                  int index,
@@ -646,12 +653,15 @@
  private:
   MaybeObject* GetCode(PropertyType type, String* name);
 
-  Code::ExtraICState extra_ic_state_;
+  StrictModeFlag strict_mode_;
 };
 
 
 class KeyedStoreStubCompiler: public StubCompiler {
  public:
+  explicit KeyedStoreStubCompiler(StrictModeFlag strict_mode)
+    : strict_mode_(strict_mode) { }
+
   MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
                                                  int index,
                                                  Map* transition,
@@ -659,8 +669,12 @@
 
   MUST_USE_RESULT MaybeObject* CompileStoreSpecialized(JSObject* receiver);
 
+  MUST_USE_RESULT MaybeObject* CompileStorePixelArray(JSObject* receiver);
+
  private:
   MaybeObject* GetCode(PropertyType type, String* name);
+
+  StrictModeFlag strict_mode_;
 };
 
 
diff --git a/src/top.cc b/src/top.cc
index 3364c0d..78db26a 100644
--- a/src/top.cc
+++ b/src/top.cc
@@ -333,7 +333,7 @@
 
 
 void Top::UnregisterTryCatchHandler(v8::TryCatch* that) {
-  ASSERT(thread_local_.TryCatchHandler() == that);
+  ASSERT(try_catch_handler() == that);
   thread_local_.set_try_catch_handler_address(
       reinterpret_cast<Address>(that->next_));
   thread_local_.catcher_ = NULL;
@@ -732,6 +732,12 @@
 
 
 Failure* Top::ReThrow(MaybeObject* exception, MessageLocation* location) {
+  bool can_be_caught_externally = false;
+  ShouldReportException(&can_be_caught_externally,
+                        is_catchable_by_javascript(exception));
+  thread_local_.catcher_ = can_be_caught_externally ?
+      try_catch_handler() : NULL;
+
   // Set the exception being re-thrown.
   set_pending_exception(exception);
   return Failure::Exception();
@@ -807,7 +813,7 @@
 }
 
 
-bool Top::ShouldReportException(bool* is_caught_externally,
+bool Top::ShouldReportException(bool* can_be_caught_externally,
                                 bool catchable_by_javascript) {
   // Find the top-most try-catch handler.
   StackHandler* handler =
@@ -823,13 +829,13 @@
   // The exception has been externally caught if and only if there is
   // an external handler which is on top of the top-most try-catch
   // handler.
-  *is_caught_externally = external_handler_address != NULL &&
+  *can_be_caught_externally = external_handler_address != NULL &&
       (handler == NULL || handler->address() > external_handler_address ||
        !catchable_by_javascript);
 
-  if (*is_caught_externally) {
+  if (*can_be_caught_externally) {
     // Only report the exception if the external handler is verbose.
-    return thread_local_.TryCatchHandler()->is_verbose_;
+    return try_catch_handler()->is_verbose_;
   } else {
     // Report the exception if it isn't caught by JavaScript code.
     return handler == NULL;
@@ -848,14 +854,12 @@
   Handle<Object> exception_handle(exception_object);
 
   // Determine reporting and whether the exception is caught externally.
-  bool is_out_of_memory = exception == Failure::OutOfMemoryException();
-  bool is_termination_exception = exception == Heap::termination_exception();
-  bool catchable_by_javascript = !is_termination_exception && !is_out_of_memory;
+  bool catchable_by_javascript = is_catchable_by_javascript(exception);
   // Only real objects can be caught by JS.
   ASSERT(!catchable_by_javascript || is_object);
-  bool is_caught_externally = false;
+  bool can_be_caught_externally = false;
   bool should_report_exception =
-      ShouldReportException(&is_caught_externally, catchable_by_javascript);
+      ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
   bool report_exception = catchable_by_javascript && should_report_exception;
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
@@ -869,8 +873,8 @@
   Handle<Object> message_obj;
   MessageLocation potential_computed_location;
   bool try_catch_needs_message =
-      is_caught_externally &&
-      thread_local_.TryCatchHandler()->capture_message_;
+      can_be_caught_externally &&
+      try_catch_handler()->capture_message_;
   if (report_exception || try_catch_needs_message) {
     if (location == NULL) {
       // If no location was specified we use a computed one instead
@@ -908,9 +912,10 @@
     }
   }
 
-  if (is_caught_externally) {
-    thread_local_.catcher_ = thread_local_.TryCatchHandler();
-  }
+  // Do not forget to clean catcher_ if currently thrown exception cannot
+  // be caught.  If necessary, ReThrow will update the catcher.
+  thread_local_.catcher_ = can_be_caught_externally ?
+      try_catch_handler() : NULL;
 
   // NOTE: Notifying the debugger or generating the message
   // may have caused new exceptions. For now, we just ignore
@@ -925,22 +930,63 @@
 }
 
 
+bool Top::IsExternallyCaught() {
+  ASSERT(has_pending_exception());
+
+  if ((thread_local_.catcher_ == NULL) ||
+      (try_catch_handler() != thread_local_.catcher_)) {
+    // When throwing the exception, we found no v8::TryCatch
+    // which should care about this exception.
+    return false;
+  }
+
+  if (!is_catchable_by_javascript(pending_exception())) {
+    return true;
+  }
+
+  // Get the address of the external handler so we can compare the address to
+  // determine which one is closer to the top of the stack.
+  Address external_handler_address = thread_local_.try_catch_handler_address();
+  ASSERT(external_handler_address != NULL);
+
+  // The exception has been externally caught if and only if there is
+  // an external handler which is on top of the top-most try-finally
+  // handler.
+  // There should be no try-catch blocks as they would prohibit us from
+  // finding external catcher in the first place (see catcher_ check above).
+  //
+  // Note, that finally clause would rethrow an exception unless it's
+  // aborted by jumps in control flow like return, break, etc. and we'll
+  // have another chances to set proper v8::TryCatch.
+  StackHandler* handler =
+      StackHandler::FromAddress(Top::handler(Top::GetCurrentThread()));
+  while (handler != NULL && handler->address() < external_handler_address) {
+    ASSERT(!handler->is_try_catch());
+    if (handler->is_try_finally()) return false;
+
+    handler = handler->next();
+  }
+
+  return true;
+}
+
+
 void Top::ReportPendingMessages() {
   ASSERT(has_pending_exception());
-  setup_external_caught();
   // If the pending exception is OutOfMemoryException set out_of_memory in
   // the global context.  Note: We have to mark the global context here
   // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to
   // set it.
-  bool external_caught = thread_local_.external_caught_exception_;
+  bool external_caught = IsExternallyCaught();
+  thread_local_.external_caught_exception_ = external_caught;
   HandleScope scope;
   if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) {
     context()->mark_out_of_memory();
   } else if (thread_local_.pending_exception_ ==
              Heap::termination_exception()) {
     if (external_caught) {
-      thread_local_.TryCatchHandler()->can_continue_ = false;
-      thread_local_.TryCatchHandler()->exception_ = Heap::null_value();
+      try_catch_handler()->can_continue_ = false;
+      try_catch_handler()->exception_ = Heap::null_value();
     }
   } else {
     // At this point all non-object (failure) exceptions have
@@ -949,9 +995,8 @@
     Handle<Object> exception(pending_exception_object);
     thread_local_.external_caught_exception_ = false;
     if (external_caught) {
-      thread_local_.TryCatchHandler()->can_continue_ = true;
-      thread_local_.TryCatchHandler()->exception_ =
-        thread_local_.pending_exception_;
+      try_catch_handler()->can_continue_ = true;
+      try_catch_handler()->exception_ = thread_local_.pending_exception_;
       if (!thread_local_.pending_message_obj_->IsTheHole()) {
         try_catch_handler()->message_ = thread_local_.pending_message_obj_;
       }
diff --git a/src/top.h b/src/top.h
index c052dad..26ae542 100644
--- a/src/top.h
+++ b/src/top.h
@@ -249,12 +249,7 @@
     thread_local_.scheduled_exception_ = Heap::the_hole_value();
   }
 
-  static void setup_external_caught() {
-    thread_local_.external_caught_exception_ =
-        has_pending_exception() &&
-        (thread_local_.catcher_ != NULL) &&
-        (try_catch_handler() == thread_local_.catcher_);
-  }
+  static bool IsExternallyCaught();
 
   static void SetCaptureStackTraceForUncaughtExceptions(
       bool capture,
@@ -265,6 +260,11 @@
   // exception.
   static bool is_out_of_memory();
 
+  static bool is_catchable_by_javascript(MaybeObject* exception) {
+    return (exception != Failure::OutOfMemoryException()) &&
+        (exception != Heap::termination_exception());
+  }
+
   // JS execution stack (see frames.h).
   static Address c_entry_fp(ThreadLocalTop* thread) {
     return thread->c_entry_fp_;
@@ -397,7 +397,7 @@
                       const char* message);
   // Checks if exception should be reported and finds out if it's
   // caught externally.
-  static bool ShouldReportException(bool* is_caught_externally,
+  static bool ShouldReportException(bool* can_be_caught_externally,
                                     bool catchable_by_javascript);
 
   // Attempts to compute the current source location, storing the
diff --git a/src/type-info.cc b/src/type-info.cc
index 0bb7262..3438ff8 100644
--- a/src/type-info.cc
+++ b/src/type-info.cc
@@ -337,26 +337,27 @@
       // position by making sure that we have position information
       // recorded for all binary ICs.
       if (GetElement(map_, position)->IsUndefined()) {
-        SetElement(map_, position, target);
+        SetElement(map_, position, target, kNonStrictMode);
       }
     } else if (state == MONOMORPHIC) {
       if (target->kind() != Code::CALL_IC ||
           target->check_type() == RECEIVER_MAP_CHECK) {
         Handle<Map> map = Handle<Map>(target->FindFirstMap());
         if (*map == NULL) {
-          SetElement(map_, position, target);
+          SetElement(map_, position, target, kNonStrictMode);
         } else {
-          SetElement(map_, position, map);
+          SetElement(map_, position, map, kNonStrictMode);
         }
       } else {
         ASSERT(target->kind() == Code::CALL_IC);
         CheckType check = target->check_type();
         ASSERT(check != RECEIVER_MAP_CHECK);
-        SetElement(map_, position, Handle<Object>(Smi::FromInt(check)));
+        SetElement(map_, position,
+                   Handle<Object>(Smi::FromInt(check)), kNonStrictMode);
         ASSERT(Smi::cast(*GetElement(map_, position))->value() == check);
       }
     } else if (state == MEGAMORPHIC) {
-      SetElement(map_, position, target);
+      SetElement(map_, position, target, kNonStrictMode);
     }
   }
 }
diff --git a/src/v8.cc b/src/v8.cc
index 0ff7649..945043d 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -54,7 +54,12 @@
   if (has_been_disposed_ || has_fatal_error_) return false;
   if (IsRunning()) return true;
 
+#if defined(V8_TARGET_ARCH_ARM) && !defined(USE_ARM_EABI)
+  use_crankshaft_ = false;
+#else
   use_crankshaft_ = FLAG_crankshaft;
+#endif
+
   // Peephole optimization might interfere with deoptimization.
   FLAG_peephole_optimization = !use_crankshaft_;
   is_running_ = true;
diff --git a/src/v8natives.js b/src/v8natives.js
index 83b00b0..563de73 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -92,7 +92,7 @@
 
 // ECMA-262 - 15.1.2.2
 function GlobalParseInt(string, radix) {
-  if (IS_UNDEFINED(radix)) {
+  if (IS_UNDEFINED(radix) || radix === 10 || radix === 0) {
     // Some people use parseInt instead of Math.floor.  This
     // optimization makes parseInt on a Smi 12 times faster (60ns
     // vs 800ns).  The following optimization makes parseInt on a
@@ -105,7 +105,7 @@
       // Truncate number.
       return string | 0;
     }
-    radix = 0;
+    if (IS_UNDEFINED(radix)) radix = 0;
   } else {
     radix = TO_INT32(radix);
     if (!(radix == 0 || (2 <= radix && radix <= 36)))
@@ -143,7 +143,7 @@
   var f = %CompileString(x);
   if (!IS_FUNCTION(f)) return f;
 
-  return f.call(this);
+  return %_CallFunction(this, f);
 }
 
 
@@ -152,7 +152,7 @@
   // NOTE: We don't care about the character casing.
   if (!lang || /javascript/i.test(lang)) {
     var f = %CompileString(ToString(expr));
-    f.call(%GlobalReceiver(global));
+    %_CallFunction(%GlobalReceiver(global), f);
   }
   return null;
 }
@@ -586,17 +586,20 @@
       // Step 7
       if (desc.isConfigurable() ||
           (desc.hasEnumerable() &&
-           desc.isEnumerable() != current.isEnumerable()))
+           desc.isEnumerable() != current.isEnumerable())) {
         throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+      }
       // Step 8
       if (!IsGenericDescriptor(desc)) {
         // Step 9a
-        if (IsDataDescriptor(current) != IsDataDescriptor(desc))
+        if (IsDataDescriptor(current) != IsDataDescriptor(desc)) {
           throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+        }
         // Step 10a
         if (IsDataDescriptor(current) && IsDataDescriptor(desc)) {
-          if (!current.isWritable() && desc.isWritable())
+          if (!current.isWritable() && desc.isWritable()) {
             throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+          }
           if (!current.isWritable() && desc.hasValue() &&
               !SameValue(desc.getValue(), current.getValue())) {
             throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
@@ -604,11 +607,12 @@
         }
         // Step 11
         if (IsAccessorDescriptor(desc) && IsAccessorDescriptor(current)) {
-          if (desc.hasSetter() && !SameValue(desc.getSet(), current.getSet())){
+          if (desc.hasSetter() && !SameValue(desc.getSet(), current.getSet())) {
             throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
           }
-          if (desc.hasGetter() && !SameValue(desc.getGet(),current.getGet()))
+          if (desc.hasGetter() && !SameValue(desc.getGet(),current.getGet())) {
             throw MakeTypeError("redefine_disallowed", ["defineProperty"]);
+          }
         }
       }
     }
@@ -1166,7 +1170,7 @@
       return fn.apply(this_arg, arguments);
     };
   } else {
-    var bound_args = new $Array(argc_bound);
+    var bound_args = new InternalArray(argc_bound);
     for(var i = 0; i < argc_bound; i++) {
       bound_args[i] = %_Arguments(i+1);
     }
@@ -1184,7 +1188,7 @@
       // Combine the args we got from the bind call with the args
       // given as argument to the invocation.
       var argc = %_ArgumentsLength();
-      var args = new $Array(argc + argc_bound);
+      var args = new InternalArray(argc + argc_bound);
       // Add bound arguments.
       for (var i = 0; i < argc_bound; i++) {
         args[i] = bound_args[i];
@@ -1216,7 +1220,7 @@
   var n = %_ArgumentsLength();
   var p = '';
   if (n > 1) {
-    p = new $Array(n - 1);
+    p = new InternalArray(n - 1);
     for (var i = 0; i < n - 1; i++) p[i] = %_Arguments(i);
     p = Join(p, n - 1, ',', NonStringToString);
     // If the formal parameters string include ) - an illegal
diff --git a/src/version.cc b/src/version.cc
index 2471bc9..ac4ab4a 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -33,9 +33,9 @@
 // NOTE these macros are used by the SCons build script so their names
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
-#define MINOR_VERSION     1
-#define BUILD_NUMBER      4
-#define PATCH_LEVEL       0
+#define MINOR_VERSION     2
+#define BUILD_NUMBER      0
+#define PATCH_LEVEL       1
 #define CANDIDATE_VERSION false
 
 // Define SONAME to have the SCons build the put a specific SONAME into the
diff --git a/src/virtual-frame-heavy-inl.h b/src/virtual-frame-heavy-inl.h
index 2755eee..cf12eca 100644
--- a/src/virtual-frame-heavy-inl.h
+++ b/src/virtual-frame-heavy-inl.h
@@ -82,10 +82,8 @@
 }
 
 
-void VirtualFrame::Push(Handle<Object> value) {
-  FrameElement element =
-      FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED);
-  elements_.Add(element);
+bool VirtualFrame::ConstantPoolOverflowed() {
+  return FrameElement::ConstantPoolOverflowed();
 }
 
 
diff --git a/src/x64/assembler-x64-inl.h b/src/x64/assembler-x64-inl.h
index 285c078..b082624 100644
--- a/src/x64/assembler-x64-inl.h
+++ b/src/x64/assembler-x64-inl.h
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 697f6cd..41111a7 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -190,13 +190,13 @@
 // -----------------------------------------------------------------------------
 // Register constants.
 
-const int Register::registerCodeByAllocationIndex[kNumAllocatableRegisters] = {
-    // rax, rbx, rdx, rcx, rdi, r8, r9, r11, r14, r12
-    0, 3, 2, 1, 7, 8, 9, 11, 14, 12
+const int Register::kRegisterCodeByAllocationIndex[kNumAllocatableRegisters] = {
+  // rax, rbx, rdx, rcx, rdi, r8, r9, r11, r14, r12
+  0, 3, 2, 1, 7, 8, 9, 11, 14, 12
 };
 
-const int Register::allocationIndexByRegisterCode[kNumRegisters] = {
-    0, 3, 2, 1, -1, -1, -1, 4, 5, 6, -1, 7, 9, -1, 8, -1
+const int Register::kAllocationIndexByRegisterCode[kNumRegisters] = {
+  0, 3, 2, 1, -1, -1, -1, 4, 5, 6, -1, 7, 9, -1, 8, -1
 };
 
 
@@ -2995,6 +2995,28 @@
 }
 
 
+void Assembler::andpd(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x54);
+  emit_sse_operand(dst, src);
+}
+
+
+void Assembler::orpd(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x56);
+  emit_sse_operand(dst, src);
+}
+
+
 void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
@@ -3114,8 +3136,8 @@
 }
 
 
-void Assembler::RecordComment(const char* msg) {
-  if (FLAG_code_comments) {
+void Assembler::RecordComment(const char* msg, bool force) {
+  if (FLAG_code_comments || force) {
     EnsureSpace ensure_space(this);
     RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
   }
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index 91e7e6c..f6cd570 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -30,7 +30,7 @@
 
 // The original source code covered by the above license above has been
 // modified significantly by Google Inc.
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 
 // A lightweight X64 Assembler.
 
@@ -99,12 +99,12 @@
   static const int kNumAllocatableRegisters = 10;
 
   static int ToAllocationIndex(Register reg) {
-    return allocationIndexByRegisterCode[reg.code()];
+    return kAllocationIndexByRegisterCode[reg.code()];
   }
 
   static Register FromAllocationIndex(int index) {
     ASSERT(index >= 0 && index < kNumAllocatableRegisters);
-    Register result = { registerCodeByAllocationIndex[index] };
+    Register result = { kRegisterCodeByAllocationIndex[index] };
     return result;
   }
 
@@ -155,8 +155,8 @@
   int code_;
 
  private:
-  static const int registerCodeByAllocationIndex[kNumAllocatableRegisters];
-  static const int allocationIndexByRegisterCode[kNumRegisters];
+  static const int kRegisterCodeByAllocationIndex[kNumAllocatableRegisters];
+  static const int kAllocationIndexByRegisterCode[kNumRegisters];
 };
 
 const Register rax = { 0 };
@@ -1284,6 +1284,8 @@
   void mulsd(XMMRegister dst, XMMRegister src);
   void divsd(XMMRegister dst, XMMRegister src);
 
+  void andpd(XMMRegister dst, XMMRegister src);
+  void orpd(XMMRegister dst, XMMRegister src);
   void xorpd(XMMRegister dst, XMMRegister src);
   void sqrtsd(XMMRegister dst, XMMRegister src);
 
@@ -1312,7 +1314,7 @@
 
   // Record a comment relocation entry that can be used by a disassembler.
   // Use --code-comments to enable.
-  void RecordComment(const char* msg);
+  void RecordComment(const char* msg, bool force = false);
 
   // Writes a single word of data in the code stream.
   // Used for inline tables, e.g., jump-tables.
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index 08cd21d..b545876 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -601,7 +601,16 @@
 
 
 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
-  __ int3();
+  // For now, we are relying on the fact that Runtime::NotifyOSR
+  // doesn't do any garbage collection which allows us to save/restore
+  // the registers without worrying about which of them contain
+  // pointers. This seems a bit fragile.
+  __ Pushad();
+  __ EnterInternalFrame();
+  __ CallRuntime(Runtime::kNotifyOSR, 0);
+  __ LeaveInternalFrame();
+  __ Popad();
+  __ ret(0);
 }
 
 
@@ -642,6 +651,13 @@
     // Change context eagerly in case we need the global receiver.
     __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
 
+    // Do not transform the receiver for strict mode functions.
+    __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
+    __ testb(FieldOperand(rbx, SharedFunctionInfo::kStrictModeByteOffset),
+             Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
+    __ j(not_equal, &shift_arguments);
+
+    // Compute the receiver in non-strict mode.
     __ movq(rbx, Operand(rsp, rax, times_pointer_size, 0));
     __ JumpIfSmi(rbx, &convert_to_object);
 
@@ -798,6 +814,14 @@
   // Compute the receiver.
   Label call_to_object, use_global_receiver, push_receiver;
   __ movq(rbx, Operand(rbp, kReceiverOffset));
+
+  // Do not transform the receiver for strict mode functions.
+  __ movq(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
+  __ testb(FieldOperand(rdx, SharedFunctionInfo::kStrictModeByteOffset),
+           Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
+  __ j(not_equal, &push_receiver);
+
+  // Compute the receiver in non-strict mode.
   __ JumpIfSmi(rbx, &call_to_object);
   __ CompareRoot(rbx, Heap::kNullValueRootIndex);
   __ j(equal, &use_global_receiver);
@@ -1224,7 +1248,7 @@
   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rdi);
 
   if (FLAG_debug_code) {
-    // Initial map for the builtin Array function shoud be a map.
+    // Initial map for the builtin Array functions should be maps.
     __ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
     // Will both indicate a NULL and a Smi.
     ASSERT(kSmiTag == 0);
@@ -1256,11 +1280,8 @@
   Label generic_constructor;
 
   if (FLAG_debug_code) {
-    // The array construct code is only set for the builtin Array function which
-    // does always have a map.
-    __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rbx);
-    __ cmpq(rdi, rbx);
-    __ Check(equal, "Unexpected Array function");
+    // The array construct code is only set for the builtin and internal
+    // Array functions which always have a map.
     // Initial map for the builtin Array function should be a map.
     __ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
     // Will both indicate a NULL and a Smi.
@@ -1406,7 +1427,58 @@
 
 
 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
-  __ int3();
+  // Get the loop depth of the stack guard check. This is recorded in
+  // a test(rax, depth) instruction right after the call.
+  Label stack_check;
+  __ movq(rbx, Operand(rsp, 0));  // return address
+  __ movzxbq(rbx, Operand(rbx, 1));  // depth
+
+  // Get the loop nesting level at which we allow OSR from the
+  // unoptimized code and check if we want to do OSR yet. If not we
+  // should perform a stack guard check so we can get interrupts while
+  // waiting for on-stack replacement.
+  __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
+  __ movq(rcx, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
+  __ movq(rcx, FieldOperand(rcx, SharedFunctionInfo::kCodeOffset));
+  __ cmpb(rbx, FieldOperand(rcx, Code::kAllowOSRAtLoopNestingLevelOffset));
+  __ j(greater, &stack_check);
+
+  // Pass the function to optimize as the argument to the on-stack
+  // replacement runtime function.
+  __ EnterInternalFrame();
+  __ push(rax);
+  __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
+  __ LeaveInternalFrame();
+
+  // If the result was -1 it means that we couldn't optimize the
+  // function. Just return and continue in the unoptimized version.
+  NearLabel skip;
+  __ SmiCompare(rax, Smi::FromInt(-1));
+  __ j(not_equal, &skip);
+  __ ret(0);
+
+  // If we decide not to perform on-stack replacement we perform a
+  // stack guard check to enable interrupts.
+  __ bind(&stack_check);
+  NearLabel ok;
+  __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
+  __ j(above_equal, &ok);
+
+  StackCheckStub stub;
+  __ TailCallStub(&stub);
+  __ Abort("Unreachable code: returned from tail call.");
+  __ bind(&ok);
+  __ ret(0);
+
+  __ bind(&skip);
+  // Untag the AST id and push it on the stack.
+  __ SmiToInteger32(rax, rax);
+  __ push(rax);
+
+  // Generate the code for doing the frame-to-frame translation using
+  // the deoptimizer infrastructure.
+  Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR);
+  generator.Generate();
 }
 
 
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 4b4531e..eb92978 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -1336,54 +1336,33 @@
 
 
 void TypeRecordingBinaryOpStub::GenerateStringAddCode(MacroAssembler* masm) {
-  GenerateRegisterArgsPush(masm);
+  ASSERT(op_ == Token::ADD);
+  NearLabel left_not_string, call_runtime;
+
   // Registers containing left and right operands respectively.
-  Register lhs = rdx;
-  Register rhs = rax;
+  Register left = rdx;
+  Register right = rax;
 
-  // Test for string arguments before calling runtime.
-  Label not_strings, both_strings, not_string1, string1, string1_smi2;
+  // Test if left operand is a string.
+  __ JumpIfSmi(left, &left_not_string);
+  __ CmpObjectType(left, FIRST_NONSTRING_TYPE, rcx);
+  __ j(above_equal, &left_not_string);
+  StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB);
+  GenerateRegisterArgsPush(masm);
+  __ TailCallStub(&string_add_left_stub);
 
-  __ JumpIfNotString(lhs, r8, &not_string1);
+  // Left operand is not a string, test right.
+  __ bind(&left_not_string);
+  __ JumpIfSmi(right, &call_runtime);
+  __ CmpObjectType(right, FIRST_NONSTRING_TYPE, rcx);
+  __ j(above_equal, &call_runtime);
 
-  // First argument is a a string, test second.
-  __ JumpIfSmi(rhs, &string1_smi2);
-  __ CmpObjectType(rhs, FIRST_NONSTRING_TYPE, r9);
-  __ j(above_equal, &string1);
+  StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB);
+  GenerateRegisterArgsPush(masm);
+  __ TailCallStub(&string_add_right_stub);
 
-  // First and second argument are strings.
-  StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB);
-  __ TailCallStub(&string_add_stub);
-
-  __ bind(&string1_smi2);
-  // First argument is a string, second is a smi. Try to lookup the number
-  // string for the smi in the number string cache.
-  NumberToStringStub::GenerateLookupNumberStringCache(
-      masm, rhs, rbx, rcx, r8, true, &string1);
-
-  // Replace second argument on stack and tailcall string add stub to make
-  // the result.
-  __ movq(Operand(rsp, 1 * kPointerSize), rbx);
-  __ TailCallStub(&string_add_stub);
-
-  // Only first argument is a string.
-  __ bind(&string1);
-  __ InvokeBuiltin(Builtins::STRING_ADD_LEFT, JUMP_FUNCTION);
-
-  // First argument was not a string, test second.
-  __ bind(&not_string1);
-  __ JumpIfNotString(rhs, rhs, &not_strings);
-
-  // Only second argument is a string.
-  __ InvokeBuiltin(Builtins::STRING_ADD_RIGHT, JUMP_FUNCTION);
-
-  __ bind(&not_strings);
   // Neither argument is a string.
-  // Pop arguments, because CallRuntimeCode wants to push them again.
-  __ pop(rcx);
-  __ pop(rax);
-  __ pop(rdx);
-  __ push(rcx);
+  __ bind(&call_runtime);
 }
 
 
@@ -1440,9 +1419,11 @@
 
 
 void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
+  ASSERT(operands_type_ == TRBinaryOpIC::STRING);
   ASSERT(op_ == Token::ADD);
   GenerateStringAddCode(masm);
-
+  // Try to add arguments as strings, otherwise, transition to the generic
+  // TRBinaryOpIC type.
   GenerateTypeTransition(masm);
 }
 
@@ -1525,40 +1506,59 @@
 
 
 void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
-  // Input on stack:
-  // rsp[8]: argument (should be number).
-  // rsp[0]: return address.
+  // TAGGED case:
+  //   Input:
+  //     rsp[8]: argument (should be number).
+  //     rsp[0]: return address.
+  //   Output:
+  //     rax: tagged double result.
+  // UNTAGGED case:
+  //   Input::
+  //     rsp[0]: return address.
+  //     xmm1: untagged double input argument
+  //   Output:
+  //     xmm1: untagged double result.
+
   Label runtime_call;
   Label runtime_call_clear_stack;
-  Label input_not_smi;
-  NearLabel loaded;
-  // Test that rax is a number.
-  __ movq(rax, Operand(rsp, kPointerSize));
-  __ JumpIfNotSmi(rax, &input_not_smi);
-  // Input is a smi. Untag and load it onto the FPU stack.
-  // Then load the bits of the double into rbx.
-  __ SmiToInteger32(rax, rax);
-  __ subq(rsp, Immediate(kPointerSize));
-  __ cvtlsi2sd(xmm1, rax);
-  __ movsd(Operand(rsp, 0), xmm1);
-  __ movq(rbx, xmm1);
-  __ movq(rdx, xmm1);
-  __ fld_d(Operand(rsp, 0));
-  __ addq(rsp, Immediate(kPointerSize));
-  __ jmp(&loaded);
+  Label skip_cache;
+  const bool tagged = (argument_type_ == TAGGED);
+  if (tagged) {
+    NearLabel input_not_smi;
+    NearLabel loaded;
+    // Test that rax is a number.
+    __ movq(rax, Operand(rsp, kPointerSize));
+    __ JumpIfNotSmi(rax, &input_not_smi);
+    // Input is a smi. Untag and load it onto the FPU stack.
+    // Then load the bits of the double into rbx.
+    __ SmiToInteger32(rax, rax);
+    __ subq(rsp, Immediate(kDoubleSize));
+    __ cvtlsi2sd(xmm1, rax);
+    __ movsd(Operand(rsp, 0), xmm1);
+    __ movq(rbx, xmm1);
+    __ movq(rdx, xmm1);
+    __ fld_d(Operand(rsp, 0));
+    __ addq(rsp, Immediate(kDoubleSize));
+    __ jmp(&loaded);
 
-  __ bind(&input_not_smi);
-  // Check if input is a HeapNumber.
-  __ Move(rbx, Factory::heap_number_map());
-  __ cmpq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
-  __ j(not_equal, &runtime_call);
-  // Input is a HeapNumber. Push it on the FPU stack and load its
-  // bits into rbx.
-  __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset));
-  __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset));
-  __ movq(rdx, rbx);
-  __ bind(&loaded);
-  // ST[0] == double value
+    __ bind(&input_not_smi);
+    // Check if input is a HeapNumber.
+    __ LoadRoot(rbx, Heap::kHeapNumberMapRootIndex);
+    __ cmpq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
+    __ j(not_equal, &runtime_call);
+    // Input is a HeapNumber. Push it on the FPU stack and load its
+    // bits into rbx.
+    __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset));
+    __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset));
+    __ movq(rdx, rbx);
+
+    __ bind(&loaded);
+  } else {  // UNTAGGED.
+    __ movq(rbx, xmm1);
+    __ movq(rdx, xmm1);
+  }
+
+  // ST[0] == double value, if TAGGED.
   // rbx = bits of double value.
   // rdx = also bits of double value.
   // Compute hash (h is 32 bits, bits are 64 and the shifts are arithmetic):
@@ -1590,7 +1590,7 @@
   // rax points to the cache for the type type_.
   // If NULL, the cache hasn't been initialized yet, so go through runtime.
   __ testq(rax, rax);
-  __ j(zero, &runtime_call_clear_stack);
+  __ j(zero, &runtime_call_clear_stack);  // Only clears stack if TAGGED.
 #ifdef DEBUG
   // Check that the layout of cache elements match expectations.
   {  // NOLINT - doesn't like a single brace on a line.
@@ -1616,30 +1616,70 @@
   __ j(not_equal, &cache_miss);
   // Cache hit!
   __ movq(rax, Operand(rcx, 2 * kIntSize));
-  __ fstp(0);  // Clear FPU stack.
-  __ ret(kPointerSize);
+  if (tagged) {
+    __ fstp(0);  // Clear FPU stack.
+    __ ret(kPointerSize);
+  } else {  // UNTAGGED.
+    __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
+    __ Ret();
+  }
 
   __ bind(&cache_miss);
   // Update cache with new value.
-  Label nan_result;
-  GenerateOperation(masm, &nan_result);
+  if (tagged) {
   __ AllocateHeapNumber(rax, rdi, &runtime_call_clear_stack);
+  } else {  // UNTAGGED.
+    __ AllocateHeapNumber(rax, rdi, &skip_cache);
+    __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm1);
+    __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset));
+  }
+  GenerateOperation(masm);
   __ movq(Operand(rcx, 0), rbx);
   __ movq(Operand(rcx, 2 * kIntSize), rax);
   __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
-  __ ret(kPointerSize);
+  if (tagged) {
+    __ ret(kPointerSize);
+  } else {  // UNTAGGED.
+    __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
+    __ Ret();
 
-  __ bind(&runtime_call_clear_stack);
-  __ fstp(0);
-  __ bind(&runtime_call);
-  __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
+    // Skip cache and return answer directly, only in untagged case.
+    __ bind(&skip_cache);
+    __ subq(rsp, Immediate(kDoubleSize));
+    __ movsd(Operand(rsp, 0), xmm1);
+    __ fld_d(Operand(rsp, 0));
+    GenerateOperation(masm);
+    __ fstp_d(Operand(rsp, 0));
+    __ movsd(xmm1, Operand(rsp, 0));
+    __ addq(rsp, Immediate(kDoubleSize));
+    // We return the value in xmm1 without adding it to the cache, but
+    // we cause a scavenging GC so that future allocations will succeed.
+    __ EnterInternalFrame();
+    // Allocate an unused object bigger than a HeapNumber.
+    __ Push(Smi::FromInt(2 * kDoubleSize));
+    __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace);
+    __ LeaveInternalFrame();
+    __ Ret();
+  }
 
-  __ bind(&nan_result);
-  __ fstp(0);  // Remove argument from FPU stack.
-  __ LoadRoot(rax, Heap::kNanValueRootIndex);
-  __ movq(Operand(rcx, 0), rbx);
-  __ movq(Operand(rcx, 2 * kIntSize), rax);
-  __ ret(kPointerSize);
+  // Call runtime, doing whatever allocation and cleanup is necessary.
+  if (tagged) {
+    __ bind(&runtime_call_clear_stack);
+    __ fstp(0);
+    __ bind(&runtime_call);
+    __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
+  } else {  // UNTAGGED.
+    __ bind(&runtime_call_clear_stack);
+    __ bind(&runtime_call);
+    __ AllocateHeapNumber(rax, rdi, &skip_cache);
+    __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm1);
+    __ EnterInternalFrame();
+    __ push(rax);
+    __ CallRuntime(RuntimeFunction(), 1);
+    __ LeaveInternalFrame();
+    __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
+    __ Ret();
+  }
 }
 
 
@@ -1656,9 +1696,9 @@
 }
 
 
-void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm,
-                                                Label* on_nan_result) {
+void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) {
   // Registers:
+  // rax: Newly allocated HeapNumber, which must be preserved.
   // rbx: Bits of input double. Must be preserved.
   // rcx: Pointer to cache entry. Must be preserved.
   // st(0): Input double
@@ -1680,9 +1720,18 @@
     __ j(below, &in_range);
     // Check for infinity and NaN. Both return NaN for sin.
     __ cmpl(rdi, Immediate(0x7ff));
-    __ j(equal, on_nan_result);
+    NearLabel non_nan_result;
+    __ j(not_equal, &non_nan_result);
+    // Input is +/-Infinity or NaN. Result is NaN.
+    __ fstp(0);
+    __ LoadRoot(kScratchRegister, Heap::kNanValueRootIndex);
+    __ fld_d(FieldOperand(kScratchRegister, HeapNumber::kValueOffset));
+    __ jmp(&done);
+
+    __ bind(&non_nan_result);
 
     // Use fpmod to restrict argument to the range +/-2*PI.
+    __ movq(rdi, rax);  // Save rax before using fnstsw_ax.
     __ fldpi();
     __ fadd(0);
     __ fld(1);
@@ -1715,6 +1764,7 @@
     // FPU Stack: input % 2*pi, 2*pi,
     __ fstp(0);
     // FPU Stack: input % 2*pi
+    __ movq(rax, rdi);  // Restore rax, pointer to the new HeapNumber.
     __ bind(&in_range);
     switch (type_) {
       case TranscendentalCache::SIN:
@@ -1967,8 +2017,8 @@
       __ AbortIfSmi(rax);
     }
 
-    __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
-    __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex);
+    __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
+                   Heap::kHeapNumberMapRootIndex);
     __ j(not_equal, &slow);
     // Operand is a float, negate its value by flipping sign bit.
     __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset));
@@ -1997,8 +2047,8 @@
     }
 
     // Check if the operand is a heap number.
-    __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
-    __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex);
+    __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
+                   Heap::kHeapNumberMapRootIndex);
     __ j(not_equal, &slow);
 
     // Convert the heap number in rax to an untagged integer in rcx.
@@ -2031,6 +2081,157 @@
 }
 
 
+void MathPowStub::Generate(MacroAssembler* masm) {
+  // Registers are used as follows:
+  // rdx = base
+  // rax = exponent
+  // rcx = temporary, result
+
+  Label allocate_return, call_runtime;
+
+  // Load input parameters.
+  __ movq(rdx, Operand(rsp, 2 * kPointerSize));
+  __ movq(rax, Operand(rsp, 1 * kPointerSize));
+
+  // Save 1 in xmm3 - we need this several times later on.
+  __ movl(rcx, Immediate(1));
+  __ cvtlsi2sd(xmm3, rcx);
+
+  Label exponent_nonsmi;
+  Label base_nonsmi;
+  // If the exponent is a heap number go to that specific case.
+  __ JumpIfNotSmi(rax, &exponent_nonsmi);
+  __ JumpIfNotSmi(rdx, &base_nonsmi);
+
+  // Optimized version when both exponent and base are smis.
+  Label powi;
+  __ SmiToInteger32(rdx, rdx);
+  __ cvtlsi2sd(xmm0, rdx);
+  __ jmp(&powi);
+  // Exponent is a smi and base is a heapnumber.
+  __ bind(&base_nonsmi);
+  __ CompareRoot(FieldOperand(rdx, HeapObject::kMapOffset),
+                 Heap::kHeapNumberMapRootIndex);
+  __ j(not_equal, &call_runtime);
+
+  __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
+
+  // Optimized version of pow if exponent is a smi.
+  // xmm0 contains the base.
+  __ bind(&powi);
+  __ SmiToInteger32(rax, rax);
+
+  // Save exponent in base as we need to check if exponent is negative later.
+  // We know that base and exponent are in different registers.
+  __ movq(rdx, rax);
+
+  // Get absolute value of exponent.
+  NearLabel no_neg;
+  __ cmpl(rax, Immediate(0));
+  __ j(greater_equal, &no_neg);
+  __ negl(rax);
+  __ bind(&no_neg);
+
+  // Load xmm1 with 1.
+  __ movsd(xmm1, xmm3);
+  NearLabel while_true;
+  NearLabel no_multiply;
+
+  __ bind(&while_true);
+  __ shrl(rax, Immediate(1));
+  __ j(not_carry, &no_multiply);
+  __ mulsd(xmm1, xmm0);
+  __ bind(&no_multiply);
+  __ mulsd(xmm0, xmm0);
+  __ j(not_zero, &while_true);
+
+  // Base has the original value of the exponent - if the exponent  is
+  // negative return 1/result.
+  __ testl(rdx, rdx);
+  __ j(positive, &allocate_return);
+  // Special case if xmm1 has reached infinity.
+  __ divsd(xmm3, xmm1);
+  __ movsd(xmm1, xmm3);
+  __ xorpd(xmm0, xmm0);
+  __ ucomisd(xmm0, xmm1);
+  __ j(equal, &call_runtime);
+
+  __ jmp(&allocate_return);
+
+  // Exponent (or both) is a heapnumber - no matter what we should now work
+  // on doubles.
+  __ bind(&exponent_nonsmi);
+  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
+                 Heap::kHeapNumberMapRootIndex);
+  __ j(not_equal, &call_runtime);
+  __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
+  // Test if exponent is nan.
+  __ ucomisd(xmm1, xmm1);
+  __ j(parity_even, &call_runtime);
+
+  NearLabel base_not_smi;
+  NearLabel handle_special_cases;
+  __ JumpIfNotSmi(rdx, &base_not_smi);
+  __ SmiToInteger32(rdx, rdx);
+  __ cvtlsi2sd(xmm0, rdx);
+  __ jmp(&handle_special_cases);
+
+  __ bind(&base_not_smi);
+  __ CompareRoot(FieldOperand(rdx, HeapObject::kMapOffset),
+                 Heap::kHeapNumberMapRootIndex);
+  __ j(not_equal, &call_runtime);
+  __ movl(rcx, FieldOperand(rdx, HeapNumber::kExponentOffset));
+  __ andl(rcx, Immediate(HeapNumber::kExponentMask));
+  __ cmpl(rcx, Immediate(HeapNumber::kExponentMask));
+  // base is NaN or +/-Infinity
+  __ j(greater_equal, &call_runtime);
+  __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
+
+  // base is in xmm0 and exponent is in xmm1.
+  __ bind(&handle_special_cases);
+  NearLabel not_minus_half;
+  // Test for -0.5.
+  // Load xmm2 with -0.5.
+  __ movq(rcx, V8_UINT64_C(0xBFE0000000000000), RelocInfo::NONE);
+  __ movq(xmm2, rcx);
+  // xmm2 now has -0.5.
+  __ ucomisd(xmm2, xmm1);
+  __ j(not_equal, &not_minus_half);
+
+  // Calculates reciprocal of square root.
+  // sqrtsd returns -0 when input is -0.  ECMA spec requires +0.
+  __ xorpd(xmm1, xmm1);
+  __ addsd(xmm1, xmm0);
+  __ sqrtsd(xmm1, xmm1);
+  __ divsd(xmm3, xmm1);
+  __ movsd(xmm1, xmm3);
+  __ jmp(&allocate_return);
+
+  // Test for 0.5.
+  __ bind(&not_minus_half);
+  // Load xmm2 with 0.5.
+  // Since xmm3 is 1 and xmm2 is -0.5 this is simply xmm2 + xmm3.
+  __ addsd(xmm2, xmm3);
+  // xmm2 now has 0.5.
+  __ ucomisd(xmm2, xmm1);
+  __ j(not_equal, &call_runtime);
+  // Calculates square root.
+  // sqrtsd returns -0 when input is -0.  ECMA spec requires +0.
+  __ xorpd(xmm1, xmm1);
+  __ addsd(xmm1, xmm0);
+  __ sqrtsd(xmm1, xmm1);
+
+  __ bind(&allocate_return);
+  __ AllocateHeapNumber(rcx, rax, &call_runtime);
+  __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm1);
+  __ movq(rax, rcx);
+  __ ret(2 * kPointerSize);
+
+  __ bind(&call_runtime);
+  __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1);
+}
+
+
 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
   // The key is in rdx and the parameter count is in rax.
 
@@ -2268,46 +2469,46 @@
   // rcx: RegExp data (FixedArray)
   // rdx: Number of capture registers
   // Check that the second argument is a string.
-  __ movq(rax, Operand(rsp, kSubjectOffset));
-  __ JumpIfSmi(rax, &runtime);
-  Condition is_string = masm->IsObjectStringType(rax, rbx, rbx);
+  __ movq(rdi, Operand(rsp, kSubjectOffset));
+  __ JumpIfSmi(rdi, &runtime);
+  Condition is_string = masm->IsObjectStringType(rdi, rbx, rbx);
   __ j(NegateCondition(is_string), &runtime);
 
-  // rax: Subject string.
-  // rcx: RegExp data (FixedArray).
+  // rdi: Subject string.
+  // rax: RegExp data (FixedArray).
   // rdx: Number of capture registers.
   // Check that the third argument is a positive smi less than the string
   // length. A negative value will be greater (unsigned comparison).
   __ movq(rbx, Operand(rsp, kPreviousIndexOffset));
   __ JumpIfNotSmi(rbx, &runtime);
-  __ SmiCompare(rbx, FieldOperand(rax, String::kLengthOffset));
+  __ SmiCompare(rbx, FieldOperand(rdi, String::kLengthOffset));
   __ j(above_equal, &runtime);
 
-  // rcx: RegExp data (FixedArray)
+  // rax: RegExp data (FixedArray)
   // rdx: Number of capture registers
   // Check that the fourth object is a JSArray object.
-  __ movq(rax, Operand(rsp, kLastMatchInfoOffset));
-  __ JumpIfSmi(rax, &runtime);
-  __ CmpObjectType(rax, JS_ARRAY_TYPE, kScratchRegister);
+  __ movq(rdi, Operand(rsp, kLastMatchInfoOffset));
+  __ JumpIfSmi(rdi, &runtime);
+  __ CmpObjectType(rdi, JS_ARRAY_TYPE, kScratchRegister);
   __ j(not_equal, &runtime);
   // Check that the JSArray is in fast case.
-  __ movq(rbx, FieldOperand(rax, JSArray::kElementsOffset));
-  __ movq(rax, FieldOperand(rbx, HeapObject::kMapOffset));
-  __ Cmp(rax, Factory::fixed_array_map());
+  __ movq(rbx, FieldOperand(rdi, JSArray::kElementsOffset));
+  __ movq(rdi, FieldOperand(rbx, HeapObject::kMapOffset));
+  __ Cmp(rdi, Factory::fixed_array_map());
   __ j(not_equal, &runtime);
   // Check that the last match info has space for the capture registers and the
   // additional information. Ensure no overflow in add.
   STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset);
-  __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset));
+  __ SmiToInteger32(rdi, FieldOperand(rbx, FixedArray::kLengthOffset));
   __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead));
-  __ cmpl(rdx, rax);
+  __ cmpl(rdx, rdi);
   __ j(greater, &runtime);
 
-  // rcx: RegExp data (FixedArray)
+  // rax: RegExp data (FixedArray)
   // Check the representation and encoding of the subject string.
   NearLabel seq_ascii_string, seq_two_byte_string, check_code;
-  __ movq(rax, Operand(rsp, kSubjectOffset));
-  __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
+  __ movq(rdi, Operand(rsp, kSubjectOffset));
+  __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
   __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
   // First check for flat two byte string.
   __ andb(rbx, Immediate(
@@ -2328,13 +2529,13 @@
   __ testb(rbx, Immediate(kIsNotStringMask | kExternalStringTag));
   __ j(not_zero, &runtime);
   // String is a cons string.
-  __ movq(rdx, FieldOperand(rax, ConsString::kSecondOffset));
+  __ movq(rdx, FieldOperand(rdi, ConsString::kSecondOffset));
   __ Cmp(rdx, Factory::empty_string());
   __ j(not_equal, &runtime);
-  __ movq(rax, FieldOperand(rax, ConsString::kFirstOffset));
-  __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
+  __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset));
+  __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
   // String is a cons string with empty second part.
-  // rax: first part of cons string.
+  // rdi: first part of cons string.
   // rbx: map of first part of cons string.
   // Is first part a flat two byte string?
   __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
@@ -2347,17 +2548,17 @@
   __ j(not_zero, &runtime);
 
   __ bind(&seq_ascii_string);
-  // rax: subject string (sequential ascii)
-  // rcx: RegExp data (FixedArray)
-  __ movq(r11, FieldOperand(rcx, JSRegExp::kDataAsciiCodeOffset));
-  __ Set(rdi, 1);  // Type is ascii.
+  // rdi: subject string (sequential ascii)
+  // rax: RegExp data (FixedArray)
+  __ movq(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset));
+  __ Set(rcx, 1);  // Type is ascii.
   __ jmp(&check_code);
 
   __ bind(&seq_two_byte_string);
-  // rax: subject string (flat two-byte)
-  // rcx: RegExp data (FixedArray)
-  __ movq(r11, FieldOperand(rcx, JSRegExp::kDataUC16CodeOffset));
-  __ Set(rdi, 0);  // Type is two byte.
+  // rdi: subject string (flat two-byte)
+  // rax: RegExp data (FixedArray)
+  __ movq(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset));
+  __ Set(rcx, 0);  // Type is two byte.
 
   __ bind(&check_code);
   // Check that the irregexp code has been generated for the actual string
@@ -2366,27 +2567,24 @@
   __ CmpObjectType(r11, CODE_TYPE, kScratchRegister);
   __ j(not_equal, &runtime);
 
-  // rax: subject string
-  // rdi: encoding of subject string (1 if ascii, 0 if two_byte);
+  // rdi: subject string
+  // rcx: encoding of subject string (1 if ascii, 0 if two_byte);
   // r11: code
   // Load used arguments before starting to push arguments for call to native
   // RegExp code to avoid handling changing stack height.
   __ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset));
 
-  // rax: subject string
+  // rdi: subject string
   // rbx: previous index
-  // rdi: encoding of subject string (1 if ascii 0 if two_byte);
+  // rcx: encoding of subject string (1 if ascii 0 if two_byte);
   // r11: code
   // All checks done. Now push arguments for native regexp code.
   __ IncrementCounter(&Counters::regexp_entry_native, 1);
 
-  // rsi is caller save on Windows and used to pass parameter on Linux.
-  __ push(rsi);
-
   static const int kRegExpExecuteArguments = 7;
-  __ PrepareCallCFunction(kRegExpExecuteArguments);
   int argument_slots_on_stack =
       masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments);
+  __ EnterApiExitFrame(argument_slots_on_stack);  // Clobbers rax!
 
   // Argument 7: Indicate that this is a direct call from JavaScript.
   __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize),
@@ -2423,60 +2621,57 @@
 #endif
 
   // Keep track on aliasing between argX defined above and the registers used.
-  // rax: subject string
+  // rdi: subject string
   // rbx: previous index
-  // rdi: encoding of subject string (1 if ascii 0 if two_byte);
+  // rcx: encoding of subject string (1 if ascii 0 if two_byte);
   // r11: code
 
   // Argument 4: End of string data
   // Argument 3: Start of string data
   NearLabel setup_two_byte, setup_rest;
-  __ testb(rdi, rdi);
+  __ testb(rcx, rcx);  // Last use of rcx as encoding of subject string.
   __ j(zero, &setup_two_byte);
-  __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset));
-  __ lea(arg4, FieldOperand(rax, rdi, times_1, SeqAsciiString::kHeaderSize));
-  __ lea(arg3, FieldOperand(rax, rbx, times_1, SeqAsciiString::kHeaderSize));
+  __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset));
+  __ lea(arg4, FieldOperand(rdi, rcx, times_1, SeqAsciiString::kHeaderSize));
+  __ lea(arg3, FieldOperand(rdi, rbx, times_1, SeqAsciiString::kHeaderSize));
   __ jmp(&setup_rest);
   __ bind(&setup_two_byte);
-  __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset));
-  __ lea(arg4, FieldOperand(rax, rdi, times_2, SeqTwoByteString::kHeaderSize));
-  __ lea(arg3, FieldOperand(rax, rbx, times_2, SeqTwoByteString::kHeaderSize));
+  __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset));
+  __ lea(arg4, FieldOperand(rdi, rcx, times_2, SeqTwoByteString::kHeaderSize));
+  __ lea(arg3, FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize));
 
   __ bind(&setup_rest);
   // Argument 2: Previous index.
   __ movq(arg2, rbx);
 
   // Argument 1: Subject string.
-  __ movq(arg1, rax);
+#ifdef _WIN64
+  __ movq(arg1, rdi);
+#else
+  // Already there in AMD64 calling convention.
+  ASSERT(arg1.is(rdi));
+#endif
 
   // Locate the code entry and call it.
   __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag));
-  __ CallCFunction(r11, kRegExpExecuteArguments);
+  __ call(r11);
 
-  // rsi is caller save, as it is used to pass parameter.
-  __ pop(rsi);
+  __ LeaveApiExitFrame();
 
   // Check the result.
   NearLabel success;
+  Label exception;
   __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS));
   __ j(equal, &success);
-  NearLabel failure;
-  __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE));
-  __ j(equal, &failure);
   __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION));
-  // If not exception it can only be retry. Handle that in the runtime system.
+  __ j(equal, &exception);
+  __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE));
+  // If none of the above, it can only be retry.
+  // Handle that in the runtime system.
   __ j(not_equal, &runtime);
-  // Result must now be exception. If there is no pending exception already a
-  // stack overflow (on the backtrack stack) was detected in RegExp code but
-  // haven't created the exception yet. Handle that in the runtime system.
-  // TODO(592): Rerunning the RegExp to get the stack overflow exception.
-  ExternalReference pending_exception_address(Top::k_pending_exception_address);
-  __ movq(kScratchRegister, pending_exception_address);
-  __ Cmp(kScratchRegister, Factory::the_hole_value());
-  __ j(equal, &runtime);
-  __ bind(&failure);
-  // For failure and exception return null.
-  __ Move(rax, Factory::null_value());
+
+  // For failure return null.
+  __ LoadRoot(rax, Heap::kNullValueRootIndex);
   __ ret(4 * kPointerSize);
 
   // Load RegExp data.
@@ -2537,6 +2732,27 @@
   __ movq(rax, Operand(rsp, kLastMatchInfoOffset));
   __ ret(4 * kPointerSize);
 
+  __ bind(&exception);
+  // Result must now be exception. If there is no pending exception already a
+  // stack overflow (on the backtrack stack) was detected in RegExp code but
+  // haven't created the exception yet. Handle that in the runtime system.
+  // TODO(592): Rerunning the RegExp to get the stack overflow exception.
+  ExternalReference pending_exception_address(Top::k_pending_exception_address);
+  __ movq(rbx, pending_exception_address);
+  __ movq(rax, Operand(rbx, 0));
+  __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
+  __ cmpq(rax, rdx);
+  __ j(equal, &runtime);
+  __ movq(Operand(rbx, 0), rdx);
+
+  __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex);
+  NearLabel termination_exception;
+  __ j(equal, &termination_exception);
+  __ Throw(rax);
+
+  __ bind(&termination_exception);
+  __ ThrowUncatchable(TERMINATION, rax);
+
   // Do the runtime call to execute the regexp.
   __ bind(&runtime);
   __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
@@ -3085,31 +3301,8 @@
 
 
 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
-  // Check that stack should contain next handler, frame pointer, state and
-  // return address in that order.
-  STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize ==
-            StackHandlerConstants::kStateOffset);
-  STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize ==
-            StackHandlerConstants::kPCOffset);
-
-  ExternalReference handler_address(Top::k_handler_address);
-  __ movq(kScratchRegister, handler_address);
-  __ movq(rsp, Operand(kScratchRegister, 0));
-  // get next in chain
-  __ pop(rcx);
-  __ movq(Operand(kScratchRegister, 0), rcx);
-  __ pop(rbp);  // pop frame pointer
-  __ pop(rdx);  // remove state
-
-  // Before returning we restore the context from the frame pointer if not NULL.
-  // The frame pointer is NULL in the exception handler of a JS entry frame.
-  __ Set(rsi, 0);  // Tentatively set context pointer to NULL
-  NearLabel skip;
-  __ cmpq(rbp, Immediate(0));
-  __ j(equal, &skip);
-  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
-  __ bind(&skip);
-  __ ret(0);
+  // Throw exception in eax.
+  __ Throw(rax);
 }
 
 
@@ -3251,54 +3444,7 @@
 
 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm,
                                           UncatchableExceptionType type) {
-  // Fetch top stack handler.
-  ExternalReference handler_address(Top::k_handler_address);
-  __ movq(kScratchRegister, handler_address);
-  __ movq(rsp, Operand(kScratchRegister, 0));
-
-  // Unwind the handlers until the ENTRY handler is found.
-  NearLabel loop, done;
-  __ bind(&loop);
-  // Load the type of the current stack handler.
-  const int kStateOffset = StackHandlerConstants::kStateOffset;
-  __ cmpq(Operand(rsp, kStateOffset), Immediate(StackHandler::ENTRY));
-  __ j(equal, &done);
-  // Fetch the next handler in the list.
-  const int kNextOffset = StackHandlerConstants::kNextOffset;
-  __ movq(rsp, Operand(rsp, kNextOffset));
-  __ jmp(&loop);
-  __ bind(&done);
-
-  // Set the top handler address to next handler past the current ENTRY handler.
-  __ movq(kScratchRegister, handler_address);
-  __ pop(Operand(kScratchRegister, 0));
-
-  if (type == OUT_OF_MEMORY) {
-    // Set external caught exception to false.
-    ExternalReference external_caught(Top::k_external_caught_exception_address);
-    __ movq(rax, Immediate(false));
-    __ store_rax(external_caught);
-
-    // Set pending exception and rax to out of memory exception.
-    ExternalReference pending_exception(Top::k_pending_exception_address);
-    __ movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE);
-    __ store_rax(pending_exception);
-  }
-
-  // Clear the context pointer.
-  __ Set(rsi, 0);
-
-  // Restore registers from handler.
-  STATIC_ASSERT(StackHandlerConstants::kNextOffset + kPointerSize ==
-            StackHandlerConstants::kFPOffset);
-  __ pop(rbp);  // FP
-  STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize ==
-            StackHandlerConstants::kStateOffset);
-  __ pop(rdx);  // State
-
-  STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize ==
-            StackHandlerConstants::kPCOffset);
-  __ ret(0);
+  __ ThrowUncatchable(type, rax);
 }
 
 
@@ -3415,8 +3561,7 @@
 
   // Set up the roots and smi constant registers.
   // Needs to be done before any further smi loads.
-  ExternalReference roots_address = ExternalReference::roots_address();
-  __ movq(kRootRegister, roots_address);
+  __ InitializeRootRegister();
   __ InitializeSmiConstantRegister();
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
@@ -3516,6 +3661,9 @@
   // is and instance of the function and anything else to
   // indicate that the value is not an instance.
 
+  // None of the flags are supported on X64.
+  ASSERT(flags_ == kNoFlags);
+
   // Get the object - go slow case if it's a smi.
   Label slow;
   __ movq(rax, Operand(rsp, 2 * kPointerSize));
@@ -3591,10 +3739,11 @@
 }
 
 
-Register InstanceofStub::left() { return rax; }
+// Passing arguments in registers is not supported.
+Register InstanceofStub::left() { return no_reg; }
 
 
-Register InstanceofStub::right() { return rdx; }
+Register InstanceofStub::right() { return no_reg; }
 
 
 int CompareStub::MinorKey() {
@@ -3853,14 +4002,15 @@
 
 
 void StringAddStub::Generate(MacroAssembler* masm) {
-  Label string_add_runtime;
+  Label string_add_runtime, call_builtin;
+  Builtins::JavaScript builtin_id = Builtins::ADD;
 
   // Load the two arguments.
-  __ movq(rax, Operand(rsp, 2 * kPointerSize));  // First argument.
-  __ movq(rdx, Operand(rsp, 1 * kPointerSize));  // Second argument.
+  __ movq(rax, Operand(rsp, 2 * kPointerSize));  // First argument (left).
+  __ movq(rdx, Operand(rsp, 1 * kPointerSize));  // Second argument (right).
 
   // Make sure that both arguments are strings if not known in advance.
-  if (string_check_) {
+  if (flags_ == NO_STRING_ADD_FLAGS) {
     Condition is_smi;
     is_smi = masm->CheckSmi(rax);
     __ j(is_smi, &string_add_runtime);
@@ -3872,6 +4022,20 @@
     __ j(is_smi, &string_add_runtime);
     __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9);
     __ j(above_equal, &string_add_runtime);
+  } else {
+    // Here at least one of the arguments is definitely a string.
+    // We convert the one that is not known to be a string.
+    if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) {
+      ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0);
+      GenerateConvertArgument(masm, 2 * kPointerSize, rax, rbx, rcx, rdi,
+                              &call_builtin);
+      builtin_id = Builtins::STRING_ADD_RIGHT;
+    } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) {
+      ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0);
+      GenerateConvertArgument(masm, 1 * kPointerSize, rdx, rbx, rcx, rdi,
+                              &call_builtin);
+      builtin_id = Builtins::STRING_ADD_LEFT;
+    }
   }
 
   // Both arguments are strings.
@@ -3899,14 +4063,14 @@
   // rbx: length of first string
   // rcx: length of second string
   // rdx: second string
-  // r8: map of first string if string check was performed above
-  // r9: map of second string if string check was performed above
+  // r8: map of first string (if flags_ == NO_STRING_ADD_FLAGS)
+  // r9: map of second string (if flags_ == NO_STRING_ADD_FLAGS)
   Label string_add_flat_result, longer_than_two;
   __ bind(&both_not_zero_length);
 
   // If arguments where known to be strings, maps are not loaded to r8 and r9
   // by the code above.
-  if (!string_check_) {
+  if (flags_ != NO_STRING_ADD_FLAGS) {
     __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset));
     __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset));
   }
@@ -4092,6 +4256,54 @@
   // Just jump to runtime to add the two strings.
   __ bind(&string_add_runtime);
   __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
+
+  if (call_builtin.is_linked()) {
+    __ bind(&call_builtin);
+    __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
+  }
+}
+
+
+void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
+                                            int stack_offset,
+                                            Register arg,
+                                            Register scratch1,
+                                            Register scratch2,
+                                            Register scratch3,
+                                            Label* slow) {
+  // First check if the argument is already a string.
+  Label not_string, done;
+  __ JumpIfSmi(arg, &not_string);
+  __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1);
+  __ j(below, &done);
+
+  // Check the number to string cache.
+  Label not_cached;
+  __ bind(&not_string);
+  // Puts the cached result into scratch1.
+  NumberToStringStub::GenerateLookupNumberStringCache(masm,
+                                                      arg,
+                                                      scratch1,
+                                                      scratch2,
+                                                      scratch3,
+                                                      false,
+                                                      &not_cached);
+  __ movq(arg, scratch1);
+  __ movq(Operand(rsp, stack_offset), arg);
+  __ jmp(&done);
+
+  // Check if the argument is a safe string wrapper.
+  __ bind(&not_cached);
+  __ JumpIfSmi(arg, slow);
+  __ CmpObjectType(arg, JS_VALUE_TYPE, scratch1);  // map -> scratch1.
+  __ j(not_equal, slow);
+  __ testb(FieldOperand(scratch1, Map::kBitField2Offset),
+           Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
+  __ j(zero, slow);
+  __ movq(arg, FieldOperand(arg, JSValue::kValueOffset));
+  __ movq(Operand(rsp, stack_offset), arg);
+
+  __ bind(&done);
 }
 
 
@@ -4620,6 +4832,61 @@
   __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
 }
 
+
+void StringCharAtStub::Generate(MacroAssembler* masm) {
+  // Expects two arguments (object, index) on the stack:
+
+  // Stack frame on entry.
+  //  rsp[0]: return address
+  //  rsp[8]: index
+  //  rsp[16]: object
+
+  Register object = rbx;
+  Register index = rax;
+  Register scratch1 = rcx;
+  Register scratch2 = rdx;
+  Register result = rax;
+
+  __ pop(scratch1);  // Return address.
+  __ pop(index);
+  __ pop(object);
+  __ push(scratch1);
+
+  Label need_conversion;
+  Label index_out_of_range;
+  Label done;
+  StringCharAtGenerator generator(object,
+                                  index,
+                                  scratch1,
+                                  scratch2,
+                                  result,
+                                  &need_conversion,
+                                  &need_conversion,
+                                  &index_out_of_range,
+                                  STRING_INDEX_IS_NUMBER);
+  generator.GenerateFast(masm);
+  __ jmp(&done);
+
+  __ bind(&index_out_of_range);
+  // When the index is out of range, the spec requires us to return
+  // the empty string.
+  __ Move(result, Factory::empty_string());
+  __ jmp(&done);
+
+  __ bind(&need_conversion);
+  // Move smi zero into the result register, which will trigger
+  // conversion.
+  __ Move(result, Smi::FromInt(0));
+  __ jmp(&done);
+
+  StubRuntimeCallHelper call_helper;
+  generator.GenerateSlow(masm, call_helper);
+
+  __ bind(&done);
+  __ ret(0);
+}
+
+
 void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
   ASSERT(state_ == CompareIC::SMIS);
   NearLabel miss;
@@ -4767,9 +5034,19 @@
   }
   __ SmiToInteger32(untagged_key, key);
 
-  // Verify that the receiver has pixel array elements.
   __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset));
-  __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true);
+  // By passing NULL as not_pixel_array, callers signal that they have already
+  // verified that the receiver has pixel array elements.
+  if (not_pixel_array != NULL) {
+    __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true);
+  } else {
+    if (FLAG_debug_code) {
+      // Map check should have already made sure that elements is a pixel array.
+      __  Cmp(FieldOperand(elements, HeapObject::kMapOffset),
+              Factory::pixel_array_map());
+      __ Assert(equal, "Elements isn't a pixel array");
+    }
+  }
 
   // Check that the smi is in range.
   __ cmpl(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset));
@@ -4783,6 +5060,88 @@
 }
 
 
+// Stores an indexed element into a pixel array, clamping the stored value.
+void GenerateFastPixelArrayStore(MacroAssembler* masm,
+                                 Register receiver,
+                                 Register key,
+                                 Register value,
+                                 Register elements,
+                                 Register scratch1,
+                                 bool load_elements_from_receiver,
+                                 bool key_is_untagged,
+                                 Label* key_not_smi,
+                                 Label* value_not_smi,
+                                 Label* not_pixel_array,
+                                 Label* out_of_range) {
+  // Register use:
+  //   receiver - holds the receiver and is unchanged.
+  //   key - holds the key (must be a smi) and is unchanged.
+  //   value - holds the value (must be a smi) and is unchanged.
+  //   elements - holds the element object of the receiver on entry if
+  //              load_elements_from_receiver is false, otherwise used
+  //              internally to store the pixel arrays elements and
+  //              external array pointer.
+  //
+  Register external_pointer = elements;
+  Register untagged_key = scratch1;
+  Register untagged_value = receiver;  // Only set once success guaranteed.
+
+  // Fetch the receiver's elements if the caller hasn't already done so.
+  if (load_elements_from_receiver) {
+    __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset));
+  }
+
+  // By passing NULL as not_pixel_array, callers signal that they have already
+  // verified that the receiver has pixel array elements.
+  if (not_pixel_array != NULL) {
+    __ CheckMap(elements, Factory::pixel_array_map(), not_pixel_array, true);
+  } else {
+    if (FLAG_debug_code) {
+      // Map check should have already made sure that elements is a pixel array.
+      __  Cmp(FieldOperand(elements, HeapObject::kMapOffset),
+              Factory::pixel_array_map());
+      __ Assert(equal, "Elements isn't a pixel array");
+    }
+  }
+
+  // Key must be a smi and it must be in range.
+  if (key_is_untagged) {
+    untagged_key = key;
+  } else {
+    // Some callers already have verified that the key is a smi.  key_not_smi is
+    // set to NULL as a sentinel for that case.  Otherwise, add an explicit
+    // check to ensure the key is a smi.
+    if (key_not_smi != NULL) {
+      __ JumpIfNotSmi(key, key_not_smi);
+    } else {
+      if (FLAG_debug_code) {
+        __ AbortIfNotSmi(key);
+      }
+    }
+    __ SmiToInteger32(untagged_key, key);
+  }
+  __ cmpl(untagged_key, FieldOperand(elements, PixelArray::kLengthOffset));
+  __ j(above_equal, out_of_range);  // unsigned check handles negative keys.
+
+  // Value must be a smi.
+  __ JumpIfNotSmi(value, value_not_smi);
+  __ SmiToInteger32(untagged_value, value);
+
+  {  // Clamp the value to [0..255].
+    NearLabel done;
+    __ testl(untagged_value, Immediate(0xFFFFFF00));
+    __ j(zero, &done);
+    __ setcc(negative, untagged_value);  // 1 if negative, 0 if positive.
+    __ decb(untagged_value);  // 0 if negative, 255 if positive.
+    __ bind(&done);
+  }
+
+  __ movq(external_pointer,
+          FieldOperand(elements, PixelArray::kExternalPointerOffset));
+  __ movb(Operand(external_pointer, untagged_key, times_1, 0), untagged_value);
+  __ ret(0);  // Return value in eax.
+}
+
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h
index 8051d4b..32a37b2 100644
--- a/src/x64/code-stubs-x64.h
+++ b/src/x64/code-stubs-x64.h
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -39,15 +39,23 @@
 // TranscendentalCache runtime function.
 class TranscendentalCacheStub: public CodeStub {
  public:
-  explicit TranscendentalCacheStub(TranscendentalCache::Type type)
-      : type_(type) {}
+  enum ArgumentType {
+    TAGGED = 0,
+    UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits
+  };
+
+  explicit TranscendentalCacheStub(TranscendentalCache::Type type,
+                                   ArgumentType argument_type)
+      : type_(type), argument_type_(argument_type) {}
   void Generate(MacroAssembler* masm);
  private:
   TranscendentalCache::Type type_;
+  ArgumentType argument_type_;
+
   Major MajorKey() { return TranscendentalCache; }
-  int MinorKey() { return type_; }
+  int MinorKey() { return type_ | argument_type_; }
   Runtime::FunctionId RuntimeFunction();
-  void GenerateOperation(MacroAssembler* masm, Label* on_nan_result);
+  void GenerateOperation(MacroAssembler* masm);
 };
 
 
@@ -360,24 +368,35 @@
 // Flag that indicates how to generate code for the stub StringAddStub.
 enum StringAddFlags {
   NO_STRING_ADD_FLAGS = 0,
-  NO_STRING_CHECK_IN_STUB = 1 << 0  // Omit string check in stub.
+  // Omit left string check in stub (left is definitely a string).
+  NO_STRING_CHECK_LEFT_IN_STUB = 1 << 0,
+  // Omit right string check in stub (right is definitely a string).
+  NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 1,
+  // Omit both string checks in stub.
+  NO_STRING_CHECK_IN_STUB =
+      NO_STRING_CHECK_LEFT_IN_STUB | NO_STRING_CHECK_RIGHT_IN_STUB
 };
 
 
 class StringAddStub: public CodeStub {
  public:
-  explicit StringAddStub(StringAddFlags flags) {
-    string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0);
-  }
+  explicit StringAddStub(StringAddFlags flags) : flags_(flags) {}
 
  private:
   Major MajorKey() { return StringAdd; }
-  int MinorKey() { return string_check_ ? 0 : 1; }
+  int MinorKey() { return flags_; }
 
   void Generate(MacroAssembler* masm);
 
-  // Should the stub check whether arguments are strings?
-  bool string_check_;
+  void GenerateConvertArgument(MacroAssembler* masm,
+                               int stack_offset,
+                               Register arg,
+                               Register scratch1,
+                               Register scratch2,
+                               Register scratch3,
+                               Label* slow);
+
+  const StringAddFlags flags_;
 };
 
 
@@ -452,14 +471,14 @@
 };
 
 
-// Generate code the to load an element from a pixel array. The receiver is
-// assumed to not be a smi and to have elements, the caller must guarantee this
-// precondition. If the receiver does not have elements that are pixel arrays,
-// the generated code jumps to not_pixel_array. If key is not a smi, then the
-// generated code branches to key_not_smi. Callers can specify NULL for
-// key_not_smi to signal that a smi check has already been performed on key so
-// that the smi check is not generated . If key is not a valid index within the
-// bounds of the pixel array, the generated code jumps to out_of_range.
+// Generate code to load an element from a pixel array. The receiver is assumed
+// to not be a smi and to have elements, the caller must guarantee this
+// precondition. If key is not a smi, then the generated code branches to
+// key_not_smi. Callers can specify NULL for key_not_smi to signal that a smi
+// check has already been performed on key so that the smi check is not
+// generated. If key is not a valid index within the bounds of the pixel array,
+// the generated code jumps to out_of_range. receiver, key and elements are
+// unchanged throughout the generated code sequence.
 void GenerateFastPixelArrayLoad(MacroAssembler* masm,
                                 Register receiver,
                                 Register key,
@@ -470,6 +489,30 @@
                                 Label* key_not_smi,
                                 Label* out_of_range);
 
+// Generate code to store an element into a pixel array, clamping values between
+// [0..255]. The receiver is assumed to not be a smi and to have elements, the
+// caller must guarantee this precondition. If key is not a smi, then the
+// generated code branches to key_not_smi. Callers can specify NULL for
+// key_not_smi to signal that a smi check has already been performed on key so
+// that the smi check is not generated. If the value is not a smi, the
+// generated code will branch to value_not_smi.  If the receiver
+// doesn't have pixel array elements, the generated code will branch to
+// not_pixel_array, unless not_pixel_array is NULL, in which case the caller
+// must ensure that the receiver has pixel array elements.  If key is not a
+// valid index within the bounds of the pixel array, the generated code jumps to
+// out_of_range.
+void GenerateFastPixelArrayStore(MacroAssembler* masm,
+                                 Register receiver,
+                                 Register key,
+                                 Register value,
+                                 Register elements,
+                                 Register scratch1,
+                                 bool load_elements_from_receiver,
+                                 bool key_is_untagged,
+                                 Label* key_not_smi,
+                                 Label* value_not_smi,
+                                 Label* not_pixel_array,
+                                 Label* out_of_range);
 
 } }  // namespace v8::internal
 
diff --git a/src/x64/codegen-x64-inl.h b/src/x64/codegen-x64-inl.h
index 60e9ab0..53caf91 100644
--- a/src/x64/codegen-x64-inl.h
+++ b/src/x64/codegen-x64-inl.h
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index fe90567..fc4bc04 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -2747,7 +2747,8 @@
   frame_->EmitPush(rsi);  // The context is the first argument.
   frame_->EmitPush(kScratchRegister);
   frame_->EmitPush(Smi::FromInt(is_eval() ? 1 : 0));
-  Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
+  frame_->EmitPush(Smi::FromInt(strict_mode_flag()));
+  Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 4);
   // Return value is ignored.
 }
 
@@ -4605,7 +4606,8 @@
       // by initialization.
       value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
     } else {
-      value = frame_->CallRuntime(Runtime::kStoreContextSlot, 3);
+      frame_->Push(Smi::FromInt(strict_mode_flag()));
+      value = frame_->CallRuntime(Runtime::kStoreContextSlot, 4);
     }
     // Storing a variable must keep the (new) value on the expression
     // stack. This is necessary for compiling chained assignment
@@ -4914,8 +4916,9 @@
         Load(property->key());
         Load(property->value());
         if (property->emit_store()) {
+          frame_->Push(Smi::FromInt(NONE));   // PropertyAttributes
           // Ignore the result.
-          Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3);
+          Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 4);
         } else {
           frame_->Drop(3);
         }
@@ -7030,7 +7033,8 @@
 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
   ASSERT_EQ(args->length(), 1);
   Load(args->at(0));
-  TranscendentalCacheStub stub(TranscendentalCache::SIN);
+  TranscendentalCacheStub stub(TranscendentalCache::SIN,
+                               TranscendentalCacheStub::TAGGED);
   Result result = frame_->CallStub(&stub, 1);
   frame_->Push(&result);
 }
@@ -7039,7 +7043,8 @@
 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
   ASSERT_EQ(args->length(), 1);
   Load(args->at(0));
-  TranscendentalCacheStub stub(TranscendentalCache::COS);
+  TranscendentalCacheStub stub(TranscendentalCache::COS,
+                               TranscendentalCacheStub::TAGGED);
   Result result = frame_->CallStub(&stub, 1);
   frame_->Push(&result);
 }
@@ -7048,7 +7053,8 @@
 void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) {
   ASSERT_EQ(args->length(), 1);
   Load(args->at(0));
-  TranscendentalCacheStub stub(TranscendentalCache::LOG);
+  TranscendentalCacheStub stub(TranscendentalCache::LOG,
+                               TranscendentalCacheStub::TAGGED);
   Result result = frame_->CallStub(&stub, 1);
   frame_->Push(&result);
 }
@@ -7230,21 +7236,25 @@
     if (property != NULL) {
       Load(property->obj());
       Load(property->key());
-      Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2);
+      frame_->Push(Smi::FromInt(strict_mode_flag()));
+      Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 3);
       frame_->Push(&answer);
       return;
     }
 
     Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
     if (variable != NULL) {
+      // Delete of an unqualified identifier is disallowed in strict mode
+      // but "delete this" is.
+      ASSERT(strict_mode_flag() == kNonStrictMode || variable->is_this());
       Slot* slot = variable->AsSlot();
       if (variable->is_global()) {
         LoadGlobal();
         frame_->Push(variable->name());
+        frame_->Push(Smi::FromInt(kNonStrictMode));
         Result answer = frame_->InvokeBuiltin(Builtins::DELETE,
-                                              CALL_FUNCTION, 2);
+                                              CALL_FUNCTION, 3);
         frame_->Push(&answer);
-        return;
 
       } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
         // Call the runtime to delete from the context holding the named
@@ -7255,13 +7265,11 @@
         frame_->EmitPush(variable->name());
         Result answer = frame_->CallRuntime(Runtime::kDeleteContextSlot, 2);
         frame_->Push(&answer);
-        return;
+      } else {
+        // Default: Result of deleting non-global, not dynamically
+        // introduced variables is false.
+        frame_->Push(Factory::false_value());
       }
-
-      // Default: Result of deleting non-global, not dynamically
-      // introduced variables is false.
-      frame_->Push(Factory::false_value());
-
     } else {
       // Default: Result of deleting expressions is true.
       Load(node->expression());  // may have side-effects
@@ -8070,8 +8078,12 @@
  public:
   DeferredReferenceSetKeyedValue(Register value,
                                  Register key,
-                                 Register receiver)
-      : value_(value), key_(key), receiver_(receiver) {
+                                 Register receiver,
+                                 StrictModeFlag strict_mode)
+      : value_(value),
+        key_(key),
+        receiver_(receiver),
+        strict_mode_(strict_mode) {
     set_comment("[ DeferredReferenceSetKeyedValue");
   }
 
@@ -8084,6 +8096,7 @@
   Register key_;
   Register receiver_;
   Label patch_site_;
+  StrictModeFlag strict_mode_;
 };
 
 
@@ -8135,7 +8148,9 @@
   }
 
   // Call the IC stub.
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
+                                    : Builtins::KeyedStoreIC_Initialize));
   __ Call(ic, RelocInfo::CODE_TARGET);
   // The delta from the start of the map-compare instructions (initial movq)
   // to the test instruction.  We use masm_-> directly here instead of the
@@ -8202,7 +8217,8 @@
     // This is the map check instruction that will be patched (so we can't
     // use the double underscore macro that may insert instructions).
     // Initially use an invalid map to force a failure.
-    masm()->Move(kScratchRegister, Factory::null_value());
+    masm()->movq(kScratchRegister, Factory::null_value(),
+                 RelocInfo::EMBEDDED_OBJECT);
     masm()->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
                  kScratchRegister);
     // This branch is always a forwards branch so it's always a fixed
@@ -8278,7 +8294,8 @@
     // the __ macro for the following two instructions because it
     // might introduce extra instructions.
     __ bind(&patch_site);
-    masm()->Move(kScratchRegister, Factory::null_value());
+    masm()->movq(kScratchRegister, Factory::null_value(),
+                 RelocInfo::EMBEDDED_OBJECT);
     masm()->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
                  kScratchRegister);
     // This branch is always a forwards branch so it's always a fixed size
@@ -8476,7 +8493,8 @@
     DeferredReferenceSetKeyedValue* deferred =
         new DeferredReferenceSetKeyedValue(result.reg(),
                                            key.reg(),
-                                           receiver.reg());
+                                           receiver.reg(),
+                                           strict_mode_flag());
 
     // Check that the receiver is not a smi.
     __ JumpIfSmi(receiver.reg(), deferred->entry_label());
@@ -8538,7 +8556,7 @@
 
     deferred->BindExit();
   } else {
-    result = frame()->CallKeyedStoreIC();
+    result = frame()->CallKeyedStoreIC(strict_mode_flag());
     // Make sure that we do not have a test instruction after the
     // call.  A test instruction after the call is used to
     // indicate that we have generated an inline version of the
diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h
index c283db3..4392829 100644
--- a/src/x64/codegen-x64.h
+++ b/src/x64/codegen-x64.h
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
diff --git a/src/x64/cpu-x64.cc b/src/x64/cpu-x64.cc
index 513c522..3ff292e 100644
--- a/src/x64/cpu-x64.cc
+++ b/src/x64/cpu-x64.cc
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
diff --git a/src/x64/debug-x64.cc b/src/x64/debug-x64.cc
index 4218647..2c50ddd 100644
--- a/src/x64/debug-x64.cc
+++ b/src/x64/debug-x64.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
diff --git a/src/x64/deoptimizer-x64.cc b/src/x64/deoptimizer-x64.cc
index ed6c47b..daa9128 100644
--- a/src/x64/deoptimizer-x64.cc
+++ b/src/x64/deoptimizer-x64.cc
@@ -203,19 +203,196 @@
 void Deoptimizer::PatchStackCheckCodeAt(Address pc_after,
                                         Code* check_code,
                                         Code* replacement_code) {
-  UNIMPLEMENTED();
+  Address call_target_address = pc_after - kIntSize;
+  ASSERT(check_code->entry() ==
+         Assembler::target_address_at(call_target_address));
+  // The stack check code matches the pattern:
+  //
+  //     cmp rsp, <limit>
+  //     jae ok
+  //     call <stack guard>
+  //     test rax, <loop nesting depth>
+  // ok: ...
+  //
+  // We will patch away the branch so the code is:
+  //
+  //     cmp rsp, <limit>  ;; Not changed
+  //     nop
+  //     nop
+  //     call <on-stack replacment>
+  //     test rax, <loop nesting depth>
+  // ok:
+  //
+  ASSERT(*(call_target_address - 3) == 0x73 &&  // jae
+         *(call_target_address - 2) == 0x07 &&  // offset
+         *(call_target_address - 1) == 0xe8);   // call
+  *(call_target_address - 3) = 0x90;  // nop
+  *(call_target_address - 2) = 0x90;  // nop
+  Assembler::set_target_address_at(call_target_address,
+                                   replacement_code->entry());
 }
 
 
 void Deoptimizer::RevertStackCheckCodeAt(Address pc_after,
                                          Code* check_code,
                                          Code* replacement_code) {
-  UNIMPLEMENTED();
+  Address call_target_address = pc_after - kIntSize;
+  ASSERT(replacement_code->entry() ==
+         Assembler::target_address_at(call_target_address));
+  // Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to
+  // restore the conditional branch.
+  ASSERT(*(call_target_address - 3) == 0x90 &&  // nop
+         *(call_target_address - 2) == 0x90 &&  // nop
+         *(call_target_address - 1) == 0xe8);   // call
+  *(call_target_address - 3) = 0x73;  // jae
+  *(call_target_address - 2) = 0x07;  // offset
+  Assembler::set_target_address_at(call_target_address,
+                                   check_code->entry());
+}
+
+
+static int LookupBailoutId(DeoptimizationInputData* data, unsigned ast_id) {
+  ByteArray* translations = data->TranslationByteArray();
+  int length = data->DeoptCount();
+  for (int i = 0; i < length; i++) {
+    if (static_cast<unsigned>(data->AstId(i)->value()) == ast_id) {
+      TranslationIterator it(translations,  data->TranslationIndex(i)->value());
+      int value = it.Next();
+      ASSERT(Translation::BEGIN == static_cast<Translation::Opcode>(value));
+      // Read the number of frames.
+      value = it.Next();
+      if (value == 1) return i;
+    }
+  }
+  UNREACHABLE();
+  return -1;
 }
 
 
 void Deoptimizer::DoComputeOsrOutputFrame() {
-  UNIMPLEMENTED();
+  DeoptimizationInputData* data = DeoptimizationInputData::cast(
+      optimized_code_->deoptimization_data());
+  unsigned ast_id = data->OsrAstId()->value();
+  // TODO(kasperl): This should not be the bailout_id_. It should be
+  // the ast id. Confusing.
+  ASSERT(bailout_id_ == ast_id);
+
+  int bailout_id = LookupBailoutId(data, ast_id);
+  unsigned translation_index = data->TranslationIndex(bailout_id)->value();
+  ByteArray* translations = data->TranslationByteArray();
+
+  TranslationIterator iterator(translations, translation_index);
+  Translation::Opcode opcode =
+      static_cast<Translation::Opcode>(iterator.Next());
+  ASSERT(Translation::BEGIN == opcode);
+  USE(opcode);
+  int count = iterator.Next();
+  ASSERT(count == 1);
+  USE(count);
+
+  opcode = static_cast<Translation::Opcode>(iterator.Next());
+  USE(opcode);
+  ASSERT(Translation::FRAME == opcode);
+  unsigned node_id = iterator.Next();
+  USE(node_id);
+  ASSERT(node_id == ast_id);
+  JSFunction* function = JSFunction::cast(ComputeLiteral(iterator.Next()));
+  USE(function);
+  ASSERT(function == function_);
+  unsigned height = iterator.Next();
+  unsigned height_in_bytes = height * kPointerSize;
+  USE(height_in_bytes);
+
+  unsigned fixed_size = ComputeFixedSize(function_);
+  unsigned input_frame_size = static_cast<unsigned>(input_->GetFrameSize());
+  ASSERT(fixed_size + height_in_bytes == input_frame_size);
+
+  unsigned stack_slot_size = optimized_code_->stack_slots() * kPointerSize;
+  unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value();
+  unsigned outgoing_size = outgoing_height * kPointerSize;
+  unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size;
+  ASSERT(outgoing_size == 0);  // OSR does not happen in the middle of a call.
+
+  if (FLAG_trace_osr) {
+    PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ",
+           reinterpret_cast<intptr_t>(function_));
+    function_->PrintName();
+    PrintF(" => node=%u, frame=%d->%d]\n",
+           ast_id,
+           input_frame_size,
+           output_frame_size);
+  }
+
+  // There's only one output frame in the OSR case.
+  output_count_ = 1;
+  output_ = new FrameDescription*[1];
+  output_[0] = new(output_frame_size) FrameDescription(
+      output_frame_size, function_);
+
+  // Clear the incoming parameters in the optimized frame to avoid
+  // confusing the garbage collector.
+  unsigned output_offset = output_frame_size - kPointerSize;
+  int parameter_count = function_->shared()->formal_parameter_count() + 1;
+  for (int i = 0; i < parameter_count; ++i) {
+    output_[0]->SetFrameSlot(output_offset, 0);
+    output_offset -= kPointerSize;
+  }
+
+  // Translate the incoming parameters. This may overwrite some of the
+  // incoming argument slots we've just cleared.
+  int input_offset = input_frame_size - kPointerSize;
+  bool ok = true;
+  int limit = input_offset - (parameter_count * kPointerSize);
+  while (ok && input_offset > limit) {
+    ok = DoOsrTranslateCommand(&iterator, &input_offset);
+  }
+
+  // There are no translation commands for the caller's pc and fp, the
+  // context, and the function.  Set them up explicitly.
+  for (int i = 0; ok && i < 4; i++) {
+    intptr_t input_value = input_->GetFrameSlot(input_offset);
+    if (FLAG_trace_osr) {
+      PrintF("    [esp + %d] <- 0x%08" V8PRIxPTR " ; [esp + %d] (fixed part)\n",
+             output_offset,
+             input_value,
+             input_offset);
+    }
+    output_[0]->SetFrameSlot(output_offset, input_->GetFrameSlot(input_offset));
+    input_offset -= kPointerSize;
+    output_offset -= kPointerSize;
+  }
+
+  // Translate the rest of the frame.
+  while (ok && input_offset >= 0) {
+    ok = DoOsrTranslateCommand(&iterator, &input_offset);
+  }
+
+  // If translation of any command failed, continue using the input frame.
+  if (!ok) {
+    delete output_[0];
+    output_[0] = input_;
+    output_[0]->SetPc(reinterpret_cast<intptr_t>(from_));
+  } else {
+    // Setup the frame pointer and the context pointer.
+    output_[0]->SetRegister(rbp.code(), input_->GetRegister(rbp.code()));
+    output_[0]->SetRegister(rsi.code(), input_->GetRegister(rsi.code()));
+
+    unsigned pc_offset = data->OsrPcOffset()->value();
+    intptr_t pc = reinterpret_cast<intptr_t>(
+        optimized_code_->entry() + pc_offset);
+    output_[0]->SetPc(pc);
+  }
+  Code* continuation = Builtins::builtin(Builtins::NotifyOSR);
+  output_[0]->SetContinuation(
+      reinterpret_cast<intptr_t>(continuation->entry()));
+
+  if (FLAG_trace_osr) {
+    PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ",
+           ok ? "finished" : "aborted",
+           reinterpret_cast<intptr_t>(function));
+    function->PrintName();
+    PrintF(" => pc=0x%0" V8PRIxPTR "]\n", output_[0]->GetPc());
+  }
 }
 
 
@@ -321,14 +498,16 @@
            fp_value, output_offset, value);
   }
 
-  // The context can be gotten from the function so long as we don't
-  // optimize functions that need local contexts.
+  // For the bottommost output frame the context can be gotten from the input
+  // frame. For all subsequent output frames it can be gotten from the function
+  // so long as we don't inline functions that need local contexts.
   output_offset -= kPointerSize;
   input_offset -= kPointerSize;
-  value = reinterpret_cast<intptr_t>(function->context());
-  // The context for the bottommost output frame should also agree with the
-  // input frame.
-  ASSERT(!is_bottommost || input_->GetFrameSlot(input_offset) == value);
+  if (is_bottommost) {
+    value = input_->GetFrameSlot(input_offset);
+  } else {
+    value = reinterpret_cast<intptr_t>(function->context());
+  }
   output_frame->SetFrameSlot(output_offset, value);
   if (is_topmost) output_frame->SetRegister(rsi.code(), value);
   if (FLAG_trace_deopt) {
@@ -461,7 +640,7 @@
   // On windows put the argument on the stack (PrepareCallCFunction have
   // created space for this). On linux pass the argument in r8.
 #ifdef _WIN64
-  __ movq(Operand(rsp, 0 * kPointerSize), arg5);
+  __ movq(Operand(rsp, 4 * kPointerSize), arg5);
 #else
   __ movq(r8, arg5);
 #endif
@@ -570,11 +749,8 @@
 
   // Set up the roots register.
   ExternalReference roots_address = ExternalReference::roots_address();
-  __ movq(r13, roots_address);
-
-  __ movq(kSmiConstantRegister,
-          reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)),
-          RelocInfo::NONE);
+  __ InitializeRootRegister();
+  __ InitializeSmiConstantRegister();
 
   // Return to the continuation point.
   __ ret(0);
diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc
index f73f948..21a100f 100644
--- a/src/x64/disasm-x64.cc
+++ b/src/x64/disasm-x64.cc
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -1040,14 +1040,18 @@
         AppendToBuffer(", %s", NameOfXMMRegister(regop));
       } else {
         const char* mnemonic = "?";
-        if (opcode == 0x57) {
+        if (opcode == 0x50) {
+          mnemonic = "movmskpd";
+        } else  if (opcode == 0x54) {
+          mnemonic = "andpd";
+        } else  if (opcode == 0x56) {
+          mnemonic = "orpd";
+        } else  if (opcode == 0x57) {
           mnemonic = "xorpd";
         } else if (opcode == 0x2E) {
           mnemonic = "ucomisd";
         } else if (opcode == 0x2F) {
           mnemonic = "comisd";
-        } else if (opcode == 0x50) {
-          mnemonic = "movmskpd";
         } else {
           UnimplementedInstruction();
         }
diff --git a/src/x64/frames-x64.cc b/src/x64/frames-x64.cc
index 9c96047..6c58bc9 100644
--- a/src/x64/frames-x64.cc
+++ b/src/x64/frames-x64.cc
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
diff --git a/src/x64/frames-x64.h b/src/x64/frames-x64.h
index 998b3e9..81be819 100644
--- a/src/x64/frames-x64.h
+++ b/src/x64/frames-x64.h
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 556ec85..780f4b0 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -207,43 +207,45 @@
     Move(dot_arguments_slot, rcx, rbx, rdx);
   }
 
-  { Comment cmnt(masm_, "[ Declarations");
-    // For named function expressions, declare the function name as a
-    // constant.
-    if (scope()->is_function_scope() && scope()->function() != NULL) {
-      EmitDeclaration(scope()->function(), Variable::CONST, NULL);
-    }
-    // Visit all the explicit declarations unless there is an illegal
-    // redeclaration.
-    if (scope()->HasIllegalRedeclaration()) {
-      scope()->VisitIllegalRedeclaration(this);
-    } else {
-      VisitDeclarations(scope()->declarations());
-    }
-  }
-
   if (FLAG_trace) {
     __ CallRuntime(Runtime::kTraceEnter, 0);
   }
 
-  { Comment cmnt(masm_, "[ Stack check");
-    PrepareForBailout(info->function(), NO_REGISTERS);
-    NearLabel ok;
-    __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
-    __ j(above_equal, &ok);
-    StackCheckStub stub;
-    __ CallStub(&stub);
-    __ bind(&ok);
+  // Visit the declarations and body unless there is an illegal
+  // redeclaration.
+  if (scope()->HasIllegalRedeclaration()) {
+    Comment cmnt(masm_, "[ Declarations");
+    scope()->VisitIllegalRedeclaration(this);
+  } else {
+    { Comment cmnt(masm_, "[ Declarations");
+      // For named function expressions, declare the function name as a
+      // constant.
+      if (scope()->is_function_scope() && scope()->function() != NULL) {
+        EmitDeclaration(scope()->function(), Variable::CONST, NULL);
+      }
+      VisitDeclarations(scope()->declarations());
+    }
+
+    { Comment cmnt(masm_, "[ Stack check");
+      PrepareForBailout(info->function(), NO_REGISTERS);
+      NearLabel ok;
+      __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
+      __ j(above_equal, &ok);
+      StackCheckStub stub;
+      __ CallStub(&stub);
+      __ bind(&ok);
+    }
+
+    { Comment cmnt(masm_, "[ Body");
+      ASSERT(loop_depth() == 0);
+      VisitStatements(function()->body());
+      ASSERT(loop_depth() == 0);
+    }
   }
 
-  { Comment cmnt(masm_, "[ Body");
-    ASSERT(loop_depth() == 0);
-    VisitStatements(function()->body());
-    ASSERT(loop_depth() == 0);
-  }
-
+  // Always emit a 'return undefined' in case control fell off the end of
+  // the body.
   { Comment cmnt(masm_, "[ return <undefined>;");
-    // Emit a 'return undefined' in case control fell off the end of the body.
     __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
     EmitReturnSequence();
   }
@@ -267,6 +269,13 @@
   // the deoptimization input data found in the optimized code.
   RecordStackCheck(stmt->OsrEntryId());
 
+  // Loop stack checks can be patched to perform on-stack replacement. In
+  // order to decide whether or not to perform OSR we embed the loop depth
+  // in a test instruction after the call so we can extract it from the OSR
+  // builtin.
+  ASSERT(loop_depth() > 0);
+  __ testl(rax, Immediate(Min(loop_depth(), Code::kMaxLoopNestingMarker)));
+
   __ bind(&ok);
   PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
   // Record a mapping of the OSR id to this PC.  This is used if the OSR
@@ -318,13 +327,6 @@
 }
 
 
-FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand(
-    Token::Value op, Expression* left, Expression* right) {
-  ASSERT(ShouldInlineSmiCase(op));
-  return kNoConstants;
-}
-
-
 void FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
 }
 
@@ -543,7 +545,7 @@
   __ j(equal, if_true);
   __ CompareRoot(result_register(), Heap::kFalseValueRootIndex);
   __ j(equal, if_false);
-  ASSERT_EQ(0, kSmiTag);
+  STATIC_ASSERT(kSmiTag == 0);
   __ SmiCompare(result_register(), Smi::FromInt(0));
   __ j(equal, if_false);
   Condition is_smi = masm_->CheckSmi(result_register());
@@ -733,7 +735,9 @@
              prop->key()->AsLiteral()->handle()->IsSmi());
       __ Move(rcx, prop->key()->AsLiteral()->handle());
 
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(is_strict()
+          ? Builtins::KeyedStoreIC_Initialize_Strict
+          : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
     }
   }
@@ -750,7 +754,8 @@
   __ push(rsi);  // The context is the first argument.
   __ Push(pairs);
   __ Push(Smi::FromInt(is_eval() ? 1 : 0));
-  __ CallRuntime(Runtime::kDeclareGlobals, 3);
+  __ Push(Smi::FromInt(strict_mode_flag()));
+  __ CallRuntime(Runtime::kDeclareGlobals, 4);
   // Return value is ignored.
 }
 
@@ -851,7 +856,9 @@
   VisitForAccumulatorValue(stmt->enumerable());
   __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
   __ j(equal, &exit);
-  __ CompareRoot(rax, Heap::kNullValueRootIndex);
+  Register null_value = rdi;
+  __ LoadRoot(null_value, Heap::kNullValueRootIndex);
+  __ cmpq(rax, null_value);
   __ j(equal, &exit);
 
   // Convert the object to a JS object.
@@ -865,12 +872,61 @@
   __ bind(&done_convert);
   __ push(rax);
 
-  // BUG(867): Check cache validity in generated code. This is a fast
-  // case for the JSObject::IsSimpleEnum cache validity checks. If we
-  // cannot guarantee cache validity, call the runtime system to check
-  // cache validity or get the property names in a fixed array.
+  // Check cache validity in generated code. This is a fast case for
+  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
+  // guarantee cache validity, call the runtime system to check cache
+  // validity or get the property names in a fixed array.
+  Label next, call_runtime;
+  Register empty_fixed_array_value = r8;
+  __ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
+  Register empty_descriptor_array_value = r9;
+  __ LoadRoot(empty_descriptor_array_value,
+              Heap::kEmptyDescriptorArrayRootIndex);
+  __ movq(rcx, rax);
+  __ bind(&next);
+
+  // Check that there are no elements.  Register rcx contains the
+  // current JS object we've reached through the prototype chain.
+  __ cmpq(empty_fixed_array_value,
+          FieldOperand(rcx, JSObject::kElementsOffset));
+  __ j(not_equal, &call_runtime);
+
+  // Check that instance descriptors are not empty so that we can
+  // check for an enum cache.  Leave the map in rbx for the subsequent
+  // prototype load.
+  __ movq(rbx, FieldOperand(rcx, HeapObject::kMapOffset));
+  __ movq(rdx, FieldOperand(rbx, Map::kInstanceDescriptorsOffset));
+  __ cmpq(rdx, empty_descriptor_array_value);
+  __ j(equal, &call_runtime);
+
+  // Check that there is an enum cache in the non-empty instance
+  // descriptors (rdx).  This is the case if the next enumeration
+  // index field does not contain a smi.
+  __ movq(rdx, FieldOperand(rdx, DescriptorArray::kEnumerationIndexOffset));
+  __ JumpIfSmi(rdx, &call_runtime);
+
+  // For all objects but the receiver, check that the cache is empty.
+  NearLabel check_prototype;
+  __ cmpq(rcx, rax);
+  __ j(equal, &check_prototype);
+  __ movq(rdx, FieldOperand(rdx, DescriptorArray::kEnumCacheBridgeCacheOffset));
+  __ cmpq(rdx, empty_fixed_array_value);
+  __ j(not_equal, &call_runtime);
+
+  // Load the prototype from the map and loop if non-null.
+  __ bind(&check_prototype);
+  __ movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
+  __ cmpq(rcx, null_value);
+  __ j(not_equal, &next);
+
+  // The enum cache is valid.  Load the map of the object being
+  // iterated over and use the cache for the iteration.
+  NearLabel use_cache;
+  __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
+  __ jmp(&use_cache);
 
   // Get the set of properties to enumerate.
+  __ bind(&call_runtime);
   __ push(rax);  // Duplicate the enumerable object on the stack.
   __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
 
@@ -883,6 +939,7 @@
   __ j(not_equal, &fixed_array);
 
   // We got a map in register rax. Get the enumeration cache from it.
+  __ bind(&use_cache);
   __ movq(rcx, FieldOperand(rax, Map::kInstanceDescriptorsOffset));
   __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset));
   __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
@@ -971,8 +1028,14 @@
 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
                                        bool pretenure) {
   // Use the fast case closure allocation code that allocates in new
-  // space for nested functions that don't need literals cloning.
-  if (scope()->is_function_scope() &&
+  // space for nested functions that don't need literals cloning. If
+  // we're running with the --always-opt or the --prepare-always-opt
+  // flag, we need to use the runtime function so that the new function
+  // we are creating here gets a chance to have its code optimized and
+  // doesn't just get a copy of the existing unoptimized code.
+  if (!FLAG_always_opt &&
+      !FLAG_prepare_always_opt &&
+      scope()->is_function_scope() &&
       info->num_literals() == 0 &&
       !pretenure) {
     FastNewClosureStub stub;
@@ -1082,8 +1145,11 @@
   // Check that last extension is NULL.
   __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
   __ j(not_equal, slow);
-  __ movq(temp, ContextOperand(context, Context::FCONTEXT_INDEX));
-  return ContextOperand(temp, slot->index());
+
+  // This function is used only for loads, not stores, so it's safe to
+  // return an rsi-based operand (the write barrier cannot be allowed to
+  // destroy the rsi register).
+  return ContextOperand(context, slot->index());
 }
 
 
@@ -1333,7 +1399,8 @@
         VisitForStackValue(key);
         VisitForStackValue(value);
         if (property->emit_store()) {
-          __ CallRuntime(Runtime::kSetProperty, 3);
+          __ Push(Smi::FromInt(NONE));    // PropertyAttributes
+          __ CallRuntime(Runtime::kSetProperty, 4);
         } else {
           __ Drop(3);
         }
@@ -1509,14 +1576,8 @@
     }
 
     Token::Value op = expr->binary_op();
-    ConstantOperand constant = ShouldInlineSmiCase(op)
-        ? GetConstantOperand(op, expr->target(), expr->value())
-        : kNoConstants;
-    ASSERT(constant == kRightConstant || constant == kNoConstants);
-    if (constant == kNoConstants) {
-      __ push(rax);  // Left operand goes on the stack.
-      VisitForAccumulatorValue(expr->value());
-    }
+    __ push(rax);  // Left operand goes on the stack.
+    VisitForAccumulatorValue(expr->value());
 
     OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
         ? OVERWRITE_RIGHT
@@ -1528,8 +1589,7 @@
                             op,
                             mode,
                             expr->target(),
-                            expr->value(),
-                            constant);
+                            expr->value());
     } else {
       EmitBinaryOp(op, mode);
     }
@@ -1580,10 +1640,7 @@
                                               Token::Value op,
                                               OverwriteMode mode,
                                               Expression* left,
-                                              Expression* right,
-                                              ConstantOperand constant) {
-  ASSERT(constant == kNoConstants);  // Only handled case.
-
+                                              Expression* right) {
   // Do combined smi check of the operands. Left operand is on the
   // stack (popped into rdx). Right operand is in rax but moved into
   // rcx to make the shifts easier.
@@ -1680,18 +1737,32 @@
       __ movq(rdx, rax);
       __ pop(rax);  // Restore value.
       __ Move(rcx, prop->key()->AsLiteral()->handle());
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::StoreIC_Initialize_Strict
+                      : Builtins::StoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
     case KEYED_PROPERTY: {
       __ push(rax);  // Preserve value.
-      VisitForStackValue(prop->obj());
-      VisitForAccumulatorValue(prop->key());
-      __ movq(rcx, rax);
-      __ pop(rdx);
-      __ pop(rax);
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      if (prop->is_synthetic()) {
+        ASSERT(prop->obj()->AsVariableProxy() != NULL);
+        ASSERT(prop->key()->AsLiteral() != NULL);
+        { AccumulatorValueContext for_object(this);
+          EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
+        }
+        __ movq(rdx, rax);
+        __ Move(rcx, prop->key()->AsLiteral()->handle());
+      } else {
+        VisitForStackValue(prop->obj());
+        VisitForAccumulatorValue(prop->key());
+        __ movq(rcx, rax);
+        __ pop(rdx);
+      }
+      __ pop(rax);  // Restore value.
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                      : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
@@ -1720,57 +1791,76 @@
         : Builtins::StoreIC_Initialize));
     EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
 
-  } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) {
-    // Perform the assignment for non-const variables and for initialization
-    // of const variables.  Const assignments are simply skipped.
-    Label done;
+  } else if (op == Token::INIT_CONST) {
+    // Like var declarations, const declarations are hoisted to function
+    // scope.  However, unlike var initializers, const initializers are able
+    // to drill a hole to that function context, even from inside a 'with'
+    // context.  We thus bypass the normal static scope lookup.
+    Slot* slot = var->AsSlot();
+    Label skip;
+    switch (slot->type()) {
+      case Slot::PARAMETER:
+        // No const parameters.
+        UNREACHABLE();
+        break;
+      case Slot::LOCAL:
+        __ movq(rdx, Operand(rbp, SlotOffset(slot)));
+        __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
+        __ j(not_equal, &skip);
+        __ movq(Operand(rbp, SlotOffset(slot)), rax);
+        break;
+      case Slot::CONTEXT: {
+        __ movq(rcx, ContextOperand(rsi, Context::FCONTEXT_INDEX));
+        __ movq(rdx, ContextOperand(rcx, slot->index()));
+        __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
+        __ j(not_equal, &skip);
+        __ movq(ContextOperand(rcx, slot->index()), rax);
+        int offset = Context::SlotOffset(slot->index());
+        __ movq(rdx, rax);  // Preserve the stored value in eax.
+        __ RecordWrite(rcx, offset, rdx, rbx);
+        break;
+      }
+      case Slot::LOOKUP:
+        __ push(rax);
+        __ push(rsi);
+        __ Push(var->name());
+        __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
+        break;
+    }
+    __ bind(&skip);
+
+  } else if (var->mode() != Variable::CONST) {
+    // Perform the assignment for non-const variables.  Const assignments
+    // are simply skipped.
     Slot* slot = var->AsSlot();
     switch (slot->type()) {
       case Slot::PARAMETER:
       case Slot::LOCAL:
-        if (op == Token::INIT_CONST) {
-          // Detect const reinitialization by checking for the hole value.
-          __ movq(rdx, Operand(rbp, SlotOffset(slot)));
-          __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
-          __ j(not_equal, &done);
-        }
         // Perform the assignment.
         __ movq(Operand(rbp, SlotOffset(slot)), rax);
         break;
 
       case Slot::CONTEXT: {
         MemOperand target = EmitSlotSearch(slot, rcx);
-        if (op == Token::INIT_CONST) {
-          // Detect const reinitialization by checking for the hole value.
-          __ movq(rdx, target);
-          __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
-          __ j(not_equal, &done);
-        }
         // Perform the assignment and issue the write barrier.
         __ movq(target, rax);
         // The value of the assignment is in rax.  RecordWrite clobbers its
         // register arguments.
         __ movq(rdx, rax);
-        int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
+        int offset = Context::SlotOffset(slot->index());
         __ RecordWrite(rcx, offset, rdx, rbx);
         break;
       }
 
       case Slot::LOOKUP:
-        // Call the runtime for the assignment.  The runtime will ignore
-        // const reinitialization.
+        // Call the runtime for the assignment.
         __ push(rax);  // Value.
         __ push(rsi);  // Context.
         __ Push(var->name());
-        if (op == Token::INIT_CONST) {
-          // The runtime will ignore const redeclaration.
-          __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
-        } else {
-          __ CallRuntime(Runtime::kStoreContextSlot, 3);
-        }
+        __ Push(Smi::FromInt(strict_mode_flag()));
+        __ CallRuntime(Runtime::kStoreContextSlot, 4);
         break;
     }
-    __ bind(&done);
   }
 }
 
@@ -1799,7 +1889,9 @@
   } else {
     __ pop(rdx);
   }
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      is_strict() ? Builtins::StoreIC_Initialize_Strict
+                  : Builtins::StoreIC_Initialize));
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -1837,7 +1929,9 @@
   }
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                  : Builtins::KeyedStoreIC_Initialize));
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -1953,6 +2047,27 @@
 }
 
 
+void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
+                                                      int arg_count) {
+  // Push copy of the first argument or undefined if it doesn't exist.
+  if (arg_count > 0) {
+    __ push(Operand(rsp, arg_count * kPointerSize));
+  } else {
+    __ PushRoot(Heap::kUndefinedValueRootIndex);
+  }
+
+  // Push the receiver of the enclosing function and do runtime call.
+  __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize));
+
+  // Push the strict mode flag.
+  __ Push(Smi::FromInt(strict_mode_flag()));
+
+  __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
+                 ? Runtime::kResolvePossiblyDirectEvalNoLookup
+                 : Runtime::kResolvePossiblyDirectEval, 4);
+}
+
+
 void FullCodeGenerator::VisitCall(Call* expr) {
 #ifdef DEBUG
   // We want to verify that RecordJSReturnSite gets called on all paths
@@ -1980,21 +2095,30 @@
         VisitForStackValue(args->at(i));
       }
 
-      // Push copy of the function - found below the arguments.
-      __ push(Operand(rsp, (arg_count + 1) * kPointerSize));
-
-      // Push copy of the first argument or undefined if it doesn't exist.
-      if (arg_count > 0) {
-        __ push(Operand(rsp, arg_count * kPointerSize));
-      } else {
-      __ PushRoot(Heap::kUndefinedValueRootIndex);
+      // If we know that eval can only be shadowed by eval-introduced
+      // variables we attempt to load the global eval function directly
+      // in generated code. If we succeed, there is no need to perform a
+      // context lookup in the runtime system.
+      Label done;
+      if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
+        Label slow;
+        EmitLoadGlobalSlotCheckExtensions(var->AsSlot(),
+                                          NOT_INSIDE_TYPEOF,
+                                          &slow);
+        // Push the function and resolve eval.
+        __ push(rax);
+        EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count);
+        __ jmp(&done);
+        __ bind(&slow);
       }
 
-      // Push the receiver of the enclosing function and do runtime call.
-      __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize));
-      // Push the strict mode flag.
-      __ Push(Smi::FromInt(strict_mode_flag()));
-      __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
+      // Push copy of the function (found below the arguments) and
+      // resolve eval.
+      __ push(Operand(rsp, (arg_count + 1) * kPointerSize));
+      EmitResolvePossiblyDirectEval(PERFORM_CONTEXT_LOOKUP, arg_count);
+      if (done.is_linked()) {
+        __ bind(&done);
+      }
 
       // The runtime call returns a pair of values in rax (function) and
       // rdx (receiver). Touch up the stack with the right values.
@@ -2611,7 +2735,8 @@
   ASSERT(args->length() == 2);
   VisitForStackValue(args->at(0));
   VisitForStackValue(args->at(1));
-  __ CallRuntime(Runtime::kMath_pow, 2);
+  MathPowStub stub;
+  __ CallStub(&stub);
   context()->Plug(rax);
 }
 
@@ -2795,7 +2920,8 @@
 
 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
   // Load the argument on the stack and call the stub.
-  TranscendentalCacheStub stub(TranscendentalCache::SIN);
+  TranscendentalCacheStub stub(TranscendentalCache::SIN,
+                               TranscendentalCacheStub::TAGGED);
   ASSERT(args->length() == 1);
   VisitForStackValue(args->at(0));
   __ CallStub(&stub);
@@ -2805,7 +2931,8 @@
 
 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
   // Load the argument on the stack and call the stub.
-  TranscendentalCacheStub stub(TranscendentalCache::COS);
+  TranscendentalCacheStub stub(TranscendentalCache::COS,
+                               TranscendentalCacheStub::TAGGED);
   ASSERT(args->length() == 1);
   VisitForStackValue(args->at(0));
   __ CallStub(&stub);
@@ -2815,7 +2942,8 @@
 
 void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
   // Load the argument on the stack and call the stub.
-  TranscendentalCacheStub stub(TranscendentalCache::LOG);
+  TranscendentalCacheStub stub(TranscendentalCache::LOG,
+                               TranscendentalCacheStub::TAGGED);
   ASSERT(args->length() == 1);
   VisitForStackValue(args->at(0));
   __ CallStub(&stub);
@@ -2867,7 +2995,73 @@
   VisitForStackValue(args->at(0));
   VisitForStackValue(args->at(1));
   VisitForStackValue(args->at(2));
+  Label done;
+  Label slow_case;
+  Register object = rax;
+  Register index_1 = rbx;
+  Register index_2 = rcx;
+  Register elements = rdi;
+  Register temp = rdx;
+  __ movq(object, Operand(rsp, 2 * kPointerSize));
+  // Fetch the map and check if array is in fast case.
+  // Check that object doesn't require security checks and
+  // has no indexed interceptor.
+  __ CmpObjectType(object, FIRST_JS_OBJECT_TYPE, temp);
+  __ j(below, &slow_case);
+  __ testb(FieldOperand(temp, Map::kBitFieldOffset),
+           Immediate(KeyedLoadIC::kSlowCaseBitFieldMask));
+  __ j(not_zero, &slow_case);
+
+  // Check the object's elements are in fast case and writable.
+  __ movq(elements, FieldOperand(object, JSObject::kElementsOffset));
+  __ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
+                 Heap::kFixedArrayMapRootIndex);
+  __ j(not_equal, &slow_case);
+
+  // Check that both indices are smis.
+  __ movq(index_1, Operand(rsp, 1 * kPointerSize));
+  __ movq(index_2, Operand(rsp, 0 * kPointerSize));
+  __ JumpIfNotBothSmi(index_1, index_2, &slow_case);
+
+  // Check that both indices are valid.
+  // The JSArray length field is a smi since the array is in fast case mode.
+  __ movq(temp, FieldOperand(object, JSArray::kLengthOffset));
+  __ SmiCompare(temp, index_1);
+  __ j(below_equal, &slow_case);
+  __ SmiCompare(temp, index_2);
+  __ j(below_equal, &slow_case);
+
+  __ SmiToInteger32(index_1, index_1);
+  __ SmiToInteger32(index_2, index_2);
+  // Bring addresses into index1 and index2.
+  __ lea(index_1, FieldOperand(elements, index_1, times_pointer_size,
+                               FixedArray::kHeaderSize));
+  __ lea(index_2, FieldOperand(elements, index_2, times_pointer_size,
+                               FixedArray::kHeaderSize));
+
+  // Swap elements.  Use object and temp as scratch registers.
+  __ movq(object, Operand(index_1, 0));
+  __ movq(temp,   Operand(index_2, 0));
+  __ movq(Operand(index_2, 0), object);
+  __ movq(Operand(index_1, 0), temp);
+
+  Label new_space;
+  __ InNewSpace(elements, temp, equal, &new_space);
+
+  __ movq(object, elements);
+  __ RecordWriteHelper(object, index_1, temp);
+  __ RecordWriteHelper(elements, index_2, temp);
+
+  __ bind(&new_space);
+  // We are done. Drop elements from the stack, and return undefined.
+  __ addq(rsp, Immediate(3 * kPointerSize));
+  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
+  __ jmp(&done);
+
+  __ bind(&slow_case);
   __ CallRuntime(Runtime::kSwapElements, 3);
+
+  __ bind(&done);
   context()->Plug(rax);
 }
 
@@ -2990,9 +3184,12 @@
 
 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
   ASSERT(args->length() == 1);
-
   VisitForAccumulatorValue(args->at(0));
 
+  if (FLAG_debug_code) {
+    __ AbortIfNotString(rax);
+  }
+
   __ movl(rax, FieldOperand(rax, String::kHashFieldOffset));
   ASSERT(String::kHashShift >= kSmiTagSize);
   __ IndexFromHash(rax, rax);
@@ -3050,19 +3247,8 @@
       Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
       Property* prop = expr->expression()->AsProperty();
       Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
-      if (prop == NULL && var == NULL) {
-        // Result of deleting non-property, non-variable reference is true.
-        // The subexpression may have side effects.
-        VisitForEffect(expr->expression());
-        context()->Plug(true);
-      } else if (var != NULL &&
-                 !var->is_global() &&
-                 var->AsSlot() != NULL &&
-                 var->AsSlot()->type() != Slot::LOOKUP) {
-        // Result of deleting non-global, non-dynamic variables is false.
-        // The subexpression does not have side effects.
-        context()->Plug(false);
-      } else if (prop != NULL) {
+
+      if (prop != NULL) {
         if (prop->is_synthetic()) {
           // Result of deleting parameters is false, even when they rewrite
           // to accesses on the arguments object.
@@ -3070,21 +3256,38 @@
         } else {
           VisitForStackValue(prop->obj());
           VisitForStackValue(prop->key());
+          __ Push(Smi::FromInt(strict_mode_flag()));
           __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
           context()->Plug(rax);
         }
-      } else if (var->is_global()) {
-        __ push(GlobalObjectOperand());
-        __ Push(var->name());
-        __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
-        context()->Plug(rax);
+      } else if (var != NULL) {
+        // Delete of an unqualified identifier is disallowed in strict mode
+        // but "delete this" is.
+        ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
+        if (var->is_global()) {
+          __ push(GlobalObjectOperand());
+          __ Push(var->name());
+          __ Push(Smi::FromInt(kNonStrictMode));
+          __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
+          context()->Plug(rax);
+        } else if (var->AsSlot() != NULL &&
+                   var->AsSlot()->type() != Slot::LOOKUP) {
+          // Result of deleting non-global, non-dynamic variables is false.
+          // The subexpression does not have side effects.
+          context()->Plug(false);
+        } else {
+          // Non-global variable.  Call the runtime to try to delete from the
+          // context where the variable was introduced.
+          __ push(context_register());
+          __ Push(var->name());
+          __ CallRuntime(Runtime::kDeleteContextSlot, 2);
+          context()->Plug(rax);
+        }
       } else {
-        // Non-global variable.  Call the runtime to try to delete from the
-        // context where the variable was introduced.
-        __ push(context_register());
-        __ Push(var->name());
-        __ CallRuntime(Runtime::kDeleteContextSlot, 2);
-        context()->Plug(rax);
+        // Result of deleting non-property, non-variable reference is true.
+        // The subexpression may have side effects.
+        VisitForEffect(expr->expression());
+        context()->Plug(true);
       }
       break;
     }
@@ -3098,16 +3301,22 @@
 
     case Token::NOT: {
       Comment cmnt(masm_, "[ UnaryOperation (NOT)");
-      Label materialize_true, materialize_false;
-      Label* if_true = NULL;
-      Label* if_false = NULL;
-      Label* fall_through = NULL;
-      // Notice that the labels are swapped.
-      context()->PrepareTest(&materialize_true, &materialize_false,
-                             &if_false, &if_true, &fall_through);
-      if (context()->IsTest()) ForwardBailoutToChild(expr);
-      VisitForControl(expr->expression(), if_true, if_false, fall_through);
-      context()->Plug(if_false, if_true);  // Labels swapped.
+      if (context()->IsEffect()) {
+        // Unary NOT has no side effects so it's only necessary to visit the
+        // subexpression.  Match the optimizing compiler by not branching.
+        VisitForEffect(expr->expression());
+      } else {
+        Label materialize_true, materialize_false;
+        Label* if_true = NULL;
+        Label* if_false = NULL;
+        Label* fall_through = NULL;
+        // Notice that the labels are swapped.
+        context()->PrepareTest(&materialize_true, &materialize_false,
+                               &if_false, &if_true, &fall_through);
+        if (context()->IsTest()) ForwardBailoutToChild(expr);
+        VisitForControl(expr->expression(), if_true, if_false, fall_through);
+        context()->Plug(if_false, if_true);  // Labels swapped.
+      }
       break;
     }
 
@@ -3333,7 +3542,9 @@
     case NAMED_PROPERTY: {
       __ Move(rcx, prop->key()->AsLiteral()->handle());
       __ pop(rdx);
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::StoreIC_Initialize_Strict
+                      : Builtins::StoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -3348,7 +3559,9 @@
     case KEYED_PROPERTY: {
       __ pop(rcx);
       __ pop(rdx);
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                      : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -3427,21 +3640,18 @@
   PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
 
   if (check->Equals(Heap::number_symbol())) {
-    Condition is_smi = masm_->CheckSmi(rax);
-    __ j(is_smi, if_true);
+    __ JumpIfSmi(rax, if_true);
     __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
     __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
     Split(equal, if_true, if_false, fall_through);
   } else if (check->Equals(Heap::string_symbol())) {
-    Condition is_smi = masm_->CheckSmi(rax);
-    __ j(is_smi, if_false);
+    __ JumpIfSmi(rax, if_false);
     // Check for undetectable objects => false.
-    __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
+    __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
+    __ j(above_equal, if_false);
     __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
              Immediate(1 << Map::kIsUndetectable));
-    __ j(not_zero, if_false);
-    __ CmpInstanceType(rdx, FIRST_NONSTRING_TYPE);
-    Split(below, if_true, if_false, fall_through);
+    Split(zero, if_true, if_false, fall_through);
   } else if (check->Equals(Heap::boolean_symbol())) {
     __ CompareRoot(rax, Heap::kTrueValueRootIndex);
     __ j(equal, if_true);
@@ -3450,38 +3660,28 @@
   } else if (check->Equals(Heap::undefined_symbol())) {
     __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
     __ j(equal, if_true);
-    Condition is_smi = masm_->CheckSmi(rax);
-    __ j(is_smi, if_false);
+    __ JumpIfSmi(rax, if_false);
     // Check for undetectable objects => true.
     __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
     __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
              Immediate(1 << Map::kIsUndetectable));
     Split(not_zero, if_true, if_false, fall_through);
   } else if (check->Equals(Heap::function_symbol())) {
-    Condition is_smi = masm_->CheckSmi(rax);
-    __ j(is_smi, if_false);
-    __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx);
-    __ j(equal, if_true);
-    // Regular expressions => 'function' (they are callable).
-    __ CmpInstanceType(rdx, JS_REGEXP_TYPE);
-    Split(equal, if_true, if_false, fall_through);
+    __ JumpIfSmi(rax, if_false);
+    __ CmpObjectType(rax, FIRST_FUNCTION_CLASS_TYPE, rdx);
+    Split(above_equal, if_true, if_false, fall_through);
   } else if (check->Equals(Heap::object_symbol())) {
-    Condition is_smi = masm_->CheckSmi(rax);
-    __ j(is_smi, if_false);
+    __ JumpIfSmi(rax, if_false);
     __ CompareRoot(rax, Heap::kNullValueRootIndex);
     __ j(equal, if_true);
-    // Regular expressions => 'function', not 'object'.
-    __ CmpObjectType(rax, JS_REGEXP_TYPE, rdx);
-    __ j(equal, if_false);
+    __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rdx);
+    __ j(below, if_false);
+    __ CmpInstanceType(rdx, FIRST_FUNCTION_CLASS_TYPE);
+    __ j(above_equal, if_false);
     // Check for undetectable objects => false.
     __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
              Immediate(1 << Map::kIsUndetectable));
-    __ j(not_zero, if_false);
-    // Check for JS objects => true.
-    __ CmpInstanceType(rdx, FIRST_JS_OBJECT_TYPE);
-    __ j(below, if_false);
-    __ CmpInstanceType(rdx, LAST_JS_OBJECT_TYPE);
-    Split(below_equal, if_true, if_false, fall_through);
+    Split(zero, if_true, if_false, fall_through);
   } else {
     if (if_false != fall_through) __ jmp(if_false);
   }
@@ -3693,6 +3893,22 @@
 
 
 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) {
+  switch (ic->kind()) {
+    case Code::LOAD_IC:
+      __ IncrementCounter(&Counters::named_load_full, 1);
+      break;
+    case Code::KEYED_LOAD_IC:
+      __ IncrementCounter(&Counters::keyed_load_full, 1);
+      break;
+    case Code::STORE_IC:
+      __ IncrementCounter(&Counters::named_store_full, 1);
+      break;
+    case Code::KEYED_STORE_IC:
+      __ IncrementCounter(&Counters::keyed_store_full, 1);
+    default:
+      break;
+  }
+
   __ call(ic, RelocInfo::CODE_TARGET);
   if (patch_site != NULL && patch_site->is_bound()) {
     patch_site->EmitPatchInfo();
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index 8c2856f..b3243cf 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -108,6 +108,9 @@
                                            Register name,
                                            Register r0,
                                            Register r1) {
+  // Assert that name contains a string.
+  if (FLAG_debug_code) __ AbortIfNotString(name);
+
   // Compute the capacity mask.
   const int kCapacityOffset =
       StringDictionary::kHeaderSize +
@@ -763,7 +766,8 @@
 }
 
 
-void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
+                                   StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- rax     : value
   //  -- rcx     : key
@@ -810,7 +814,7 @@
   __ bind(&slow);
   __ Integer32ToSmi(rcx, rcx);
   __ bind(&slow_with_tagged_index);
-  GenerateRuntimeSetProperty(masm);
+  GenerateRuntimeSetProperty(masm, strict_mode);
   // Never returns to here.
 
   // Check whether the elements is a pixel array.
@@ -819,27 +823,18 @@
   // rbx: receiver's elements array
   // rcx: index, zero-extended.
   __ bind(&check_pixel_array);
-  __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
-                 Heap::kPixelArrayMapRootIndex);
-  __ j(not_equal, &slow);
-  // Check that the value is a smi. If a conversion is needed call into the
-  // runtime to convert and clamp.
-  __ JumpIfNotSmi(rax, &slow);
-  __ cmpl(rcx, FieldOperand(rbx, PixelArray::kLengthOffset));
-  __ j(above_equal, &slow);
-  // No more bailouts to slow case on this path, so key not needed.
-  __ SmiToInteger32(rdi, rax);
-  {  // Clamp the value to [0..255].
-    NearLabel done;
-    __ testl(rdi, Immediate(0xFFFFFF00));
-    __ j(zero, &done);
-    __ setcc(negative, rdi);  // 1 if negative, 0 if positive.
-    __ decb(rdi);  // 0 if negative, 255 if positive.
-    __ bind(&done);
-  }
-  __ movq(rbx, FieldOperand(rbx, PixelArray::kExternalPointerOffset));
-  __ movb(Operand(rbx, rcx, times_1, 0), rdi);
-  __ ret(0);
+  GenerateFastPixelArrayStore(masm,
+                              rdx,
+                              rcx,
+                              rax,
+                              rbx,
+                              rdi,
+                              false,
+                              true,
+                              NULL,
+                              &slow,
+                              &slow,
+                              &slow);
 
   // Extra capacity case: Check if there is extra capacity to
   // perform the store and update the length. Used for adding one
@@ -1233,7 +1228,13 @@
   // rsp[(argc + 1) * 8]      : argument 0 = receiver
   // -----------------------------------
 
+  // Check if the name is a string.
+  Label miss;
+  __ JumpIfSmi(rcx, &miss);
+  Condition cond = masm->IsObjectStringType(rcx, rax, rax);
+  __ j(NegateCondition(cond), &miss);
   GenerateCallNormal(masm, argc);
+  __ bind(&miss);
   GenerateMiss(masm, argc);
 }
 
@@ -1474,7 +1475,7 @@
 
 
 void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
-                                  Code::ExtraICState extra_ic_state) {
+                                  StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : name
@@ -1486,7 +1487,7 @@
   Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
                                          NOT_IN_LOOP,
                                          MONOMORPHIC,
-                                         extra_ic_state);
+                                         strict_mode);
   StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg);
 
   // Cache miss: Jump to runtime.
@@ -1593,7 +1594,8 @@
 }
 
 
-void StoreIC::GenerateGlobalProxy(MacroAssembler* masm) {
+void StoreIC::GenerateGlobalProxy(MacroAssembler* masm,
+                                  StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : name
@@ -1604,14 +1606,17 @@
   __ push(rdx);
   __ push(rcx);
   __ push(rax);
-  __ push(rbx);
+  __ Push(Smi::FromInt(NONE));  // PropertyAttributes
+  __ Push(Smi::FromInt(strict_mode));
+  __ push(rbx);  // return address
 
   // Do tail-call to runtime routine.
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 }
 
 
-void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
+                                              StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- rax     : value
   //  -- rcx     : key
@@ -1623,10 +1628,12 @@
   __ push(rdx);  // receiver
   __ push(rcx);  // key
   __ push(rax);  // value
+  __ Push(Smi::FromInt(NONE));          // PropertyAttributes
+  __ Push(Smi::FromInt(strict_mode));   // Strict mode.
   __ push(rbx);  // return address
 
   // Do tail-call to runtime routine.
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 }
 
 
diff --git a/src/x64/jump-target-x64.cc b/src/x64/jump-target-x64.cc
index 1208b0d..e715604 100644
--- a/src/x64/jump-target-x64.cc
+++ b/src/x64/jump-target-x64.cc
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 36c9aac..bd968b9 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -37,6 +37,53 @@
 namespace internal {
 
 
+// When invoking builtins, we need to record the safepoint in the middle of
+// the invoke instruction sequence generated by the macro assembler.
+class SafepointGenerator : public PostCallGenerator {
+ public:
+  SafepointGenerator(LCodeGen* codegen,
+                     LPointerMap* pointers,
+                     int deoptimization_index,
+                     bool ensure_reloc_space = false)
+      : codegen_(codegen),
+        pointers_(pointers),
+        deoptimization_index_(deoptimization_index),
+        ensure_reloc_space_(ensure_reloc_space),
+        previous_safepoint_position_(-kMinSafepointSize) { }
+  virtual ~SafepointGenerator() { }
+
+  virtual void Generate() {
+    // Ensure that we have enough space after the previous safepoint position
+    // for the generated code there.
+    int position = codegen_->masm()->pc_offset();
+    ASSERT(position > previous_safepoint_position_);
+    if (position < previous_safepoint_position_ + kMinSafepointSize) {
+      int padding_size =
+          previous_safepoint_position_ + kMinSafepointSize - position;
+      STATIC_ASSERT(kMinSafepointSize <= 9);  // One multibyte nop is enough.
+      codegen_->masm()->nop(padding_size);
+      position += padding_size;
+    }
+    // Ensure that we have enough space in the reloc info to patch
+    // this with calls when doing deoptimization.
+    if (ensure_reloc_space_) {
+      codegen_->masm()->RecordComment(RelocInfo::kFillerCommentString, true);
+    }
+    codegen_->RecordSafepoint(pointers_, deoptimization_index_);
+    previous_safepoint_position_ = position;
+  }
+
+ private:
+  static const int kMinSafepointSize =
+      MacroAssembler::kShortCallInstructionLength;
+  LCodeGen* codegen_;
+  LPointerMap* pointers_;
+  int deoptimization_index_;
+  bool ensure_reloc_space_;
+  int previous_safepoint_position_;
+};
+
+
 #define __ masm()->
 
 bool LCodeGen::GenerateCode() {
@@ -46,6 +93,7 @@
   return GeneratePrologue() &&
       GenerateBody() &&
       GenerateDeferredCode() &&
+      GenerateJumpTable() &&
       GenerateSafepointTable();
 }
 
@@ -60,8 +108,8 @@
 
 void LCodeGen::Abort(const char* format, ...) {
   if (FLAG_trace_bailout) {
-    SmartPointer<char> debug_name = graph()->debug_name()->ToCString();
-    PrintF("Aborting LCodeGen in @\"%s\": ", *debug_name);
+    SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
+    PrintF("Aborting LCodeGen in @\"%s\": ", *name);
     va_list arguments;
     va_start(arguments, format);
     OS::VPrint(format, arguments);
@@ -132,6 +180,45 @@
     }
   }
 
+  // Possibly allocate a local context.
+  int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+  if (heap_slots > 0) {
+    Comment(";;; Allocate local context");
+    // Argument to NewContext is the function, which is still in rdi.
+    __ push(rdi);
+    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+      FastNewContextStub stub(heap_slots);
+      __ CallStub(&stub);
+    } else {
+      __ CallRuntime(Runtime::kNewContext, 1);
+    }
+    RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
+    // Context is returned in both rax and rsi.  It replaces the context
+    // passed to us.  It's saved in the stack and kept live in rsi.
+    __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
+
+    // Copy any necessary parameters into the context.
+    int num_parameters = scope()->num_parameters();
+    for (int i = 0; i < num_parameters; i++) {
+      Slot* slot = scope()->parameter(i)->AsSlot();
+      if (slot != NULL && slot->type() == Slot::CONTEXT) {
+        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
+            (num_parameters - 1 - i) * kPointerSize;
+        // Load parameter from stack.
+        __ movq(rax, Operand(rbp, parameter_offset));
+        // Store it in the context.
+        int context_offset = Context::SlotOffset(slot->index());
+        __ movq(Operand(rsi, context_offset), rax);
+        // Update the write barrier. This clobbers all involved
+        // registers, so we have use a third register to avoid
+        // clobbering rsi.
+        __ movq(rcx, rsi);
+        __ RecordWrite(rcx, context_offset, rax, rbx);
+      }
+    }
+    Comment(";;; End allocate local context");
+  }
+
   // Trace the call.
   if (FLAG_trace) {
     __ CallRuntime(Runtime::kTraceEnter, 0);
@@ -170,6 +257,16 @@
 }
 
 
+bool LCodeGen::GenerateJumpTable() {
+  for (int i = 0; i < jump_table_.length(); i++) {
+    JumpTableEntry* info = jump_table_[i];
+    __ bind(&(info->label_));
+    __ Jump(info->address_, RelocInfo::RUNTIME_ENTRY);
+  }
+  return !is_aborted();
+}
+
+
 bool LCodeGen::GenerateDeferredCode() {
   ASSERT(is_generating());
   for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
@@ -252,8 +349,7 @@
 
 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
   Handle<Object> literal = chunk_->LookupLiteral(op);
-  Representation r = chunk_->LookupLiteralRepresentation(op);
-  ASSERT(r.IsTagged());
+  ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
   return literal;
 }
 
@@ -443,10 +539,17 @@
   if (cc == no_condition) {
     __ Jump(entry, RelocInfo::RUNTIME_ENTRY);
   } else {
-    NearLabel done;
-    __ j(NegateCondition(cc), &done);
-    __ Jump(entry, RelocInfo::RUNTIME_ENTRY);
-    __ bind(&done);
+    JumpTableEntry* jump_info = NULL;
+    // We often have several deopts to the same entry, reuse the last
+    // jump entry if this is the case.
+    if (jump_table_.length() > 0 &&
+        jump_table_[jump_table_.length() - 1]->address_ == entry) {
+      jump_info = jump_table_[jump_table_.length() - 1];
+    } else {
+      jump_info = new JumpTableEntry(entry);
+      jump_table_.Add(jump_info);
+    }
+    __ j(cc, &jump_info->label_);
   }
 }
 
@@ -458,7 +561,8 @@
   Handle<DeoptimizationInputData> data =
       Factory::NewDeoptimizationInputData(length, TENURED);
 
-  data->SetTranslationByteArray(*translations_.CreateByteArray());
+  Handle<ByteArray> translations = translations_.CreateByteArray();
+  data->SetTranslationByteArray(*translations);
   data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
 
   Handle<FixedArray> literals =
@@ -539,6 +643,12 @@
 }
 
 
+void LCodeGen::RecordSafepoint(int deoptimization_index) {
+  LPointerMap empty_pointers(RelocInfo::kNoPosition);
+  RecordSafepoint(&empty_pointers, deoptimization_index);
+}
+
+
 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
                                             int arguments,
                                             int deoptimization_index) {
@@ -611,13 +721,13 @@
       break;
     }
     case CodeStub::StringCharAt: {
-      // TODO(1116): Add StringCharAt stub to x64.
-      Abort("Unimplemented: %s", "StringCharAt Stub");
+      StringCharAtStub stub;
+      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
       break;
     }
     case CodeStub::MathPow: {
-      // TODO(1115): Add MathPow stub to x64.
-      Abort("Unimplemented: %s", "MathPow Stub");
+      MathPowStub stub;
+      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
       break;
     }
     case CodeStub::NumberToString: {
@@ -636,7 +746,8 @@
       break;
     }
     case CodeStub::TranscendentalCache: {
-      TranscendentalCacheStub stub(instr->transcendental_type());
+      TranscendentalCacheStub stub(instr->transcendental_type(),
+                                   TranscendentalCacheStub::TAGGED);
       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
       break;
     }
@@ -652,7 +763,42 @@
 
 
 void LCodeGen::DoModI(LModI* instr) {
-  Abort("Unimplemented: %s", "DoModI");
+  LOperand* right = instr->InputAt(1);
+  ASSERT(ToRegister(instr->result()).is(rdx));
+  ASSERT(ToRegister(instr->InputAt(0)).is(rax));
+  ASSERT(!ToRegister(instr->InputAt(1)).is(rax));
+  ASSERT(!ToRegister(instr->InputAt(1)).is(rdx));
+
+  Register right_reg = ToRegister(right);
+
+  // Check for x % 0.
+  if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
+    __ testl(right_reg, right_reg);
+    DeoptimizeIf(zero, instr->environment());
+  }
+
+  // Sign extend eax to edx. (We are using only the low 32 bits of the values.)
+  __ cdq();
+
+  // Check for (0 % -x) that will produce negative zero.
+  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    NearLabel positive_left;
+    NearLabel done;
+    __ testl(rax, rax);
+    __ j(not_sign, &positive_left);
+    __ idivl(right_reg);
+
+    // Test the remainder for 0, because then the result would be -0.
+    __ testl(rdx, rdx);
+    __ j(not_zero, &done);
+
+    DeoptimizeIf(no_condition, instr->environment());
+    __ bind(&positive_left);
+    __ idivl(right_reg);
+    __ bind(&done);
+  } else {
+    __ idivl(right_reg);
+  }
 }
 
 
@@ -888,21 +1034,15 @@
   ASSERT(instr->result()->IsDoubleRegister());
   XMMRegister res = ToDoubleRegister(instr->result());
   double v = instr->value();
+  uint64_t int_val = BitCast<uint64_t, double>(v);
   // Use xor to produce +0.0 in a fast and compact way, but avoid to
   // do so if the constant is -0.0.
-  if (BitCast<uint64_t, double>(v) == 0) {
+  if (int_val == 0) {
     __ xorpd(res, res);
   } else {
     Register tmp = ToRegister(instr->TempAt(0));
-    int32_t v_int32 = static_cast<int32_t>(v);
-    if (static_cast<double>(v_int32) == v) {
-      __ movl(tmp, Immediate(v_int32));
-      __ cvtlsi2sd(res, tmp);
-    } else {
-      uint64_t int_val = BitCast<uint64_t, double>(v);
-      __ Set(tmp, int_val);
-      __ movd(res, tmp);
-    }
+    __ Set(tmp, int_val);
+    __ movq(res, tmp);
   }
 }
 
@@ -935,7 +1075,19 @@
 
 
 void LCodeGen::DoValueOf(LValueOf* instr) {
-  Abort("Unimplemented: %s", "DoValueOf");
+  Register input = ToRegister(instr->InputAt(0));
+  Register result = ToRegister(instr->result());
+  ASSERT(input.is(result));
+  NearLabel done;
+  // If the object is a smi return the object.
+  __ JumpIfSmi(input, &done);
+
+  // If the object is not a value type, return the object.
+  __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister);
+  __ j(not_equal, &done);
+  __ movq(result, FieldOperand(input, JSValue::kValueOffset));
+
+  __ bind(&done);
 }
 
 
@@ -978,7 +1130,36 @@
 
 
 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
-  Abort("Unimplemented: %s", "DoArithmeticD");
+  XMMRegister left = ToDoubleRegister(instr->InputAt(0));
+  XMMRegister right = ToDoubleRegister(instr->InputAt(1));
+  XMMRegister result = ToDoubleRegister(instr->result());
+  // All operations except MOD are computed in-place.
+  ASSERT(instr->op() == Token::MOD || left.is(result));
+  switch (instr->op()) {
+    case Token::ADD:
+      __ addsd(left, right);
+      break;
+    case Token::SUB:
+       __ subsd(left, right);
+       break;
+    case Token::MUL:
+      __ mulsd(left, right);
+      break;
+    case Token::DIV:
+      __ divsd(left, right);
+      break;
+    case Token::MOD:
+      __ PrepareCallCFunction(2);
+      __ movsd(xmm0, left);
+      ASSERT(right.is(xmm1));
+      __ CallCFunction(ExternalReference::double_fp_operation(Token::MOD), 2);
+      __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+      __ movsd(result, xmm0);
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
 }
 
 
@@ -1267,7 +1448,7 @@
     __ j(equal, &load);
     __ movl(result, Immediate(Heap::kFalseValueRootIndex));
     __ bind(&load);
-    __ movq(result, Operand(kRootRegister, result, times_pointer_size, 0));
+    __ LoadRootIndexed(result, result, 0);
   } else {
     NearLabel true_value, false_value, done;
     __ j(equal, &true_value);
@@ -1398,8 +1579,7 @@
   }
   // result is zero if input is a smi, and one otherwise.
   ASSERT(Heap::kFalseValueRootIndex == Heap::kTrueValueRootIndex + 1);
-  __ movq(result, Operand(kRootRegister, result, times_pointer_size,
-                          Heap::kTrueValueRootIndex * kPointerSize));
+  __ LoadRootIndexed(result, result, Heap::kTrueValueRootIndex);
 }
 
 
@@ -1440,7 +1620,20 @@
 
 
 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
-  Abort("Unimplemented: %s", "DoHasInstanceType");
+  Register input = ToRegister(instr->InputAt(0));
+  Register result = ToRegister(instr->result());
+
+  ASSERT(instr->hydrogen()->value()->representation().IsTagged());
+  __ testl(input, Immediate(kSmiTagMask));
+  NearLabel done, is_false;
+  __ j(zero, &is_false);
+  __ CmpObjectType(input, TestType(instr->hydrogen()), result);
+  __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false);
+  __ LoadRoot(result, Heap::kTrueValueRootIndex);
+  __ jmp(&done);
+  __ bind(&is_false);
+  __ LoadRoot(result, Heap::kFalseValueRootIndex);
+  __ bind(&done);
 }
 
 
@@ -1459,8 +1652,32 @@
 }
 
 
+void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
+  Register input = ToRegister(instr->InputAt(0));
+  Register result = ToRegister(instr->result());
+
+  if (FLAG_debug_code) {
+    __ AbortIfNotString(input);
+  }
+
+  __ movl(result, FieldOperand(input, String::kHashFieldOffset));
+  ASSERT(String::kHashShift >= kSmiTagSize);
+  __ IndexFromHash(result, result);
+}
+
+
 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
-  Abort("Unimplemented: %s", "DoHasCachedArrayIndex");
+  Register input = ToRegister(instr->InputAt(0));
+  Register result = ToRegister(instr->result());
+
+  ASSERT(instr->hydrogen()->value()->representation().IsTagged());
+  __ LoadRoot(result, Heap::kTrueValueRootIndex);
+  __ testl(FieldOperand(input, String::kHashFieldOffset),
+           Immediate(String::kContainsCachedArrayIndexMask));
+  NearLabel done;
+  __ j(zero, &done);
+  __ LoadRoot(result, Heap::kFalseValueRootIndex);
+  __ bind(&done);
 }
 
 
@@ -1473,7 +1690,7 @@
 
   __ testl(FieldOperand(input, String::kHashFieldOffset),
            Immediate(String::kContainsCachedArrayIndexMask));
-  EmitBranch(true_block, false_block, not_equal);
+  EmitBranch(true_block, false_block, equal);
 }
 
 
@@ -1582,7 +1799,18 @@
 
 
 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
-  Abort("Unimplemented: %s", "DoInstanceOf");
+  InstanceofStub stub(InstanceofStub::kNoFlags);
+  __ push(ToRegister(instr->InputAt(0)));
+  __ push(ToRegister(instr->InputAt(1)));
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+  NearLabel true_value, done;
+  __ testq(rax, rax);
+  __ j(zero, &true_value);
+  __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
+  __ jmp(&done);
+  __ bind(&true_value);
+  __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
+  __ bind(&done);
 }
 
 
@@ -1590,7 +1818,9 @@
   int true_block = chunk_->LookupDestination(instr->true_block_id());
   int false_block = chunk_->LookupDestination(instr->false_block_id());
 
-  InstanceofStub stub(InstanceofStub::kArgsInRegisters);
+  InstanceofStub stub(InstanceofStub::kNoFlags);
+  __ push(ToRegister(instr->InputAt(0)));
+  __ push(ToRegister(instr->InputAt(1)));
   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   __ testq(rax, rax);
   EmitBranch(true_block, false_block, zero);
@@ -1598,13 +1828,63 @@
 
 
 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
-  Abort("Unimplemented: %s", "DoInstanceOfKnowGLobal");
+  class DeferredInstanceOfKnownGlobal: public LDeferredCode {
+   public:
+    DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
+                                  LInstanceOfKnownGlobal* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() {
+      codegen()->DoDeferredLInstanceOfKnownGlobal(instr_);
+    }
+
+   private:
+    LInstanceOfKnownGlobal* instr_;
+  };
+
+
+  DeferredInstanceOfKnownGlobal* deferred;
+  deferred = new DeferredInstanceOfKnownGlobal(this, instr);
+
+  Label false_result;
+  Register object = ToRegister(instr->InputAt(0));
+
+  // A Smi is not an instance of anything.
+  __ JumpIfSmi(object, &false_result);
+
+  // Null is not an instance of anything.
+  __ CompareRoot(object, Heap::kNullValueRootIndex);
+  __ j(equal, &false_result);
+
+  // String values are not instances of anything.
+  __ JumpIfNotString(object, kScratchRegister, deferred->entry());
+
+  __ bind(&false_result);
+  __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
+
+  __ bind(deferred->exit());
 }
 
 
-void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
-                                                Label* map_check) {
-  Abort("Unimplemented: %s", "DoDeferredLInstanceOfKnownGlobakl");
+void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
+  __ PushSafepointRegisters();
+
+  InstanceofStub stub(InstanceofStub::kNoFlags);
+
+  __ push(ToRegister(instr->InputAt(0)));
+  __ Push(instr->function());
+  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+  __ movq(kScratchRegister, rax);
+  __ PopSafepointRegisters();
+  __ testq(kScratchRegister, kScratchRegister);
+  Label load_false;
+  Label done;
+  __ j(not_zero, &load_false);
+  __ LoadRoot(rax, Heap::kTrueValueRootIndex);
+  __ jmp(&done);
+  __ bind(&load_false);
+  __ LoadRoot(rax, Heap::kFalseValueRootIndex);
+  __ bind(&done);
 }
 
 
@@ -1701,7 +1981,21 @@
 
 
 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
-  Abort("Unimplemented: %s", "DoLoadContextSlot");
+  Register context = ToRegister(instr->context());
+  Register result = ToRegister(instr->result());
+  __ movq(result, ContextOperand(context, instr->slot_index()));
+}
+
+
+void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
+  Register context = ToRegister(instr->context());
+  Register value = ToRegister(instr->value());
+  __ movq(ContextOperand(context, instr->slot_index()), value);
+  if (instr->needs_write_barrier()) {
+    int offset = Context::SlotOffset(instr->slot_index());
+    Register scratch = ToRegister(instr->TempAt(0));
+    __ RecordWrite(context, offset, value, scratch);
+  }
 }
 
 
@@ -1797,7 +2091,20 @@
 
 
 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
-  Abort("Unimplemented: %s", "DoAccessArgumentsAt");
+  Register arguments = ToRegister(instr->arguments());
+  Register length = ToRegister(instr->length());
+  Register result = ToRegister(instr->result());
+
+  if (instr->index()->IsRegister()) {
+    __ subl(length, ToRegister(instr->index()));
+  } else {
+    __ subl(length, ToOperand(instr->index()));
+  }
+  DeoptimizeIf(below_equal, instr->environment());
+
+  // There are two words between the frame pointer and the last argument.
+  // Subtracting from length accounts for one of them add one more.
+  __ movq(result, Operand(arguments, length, times_pointer_size, kPointerSize));
 }
 
 
@@ -1831,40 +2138,135 @@
 
 
 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
-  Abort("Unimplemented: %s", "DoLoadKeyedGeneric");
+  ASSERT(ToRegister(instr->object()).is(rdx));
+  ASSERT(ToRegister(instr->key()).is(rax));
+
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
 
 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
-  Abort("Unimplemented: %s", "DoArgumentsElements");
+  Register result = ToRegister(instr->result());
+
+  // Check for arguments adapter frame.
+  NearLabel done, adapted;
+  __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
+  __ SmiCompare(Operand(result, StandardFrameConstants::kContextOffset),
+                Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+  __ j(equal, &adapted);
+
+  // No arguments adaptor frame.
+  __ movq(result, rbp);
+  __ jmp(&done);
+
+  // Arguments adaptor frame present.
+  __ bind(&adapted);
+  __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
+
+  // Result is the frame pointer for the frame if not adapted and for the real
+  // frame below the adaptor frame if adapted.
+  __ bind(&done);
 }
 
 
 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
-  Abort("Unimplemented: %s", "DoArgumentsLength");
+  Register result = ToRegister(instr->result());
+
+  NearLabel done;
+
+  // If no arguments adaptor frame the number of arguments is fixed.
+  if (instr->InputAt(0)->IsRegister()) {
+    __ cmpq(rbp, ToRegister(instr->InputAt(0)));
+  } else {
+    __ cmpq(rbp, ToOperand(instr->InputAt(0)));
+  }
+  __ movq(result, Immediate(scope()->num_parameters()));
+  __ j(equal, &done);
+
+  // Arguments adaptor frame present. Get argument length from there.
+  __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
+  __ movq(result, Operand(result,
+                          ArgumentsAdaptorFrameConstants::kLengthOffset));
+  __ SmiToInteger32(result, result);
+
+  // Argument length is in result register.
+  __ bind(&done);
 }
 
 
 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
-  Abort("Unimplemented: %s", "DoApplyArguments");
+  Register receiver = ToRegister(instr->receiver());
+  Register function = ToRegister(instr->function());
+  Register length = ToRegister(instr->length());
+  Register elements = ToRegister(instr->elements());
+  ASSERT(receiver.is(rax));  // Used for parameter count.
+  ASSERT(function.is(rdi));  // Required by InvokeFunction.
+  ASSERT(ToRegister(instr->result()).is(rax));
+
+  // If the receiver is null or undefined, we have to pass the global object
+  // as a receiver.
+  NearLabel global_object, receiver_ok;
+  __ CompareRoot(receiver, Heap::kNullValueRootIndex);
+  __ j(equal, &global_object);
+  __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex);
+  __ j(equal, &global_object);
+
+  // The receiver should be a JS object.
+  Condition is_smi = __ CheckSmi(receiver);
+  DeoptimizeIf(is_smi, instr->environment());
+  __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, kScratchRegister);
+  DeoptimizeIf(below, instr->environment());
+  __ jmp(&receiver_ok);
+
+  __ bind(&global_object);
+  // TODO(kmillikin): We have a hydrogen value for the global object.  See
+  // if it's better to use it than to explicitly fetch it from the context
+  // here.
+  __ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset));
+  __ movq(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX));
+  __ bind(&receiver_ok);
+
+  // Copy the arguments to this function possibly from the
+  // adaptor frame below it.
+  const uint32_t kArgumentsLimit = 1 * KB;
+  __ cmpq(length, Immediate(kArgumentsLimit));
+  DeoptimizeIf(above, instr->environment());
+
+  __ push(receiver);
+  __ movq(receiver, length);
+
+  // Loop through the arguments pushing them onto the execution
+  // stack.
+  NearLabel invoke, loop;
+  // length is a small non-negative integer, due to the test above.
+  __ testl(length, length);
+  __ j(zero, &invoke);
+  __ bind(&loop);
+  __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize));
+  __ decl(length);
+  __ j(not_zero, &loop);
+
+  // Invoke the function.
+  __ bind(&invoke);
+  ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
+  LPointerMap* pointers = instr->pointer_map();
+  LEnvironment* env = instr->deoptimization_environment();
+  RecordPosition(pointers->position());
+  RegisterEnvironmentForDeoptimization(env);
+  SafepointGenerator safepoint_generator(this,
+                                         pointers,
+                                         env->deoptimization_index(),
+                                         true);
+  v8::internal::ParameterCount actual(rax);
+  __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
 }
 
 
 void LCodeGen::DoPushArgument(LPushArgument* instr) {
   LOperand* argument = instr->InputAt(0);
   if (argument->IsConstantOperand()) {
-    LConstantOperand* const_op = LConstantOperand::cast(argument);
-    Handle<Object> literal = chunk_->LookupLiteral(const_op);
-    Representation r = chunk_->LookupLiteralRepresentation(const_op);
-    if (r.IsInteger32()) {
-      ASSERT(literal->IsNumber());
-      __ push(Immediate(static_cast<int32_t>(literal->Number())));
-    } else if (r.IsDouble()) {
-      Abort("unsupported double immediate");
-    } else {
-      ASSERT(r.IsTagged());
-      __ Push(literal);
-    }
+    EmitPushConstantOperand(argument);
   } else if (argument->IsRegister()) {
     __ push(ToRegister(argument));
   } else {
@@ -1880,6 +2282,15 @@
 }
 
 
+void LCodeGen::DoOuterContext(LOuterContext* instr) {
+  Register context = ToRegister(instr->context());
+  Register result = ToRegister(instr->result());
+  __ movq(result,
+          Operand(context, Context::SlotOffset(Context::CLOSURE_INDEX)));
+  __ movq(result, FieldOperand(result, JSFunction::kContextOffset));
+}
+
+
 void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
   Register result = ToRegister(instr->result());
   __ movq(result, GlobalObjectOperand());
@@ -1898,7 +2309,7 @@
                                  LInstruction* instr) {
   // Change context if needed.
   bool change_context =
-      (graph()->info()->closure()->context() != function->context()) ||
+      (info()->closure()->context() != function->context()) ||
       scope()->contains_with() ||
       (scope()->num_heap_slots() > 0);
   if (change_context) {
@@ -1915,7 +2326,7 @@
   RecordPosition(pointers->position());
 
   // Invoke function.
-  if (*function == *graph()->info()->closure()) {
+  if (*function == *info()->closure()) {
     __ CallSelf();
   } else {
     __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset));
@@ -1937,62 +2348,299 @@
 
 
 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
-  Abort("Unimplemented: %s", "DoDeferredMathAbsTaggedHeapNumber");
+  Register input_reg = ToRegister(instr->InputAt(0));
+  __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
+                 Heap::kHeapNumberMapRootIndex);
+  DeoptimizeIf(not_equal, instr->environment());
+
+  Label done;
+  Register tmp = input_reg.is(rax) ? rcx : rax;
+  Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx;
+
+  // Preserve the value of all registers.
+  __ PushSafepointRegisters();
+
+  Label negative;
+  __ movl(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
+  // Check the sign of the argument. If the argument is positive, just
+  // return it. We do not need to patch the stack since |input| and
+  // |result| are the same register and |input| will be restored
+  // unchanged by popping safepoint registers.
+  __ testl(tmp, Immediate(HeapNumber::kSignMask));
+  __ j(not_zero, &negative);
+  __ jmp(&done);
+
+  __ bind(&negative);
+
+  Label allocated, slow;
+  __ AllocateHeapNumber(tmp, tmp2, &slow);
+  __ jmp(&allocated);
+
+  // Slow case: Call the runtime system to do the number allocation.
+  __ bind(&slow);
+
+  __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
+  RecordSafepointWithRegisters(
+      instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
+  // Set the pointer to the new heap number in tmp.
+  if (!tmp.is(rax)) {
+    __ movq(tmp, rax);
+  }
+
+  // Restore input_reg after call to runtime.
+  __ LoadFromSafepointRegisterSlot(input_reg, input_reg);
+
+  __ bind(&allocated);
+  __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset));
+  __ shl(tmp2, Immediate(1));
+  __ shr(tmp2, Immediate(1));
+  __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2);
+  __ StoreToSafepointRegisterSlot(input_reg, tmp);
+
+  __ bind(&done);
+  __ PopSafepointRegisters();
+}
+
+
+void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
+  Register input_reg = ToRegister(instr->InputAt(0));
+  __ testl(input_reg, input_reg);
+  Label is_positive;
+  __ j(not_sign, &is_positive);
+  __ negl(input_reg);  // Sets flags.
+  DeoptimizeIf(negative, instr->environment());
+  __ bind(&is_positive);
 }
 
 
 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
-  Abort("Unimplemented: %s", "DoMathAbs");
+  // Class for deferred case.
+  class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
+   public:
+    DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
+                                    LUnaryMathOperation* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() {
+      codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
+    }
+   private:
+    LUnaryMathOperation* instr_;
+  };
+
+  ASSERT(instr->InputAt(0)->Equals(instr->result()));
+  Representation r = instr->hydrogen()->value()->representation();
+
+  if (r.IsDouble()) {
+    XMMRegister scratch = xmm0;
+    XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
+    __ xorpd(scratch, scratch);
+    __ subsd(scratch, input_reg);
+    __ andpd(input_reg, scratch);
+  } else if (r.IsInteger32()) {
+    EmitIntegerMathAbs(instr);
+  } else {  // Tagged case.
+    DeferredMathAbsTaggedHeapNumber* deferred =
+        new DeferredMathAbsTaggedHeapNumber(this, instr);
+    Register input_reg = ToRegister(instr->InputAt(0));
+    // Smi check.
+    __ JumpIfNotSmi(input_reg, deferred->entry());
+    EmitIntegerMathAbs(instr);
+    __ bind(deferred->exit());
+  }
 }
 
 
 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
-  Abort("Unimplemented: %s", "DoMathFloor");
+  XMMRegister xmm_scratch = xmm0;
+  Register output_reg = ToRegister(instr->result());
+  XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
+  __ xorpd(xmm_scratch, xmm_scratch);  // Zero the register.
+  __ ucomisd(input_reg, xmm_scratch);
+
+  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    DeoptimizeIf(below_equal, instr->environment());
+  } else {
+    DeoptimizeIf(below, instr->environment());
+  }
+
+  // Use truncating instruction (OK because input is positive).
+  __ cvttsd2si(output_reg, input_reg);
+
+  // Overflow is signalled with minint.
+  __ cmpl(output_reg, Immediate(0x80000000));
+  DeoptimizeIf(equal, instr->environment());
 }
 
 
 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
-  Abort("Unimplemented: %s", "DoMathRound");
+  const XMMRegister xmm_scratch = xmm0;
+  Register output_reg = ToRegister(instr->result());
+  XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
+
+  // xmm_scratch = 0.5
+  __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE);
+  __ movq(xmm_scratch, kScratchRegister);
+
+  // input = input + 0.5
+  __ addsd(input_reg, xmm_scratch);
+
+  // We need to return -0 for the input range [-0.5, 0[, otherwise
+  // compute Math.floor(value + 0.5).
+  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    __ ucomisd(input_reg, xmm_scratch);
+    DeoptimizeIf(below_equal, instr->environment());
+  } else {
+    // If we don't need to bailout on -0, we check only bailout
+    // on negative inputs.
+    __ xorpd(xmm_scratch, xmm_scratch);  // Zero the register.
+    __ ucomisd(input_reg, xmm_scratch);
+    DeoptimizeIf(below, instr->environment());
+  }
+
+  // Compute Math.floor(value + 0.5).
+  // Use truncating instruction (OK because input is positive).
+  __ cvttsd2si(output_reg, input_reg);
+
+  // Overflow is signalled with minint.
+  __ cmpl(output_reg, Immediate(0x80000000));
+  DeoptimizeIf(equal, instr->environment());
 }
 
 
 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
-  Abort("Unimplemented: %s", "DoMathSqrt");
+  XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
+  ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
+  __ sqrtsd(input_reg, input_reg);
 }
 
 
 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
-  Abort("Unimplemented: %s", "DoMathPowHalf");
+  XMMRegister xmm_scratch = xmm0;
+  XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
+  ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
+  __ xorpd(xmm_scratch, xmm_scratch);
+  __ addsd(input_reg, xmm_scratch);  // Convert -0 to +0.
+  __ sqrtsd(input_reg, input_reg);
 }
 
 
 void LCodeGen::DoPower(LPower* instr) {
-  Abort("Unimplemented: %s", "DoPower");
+  LOperand* left = instr->InputAt(0);
+  XMMRegister left_reg = ToDoubleRegister(left);
+  ASSERT(!left_reg.is(xmm1));
+  LOperand* right = instr->InputAt(1);
+  XMMRegister result_reg = ToDoubleRegister(instr->result());
+  Representation exponent_type = instr->hydrogen()->right()->representation();
+  if (exponent_type.IsDouble()) {
+    __ PrepareCallCFunction(2);
+    // Move arguments to correct registers
+    __ movsd(xmm0, left_reg);
+    ASSERT(ToDoubleRegister(right).is(xmm1));
+    __ CallCFunction(ExternalReference::power_double_double_function(), 2);
+  } else if (exponent_type.IsInteger32()) {
+    __ PrepareCallCFunction(2);
+    // Move arguments to correct registers: xmm0 and edi (not rdi).
+    // On Windows, the registers are xmm0 and edx.
+    __ movsd(xmm0, left_reg);
+#ifdef _WIN64
+    ASSERT(ToRegister(right).is(rdx));
+#else
+    ASSERT(ToRegister(right).is(rdi));
+#endif
+    __ CallCFunction(ExternalReference::power_double_int_function(), 2);
+  } else {
+    ASSERT(exponent_type.IsTagged());
+    CpuFeatures::Scope scope(SSE2);
+    Register right_reg = ToRegister(right);
+
+    Label non_smi, call;
+    __ JumpIfNotSmi(right_reg, &non_smi);
+    __ SmiToInteger32(right_reg, right_reg);
+    __ cvtlsi2sd(xmm1, right_reg);
+    __ jmp(&call);
+
+    __ bind(&non_smi);
+    __ CmpObjectType(right_reg, HEAP_NUMBER_TYPE , kScratchRegister);
+    DeoptimizeIf(not_equal, instr->environment());
+    __ movsd(xmm1, FieldOperand(right_reg, HeapNumber::kValueOffset));
+
+    __ bind(&call);
+    __ PrepareCallCFunction(2);
+    // Move arguments to correct registers xmm0 and xmm1.
+    __ movsd(xmm0, left_reg);
+    // Right argument is already in xmm1.
+    __ CallCFunction(ExternalReference::power_double_double_function(), 2);
+  }
+  // Return value is in xmm0.
+  __ movsd(result_reg, xmm0);
 }
 
 
 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
-  Abort("Unimplemented: %s", "DoMathLog");
+  ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
+  TranscendentalCacheStub stub(TranscendentalCache::LOG,
+                               TranscendentalCacheStub::UNTAGGED);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
 }
 
 
 void LCodeGen::DoMathCos(LUnaryMathOperation* instr) {
-  Abort("Unimplemented: %s", "DoMathCos");
+  ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
+  TranscendentalCacheStub stub(TranscendentalCache::LOG,
+                               TranscendentalCacheStub::UNTAGGED);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
 }
 
 
 void LCodeGen::DoMathSin(LUnaryMathOperation* instr) {
-  Abort("Unimplemented: %s", "DoMathSin");
+  ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
+  TranscendentalCacheStub stub(TranscendentalCache::LOG,
+                               TranscendentalCacheStub::UNTAGGED);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
 }
 
 
 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
-  Abort("Unimplemented: %s", "DoUnaryMathOperation");
+  switch (instr->op()) {
+    case kMathAbs:
+      DoMathAbs(instr);
+      break;
+    case kMathFloor:
+      DoMathFloor(instr);
+      break;
+    case kMathRound:
+      DoMathRound(instr);
+      break;
+    case kMathSqrt:
+      DoMathSqrt(instr);
+      break;
+    case kMathPowHalf:
+      DoMathPowHalf(instr);
+      break;
+    case kMathCos:
+      DoMathCos(instr);
+      break;
+    case kMathSin:
+      DoMathSin(instr);
+      break;
+    case kMathLog:
+      DoMathLog(instr);
+      break;
+
+    default:
+      UNREACHABLE();
+  }
 }
 
 
 void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
-  Abort("Unimplemented: %s", "DoCallKeyed");
+  ASSERT(ToRegister(instr->key()).is(rcx));
+  ASSERT(ToRegister(instr->result()).is(rax));
+
+  int arity = instr->arity();
+  Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arity, NOT_IN_LOOP);
+  CallCode(ic, RelocInfo::CODE_TARGET, instr);
+  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
 }
 
 
@@ -2008,7 +2656,13 @@
 
 
 void LCodeGen::DoCallFunction(LCallFunction* instr) {
-  Abort("Unimplemented: %s", "DoCallFunction");
+  ASSERT(ToRegister(instr->result()).is(rax));
+
+  int arity = instr->arity();
+  CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+  __ Drop(1);
 }
 
 
@@ -2040,7 +2694,7 @@
 
 
 void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
-  Abort("Unimplemented: %s", "DoCallRuntime");
+  CallRuntime(instr->function(), instr->arity(), instr);
 }
 
 
@@ -2075,7 +2729,32 @@
 
 
 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
-  Abort("Unimplemented: %s", "DoStoreNamedGeneric");
+  ASSERT(ToRegister(instr->object()).is(rdx));
+  ASSERT(ToRegister(instr->value()).is(rax));
+
+  __ Move(rcx, instr->hydrogen()->name());
+  Handle<Code> ic(Builtins::builtin(
+      info_->is_strict() ? Builtins::StoreIC_Initialize_Strict
+                         : Builtins::StoreIC_Initialize));
+  CallCode(ic, RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoStorePixelArrayElement(LStorePixelArrayElement* instr) {
+  Register external_pointer = ToRegister(instr->external_pointer());
+  Register key = ToRegister(instr->key());
+  Register value = ToRegister(instr->value());
+
+  {  // Clamp the value to [0..255].
+    NearLabel done;
+    __ testl(value, Immediate(0xFFFFFF00));
+    __ j(zero, &done);
+    __ setcc(negative, value);  // 1 if negative, 0 if positive.
+    __ decb(value);  // 0 if negative, 255 if positive.
+    __ bind(&done);
+  }
+
+  __ movb(Operand(external_pointer, key, times_1, 0), value);
 }
 
 
@@ -2121,7 +2800,161 @@
 
 
 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
-  Abort("Unimplemented: %s", "DoStoreKeyedGeneric");
+  ASSERT(ToRegister(instr->object()).is(rdx));
+  ASSERT(ToRegister(instr->key()).is(rcx));
+  ASSERT(ToRegister(instr->value()).is(rax));
+
+  Handle<Code> ic(Builtins::builtin(
+      info_->is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                         : Builtins::KeyedStoreIC_Initialize));
+  CallCode(ic, RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
+  class DeferredStringCharCodeAt: public LDeferredCode {
+   public:
+    DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); }
+   private:
+    LStringCharCodeAt* instr_;
+  };
+
+  Register string = ToRegister(instr->string());
+  Register index = no_reg;
+  int const_index = -1;
+  if (instr->index()->IsConstantOperand()) {
+    const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+    STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
+    if (!Smi::IsValid(const_index)) {
+      // Guaranteed to be out of bounds because of the assert above.
+      // So the bounds check that must dominate this instruction must
+      // have deoptimized already.
+      if (FLAG_debug_code) {
+        __ Abort("StringCharCodeAt: out of bounds index.");
+      }
+      // No code needs to be generated.
+      return;
+    }
+  } else {
+    index = ToRegister(instr->index());
+  }
+  Register result = ToRegister(instr->result());
+
+  DeferredStringCharCodeAt* deferred =
+      new DeferredStringCharCodeAt(this, instr);
+
+  NearLabel flat_string, ascii_string, done;
+
+  // Fetch the instance type of the receiver into result register.
+  __ movq(result, FieldOperand(string, HeapObject::kMapOffset));
+  __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
+
+  // We need special handling for non-sequential strings.
+  STATIC_ASSERT(kSeqStringTag == 0);
+  __ testb(result, Immediate(kStringRepresentationMask));
+  __ j(zero, &flat_string);
+
+  // Handle cons strings and go to deferred code for the rest.
+  __ testb(result, Immediate(kIsConsStringMask));
+  __ j(zero, deferred->entry());
+
+  // ConsString.
+  // Check whether the right hand side is the empty string (i.e. if
+  // this is really a flat string in a cons string). If that is not
+  // the case we would rather go to the runtime system now to flatten
+  // the string.
+  __ CompareRoot(FieldOperand(string, ConsString::kSecondOffset),
+                 Heap::kEmptyStringRootIndex);
+  __ j(not_equal, deferred->entry());
+  // Get the first of the two strings and load its instance type.
+  __ movq(string, FieldOperand(string, ConsString::kFirstOffset));
+  __ movq(result, FieldOperand(string, HeapObject::kMapOffset));
+  __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
+  // If the first cons component is also non-flat, then go to runtime.
+  STATIC_ASSERT(kSeqStringTag == 0);
+  __ testb(result, Immediate(kStringRepresentationMask));
+  __ j(not_zero, deferred->entry());
+
+  // Check for ASCII or two-byte string.
+  __ bind(&flat_string);
+  STATIC_ASSERT(kAsciiStringTag != 0);
+  __ testb(result, Immediate(kStringEncodingMask));
+  __ j(not_zero, &ascii_string);
+
+  // Two-byte string.
+  // Load the two-byte character code into the result register.
+  STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
+  if (instr->index()->IsConstantOperand()) {
+    __ movzxwl(result,
+               FieldOperand(string,
+                            SeqTwoByteString::kHeaderSize +
+                            (kUC16Size * const_index)));
+  } else {
+    __ movzxwl(result, FieldOperand(string,
+                                    index,
+                                    times_2,
+                                    SeqTwoByteString::kHeaderSize));
+  }
+  __ jmp(&done);
+
+  // ASCII string.
+  // Load the byte into the result register.
+  __ bind(&ascii_string);
+  if (instr->index()->IsConstantOperand()) {
+    __ movzxbl(result, FieldOperand(string,
+                                    SeqAsciiString::kHeaderSize + const_index));
+  } else {
+    __ movzxbl(result, FieldOperand(string,
+                                    index,
+                                    times_1,
+                                    SeqAsciiString::kHeaderSize));
+  }
+  __ bind(&done);
+  __ bind(deferred->exit());
+}
+
+
+void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
+  Register string = ToRegister(instr->string());
+  Register result = ToRegister(instr->result());
+
+  // TODO(3095996): Get rid of this. For now, we need to make the
+  // result register contain a valid pointer because it is already
+  // contained in the register pointer map.
+  __ Set(result, 0);
+
+  __ PushSafepointRegisters();
+  __ push(string);
+  // Push the index as a smi. This is safe because of the checks in
+  // DoStringCharCodeAt above.
+  STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
+  if (instr->index()->IsConstantOperand()) {
+    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+    __ Push(Smi::FromInt(const_index));
+  } else {
+    Register index = ToRegister(instr->index());
+    __ Integer32ToSmi(index, index);
+    __ push(index);
+  }
+  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+  __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt);
+  RecordSafepointWithRegisters(
+      instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex);
+  if (FLAG_debug_code) {
+    __ AbortIfNotSmi(rax);
+  }
+  __ SmiToInteger32(rax, rax);
+  __ StoreToSafepointRegisterSlot(result, rax);
+  __ PopSafepointRegisters();
+}
+
+
+void LCodeGen::DoStringLength(LStringLength* instr) {
+  Register string = ToRegister(instr->string());
+  Register result = ToRegister(instr->result());
+  __ movq(result, FieldOperand(string, String::kLengthOffset));
 }
 
 
@@ -2130,7 +2963,11 @@
   ASSERT(input->IsRegister() || input->IsStackSlot());
   LOperand* output = instr->result();
   ASSERT(output->IsDoubleRegister());
-  __ cvtlsi2sd(ToDoubleRegister(output), ToOperand(input));
+  if (input->IsRegister()) {
+    __ cvtlsi2sd(ToDoubleRegister(output), ToRegister(input));
+  } else {
+    __ cvtlsi2sd(ToDoubleRegister(output), ToOperand(input));
+  }
 }
 
 
@@ -2233,7 +3070,7 @@
 
   // Smi to XMM conversion
   __ bind(&load_smi);
-  __ SmiToInteger32(kScratchRegister, input_reg);  // Untag smi first.
+  __ SmiToInteger32(kScratchRegister, input_reg);
   __ cvtlsi2sd(result_reg, kScratchRegister);
   __ bind(&done);
 }
@@ -2310,12 +3147,55 @@
 
 
 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
-  Abort("Unimplemented: %s", "DoNumberUntagD");
+  LOperand* input = instr->InputAt(0);
+  ASSERT(input->IsRegister());
+  LOperand* result = instr->result();
+  ASSERT(result->IsDoubleRegister());
+
+  Register input_reg = ToRegister(input);
+  XMMRegister result_reg = ToDoubleRegister(result);
+
+  EmitNumberUntagD(input_reg, result_reg, instr->environment());
 }
 
 
 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
-  Abort("Unimplemented: %s", "DoDoubleToI");
+  LOperand* input = instr->InputAt(0);
+  ASSERT(input->IsDoubleRegister());
+  LOperand* result = instr->result();
+  ASSERT(result->IsRegister());
+
+  XMMRegister input_reg = ToDoubleRegister(input);
+  Register result_reg = ToRegister(result);
+
+  if (instr->truncating()) {
+    // Performs a truncating conversion of a floating point number as used by
+    // the JS bitwise operations.
+    __ cvttsd2siq(result_reg, input_reg);
+    __ movq(kScratchRegister, V8_INT64_C(0x8000000000000000), RelocInfo::NONE);
+    __ cmpl(result_reg, kScratchRegister);
+      DeoptimizeIf(equal, instr->environment());
+  } else {
+    __ cvttsd2si(result_reg, input_reg);
+    __ cvtlsi2sd(xmm0, result_reg);
+    __ ucomisd(xmm0, input_reg);
+    DeoptimizeIf(not_equal, instr->environment());
+    DeoptimizeIf(parity_even, instr->environment());  // NaN.
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      NearLabel done;
+      // The integer converted back is equal to the original. We
+      // only have to test if we got -0 as an input.
+      __ testl(result_reg, result_reg);
+      __ j(not_zero, &done);
+      __ movmskpd(result_reg, input_reg);
+      // Bit 0 contains the sign of the double in input_reg.
+      // If input was positive, we are ok and return 0, otherwise
+      // deoptimize.
+      __ andl(result_reg, Immediate(1));
+      DeoptimizeIf(not_zero, instr->environment());
+      __ bind(&done);
+    }
+  }
 }
 
 
@@ -2464,7 +3344,54 @@
 
 
 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
-  Abort("Unimplemented: %s", "DoRegExpLiteral");
+  NearLabel materialized;
+  // Registers will be used as follows:
+  // rdi = JS function.
+  // rcx = literals array.
+  // rbx = regexp literal.
+  // rax = regexp literal clone.
+  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
+  __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
+  int literal_offset = FixedArray::kHeaderSize +
+      instr->hydrogen()->literal_index() * kPointerSize;
+  __ movq(rbx, FieldOperand(rcx, literal_offset));
+  __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
+  __ j(not_equal, &materialized);
+
+  // Create regexp literal using runtime function
+  // Result will be in rax.
+  __ push(rcx);
+  __ Push(Smi::FromInt(instr->hydrogen()->literal_index()));
+  __ Push(instr->hydrogen()->pattern());
+  __ Push(instr->hydrogen()->flags());
+  CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
+  __ movq(rbx, rax);
+
+  __ bind(&materialized);
+  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
+  Label allocated, runtime_allocate;
+  __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
+  __ jmp(&allocated);
+
+  __ bind(&runtime_allocate);
+  __ push(rbx);
+  __ Push(Smi::FromInt(size));
+  CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
+  __ pop(rbx);
+
+  __ bind(&allocated);
+  // Copy the content into the newly allocated memory.
+  // (Unroll copy loop once for better throughput).
+  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
+    __ movq(rdx, FieldOperand(rbx, i));
+    __ movq(rcx, FieldOperand(rbx, i + kPointerSize));
+    __ movq(FieldOperand(rax, i), rdx);
+    __ movq(FieldOperand(rax, i + kPointerSize), rcx);
+  }
+  if ((size % (2 * kPointerSize)) != 0) {
+    __ movq(rdx, FieldOperand(rbx, size - kPointerSize));
+    __ movq(FieldOperand(rax, size - kPointerSize), rdx);
+  }
 }
 
 
@@ -2487,12 +3414,134 @@
 
 
 void LCodeGen::DoTypeof(LTypeof* instr) {
-  Abort("Unimplemented: %s", "DoTypeof");
+  LOperand* input = instr->InputAt(0);
+  if (input->IsConstantOperand()) {
+    __ Push(ToHandle(LConstantOperand::cast(input)));
+  } else if (input->IsRegister()) {
+    __ push(ToRegister(input));
+  } else {
+    ASSERT(input->IsStackSlot());
+    __ push(ToOperand(input));
+  }
+  CallRuntime(Runtime::kTypeof, 1, instr);
 }
 
 
 void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
-  Abort("Unimplemented: %s", "DoTypeofIs");
+  Register input = ToRegister(instr->InputAt(0));
+  Register result = ToRegister(instr->result());
+  Label true_label;
+  Label false_label;
+  NearLabel done;
+
+  Condition final_branch_condition = EmitTypeofIs(&true_label,
+                                                  &false_label,
+                                                  input,
+                                                  instr->type_literal());
+  __ j(final_branch_condition, &true_label);
+  __ bind(&false_label);
+  __ LoadRoot(result, Heap::kFalseValueRootIndex);
+  __ jmp(&done);
+
+  __ bind(&true_label);
+  __ LoadRoot(result, Heap::kTrueValueRootIndex);
+
+  __ bind(&done);
+}
+
+
+void LCodeGen::EmitPushConstantOperand(LOperand* operand) {
+  ASSERT(operand->IsConstantOperand());
+  LConstantOperand* const_op = LConstantOperand::cast(operand);
+  Handle<Object> literal = chunk_->LookupLiteral(const_op);
+  Representation r = chunk_->LookupLiteralRepresentation(const_op);
+  if (r.IsInteger32()) {
+    ASSERT(literal->IsNumber());
+    __ push(Immediate(static_cast<int32_t>(literal->Number())));
+  } else if (r.IsDouble()) {
+    Abort("unsupported double immediate");
+  } else {
+    ASSERT(r.IsTagged());
+    __ Push(literal);
+  }
+}
+
+
+void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
+  Register input = ToRegister(instr->InputAt(0));
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+  Label* true_label = chunk_->GetAssemblyLabel(true_block);
+  Label* false_label = chunk_->GetAssemblyLabel(false_block);
+
+  Condition final_branch_condition = EmitTypeofIs(true_label,
+                                                  false_label,
+                                                  input,
+                                                  instr->type_literal());
+
+  EmitBranch(true_block, false_block, final_branch_condition);
+}
+
+
+Condition LCodeGen::EmitTypeofIs(Label* true_label,
+                                 Label* false_label,
+                                 Register input,
+                                 Handle<String> type_name) {
+  Condition final_branch_condition = no_condition;
+  if (type_name->Equals(Heap::number_symbol())) {
+    __ JumpIfSmi(input, true_label);
+    __ Cmp(FieldOperand(input, HeapObject::kMapOffset),
+           Factory::heap_number_map());
+    final_branch_condition = equal;
+
+  } else if (type_name->Equals(Heap::string_symbol())) {
+    __ JumpIfSmi(input, false_label);
+    __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
+    __ j(above_equal, false_label);
+    __ testb(FieldOperand(input, Map::kBitFieldOffset),
+             Immediate(1 << Map::kIsUndetectable));
+    final_branch_condition = zero;
+
+  } else if (type_name->Equals(Heap::boolean_symbol())) {
+    __ CompareRoot(input, Heap::kTrueValueRootIndex);
+    __ j(equal, true_label);
+    __ CompareRoot(input, Heap::kFalseValueRootIndex);
+    final_branch_condition = equal;
+
+  } else if (type_name->Equals(Heap::undefined_symbol())) {
+    __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
+    __ j(equal, true_label);
+    __ JumpIfSmi(input, false_label);
+    // Check for undetectable objects => true.
+    __ movq(input, FieldOperand(input, HeapObject::kMapOffset));
+    __ testb(FieldOperand(input, Map::kBitFieldOffset),
+             Immediate(1 << Map::kIsUndetectable));
+    final_branch_condition = not_zero;
+
+  } else if (type_name->Equals(Heap::function_symbol())) {
+    __ JumpIfSmi(input, false_label);
+    __ CmpObjectType(input, FIRST_FUNCTION_CLASS_TYPE, input);
+    final_branch_condition = above_equal;
+
+  } else if (type_name->Equals(Heap::object_symbol())) {
+    __ JumpIfSmi(input, false_label);
+    __ CompareRoot(input, Heap::kNullValueRootIndex);
+    __ j(equal, true_label);
+    __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, input);
+    __ j(below, false_label);
+    __ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE);
+    __ j(above_equal, false_label);
+    // Check for undetectable objects => false.
+    __ testb(FieldOperand(input, Map::kBitFieldOffset),
+             Immediate(1 << Map::kIsUndetectable));
+    final_branch_condition = zero;
+
+  } else {
+    final_branch_condition = never;
+    __ jmp(false_label);
+  }
+
+  return final_branch_condition;
 }
 
 
@@ -2544,86 +3593,6 @@
 }
 
 
-void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
-  Register input = ToRegister(instr->InputAt(0));
-  int true_block = chunk_->LookupDestination(instr->true_block_id());
-  int false_block = chunk_->LookupDestination(instr->false_block_id());
-  Label* true_label = chunk_->GetAssemblyLabel(true_block);
-  Label* false_label = chunk_->GetAssemblyLabel(false_block);
-
-  Condition final_branch_condition = EmitTypeofIs(true_label,
-                                                  false_label,
-                                                  input,
-                                                  instr->type_literal());
-
-  EmitBranch(true_block, false_block, final_branch_condition);
-}
-
-
-Condition LCodeGen::EmitTypeofIs(Label* true_label,
-                                 Label* false_label,
-                                 Register input,
-                                 Handle<String> type_name) {
-  Condition final_branch_condition = no_condition;
-  if (type_name->Equals(Heap::number_symbol())) {
-    __ JumpIfSmi(input, true_label);
-    __ Cmp(FieldOperand(input, HeapObject::kMapOffset),
-           Factory::heap_number_map());
-    final_branch_condition = equal;
-
-  } else if (type_name->Equals(Heap::string_symbol())) {
-    __ JumpIfSmi(input, false_label);
-    __ movq(input, FieldOperand(input, HeapObject::kMapOffset));
-    __ testb(FieldOperand(input, Map::kBitFieldOffset),
-             Immediate(1 << Map::kIsUndetectable));
-    __ j(not_zero, false_label);
-    __ CmpInstanceType(input, FIRST_NONSTRING_TYPE);
-    final_branch_condition = below;
-
-  } else if (type_name->Equals(Heap::boolean_symbol())) {
-    __ CompareRoot(input, Heap::kTrueValueRootIndex);
-    __ j(equal, true_label);
-    __ CompareRoot(input, Heap::kFalseValueRootIndex);
-    final_branch_condition = equal;
-
-  } else if (type_name->Equals(Heap::undefined_symbol())) {
-    __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
-    __ j(equal, true_label);
-    __ JumpIfSmi(input, false_label);
-    // Check for undetectable objects => true.
-    __ movq(input, FieldOperand(input, HeapObject::kMapOffset));
-    __ testb(FieldOperand(input, Map::kBitFieldOffset),
-             Immediate(1 << Map::kIsUndetectable));
-    final_branch_condition = not_zero;
-
-  } else if (type_name->Equals(Heap::function_symbol())) {
-    __ JumpIfSmi(input, false_label);
-    __ CmpObjectType(input, FIRST_FUNCTION_CLASS_TYPE, input);
-    final_branch_condition = above_equal;
-
-  } else if (type_name->Equals(Heap::object_symbol())) {
-    __ JumpIfSmi(input, false_label);
-    __ Cmp(input, Factory::null_value());
-    __ j(equal, true_label);
-    // Check for undetectable objects => false.
-    __ testb(FieldOperand(input, Map::kBitFieldOffset),
-             Immediate(1 << Map::kIsUndetectable));
-    __ j(not_zero, false_label);
-    // Check for JS objects that are not RegExp or Function => true.
-    __ CmpInstanceType(input, FIRST_JS_OBJECT_TYPE);
-    __ j(below, false_label);
-    __ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE);
-    final_branch_condition = below_equal;
-
-  } else {
-    final_branch_condition = never;
-    __ jmp(false_label);
-  }
-
-  return final_branch_condition;
-}
-
-
 void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
   // No code for lazy bailout instruction. Used to capture environment after a
   // call for populating the safepoint data with deoptimization data.
@@ -2636,7 +3605,36 @@
 
 
 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
-  Abort("Unimplemented: %s", "DoDeleteProperty");
+  LOperand* obj = instr->object();
+  LOperand* key = instr->key();
+  // Push object.
+  if (obj->IsRegister()) {
+    __ push(ToRegister(obj));
+  } else {
+    __ push(ToOperand(obj));
+  }
+  // Push key.
+  if (key->IsConstantOperand()) {
+    EmitPushConstantOperand(key);
+  } else if (key->IsRegister()) {
+    __ push(ToRegister(key));
+  } else {
+    __ push(ToOperand(key));
+  }
+  ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
+  LPointerMap* pointers = instr->pointer_map();
+  LEnvironment* env = instr->deoptimization_environment();
+  RecordPosition(pointers->position());
+  RegisterEnvironmentForDeoptimization(env);
+  // Create safepoint generator that will also ensure enough space in the
+  // reloc info for patching in deoptimization (since this is invoking a
+  // builtin)
+  SafepointGenerator safepoint_generator(this,
+                                         pointers,
+                                         env->deoptimization_index(),
+                                         true);
+  __ Push(Smi::FromInt(strict_mode_flag()));
+  __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, &safepoint_generator);
 }
 
 
@@ -2653,7 +3651,19 @@
 
 
 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
-  Abort("Unimplemented: %s", "DoOsrEntry");
+  // This is a pseudo-instruction that ensures that the environment here is
+  // properly registered for deoptimization and records the assembler's PC
+  // offset.
+  LEnvironment* environment = instr->environment();
+  environment->SetSpilledRegisters(instr->SpilledRegisterArray(),
+                                   instr->SpilledDoubleRegisterArray());
+
+  // If the environment were already registered, we would have no way of
+  // backpatching it with the spill slot operands.
+  ASSERT(!environment->HasBeenRegistered());
+  RegisterEnvironmentForDeoptimization(environment);
+  ASSERT(osr_pc_offset_ == -1);
+  osr_pc_offset_ = masm()->pc_offset();
 }
 
 #undef __
diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h
index 6f8f06e..ab0dffb 100644
--- a/src/x64/lithium-codegen-x64.h
+++ b/src/x64/lithium-codegen-x64.h
@@ -53,9 +53,10 @@
         current_instruction_(-1),
         instructions_(chunk->instructions()),
         deoptimizations_(4),
+        jump_table_(4),
         deoptimization_literals_(8),
         inlined_function_count_(0),
-        scope_(chunk->graph()->info()->scope()),
+        scope_(info->scope()),
         status_(UNUSED),
         deferred_(8),
         osr_pc_offset_(-1),
@@ -65,6 +66,7 @@
 
   // Simple accessors.
   MacroAssembler* masm() const { return masm_; }
+  CompilationInfo* info() const { return info_; }
 
   // Support for converting LOperands to assembler types.
   Register ToRegister(LOperand* op) const;
@@ -90,8 +92,8 @@
   void DoDeferredTaggedToI(LTaggedToI* instr);
   void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
   void DoDeferredStackCheck(LGoto* instr);
-  void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
-                                        Label* map_check);
+  void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
+  void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr);
 
   // Parallel move support.
   void DoParallelMove(LParallelMove* move);
@@ -117,6 +119,10 @@
   bool is_done() const { return status_ == DONE; }
   bool is_aborted() const { return status_ == ABORTED; }
 
+  int strict_mode_flag() const {
+    return info()->is_strict() ? kStrictMode : kNonStrictMode;
+  }
+
   LChunk* chunk() const { return chunk_; }
   Scope* scope() const { return scope_; }
   HGraph* graph() const { return chunk_->graph(); }
@@ -143,6 +149,7 @@
   bool GeneratePrologue();
   bool GenerateBody();
   bool GenerateDeferredCode();
+  bool GenerateJumpTable();
   bool GenerateSafepointTable();
 
   void CallCode(Handle<Code> code,
@@ -182,6 +189,7 @@
   XMMRegister ToDoubleRegister(int index) const;
 
   // Specific math operations - used from DoUnaryMathOperation.
+  void EmitIntegerMathAbs(LUnaryMathOperation* instr);
   void DoMathAbs(LUnaryMathOperation* instr);
   void DoMathFloor(LUnaryMathOperation* instr);
   void DoMathRound(LUnaryMathOperation* instr);
@@ -197,6 +205,7 @@
                        int arguments,
                        int deoptimization_index);
   void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
+  void RecordSafepoint(int deoptimization_index);
   void RecordSafepointWithRegisters(LPointerMap* pointers,
                                     int arguments,
                                     int deoptimization_index);
@@ -225,6 +234,17 @@
   // Caller should branch on equal condition.
   void EmitIsConstructCall(Register temp);
 
+  // Emits code for pushing a constant operand.
+  void EmitPushConstantOperand(LOperand* operand);
+
+  struct JumpTableEntry {
+    inline JumpTableEntry(Address address)
+        : label_(),
+          address_(address) { }
+    Label label_;
+    Address address_;
+  };
+
   LChunk* const chunk_;
   MacroAssembler* const masm_;
   CompilationInfo* const info_;
@@ -233,6 +253,7 @@
   int current_instruction_;
   const ZoneList<LInstruction*>* instructions_;
   ZoneList<LEnvironment*> deoptimizations_;
+  ZoneList<JumpTableEntry*> jump_table_;
   ZoneList<Handle<Object> > deoptimization_literals_;
   int inlined_function_count_;
   Scope* const scope_;
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index a6afbf7..bf4d5a1 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -296,8 +296,15 @@
 }
 
 
+void LStoreContextSlot::PrintDataTo(StringStream* stream) {
+  InputAt(0)->PrintTo(stream);
+  stream->Add("[%d] <- ", slot_index());
+  InputAt(1)->PrintTo(stream);
+}
+
+
 void LCallKeyed::PrintDataTo(StringStream* stream) {
-  stream->Add("[ecx] #%d / ", arity());
+  stream->Add("[rcx] #%d / ", arity());
 }
 
 
@@ -398,7 +405,7 @@
 }
 
 
-void LStoreNamed::PrintDataTo(StringStream* stream) {
+void LStoreNamedField::PrintDataTo(StringStream* stream) {
   object()->PrintTo(stream);
   stream->Add(".");
   stream->Add(*String::cast(*name())->ToCString());
@@ -407,7 +414,25 @@
 }
 
 
-void LStoreKeyed::PrintDataTo(StringStream* stream) {
+void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
+  object()->PrintTo(stream);
+  stream->Add(".");
+  stream->Add(*String::cast(*name())->ToCString());
+  stream->Add(" <- ");
+  value()->PrintTo(stream);
+}
+
+
+void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
+  object()->PrintTo(stream);
+  stream->Add("[");
+  key()->PrintTo(stream);
+  stream->Add("] <- ");
+  value()->PrintTo(stream);
+}
+
+
+void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
   object()->PrintTo(stream);
   stream->Add("[");
   key()->PrintTo(stream);
@@ -445,7 +470,7 @@
   // shift all parameter indexes down by the number of parameters, and
   // make sure they end up negative so they are distinguishable from
   // spill slots.
-  int result = index - graph()->info()->scope()->num_parameters() - 1;
+  int result = index - info()->scope()->num_parameters() - 1;
   ASSERT(result < 0);
   return result;
 }
@@ -453,7 +478,7 @@
 // A parameter relative to ebp in the arguments stub.
 int LChunk::ParameterAt(int index) {
   ASSERT(-1 <= index);  // -1 is the receiver.
-  return (1 + graph()->info()->scope()->num_parameters() - index) *
+  return (1 + info()->scope()->num_parameters() - index) *
       kPointerSize;
 }
 
@@ -492,7 +517,7 @@
 
 LChunk* LChunkBuilder::Build() {
   ASSERT(is_unused());
-  chunk_ = new LChunk(graph());
+  chunk_ = new LChunk(info(), graph());
   HPhase phase("Building chunk", chunk_);
   status_ = BUILDING;
   const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
@@ -509,8 +534,8 @@
 
 void LChunkBuilder::Abort(const char* format, ...) {
   if (FLAG_trace_bailout) {
-    SmartPointer<char> debug_name = graph()->debug_name()->ToCString();
-    PrintF("Aborting LChunk building in @\"%s\": ", *debug_name);
+    SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
+    PrintF("Aborting LChunk building in @\"%s\": ", *name);
     va_list arguments;
     va_start(arguments, format);
     OS::VPrint(format, arguments);
@@ -843,8 +868,14 @@
 
 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
                                            HArithmeticBinaryOperation* instr) {
-  Abort("Unimplemented: %s", "DoArithmeticD");
-  return NULL;
+  ASSERT(instr->representation().IsDouble());
+  ASSERT(instr->left()->representation().IsDouble());
+  ASSERT(instr->right()->representation().IsDouble());
+  ASSERT(op != Token::MOD);
+  LOperand* left = UseRegisterAtStart(instr->left());
+  LOperand* right = UseRegisterAtStart(instr->right());
+  LArithmeticD* result = new LArithmeticD(op, left, right);
+  return DefineSameAsFirst(result);
 }
 
 
@@ -1073,9 +1104,8 @@
     } else if (v->IsInstanceOf()) {
       HInstanceOf* instance_of = HInstanceOf::cast(v);
       LInstanceOfAndBranch* result =
-          new LInstanceOfAndBranch(
-              UseFixed(instance_of->left(), InstanceofStub::left()),
-              UseFixed(instance_of->right(), InstanceofStub::right()));
+          new LInstanceOfAndBranch(UseFixed(instance_of->left(), rax),
+                                   UseFixed(instance_of->right(), rdx));
       return MarkAsCall(result, instr);
     } else if (v->IsTypeofIs()) {
       HTypeofIs* typeof_is = HTypeofIs::cast(v);
@@ -1106,33 +1136,41 @@
 
 
 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
-  Abort("Unimplemented: %s", "DoArgumentsLength");
-  return NULL;
+  return DefineAsRegister(new LArgumentsLength(Use(length->value())));
 }
 
 
 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
-  Abort("Unimplemented: %s", "DoArgumentsElements");
-  return NULL;
+  return DefineAsRegister(new LArgumentsElements);
 }
 
 
 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
-  Abort("Unimplemented: %s", "DoInstanceOf");
-  return NULL;
+  LOperand* left = UseFixed(instr->left(), rax);
+  LOperand* right = UseFixed(instr->right(), rdx);
+  LInstanceOf* result = new LInstanceOf(left, right);
+  return MarkAsCall(DefineFixed(result, rax), instr);
 }
 
 
 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
     HInstanceOfKnownGlobal* instr) {
-  Abort("Unimplemented: %s", "DoInstanceOfKnownGlobal");
-  return NULL;
+  LInstanceOfKnownGlobal* result =
+      new LInstanceOfKnownGlobal(UseFixed(instr->value(), rax));
+  return MarkAsCall(DefineFixed(result, rax), instr);
 }
 
 
 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
-  Abort("Unimplemented: %s", "DoApplyArguments");
-  return NULL;
+  LOperand* function = UseFixed(instr->function(), rdi);
+  LOperand* receiver = UseFixed(instr->receiver(), rax);
+  LOperand* length = UseFixed(instr->length(), rbx);
+  LOperand* elements = UseFixed(instr->elements(), rcx);
+  LApplyArguments* result = new LApplyArguments(function,
+                                                receiver,
+                                                length,
+                                                elements);
+  return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
 }
 
 
@@ -1149,8 +1187,8 @@
 
 
 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
-  Abort("Unimplemented: DoOuterContext");
-  return NULL;
+  LOperand* context = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new LOuterContext(context));
 }
 
 
@@ -1172,14 +1210,39 @@
 
 
 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
-  Abort("Unimplemented: %s", "DoUnaryMathOperation");
-  return NULL;
+  BuiltinFunctionId op = instr->op();
+  if (op == kMathLog || op == kMathSin || op == kMathCos) {
+    LOperand* input = UseFixedDouble(instr->value(), xmm1);
+    LUnaryMathOperation* result = new LUnaryMathOperation(input);
+    return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
+  } else {
+    LOperand* input = UseRegisterAtStart(instr->value());
+    LUnaryMathOperation* result = new LUnaryMathOperation(input);
+    switch (op) {
+      case kMathAbs:
+        return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
+      case kMathFloor:
+        return AssignEnvironment(DefineAsRegister(result));
+      case kMathRound:
+        return AssignEnvironment(DefineAsRegister(result));
+      case kMathSqrt:
+        return DefineSameAsFirst(result);
+      case kMathPowHalf:
+        return DefineSameAsFirst(result);
+      default:
+        UNREACHABLE();
+        return NULL;
+    }
+  }
 }
 
 
 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
-  Abort("Unimplemented: %s", "DoCallKeyed");
-  return NULL;
+  ASSERT(instr->key()->representation().IsTagged());
+  LOperand* key = UseFixed(instr->key(), rcx);
+  argument_count_ -= instr->argument_count();
+  LCallKeyed* result = new LCallKeyed(key);
+  return MarkAsCall(DefineFixed(result, rax), instr);
 }
 
 
@@ -1210,8 +1273,9 @@
 
 
 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
-  Abort("Unimplemented: %s", "DoCallFunction");
-  return NULL;
+  argument_count_ -= instr->argument_count();
+  LCallFunction* result = new LCallFunction();
+  return MarkAsCall(DefineFixed(result, rax), instr);
 }
 
 
@@ -1279,8 +1343,32 @@
 
 
 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
-  Abort("Unimplemented: %s", "DoMod");
-  return NULL;
+  if (instr->representation().IsInteger32()) {
+    ASSERT(instr->left()->representation().IsInteger32());
+    ASSERT(instr->right()->representation().IsInteger32());
+    // The temporary operand is necessary to ensure that right is not allocated
+    // into edx.
+    LOperand* temp = FixedTemp(rdx);
+    LOperand* value = UseFixed(instr->left(), rax);
+    LOperand* divisor = UseRegister(instr->right());
+    LModI* mod = new LModI(value, divisor, temp);
+    LInstruction* result = DefineFixed(mod, rdx);
+    return (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
+            instr->CheckFlag(HValue::kCanBeDivByZero))
+        ? AssignEnvironment(result)
+        : result;
+  } else if (instr->representation().IsTagged()) {
+    return DoArithmeticT(Token::MOD, instr);
+  } else {
+    ASSERT(instr->representation().IsDouble());
+    // We call a C function for double modulo. It can't trigger a GC.
+    // We need to use fixed result register for the call.
+    // TODO(fschneider): Allow any register as input registers.
+    LOperand* left = UseFixedDouble(instr->left(), xmm2);
+    LOperand* right = UseFixedDouble(instr->right(), xmm1);
+    LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
+    return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
+  }
 }
 
 
@@ -1335,7 +1423,7 @@
     }
     return result;
   } else if (instr->representation().IsDouble()) {
-    Abort("Unimplemented: %s", "DoAdd on Doubles");
+    return DoArithmeticD(Token::ADD, instr);
   } else {
     ASSERT(instr->representation().IsTagged());
     return DoArithmeticT(Token::ADD, instr);
@@ -1345,8 +1433,22 @@
 
 
 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
-  Abort("Unimplemented: %s", "DoPower");
-  return NULL;
+  ASSERT(instr->representation().IsDouble());
+  // We call a C function for double power. It can't trigger a GC.
+  // We need to use fixed result register for the call.
+  Representation exponent_type = instr->right()->representation();
+  ASSERT(instr->left()->representation().IsDouble());
+  LOperand* left = UseFixedDouble(instr->left(), xmm2);
+  LOperand* right = exponent_type.IsDouble() ?
+      UseFixedDouble(instr->right(), xmm1) :
+#ifdef _WIN64
+      UseFixed(instr->right(), rdx);
+#else
+      UseFixed(instr->right(), rdi);
+#endif
+  LPower* result = new LPower(left, right);
+  return MarkAsCall(DefineFixedDouble(result, xmm1), instr,
+                    CAN_DEOPTIMIZE_EAGERLY);
 }
 
 
@@ -1411,15 +1513,27 @@
 
 
 LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) {
-  Abort("Unimplemented: %s", "DoHasInstanceType");
-  return NULL;
+  ASSERT(instr->value()->representation().IsTagged());
+  LOperand* value = UseRegisterAtStart(instr->value());
+
+  return DefineAsRegister(new LHasInstanceType(value));
+}
+
+
+LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
+    HGetCachedArrayIndex* instr)  {
+  ASSERT(instr->value()->representation().IsTagged());
+  LOperand* value = UseRegisterAtStart(instr->value());
+
+  return DefineAsRegister(new LGetCachedArrayIndex(value));
 }
 
 
 LInstruction* LChunkBuilder::DoHasCachedArrayIndex(
     HHasCachedArrayIndex* instr) {
-  Abort("Unimplemented: %s", "DoHasCachedArrayIndex");
-  return NULL;
+  ASSERT(instr->value()->representation().IsTagged());
+  LOperand* value = UseRegister(instr->value());
+  return DefineAsRegister(new LHasCachedArrayIndex(value));
 }
 
 
@@ -1448,8 +1562,9 @@
 
 
 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
-  Abort("Unimplemented: %s", "DoValueOf");
-  return NULL;
+  LOperand* object = UseRegister(instr->value());
+  LValueOf* result = new LValueOf(object);
+  return AssignEnvironment(DefineSameAsFirst(result));
 }
 
 
@@ -1506,12 +1621,8 @@
       return AssignPointerMap(Define(result, result_temp));
     } else {
       ASSERT(to.IsInteger32());
-      bool needs_temp = instr->CanTruncateToInt32() &&
-          !CpuFeatures::IsSupported(SSE3);
-      LOperand* value = needs_temp ?
-          UseTempRegister(instr->value()) : UseRegister(instr->value());
-      LOperand* temp = needs_temp ? TempRegister() : NULL;
-      return AssignEnvironment(DefineAsRegister(new LDoubleToI(value, temp)));
+      LOperand* value = UseRegister(instr->value());
+      return AssignEnvironment(DefineAsRegister(new LDoubleToI(value)));
     }
   } else if (from.IsInteger32()) {
     if (to.IsTagged()) {
@@ -1609,14 +1720,25 @@
 
 
 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
-  Abort("Unimplemented: %s", "DoLoadContextSlot");
-  return NULL;
+  LOperand* context = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new LLoadContextSlot(context));
 }
 
 
 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
-  Abort("Unimplemented: DoStoreContextSlot");
-  return NULL;
+  LOperand* context;
+  LOperand* value;
+  LOperand* temp;
+  if (instr->NeedsWriteBarrier()) {
+    context = UseTempRegister(instr->context());
+    value = UseTempRegister(instr->value());
+    temp = TempRegister();
+  } else {
+    context = UseRegister(instr->context());
+    value = UseRegister(instr->value());
+    temp = NULL;
+  }
+  return new LStoreContextSlot(context, value, temp);
 }
 
 
@@ -1679,8 +1801,11 @@
 
 
 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
-  Abort("Unimplemented: %s", "DoLoadKeyedGeneric");
-  return NULL;
+  LOperand* object = UseFixed(instr->object(), rdx);
+  LOperand* key = UseFixed(instr->key(), rax);
+
+  LLoadKeyedGeneric* result = new LLoadKeyedGeneric(object, key);
+  return MarkAsCall(DefineFixed(result, rax), instr);
 }
 
 
@@ -1703,9 +1828,31 @@
 }
 
 
+LInstruction* LChunkBuilder::DoStorePixelArrayElement(
+    HStorePixelArrayElement* instr) {
+  ASSERT(instr->value()->representation().IsInteger32());
+  ASSERT(instr->external_pointer()->representation().IsExternal());
+  ASSERT(instr->key()->representation().IsInteger32());
+
+  LOperand* external_pointer = UseRegister(instr->external_pointer());
+  LOperand* val = UseTempRegister(instr->value());
+  LOperand* key = UseRegister(instr->key());
+
+  return new LStorePixelArrayElement(external_pointer, key, val);
+}
+
+
 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
-  Abort("Unimplemented: %s", "DoStoreKeyedGeneric");
-  return NULL;
+  LOperand* object = UseFixed(instr->object(), rdx);
+  LOperand* key = UseFixed(instr->key(), rcx);
+  LOperand* value = UseFixed(instr->value(), rax);
+
+  ASSERT(instr->object()->representation().IsTagged());
+  ASSERT(instr->key()->representation().IsTagged());
+  ASSERT(instr->value()->representation().IsTagged());
+
+  LStoreKeyedGeneric* result = new LStoreKeyedGeneric(object, key, value);
+  return MarkAsCall(result, instr);
 }
 
 
@@ -1730,20 +1877,25 @@
 
 
 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
-  Abort("Unimplemented: %s", "DoStoreNamedGeneric");
-  return NULL;
+  LOperand* object = UseFixed(instr->object(), rdx);
+  LOperand* value = UseFixed(instr->value(), rax);
+
+  LStoreNamedGeneric* result = new LStoreNamedGeneric(object, value);
+  return MarkAsCall(result, instr);
 }
 
 
 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
-  Abort("Unimplemented: %s", "DoStringCharCodeAt");
-  return NULL;
+  LOperand* string = UseRegister(instr->string());
+  LOperand* index = UseRegisterOrConstant(instr->index());
+  LStringCharCodeAt* result = new LStringCharCodeAt(string, index);
+  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
 }
 
 
 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
-  Abort("Unimplemented: %s", "DoStringLength");
-  return NULL;
+  LOperand* string = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new LStringLength(string));
 }
 
 
@@ -1758,8 +1910,7 @@
 
 
 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
-  Abort("Unimplemented: %s", "DoRegExpLiteral");
-  return NULL;
+  return MarkAsCall(DefineFixed(new LRegExpLiteral, rax), instr);
 }
 
 
@@ -1769,14 +1920,16 @@
 
 
 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
-  Abort("Unimplemented: %s", "DoDeleteProperty");
-  return NULL;
+  LDeleteProperty* result =
+      new LDeleteProperty(Use(instr->object()), UseOrConstant(instr->key()));
+  return MarkAsCall(DefineFixed(result, rax), instr);
 }
 
 
 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
-  Abort("Unimplemented: %s", "DoOsrEntry");
-  return NULL;
+  allocator_->MarkAsOsrEntry();
+  current_block_->last_environment()->set_ast_id(instr->ast_id());
+  return AssignEnvironment(new LOsrEntry);
 }
 
 
@@ -1787,8 +1940,8 @@
 
 
 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
-  Abort("Unimplemented: %s", "DoUnknownOSRValue");
-  return NULL;
+  int spill_index = chunk()->GetNextSpillIndex(false);  // Not double-width.
+  return DefineAsSpilled(new LUnknownOSRValue, spill_index);
 }
 
 
@@ -1799,26 +1952,31 @@
 
 
 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
-  Abort("Unimplemented: %s", "DoArgumentsObject");
+  // There are no real uses of the arguments object.
+  // arguments.length and element access are supported directly on
+  // stack arguments, and any real arguments object use causes a bailout.
+  // So this value is never used.
   return NULL;
 }
 
 
 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
-  Abort("Unimplemented: %s", "DoAccessArgumentsAt");
-  return NULL;
+  LOperand* arguments = UseRegister(instr->arguments());
+  LOperand* length = UseTempRegister(instr->length());
+  LOperand* index = Use(instr->index());
+  LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index);
+  return AssignEnvironment(DefineAsRegister(result));
 }
 
 
 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
-  Abort("Unimplemented: %s", "DoTypeof");
-  return NULL;
+  LTypeof* result = new LTypeof(UseAtStart(instr->value()));
+  return MarkAsCall(DefineFixed(result, rax), instr);
 }
 
 
 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) {
-  Abort("Unimplemented: %s", "DoTypeofIs");
-  return NULL;
+  return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value())));
 }
 
 
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index 0cb5cc7..67ec7af 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -42,8 +42,6 @@
 #define LITHIUM_ALL_INSTRUCTION_LIST(V)         \
   V(ControlInstruction)                         \
   V(Call)                                       \
-  V(StoreKeyed)                                 \
-  V(StoreNamed)                                 \
   LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
 
 
@@ -91,6 +89,7 @@
   V(DoubleToI)                                  \
   V(FunctionLiteral)                            \
   V(Gap)                                        \
+  V(GetCachedArrayIndex)                        \
   V(GlobalObject)                               \
   V(GlobalReceiver)                             \
   V(Goto)                                       \
@@ -131,6 +130,7 @@
   V(NumberUntagD)                               \
   V(ObjectLiteral)                              \
   V(OsrEntry)                                   \
+  V(OuterContext)                               \
   V(Parameter)                                  \
   V(PixelArrayLength)                           \
   V(Power)                                      \
@@ -141,11 +141,15 @@
   V(SmiTag)                                     \
   V(SmiUntag)                                   \
   V(StackCheck)                                 \
+  V(StoreContextSlot)                           \
   V(StoreGlobal)                                \
   V(StoreKeyedFastElement)                      \
   V(StoreKeyedGeneric)                          \
   V(StoreNamedField)                            \
   V(StoreNamedGeneric)                          \
+  V(StorePixelArrayElement)                     \
+  V(StringCharCodeAt)                           \
+  V(StringLength)                               \
   V(SubI)                                       \
   V(TaggedToI)                                  \
   V(Throw)                                      \
@@ -727,6 +731,17 @@
 };
 
 
+class LGetCachedArrayIndex: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LGetCachedArrayIndex(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index")
+  DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex)
+};
+
+
 class LHasCachedArrayIndex: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LHasCachedArrayIndex(LOperand* value) {
@@ -829,11 +844,10 @@
 };
 
 
-class LInstanceOfKnownGlobal: public LTemplateInstruction<1, 1, 1> {
+class LInstanceOfKnownGlobal: public LTemplateInstruction<1, 1, 0> {
  public:
-  LInstanceOfKnownGlobal(LOperand* value, LOperand* temp) {
+  explicit LInstanceOfKnownGlobal(LOperand* value) {
     inputs_[0] = value;
-    temps_[0] = temp;
   }
 
   DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
@@ -1004,11 +1018,10 @@
 };
 
 
-class LValueOf: public LTemplateInstruction<1, 1, 1> {
+class LValueOf: public LTemplateInstruction<1, 1, 0> {
  public:
-  LValueOf(LOperand* value, LOperand* temp) {
+  explicit LValueOf(LOperand* value) {
     inputs_[0] = value;
-    temps_[0] = temp;
   }
 
   DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value-of")
@@ -1245,6 +1258,26 @@
 };
 
 
+class LStoreContextSlot: public LTemplateInstruction<0, 2, 1> {
+ public:
+  LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) {
+    inputs_[0] = context;
+    inputs_[1] = value;
+    temps_[0] = temp;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
+  DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot)
+
+  LOperand* context() { return InputAt(0); }
+  LOperand* value() { return InputAt(1); }
+  int slot_index() { return hydrogen()->slot_index(); }
+  int needs_write_barrier() { return hydrogen()->NeedsWriteBarrier(); }
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
 class LPushArgument: public LTemplateInstruction<0, 1, 0> {
  public:
   explicit LPushArgument(LOperand* value) {
@@ -1261,6 +1294,18 @@
 };
 
 
+class LOuterContext: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LOuterContext(LOperand* context) {
+    inputs_[0] = context;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer-context")
+
+  LOperand* context() { return InputAt(0); }
+};
+
+
 class LGlobalObject: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
@@ -1294,6 +1339,8 @@
   DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call-keyed")
   DECLARE_HYDROGEN_ACCESSOR(CallKeyed)
 
+  LOperand* key() { return inputs_[0]; }
+
   virtual void PrintDataTo(StringStream* stream);
 
   int arity() const { return hydrogen()->argument_count() - 1; }
@@ -1314,6 +1361,8 @@
 
 class LCallFunction: public LTemplateInstruction<1, 0, 0> {
  public:
+  LCallFunction() {}
+
   DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function")
   DECLARE_HYDROGEN_ACCESSOR(CallFunction)
 
@@ -1402,11 +1451,10 @@
 
 
 // Sometimes truncating conversion from a tagged value to an int32.
-class LDoubleToI: public LTemplateInstruction<1, 1, 1> {
+class LDoubleToI: public LTemplateInstruction<1, 1, 0> {
  public:
-  LDoubleToI(LOperand* value, LOperand* temp) {
+  explicit LDoubleToI(LOperand* value) {
     inputs_[0] = value;
-    temps_[0] = temp;
   }
 
   DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i")
@@ -1467,15 +1515,39 @@
 };
 
 
-class LStoreNamed: public LTemplateInstruction<0, 2, 1> {
+class LStoreNamedField: public LTemplateInstruction<0, 2, 1> {
  public:
-  LStoreNamed(LOperand* obj, LOperand* val) {
-    inputs_[0] = obj;
-    inputs_[1] = val;
+  LStoreNamedField(LOperand* object, LOperand* value, LOperand* temp) {
+    inputs_[0] = object;
+    inputs_[1] = value;
+    temps_[0] = temp;
   }
 
-  DECLARE_INSTRUCTION(StoreNamed)
-  DECLARE_HYDROGEN_ACCESSOR(StoreNamed)
+  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
+  DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  LOperand* object() { return inputs_[0]; }
+  LOperand* value() { return inputs_[1]; }
+
+  Handle<Object> name() const { return hydrogen()->name(); }
+  bool is_in_object() { return hydrogen()->is_in_object(); }
+  int offset() { return hydrogen()->offset(); }
+  bool needs_write_barrier() { return hydrogen()->NeedsWriteBarrier(); }
+  Handle<Map> transition() const { return hydrogen()->transition(); }
+};
+
+
+class LStoreNamedGeneric: public LTemplateInstruction<0, 2, 0> {
+ public:
+  LStoreNamedGeneric(LOperand* object, LOperand* value) {
+    inputs_[0] = object;
+    inputs_[1] = value;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
+  DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
 
   virtual void PrintDataTo(StringStream* stream);
 
@@ -1485,42 +1557,17 @@
 };
 
 
-class LStoreNamedField: public LStoreNamed {
+class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
  public:
-  LStoreNamedField(LOperand* obj, LOperand* val, LOperand* temp)
-      : LStoreNamed(obj, val) {
-    temps_[0] = temp;
-  }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
-  DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
-
-  bool is_in_object() { return hydrogen()->is_in_object(); }
-  int offset() { return hydrogen()->offset(); }
-  bool needs_write_barrier() { return hydrogen()->NeedsWriteBarrier(); }
-  Handle<Map> transition() const { return hydrogen()->transition(); }
-};
-
-
-class LStoreNamedGeneric: public LStoreNamed {
- public:
-  LStoreNamedGeneric(LOperand* obj, LOperand* val)
-      : LStoreNamed(obj, val) { }
-
-  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
-  DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
-};
-
-
-class LStoreKeyed: public LTemplateInstruction<0, 3, 0> {
- public:
-  LStoreKeyed(LOperand* obj, LOperand* key, LOperand* val) {
+  LStoreKeyedFastElement(LOperand* obj, LOperand* key, LOperand* val) {
     inputs_[0] = obj;
     inputs_[1] = key;
     inputs_[2] = val;
   }
 
-  DECLARE_INSTRUCTION(StoreKeyed)
+  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
+                               "store-keyed-fast-element")
+  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastElement)
 
   virtual void PrintDataTo(StringStream* stream);
 
@@ -1530,23 +1577,69 @@
 };
 
 
-class LStoreKeyedFastElement: public LStoreKeyed {
+class LStorePixelArrayElement: public LTemplateInstruction<0, 3, 0> {
  public:
-  LStoreKeyedFastElement(LOperand* obj, LOperand* key, LOperand* val)
-      : LStoreKeyed(obj, key, val) {}
+  LStorePixelArrayElement(LOperand* external_pointer,
+                          LOperand* key,
+                          LOperand* val) {
+    inputs_[0] = external_pointer;
+    inputs_[1] = key;
+    inputs_[2] = val;
+  }
 
-  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
-                               "store-keyed-fast-element")
-  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastElement)
+  DECLARE_CONCRETE_INSTRUCTION(StorePixelArrayElement,
+                               "store-pixel-array-element")
+  DECLARE_HYDROGEN_ACCESSOR(StorePixelArrayElement)
+
+  LOperand* external_pointer() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
+  LOperand* value() { return inputs_[2]; }
 };
 
 
-class LStoreKeyedGeneric: public LStoreKeyed {
+class LStoreKeyedGeneric: public LTemplateInstruction<0, 3, 0> {
  public:
-  LStoreKeyedGeneric(LOperand* obj, LOperand* key, LOperand* val)
-      : LStoreKeyed(obj, key, val) { }
+  LStoreKeyedGeneric(LOperand* object, LOperand* key, LOperand* value) {
+    inputs_[0] = object;
+    inputs_[1] = key;
+    inputs_[2] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  LOperand* object() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
+  LOperand* value() { return inputs_[2]; }
+};
+
+
+class LStringCharCodeAt: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LStringCharCodeAt(LOperand* string, LOperand* index) {
+    inputs_[0] = string;
+    inputs_[1] = index;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at")
+  DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt)
+
+  LOperand* string() { return inputs_[0]; }
+  LOperand* index() { return inputs_[1]; }
+};
+
+
+class LStringLength: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LStringLength(LOperand* string) {
+    inputs_[0] = string;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(StringLength, "string-length")
+  DECLARE_HYDROGEN_ACCESSOR(StringLength)
+
+  LOperand* string() { return inputs_[0]; }
 };
 
 
@@ -1750,8 +1843,9 @@
 class LChunkBuilder;
 class LChunk: public ZoneObject {
  public:
-  explicit LChunk(HGraph* graph)
+  explicit LChunk(CompilationInfo* info, HGraph* graph)
     : spill_slot_count_(0),
+      info_(info),
       graph_(graph),
       instructions_(32),
       pointer_maps_(8),
@@ -1768,6 +1862,7 @@
   int ParameterAt(int index);
   int GetParameterStackSlot(int index) const;
   int spill_slot_count() const { return spill_slot_count_; }
+  CompilationInfo* info() const { return info_; }
   HGraph* graph() const { return graph_; }
   const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
   void AddGapMove(int index, LOperand* from, LOperand* to);
@@ -1804,6 +1899,7 @@
 
  private:
   int spill_slot_count_;
+  CompilationInfo* info_;
   HGraph* const graph_;
   ZoneList<LInstruction*> instructions_;
   ZoneList<LPointerMap*> pointer_maps_;
@@ -1813,8 +1909,9 @@
 
 class LChunkBuilder BASE_EMBEDDED {
  public:
-  LChunkBuilder(HGraph* graph, LAllocator* allocator)
+  LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator)
       : chunk_(NULL),
+        info_(info),
         graph_(graph),
         status_(UNUSED),
         current_instruction_(NULL),
@@ -1843,6 +1940,7 @@
   };
 
   LChunk* chunk() const { return chunk_; }
+  CompilationInfo* info() const { return info_; }
   HGraph* graph() const { return graph_; }
 
   bool is_unused() const { return status_ == UNUSED; }
@@ -1949,6 +2047,7 @@
                               HArithmeticBinaryOperation* instr);
 
   LChunk* chunk_;
+  CompilationInfo* info_;
   HGraph* const graph_;
   Status status_;
   HInstruction* current_instruction_;
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 56a2d6f..b468e82 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -49,22 +49,35 @@
 
 
 void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
-  movq(destination, Operand(kRootRegister, index << kPointerSizeLog2));
+  movq(destination, Operand(kRootRegister,
+                            (index << kPointerSizeLog2) - kRootRegisterBias));
+}
+
+
+void MacroAssembler::LoadRootIndexed(Register destination,
+                                     Register variable_offset,
+                                     int fixed_offset) {
+  movq(destination,
+       Operand(kRootRegister,
+               variable_offset, times_pointer_size,
+               (fixed_offset << kPointerSizeLog2) - kRootRegisterBias));
 }
 
 
 void MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) {
-  movq(Operand(kRootRegister, index << kPointerSizeLog2), source);
+  movq(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias),
+       source);
 }
 
 
 void MacroAssembler::PushRoot(Heap::RootListIndex index) {
-  push(Operand(kRootRegister, index << kPointerSizeLog2));
+  push(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias));
 }
 
 
 void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
-  cmpq(with, Operand(kRootRegister, index << kPointerSizeLog2));
+  cmpq(with, Operand(kRootRegister,
+                     (index << kPointerSizeLog2) - kRootRegisterBias));
 }
 
 
@@ -136,7 +149,7 @@
                                  Register value) {
   // The compiled code assumes that record write doesn't change the
   // context register, so we check that none of the clobbered
-  // registers are esi.
+  // registers are rsi.
   ASSERT(!object.is(rsi) && !value.is(rsi) && !address.is(rsi));
 
   // First, check if a write barrier is even needed. The tests below
@@ -623,7 +636,9 @@
 }
 
 
-void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) {
+void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
+                                   InvokeFlag flag,
+                                   PostCallGenerator* post_call_generator) {
   // Calls are not allowed in some stubs.
   ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
 
@@ -632,7 +647,7 @@
   // parameter count to avoid emitting code to do the check.
   ParameterCount expected(0);
   GetBuiltinEntry(rdx, id);
-  InvokeCode(rdx, expected, expected, flag);
+  InvokeCode(rdx, expected, expected, flag, post_call_generator);
 }
 
 
@@ -906,7 +921,7 @@
 
 Condition MacroAssembler::CheckNonNegativeSmi(Register src) {
   ASSERT_EQ(0, kSmiTag);
-  // Make mask 0x8000000000000001 and test that both bits are zero.
+  // Test that both bits of the mask 0x8000000000000001 are zero.
   movq(kScratchRegister, src);
   rol(kScratchRegister, Immediate(1));
   testb(kScratchRegister, Immediate(3));
@@ -1442,10 +1457,19 @@
   // r13 is kRootRegister.
   push(r14);
   // r15 is kSmiConstantRegister
+  STATIC_ASSERT(11 == kNumSafepointSavedRegisters);
+  // Use lea for symmetry with Popad.
+  int sp_delta =
+      (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize;
+  lea(rsp, Operand(rsp, -sp_delta));
 }
 
 
 void MacroAssembler::Popad() {
+  // Popad must not change the flags, so use lea instead of addq.
+  int sp_delta =
+      (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize;
+  lea(rsp, Operand(rsp, sp_delta));
   pop(r14);
   pop(r12);
   pop(r11);
@@ -1461,8 +1485,7 @@
 
 
 void MacroAssembler::Dropad() {
-  const int kRegistersPushedByPushad = 11;
-  addq(rsp, Immediate(kRegistersPushedByPushad * kPointerSize));
+  addq(rsp, Immediate(kNumSafepointRegisters * kPointerSize));
 }
 
 
@@ -1488,6 +1511,21 @@
 };
 
 
+void MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
+  movq(SafepointRegisterSlot(dst), src);
+}
+
+
+void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
+  movq(dst, SafepointRegisterSlot(src));
+}
+
+
+Operand MacroAssembler::SafepointRegisterSlot(Register reg) {
+  return Operand(rsp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
+}
+
+
 void MacroAssembler::PushTryHandler(CodeLocation try_location,
                                     HandlerType type) {
   // Adjust this code if not the case.
@@ -1536,6 +1574,96 @@
 }
 
 
+void MacroAssembler::Throw(Register value) {
+  // Check that stack should contain next handler, frame pointer, state and
+  // return address in that order.
+  STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize ==
+            StackHandlerConstants::kStateOffset);
+  STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize ==
+            StackHandlerConstants::kPCOffset);
+  // Keep thrown value in rax.
+  if (!value.is(rax)) {
+    movq(rax, value);
+  }
+
+  ExternalReference handler_address(Top::k_handler_address);
+  movq(kScratchRegister, handler_address);
+  movq(rsp, Operand(kScratchRegister, 0));
+  // get next in chain
+  pop(rcx);
+  movq(Operand(kScratchRegister, 0), rcx);
+  pop(rbp);  // pop frame pointer
+  pop(rdx);  // remove state
+
+  // Before returning we restore the context from the frame pointer if not NULL.
+  // The frame pointer is NULL in the exception handler of a JS entry frame.
+  Set(rsi, 0);  // Tentatively set context pointer to NULL
+  NearLabel skip;
+  cmpq(rbp, Immediate(0));
+  j(equal, &skip);
+  movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+  bind(&skip);
+  ret(0);
+}
+
+
+void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
+                                      Register value) {
+  // Keep thrown value in rax.
+  if (!value.is(rax)) {
+    movq(rax, value);
+  }
+  // Fetch top stack handler.
+  ExternalReference handler_address(Top::k_handler_address);
+  movq(kScratchRegister, handler_address);
+  movq(rsp, Operand(kScratchRegister, 0));
+
+  // Unwind the handlers until the ENTRY handler is found.
+  NearLabel loop, done;
+  bind(&loop);
+  // Load the type of the current stack handler.
+  const int kStateOffset = StackHandlerConstants::kStateOffset;
+  cmpq(Operand(rsp, kStateOffset), Immediate(StackHandler::ENTRY));
+  j(equal, &done);
+  // Fetch the next handler in the list.
+  const int kNextOffset = StackHandlerConstants::kNextOffset;
+  movq(rsp, Operand(rsp, kNextOffset));
+  jmp(&loop);
+  bind(&done);
+
+  // Set the top handler address to next handler past the current ENTRY handler.
+  movq(kScratchRegister, handler_address);
+  pop(Operand(kScratchRegister, 0));
+
+  if (type == OUT_OF_MEMORY) {
+    // Set external caught exception to false.
+    ExternalReference external_caught(Top::k_external_caught_exception_address);
+    movq(rax, Immediate(false));
+    store_rax(external_caught);
+
+    // Set pending exception and rax to out of memory exception.
+    ExternalReference pending_exception(Top::k_pending_exception_address);
+    movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE);
+    store_rax(pending_exception);
+  }
+
+  // Clear the context pointer.
+  Set(rsi, 0);
+
+  // Restore registers from handler.
+  STATIC_ASSERT(StackHandlerConstants::kNextOffset + kPointerSize ==
+            StackHandlerConstants::kFPOffset);
+  pop(rbp);  // FP
+  STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize ==
+            StackHandlerConstants::kStateOffset);
+  pop(rdx);  // State
+
+  STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize ==
+            StackHandlerConstants::kPCOffset);
+  ret(0);
+}
+
+
 void MacroAssembler::Ret() {
   ret(0);
 }
@@ -1610,6 +1738,17 @@
 }
 
 
+void MacroAssembler::AbortIfNotString(Register object) {
+  testb(object, Immediate(kSmiTagMask));
+  Assert(not_equal, "Operand is not a string");
+  push(object);
+  movq(object, FieldOperand(object, HeapObject::kMapOffset));
+  CmpInstanceType(object, FIRST_NONSTRING_TYPE);
+  pop(object);
+  Assert(below, "Operand is not a string");
+}
+
+
 void MacroAssembler::AbortIfNotRootValue(Register src,
                                          Heap::RootListIndex root_value_index,
                                          const char* message) {
@@ -1728,11 +1867,19 @@
 void MacroAssembler::InvokeCode(Register code,
                                 const ParameterCount& expected,
                                 const ParameterCount& actual,
-                                InvokeFlag flag) {
+                                InvokeFlag flag,
+                                PostCallGenerator* post_call_generator) {
   NearLabel done;
-  InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag);
+  InvokePrologue(expected,
+                 actual,
+                 Handle<Code>::null(),
+                 code,
+                 &done,
+                 flag,
+                 post_call_generator);
   if (flag == CALL_FUNCTION) {
     call(code);
+    if (post_call_generator != NULL) post_call_generator->Generate();
   } else {
     ASSERT(flag == JUMP_FUNCTION);
     jmp(code);
@@ -1745,12 +1892,20 @@
                                 const ParameterCount& expected,
                                 const ParameterCount& actual,
                                 RelocInfo::Mode rmode,
-                                InvokeFlag flag) {
+                                InvokeFlag flag,
+                                PostCallGenerator* post_call_generator) {
   NearLabel done;
   Register dummy = rax;
-  InvokePrologue(expected, actual, code, dummy, &done, flag);
+  InvokePrologue(expected,
+                 actual,
+                 code,
+                 dummy,
+                 &done,
+                 flag,
+                 post_call_generator);
   if (flag == CALL_FUNCTION) {
     Call(code, rmode);
+    if (post_call_generator != NULL) post_call_generator->Generate();
   } else {
     ASSERT(flag == JUMP_FUNCTION);
     Jump(code, rmode);
@@ -1761,7 +1916,8 @@
 
 void MacroAssembler::InvokeFunction(Register function,
                                     const ParameterCount& actual,
-                                    InvokeFlag flag) {
+                                    InvokeFlag flag,
+                                    PostCallGenerator* post_call_generator) {
   ASSERT(function.is(rdi));
   movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
   movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
@@ -1772,13 +1928,14 @@
   movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
 
   ParameterCount expected(rbx);
-  InvokeCode(rdx, expected, actual, flag);
+  InvokeCode(rdx, expected, actual, flag, post_call_generator);
 }
 
 
 void MacroAssembler::InvokeFunction(JSFunction* function,
                                     const ParameterCount& actual,
-                                    InvokeFlag flag) {
+                                    InvokeFlag flag,
+                                    PostCallGenerator* post_call_generator) {
   ASSERT(function->is_compiled());
   // Get the function and setup the context.
   Move(rdi, Handle<JSFunction>(function));
@@ -1789,12 +1946,17 @@
     // the Code object every time we call the function.
     movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
     ParameterCount expected(function->shared()->formal_parameter_count());
-    InvokeCode(rdx, expected, actual, flag);
+    InvokeCode(rdx, expected, actual, flag, post_call_generator);
   } else {
     // Invoke the cached code.
     Handle<Code> code(function->code());
     ParameterCount expected(function->shared()->formal_parameter_count());
-    InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag);
+    InvokeCode(code,
+               expected,
+               actual,
+               RelocInfo::CODE_TARGET,
+               flag,
+               post_call_generator);
   }
 }
 
@@ -2387,9 +2549,21 @@
     }
     // The context may be an intermediate context, not a function context.
     movq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
-  } else {  // context is the current function context.
-    // The context may be an intermediate context, not a function context.
-    movq(dst, Operand(rsi, Context::SlotOffset(Context::FCONTEXT_INDEX)));
+  } else {
+    // Slot is in the current function context.  Move it into the
+    // destination register in case we store into it (the write barrier
+    // cannot be allowed to destroy the context in rsi).
+    movq(dst, rsi);
+  }
+
+  // We should not have found a 'with' context by walking the context chain
+  // (i.e., the static scope chain and runtime context chain do not agree).
+  // A variable occurring in such a scope should have slot type LOOKUP and
+  // not CONTEXT.
+  if (FLAG_debug_code) {
+    cmpq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
+    Check(equal, "Yo dawg, I heard you liked function contexts "
+                 "so I put function contexts in all your contexts");
   }
 }
 
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index 1002635..7a7f1a2 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -52,12 +52,16 @@
 static const Register kRootRegister = { 13 };         // r13 (callee save).
 // Value of smi in kSmiConstantRegister.
 static const int kSmiConstantRegisterValue = 1;
+// Actual value of root register is offset from the root array's start
+// to take advantage of negitive 8-bit displacement values.
+static const int kRootRegisterBias = 128;
 
 // Convenience for platform-independent signatures.
 typedef Operand MemOperand;
 
 // Forward declaration.
 class JumpTarget;
+class PostCallGenerator;
 
 struct SmiIndex {
   SmiIndex(Register index_register, ScaleFactor scale)
@@ -73,6 +77,12 @@
   MacroAssembler(void* buffer, int size);
 
   void LoadRoot(Register destination, Heap::RootListIndex index);
+  // Load a root value where the index (or part of it) is variable.
+  // The variable_offset register is added to the fixed_offset value
+  // to get the index into the root-array.
+  void LoadRootIndexed(Register destination,
+                       Register variable_offset,
+                       int fixed_offset);
   void CompareRoot(Register with, Heap::RootListIndex index);
   void CompareRoot(const Operand& with, Heap::RootListIndex index);
   void PushRoot(Heap::RootListIndex index);
@@ -170,10 +180,16 @@
   // Push and pop the registers that can hold pointers.
   void PushSafepointRegisters() { Pushad(); }
   void PopSafepointRegisters() { Popad(); }
-  static int SafepointRegisterStackIndex(int reg_code) {
-    return kSafepointPushRegisterIndices[reg_code];
-  }
+  // Store the value in register src in the safepoint register stack
+  // slot for register dst.
+  void StoreToSafepointRegisterSlot(Register dst, Register src);
+  void LoadFromSafepointRegisterSlot(Register dst, Register src);
 
+  void InitializeRootRegister() {
+    ExternalReference roots_address = ExternalReference::roots_address();
+    movq(kRootRegister, roots_address);
+    addq(kRootRegister, Immediate(kRootRegisterBias));
+  }
 
   // ---------------------------------------------------------------------------
   // JavaScript invokes
@@ -182,27 +198,33 @@
   void InvokeCode(Register code,
                   const ParameterCount& expected,
                   const ParameterCount& actual,
-                  InvokeFlag flag);
+                  InvokeFlag flag,
+                  PostCallGenerator* post_call_generator = NULL);
 
   void InvokeCode(Handle<Code> code,
                   const ParameterCount& expected,
                   const ParameterCount& actual,
                   RelocInfo::Mode rmode,
-                  InvokeFlag flag);
+                  InvokeFlag flag,
+                  PostCallGenerator* post_call_generator = NULL);
 
   // Invoke the JavaScript function in the given register. Changes the
   // current context to the context in the function before invoking.
   void InvokeFunction(Register function,
                       const ParameterCount& actual,
-                      InvokeFlag flag);
+                      InvokeFlag flag,
+                      PostCallGenerator* post_call_generator = NULL);
 
   void InvokeFunction(JSFunction* function,
                       const ParameterCount& actual,
-                      InvokeFlag flag);
+                      InvokeFlag flag,
+                      PostCallGenerator* post_call_generator = NULL);
 
   // Invoke specified builtin JavaScript function. Adds an entry to
   // the unresolved list if the name does not resolve.
-  void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag);
+  void InvokeBuiltin(Builtins::JavaScript id,
+                     InvokeFlag flag,
+                     PostCallGenerator* post_call_generator = NULL);
 
   // Store the function for the given builtin in the target register.
   void GetBuiltinFunction(Register target, Builtins::JavaScript id);
@@ -661,6 +683,9 @@
   // Abort execution if argument is not a smi. Used in debug code.
   void AbortIfNotSmi(Register object);
 
+  // Abort execution if argument is a string. Used in debug code.
+  void AbortIfNotString(Register object);
+
   // Abort execution if argument is not the root value with the given index.
   void AbortIfNotRootValue(Register src,
                            Heap::RootListIndex root_value_index,
@@ -676,6 +701,13 @@
   // Unlink the stack handler on top of the stack from the try handler chain.
   void PopTryHandler();
 
+  // Activate the top handler in the try hander chain and pass the
+  // thrown value.
+  void Throw(Register value);
+
+  // Propagate an uncatchable exception out of the current JS stack.
+  void ThrowUncatchable(UncatchableExceptionType type, Register value);
+
   // ---------------------------------------------------------------------------
   // Inline caching support
 
@@ -963,6 +995,8 @@
   // Order general registers are pushed by Pushad.
   // rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r12, r14.
   static int kSafepointPushRegisterIndices[Register::kNumRegisters];
+  static const int kNumSafepointSavedRegisters = 11;
+
   bool generating_stub_;
   bool allow_stub_calls_;
 
@@ -983,7 +1017,8 @@
                       Handle<Code> code_constant,
                       Register code_register,
                       LabelType* done,
-                      InvokeFlag flag);
+                      InvokeFlag flag,
+                      PostCallGenerator* post_call_generator);
 
   // Activation support.
   void EnterFrame(StackFrame::Type type);
@@ -1014,6 +1049,17 @@
   Object* PopHandleScopeHelper(Register saved,
                                Register scratch,
                                bool gc_allowed);
+
+
+  // Compute memory operands for safepoint stack slots.
+  Operand SafepointRegisterSlot(Register reg);
+  static int SafepointRegisterStackIndex(int reg_code) {
+    return kNumSafepointRegisters - kSafepointPushRegisterIndices[reg_code] - 1;
+  }
+
+  // Needs access to SafepointRegisterStackIndex for optimized frame
+  // traversal.
+  friend class OptimizedFrame;
 };
 
 
@@ -1037,6 +1083,17 @@
 };
 
 
+// Helper class for generating code or data associated with the code
+// right after a call instruction. As an example this can be used to
+// generate safepoint data after calls for crankshaft.
+class PostCallGenerator {
+ public:
+  PostCallGenerator() { }
+  virtual ~PostCallGenerator() { }
+  virtual void Generate() = 0;
+};
+
+
 // -----------------------------------------------------------------------------
 // Static helper functions.
 
@@ -1743,7 +1800,8 @@
                                     Handle<Code> code_constant,
                                     Register code_register,
                                     LabelType* done,
-                                    InvokeFlag flag) {
+                                    InvokeFlag flag,
+                                    PostCallGenerator* post_call_generator) {
   bool definitely_matches = false;
   NearLabel invoke;
   if (expected.is_immediate()) {
@@ -1794,6 +1852,7 @@
 
     if (flag == CALL_FUNCTION) {
       Call(adaptor, RelocInfo::CODE_TARGET);
+      if (post_call_generator != NULL) post_call_generator->Generate();
       jmp(done);
     } else {
       Jump(adaptor, RelocInfo::CODE_TARGET);
diff --git a/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc
index 27f3482..cd3bfbd 100644
--- a/src/x64/regexp-macro-assembler-x64.cc
+++ b/src/x64/regexp-macro-assembler-x64.cc
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
diff --git a/src/x64/regexp-macro-assembler-x64.h b/src/x64/regexp-macro-assembler-x64.h
index 182bc55..421a229 100644
--- a/src/x64/regexp-macro-assembler-x64.h
+++ b/src/x64/regexp-macro-assembler-x64.h
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
diff --git a/src/x64/simulator-x64.h b/src/x64/simulator-x64.h
index e607c8b..aa2994f 100644
--- a/src/x64/simulator-x64.h
+++ b/src/x64/simulator-x64.h
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -39,10 +39,13 @@
 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
   (entry(p0, p1, p2, p3, p4))
 
-// Call the generated regexp code directly. The entry function pointer should
+typedef int (*regexp_matcher)(String*, int, const byte*,
+                              const byte*, int*, Address, int);
+
+// Call the generated regexp code directly. The code at the entry address should
 // expect seven int/pointer sized arguments and return an int.
 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
-  (entry(p0, p1, p2, p3, p4, p5, p6))
+  (FUNCTION_CAST<regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6))
 
 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
   (reinterpret_cast<TryCatch*>(try_catch_address))
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 9cb88f3..109985c 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -2060,8 +2060,9 @@
       break;
 
     case STRING_CHECK:
-      if (!function->IsBuiltin()) {
-        // Calling non-builtins with a value as receiver requires boxing.
+      if (!function->IsBuiltin() && !function_info->strict_mode()) {
+        // Calling non-strict non-builtins with a value as the receiver
+        // requires boxing.
         __ jmp(&miss);
       } else {
         // Check that the object is a two-byte string or a symbol.
@@ -2076,8 +2077,9 @@
       break;
 
     case NUMBER_CHECK: {
-      if (!function->IsBuiltin()) {
-        // Calling non-builtins with a value as receiver requires boxing.
+      if (!function->IsBuiltin() && !function_info->strict_mode()) {
+        // Calling non-strict non-builtins with a value as the receiver
+        // requires boxing.
         __ jmp(&miss);
       } else {
         Label fast;
@@ -2096,8 +2098,9 @@
     }
 
     case BOOLEAN_CHECK: {
-      if (!function->IsBuiltin()) {
-        // Calling non-builtins with a value as receiver requires boxing.
+      if (!function->IsBuiltin() && !function_info->strict_mode()) {
+        // Calling non-strict non-builtins with a value as the receiver
+        // requires boxing.
         __ jmp(&miss);
       } else {
         Label fast;
@@ -2405,12 +2408,13 @@
   __ push(rdx);  // receiver
   __ push(rcx);  // name
   __ push(rax);  // value
+  __ Push(Smi::FromInt(strict_mode_));
   __ push(rbx);  // restore return address
 
   // Do tail-call to the runtime system.
   ExternalReference store_ic_property =
       ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
-  __ TailCallExternalReference(store_ic_property, 3, 1);
+  __ TailCallExternalReference(store_ic_property, 4, 1);
 
   // Handle store cache miss.
   __ bind(&miss);
@@ -2559,6 +2563,43 @@
 }
 
 
+MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray(
+    JSObject* receiver) {
+  // ----------- S t a t e -------------
+  //  -- rax    : value
+  //  -- rcx    : key
+  //  -- rdx    : receiver
+  //  -- rsp[0] : return address
+  // -----------------------------------
+  Label miss;
+
+  // Check that the map matches.
+  __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, false);
+
+  // Do the load.
+  GenerateFastPixelArrayStore(masm(),
+                              rdx,
+                              rcx,
+                              rax,
+                              rdi,
+                              rbx,
+                              true,
+                              false,
+                              &miss,
+                              &miss,
+                              NULL,
+                              &miss);
+
+  // Handle store cache miss.
+  __ bind(&miss);
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
+  __ jmp(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(NORMAL, NULL);
+}
+
+
 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
                                                       JSObject* object,
                                                       JSObject* last) {
@@ -3450,10 +3491,13 @@
   __ push(rdx);  // receiver
   __ push(rcx);  // key
   __ push(rax);  // value
+  __ Push(Smi::FromInt(NONE));   // PropertyAttributes
+  __ Push(Smi::FromInt(
+      Code::ExtractExtraICStateFromFlags(flags) & kStrictMode));
   __ push(rbx);  // return address
 
   // Do tail-call to runtime routine.
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 
   return GetCode(flags);
 }
diff --git a/src/x64/virtual-frame-x64.cc b/src/x64/virtual-frame-x64.cc
index 31f9527..c4d7e65 100644
--- a/src/x64/virtual-frame-x64.cc
+++ b/src/x64/virtual-frame-x64.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -274,6 +274,24 @@
 }
 
 
+void VirtualFrame::Push(Handle<Object> value) {
+  if (ConstantPoolOverflowed()) {
+    Result temp = cgen()->allocator()->Allocate();
+    ASSERT(temp.is_valid());
+    if (value->IsSmi()) {
+      __ Move(temp.reg(), Smi::cast(*value));
+    } else {
+      __ movq(temp.reg(), value, RelocInfo::EMBEDDED_OBJECT);
+    }
+    Push(&temp);
+  } else {
+    FrameElement element =
+        FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED);
+    elements_.Add(element);
+  }
+}
+
+
 void VirtualFrame::Drop(int count) {
   ASSERT(count >= 0);
   ASSERT(height() >= count);
@@ -1124,9 +1142,9 @@
                                  StrictModeFlag strict_mode) {
   // Value and (if not contextual) receiver are on top of the frame.
   // The IC expects name in rcx, value in rax, and receiver in rdx.
-  Handle<Code> ic(Builtins::builtin(strict_mode == kStrictMode
-      ? Builtins::StoreIC_Initialize_Strict
-      : Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode == kStrictMode) ? Builtins::StoreIC_Initialize_Strict
+                                   : Builtins::StoreIC_Initialize));
   Result value = Pop();
   RelocInfo::Mode mode;
   if (is_contextual) {
@@ -1146,7 +1164,7 @@
 }
 
 
-Result VirtualFrame::CallKeyedStoreIC() {
+Result VirtualFrame::CallKeyedStoreIC(StrictModeFlag strict_mode) {
   // Value, key, and receiver are on the top of the frame.  The IC
   // expects value in rax, key in rcx, and receiver in rdx.
   Result value = Pop();
@@ -1190,7 +1208,9 @@
     receiver.Unuse();
   }
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
+                                   : Builtins::KeyedStoreIC_Initialize));
   return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
 }
 
diff --git a/src/x64/virtual-frame-x64.h b/src/x64/virtual-frame-x64.h
index 4a9c720..7396db1 100644
--- a/src/x64/virtual-frame-x64.h
+++ b/src/x64/virtual-frame-x64.h
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -343,7 +343,7 @@
 
   // Call keyed store IC.  Value, key, and receiver are found on top
   // of the frame.  All three are dropped.
-  Result CallKeyedStoreIC();
+  Result CallKeyedStoreIC(StrictModeFlag strict_mode);
 
   // Call call IC.  Function name, arguments, and receiver are found on top
   // of the frame and dropped by the call.
@@ -400,9 +400,11 @@
   // Uses kScratchRegister, emits appropriate relocation info.
   void EmitPush(Handle<Object> value);
 
+  inline bool ConstantPoolOverflowed();
+
   // Push an element on the virtual frame.
+  void Push(Handle<Object> value);
   inline void Push(Register reg, TypeInfo info = TypeInfo::Unknown());
-  inline void Push(Handle<Object> value);
   inline void Push(Smi* value);
 
   // Pushing a result invalidates it (its contents become owned by the
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index a7422c2..e573eb2 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -47,29 +47,8 @@
 test-serialize/DependentTestThatAlwaysFails: FAIL
 
 ##############################################################################
-[ $arch == x64 ]
-
-# Optimization is currently not working on crankshaft x64 and ARM.
-test-heap/TestInternalWeakLists: PASS || FAIL
-test-heap/TestInternalWeakListsTraverseWithGC: PASS || FAIL
-
-
-##############################################################################
-[ $arch == x64 && $crankshaft ]
-
-# Tests that fail with crankshaft.
-test-deoptimization/DeoptimizeBinaryOperationMOD: FAIL
-test-deoptimization/DeoptimizeLoadICStoreIC: FAIL
-test-deoptimization/DeoptimizeLoadICStoreICNested: FAIL
-test-deoptimization/DeoptimizeCompare: PASS || FAIL
-
-##############################################################################
 [ $arch == arm ]
 
-# Optimization is currently not working on crankshaft x64 and ARM.
-test-heap/TestInternalWeakLists: PASS || FAIL
-test-heap/TestInternalWeakListsTraverseWithGC: PASS || FAIL
-
 # We cannot assume that we can throw OutOfMemory exceptions in all situations.
 # Apparently our ARM box is in such a state. Skip the test as it also runs for
 # a long time.
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index b92185f..cd26412 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -2691,6 +2691,41 @@
 }
 
 
+THREADED_TEST(TryCatchAndFinallyHidingException) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::TryCatch try_catch;
+  CHECK(!try_catch.HasCaught());
+  CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
+  CompileRun("f({toString: function() { throw 42; }});");
+  CHECK(!try_catch.HasCaught());
+}
+
+
+v8::Handle<v8::Value> WithTryCatch(const v8::Arguments& args) {
+  v8::TryCatch try_catch;
+  return v8::Undefined();
+}
+
+
+THREADED_TEST(TryCatchAndFinally) {
+  v8::HandleScope scope;
+  LocalContext context;
+  context->Global()->Set(
+      v8_str("native_with_try_catch"),
+      v8::FunctionTemplate::New(WithTryCatch)->GetFunction());
+  v8::TryCatch try_catch;
+  CHECK(!try_catch.HasCaught());
+  CompileRun(
+      "try {\n"
+      "  throw new Error('a');\n"
+      "} finally {\n"
+      "  native_with_try_catch();\n"
+      "}\n");
+  CHECK(try_catch.HasCaught());
+}
+
+
 THREADED_TEST(Equality) {
   v8::HandleScope scope;
   LocalContext context;
@@ -5617,6 +5652,56 @@
 }
 
 
+TEST(AccessControlES5) {
+  v8::HandleScope handle_scope;
+  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
+
+  global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
+                                           IndexedAccessBlocker);
+
+  // Add an accessor that is not accessible by cross-domain JS code.
+  global_template->SetAccessor(v8_str("blocked_prop"),
+                               UnreachableGetter, UnreachableSetter,
+                               v8::Handle<Value>(),
+                               v8::DEFAULT);
+
+  // Create an environment
+  v8::Persistent<Context> context0 = Context::New(NULL, global_template);
+  context0->Enter();
+
+  v8::Handle<v8::Object> global0 = context0->Global();
+
+  v8::Persistent<Context> context1 = Context::New();
+  context1->Enter();
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("other"), global0);
+
+  // Regression test for issue 1154.
+  ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
+
+  ExpectUndefined("other.blocked_prop");
+
+  // Regression test for issue 1027.
+  CompileRun("Object.defineProperty(\n"
+             "  other, 'blocked_prop', {configurable: false})");
+  ExpectUndefined("other.blocked_prop");
+  ExpectUndefined(
+      "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
+
+  // Regression test for issue 1171.
+  ExpectTrue("Object.isExtensible(other)");
+  CompileRun("Object.preventExtensions(other)");
+  ExpectTrue("Object.isExtensible(other)");
+
+  // Object.seal and Object.freeze.
+  CompileRun("Object.freeze(other)");
+  ExpectTrue("Object.isExtensible(other)");
+
+  CompileRun("Object.seal(other)");
+  ExpectTrue("Object.isExtensible(other)");
+}
+
+
 static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
                                             Local<Value> name,
                                             v8::AccessType type,
@@ -7542,10 +7627,11 @@
       "garbage = undefined;");
 }
 
+
 v8::Handle<v8::Value> DirectApiCallback(const v8::Arguments& args) {
   static int count = 0;
   if (count++ % 3 == 0) {
-    v8::V8::LowMemoryNotification();  // This should move the stub
+    i::Heap::CollectAllGarbage(true);  // This should move the stub
     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
   }
   return v8::Handle<v8::Value>();
@@ -7597,6 +7683,54 @@
 }
 
 
+v8::Handle<v8::Value> DirectGetterCallback(Local<String> name,
+                                           const v8::AccessorInfo& info) {
+  if (++p_getter_count % 3 == 0) {
+    i::Heap::CollectAllGarbage(true);
+    GenerateSomeGarbage();
+  }
+  return v8::Handle<v8::Value>();
+}
+
+
+THREADED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
+  obj->SetAccessor(v8_str("p1"), DirectGetterCallback);
+  context->Global()->Set(v8_str("o1"), obj->NewInstance());
+  p_getter_count = 0;
+  CompileRun(
+      "function f() {"
+      "  for (var i = 0; i < 30; i++) o1.p1;"
+      "}"
+      "f();");
+  CHECK_EQ(30, p_getter_count);
+}
+
+
+v8::Handle<v8::Value> ThrowingDirectGetterCallback(
+    Local<String> name, const v8::AccessorInfo& info) {
+  return v8::ThrowException(v8_str("g"));
+}
+
+
+THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
+  obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
+  context->Global()->Set(v8_str("o1"), obj->NewInstance());
+  v8::Handle<Value> result = CompileRun(
+      "var result = '';"
+      "for (var i = 0; i < 5; i++) {"
+      "    try { o1.p1; } catch (e) { result += e; }"
+      "}"
+      "result;");
+  CHECK_EQ(v8_str("ggggg"), result);
+}
+
+
 THREADED_TEST(InterceptorCallICFastApi_TrivialSignature) {
   int interceptor_call_count = 0;
   v8::HandleScope scope;
@@ -9957,10 +10091,11 @@
     // Inject the input as a global variable.
     i::Handle<i::String> input_name =
         i::Factory::NewStringFromAscii(i::Vector<const char>("input", 5));
-    i::Top::global_context()->global()->SetProperty(*input_name,
-                                                    *input_,
-                                                    NONE)->ToObjectChecked();
-
+    i::Top::global_context()->global()->SetProperty(
+        *input_name,
+        *input_,
+        NONE,
+        i::kNonStrictMode)->ToObjectChecked();
 
     MorphThread morph_thread(this);
     morph_thread.Start();
@@ -10482,14 +10617,14 @@
   CHECK_EQ(28, result->Int32Value());
 
   i::Handle<i::Smi> value(i::Smi::FromInt(2));
-  i::SetElement(jsobj, 1, value);
+  i::SetElement(jsobj, 1, value, i::kNonStrictMode);
   CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   *value.location() = i::Smi::FromInt(256);
-  i::SetElement(jsobj, 1, value);
+  i::SetElement(jsobj, 1, value, i::kNonStrictMode);
   CHECK_EQ(255,
            i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
   *value.location() = i::Smi::FromInt(-1);
-  i::SetElement(jsobj, 1, value);
+  i::SetElement(jsobj, 1, value, i::kNonStrictMode);
   CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
 
   result = CompileRun("for (var i = 0; i < 8; i++) {"
@@ -10691,7 +10826,62 @@
                       "result");
   CHECK_EQ(32640, result->Int32Value());
 
-    // Make sure that pixel array loads are optimized by crankshaft.
+  // Make sure that pixel array store ICs clamp values correctly.
+  result = CompileRun("function pa_store(p) {"
+                      "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
+                      "}"
+                      "pa_store(pixels);"
+                      "var sum = 0;"
+                      "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
+                      "sum");
+  CHECK_EQ(48896, result->Int32Value());
+
+  // Make sure that pixel array stores correctly handle accesses outside
+  // of the pixel array..
+  result = CompileRun("function pa_store(p,start) {"
+                      "  for (var j = 0; j < 256; j++) {"
+                      "    p[j+start] = j * 2;"
+                      "  }"
+                      "}"
+                      "pa_store(pixels,0);"
+                      "pa_store(pixels,-128);"
+                      "var sum = 0;"
+                      "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
+                      "sum");
+  CHECK_EQ(65280, result->Int32Value());
+
+  // Make sure that the generic store stub correctly handle accesses outside
+  // of the pixel array..
+  result = CompileRun("function pa_store(p,start) {"
+                      "  for (var j = 0; j < 256; j++) {"
+                      "    p[j+start] = j * 2;"
+                      "  }"
+                      "}"
+                      "pa_store(pixels,0);"
+                      "just_ints = new Object();"
+                      "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
+                      "pa_store(just_ints, 0);"
+                      "pa_store(pixels,-128);"
+                      "var sum = 0;"
+                      "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
+                      "sum");
+  CHECK_EQ(65280, result->Int32Value());
+
+  // Make sure that the generic keyed store stub clamps pixel array values
+  // correctly.
+  result = CompileRun("function pa_store(p) {"
+                      "  for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
+                      "}"
+                      "pa_store(pixels);"
+                      "just_ints = new Object();"
+                      "pa_store(just_ints);"
+                      "pa_store(pixels);"
+                      "var sum = 0;"
+                      "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
+                      "sum");
+  CHECK_EQ(48896, result->Int32Value());
+
+  // Make sure that pixel array loads are optimized by crankshaft.
   result = CompileRun("function pa_load(p) {"
                       "  var sum = 0;"
                       "  for (var i=0; i<256; ++i) {"
@@ -10706,6 +10896,24 @@
                       "result");
   CHECK_EQ(32640, result->Int32Value());
 
+  // Make sure that pixel array stores are optimized by crankshaft.
+  result = CompileRun("function pa_init(p) {"
+                      "for (var i = 0; i < 256; ++i) { p[i] = i; }"
+                      "}"
+                      "function pa_load(p) {"
+                      "  var sum = 0;"
+                      "  for (var i=0; i<256; ++i) {"
+                      "    sum += p[i];"
+                      "  }"
+                      "  return sum; "
+                      "}"
+                      "for (var i = 0; i < 100000; ++i) {"
+                      "  pa_init(pixels);"
+                      "}"
+                      "result = pa_load(pixels);"
+                      "result");
+  CHECK_EQ(32640, result->Int32Value());
+
   free(pixel_data);
 }
 
@@ -10725,6 +10933,53 @@
 }
 
 
+static v8::Handle<Value> NotHandledIndexedPropertyGetter(
+    uint32_t index,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8::Handle<Value>();
+}
+
+
+static v8::Handle<Value> NotHandledIndexedPropertySetter(
+    uint32_t index,
+    Local<Value> value,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8::Handle<Value>();
+}
+
+
+THREADED_TEST(PixelArrayWithInterceptor) {
+  v8::HandleScope scope;
+  LocalContext context;
+  const int kElementCount = 260;
+  uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
+  i::Handle<i::PixelArray> pixels =
+      i::Factory::NewPixelArray(kElementCount, pixel_data);
+  for (int i = 0; i < kElementCount; i++) {
+    pixels->set(i, i % 256);
+  }
+  v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
+  templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
+                                   NotHandledIndexedPropertySetter);
+  v8::Handle<v8::Object> obj = templ->NewInstance();
+  obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
+  context->Global()->Set(v8_str("pixels"), obj);
+  v8::Handle<v8::Value> result = CompileRun("pixels[1]");
+  CHECK_EQ(1, result->Int32Value());
+  result = CompileRun("var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  sum += pixels[i] = pixels[i] = -i;"
+                      "}"
+                      "sum;");
+  CHECK_EQ(-28, result->Int32Value());
+  result = CompileRun("pixels.hasOwnProperty('1')");
+  CHECK(result->BooleanValue());
+  free(pixel_data);
+}
+
+
 static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
   switch (array_type) {
     case v8::kExternalByteArray:
diff --git a/test/cctest/test-compiler.cc b/test/cctest/test-compiler.cc
index b424b7f..9f21b78 100644
--- a/test/cctest/test-compiler.cc
+++ b/test/cctest/test-compiler.cc
@@ -108,7 +108,7 @@
   Handle<Object> object(value);
   Handle<String> symbol = Factory::LookupAsciiSymbol(name);
   Handle<JSObject> global(Top::context()->global());
-  SetProperty(global, symbol, object, NONE);
+  SetProperty(global, symbol, object, NONE, kNonStrictMode);
 }
 
 
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index 239d8ae..7f06bc3 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -50,7 +50,7 @@
                                    i::Address frame3 = NULL) {
   i::TickSample* sample = proc->TickSampleEvent();
   sample->pc = frame1;
-  sample->function = frame1;
+  sample->tos = frame1;
   sample->frames_count = 0;
   if (frame2 != NULL) {
     sample->stack[0] = frame2;
@@ -103,7 +103,8 @@
                             i::Heap::empty_string(),
                             0,
                             ToAddress(0x1000),
-                            0x100);
+                            0x100,
+                            ToAddress(0x10000));
   processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
                             "bbb",
                             ToAddress(0x1200),
@@ -116,8 +117,6 @@
   processor.CodeMoveEvent(ToAddress(0x1400), ToAddress(0x1500));
   processor.CodeCreateEvent(i::Logger::STUB_TAG, 3, ToAddress(0x1600), 0x10);
   processor.CodeDeleteEvent(ToAddress(0x1600));
-  processor.FunctionCreateEvent(ToAddress(0x1700), ToAddress(0x1000),
-                                TokenEnumerator::kNoSecurityToken);
   // Enqueue a tick event to enable code events processing.
   EnqueueTickSampleEvent(&processor, ToAddress(0x1000));
 
@@ -139,9 +138,6 @@
   CHECK_NE(NULL, entry4);
   CHECK_EQ("ddd", entry4->name());
   CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1600)));
-  CodeEntry* entry5 = generator.code_map()->FindEntry(ToAddress(0x1700));
-  CHECK_NE(NULL, entry5);
-  CHECK_EQ(aaa_str, entry5->name());
 }
 
 
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 441aae6..7245e54 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -153,7 +153,8 @@
     Handle<v8::internal::String> debug_string =
         v8::internal::Factory::LookupAsciiSymbol("debug");
     SetProperty(global, debug_string,
-        Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM);
+        Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM,
+        ::v8::internal::kNonStrictMode);
   }
  private:
   v8::Persistent<v8::Context> context_;
diff --git a/test/cctest/test-decls.cc b/test/cctest/test-decls.cc
index 88fa79b..6ea4c84 100644
--- a/test/cctest/test-decls.cc
+++ b/test/cctest/test-decls.cc
@@ -223,7 +223,7 @@
   { DeclarationContext context;
     context.Check("function x() { }; x",
                   1,  // access
-                  1,  // declaration
+                  0,
                   0,
                   EXPECT_RESULT);
   }
@@ -278,7 +278,7 @@
   { PresentPropertyContext context;
     context.Check("function x() { }; x",
                   1,  // access
-                  1,  // declaration
+                  0,
                   0,
                   EXPECT_RESULT);
   }
@@ -332,7 +332,7 @@
   { AbsentPropertyContext context;
     context.Check("function x() { }; x",
                   1,  // access
-                  1,  // declaration
+                  0,
                   0,
                   EXPECT_RESULT);
   }
@@ -422,7 +422,7 @@
   { AppearingPropertyContext context;
     context.Check("function x() { }; x",
                   1,  // access
-                  1,  // declaration
+                  0,
                   0,
                   EXPECT_RESULT);
   }
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index a23ee17..4cc7f8b 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -212,13 +212,14 @@
     Handle<Map> initial_map =
         Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     function->set_initial_map(*initial_map);
-    Top::context()->global()->SetProperty(*name,
-                                          *function,
-                                          NONE)->ToObjectChecked();
+    Top::context()->global()->SetProperty(
+        *name, *function, NONE, kNonStrictMode)->ToObjectChecked();
     // Allocate an object.  Unrooted after leaving the scope.
     Handle<JSObject> obj = Factory::NewJSObject(function);
-    obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked();
-    obj->SetProperty(*prop_namex, Smi::FromInt(24), NONE)->ToObjectChecked();
+    obj->SetProperty(
+        *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
+    obj->SetProperty(
+        *prop_namex, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked();
 
     CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
     CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex));
@@ -238,10 +239,10 @@
     HandleScope inner_scope;
     // Allocate another object, make it reachable from global.
     Handle<JSObject> obj = Factory::NewJSObject(function);
-    Top::context()->global()->SetProperty(*obj_name,
-                                          *obj,
-                                          NONE)->ToObjectChecked();
-    obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked();
+    Top::context()->global()->SetProperty(
+        *obj_name, *obj, NONE, kNonStrictMode)->ToObjectChecked();
+    obj->SetProperty(
+        *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
   }
 
   // After gc, it should survive.
@@ -540,12 +541,12 @@
 
   Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot");
   Handle<JSObject> obj = Factory::NewJSObject(function);
-  obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
   CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
   // Check that we can add properties to function objects.
-  function->SetProperty(*prop_name,
-                        Smi::FromInt(24),
-                        NONE)->ToObjectChecked();
+  function->SetProperty(
+      *prop_name, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked();
   CHECK_EQ(Smi::FromInt(24), function->GetProperty(*prop_name));
 }
 
@@ -567,7 +568,8 @@
   CHECK(!obj->HasLocalProperty(*first));
 
   // add first
-  obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
   CHECK(obj->HasLocalProperty(*first));
 
   // delete first
@@ -575,8 +577,10 @@
   CHECK(!obj->HasLocalProperty(*first));
 
   // add first and then second
-  obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked();
-  obj->SetProperty(*second, Smi::FromInt(2), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
+  obj->SetProperty(
+      *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
   CHECK(obj->HasLocalProperty(*first));
   CHECK(obj->HasLocalProperty(*second));
 
@@ -588,8 +592,10 @@
   CHECK(!obj->HasLocalProperty(*second));
 
   // add first and then second
-  obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked();
-  obj->SetProperty(*second, Smi::FromInt(2), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
+  obj->SetProperty(
+      *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
   CHECK(obj->HasLocalProperty(*first));
   CHECK(obj->HasLocalProperty(*second));
 
@@ -603,14 +609,16 @@
   // check string and symbol match
   static const char* string1 = "fisk";
   Handle<String> s1 = Factory::NewStringFromAscii(CStrVector(string1));
-  obj->SetProperty(*s1, Smi::FromInt(1), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *s1, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
   Handle<String> s1_symbol = Factory::LookupAsciiSymbol(string1);
   CHECK(obj->HasLocalProperty(*s1_symbol));
 
   // check symbol and string match
   static const char* string2 = "fugl";
   Handle<String> s2_symbol = Factory::LookupAsciiSymbol(string2);
-  obj->SetProperty(*s2_symbol, Smi::FromInt(1), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *s2_symbol, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
   Handle<String> s2 = Factory::NewStringFromAscii(CStrVector(string2));
   CHECK(obj->HasLocalProperty(*s2));
 }
@@ -631,7 +639,8 @@
   Handle<JSObject> obj = Factory::NewJSObject(function);
 
   // Set a propery
-  obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
   CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
 
   // Check the map has changed
@@ -661,7 +670,7 @@
   CHECK(array->HasFastElements());  // Must be in fast mode.
 
   // array[length] = name.
-  ok = array->SetElement(0, *name)->ToObjectChecked();
+  ok = array->SetElement(0, *name, kNonStrictMode)->ToObjectChecked();
   CHECK_EQ(Smi::FromInt(1), array->length());
   CHECK_EQ(array->GetElement(0), *name);
 
@@ -676,7 +685,7 @@
   CHECK(array->HasDictionaryElements());  // Must be in slow mode.
 
   // array[length] = name.
-  ok = array->SetElement(int_length, *name)->ToObjectChecked();
+  ok = array->SetElement(int_length, *name, kNonStrictMode)->ToObjectChecked();
   uint32_t new_int_length = 0;
   CHECK(array->length()->ToArrayIndex(&new_int_length));
   CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
@@ -698,12 +707,14 @@
   Handle<String> first = Factory::LookupAsciiSymbol("first");
   Handle<String> second = Factory::LookupAsciiSymbol("second");
 
-  obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked();
-  obj->SetProperty(*second, Smi::FromInt(2), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
+  obj->SetProperty(
+      *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
 
-  Object* ok = obj->SetElement(0, *first)->ToObjectChecked();
+  Object* ok = obj->SetElement(0, *first, kNonStrictMode)->ToObjectChecked();
 
-  ok = obj->SetElement(1, *second)->ToObjectChecked();
+  ok = obj->SetElement(1, *second, kNonStrictMode)->ToObjectChecked();
 
   // Make the clone.
   Handle<JSObject> clone = Copy(obj);
@@ -716,11 +727,13 @@
   CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second));
 
   // Flip the values.
-  clone->SetProperty(*first, Smi::FromInt(2), NONE)->ToObjectChecked();
-  clone->SetProperty(*second, Smi::FromInt(1), NONE)->ToObjectChecked();
+  clone->SetProperty(
+      *first, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
+  clone->SetProperty(
+      *second, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
 
-  ok = clone->SetElement(0, *second)->ToObjectChecked();
-  ok = clone->SetElement(1, *first)->ToObjectChecked();
+  ok = clone->SetElement(0, *second, kNonStrictMode)->ToObjectChecked();
+  ok = clone->SetElement(1, *first, kNonStrictMode)->ToObjectChecked();
 
   CHECK_EQ(obj->GetElement(1), clone->GetElement(0));
   CHECK_EQ(obj->GetElement(0), clone->GetElement(1));
diff --git a/test/cctest/test-log-stack-tracer.cc b/test/cctest/test-log-stack-tracer.cc
index c85f6c0..bf72184 100644
--- a/test/cctest/test-log-stack-tracer.cc
+++ b/test/cctest/test-log-stack-tracer.cc
@@ -33,6 +33,7 @@
 
 #include "v8.h"
 
+#include "api.h"
 #include "codegen.h"
 #include "log.h"
 #include "top.h"
@@ -200,16 +201,16 @@
 }
 
 
-static void CheckJSFunctionAtAddress(const char* func_name, Address addr) {
-  CHECK(i::Heap::Contains(addr));
-  i::Object* obj = i::HeapObject::FromAddress(addr);
-  CHECK(obj->IsJSFunction());
-  CHECK(JSFunction::cast(obj)->shared()->name()->IsString());
-  i::SmartPointer<char> found_name =
-      i::String::cast(
-          JSFunction::cast(
-              obj)->shared()->name())->ToCString();
-  CHECK_EQ(func_name, *found_name);
+static bool IsAddressWithinFuncCode(JSFunction* function, Address addr) {
+  i::Code* code = function->code();
+  return code->contains(addr);
+}
+
+static bool IsAddressWithinFuncCode(const char* func_name, Address addr) {
+  v8::Local<v8::Value> func = env->Global()->Get(v8_str(func_name));
+  CHECK(func->IsFunction());
+  JSFunction* js_func = JSFunction::cast(*v8::Utils::OpenHandle(*func));
+  return IsAddressWithinFuncCode(js_func, addr);
 }
 
 
@@ -309,8 +310,8 @@
 
   // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace"
   CHECK_GT(sample.frames_count, base + 1);
-  CheckJSFunctionAtAddress("JSFuncDoTrace", sample.stack[base + 0]);
-  CheckJSFunctionAtAddress("JSTrace", sample.stack[base + 1]);
+  CHECK(IsAddressWithinFuncCode("JSFuncDoTrace", sample.stack[base + 0]));
+  CHECK(IsAddressWithinFuncCode("JSTrace", sample.stack[base + 1]));
 }
 
 
@@ -351,9 +352,6 @@
   //           DoTraceHideCEntryFPAddress(EBP) [native]
   //             StackTracer::Trace
   //
-  // The last JS function called. It is only visible through
-  // sample.function, as its return address is above captured EBP value.
-  CheckJSFunctionAtAddress("JSFuncDoTrace", sample.function);
 
   // The VM state tracking keeps track of external callbacks and puts
   // them at the top of the sample stack.
@@ -363,8 +361,8 @@
 
   // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace"
   CHECK_GT(sample.frames_count, base + 1);
-  CheckJSFunctionAtAddress("JSTrace", sample.stack[base + 0]);
-  CheckJSFunctionAtAddress("OuterJSTrace", sample.stack[base + 1]);
+  CHECK(IsAddressWithinFuncCode("JSTrace", sample.stack[base + 0]));
+  CHECK(IsAddressWithinFuncCode("OuterJSTrace", sample.stack[base + 1]));
 }
 
 
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index 032a183..30b8a48 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -1053,10 +1053,10 @@
   // Skip size.
   ref_s = strchr(ref_s, ',') + 1;
   new_s = strchr(new_s, ',') + 1;
-  int ref_len = StrChrLen(ref_s, '\n');
-  int new_len = StrChrLen(new_s, '\n');
-  // If reference is anonymous (""), it's OK to have anything in new.
-  if (ref_len == 2) return true;
+  CHECK_EQ('"', ref_s[0]);
+  CHECK_EQ('"', new_s[0]);
+  int ref_len = StrChrLen(ref_s + 1, '\"');
+  int new_len = StrChrLen(new_s + 1, '\"');
   // A special case for ErrorPrototype. Haven't yet figured out why they
   // are different.
   const char* error_prototype = "\"ErrorPrototype";
@@ -1074,21 +1074,6 @@
       return true;
     }
   }
-  // Code objects can change their optimizability: code object may start
-  // as optimizable, but later be discovered to be actually not optimizable.
-  // Alas, we don't record this info as of now, so we allow cases when
-  // ref is thought to be optimizable while traverse finds it to be
-  // not optimizable.
-  if (ref_s[1] == '~') {  // Code object used to be optimizable
-    if (new_s[1] == ' ') {  // ...but later was set unoptimizable.
-      CHECK_EQ('"', ref_s[0]);
-      CHECK_EQ('"', new_s[0]);
-      ref_s += 2;  // Cut the leading quote and the marker
-      ref_len -= 2;
-      new_s += 1;  // Cut the leading quote only.
-      new_len -= 1;
-    }
-  }
   return ref_len == new_len && strncmp(ref_s, new_s, ref_len) == 0;
 }
 
diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc
index 86f105f..3e3175e 100644
--- a/test/cctest/test-mark-compact.cc
+++ b/test/cctest/test-mark-compact.cc
@@ -189,7 +189,8 @@
   function->set_initial_map(initial_map);
   Top::context()->global()->SetProperty(func_name,
                                         function,
-                                        NONE)->ToObjectChecked();
+                                        NONE,
+                                        kNonStrictMode)->ToObjectChecked();
 
   JSObject* obj =
       JSObject::cast(Heap::AllocateJSObject(function)->ToObjectChecked());
@@ -208,10 +209,14 @@
       String::cast(Heap::LookupAsciiSymbol("theObject")->ToObjectChecked());
   Top::context()->global()->SetProperty(obj_name,
                                         obj,
-                                        NONE)->ToObjectChecked();
+                                        NONE,
+                                        kNonStrictMode)->ToObjectChecked();
   String* prop_name =
       String::cast(Heap::LookupAsciiSymbol("theSlot")->ToObjectChecked());
-  obj->SetProperty(prop_name, Smi::FromInt(23), NONE)->ToObjectChecked();
+  obj->SetProperty(prop_name,
+                   Smi::FromInt(23),
+                   NONE,
+                   kNonStrictMode)->ToObjectChecked();
 
   Heap::CollectGarbage(OLD_POINTER_SPACE);
 
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index 151cf50..8ee4038 100755
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -321,14 +321,17 @@
 
   data->Initialize();
 
-  int first_function = strstr(program, "function") - program;
-  int first_lbrace = first_function + strlen("function () ");
+  int first_function =
+      static_cast<int>(strstr(program, "function") - program);
+  int first_lbrace = first_function + static_cast<int>(strlen("function () "));
   CHECK_EQ('{', program[first_lbrace]);
   i::FunctionEntry entry1 = data->GetFunctionEntry(first_lbrace);
   CHECK(!entry1.is_valid());
 
-  int second_function = strstr(program + first_lbrace, "function") - program;
-  int second_lbrace = second_function + strlen("function () ");
+  int second_function =
+      static_cast<int>(strstr(program + first_lbrace, "function") - program);
+  int second_lbrace =
+      second_function + static_cast<int>(strlen("function () "));
   CHECK_EQ('{', program[second_lbrace]);
   i::FunctionEntry entry2 = data->GetFunctionEntry(second_lbrace);
   CHECK(entry2.is_valid());
diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc
index f849d40..c60d072 100644
--- a/test/cctest/test-profile-generator.cc
+++ b/test/cctest/test-profile-generator.cc
@@ -600,13 +600,13 @@
   //      -> ccc -> aaa  - sample3
   TickSample sample1;
   sample1.pc = ToAddress(0x1600);
-  sample1.function = ToAddress(0x1500);
+  sample1.tos = ToAddress(0x1500);
   sample1.stack[0] = ToAddress(0x1510);
   sample1.frames_count = 1;
   generator.RecordTickSample(sample1);
   TickSample sample2;
   sample2.pc = ToAddress(0x1925);
-  sample2.function = ToAddress(0x1900);
+  sample2.tos = ToAddress(0x1900);
   sample2.stack[0] = ToAddress(0x1780);
   sample2.stack[1] = ToAddress(0x10000);  // non-existent.
   sample2.stack[2] = ToAddress(0x1620);
@@ -614,7 +614,7 @@
   generator.RecordTickSample(sample2);
   TickSample sample3;
   sample3.pc = ToAddress(0x1510);
-  sample3.function = ToAddress(0x1500);
+  sample3.tos = ToAddress(0x1500);
   sample3.stack[0] = ToAddress(0x1910);
   sample3.stack[1] = ToAddress(0x1610);
   sample3.frames_count = 2;
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index 1cbaf2b..80910c2 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -104,7 +104,7 @@
   ExternalReferenceEncoder encoder;
   CHECK_EQ(make_code(BUILTIN, Builtins::ArrayCode),
            Encode(encoder, Builtins::ArrayCode));
-  CHECK_EQ(make_code(RUNTIME_FUNCTION, Runtime::kAbort),
+  CHECK_EQ(make_code(v8::internal::RUNTIME_FUNCTION, Runtime::kAbort),
            Encode(encoder, Runtime::kAbort));
   CHECK_EQ(make_code(IC_UTILITY, IC::kLoadCallbackProperty),
            Encode(encoder, IC_Utility(IC::kLoadCallbackProperty)));
@@ -142,7 +142,8 @@
   CHECK_EQ(AddressOf(Builtins::ArrayCode),
            decoder.Decode(make_code(BUILTIN, Builtins::ArrayCode)));
   CHECK_EQ(AddressOf(Runtime::kAbort),
-           decoder.Decode(make_code(RUNTIME_FUNCTION, Runtime::kAbort)));
+           decoder.Decode(make_code(v8::internal::RUNTIME_FUNCTION,
+                                    Runtime::kAbort)));
   CHECK_EQ(AddressOf(IC_Utility(IC::kLoadCallbackProperty)),
            decoder.Decode(make_code(IC_UTILITY, IC::kLoadCallbackProperty)));
   ExternalReference keyed_load_function =
diff --git a/test/es5conform/es5conform.status b/test/es5conform/es5conform.status
index 39754ca..d6f7caf 100644
--- a/test/es5conform/es5conform.status
+++ b/test/es5conform/es5conform.status
@@ -239,15 +239,6 @@
 # Incorrect test - need double escape in eval.
 chapter07/7.8/7.8.4/7.8.4-1-s: FAIL
 
-# this is not coerced to an object in strict mode (Number)
-chapter10/10.4/10.4.3/10.4.3-1-1-s: FAIL
-# this is not coerced to an object in strict mode (string)
-chapter10/10.4/10.4.3/10.4.3-1-2-s: FAIL
-# this is not coerced to an object in strict mode (undefined)
-chapter10/10.4/10.4.3/10.4.3-1-3-s: FAIL
-# this is not coerced to an object in strict mode (boolean)
-chapter10/10.4/10.4.3/10.4.3-1-4-s: FAIL
-
 # arguments[i] remains same after changing actual parameters in strict mode
 chapter10/10.6/10.6-10-c-ii-1-s: FAIL
 # arguments[i] doesn't map to actual parameters in strict mode
@@ -278,97 +269,30 @@
 # in strict mode (Global.length)
 chapter11/11.13/11.13.1/11.13.1-4-4-s: FAIL
 # simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Object.length)
-chapter11/11.13/11.13.1/11.13.1-4-5-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Function.length)
-chapter11/11.13/11.13.1/11.13.1-4-6-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Array.length)
-chapter11/11.13/11.13.1/11.13.1-4-7-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (String.length)
-chapter11/11.13/11.13.1/11.13.1-4-8-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Boolean.length)
-chapter11/11.13/11.13.1/11.13.1-4-9-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Number.length)
-chapter11/11.13/11.13.1/11.13.1-4-10-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Date.length)
-chapter11/11.13/11.13.1/11.13.1-4-11-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (RegExp.length)
-chapter11/11.13/11.13.1/11.13.1-4-12-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Error.length)
-chapter11/11.13/11.13.1/11.13.1-4-13-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Number.MAX_VALUE)
-chapter11/11.13/11.13.1/11.13.1-4-14-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Number.MIN_VALUE)
-chapter11/11.13/11.13.1/11.13.1-4-15-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Number.NaN)
-chapter11/11.13/11.13.1/11.13.1-4-16-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Number.NEGATIVE_INFINITY)
-chapter11/11.13/11.13.1/11.13.1-4-17-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Number.POSITIVE_INFINITY)
-chapter11/11.13/11.13.1/11.13.1-4-18-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.E)
-chapter11/11.13/11.13.1/11.13.1-4-19-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.LN10)
-chapter11/11.13/11.13.1/11.13.1-4-20-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.LN2)
-chapter11/11.13/11.13.1/11.13.1-4-21-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.LOG2E)
-chapter11/11.13/11.13.1/11.13.1-4-22-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.LOG10E)
-chapter11/11.13/11.13.1/11.13.1-4-23-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.PI)
-chapter11/11.13/11.13.1/11.13.1-4-24-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.SQRT1_2)
-chapter11/11.13/11.13.1/11.13.1-4-25-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.SQRT2)
-chapter11/11.13/11.13.1/11.13.1-4-26-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
 # in strict mode (Global.undefined)
 chapter11/11.13/11.13.1/11.13.1-4-27-s: FAIL
 
-# delete operator throws TypeError when deleting a non-configurable data
-# property in strict mode
-chapter11/11.4/11.4.1/11.4.1-4.a-3-s: FAIL
 # delete operator throws TypeError when when deleting a non-configurable
 # data property in strict mode (Global.NaN)
-chapter11/11.4/11.4.1/11.4.1-4.a-4-s: FAIL
-# delete operator throws TypeError when deleting a non-configurable data
-# property in strict mode (Math.LN2)
-chapter11/11.4/11.4.1/11.4.1-4.a-9-s: FAIL
+# Invalid test case - "this" is not a global object within the test case.
+# (http://es5conform.codeplex.com/workitem/29151)
+chapter11/11.4/11.4.1/11.4.1-4.a-4-s: FAIL_OK
 
 # delete operator throws ReferenceError when deleting a direct reference
 # to a var in strict mode
+# Invalid test case. Test expects ReferenceError instead of SyntaxError.
+# http://es5conform.codeplex.com/workitem/29084
 chapter11/11.4/11.4.1/11.4.1-5-1-s: FAIL
 # delete operator throws ReferenceError when deleting a direct reference
 # to a function argument in strict mode
+# Invalid test case. Test expects ReferenceError instead of SyntaxError.
+# http://es5conform.codeplex.com/workitem/29084
 chapter11/11.4/11.4.1/11.4.1-5-2-s: FAIL
 # delete operator throws ReferenceError when deleting a direct reference
 # to a function name in strict mode
+# Invalid test case. Test expects ReferenceError instead of SyntaxError.
+# http://es5conform.codeplex.com/workitem/29084
 chapter11/11.4/11.4.1/11.4.1-5-3-s: FAIL
-# delete operator throws SyntaxError when deleting a direct reference
-# to a function argument(object) in strict mode
-chapter11/11.4/11.4.1/11.4.1-5-4-s: FAIL
 
 # eval - a function declaring a var named 'eval' throws EvalError in strict mode
 # Invalid test case. SyntaxError should be expected instead of EvalError.
@@ -437,53 +361,13 @@
 # Test fails to return true on success (invalid test case).
 chapter13/13.1/13.1-3-12-s: FAIL
 
-# 'use strict' directive - correct usage
-# depends on "this is not coerced to an object in strict mode (undefined)"
-chapter14/14.1/14.1-1-s: FAIL
-# "use strict" directive - correct usage double quotes
-# depends on "this is not coerced to an object in strict mode (undefined)"
-chapter14/14.1/14.1-2-s: FAIL
-# 'use strict' directive - may follow other directives
-# depends on "this is not coerced to an object in strict mode (undefined)"
-chapter14/14.1/14.1-8-s: FAIL
-# 'use strict' directive - may occur multiple times
-# depends on "this is not coerced to an object in strict mode (undefined)"
-chapter14/14.1/14.1-9-s: FAIL
-# other directives - may follow 'use strict' directive
-# depends on "this is not coerced to an object in strict mode (undefined)"
-chapter14/14.1/14.1-10-s: FAIL
-# comments may preceed 'use strict' directive
-# depends on "this is not coerced to an object in strict mode (undefined)"
-chapter14/14.1/14.1-11-s: FAIL
-# comments may follow 'use strict' directive
-# depends on "this is not coerced to an object in strict mode (undefined)"
-chapter14/14.1/14.1-12-s: FAIL
-# semicolon insertion works for'use strict' directive
-# depends on "this is not coerced to an object in strict mode (undefined)"
-chapter14/14.1/14.1-13-s: FAIL
-# semicolon insertion may come before 'use strict' directive
-# depends on "this is not coerced to an object in strict mode (undefined)"
-chapter14/14.1/14.1-14-s: FAIL
-# blank lines may come before 'use strict' directive
-# depends on "this is not coerced to an object in strict mode (undefined)"
-chapter14/14.1/14.1-15-s: FAIL
-
 # Duplicate combined parameter name allowed in Function constructor called
 # in strict mode if body not strict
 # Test fails to return true on success (invalid test case).
 chapter15/15.3/15.3.2/15.3.2.1/15.3.2.1-11-6-s: FAIL
 
-# Array.prototype.every - thisArg not passed to strict callbackfn
-chapter15/15.4/15.4.4/15.4.4.16/15.4.4.16-5-1-s: FAIL
-# Array.prototype.some - thisArg not passed to strict callbackfn
-chapter15/15.4/15.4.4/15.4.4.17/15.4.4.17-5-1-s: FAIL
-# Array.prototype.forEach - thisArg not passed to strict callbackfn
-chapter15/15.4/15.4.4/15.4.4.18/15.4.4.18-5-1-s: FAIL
-# Array.prototype.map - thisArg not passed to strict callbackfn
-chapter15/15.4/15.4.4/15.4.4.19/15.4.4.19-5-1-s: FAIL
-# Array.prototype.filter - thisArg not passed to strict callbackfn
-chapter15/15.4/15.4.4/15.4.4.20/15.4.4.20-5-1-s: FAIL
 # Array.prototype.reduce - null passed as thisValue to strict callbackfn
+# Invalid test case: http://es5conform.codeplex.com/workitem/29085
 chapter15/15.4/15.4.4/15.4.4.21/15.4.4.21-9-c-ii-4-s: FAIL
 
 [ $arch == mips ]
diff --git a/test/mjsunit/array-concat.js b/test/mjsunit/array-concat.js
index db89f4d..97bd85a 100644
--- a/test/mjsunit/array-concat.js
+++ b/test/mjsunit/array-concat.js
@@ -101,7 +101,6 @@
   assertEquals("undefined", typeof(c[-1]));
   assertEquals("undefined", typeof(c[0xffffffff]));
   assertEquals(c.length, a.length + 1);
-
 }
 
 poses = [140, 4000000000];
@@ -193,3 +192,46 @@
     assertTrue(i in holey);
   }
 }
+
+// Polluted prototype from prior tests.
+delete Array.prototype[123];
+
+// Check that concat reads getters in the correct order.
+var arr1 = [,2];
+var arr2 = [1,3];
+var r1 = [].concat(arr1, arr2);  // [,2,1,3]
+assertEquals([,2,1,3], r1);
+
+// Make first array change length of second array.
+Object.defineProperty(arr1, 0, {get: function() {
+      arr2.push("X");
+      return undefined;
+    }, configurable: true})
+var r2 = [].concat(arr1, arr2);  // [undefined,2,1,3,"X"]
+assertEquals([undefined,2,1,3,"X"], r2);
+
+// Make first array change length of second array massively.
+arr2.length = 2;
+Object.defineProperty(arr1, 0, {get: function() {
+      arr2[500000] = "X";
+      return undefined;
+    }, configurable: true})
+var r3 = [].concat(arr1, arr2);  // [undefined,2,1,3,"X"]
+var expected = [undefined,2,1,3];
+expected[500000 + 2] = "X";
+
+assertEquals(expected, r3);
+
+var arr3 = [];
+var trace = [];
+var expectedTrace = []
+function mkGetter(i) { return function() { trace.push(i); }; }
+arr3.length = 10000;
+for (var i = 0; i < 100; i++) {
+  Object.defineProperty(arr3, i * i, {get: mkGetter(i)});
+  expectedTrace[i] = i;
+  expectedTrace[100 + i] = i;
+}
+var r4 = [0].concat(arr3, arr3);
+assertEquals(1 + arr3.length * 2, r4.length);
+assertEquals(expectedTrace, trace);
diff --git a/test/mjsunit/array-join.js b/test/mjsunit/array-join.js
index c66e462..ddd1496 100644
--- a/test/mjsunit/array-join.js
+++ b/test/mjsunit/array-join.js
@@ -27,19 +27,44 @@
 
 // Test that array join calls toString on subarrays.
 var a = [[1,2],3,4,[5,6]];
+assertEquals('1,2345,6', a.join(''));
 assertEquals('1,2*3*4*5,6', a.join('*'));
+assertEquals('1,2**3**4**5,6', a.join('**'));
+assertEquals('1,2****3****4****5,6', a.join('****'));
+assertEquals('1,2********3********4********5,6', a.join('********'));
+assertEquals('1,2**********3**********4**********5,6', a.join('**********'));
 
 // Create a cycle.
 a.push(a);
+assertEquals('1,2345,6', a.join(''));
 assertEquals('1,2*3*4*5,6*', a.join('*'));
+assertEquals('1,2**3**4**5,6**', a.join('**'));
+assertEquals('1,2****3****4****5,6****', a.join('****'));
+assertEquals('1,2********3********4********5,6********', a.join('********'));
+assertEquals('1,2**********3**********4**********5,6**********', a.join('**********'));
 
 // Replace array.prototype.toString.
 Array.prototype.toString = function() { return "array"; }
+assertEquals('array34arrayarray', a.join(''));
 assertEquals('array*3*4*array*array', a.join('*'));
+assertEquals('array**3**4**array**array', a.join('**'));
+assertEquals('array****3****4****array****array', a.join('****'));
+assertEquals('array********3********4********array********array', a.join('********'));
+assertEquals('array**********3**********4**********array**********array', a.join('**********'));
 
 Array.prototype.toString = function() { throw 42; }
+assertThrows("a.join('')");
 assertThrows("a.join('*')");
+assertThrows("a.join('**')");
+assertThrows("a.join('****')");
+assertThrows("a.join('********')");
+assertThrows("a.join('**********')");
 
 Array.prototype.toString = function() { return "array"; }
+assertEquals('array34arrayarray', a.join(''));
 assertEquals('array*3*4*array*array', a.join('*'));
+assertEquals('array**3**4**array**array', a.join('**'));
+assertEquals('array****3****4****array****array', a.join('****'));
+assertEquals('array********3********4********array********array', a.join('********'));
+assertEquals('array**********3**********4**********array**********array', a.join('**********'));
 
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/compiler/regress-valueof.js
similarity index 83%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/compiler/regress-valueof.js
index cfe2bd3..7b29b46 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/compiler/regress-valueof.js
@@ -25,14 +25,11 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// This should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// Flags: --allow-natives-syntax
 
-__defineSetter__("x", function(){ throw 42; });
+// Test valueof with integer input.
+function f(x) { var y = x + 1; return %_ValueOf(y); }
 
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
-}
+for (var i=0; i<100000; i++) f(42);
+
+assertEquals(43, f(42));
diff --git a/test/mjsunit/fuzz-natives.js b/test/mjsunit/fuzz-natives.js
index 020e3c0..cefef0a 100644
--- a/test/mjsunit/fuzz-natives.js
+++ b/test/mjsunit/fuzz-natives.js
@@ -118,8 +118,9 @@
   "Abort": true,
 
   // Avoid calling the concat operation, because weird lengths
-  // may lead to out-of-memory.
+  // may lead to out-of-memory.  Ditto for StringBuilderJoin.
   "StringBuilderConcat": true,
+  "StringBuilderJoin": true,
 
   // These functions use pseudo-stack-pointers and are not robust
   // to unexpected integer values.
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/indexed-value-properties.js
similarity index 69%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/indexed-value-properties.js
index cfe2bd3..92bb896 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/indexed-value-properties.js
@@ -25,14 +25,32 @@
 // (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 should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// Test that the Number, String and Boolean prototypes are searched
+// for indexed properties on value objects.
 
-__defineSetter__("x", function(){ throw 42; });
+function return_one() { return 1; };
 
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
+function test(value) {
+  for (var i = 0; i < 10; i++) {
+    assertEquals(0, (value)[0]);
+    assertEquals(0, (value)["0"]);
+    assertEquals(return_one, (value)[1]);
+    assertEquals(return_one, (value)["1"]);
+    assertEquals(1, (value)[1]());
+    assertEquals(1, (value)["1"]());
+  }
 }
+
+Number.prototype[0] = 0;
+Number.prototype[1] = return_one;
+test(0);
+test(0.1);
+
+String.prototype[0] = 0;
+String.prototype[1] = return_one;
+test("");
+
+Boolean.prototype[0] = 0;
+Boolean.prototype[1] = return_one;
+test(true);
+test(false);
diff --git a/test/mjsunit/mjsunit.js b/test/mjsunit/mjsunit.js
index 558282f..fe580f3 100644
--- a/test/mjsunit/mjsunit.js
+++ b/test/mjsunit/mjsunit.js
@@ -104,6 +104,13 @@
 }
 
 
+function assertSame(expected, found, name_opt) {
+  if (found !== expected) {
+    fail(expected, found, name_opt);
+  }
+}
+
+
 function assertEquals(expected, found, name_opt) {
   if (!deepEquals(found, expected)) {
     fail(expected, found, name_opt);
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 4012799..8f042ce 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -111,24 +111,6 @@
 regress/regress-1132: SKIP
 
 ##############################################################################
-[ $arch == arm && $crankshaft ]
-
-# Test that currently fails with crankshaft on ARM.
-compiler/simple-osr: FAIL
-
-# BUG (1094)
-regress/regress-deopt-gc: SKIP
-
-##############################################################################
-[ $arch == x64 && $crankshaft ]
-
-# BUG (1026) This test is currently flaky.
-compiler/simple-osr: SKIP
-
-# BUG (1094)
-regress/regress-deopt-gc: SKIP
-
-##############################################################################
 [ $arch == mips ]
 
 # Skip all tests on MIPS.
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/override-eval-with-non-function.js
similarity index 83%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/override-eval-with-non-function.js
index cfe2bd3..aa93b25 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/override-eval-with-non-function.js
@@ -25,14 +25,12 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// This should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// When 'eval' is overridden with a non-function object we should
+// check whether the object is callable.
 
-__defineSetter__("x", function(){ throw 42; });
-
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
+function test() {
+  eval = /foo/;
+  assertEquals("foo", eval("foobar"));
 }
+
+test();
diff --git a/test/mjsunit/regexp.js b/test/mjsunit/regexp.js
index 8d776ad..24e1b21 100644
--- a/test/mjsunit/regexp.js
+++ b/test/mjsunit/regexp.js
@@ -676,3 +676,17 @@
 assertFalse(re.test("c"));
 assertFalse(re.test(""));
 
+// Valid syntax in ES5.
+re = RegExp("(?:x)*");
+re = RegExp("(x)*");
+
+// Syntax extension relative to ES5, for matching JSC (and ES3).
+// Shouldn't throw.
+re = RegExp("(?=x)*");
+re = RegExp("(?!x)*");
+
+// Should throw. Shouldn't hit asserts in debug mode.
+assertThrows("RegExp('(*)')");
+assertThrows("RegExp('(?:*)')");
+assertThrows("RegExp('(?=*)')");
+assertThrows("RegExp('(?!*)')");
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1145.js
similarity index 64%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1145.js
index cfe2bd3..16d5527 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1145.js
@@ -25,14 +25,30 @@
 // (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 should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// Flags: --opt-eagerly --debug-code --lazy
 
-__defineSetter__("x", function(){ throw 42; });
+// See: http://code.google.com/p/v8/issues/detail?id=1145
+// Should not throw a syntax error exception (change this if we make lazily
+// compiled functions with syntax errors into early errors).
+// Should not hit an assertion in debug mode.
 
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
+// A lazily compiled function with a syntax error that is attempted inlined
+// would set a pending exception that is then ignored (until it triggers
+// an assert).
+// This file must be at least 1024 bytes long to trigger lazy compilation.
+
+function f() { return 1; }
+
+// Must be lazy. Must throw SyntaxError during compilation.
+function fail() { continue; }
+
+function opt_me() {
+  var x = 1;
+  // Do lots of function calls and hope to be optimized.
+  for (var i = 0; i < 1000000; i++) {
+    x = f();
+  }
+  if (x == 0) fail();  // Hope to be inlined during optimization.
 }
+
+opt_me();
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1146.js
similarity index 78%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1146.js
index cfe2bd3..e8028ce 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1146.js
@@ -25,14 +25,24 @@
 // (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 should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// Test keyed calls with different key types.
+function F() {}
+var a = new F();
+function f(i) { return a[i](); }
 
-__defineSetter__("x", function(){ throw 42; });
+a.first = function() { return 11; }
+a[0] = function() { return 22; }
+var obj = {};
+a[obj] = function() { return 33; }
 
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
-}
+// Make object slow-case.
+a.foo = 0;
+delete a.foo;
+// Do multiple calls for IC transitions.
+var b = "first";
+f(b);
+f(b);
+
+assertEquals(11, f(b));
+assertEquals(22, f(0));
+assertEquals(33, f(obj));
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1149.js
similarity index 84%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1149.js
index cfe2bd3..d7a7d1b 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1149.js
@@ -25,14 +25,15 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// This should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// We should not try to record duplicate bailout IDs for the 'left-hand
+// side' of a for/in, even if it is a parameter in a function using the
+// arguments object.
 
-__defineSetter__("x", function(){ throw 42; });
-
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
+function f(x) {
+  for (x in arguments) {
+    for (x in arguments) {
+    }
+  }
 }
+
+f();
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1151.js
similarity index 68%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1151.js
index cfe2bd3..8d0bca9 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1151.js
@@ -25,14 +25,25 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// This should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// Test that we do not try to create prototypes on objects that has the,
+// should_have_prototype flag set to false.
 
-__defineSetter__("x", function(){ throw 42; });
+__defineSetter__.__proto__ = function() {};
+__defineSetter__['prototype']
 
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
-}
+eval.__proto__ = function () { };
+eval['prototype'] = {};
+
+// Test that we are compatible with Safari on prototypes set locally and
+// on the actual prototype set using __proto__ on objects that has the
+// should_have_prototype set to false.
+function f() { return 42; }
+f.prototype = 43;
+__defineGetter__.__proto__ = f;
+
+// Regression test for not returning undefined.
+assertEquals(__defineGetter__.prototype, 43);
+
+// Regression test for not crashing.
+__defineGetter__.prototype = "foo";
+assertEquals(__defineGetter__.prototype, "foo");
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1156.js
similarity index 80%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1156.js
index cfe2bd3..8ec7f81 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1156.js
@@ -25,14 +25,25 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// This should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// Flags: --allow-natives-syntax --nouse-inlining
 
-__defineSetter__("x", function(){ throw 42; });
+// Test that we do not crash we invoke builtins from optimized code that
+// is then deoptimized.
 
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
+function foo(a) {
+  delete a[1];
+  delete a[2];
+  delete a[3];
+  delete a[4];
+  delete a[5];
+  return void 0;
 }
+
+function call_and_deopt() {
+  var b = [1,2,3];
+  foo(b);
+  foo(b);
+  %DeoptimizeFunction(foo);
+}
+
+call_and_deopt();
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1160.js
similarity index 71%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1160.js
index cfe2bd3..8e6e29b 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1160.js
@@ -25,14 +25,22 @@
 // (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 should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// See: http://code.google.com/p/v8/issues/detail?id=1160
 
-__defineSetter__("x", function(){ throw 42; });
+// Array.prototype.join uses a temporary array internally. Verify it
+// does not crash and throws an illegal argument exception instead
+// when keyed store on the array does not work as expected because of
+// the setter on its prototype.
 
 try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
-}
+  var N = 100;
+  var array = Array(N);
+  for (var i = 0; i < N; ++i) {
+    array[i] = i;
+  }
+  Array.prototype.__defineSetter__(32, function() { });
+  // The next line throws. We should make it work even with changed
+  // prototype. See http://code.google.com/p/v8/issues/detail?id=1161
+  array.join(",");
+  assertUnreachable();
+} catch (e) { }
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1166.js
similarity index 84%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1166.js
index cfe2bd3..d75d397 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1166.js
@@ -25,14 +25,11 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// This should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// Deoptimization after a short-circuit logical operation in an effect
+// context should not see the value of the expression.
+function observe(x, y) { return x; }
 
-__defineSetter__("x", function(){ throw 42; });
+function test(x) { return observe(1, ((false || false), x + 1)); }
 
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
-}
+for (var i = 0; i < 10000000; ++i) test(0);
+test("a");
diff --git a/test/mjsunit/regress/regress-1167.js b/test/mjsunit/regress/regress-1167.js
new file mode 100644
index 0000000..8437d83
--- /dev/null
+++ b/test/mjsunit/regress/regress-1167.js
@@ -0,0 +1,72 @@
+// 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.
+
+// Deoptimization after a logical not in an effect context should not see a
+// value for the logical not expression.
+function test0(n) {
+  var a = new Array(n);
+  for (var i = 0; i < n; ++i) {
+    // ~ of a non-numeric value is used to trigger deoptimization.
+    a[i] = void(!(delete 'object')) % ~(delete 4);
+  }
+}
+
+// OSR (after deoptimization) is used to observe the stack height mismatch.
+for (var i = 0; i < 5; ++i) {
+  for (var j = 1; j < 12; ++j) {
+    test0(j * 1000);
+  }
+}
+
+
+// Similar test with a different subexpression of unary !.
+function test1(n) {
+  var a = new Array(n);
+  for (var i = 0; i < n; ++i) {
+    a[i] = void(!(- 'object')) % ~(delete 4);
+  }
+}
+
+for (i = 0; i < 5; ++i) {
+  for (j = 1; j < 12; ++j) {
+    test1(j * 1000);
+  }
+}
+
+
+// A similar issue, different subexpression of unary ! (e0 !== e1 is
+// translated into !(e0 == e1)) and different effect context.
+function side_effect() { }
+function observe(x, y) { return x; }
+function test2(x) {
+  return observe(this,
+                 (((side_effect.observe <= side_effect.side_effect) !== false),
+                  x + 1));
+}
+
+for (var i = 0; i < 1000000; ++i) test2(0);
+test2(test2);
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1170.js
similarity index 63%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1170.js
index cfe2bd3..8a5a9cf 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1170.js
@@ -25,14 +25,42 @@
 // (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 should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+var setter_value = 0;
 
-__defineSetter__("x", function(){ throw 42; });
+__proto__.__defineSetter__("a", function(v) { setter_value = v; });
+eval("var a = 1");
+assertEquals(1, setter_value);
+assertFalse(hasOwnProperty("a"));
 
+eval("with({}) { eval('var a = 2') }");
+assertEquals(2, setter_value);
+assertFalse(hasOwnProperty("a"));
+
+// Function declarations are treated specially to match Safari. We do
+// not call setters for them.
+eval("function a() {}");
+assertTrue(hasOwnProperty("a"));
+
+__proto__.__defineSetter__("b", function(v) {   assertUnreachable(); });
 try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
+  eval("const b = 23");
+  assertUnreachable();
+} catch(e) {
+  assertTrue(/TypeError/.test(e));
 }
+try {
+  eval("with({}) { eval('const b = 23') }");
+  assertUnreachable();
+} catch(e) {
+  assertTrue(/TypeError/.test(e));
+}
+
+__proto__.__defineSetter__("c", function(v) { throw 42; });
+try {
+  eval("var c = 1");
+  assertUnreachable();
+} catch(e) {
+  assertEquals(42, e);
+  assertFalse(hasOwnProperty("c"));
+}
+
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1172-bis.js
similarity index 84%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1172-bis.js
index cfe2bd3..e8d5c81 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1172-bis.js
@@ -25,14 +25,13 @@
 // (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 should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// Verifies that exception thrown from JS accessors when attempting a call
+// are properly treated.
 
-__defineSetter__("x", function(){ throw 42; });
-
+Object.prototype.__defineGetter__(0, function() { throw 42; });
 try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
+  Object[0]();
+  assertUnreachable();
+} catch(e) {
+  assertEquals(42, e);
 }
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1172.js
similarity index 78%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1172.js
index cfe2bd3..f5ef67b 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1172.js
@@ -25,14 +25,15 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// This should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// Check that 'constructor' property is forcefully installed on
+// function's prototype even in the presence of JS accessors.
 
-__defineSetter__("x", function(){ throw 42; });
+// Note: no setters would lead to runtime exception if we ever attempt
+// to use JS accessors to set 'constructor' property.
+Object.prototype.__defineGetter__('constructor', function() { throw 42; });
 
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
-}
+function f() {}
+assertSame(f, f.prototype.constructor);
+
+var o = new f();
+assertSame(f, o.constructor);
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1174.js
similarity index 82%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1174.js
index cfe2bd3..7c014bf 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1174.js
@@ -25,14 +25,19 @@
 // (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 should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// Flags: --allow-natives-syntax
 
-__defineSetter__("x", function(){ throw 42; });
+// Test that we do not crash when doing deoptimization of a function that has
+// reloc info that only take up 1 byte per call (like KeyedStoreIC).
 
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
+function Regular() {
+  this[0] >>=  0;
+  this[1] ^=  1;
 }
+
+function foo() {
+  var regular = new Regular();
+  %DeoptimizeFunction(Regular);
+}
+
+foo();
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1176.js
similarity index 84%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1176.js
index cfe2bd3..58eda1b 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1176.js
@@ -25,14 +25,9 @@
 // (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 should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
-
-__defineSetter__("x", function(){ throw 42; });
-
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
+"use strict";
+function strict_delete_this() {
+  // "delete this" is allowed in strict mode.
+  delete this;
 }
+strict_delete_this();
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1181.js
similarity index 74%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1181.js
index cfe2bd3..d45a0be 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1181.js
@@ -25,14 +25,30 @@
 // (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 should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// The first count times, test is called with an integer argument and
+// crankshaft produces code for int32 representation. Test that the
+// implementation correctly deoptimizes.
 
-__defineSetter__("x", function(){ throw 42; });
+// Flags: --allow-natives-syntax
 
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
+function test(x) {
+    var xp = x  * 1 - 1;
+    return xp;
 }
+
+
+function check(count) {
+    %DeoptimizeFunction(test);
+    var i;
+    for(var x=0; x < count; x++){
+        for(var y=0; y < count; y++){
+            i = test(x / 100);
+        }
+    }
+    assertEquals((count - 1) / 100, i + 1);
+}
+
+
+check(150);
+check(200);
+check(350);
\ No newline at end of file
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1184.js
similarity index 70%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1184.js
index cfe2bd3..0bb1b3c 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1184.js
@@ -25,14 +25,23 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// This should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// Test the case when finally clause throws another exception (stack overflow)
+// which goes through some try/catch block---we need to clear v8::TryCatch
+// catcher as it doesn't catch original exception any more.
 
-__defineSetter__("x", function(){ throw 42; });
-
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
-}
+o = {};
+o.__defineGetter__('foo', function() { throw 42; });
+function f() {
+ try {
+   // throw below sets up Top::thread_local_.catcher_...
+   throw 42;
+ } finally {
+   // ...JS accessor traverses v8 runtime/JS boundary and
+   // when coming back from JS to v8 runtime, retraverses
+   // stack with catcher set while processing exception
+   // which is not caught by external try catch.
+   try { o.foo; } catch(e) { };
+   return;
+ }
+};
+f();
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1207.js
similarity index 84%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1207.js
index cfe2bd3..102178a 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1207.js
@@ -25,14 +25,11 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// This should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
-
-__defineSetter__("x", function(){ throw 42; });
-
+// Test throwing an exception from instanceof.
 try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
+var object = { };
+function fib(n) {
+  var f0 = (object instanceof encodeURI)('#2: var x = 1; x <= 1 === true'), f1 = 1;
 }
+fib(75);
+} catch (o) { }
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1209.js
similarity index 84%
rename from test/mjsunit/regress/regress-1105.js
rename to test/mjsunit/regress/regress-1209.js
index cfe2bd3..c017fb5 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1209.js
@@ -25,14 +25,10 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// This should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
-
-__defineSetter__("x", function(){ throw 42; });
-
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
+function crashMe(n) {
+  var nasty = [];
+  while (n--)
+    nasty.push("a" + 0);
+  return Function.apply(null, nasty);
 }
+crashMe(64 + 1).length;
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1210.js
similarity index 72%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1210.js
index cfe2bd3..9c708a5 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1210.js
@@ -25,14 +25,24 @@
 // (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 should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// Deoptimization of the key expression in an arguments access should see
+// the arguments object as the value of the receiver.
 
-__defineSetter__("x", function(){ throw 42; });
+var a = 0;
 
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
+function observe(x, y) { return x; }
+
+function side_effect(x) { a = x; }
+
+function test() {
+  // We will trigger deoptimization of 'a + 0' which should bail out to
+  // immediately after the call to 'side_effect' (i.e., still in the key
+  // subexpression of the arguments access).
+  return observe(a, arguments[side_effect(a), a + 0]);
 }
+
+// Run enough to optimize assuming global 'a' is a smi.
+for (var i = 0; i < 1000000; ++i) test(0);
+
+a = "hello";
+test(0);
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1213.js
similarity index 83%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1213.js
index cfe2bd3..d66e3ce 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1213.js
@@ -25,14 +25,19 @@
 // (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 should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// Test that we do not allow overwriting a global property with a
+// redeclaration that makes the property configurable (and hence
+// deletable).
 
-__defineSetter__("x", function(){ throw 42; });
+var x = 0;
 
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
+function TestGlobal() {
+  for (var i = 0; i < 2; i++) {
+    x = x + 1;
+  }
+  this.eval('function x() {};');
+  delete this['x'];
 }
+
+TestGlobal();
+TestGlobal();
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1218.js
similarity index 84%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-1218.js
index cfe2bd3..dd036ed 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-1218.js
@@ -25,14 +25,5 @@
 // (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 should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
-
-__defineSetter__("x", function(){ throw 42; });
-
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
-}
+// Builtin functions should not have prototype objects.
+assertFalse(Error.prototype.toString.hasOwnProperty("prototype"));
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-crbug-72736.js
similarity index 80%
copy from test/mjsunit/regress/regress-1105.js
copy to test/mjsunit/regress/regress-crbug-72736.js
index cfe2bd3..4b4b145 100644
--- a/test/mjsunit/regress/regress-1105.js
+++ b/test/mjsunit/regress/regress-crbug-72736.js
@@ -25,14 +25,13 @@
 // (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 should properly catch the exception from the setter triggered
-// by the loaded file, and it should not fail an assertion in debug mode.
+// See http://crbug.com/72736
 
-__defineSetter__("x", function(){ throw 42; });
+// This tests that Object.defineProperty actually allows to change the value of
+// a non-writable property if configurable is true.
 
-try {
-   this.eval('function x(){}');
-   assertUnreachable();
-} catch (e) {
-   assertEquals(42, e);
-}
+var obj = {};
+Object.defineProperty(obj, 'foo', { value: 10, configurable: true });
+assertEquals(obj.foo, 10);
+Object.defineProperty(obj, 'foo', { value: 20, configurable: true });
+assertEquals(obj.foo, 20);
diff --git a/test/mjsunit/strict-mode.js b/test/mjsunit/strict-mode.js
index 6b775fc..69be19c 100644
--- a/test/mjsunit/strict-mode.js
+++ b/test/mjsunit/strict-mode.js
@@ -169,13 +169,20 @@
 CheckStrictMode("var x = { '1234' : 1, '2345' : 2, 1234 : 3 };", SyntaxError);
 CheckStrictMode("var x = { 3.14 : 1, 2.71 : 2, 3.14 : 3 };", SyntaxError);
 CheckStrictMode("var x = { 3.14 : 1, '3.14' : 2 };", SyntaxError);
-CheckStrictMode("var x = { 123: 1, 123.00000000000000000000000000000000000000000000000000000000000000000001 : 2 }", SyntaxError);
+CheckStrictMode("var x = { \
+  123: 1, \
+  123.00000000000000000000000000000000000000000000000000000000000000000001: 2 \
+}", SyntaxError);
 
 // Non-conflicting data properties.
 (function StrictModeNonDuplicate() {
   "use strict";
   var x = { 123 : 1, "0123" : 2 };
-  var x = { 123: 1, '123.00000000000000000000000000000000000000000000000000000000000000000001' : 2 }
+  var x = {
+    123: 1,
+    '123.00000000000000000000000000000000000000000000000000000000000000000001':
+      2
+  };
 })();
 
 // Two getters (non-strict)
@@ -214,23 +221,32 @@
 CheckStrictMode("function strict() { eval = undefined; }", SyntaxError);
 CheckStrictMode("function strict() { arguments = undefined; }", SyntaxError);
 CheckStrictMode("function strict() { print(eval = undefined); }", SyntaxError);
-CheckStrictMode("function strict() { print(arguments = undefined); }", SyntaxError);
+CheckStrictMode("function strict() { print(arguments = undefined); }",
+                SyntaxError);
 CheckStrictMode("function strict() { var x = eval = undefined; }", SyntaxError);
-CheckStrictMode("function strict() { var x = arguments = undefined; }", SyntaxError);
+CheckStrictMode("function strict() { var x = arguments = undefined; }",
+                SyntaxError);
 
 // Compound assignment to eval or arguments
 CheckStrictMode("function strict() { eval *= undefined; }", SyntaxError);
 CheckStrictMode("function strict() { arguments /= undefined; }", SyntaxError);
 CheckStrictMode("function strict() { print(eval %= undefined); }", SyntaxError);
-CheckStrictMode("function strict() { print(arguments %= undefined); }", SyntaxError);
-CheckStrictMode("function strict() { var x = eval += undefined; }", SyntaxError);
-CheckStrictMode("function strict() { var x = arguments -= undefined; }", SyntaxError);
+CheckStrictMode("function strict() { print(arguments %= undefined); }",
+                SyntaxError);
+CheckStrictMode("function strict() { var x = eval += undefined; }",
+                SyntaxError);
+CheckStrictMode("function strict() { var x = arguments -= undefined; }",
+                SyntaxError);
 CheckStrictMode("function strict() { eval <<= undefined; }", SyntaxError);
 CheckStrictMode("function strict() { arguments >>= undefined; }", SyntaxError);
-CheckStrictMode("function strict() { print(eval >>>= undefined); }", SyntaxError);
-CheckStrictMode("function strict() { print(arguments &= undefined); }", SyntaxError);
-CheckStrictMode("function strict() { var x = eval ^= undefined; }", SyntaxError);
-CheckStrictMode("function strict() { var x = arguments |= undefined; }", SyntaxError);
+CheckStrictMode("function strict() { print(eval >>>= undefined); }",
+                SyntaxError);
+CheckStrictMode("function strict() { print(arguments &= undefined); }",
+                SyntaxError);
+CheckStrictMode("function strict() { var x = eval ^= undefined; }",
+                SyntaxError);
+CheckStrictMode("function strict() { var x = arguments |= undefined; }",
+                SyntaxError);
 
 // Postfix increment with eval or arguments
 CheckStrictMode("function strict() { eval++; }", SyntaxError);
@@ -264,6 +280,37 @@
 CheckStrictMode("function strict() { var x = --eval; }", SyntaxError);
 CheckStrictMode("function strict() { var x = --arguments; }", SyntaxError);
 
+// Use of const in strict mode is disallowed in anticipation of ES Harmony.
+CheckStrictMode("const x = 0;", SyntaxError);
+CheckStrictMode("for (const x = 0; false;) {}", SyntaxError);
+CheckStrictMode("function strict() { const x = 0; }", SyntaxError);
+
+// Strict mode only allows functions in SourceElements
+CheckStrictMode("if (true) { function invalid() {} }", SyntaxError);
+CheckStrictMode("for (;false;) { function invalid() {} }", SyntaxError);
+CheckStrictMode("{ function invalid() {} }", SyntaxError);
+CheckStrictMode("try { function invalid() {} } catch(e) {}", SyntaxError);
+CheckStrictMode("try { } catch(e) { function invalid() {} }", SyntaxError);
+CheckStrictMode("function outer() {{ function invalid() {} }}", SyntaxError);
+
+// Delete of an unqualified identifier
+CheckStrictMode("delete unqualified;", SyntaxError);
+CheckStrictMode("function strict() { delete unqualified; }", SyntaxError);
+CheckStrictMode("function function_name() { delete function_name; }",
+                SyntaxError);
+CheckStrictMode("function strict(parameter) { delete parameter; }",
+                SyntaxError);
+CheckStrictMode("function strict() { var variable; delete variable; }",
+                SyntaxError);
+CheckStrictMode("var variable; delete variable;", SyntaxError);
+
+(function TestStrictDelete() {
+  "use strict";
+  // "delete this" is allowed in strict mode and should work.
+  function strict_delete() { delete this; }
+  strict_delete();
+})();
+
 // Prefix unary operators other than delete, ++, -- are valid in strict mode
 (function StrictModeUnaryOperators() {
   "use strict";
@@ -318,17 +365,22 @@
   // Function names and arguments when the body is strict
   assertThrows("function " + word + " () { 'use strict'; }", SyntaxError);
   assertThrows("function foo (" + word + ")  'use strict'; {}", SyntaxError);
-  assertThrows("function foo (" + word + ", " + word + ") { 'use strict'; }", SyntaxError);
+  assertThrows("function foo (" + word + ", " + word + ") { 'use strict'; }",
+               SyntaxError);
   assertThrows("function foo (a, " + word + ") { 'use strict'; }", SyntaxError);
   assertThrows("function foo (" + word + ", a) { 'use strict'; }", SyntaxError);
-  assertThrows("function foo (a, " + word + ", b) { 'use strict'; }", SyntaxError);
-  assertThrows("var foo = function (" + word + ") { 'use strict'; }", SyntaxError);
+  assertThrows("function foo (a, " + word + ", b) { 'use strict'; }",
+               SyntaxError);
+  assertThrows("var foo = function (" + word + ") { 'use strict'; }",
+               SyntaxError);
 
   // get/set when the body is strict
   eval("var x = { get " + word + " () { 'use strict'; } };");
   eval("var x = { set " + word + " (value) { 'use strict'; } };");
-  assertThrows("var x = { get foo(" + word + ") { 'use strict'; } };", SyntaxError);
-  assertThrows("var x = { set foo(" + word + ") { 'use strict'; } };", SyntaxError);
+  assertThrows("var x = { get foo(" + word + ") { 'use strict'; } };",
+               SyntaxError);
+  assertThrows("var x = { set foo(" + word + ") { 'use strict'; } };",
+               SyntaxError);
 }
 
 for (var i = 0; i < future_reserved_words.length; i++) {
@@ -374,3 +426,534 @@
 repeat(10, function() { testAssignToUndefined(true); });
 possibly_undefined_variable_for_strict_mode_test = undefined;
 repeat(10, function() { testAssignToUndefined(false); });
+
+(function testDeleteNonConfigurable() {
+  function delete_property(o) {
+    "use strict";
+    delete o.property;
+  }
+  function delete_element(o, i) {
+    "use strict";
+    delete o[i];
+  }
+
+  var object = {};
+
+  Object.defineProperty(object, "property", { value: "property_value" });
+  Object.defineProperty(object, "1", { value: "one" });
+  Object.defineProperty(object, 7, { value: "seven" });
+  Object.defineProperty(object, 3.14, { value: "pi" });
+
+  assertThrows(function() { delete_property(object); }, TypeError);
+  assertEquals(object.property, "property_value");
+  assertThrows(function() { delete_element(object, "1"); }, TypeError);
+  assertThrows(function() { delete_element(object, 1); }, TypeError);
+  assertEquals(object[1], "one");
+  assertThrows(function() { delete_element(object, "7"); }, TypeError);
+  assertThrows(function() { delete_element(object, 7); }, TypeError);
+  assertEquals(object[7], "seven");
+  assertThrows(function() { delete_element(object, "3.14"); }, TypeError);
+  assertThrows(function() { delete_element(object, 3.14); }, TypeError);
+  assertEquals(object[3.14], "pi");
+})();
+
+// Not transforming this in Function.call and Function.apply.
+(function testThisTransformCallApply() {
+  function non_strict() {
+    return this;
+  }
+  function strict() {
+    "use strict";
+    return this;
+  }
+
+  var global_object = (function() { return this; })();
+  var object = {};
+
+  // Non-strict call.
+  assertTrue(non_strict.call(null) === global_object);
+  assertTrue(non_strict.call(undefined) === global_object);
+  assertEquals(typeof non_strict.call(7), "object");
+  assertEquals(typeof non_strict.call("Hello"), "object");
+  assertTrue(non_strict.call(object) === object);
+
+  // Non-strict apply.
+  assertTrue(non_strict.apply(null) === global_object);
+  assertTrue(non_strict.apply(undefined) === global_object);
+  assertEquals(typeof non_strict.apply(7), "object");
+  assertEquals(typeof non_strict.apply("Hello"), "object");
+  assertTrue(non_strict.apply(object) === object);
+
+  // Strict call.
+  assertTrue(strict.call(null) === null);
+  assertTrue(strict.call(undefined) === undefined);
+  assertEquals(typeof strict.call(7), "number");
+  assertEquals(typeof strict.call("Hello"), "string");
+  assertTrue(strict.call(object) === object);
+
+  // Strict apply.
+  assertTrue(strict.apply(null) === null);
+  assertTrue(strict.apply(undefined) === undefined);
+  assertEquals(typeof strict.apply(7), "number");
+  assertEquals(typeof strict.apply("Hello"), "string");
+  assertTrue(strict.apply(object) === object);
+})();
+
+(function testThisTransform() {
+  try {
+    function strict() {
+      "use strict";
+      return typeof(this);
+    }
+    function nonstrict() {
+      return typeof(this);
+    }
+
+    // Concat to avoid symbol.
+    var strict_name = "str" + "ict";
+    var nonstrict_name = "non" + "str" + "ict";
+    var strict_number = 17;
+    var nonstrict_number = 19;
+    var strict_name_get = "str" + "ict" + "get";
+    var nonstrict_name_get = "non" + "str" + "ict" + "get"
+    var strict_number_get = 23;
+    var nonstrict_number_get = 29;
+
+    function install(t) {
+      t.prototype.strict = strict;
+      t.prototype.nonstrict = nonstrict;
+      t.prototype[strict_number] = strict;
+      t.prototype[nonstrict_number] = nonstrict;
+      Object.defineProperty(t.prototype, strict_name_get,
+                            { get: function() { return strict; },
+                              configurable: true });
+      Object.defineProperty(t.prototype, nonstrict_name_get,
+                            { get: function() { return nonstrict; },
+                              configurable: true });
+      Object.defineProperty(t.prototype, strict_number_get,
+                            { get: function() { return strict; },
+                              configurable: true });
+      Object.defineProperty(t.prototype, nonstrict_number_get,
+                            { get: function() { return nonstrict; },
+                              configurable: true });
+    }
+
+    function cleanup(t) {
+      delete t.prototype.strict;
+      delete t.prototype.nonstrict;
+      delete t.prototype[strict_number];
+      delete t.prototype[nonstrict_number];
+      delete t.prototype[strict_name_get];
+      delete t.prototype[nonstrict_name_get];
+      delete t.prototype[strict_number_get];
+      delete t.prototype[nonstrict_number_get];
+    }
+
+    // Set up fakes
+    install(String);
+    install(Number);
+    install(Boolean)
+
+    function callStrict(o) {
+      return o.strict();
+    }
+    function callNonStrict(o) {
+      return o.nonstrict();
+    }
+    function callKeyedStrict(o) {
+      return o[strict_name]();
+    }
+    function callKeyedNonStrict(o) {
+      return o[nonstrict_name]();
+    }
+    function callIndexedStrict(o) {
+      return o[strict_number]();
+    }
+    function callIndexedNonStrict(o) {
+      return o[nonstrict_number]();
+    }
+    function callStrictGet(o) {
+      return o.strictget();
+    }
+    function callNonStrictGet(o) {
+      return o.nonstrictget();
+    }
+    function callKeyedStrictGet(o) {
+      return o[strict_name_get]();
+    }
+    function callKeyedNonStrictGet(o) {
+      return o[nonstrict_name_get]();
+    }
+    function callIndexedStrictGet(o) {
+      return o[strict_number_get]();
+    }
+    function callIndexedNonStrictGet(o) {
+      return o[nonstrict_number_get]();
+    }
+
+    for (var i = 0; i < 10; i ++) {
+      assertEquals(("hello").strict(), "string");
+      assertEquals(("hello").nonstrict(), "object");
+      assertEquals(("hello")[strict_name](), "string");
+      assertEquals(("hello")[nonstrict_name](), "object");
+      assertEquals(("hello")[strict_number](), "string");
+      assertEquals(("hello")[nonstrict_number](), "object");
+
+      assertEquals((10 + i).strict(), "number");
+      assertEquals((10 + i).nonstrict(), "object");
+      assertEquals((10 + i)[strict_name](), "number");
+      assertEquals((10 + i)[nonstrict_name](), "object");
+      assertEquals((10 + i)[strict_number](), "number");
+      assertEquals((10 + i)[nonstrict_number](), "object");
+
+      assertEquals((true).strict(), "boolean");
+      assertEquals((true).nonstrict(), "object");
+      assertEquals((true)[strict_name](), "boolean");
+      assertEquals((true)[nonstrict_name](), "object");
+      assertEquals((true)[strict_number](), "boolean");
+      assertEquals((true)[nonstrict_number](), "object");
+
+      assertEquals((false).strict(), "boolean");
+      assertEquals((false).nonstrict(), "object");
+      assertEquals((false)[strict_name](), "boolean");
+      assertEquals((false)[nonstrict_name](), "object");
+      assertEquals((false)[strict_number](), "boolean");
+      assertEquals((false)[nonstrict_number](), "object");
+
+      assertEquals(callStrict("howdy"), "string");
+      assertEquals(callNonStrict("howdy"), "object");
+      assertEquals(callKeyedStrict("howdy"), "string");
+      assertEquals(callKeyedNonStrict("howdy"), "object");
+      assertEquals(callIndexedStrict("howdy"), "string");
+      assertEquals(callIndexedNonStrict("howdy"), "object");
+
+      assertEquals(callStrict(17 + i), "number");
+      assertEquals(callNonStrict(17 + i), "object");
+      assertEquals(callKeyedStrict(17 + i), "number");
+      assertEquals(callKeyedNonStrict(17 + i), "object");
+      assertEquals(callIndexedStrict(17 + i), "number");
+      assertEquals(callIndexedNonStrict(17 + i), "object");
+
+      assertEquals(callStrict(true), "boolean");
+      assertEquals(callNonStrict(true), "object");
+      assertEquals(callKeyedStrict(true), "boolean");
+      assertEquals(callKeyedNonStrict(true), "object");
+      assertEquals(callIndexedStrict(true), "boolean");
+      assertEquals(callIndexedNonStrict(true), "object");
+
+      assertEquals(callStrict(false), "boolean");
+      assertEquals(callNonStrict(false), "object");
+      assertEquals(callKeyedStrict(false), "boolean");
+      assertEquals(callKeyedNonStrict(false), "object");
+      assertEquals(callIndexedStrict(false), "boolean");
+      assertEquals(callIndexedNonStrict(false), "object");
+
+      // All of the above, with getters
+      assertEquals(("hello").strictget(), "string");
+      assertEquals(("hello").nonstrictget(), "object");
+      assertEquals(("hello")[strict_name_get](), "string");
+      assertEquals(("hello")[nonstrict_name_get](), "object");
+      assertEquals(("hello")[strict_number_get](), "string");
+      assertEquals(("hello")[nonstrict_number_get](), "object");
+
+      assertEquals((10 + i).strictget(), "number");
+      assertEquals((10 + i).nonstrictget(), "object");
+      assertEquals((10 + i)[strict_name_get](), "number");
+      assertEquals((10 + i)[nonstrict_name_get](), "object");
+      assertEquals((10 + i)[strict_number_get](), "number");
+      assertEquals((10 + i)[nonstrict_number_get](), "object");
+
+      assertEquals((true).strictget(), "boolean");
+      assertEquals((true).nonstrictget(), "object");
+      assertEquals((true)[strict_name_get](), "boolean");
+      assertEquals((true)[nonstrict_name_get](), "object");
+      assertEquals((true)[strict_number_get](), "boolean");
+      assertEquals((true)[nonstrict_number_get](), "object");
+
+      assertEquals((false).strictget(), "boolean");
+      assertEquals((false).nonstrictget(), "object");
+      assertEquals((false)[strict_name_get](), "boolean");
+      assertEquals((false)[nonstrict_name_get](), "object");
+      assertEquals((false)[strict_number_get](), "boolean");
+      assertEquals((false)[nonstrict_number_get](), "object");
+
+      assertEquals(callStrictGet("howdy"), "string");
+      assertEquals(callNonStrictGet("howdy"), "object");
+      assertEquals(callKeyedStrictGet("howdy"), "string");
+      assertEquals(callKeyedNonStrictGet("howdy"), "object");
+      assertEquals(callIndexedStrictGet("howdy"), "string");
+      assertEquals(callIndexedNonStrictGet("howdy"), "object");
+
+      assertEquals(callStrictGet(17 + i), "number");
+      assertEquals(callNonStrictGet(17 + i), "object");
+      assertEquals(callKeyedStrictGet(17 + i), "number");
+      assertEquals(callKeyedNonStrictGet(17 + i), "object");
+      assertEquals(callIndexedStrictGet(17 + i), "number");
+      assertEquals(callIndexedNonStrictGet(17 + i), "object");
+
+      assertEquals(callStrictGet(true), "boolean");
+      assertEquals(callNonStrictGet(true), "object");
+      assertEquals(callKeyedStrictGet(true), "boolean");
+      assertEquals(callKeyedNonStrictGet(true), "object");
+      assertEquals(callIndexedStrictGet(true), "boolean");
+      assertEquals(callIndexedNonStrictGet(true), "object");
+
+      assertEquals(callStrictGet(false), "boolean");
+      assertEquals(callNonStrictGet(false), "object");
+      assertEquals(callKeyedStrictGet(false), "boolean");
+      assertEquals(callKeyedNonStrictGet(false), "object");
+      assertEquals(callIndexedStrictGet(false), "boolean");
+      assertEquals(callIndexedNonStrictGet(false), "object");
+
+    }
+  } finally {
+    // Cleanup
+    cleanup(String);
+    cleanup(Number);
+    cleanup(Boolean);
+  }
+})();
+
+
+(function ObjectEnvironment() {
+  var o = {};
+  Object.defineProperty(o, "foo", { value: "FOO", writable: false });
+  assertThrows(
+    function () {
+      with (o) {
+        (function() {
+          "use strict";
+          foo = "Hello";
+        })();
+      }
+    },
+    TypeError);
+})();
+
+
+(function TestSetPropertyWithoutSetter() {
+  var o = { get foo() { return "Yey"; } };
+  assertThrows(
+    function broken() {
+      "use strict";
+      o.foo = (0xBADBAD00 >> 1);
+    },
+    TypeError);
+})();
+
+
+(function TestSetPropertyNonConfigurable() {
+  var frozen = Object.freeze({});
+  var sealed = Object.seal({});
+
+  function strict(o) {
+    "use strict";
+    o.property = "value";
+  }
+
+  assertThrows(function() { strict(frozen); }, TypeError);
+  assertThrows(function() { strict(sealed); }, TypeError);
+})();
+
+
+(function TestAssignmentToReadOnlyProperty() {
+  "use strict";
+
+  var o = {};
+  Object.defineProperty(o, "property", { value: 7 });
+
+  assertThrows(function() { o.property = "new value"; }, TypeError);
+  assertThrows(function() { o.property += 10; }, TypeError);
+  assertThrows(function() { o.property -= 10; }, TypeError);
+  assertThrows(function() { o.property *= 10; }, TypeError);
+  assertThrows(function() { o.property /= 10; }, TypeError);
+  assertThrows(function() { o.property++; }, TypeError);
+  assertThrows(function() { o.property--; }, TypeError);
+  assertThrows(function() { ++o.property; }, TypeError);
+  assertThrows(function() { --o.property; }, TypeError);
+
+  var name = "prop" + "erty"; // to avoid symbol path.
+  assertThrows(function() { o[name] = "new value"; }, TypeError);
+  assertThrows(function() { o[name] += 10; }, TypeError);
+  assertThrows(function() { o[name] -= 10; }, TypeError);
+  assertThrows(function() { o[name] *= 10; }, TypeError);
+  assertThrows(function() { o[name] /= 10; }, TypeError);
+  assertThrows(function() { o[name]++; }, TypeError);
+  assertThrows(function() { o[name]--; }, TypeError);
+  assertThrows(function() { ++o[name]; }, TypeError);
+  assertThrows(function() { --o[name]; }, TypeError);
+
+  assertEquals(o.property, 7);
+})();
+
+
+(function TestAssignmentToReadOnlyLoop() {
+  var name = "prop" + "erty"; // to avoid symbol path.
+  var o = {};
+  Object.defineProperty(o, "property", { value: 7 });
+
+  function strict(o, name) {
+    "use strict";
+    o[name] = "new value";
+  }
+
+  for (var i = 0; i < 10; i ++) {
+    try {
+      strict(o, name);
+      assertUnreachable();
+    } catch(e) {
+      assertInstanceof(e, TypeError);
+    }
+  }
+})();
+
+
+// Specialized KeyedStoreIC experiencing miss.
+(function testKeyedStoreICStrict() {
+  var o = [9,8,7,6,5,4,3,2,1];
+
+  function test(o, i, v) {
+    "use strict";
+    o[i] = v;
+  }
+
+  for (var i = 0; i < 10; i ++) {
+    test(o, 5, 17);        // start specialized for smi indices
+    assertEquals(o[5], 17);
+    test(o, "a", 19);
+    assertEquals(o["a"], 19);
+    test(o, "5", 29);
+    assertEquals(o[5], 29);
+    test(o, 100000, 31);
+    assertEquals(o[100000], 31);
+  }
+})();
+
+
+(function TestSetElementWithoutSetter() {
+  "use strict";
+
+  var o = { };
+  Object.defineProperty(o, 0, { get : function() { } });
+
+  var zero_smi = 0;
+  var zero_number = new Number(0);
+  var zero_symbol = "0";
+  var zero_string = "-0-".substring(1,2);
+
+  assertThrows(function() { o[zero_smi] = "new value"; }, TypeError);
+  assertThrows(function() { o[zero_number] = "new value"; }, TypeError);
+  assertThrows(function() { o[zero_symbol] = "new value"; }, TypeError);
+  assertThrows(function() { o[zero_string] = "new value"; }, TypeError);
+})();
+
+
+(function TestSetElementNonConfigurable() {
+  "use strict";
+  var frozen = Object.freeze({});
+  var sealed = Object.seal({});
+
+  var zero_number = 0;
+  var zero_symbol = "0";
+  var zero_string = "-0-".substring(1,2);
+
+  assertThrows(function() { frozen[zero_number] = "value"; }, TypeError);
+  assertThrows(function() { sealed[zero_number] = "value"; }, TypeError);
+  assertThrows(function() { frozen[zero_symbol] = "value"; }, TypeError);
+  assertThrows(function() { sealed[zero_symbol] = "value"; }, TypeError);
+  assertThrows(function() { frozen[zero_string] = "value"; }, TypeError);
+  assertThrows(function() { sealed[zero_string] = "value"; }, TypeError);
+})();
+
+
+(function TestAssignmentToReadOnlyElement() {
+  "use strict";
+
+  var o = {};
+  Object.defineProperty(o, 7, { value: 17 });
+
+  var seven_smi = 7;
+  var seven_number = new Number(7);
+  var seven_symbol = "7";
+  var seven_string = "-7-".substring(1,2);
+
+  // Index with number.
+  assertThrows(function() { o[seven_smi] = "value"; }, TypeError);
+  assertThrows(function() { o[seven_smi] += 10; }, TypeError);
+  assertThrows(function() { o[seven_smi] -= 10; }, TypeError);
+  assertThrows(function() { o[seven_smi] *= 10; }, TypeError);
+  assertThrows(function() { o[seven_smi] /= 10; }, TypeError);
+  assertThrows(function() { o[seven_smi]++; }, TypeError);
+  assertThrows(function() { o[seven_smi]--; }, TypeError);
+  assertThrows(function() { ++o[seven_smi]; }, TypeError);
+  assertThrows(function() { --o[seven_smi]; }, TypeError);
+
+  assertThrows(function() { o[seven_number] = "value"; }, TypeError);
+  assertThrows(function() { o[seven_number] += 10; }, TypeError);
+  assertThrows(function() { o[seven_number] -= 10; }, TypeError);
+  assertThrows(function() { o[seven_number] *= 10; }, TypeError);
+  assertThrows(function() { o[seven_number] /= 10; }, TypeError);
+  assertThrows(function() { o[seven_number]++; }, TypeError);
+  assertThrows(function() { o[seven_number]--; }, TypeError);
+  assertThrows(function() { ++o[seven_number]; }, TypeError);
+  assertThrows(function() { --o[seven_number]; }, TypeError);
+
+  assertThrows(function() { o[seven_symbol] = "value"; }, TypeError);
+  assertThrows(function() { o[seven_symbol] += 10; }, TypeError);
+  assertThrows(function() { o[seven_symbol] -= 10; }, TypeError);
+  assertThrows(function() { o[seven_symbol] *= 10; }, TypeError);
+  assertThrows(function() { o[seven_symbol] /= 10; }, TypeError);
+  assertThrows(function() { o[seven_symbol]++; }, TypeError);
+  assertThrows(function() { o[seven_symbol]--; }, TypeError);
+  assertThrows(function() { ++o[seven_symbol]; }, TypeError);
+  assertThrows(function() { --o[seven_symbol]; }, TypeError);
+
+  assertThrows(function() { o[seven_string] = "value"; }, TypeError);
+  assertThrows(function() { o[seven_string] += 10; }, TypeError);
+  assertThrows(function() { o[seven_string] -= 10; }, TypeError);
+  assertThrows(function() { o[seven_string] *= 10; }, TypeError);
+  assertThrows(function() { o[seven_string] /= 10; }, TypeError);
+  assertThrows(function() { o[seven_string]++; }, TypeError);
+  assertThrows(function() { o[seven_string]--; }, TypeError);
+  assertThrows(function() { ++o[seven_string]; }, TypeError);
+  assertThrows(function() { --o[seven_string]; }, TypeError);
+
+  assertEquals(o[seven_number], 17);
+  assertEquals(o[seven_symbol], 17);
+  assertEquals(o[seven_string], 17);
+})();
+
+
+(function TestAssignmentToReadOnlyLoop() {
+  "use strict";
+
+  var o = {};
+  Object.defineProperty(o, 7, { value: 17 });
+
+  var seven_smi = 7;
+  var seven_number = new Number(7);
+  var seven_symbol = "7";
+  var seven_string = "-7-".substring(1,2);
+
+  for (var i = 0; i < 10; i ++) {
+    assertThrows(function() { o[seven_smi] = "value" }, TypeError);
+    assertThrows(function() { o[seven_number] = "value" }, TypeError);
+    assertThrows(function() { o[seven_symbol] = "value" }, TypeError);
+    assertThrows(function() { o[seven_string] = "value" }, TypeError);
+  }
+
+  assertEquals(o[7], 17);
+})();
+
+
+(function TestAssignmentToStringLength() {
+  "use strict";
+
+  var str_val = "string";
+  var str_obj = new String(str_val);
+  var str_cat = str_val + str_val + str_obj;
+
+  assertThrows(function() { str_val.length = 1; }, TypeError);
+  assertThrows(function() { str_obj.length = 1; }, TypeError);
+  assertThrows(function() { str_cat.length = 1; }, TypeError);
+})();
diff --git a/test/mjsunit/tools/tickprocessor-test-func-info.log b/test/mjsunit/tools/tickprocessor-test-func-info.log
index 29a12f6..755fbb2 100644
--- a/test/mjsunit/tools/tickprocessor-test-func-info.log
+++ b/test/mjsunit/tools/tickprocessor-test-func-info.log
@@ -3,11 +3,9 @@
 shared-library,"ffffe000-fffff000",0xffffe000,0xfffff000
 profiler,"begin",1
 code-creation,Stub,0x424260,348,"CompareStub_GE"
-code-creation,LazyCompile,0x2a8100,18535,"DrawQube 3d-cube.js:188"
-function-creation,0x2d11b8,0x2a8100
-code-creation,LazyCompile,0x480100,3908,"DrawLine 3d-cube.js:17"
-function-creation,0x2d0f7c,0x480100
-tick,0x424284,0xbfffeea0,0x2d0f7c,0,0x2aaaa5
-tick,0x42429f,0xbfffed88,0x2d0f7c,0,0x2aacb4
+code-creation,LazyCompile,0x2a8100,18535,"DrawQube 3d-cube.js:188",0xf43abcac,
+code-creation,LazyCompile,0x480100,3908,"DrawLine 3d-cube.js:17",0xf43abc50,
+tick,0x424284,0xbfffeea0,0x480600,0,0x2aaaa5
+tick,0x42429f,0xbfffed88,0x480600,0,0x2aacb4
 tick,0x48063d,0xbfffec7c,0x2d0f7c,0,0x2aaec6
 profiler,"end"
diff --git a/test/sputnik/README b/test/sputnik/README
index 94c689b..50d721f 100644
--- a/test/sputnik/README
+++ b/test/sputnik/README
@@ -1,6 +1,6 @@
 To run the sputniktests you must check out the test suite from
 googlecode.com.  The test expectations are currently relative to
-version 28.  To get the tests run the following command within
+version 94. To get the tests run the following command within
 v8/test/sputnik/
 
-  svn co http://sputniktests.googlecode.com/svn/trunk/ -r28 sputniktests
+  svn co http://sputniktests.googlecode.com/svn/trunk/ -r94 sputniktests
diff --git a/test/sputnik/sputnik.status b/test/sputnik/sputnik.status
index 966500d..6da87ea 100644
--- a/test/sputnik/sputnik.status
+++ b/test/sputnik/sputnik.status
@@ -102,33 +102,20 @@
 S7.8.4_A7.2_T5: FAIL_OK
 
 # We allow some keywords to be used as identifiers
-S7.5.3_A1.17: FAIL_OK
 S7.5.3_A1.26: FAIL_OK
 S7.5.3_A1.18: FAIL_OK
 S7.5.3_A1.27: FAIL_OK
-S7.5.3_A1.28: FAIL_OK
-S7.5.3_A1.19: FAIL_OK
-S7.5.3_A1.29: FAIL_OK
-S7.5.3_A1.1: FAIL_OK
-S7.5.3_A1.2: FAIL_OK
-S7.5.3_A1.3: FAIL_OK
-S7.5.3_A1.4: FAIL_OK
 S7.5.3_A1.5: FAIL_OK
-S7.5.3_A1.8: FAIL_OK
 S7.5.3_A1.9: FAIL_OK
 S7.5.3_A1.10: FAIL_OK
 S7.5.3_A1.11: FAIL_OK
+# native
+S7.5.3_A1.20: FAIL_OK
 S7.5.3_A1.21: FAIL_OK
-S7.5.3_A1.12: FAIL_OK
-S7.5.3_A1.30: FAIL_OK
-S7.5.3_A1.31: FAIL_OK
-S7.5.3_A1.13: FAIL_OK
 S7.5.3_A1.22: FAIL_OK
 S7.5.3_A1.23: FAIL_OK
-S7.5.3_A1.14: FAIL_OK
 S7.5.3_A1.15: FAIL_OK
 S7.5.3_A1.24: FAIL_OK
-S7.5.3_A1.25: FAIL_OK
 S7.5.3_A1.16: FAIL_OK
 
 # This checks for non-262 behavior
@@ -199,10 +186,40 @@
 S15.1.3.2_A2.5_T1: PASS, SKIP if $mode == debug
 S15.1.3.1_A2.5_T1: PASS, SKIP if $mode == debug
 
+# V8 Bug: http://code.google.com/p/v8/issues/detail?id=1196
+S8.7_A5_T2: FAIL
+
+# V8 bugs: http://code.google.com/p/v8/issues/detail?id=1198
+# V8 should not wrap this when calling builtin functions
+S15.2.4.3_A12: FAIL
+S15.2.4.7_A13: FAIL
+# Object.prototype.toString
+S15.2.4.2_A12: FAIL
+S15.2.4.2_A13: FAIL
+# Object.prototype.toLocaleString
+S15.2.4.3_A13: FAIL
+S15.2.4.4_A13: FAIL
+S15.2.4.4_A12: FAIL
+# Object.prototype.propertyIsEnumerable
+S15.2.4.7_A12: FAIL
+# Object.prototype.hasOwnProperty
+S15.2.4.5_A12: FAIL
+S15.2.4.5_A13: FAIL
+# Object.prototype.isPrototypeOf
+S15.2.4.6_A13: FAIL
+S15.2.4.6_A12: FAIL
+
+# Invalid test case (recent change adding var changes semantics)
+S8.3_A1_T1: FAIL
+# Test bug: http://code.google.com/p/sputniktests/issues/detail?id=35
+S15.5.4.8_A1_T1: FAIL
+# Invalid test case (recent change adding var changes semantics)
+S15.3_A3_T1: FAIL
+# Invalid test case (recent change adding var changes semantics)
+S15.3_A3_T3: FAIL
 
 # These tests fail because we had to add bugs to be compatible with JSC.  See
 # http://code.google.com/p/chromium/issues/detail?id=1717
-S15.4.4_A1.1_T2: FAIL_OK
 S15.5.4.1_A1_T2: FAIL_OK
 S15.5.4_A1: FAIL_OK
 S15.5.4_A3: FAIL_OK
diff --git a/test/sputnik/testcfg.py b/test/sputnik/testcfg.py
index f7a5edc..31e4b22 100644
--- a/test/sputnik/testcfg.py
+++ b/test/sputnik/testcfg.py
@@ -88,7 +88,8 @@
     sys.path.append(modroot)
     import sputnik
     globals()['sputnik'] = sputnik
-    test_suite = sputnik.TestSuite(testroot)
+    # Do not run strict mode tests yet. TODO(mmaly)
+    test_suite = sputnik.TestSuite(testroot, False)
     test_suite.Validate()
     tests = test_suite.EnumerateTests([])
     result = []
diff --git a/tools/disasm.py b/tools/disasm.py
new file mode 100644
index 0000000..c326382
--- /dev/null
+++ b/tools/disasm.py
@@ -0,0 +1,92 @@
+#!/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.
+
+import os
+import re
+import subprocess
+import tempfile
+
+
+# Avoid using the slow (google-specific) wrapper around objdump.
+OBJDUMP_BIN = "/usr/bin/objdump"
+if not os.path.exists(OBJDUMP_BIN):
+  OBJDUMP_BIN = "objdump"
+
+
+_COMMON_DISASM_OPTIONS = ["-M", "intel-mnemonic", "-C"]
+
+_DISASM_HEADER_RE = re.compile(r"[a-f0-9]+\s+<.*:$")
+_DISASM_LINE_RE = re.compile(r"\s*([a-f0-9]+):\s*(\S.*)")
+
+# Keys must match constants in Logger::LogCodeInfo.
+_ARCH_MAP = {
+  "ia32": "-m i386",
+  "x64": "-m i386 -M x86-64",
+  "arm": "-m arm"  # Not supported by our objdump build.
+}
+
+
+def GetDisasmLines(filename, offset, size, arch, inplace):
+  tmp_name = None
+  if not inplace:
+    # Create a temporary file containing a copy of the code.
+    assert arch in _ARCH_MAP, "Unsupported architecture '%s'" % arch
+    arch_flags = _ARCH_MAP[arch]
+    tmp_name = tempfile.mktemp(".v8code")
+    command = "dd if=%s of=%s bs=1 count=%d skip=%d && " \
+              "%s %s -D -b binary %s %s" % (
+      filename, tmp_name, size, offset,
+      OBJDUMP_BIN, ' '.join(_COMMON_DISASM_OPTIONS), arch_flags,
+      tmp_name)
+  else:
+    command = "%s %s --start-address=%d --stop-address=%d -d %s " % (
+      OBJDUMP_BIN, ' '.join(_COMMON_DISASM_OPTIONS),
+      offset,
+      offset + size,
+      filename)
+  process = subprocess.Popen(command,
+                             shell=True,
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.STDOUT)
+  out, err = process.communicate()
+  lines = out.split("\n")
+  header_line = 0
+  for i, line in enumerate(lines):
+    if _DISASM_HEADER_RE.match(line):
+      header_line = i
+      break
+  if tmp_name:
+    os.unlink(tmp_name)
+  split_lines = []
+  for line in lines[header_line + 1:]:
+    match = _DISASM_LINE_RE.match(line)
+    if match:
+      line_address = int(match.group(1), 16)
+      split_lines.append((line_address, match.group(2)))
+  return split_lines
diff --git a/tools/grokdump.py b/tools/grokdump.py
new file mode 100755
index 0000000..de681b2
--- /dev/null
+++ b/tools/grokdump.py
@@ -0,0 +1,840 @@
+#!/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.
+
+import ctypes
+import mmap
+import optparse
+import os
+import disasm
+import sys
+import types
+import codecs
+import re
+
+
+USAGE="""usage: %prog [OPTION]...
+
+Minidump analyzer.
+
+Shows the processor state at the point of exception including the
+stack of the active thread and the referenced objects in the V8
+heap. Code objects are disassembled and the addresses linked from the
+stack (pushed return addresses) are marked with "=>".
+
+
+Examples:
+  $ %prog 12345678-1234-1234-1234-123456789abcd-full.dmp
+"""
+
+DEBUG=False
+
+
+def DebugPrint(s):
+  if not DEBUG: return
+  print s
+
+
+class Descriptor(object):
+  """Descriptor of a structure in a memory."""
+
+  def __init__(self, fields):
+    self.fields = fields
+    self.is_flexible = False
+    for _, type_or_func in fields:
+      if isinstance(type_or_func, types.FunctionType):
+        self.is_flexible = True
+        break
+    if not self.is_flexible:
+      self.ctype = Descriptor._GetCtype(fields)
+      self.size = ctypes.sizeof(self.ctype)
+
+  def Read(self, memory, offset):
+    if self.is_flexible:
+      fields_copy = self.fields[:]
+      last = 0
+      for name, type_or_func in fields_copy:
+        if isinstance(type_or_func, types.FunctionType):
+          partial_ctype = Descriptor._GetCtype(fields_copy[:last])
+          partial_object = partial_ctype.from_buffer(memory, offset)
+          type = type_or_func(partial_object)
+          if type is not None:
+            fields_copy[last] = (name, type)
+            last += 1
+        else:
+          last += 1
+      complete_ctype = Descriptor._GetCtype(fields_copy[:last])
+    else:
+      complete_ctype = self.ctype
+    return complete_ctype.from_buffer(memory, offset)
+
+  @staticmethod
+  def _GetCtype(fields):
+    class Raw(ctypes.Structure):
+      _fields_ = fields
+      _pack_ = 1
+
+      def __str__(self):
+        return "{" + ", ".join("%s: %s" % (field, self.__getattribute__(field))
+                               for field, _ in Raw._fields_) + "}"
+    return Raw
+
+
+# Set of structures and constants that describe the layout of minidump
+# files. Based on MSDN and Google Breakpad.
+
+MINIDUMP_HEADER = Descriptor([
+  ("signature", ctypes.c_uint32),
+  ("version", ctypes.c_uint32),
+  ("stream_count", ctypes.c_uint32),
+  ("stream_directories_rva", ctypes.c_uint32),
+  ("checksum", ctypes.c_uint32),
+  ("time_date_stampt", ctypes.c_uint32),
+  ("flags", ctypes.c_uint64)
+])
+
+MINIDUMP_LOCATION_DESCRIPTOR = Descriptor([
+  ("data_size", ctypes.c_uint32),
+  ("rva", ctypes.c_uint32)
+])
+
+MINIDUMP_DIRECTORY = Descriptor([
+  ("stream_type", ctypes.c_uint32),
+  ("location", MINIDUMP_LOCATION_DESCRIPTOR.ctype)
+])
+
+MD_EXCEPTION_MAXIMUM_PARAMETERS = 15
+
+MINIDUMP_EXCEPTION = Descriptor([
+  ("code", ctypes.c_uint32),
+  ("flags", ctypes.c_uint32),
+  ("record", ctypes.c_uint64),
+  ("address", ctypes.c_uint64),
+  ("parameter_count", ctypes.c_uint32),
+  ("unused_alignment", ctypes.c_uint32),
+  ("information", ctypes.c_uint64 * MD_EXCEPTION_MAXIMUM_PARAMETERS)
+])
+
+MINIDUMP_EXCEPTION_STREAM = Descriptor([
+  ("thread_id", ctypes.c_uint32),
+  ("unused_alignment", ctypes.c_uint32),
+  ("exception", MINIDUMP_EXCEPTION.ctype),
+  ("thread_context", MINIDUMP_LOCATION_DESCRIPTOR.ctype)
+])
+
+# Stream types.
+MD_UNUSED_STREAM = 0
+MD_RESERVED_STREAM_0 = 1
+MD_RESERVED_STREAM_1 = 2
+MD_THREAD_LIST_STREAM = 3
+MD_MODULE_LIST_STREAM = 4
+MD_MEMORY_LIST_STREAM = 5
+MD_EXCEPTION_STREAM = 6
+MD_SYSTEM_INFO_STREAM = 7
+MD_THREAD_EX_LIST_STREAM = 8
+MD_MEMORY_64_LIST_STREAM = 9
+MD_COMMENT_STREAM_A = 10
+MD_COMMENT_STREAM_W = 11
+MD_HANDLE_DATA_STREAM = 12
+MD_FUNCTION_TABLE_STREAM = 13
+MD_UNLOADED_MODULE_LIST_STREAM = 14
+MD_MISC_INFO_STREAM = 15
+MD_MEMORY_INFO_LIST_STREAM = 16
+MD_THREAD_INFO_LIST_STREAM = 17
+MD_HANDLE_OPERATION_LIST_STREAM = 18
+
+MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE = 80
+
+MINIDUMP_FLOATING_SAVE_AREA_X86 = Descriptor([
+  ("control_word", ctypes.c_uint32),
+  ("status_word", ctypes.c_uint32),
+  ("tag_word", ctypes.c_uint32),
+  ("error_offset", ctypes.c_uint32),
+  ("error_selector", ctypes.c_uint32),
+  ("data_offset", ctypes.c_uint32),
+  ("data_selector", ctypes.c_uint32),
+  ("register_area", ctypes.c_uint8 * MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE),
+  ("cr0_npx_state", ctypes.c_uint32)
+])
+
+MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE = 512
+
+# Context flags.
+MD_CONTEXT_X86 = 0x00010000
+MD_CONTEXT_X86_CONTROL = (MD_CONTEXT_X86 | 0x00000001)
+MD_CONTEXT_X86_INTEGER = (MD_CONTEXT_X86 | 0x00000002)
+MD_CONTEXT_X86_SEGMENTS = (MD_CONTEXT_X86 | 0x00000004)
+MD_CONTEXT_X86_FLOATING_POINT = (MD_CONTEXT_X86 | 0x00000008)
+MD_CONTEXT_X86_DEBUG_REGISTERS = (MD_CONTEXT_X86 | 0x00000010)
+MD_CONTEXT_X86_EXTENDED_REGISTERS = (MD_CONTEXT_X86 | 0x00000020)
+
+def EnableOnFlag(type, flag):
+  return lambda o: [None, type][int((o.context_flags & flag) != 0)]
+
+MINIDUMP_CONTEXT_X86 = Descriptor([
+  ("context_flags", ctypes.c_uint32),
+  # MD_CONTEXT_X86_DEBUG_REGISTERS.
+  ("dr0", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
+  ("dr1", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
+  ("dr2", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
+  ("dr3", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
+  ("dr6", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
+  ("dr7", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
+  # MD_CONTEXT_X86_FLOATING_POINT.
+  ("float_save", EnableOnFlag(MINIDUMP_FLOATING_SAVE_AREA_X86.ctype,
+                              MD_CONTEXT_X86_FLOATING_POINT)),
+  # MD_CONTEXT_X86_SEGMENTS.
+  ("gs", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_SEGMENTS)),
+  ("fs", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_SEGMENTS)),
+  ("es", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_SEGMENTS)),
+  ("ds", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_SEGMENTS)),
+  # MD_CONTEXT_X86_INTEGER.
+  ("edi", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
+  ("esi", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
+  ("ebx", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
+  ("edx", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
+  ("ecx", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
+  ("eax", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
+  # MD_CONTEXT_X86_CONTROL.
+  ("ebp", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
+  ("eip", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
+  ("cs", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
+  ("eflags", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
+  ("esp", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
+  ("ss", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
+  # MD_CONTEXT_X86_EXTENDED_REGISTERS.
+  ("extended_registers",
+   EnableOnFlag(ctypes.c_uint8 * MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE,
+                MD_CONTEXT_X86_EXTENDED_REGISTERS))
+])
+
+MINIDUMP_MEMORY_DESCRIPTOR = Descriptor([
+  ("start", ctypes.c_uint64),
+  ("memory", MINIDUMP_LOCATION_DESCRIPTOR.ctype)
+])
+
+MINIDUMP_MEMORY_DESCRIPTOR64 = Descriptor([
+  ("start", ctypes.c_uint64),
+  ("size", ctypes.c_uint64)
+])
+
+MINIDUMP_MEMORY_LIST = Descriptor([
+  ("range_count", ctypes.c_uint32),
+  ("ranges", lambda m: MINIDUMP_MEMORY_DESCRIPTOR.ctype * m.range_count)
+])
+
+MINIDUMP_MEMORY_LIST64 = Descriptor([
+  ("range_count", ctypes.c_uint64),
+  ("base_rva", ctypes.c_uint64),
+  ("ranges", lambda m: MINIDUMP_MEMORY_DESCRIPTOR64.ctype * m.range_count)
+])
+
+MINIDUMP_THREAD = Descriptor([
+  ("id", ctypes.c_uint32),
+  ("suspend_count", ctypes.c_uint32),
+  ("priority_class", ctypes.c_uint32),
+  ("priority", ctypes.c_uint32),
+  ("ted", ctypes.c_uint64),
+  ("stack", MINIDUMP_MEMORY_DESCRIPTOR.ctype),
+  ("context", MINIDUMP_LOCATION_DESCRIPTOR.ctype)
+])
+
+MINIDUMP_THREAD_LIST = Descriptor([
+  ("thread_count", ctypes.c_uint32),
+  ("threads", lambda t: MINIDUMP_THREAD.ctype * t.thread_count)
+])
+
+
+class MinidumpReader(object):
+  """Minidump (.dmp) reader."""
+
+  _HEADER_MAGIC = 0x504d444d
+
+  def __init__(self, options, minidump_name):
+    self.minidump_name = minidump_name
+    self.minidump_file = open(minidump_name, "r")
+    self.minidump = mmap.mmap(self.minidump_file.fileno(), 0, mmap.MAP_PRIVATE)
+    self.header = MINIDUMP_HEADER.Read(self.minidump, 0)
+    if self.header.signature != MinidumpReader._HEADER_MAGIC:
+      print >>sys.stderr, "Warning: unsupported minidump header magic"
+    DebugPrint(self.header)
+    directories = []
+    offset = self.header.stream_directories_rva
+    for _ in xrange(self.header.stream_count):
+      directories.append(MINIDUMP_DIRECTORY.Read(self.minidump, offset))
+      offset += MINIDUMP_DIRECTORY.size
+    self.exception = None
+    self.exception_context = None
+    self.memory_list = None
+    self.thread_map = {}
+    for d in directories:
+      DebugPrint(d)
+      # TODO(vitalyr): extract system info including CPU features.
+      if d.stream_type == MD_EXCEPTION_STREAM:
+        self.exception = MINIDUMP_EXCEPTION_STREAM.Read(
+          self.minidump, d.location.rva)
+        DebugPrint(self.exception)
+        self.exception_context = MINIDUMP_CONTEXT_X86.Read(
+          self.minidump, self.exception.thread_context.rva)
+        DebugPrint(self.exception_context)
+      elif d.stream_type == MD_THREAD_LIST_STREAM:
+        thread_list = MINIDUMP_THREAD_LIST.Read(self.minidump, d.location.rva)
+        assert ctypes.sizeof(thread_list) == d.location.data_size
+        DebugPrint(thread_list)
+        for thread in thread_list.threads:
+          DebugPrint(thread)
+          self.thread_map[thread.id] = thread
+      elif d.stream_type == MD_MEMORY_LIST_STREAM:
+        print >>sys.stderr, "Warning: not a full minidump"
+        ml = MINIDUMP_MEMORY_LIST.Read(self.minidump, d.location.rva)
+        DebugPrint(ml)
+        for m in ml.ranges:
+          DebugPrint(m)
+      elif d.stream_type == MD_MEMORY_64_LIST_STREAM:
+        assert self.memory_list is None
+        self.memory_list = MINIDUMP_MEMORY_LIST64.Read(
+          self.minidump, d.location.rva)
+        assert ctypes.sizeof(self.memory_list) == d.location.data_size
+        DebugPrint(self.memory_list)
+
+  def IsValidAddress(self, address):
+    return self.FindLocation(address) is not None
+
+  def ReadU8(self, address):
+    location = self.FindLocation(address)
+    return ctypes.c_uint8.from_buffer(self.minidump, location).value
+
+  def ReadU32(self, address):
+    location = self.FindLocation(address)
+    return ctypes.c_uint32.from_buffer(self.minidump, location).value
+
+  def ReadBytes(self, address, size):
+    location = self.FindLocation(address)
+    return self.minidump[location:location + size]
+
+  def FindLocation(self, address):
+    # TODO(vitalyr): only works for full minidumps (...64 structure variants).
+    offset = 0
+    for r in self.memory_list.ranges:
+      if r.start <= address < r.start + r.size:
+        return self.memory_list.base_rva + offset + address - r.start
+      offset += r.size
+    return None
+
+  def GetDisasmLines(self, address, size):
+    location = self.FindLocation(address)
+    if location is None: return []
+    return disasm.GetDisasmLines(self.minidump_name,
+                                 location,
+                                 size,
+                                 "ia32",
+                                 False)
+
+
+  def Dispose(self):
+    self.minidump.close()
+    self.minidump_file.close()
+
+
+# List of V8 instance types. Obtained by adding the code below to any .cc file.
+#
+# #define DUMP_TYPE(T) printf("%d: \"%s\",\n", T, #T);
+# struct P {
+#   P() {
+#     printf("{\n");
+#     INSTANCE_TYPE_LIST(DUMP_TYPE)
+#     printf("}\n");
+#   }
+# };
+# 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: "PROXY_TYPE",
+  134: "BYTE_ARRAY_TYPE",
+  135: "PIXEL_ARRAY_TYPE",
+  136: "EXTERNAL_BYTE_ARRAY_TYPE",
+  137: "EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE",
+  138: "EXTERNAL_SHORT_ARRAY_TYPE",
+  139: "EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE",
+  140: "EXTERNAL_INT_ARRAY_TYPE",
+  141: "EXTERNAL_UNSIGNED_INT_ARRAY_TYPE",
+  142: "EXTERNAL_FLOAT_ARRAY_TYPE",
+  143: "FILLER_TYPE",
+  144: "ACCESSOR_INFO_TYPE",
+  145: "ACCESS_CHECK_INFO_TYPE",
+  146: "INTERCEPTOR_INFO_TYPE",
+  147: "CALL_HANDLER_INFO_TYPE",
+  148: "FUNCTION_TEMPLATE_INFO_TYPE",
+  149: "OBJECT_TEMPLATE_INFO_TYPE",
+  150: "SIGNATURE_INFO_TYPE",
+  151: "TYPE_SWITCH_INFO_TYPE",
+  152: "SCRIPT_TYPE",
+  153: "CODE_CACHE_TYPE",
+  156: "FIXED_ARRAY_TYPE",
+  157: "SHARED_FUNCTION_INFO_TYPE",
+  158: "JS_MESSAGE_OBJECT_TYPE",
+  159: "JS_VALUE_TYPE",
+  160: "JS_OBJECT_TYPE",
+  161: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
+  162: "JS_GLOBAL_OBJECT_TYPE",
+  163: "JS_BUILTINS_OBJECT_TYPE",
+  164: "JS_GLOBAL_PROXY_TYPE",
+  165: "JS_ARRAY_TYPE",
+  166: "JS_REGEXP_TYPE",
+  167: "JS_FUNCTION_TYPE",
+  154: "DEBUG_INFO_TYPE",
+  155: "BREAK_POINT_INFO_TYPE",
+}
+
+
+class Printer(object):
+  """Printer with indentation support."""
+
+  def __init__(self):
+    self.indent = 0
+
+  def Indent(self):
+    self.indent += 2
+
+  def Dedent(self):
+    self.indent -= 2
+
+  def Print(self, string):
+    print "%s%s" % (self._IndentString(), string)
+
+  def PrintLines(self, lines):
+    indent = self._IndentString()
+    print "\n".join("%s%s" % (indent, line) for line in lines)
+
+  def _IndentString(self):
+    return self.indent * " "
+
+
+ADDRESS_RE = re.compile(r"0x[0-9a-fA-F]+")
+
+
+def FormatDisasmLine(start, heap, line):
+  line_address = start + line[0]
+  stack_slot = heap.stack_map.get(line_address)
+  marker = "  "
+  if stack_slot:
+    marker = "=>"
+  code = AnnotateAddresses(heap, line[1])
+  return "%s%08x %08x: %s" % (marker, line_address, line[0], code)
+
+
+def AnnotateAddresses(heap, line):
+  extra = []
+  for m in ADDRESS_RE.finditer(line):
+    maybe_address = int(m.group(0), 16)
+    object = heap.FindObject(maybe_address)
+    if not object: continue
+    extra.append(str(object))
+  if len(extra) == 0: return line
+  return "%s  ;; %s" % (line, ", ".join(extra))
+
+
+class HeapObject(object):
+  def __init__(self, heap, map, address):
+    self.heap = heap
+    self.map = map
+    self.address = address
+
+  def Is(self, cls):
+    return isinstance(self, cls)
+
+  def Print(self, p):
+    p.Print(str(self))
+
+  def __str__(self):
+    return "HeapObject(%08x, %s)" % (self.address,
+                                     INSTANCE_TYPES[self.map.instance_type])
+
+  def ObjectField(self, offset):
+    field_value = self.heap.reader.ReadU32(self.address + offset)
+    return self.heap.FindObjectOrSmi(field_value)
+
+  def SmiField(self, offset):
+    field_value = self.heap.reader.ReadU32(self.address + offset)
+    assert (field_value & 1) == 0
+    return field_value / 2
+
+
+class Map(HeapObject):
+  INSTANCE_TYPE_OFFSET = 8
+
+  def __init__(self, heap, map, address):
+    HeapObject.__init__(self, heap, map, address)
+    self.instance_type = \
+        heap.reader.ReadU8(self.address + Map.INSTANCE_TYPE_OFFSET)
+
+
+class String(HeapObject):
+  LENGTH_OFFSET = 4
+
+  def __init__(self, heap, map, address):
+    HeapObject.__init__(self, heap, map, address)
+    self.length = self.SmiField(String.LENGTH_OFFSET)
+
+  def GetChars(self):
+    return "?string?"
+
+  def Print(self, p):
+    p.Print(str(self))
+
+  def __str__(self):
+    return "\"%s\"" % self.GetChars()
+
+
+class SeqString(String):
+  CHARS_OFFSET = 12
+
+  def __init__(self, heap, map, address):
+    String.__init__(self, heap, map, address)
+    self.chars = heap.reader.ReadBytes(self.address + SeqString.CHARS_OFFSET,
+                                       self.length)
+
+  def GetChars(self):
+    return self.chars
+
+
+class ExternalString(String):
+  RESOURCE_OFFSET = 12
+
+  WEBKIT_RESOUCE_STRING_IMPL_OFFSET = 4
+  WEBKIT_STRING_IMPL_CHARS_OFFSET = 8
+
+  def __init__(self, heap, map, address):
+    String.__init__(self, heap, map, address)
+    reader = heap.reader
+    self.resource = \
+        reader.ReadU32(self.address + ExternalString.RESOURCE_OFFSET)
+    self.chars = "?external string?"
+    if not reader.IsValidAddress(self.resource): return
+    string_impl_address = self.resource + \
+        ExternalString.WEBKIT_RESOUCE_STRING_IMPL_OFFSET
+    if not reader.IsValidAddress(string_impl_address): return
+    string_impl = reader.ReadU32(string_impl_address)
+    chars_ptr_address = string_impl + \
+        ExternalString.WEBKIT_STRING_IMPL_CHARS_OFFSET
+    if not reader.IsValidAddress(chars_ptr_address): return
+    chars_ptr = reader.ReadU32(chars_ptr_address)
+    if not reader.IsValidAddress(chars_ptr): return
+    raw_chars = reader.ReadBytes(chars_ptr, 2 * self.length)
+    self.chars = codecs.getdecoder("utf16")(raw_chars)[0]
+
+  def GetChars(self):
+    return self.chars
+
+
+class ConsString(String):
+  LEFT_OFFSET = 12
+  RIGHT_OFFSET = 16
+
+  def __init__(self, heap, map, address):
+    String.__init__(self, heap, map, address)
+    self.left = self.ObjectField(ConsString.LEFT_OFFSET)
+    self.right = self.ObjectField(ConsString.RIGHT_OFFSET)
+
+  def GetChars(self):
+    return self.left.GetChars() + self.right.GetChars()
+
+
+class Oddball(HeapObject):
+  TO_STRING_OFFSET = 4
+
+  def __init__(self, heap, map, address):
+    HeapObject.__init__(self, heap, map, address)
+    self.to_string = self.ObjectField(Oddball.TO_STRING_OFFSET)
+
+  def Print(self, p):
+    p.Print(str(self))
+
+  def __str__(self):
+    return "<%s>" % self.to_string.GetChars()
+
+
+class FixedArray(HeapObject):
+  LENGTH_OFFSET = 4
+  ELEMENTS_OFFSET = 8
+
+  def __init__(self, heap, map, address):
+    HeapObject.__init__(self, heap, map, address)
+    self.length = self.SmiField(FixedArray.LENGTH_OFFSET)
+
+  def Print(self, p):
+    p.Print("FixedArray(%08x) {" % self.address)
+    p.Indent()
+    p.Print("length: %d" % self.length)
+    for i in xrange(self.length):
+      offset = FixedArray.ELEMENTS_OFFSET + 4 * i
+      p.Print("[%08d] = %s" % (i, self.ObjectField(offset)))
+    p.Dedent()
+    p.Print("}")
+
+  def __str__(self):
+    return "FixedArray(%08x, length=%d)" % (self.address, self.length)
+
+
+class JSFunction(HeapObject):
+  CODE_ENTRY_OFFSET = 12
+  SHARED_OFFSET = 20
+
+  def __init__(self, heap, map, address):
+    HeapObject.__init__(self, heap, map, address)
+    code_entry = \
+        heap.reader.ReadU32(self.address + JSFunction.CODE_ENTRY_OFFSET)
+    self.code = heap.FindObject(code_entry - Code.ENTRY_OFFSET + 1)
+    self.shared = self.ObjectField(JSFunction.SHARED_OFFSET)
+
+  def Print(self, p):
+    source = "\n".join("  %s" % line for line in self._GetSource().split("\n"))
+    p.Print("JSFunction(%08x) {" % self.address)
+    p.Indent()
+    p.Print("inferred name: %s" % self.shared.inferred_name)
+    if self.shared.script.Is(Script) and self.shared.script.name.Is(String):
+      p.Print("script name: %s" % self.shared.script.name)
+    p.Print("source:")
+    p.PrintLines(self._GetSource().split("\n"))
+    p.Print("code:")
+    self.code.Print(p)
+    if self.code != self.shared.code:
+      p.Print("unoptimized code:")
+      self.shared.code.Print(p)
+    p.Dedent()
+    p.Print("}")
+
+  def __str__(self):
+    inferred_name = ""
+    if self.shared.Is(SharedFunctionInfo):
+      inferred_name = self.shared.inferred_name
+    return "JSFunction(%08x, %s)" % (self.address, inferred_name)
+
+  def _GetSource(self):
+    source = "?source?"
+    start = self.shared.start_position
+    end = self.shared.end_position
+    if not self.shared.script.Is(Script): return source
+    script_source = self.shared.script.source
+    if not script_source.Is(String): return source
+    return script_source.GetChars()[start:end]
+
+
+class SharedFunctionInfo(HeapObject):
+  CODE_OFFSET = 2 * 4
+  SCRIPT_OFFSET = 7 * 4
+  INFERRED_NAME_OFFSET = 9 * 4
+  START_POSITION_AND_TYPE_OFFSET = 17 * 4
+  END_POSITION_OFFSET = 18 * 4
+
+  def __init__(self, heap, map, address):
+    HeapObject.__init__(self, heap, map, address)
+    self.code = self.ObjectField(SharedFunctionInfo.CODE_OFFSET)
+    self.script = self.ObjectField(SharedFunctionInfo.SCRIPT_OFFSET)
+    self.inferred_name = \
+        self.ObjectField(SharedFunctionInfo.INFERRED_NAME_OFFSET)
+    start_position_and_type = \
+        self.SmiField(SharedFunctionInfo.START_POSITION_AND_TYPE_OFFSET)
+    self.start_position = start_position_and_type >> 2
+    self.end_position = self.SmiField(SharedFunctionInfo.END_POSITION_OFFSET)
+
+
+class Script(HeapObject):
+  SOURCE_OFFSET = 4
+  NAME_OFFSET = 8
+
+  def __init__(self, heap, map, address):
+    HeapObject.__init__(self, heap, map, address)
+    self.source = self.ObjectField(Script.SOURCE_OFFSET)
+    self.name = self.ObjectField(Script.NAME_OFFSET)
+
+
+class Code(HeapObject):
+  INSTRUCTION_SIZE_OFFSET = 4
+  ENTRY_OFFSET = 32
+
+  def __init__(self, heap, map, address):
+    HeapObject.__init__(self, heap, map, address)
+    self.entry = self.address + Code.ENTRY_OFFSET
+    self.instruction_size = \
+        heap.reader.ReadU32(self.address + Code.INSTRUCTION_SIZE_OFFSET)
+
+  def Print(self, p):
+    lines = self.heap.reader.GetDisasmLines(self.entry, self.instruction_size)
+    p.Print("Code(%08x) {" % self.address)
+    p.Indent()
+    p.Print("instruction_size: %d" % self.instruction_size)
+    p.PrintLines(self._FormatLine(line) for line in lines)
+    p.Dedent()
+    p.Print("}")
+
+  def _FormatLine(self, line):
+    return FormatDisasmLine(self.entry, self.heap, line)
+
+
+class V8Heap(object):
+  CLASS_MAP = {
+    "SYMBOL_TYPE": SeqString,
+    "ASCII_SYMBOL_TYPE": SeqString,
+    "CONS_SYMBOL_TYPE": ConsString,
+    "CONS_ASCII_SYMBOL_TYPE": ConsString,
+    "EXTERNAL_SYMBOL_TYPE": ExternalString,
+    "EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE": ExternalString,
+    "EXTERNAL_ASCII_SYMBOL_TYPE": ExternalString,
+    "STRING_TYPE": SeqString,
+    "ASCII_STRING_TYPE": SeqString,
+    "CONS_STRING_TYPE": ConsString,
+    "CONS_ASCII_STRING_TYPE": ConsString,
+    "EXTERNAL_STRING_TYPE": ExternalString,
+    "EXTERNAL_STRING_WITH_ASCII_DATA_TYPE": ExternalString,
+    "EXTERNAL_ASCII_STRING_TYPE": ExternalString,
+
+    "MAP_TYPE": Map,
+    "ODDBALL_TYPE": Oddball,
+    "FIXED_ARRAY_TYPE": FixedArray,
+    "JS_FUNCTION_TYPE": JSFunction,
+    "SHARED_FUNCTION_INFO_TYPE": SharedFunctionInfo,
+    "SCRIPT_TYPE": Script,
+    "CODE_TYPE": Code
+  }
+
+  def __init__(self, reader, stack_map):
+    self.reader = reader
+    self.stack_map = stack_map
+    self.objects = {}
+
+  def FindObjectOrSmi(self, tagged_address):
+    if (tagged_address & 1) == 0: return tagged_address / 2
+    return self.FindObject(tagged_address)
+
+  def FindObject(self, tagged_address):
+    if tagged_address in self.objects:
+      return self.objects[tagged_address]
+    if (tagged_address & 1) != 1: return None
+    address = tagged_address - 1
+    if not self.reader.IsValidAddress(address): return None
+    map_tagged_address = self.reader.ReadU32(address)
+    if tagged_address == map_tagged_address:
+      # Meta map?
+      meta_map = Map(self, None, address)
+      instance_type_name = INSTANCE_TYPES.get(meta_map.instance_type)
+      if instance_type_name != "MAP_TYPE": return None
+      meta_map.map = meta_map
+      object = meta_map
+    else:
+      map = self.FindObject(map_tagged_address)
+      if map is None: return None
+      instance_type_name = INSTANCE_TYPES.get(map.instance_type)
+      if instance_type_name is None: return None
+      cls = V8Heap.CLASS_MAP.get(instance_type_name, HeapObject)
+      object = cls(self, map, address)
+    self.objects[tagged_address] = object
+    return object
+
+
+EIP_PROXIMITY = 64
+
+
+def AnalyzeMinidump(options, minidump_name):
+  reader = MinidumpReader(options, minidump_name)
+  DebugPrint("========================================")
+  if reader.exception is None:
+    print "Minidump has no exception info"
+    return
+  print "Exception info:"
+  exception_thread = reader.thread_map[reader.exception.thread_id]
+  print "  thread id: %d" % exception_thread.id
+  print "  code: %08X" % reader.exception.exception.code
+  print "  context:"
+  print "    eax: %08x" % reader.exception_context.eax
+  print "    ebx: %08x" % reader.exception_context.ebx
+  print "    ecx: %08x" % reader.exception_context.ecx
+  print "    edx: %08x" % reader.exception_context.edx
+  print "    edi: %08x" % reader.exception_context.edi
+  print "    esi: %08x" % reader.exception_context.esi
+  print "    ebp: %08x" % reader.exception_context.ebp
+  print "    esp: %08x" % reader.exception_context.esp
+  print "    eip: %08x" % reader.exception_context.eip
+  # TODO(vitalyr): decode eflags.
+  print "    eflags: %s" % bin(reader.exception_context.eflags)[2:]
+  print
+
+  stack_bottom = exception_thread.stack.start + \
+      exception_thread.stack.memory.data_size
+  stack_map = {reader.exception_context.eip: -1}
+  for slot in xrange(reader.exception_context.esp, stack_bottom, 4):
+    maybe_address = reader.ReadU32(slot)
+    if not maybe_address in stack_map:
+      stack_map[maybe_address] = slot
+  heap = V8Heap(reader, stack_map)
+
+  print "Disassembly around exception.eip:"
+  start = reader.exception_context.eip - EIP_PROXIMITY
+  lines = reader.GetDisasmLines(start, 2 * EIP_PROXIMITY)
+  for line in lines:
+    print FormatDisasmLine(start, heap, line)
+  print
+
+  print "Annotated stack (from exception.esp to bottom):"
+  for slot in xrange(reader.exception_context.esp, stack_bottom, 4):
+    maybe_address = reader.ReadU32(slot)
+    heap_object = heap.FindObject(maybe_address)
+    print "%08x: %08x" % (slot, maybe_address)
+    if heap_object:
+      heap_object.Print(Printer())
+      print
+
+  reader.Dispose()
+
+
+if __name__ == "__main__":
+  parser = optparse.OptionParser(USAGE)
+  options, args = parser.parse_args()
+  if len(args) != 1:
+    parser.print_help()
+    sys.exit(1)
+  AnalyzeMinidump(options, args[0])
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 1518567..6dab52d 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -598,6 +598,8 @@
                 '../../src/arm/lithium-arm.h',
                 '../../src/arm/lithium-codegen-arm.cc',
                 '../../src/arm/lithium-codegen-arm.h',
+                '../../src/arm/lithium-gap-resolver-arm.cc',
+                '../../src/arm/lithium-gap-resolver-arm.h',
                 '../../src/arm/macro-assembler-arm.cc',
                 '../../src/arm/macro-assembler-arm.h',
                 '../../src/arm/regexp-macro-assembler-arm.cc',
diff --git a/tools/linux-tick-processor.py b/tools/linux-tick-processor.py
deleted file mode 100755
index 67c3b95..0000000
--- a/tools/linux-tick-processor.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2008 the V8 project authors. All rights reserved.
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-#       copyright notice, this list of conditions and the following
-#       disclaimer in the documentation and/or other materials provided
-#       with the distribution.
-#     * Neither the name of Google Inc. nor the names of its
-#       contributors may be used to endorse or promote products derived
-#       from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# Usage: process-ticks.py <logfile>
-# Where <logfile> is the log file name (eg, v8.log).
-
-import subprocess, re, sys, tickprocessor
-
-class LinuxTickProcessor(tickprocessor.TickProcessor):
-
-  def ParseVMSymbols(self, filename, start, end):
-    """Extract symbols and add them to the cpp entries."""
-    # Extra both dynamic and non-dynamic symbols.
-    command = 'nm -C -n "%s"; nm -C -n -D "%s"' % (filename, filename)
-    process = subprocess.Popen(command, shell=True,
-                               stdout=subprocess.PIPE,
-                               stderr=subprocess.STDOUT)
-    pipe = process.stdout
-    try:
-      for line in pipe:
-        row = re.match('^([0-9a-fA-F]{8}) . (.*)$', line)
-        if row:
-          addr = int(row.group(1), 16)
-          if addr < start and addr < end - start:
-            addr += start
-          self.cpp_entries.Insert(addr, tickprocessor.CodeEntry(addr, row.group(2)))
-    finally:
-      pipe.close()
-
-
-class LinuxCmdLineProcessor(tickprocessor.CmdLineProcessor):
-
-  def GetRequiredArgsNames(self):
-    return 'log_file'
-
-  def ProcessRequiredArgs(self, args):
-    if len(args) != 1:
-      self.PrintUsageAndExit()
-    else:
-      self.log_file = args[0]
-
-
-def Main():
-  cmdline_processor = LinuxCmdLineProcessor()
-  cmdline_processor.ProcessArguments()
-  tick_processor = LinuxTickProcessor()
-  cmdline_processor.RunLogfileProcessing(tick_processor)
-  tick_processor.PrintResults()
-
-
-if __name__ == '__main__':
-  Main()
diff --git a/tools/ll_prof.py b/tools/ll_prof.py
index 8390d4a..7f12c13 100755
--- a/tools/ll_prof.py
+++ b/tools/ll_prof.py
@@ -30,13 +30,13 @@
 import bisect
 import collections
 import ctypes
+import disasm
 import mmap
 import optparse
 import os
 import re
 import subprocess
 import sys
-import tempfile
 import time
 
 
@@ -74,27 +74,12 @@
 JS_ORIGIN = "js"
 JS_SNAPSHOT_ORIGIN = "js-snapshot"
 
-# Avoid using the slow (google-specific) wrapper around objdump.
-OBJDUMP_BIN = "/usr/bin/objdump"
-if not os.path.exists(OBJDUMP_BIN):
-  OBJDUMP_BIN = "objdump"
+OBJDUMP_BIN = disasm.OBJDUMP_BIN
 
 
 class Code(object):
   """Code object."""
 
-  _COMMON_DISASM_OPTIONS = ["-M", "intel-mnemonic", "-C"]
-
-  _DISASM_HEADER_RE = re.compile(r"[a-f0-9]+\s+<.*:$")
-  _DISASM_LINE_RE = re.compile(r"\s*([a-f0-9]+):.*")
-
-  # Keys must match constants in Logger::LogCodeInfo.
-  _ARCH_MAP = {
-    "ia32": "-m i386",
-    "x64": "-m i386 -M x86-64",
-    "arm": "-m arm"  # Not supported by our objdump build.
-  }
-
   _id = 0
 
   def __init__(self, name, start_address, end_address, origin, origin_offset):
@@ -150,12 +135,7 @@
     ticks_offsets = [t[0] for t in ticks_map]
     ticks_counts = [t[1] for t in ticks_map]
     # Get a list of disassembled lines and their addresses.
-    lines = []
-    for line in self._GetDisasmLines(code_info, options):
-      match = Code._DISASM_LINE_RE.match(line)
-      if match:
-        line_address = int(match.group(1), 16)
-        lines.append((line_address, line))
+    lines = self._GetDisasmLines(code_info, options)
     if len(lines) == 0:
       return
     # Print annotated lines.
@@ -179,9 +159,9 @@
       total_count += count
       count = 100.0 * count / self.self_ticks
       if count >= 0.01:
-        print "%15.2f %s" % (count, lines[i][1])
+        print "%15.2f %x: %s" % (count, lines[i][0], lines[i][1])
       else:
-        print "%s %s" % (" " * 15, lines[i][1])
+        print "%s %x: %s" % (" " * 15, lines[i][0], lines[i][1])
     print
     assert total_count == self.self_ticks, \
         "Lost ticks (%d != %d) in %s" % (total_count, self.self_ticks, self)
@@ -195,39 +175,17 @@
       self.origin)
 
   def _GetDisasmLines(self, code_info, options):
-    tmp_name = None
     if self.origin == JS_ORIGIN or self.origin == JS_SNAPSHOT_ORIGIN:
-      assert code_info.arch in Code._ARCH_MAP, \
-          "Unsupported architecture '%s'" % arch
-      arch_flags = Code._ARCH_MAP[code_info.arch]
-      # Create a temporary file just with this code object.
-      tmp_name = tempfile.mktemp(".v8code")
-      size = self.end_address - self.start_address
-      command = "dd if=%s.code of=%s bs=1 count=%d skip=%d && " \
-                "%s %s -D -b binary %s %s" % (
-        options.log, tmp_name, size, self.origin_offset,
-        OBJDUMP_BIN, ' '.join(Code._COMMON_DISASM_OPTIONS), arch_flags,
-        tmp_name)
+      inplace = False
+      filename = options.log + ".code"
     else:
-      command = "%s %s --start-address=%d --stop-address=%d -d %s " % (
-        OBJDUMP_BIN, ' '.join(Code._COMMON_DISASM_OPTIONS),
-        self.origin_offset,
-        self.origin_offset + self.end_address - self.start_address,
-        self.origin)
-    process = subprocess.Popen(command,
-                               shell=True,
-                               stdout=subprocess.PIPE,
-                               stderr=subprocess.STDOUT)
-    out, err = process.communicate()
-    lines = out.split("\n")
-    header_line = 0
-    for i, line in enumerate(lines):
-      if Code._DISASM_HEADER_RE.match(line):
-        header_line = i
-        break
-    if tmp_name:
-      os.unlink(tmp_name)
-    return lines[header_line + 1:]
+      inplace = True
+      filename = self.origin
+    return disasm.GetDisasmLines(filename,
+                                 self.origin_offset,
+                                 self.end_address - self.start_address,
+                                 code_info.arch,
+                                 inplace)
 
 
 class CodePage(object):
@@ -353,7 +311,7 @@
     r"code-info,([^,]+),(\d+)")
 
   _CODE_CREATE_RE = re.compile(
-    r"code-creation,([^,]+),(0x[a-f0-9]+),(\d+),\"(.*)\"(?:,(\d+))?")
+    r"code-creation,([^,]+),(0x[a-f0-9]+),(\d+),\"(.*)\"(?:,(0x[a-f0-9]+),([~*])?)?(?:,(\d+))?")
 
   _CODE_MOVE_RE = re.compile(
     r"code-move,(0x[a-f0-9]+),(0x[a-f0-9]+)")
@@ -400,12 +358,18 @@
           name = self.address_to_snapshot_name[start_address]
           origin = JS_SNAPSHOT_ORIGIN
         else:
-          name = "%s:%s" % (match.group(1), match.group(4))
+          tag = match.group(1)
+          optimization_status = match.group(6)
+          func_name = match.group(4)
+          if optimization_status:
+            name = "%s:%s%s" % (tag, optimization_status, func_name)
+          else:
+            name = "%s:%s" % (tag, func_name)
           origin = JS_ORIGIN
         if self.is_snapshot:
           origin_offset = 0
         else:
-          origin_offset = int(match.group(5))
+          origin_offset = int(match.group(7))
         code = Code(name, start_address, end_address, origin, origin_offset)
         conficting_code = self.code_map.Find(start_address)
         if conficting_code:
diff --git a/tools/profile.js b/tools/profile.js
index 03bee83..c9c9437 100644
--- a/tools/profile.js
+++ b/tools/profile.js
@@ -38,11 +38,6 @@
   this.bottomUpTree_ = new CallTree();
 };
 
-/**
- * Version of profiler log.
- */
-Profile.VERSION = 2;
-
 
 /**
  * Returns whether a function with the specified name must be skipped.
@@ -69,6 +64,18 @@
 
 
 /**
+ * Enum for code state regarding its dynamic optimization.
+ *
+ * @enum {number}
+ */
+Profile.CodeState = {
+  COMPILED: 0,
+  OPTIMIZABLE: 1,
+  OPTIMIZED: 2
+};
+
+
+/**
  * Called whenever the specified operation has failed finding a function
  * containing the specified address. Should be overriden by subclasses.
  * See the Profile.Operation enum for the list of
@@ -134,17 +141,30 @@
 
 
 /**
- * Creates an alias entry for a code entry.
+ * Registers dynamic (JIT-compiled) code entry.
  *
- * @param {number} aliasAddr Alias address.
- * @param {number} addr Code entry address.
+ * @param {string} type Code entry type.
+ * @param {string} name Code entry name.
+ * @param {number} start Starting address.
+ * @param {number} size Code entry size.
+ * @param {number} funcAddr Shared function object address.
+ * @param {Profile.CodeState} state Optimization state.
  */
-Profile.prototype.addCodeAlias = function(
-    aliasAddr, addr) {
-  var entry = this.codeMap_.findDynamicEntryByStartAddress(addr);
-  if (entry) {
-    this.codeMap_.addCode(aliasAddr, entry);
+Profile.prototype.addFuncCode = function(
+    type, name, start, size, funcAddr, state) {
+  // As code and functions are in the same address space,
+  // it is safe to put them in a single code map.
+  var func = this.codeMap_.findDynamicEntryByStartAddress(funcAddr);
+  if (!func) {
+    func = new Profile.FunctionEntry(name);
+    this.codeMap_.addCode(funcAddr, func);
+  } else if (func.name !== name) {
+    // Function object has been overwritten with a new one.
+    func.name = name;
   }
+  var entry = new Profile.DynamicFuncCodeEntry(size, type, func, state);
+  this.codeMap_.addCode(start, entry);
+  return entry;
 };
 
 
@@ -183,7 +203,7 @@
  * @param {number} from Current code entry address.
  * @param {number} to New code entry address.
  */
-Profile.prototype.safeMoveDynamicCode = function(from, to) {
+Profile.prototype.moveFunc = function(from, to) {
   if (this.codeMap_.findDynamicEntryByStartAddress(from)) {
     this.codeMap_.moveCode(from, to);
   }
@@ -191,18 +211,6 @@
 
 
 /**
- * Reports about deletion of a dynamic code entry.
- *
- * @param {number} start Starting address.
- */
-Profile.prototype.safeDeleteDynamicCode = function(start) {
-  if (this.codeMap_.findDynamicEntryByStartAddress(start)) {
-    this.codeMap_.deleteCode(start);
-  }
-};
-
-
-/**
  * Retrieves a code entry by an address.
  *
  * @param {number} addr Entry address.
@@ -383,14 +391,7 @@
  * Returns node name.
  */
 Profile.DynamicCodeEntry.prototype.getName = function() {
-  var name = this.name;
-  if (name.length == 0) {
-    name = '<anonymous>';
-  } else if (name.charAt(0) == ' ') {
-    // An anonymous function with location: " aaa.js:10".
-    name = '<anonymous>' + name;
-  }
-  return this.type + ': ' + name;
+  return this.type + ': ' + this.name;
 };
 
 
@@ -403,9 +404,73 @@
 
 
 Profile.DynamicCodeEntry.prototype.isJSFunction = function() {
-  return this.type == "Function" ||
-    this.type == "LazyCompile" ||
-    this.type == "Script";
+  return false;
+};
+
+
+/**
+ * Creates a dynamic code entry.
+ *
+ * @param {number} size Code size.
+ * @param {string} type Code type.
+ * @param {Profile.FunctionEntry} func Shared function entry.
+ * @param {Profile.CodeState} state Code optimization state.
+ * @constructor
+ */
+Profile.DynamicFuncCodeEntry = function(size, type, func, state) {
+  CodeMap.CodeEntry.call(this, size);
+  this.type = type;
+  this.func = func;
+  this.state = state;
+};
+
+Profile.DynamicFuncCodeEntry.STATE_PREFIX = ["", "~", "*"];
+
+/**
+ * Returns node name.
+ */
+Profile.DynamicFuncCodeEntry.prototype.getName = function() {
+  var name = this.func.getName();
+  return this.type + ': ' + Profile.DynamicFuncCodeEntry.STATE_PREFIX[this.state] + name;
+};
+
+
+/**
+ * Returns raw node name (without type decoration).
+ */
+Profile.DynamicFuncCodeEntry.prototype.getRawName = function() {
+  return this.func.getName();
+};
+
+
+Profile.DynamicFuncCodeEntry.prototype.isJSFunction = function() {
+  return true;
+};
+
+
+/**
+ * Creates a shared function object entry.
+ *
+ * @param {string} name Function name.
+ * @constructor
+ */
+Profile.FunctionEntry = function(name) {
+  CodeMap.CodeEntry.call(this, 0, name);
+};
+
+
+/**
+ * Returns node name.
+ */
+Profile.FunctionEntry.prototype.getName = function() {
+  var name = this.name;
+  if (name.length == 0) {
+    name = '<anonymous>';
+  } else if (name.charAt(0) == ' ') {
+    // An anonymous function with location: " aaa.js:10".
+    name = '<anonymous>' + name;
+  }
+  return name;
 };
 
 
diff --git a/tools/splaytree.py b/tools/splaytree.py
deleted file mode 100644
index 8c3c4fe..0000000
--- a/tools/splaytree.py
+++ /dev/null
@@ -1,226 +0,0 @@
-# Copyright 2008 the V8 project authors. All rights reserved.
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-#       copyright notice, this list of conditions and the following
-#       disclaimer in the documentation and/or other materials provided
-#       with the distribution.
-#     * Neither the name of Google Inc. nor the names of its
-#       contributors may be used to endorse or promote products derived
-#       from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-class Node(object):
-  """Nodes in the splay tree."""
-
-  def __init__(self, key, value):
-    self.key = key
-    self.value = value
-    self.left = None
-    self.right = None
-
-
-class KeyNotFoundError(Exception):
-  """KeyNotFoundError is raised when removing a non-existing node."""
-
-  def __init__(self, key):
-    self.key = key
-
-
-class SplayTree(object):
-  """The splay tree itself is just a reference to the root of the tree."""
-
-  def __init__(self):
-    """Create a new SplayTree."""
-    self.root = None
-
-  def IsEmpty(self):
-    """Is the SplayTree empty?"""
-    return not self.root
-
-  def Insert(self, key, value):
-    """Insert a new node in the SplayTree."""
-    # If the tree is empty, insert the new node.
-    if self.IsEmpty():
-      self.root = Node(key, value)
-      return
-    # Splay on the key to move the last node on the search path for
-    # the key to the root of the tree.
-    self.Splay(key)
-    # Ignore repeated insertions with the same key.
-    if self.root.key == key:
-      return
-    # Insert the new node.
-    node = Node(key, value)
-    if key > self.root.key:
-      node.left = self.root
-      node.right = self.root.right
-      self.root.right = None
-    else:
-      node.right = self.root
-      node.left = self.root.left
-      self.root.left = None
-    self.root = node
-
-  def Remove(self, key):
-    """Remove the node with the given key from the SplayTree."""
-    # Raise exception for key that is not found if the tree is empty.
-    if self.IsEmpty():
-      raise KeyNotFoundError(key)
-    # Splay on the key to move the node with the given key to the top.
-    self.Splay(key)
-    # Raise exception for key that is not found.
-    if self.root.key != key:
-      raise KeyNotFoundError(key)
-    removed = self.root
-    # Link out the root node.
-    if not self.root.left:
-      # No left child, so the new tree is just the right child.
-      self.root = self.root.right
-    else:
-      # Left child exists.
-      right = self.root.right
-      # Make the original left child the new root.
-      self.root = self.root.left
-      # Splay to make sure that the new root has an empty right child.
-      self.Splay(key)
-      # Insert the original right child as the right child of the new
-      # root.
-      self.root.right = right
-    return removed
-
-  def Find(self, key):
-    """Returns the node with the given key or None if no such node exists."""
-    if self.IsEmpty():
-      return None
-    self.Splay(key)
-    if self.root.key == key:
-      return self.root
-    return None
-
-  def FindMax(self):
-    """Returns the node with the largest key value."""
-    if self.IsEmpty():
-      return None
-    current = self.root
-    while current.right != None:
-      current = current.right
-    return current
-
-  # Returns the node with the smallest key value.
-  def FindMin(self):
-    if self.IsEmpty():
-      return None
-    current = self.root
-    while current.left != None:
-      current = current.left
-    return current
-
-  def FindGreatestsLessThan(self, key):
-    """Returns node with greatest key less than or equal to the given key."""
-    if self.IsEmpty():
-      return None
-    # Splay on the key to move the node with the given key or the last
-    # node on the search path to the top of the tree.
-    self.Splay(key)
-    # Now the result is either the root node or the greatest node in
-    # the left subtree.
-    if self.root.key <= key:
-      return self.root
-    else:
-      tmp = self.root
-      self.root = self.root.left
-      result = self.FindMax()
-      self.root = tmp
-      return result
-
-  def ExportValueList(self):
-    """Returns a list containing all the values of the nodes in the tree."""
-    result = []
-    nodes_to_visit = [self.root]
-    while len(nodes_to_visit) > 0:
-      node = nodes_to_visit.pop()
-      if not node:
-        continue
-      result.append(node.value)
-      nodes_to_visit.append(node.left)
-      nodes_to_visit.append(node.right)
-    return result
-
-  def Splay(self, key):
-    """Perform splay operation.
-
-    Perform the splay operation for the given key. Moves the node with
-    the given key to the top of the tree.  If no node has the given
-    key, the last node on the search path is moved to the top of the
-    tree.
-
-    This uses the simplified top-down splaying algorithm from:
-
-    "Self-adjusting Binary Search Trees" by Sleator and Tarjan
-
-    """
-    if self.IsEmpty():
-      return
-    # Create a dummy node.  The use of the dummy node is a bit
-    # counter-intuitive: The right child of the dummy node will hold
-    # the L tree of the algorithm.  The left child of the dummy node
-    # will hold the R tree of the algorithm.  Using a dummy node, left
-    # and right will always be nodes and we avoid special cases.
-    dummy = left = right = Node(None, None)
-    current = self.root
-    while True:
-      if key < current.key:
-        if not current.left:
-          break
-        if key < current.left.key:
-          # Rotate right.
-          tmp = current.left
-          current.left = tmp.right
-          tmp.right = current
-          current = tmp
-          if not current.left:
-            break
-        # Link right.
-        right.left = current
-        right = current
-        current = current.left
-      elif key > current.key:
-        if not current.right:
-          break
-        if key > current.right.key:
-          # Rotate left.
-          tmp = current.right
-          current.right = tmp.left
-          tmp.left = current
-          current = tmp
-          if not current.right:
-            break
-        # Link left.
-        left.right = current
-        left = current
-        current = current.right
-      else:
-        break
-    # Assemble.
-    left.right = current.left
-    right.left = current.right
-    current.left = dummy.right
-    current.right = dummy.left
-    self.root = current
diff --git a/tools/tickprocessor.js b/tools/tickprocessor.js
index db2f3c9..f105a21 100644
--- a/tools/tickprocessor.js
+++ b/tools/tickprocessor.js
@@ -57,10 +57,23 @@
 }
 
 
+/**
+ * Parser for dynamic code optimization state.
+ */
+function parseState(s) {
+  switch (s) {
+  case "": return Profile.CodeState.COMPILED;
+  case "~": return Profile.CodeState.OPTIMIZABLE;
+  case "*": return Profile.CodeState.OPTIMIZED;
+  }
+  throw new Error("unknown code state: " + s);
+}
+
+
 function SnapshotLogProcessor() {
   LogReader.call(this, {
       'code-creation': {
-          parsers: [null, parseInt, parseInt, null],
+          parsers: [null, parseInt, parseInt, null, 'var-args'],
           processor: this.processCodeCreation },
       'code-move': { parsers: [parseInt, parseInt],
           processor: this.processCodeMove },
@@ -69,6 +82,7 @@
       'function-creation': null,
       'function-move': null,
       'function-delete': null,
+      'sfi-move': null,
       'snapshot-pos': { parsers: [parseInt, parseInt],
           processor: this.processSnapshotPosition }});
 
@@ -93,8 +107,14 @@
 
 
 SnapshotLogProcessor.prototype.processCodeCreation = function(
-    type, start, size, name) {
-  var entry = this.profile_.addCode(type, name, start, size);
+    type, start, size, name, maybe_func) {
+  if (maybe_func.length) {
+    var funcAddr = parseInt(maybe_func[0]);
+    var state = parseState(maybe_func[1]);
+    this.profile_.addFuncCode(type, name, start, size, funcAddr, state);
+  } else {
+    this.profile_.addCode(type, name, start, size);
+  }
 };
 
 
@@ -131,18 +151,14 @@
       'shared-library': { parsers: [null, parseInt, parseInt],
           processor: this.processSharedLibrary },
       'code-creation': {
-          parsers: [null, parseInt, parseInt, null],
+          parsers: [null, parseInt, parseInt, null, 'var-args'],
           processor: this.processCodeCreation },
       'code-move': { parsers: [parseInt, parseInt],
           processor: this.processCodeMove },
       'code-delete': { parsers: [parseInt],
           processor: this.processCodeDelete },
-      'function-creation': { parsers: [parseInt, parseInt],
-          processor: this.processFunctionCreation },
-      'function-move': { parsers: [parseInt, parseInt],
+      'sfi-move': { parsers: [parseInt, parseInt],
           processor: this.processFunctionMove },
-      'function-delete': { parsers: [parseInt],
-          processor: this.processFunctionDelete },
       'snapshot-pos': { parsers: [parseInt, parseInt],
           processor: this.processSnapshotPosition },
       'tick': { parsers: [parseInt, parseInt, parseInt, parseInt, 'var-args'],
@@ -155,6 +171,9 @@
           processor: this.processJSProducer },
       // Ignored events.
       'profiler': null,
+      'function-creation': null,
+      'function-move': null,
+      'function-delete': null,
       'heap-sample-stats': null,
       'heap-sample-item': null,
       'heap-js-cons-item': null,
@@ -285,9 +304,15 @@
 
 
 TickProcessor.prototype.processCodeCreation = function(
-    type, start, size, name) {
+    type, start, size, name, maybe_func) {
   name = this.deserializedEntriesNames_[start] || name;
-  var entry = this.profile_.addCode(type, name, start, size);
+  if (maybe_func.length) {
+    var funcAddr = parseInt(maybe_func[0]);
+    var state = parseState(maybe_func[1]);
+    this.profile_.addFuncCode(type, name, start, size, funcAddr, state);
+  } else {
+    this.profile_.addCode(type, name, start, size);
+  }
 };
 
 
@@ -301,19 +326,8 @@
 };
 
 
-TickProcessor.prototype.processFunctionCreation = function(
-    functionAddr, codeAddr) {
-  this.profile_.addCodeAlias(functionAddr, codeAddr);
-};
-
-
 TickProcessor.prototype.processFunctionMove = function(from, to) {
-  this.profile_.safeMoveDynamicCode(from, to);
-};
-
-
-TickProcessor.prototype.processFunctionDelete = function(start) {
-  this.profile_.safeDeleteDynamicCode(start);
+  this.profile_.moveFunc(from, to);
 };
 
 
@@ -330,7 +344,7 @@
 };
 
 
-TickProcessor.prototype.processTick = function(pc, sp, func, vmState, stack) {
+TickProcessor.prototype.processTick = function(pc, sp, tos, vmState, stack) {
   this.ticks_.total++;
   if (vmState == TickProcessor.VmStates.GC) this.ticks_.gc++;
   if (!this.includeTick(vmState)) {
@@ -338,19 +352,14 @@
     return;
   }
 
-  if (func) {
-    var funcEntry = this.profile_.findEntry(func);
+  if (tos) {
+    var funcEntry = this.profile_.findEntry(tos);
     if (!funcEntry || !funcEntry.isJSFunction || !funcEntry.isJSFunction()) {
-      func = 0;
-    } else {
-      var currEntry = this.profile_.findEntry(pc);
-      if (!currEntry || !currEntry.isJSFunction || currEntry.isJSFunction()) {
-        func = 0;
-      }
+      tos = 0;
     }
   }
 
-  this.profile_.recordTick(this.processStack(pc, func, stack));
+  this.profile_.recordTick(this.processStack(pc, tos, stack));
 };
 
 
diff --git a/tools/tickprocessor.py b/tools/tickprocessor.py
deleted file mode 100644
index c932e3f..0000000
--- a/tools/tickprocessor.py
+++ /dev/null
@@ -1,571 +0,0 @@
-# Copyright 2008 the V8 project authors. All rights reserved.
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-#       copyright notice, this list of conditions and the following
-#       disclaimer in the documentation and/or other materials provided
-#       with the distribution.
-#     * Neither the name of Google Inc. nor the names of its
-#       contributors may be used to endorse or promote products derived
-#       from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import csv, splaytree, sys, re
-from operator import itemgetter
-import getopt, os, string
-
-class CodeEntry(object):
-
-  def __init__(self, start_addr, name):
-    self.start_addr = start_addr
-    self.tick_count = 0
-    self.name = name
-    self.stacks = {}
-
-  def Tick(self, pc, stack):
-    self.tick_count += 1
-    if len(stack) > 0:
-      stack.insert(0, self.ToString())
-      stack_key = tuple(stack)
-      self.stacks[stack_key] = self.stacks.setdefault(stack_key, 0) + 1
-
-  def RegionTicks(self):
-    return None
-
-  def SetStartAddress(self, start_addr):
-    self.start_addr = start_addr
-
-  def ToString(self):
-    return self.name
-
-  def IsSharedLibraryEntry(self):
-    return False
-
-  def IsICEntry(self):
-    return False
-
-  def IsJSFunction(self):
-    return False
-
-class SharedLibraryEntry(CodeEntry):
-
-  def __init__(self, start_addr, name):
-    CodeEntry.__init__(self, start_addr, name)
-
-  def IsSharedLibraryEntry(self):
-    return True
-
-
-class JSCodeEntry(CodeEntry):
-
-  def __init__(self, start_addr, name, type, size, assembler):
-    CodeEntry.__init__(self, start_addr, name)
-    self.type = type
-    self.size = size
-    self.assembler = assembler
-    self.region_ticks = None
-    self.builtin_ic_re = re.compile('^(Keyed)?(Call|Load|Store)IC_')
-
-  def Tick(self, pc, stack):
-    super(JSCodeEntry, self).Tick(pc, stack)
-    if not pc is None:
-      offset = pc - self.start_addr
-      seen = []
-      narrowest = None
-      narrowest_width = None
-      for region in self.Regions():
-        if region.Contains(offset):
-          if (not region.name in seen):
-            seen.append(region.name)
-          if narrowest is None or region.Width() < narrowest.Width():
-            narrowest = region
-      if len(seen) == 0:
-        return
-      if self.region_ticks is None:
-        self.region_ticks = {}
-      for name in seen:
-        if not name in self.region_ticks:
-          self.region_ticks[name] = [0, 0]
-        self.region_ticks[name][0] += 1
-        if name == narrowest.name:
-          self.region_ticks[name][1] += 1
-
-  def RegionTicks(self):
-    return self.region_ticks
-
-  def Regions(self):
-    if self.assembler:
-      return self.assembler.regions
-    else:
-      return []
-
-  def ToString(self):
-    name = self.name
-    if name == '':
-      name = '<anonymous>'
-    elif name.startswith(' '):
-      name = '<anonymous>' + name
-    return self.type + ': ' + name
-
-  def IsICEntry(self):
-    return self.type in ('CallIC', 'LoadIC', 'StoreIC') or \
-      (self.type == 'Builtin' and self.builtin_ic_re.match(self.name))
-
-  def IsJSFunction(self):
-    return self.type in ('Function', 'LazyCompile', 'Script')
-
-class CodeRegion(object):
-
-  def __init__(self, start_offset, name):
-    self.start_offset = start_offset
-    self.name = name
-    self.end_offset = None
-
-  def Contains(self, pc):
-    return (self.start_offset <= pc) and (pc <= self.end_offset)
-
-  def Width(self):
-    return self.end_offset - self.start_offset
-
-
-class Assembler(object):
-
-  def __init__(self):
-    # Mapping from region ids to open regions
-    self.pending_regions = {}
-    self.regions = []
-
-
-class FunctionEnumerator(object):
-
-  def __init__(self):
-    self.known_funcs = {}
-    self.next_func_id = 0
-
-  def GetFunctionId(self, name):
-    if not self.known_funcs.has_key(name):
-      self.known_funcs[name] = self.next_func_id
-      self.next_func_id += 1
-    return self.known_funcs[name]
-
-  def GetKnownFunctions(self):
-    known_funcs_items = self.known_funcs.items();
-    known_funcs_items.sort(key = itemgetter(1))
-    result = []
-    for func, id_not_used in known_funcs_items:
-      result.append(func)
-    return result
-
-
-VMStates = { 'JS': 0, 'GC': 1, 'COMPILER': 2, 'OTHER': 3, 'EXTERNAL' : 4 }
-
-
-class TickProcessor(object):
-
-  def __init__(self):
-    self.log_file = ''
-    self.deleted_code = []
-    self.vm_extent = {}
-    # Map from assembler ids to the pending assembler objects
-    self.pending_assemblers = {}
-    # Map from code addresses the have been allocated but not yet officially
-    # created to their assemblers.
-    self.assemblers = {}
-    self.js_entries = splaytree.SplayTree()
-    self.cpp_entries = splaytree.SplayTree()
-    self.total_number_of_ticks = 0
-    self.number_of_library_ticks = 0
-    self.unaccounted_number_of_ticks = 0
-    self.excluded_number_of_ticks = 0
-    self.number_of_gc_ticks = 0
-    # Flag indicating whether to ignore unaccounted ticks in the report
-    self.ignore_unknown = False
-    self.func_enum = FunctionEnumerator()
-    self.packed_stacks = []
-
-  def ProcessLogfile(self, filename, included_state = None, ignore_unknown = False, separate_ic = False, call_graph_json = False):
-    self.log_file = filename
-    self.included_state = included_state
-    self.ignore_unknown = ignore_unknown
-    self.separate_ic = separate_ic
-    self.call_graph_json = call_graph_json
-
-    try:
-      logfile = open(filename, 'rb')
-    except IOError:
-      sys.exit("Could not open logfile: " + filename)
-    try:
-      try:
-        logreader = csv.reader(logfile)
-        row_num = 1
-        for row in logreader:
-          row_num += 1
-          if row[0] == 'tick':
-            self.ProcessTick(int(row[1], 16), int(row[2], 16), int(row[3], 16), int(row[4]), self.PreprocessStack(row[5:]))
-          elif row[0] == 'code-creation':
-            self.ProcessCodeCreation(row[1], int(row[2], 16), int(row[3]), row[4])
-          elif row[0] == 'code-move':
-            self.ProcessCodeMove(int(row[1], 16), int(row[2], 16))
-          elif row[0] == 'code-delete':
-            self.ProcessCodeDelete(int(row[1], 16))
-          elif row[0] == 'function-creation':
-            self.ProcessFunctionCreation(int(row[1], 16), int(row[2], 16))
-          elif row[0] == 'function-move':
-            self.ProcessFunctionMove(int(row[1], 16), int(row[2], 16))
-          elif row[0] == 'function-delete':
-            self.ProcessFunctionDelete(int(row[1], 16))
-          elif row[0] == 'shared-library':
-            self.AddSharedLibraryEntry(row[1], int(row[2], 16), int(row[3], 16))
-            self.ParseVMSymbols(row[1], int(row[2], 16), int(row[3], 16))
-          elif row[0] == 'begin-code-region':
-            self.ProcessBeginCodeRegion(int(row[1], 16), int(row[2], 16), int(row[3], 16), row[4])
-          elif row[0] == 'end-code-region':
-            self.ProcessEndCodeRegion(int(row[1], 16), int(row[2], 16), int(row[3], 16))
-          elif row[0] == 'code-allocate':
-            self.ProcessCodeAllocate(int(row[1], 16), int(row[2], 16))
-      except csv.Error:
-        print("parse error in line " + str(row_num))
-        raise
-    finally:
-      logfile.close()
-
-  def AddSharedLibraryEntry(self, filename, start, end):
-    # Mark the pages used by this library.
-    i = start
-    while i < end:
-      page = i >> 12
-      self.vm_extent[page] = 1
-      i += 4096
-    # Add the library to the entries so that ticks for which we do not
-    # have symbol information is reported as belonging to the library.
-    self.cpp_entries.Insert(start, SharedLibraryEntry(start, filename))
-
-  def ParseVMSymbols(self, filename, start, end):
-    return
-
-  def ProcessCodeAllocate(self, addr, assem):
-    if assem in self.pending_assemblers:
-      assembler = self.pending_assemblers.pop(assem)
-      self.assemblers[addr] = assembler
-
-  def ProcessCodeCreation(self, type, addr, size, name):
-    if addr in self.assemblers:
-      assembler = self.assemblers.pop(addr)
-    else:
-      assembler = None
-    self.js_entries.Insert(addr, JSCodeEntry(addr, name, type, size, assembler))
-
-  def ProcessCodeMove(self, from_addr, to_addr):
-    try:
-      removed_node = self.js_entries.Remove(from_addr)
-      removed_node.value.SetStartAddress(to_addr);
-      self.js_entries.Insert(to_addr, removed_node.value)
-    except splaytree.KeyNotFoundError:
-      print('Code move event for unknown code: 0x%x' % from_addr)
-
-  def ProcessCodeDelete(self, from_addr):
-    try:
-      removed_node = self.js_entries.Remove(from_addr)
-      self.deleted_code.append(removed_node.value)
-    except splaytree.KeyNotFoundError:
-      print('Code delete event for unknown code: 0x%x' % from_addr)
-
-  def ProcessFunctionCreation(self, func_addr, code_addr):
-    js_entry_node = self.js_entries.Find(code_addr)
-    if js_entry_node:
-      js_entry = js_entry_node.value
-      self.js_entries.Insert(func_addr, JSCodeEntry(func_addr, js_entry.name, js_entry.type, 1, None))
-
-  def ProcessFunctionMove(self, from_addr, to_addr):
-    try:
-      removed_node = self.js_entries.Remove(from_addr)
-      removed_node.value.SetStartAddress(to_addr);
-      self.js_entries.Insert(to_addr, removed_node.value)
-    except splaytree.KeyNotFoundError:
-      return
-
-  def ProcessFunctionDelete(self, from_addr):
-    try:
-      removed_node = self.js_entries.Remove(from_addr)
-      self.deleted_code.append(removed_node.value)
-    except splaytree.KeyNotFoundError:
-      return
-
-  def ProcessBeginCodeRegion(self, id, assm, start, name):
-    if not assm in self.pending_assemblers:
-      self.pending_assemblers[assm] = Assembler()
-    assembler = self.pending_assemblers[assm]
-    assembler.pending_regions[id] = CodeRegion(start, name)
-
-  def ProcessEndCodeRegion(self, id, assm, end):
-    assm = self.pending_assemblers[assm]
-    region = assm.pending_regions.pop(id)
-    region.end_offset = end
-    assm.regions.append(region)
-
-  def IncludeTick(self, pc, sp, state):
-    return (self.included_state is None) or (self.included_state == state)
-
-  def FindEntry(self, pc):
-    page = pc >> 12
-    if page in self.vm_extent:
-      entry = self.cpp_entries.FindGreatestsLessThan(pc)
-      if entry != None:
-        return entry.value
-      else:
-        return entry
-    max = self.js_entries.FindMax()
-    min = self.js_entries.FindMin()
-    if max != None and pc < (max.key + max.value.size) and pc > min.key:
-      return self.js_entries.FindGreatestsLessThan(pc).value
-    return None
-
-  def PreprocessStack(self, stack):
-    # remove all non-addresses (e.g. 'overflow') and convert to int
-    result = []
-    for frame in stack:
-      if frame.startswith('0x'):
-        result.append(int(frame, 16))
-    return result
-
-  def ProcessStack(self, stack):
-    result = []
-    for frame in stack:
-      entry = self.FindEntry(frame)
-      if entry != None:
-        result.append(entry.ToString())
-    return result
-
-  def ProcessTick(self, pc, sp, func, state, stack):
-    if state == VMStates['GC']:
-      self.number_of_gc_ticks += 1
-    if not self.IncludeTick(pc, sp, state):
-      self.excluded_number_of_ticks += 1;
-      return
-    self.total_number_of_ticks += 1
-    entry = self.FindEntry(pc)
-    if entry == None:
-      self.unaccounted_number_of_ticks += 1
-      return
-    if entry.IsSharedLibraryEntry():
-      self.number_of_library_ticks += 1
-    if entry.IsICEntry() and not self.separate_ic:
-      if len(stack) > 0:
-        caller_pc = stack.pop(0)
-        self.total_number_of_ticks -= 1
-        self.ProcessTick(caller_pc, sp, func, state, stack)
-      else:
-        self.unaccounted_number_of_ticks += 1
-    else:
-      processed_stack = self.ProcessStack(stack)
-      if not entry.IsSharedLibraryEntry() and not entry.IsJSFunction():
-        func_entry_node = self.js_entries.Find(func)
-        if func_entry_node and func_entry_node.value.IsJSFunction():
-          processed_stack.insert(0, func_entry_node.value.ToString())
-      entry.Tick(pc, processed_stack)
-      if self.call_graph_json:
-        self.AddToPackedStacks(pc, stack)
-
-  def AddToPackedStacks(self, pc, stack):
-    full_stack = stack
-    full_stack.insert(0, pc)
-    func_names = self.ProcessStack(full_stack)
-    func_ids = []
-    for func in func_names:
-      func_ids.append(self.func_enum.GetFunctionId(func))
-    self.packed_stacks.append(func_ids)
-
-  def PrintResults(self):
-    if not self.call_graph_json:
-      self.PrintStatistics()
-    else:
-      self.PrintCallGraphJSON()
-
-  def PrintStatistics(self):
-    print('Statistical profiling result from %s, (%d ticks, %d unaccounted, %d excluded).' %
-          (self.log_file,
-           self.total_number_of_ticks,
-           self.unaccounted_number_of_ticks,
-           self.excluded_number_of_ticks))
-    if self.total_number_of_ticks > 0:
-      js_entries = self.js_entries.ExportValueList()
-      js_entries.extend(self.deleted_code)
-      cpp_entries = self.cpp_entries.ExportValueList()
-      # Print the unknown ticks percentage if they are not ignored.
-      if not self.ignore_unknown and self.unaccounted_number_of_ticks > 0:
-        self.PrintHeader('Unknown')
-        self.PrintCounter(self.unaccounted_number_of_ticks)
-      # Print the library ticks.
-      self.PrintHeader('Shared libraries')
-      self.PrintEntries(cpp_entries, lambda e:e.IsSharedLibraryEntry())
-      # Print the JavaScript ticks.
-      self.PrintHeader('JavaScript')
-      self.PrintEntries(js_entries, lambda e:not e.IsSharedLibraryEntry())
-      # Print the C++ ticks.
-      self.PrintHeader('C++')
-      self.PrintEntries(cpp_entries, lambda e:not e.IsSharedLibraryEntry())
-      # Print the GC ticks.
-      self.PrintHeader('GC')
-      self.PrintCounter(self.number_of_gc_ticks)
-      # Print call profile.
-      print('\n [Call profile]:')
-      print('   total  call path')
-      js_entries.extend(cpp_entries)
-      self.PrintCallProfile(js_entries)
-
-  def PrintHeader(self, header_title):
-    print('\n [%s]:' % header_title)
-    print('   ticks  total  nonlib   name')
-
-  def PrintCounter(self, ticks_count):
-    percentage = ticks_count * 100.0 / self.total_number_of_ticks
-    print('  %(ticks)5d  %(total)5.1f%%' % {
-      'ticks' : ticks_count,
-      'total' : percentage,
-    })
-
-  def PrintEntries(self, entries, condition):
-    # If ignoring unaccounted ticks don't include these in percentage
-    # calculations
-    number_of_accounted_ticks = self.total_number_of_ticks
-    if self.ignore_unknown:
-      number_of_accounted_ticks -= self.unaccounted_number_of_ticks
-
-    number_of_non_library_ticks = number_of_accounted_ticks - self.number_of_library_ticks
-    entries.sort(key=lambda e: (e.tick_count, e.ToString()), reverse=True)
-    for entry in entries:
-      if entry.tick_count > 0 and condition(entry):
-        total_percentage = entry.tick_count * 100.0 / number_of_accounted_ticks
-        if entry.IsSharedLibraryEntry():
-          non_library_percentage = 0
-        else:
-          non_library_percentage = entry.tick_count * 100.0 / number_of_non_library_ticks
-        print('  %(ticks)5d  %(total)5.1f%% %(nonlib)6.1f%%  %(name)s' % {
-          'ticks' : entry.tick_count,
-          'total' : total_percentage,
-          'nonlib' : non_library_percentage,
-          'name' : entry.ToString()
-        })
-        region_ticks = entry.RegionTicks()
-        if not region_ticks is None:
-          items = region_ticks.items()
-          items.sort(key=lambda e: e[1][1], reverse=True)
-          for (name, ticks) in items:
-            print('                      flat   cum')
-            print('                     %(flat)5.1f%% %(accum)5.1f%% %(name)s' % {
-              'flat' : ticks[1] * 100.0 / entry.tick_count,
-              'accum' : ticks[0] * 100.0 / entry.tick_count,
-              'name': name
-            })
-
-  def PrintCallProfile(self, entries):
-    all_stacks = {}
-    total_stacks = 0
-    for entry in entries:
-      all_stacks.update(entry.stacks)
-      for count in entry.stacks.itervalues():
-        total_stacks += count
-    all_stacks_items = all_stacks.items();
-    all_stacks_items.sort(key = itemgetter(1), reverse=True)
-    missing_percentage = (self.total_number_of_ticks - total_stacks) * 100.0 / self.total_number_of_ticks
-    print('  %(ticks)5d  %(total)5.1f%%  <no call path information>' % {
-      'ticks' : self.total_number_of_ticks - total_stacks,
-      'total' : missing_percentage
-    })
-    for stack, count in all_stacks_items:
-      total_percentage = count * 100.0 / self.total_number_of_ticks
-      print('  %(ticks)5d  %(total)5.1f%%  %(call_path)s' % {
-        'ticks' : count,
-        'total' : total_percentage,
-        'call_path' : stack[0] + '  <-  ' + stack[1]
-      })
-
-  def PrintCallGraphJSON(self):
-    print('\nvar __profile_funcs = ["' +
-          '",\n"'.join(self.func_enum.GetKnownFunctions()) +
-          '"];')
-    print('var __profile_ticks = [')
-    str_packed_stacks = []
-    for stack in self.packed_stacks:
-      str_packed_stacks.append('[' + ','.join(map(str, stack)) + ']')
-    print(',\n'.join(str_packed_stacks))
-    print('];')
-
-class CmdLineProcessor(object):
-
-  def __init__(self):
-    self.options = ["js",
-                    "gc",
-                    "compiler",
-                    "other",
-                    "external",
-                    "ignore-unknown",
-                    "separate-ic",
-                    "call-graph-json"]
-    # default values
-    self.state = None
-    self.ignore_unknown = False
-    self.log_file = None
-    self.separate_ic = False
-    self.call_graph_json = False
-
-  def ProcessArguments(self):
-    try:
-      opts, args = getopt.getopt(sys.argv[1:], "jgcoe", self.options)
-    except getopt.GetoptError:
-      self.PrintUsageAndExit()
-    for key, value in opts:
-      if key in ("-j", "--js"):
-        self.state = VMStates['JS']
-      if key in ("-g", "--gc"):
-        self.state = VMStates['GC']
-      if key in ("-c", "--compiler"):
-        self.state = VMStates['COMPILER']
-      if key in ("-o", "--other"):
-        self.state = VMStates['OTHER']
-      if key in ("-e", "--external"):
-        self.state = VMStates['EXTERNAL']
-      if key in ("--ignore-unknown"):
-        self.ignore_unknown = True
-      if key in ("--separate-ic"):
-        self.separate_ic = True
-      if key in ("--call-graph-json"):
-        self.call_graph_json = True
-    self.ProcessRequiredArgs(args)
-
-  def ProcessRequiredArgs(self, args):
-    return
-
-  def GetRequiredArgsNames(self):
-    return
-
-  def PrintUsageAndExit(self):
-    print('Usage: %(script_name)s --{%(opts)s} %(req_opts)s' % {
-        'script_name': os.path.basename(sys.argv[0]),
-        'opts': string.join(self.options, ','),
-        'req_opts': self.GetRequiredArgsNames()
-    })
-    sys.exit(2)
-
-  def RunLogfileProcessing(self, tick_processor):
-    tick_processor.ProcessLogfile(self.log_file, self.state, self.ignore_unknown,
-                                  self.separate_ic, self.call_graph_json)
-
-
-if __name__ == '__main__':
-  sys.exit('You probably want to run windows-tick-processor.py or linux-tick-processor.py.')
diff --git a/tools/utils.py b/tools/utils.py
index 8083091..fb94d14 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -49,6 +49,8 @@
     return 'linux'
   elif id == 'Darwin':
     return 'macos'
+  elif id.find('CYGWIN') >= 0:
+    return 'cygwin'
   elif id == 'Windows' or id == 'Microsoft':
     # On Windows Vista platform.system() can return 'Microsoft' with some
     # versions of Python, see http://bugs.python.org/issue1082
diff --git a/tools/v8.xcodeproj/project.pbxproj b/tools/v8.xcodeproj/project.pbxproj
index 24321e5..10fbc58 100644
--- a/tools/v8.xcodeproj/project.pbxproj
+++ b/tools/v8.xcodeproj/project.pbxproj
@@ -211,6 +211,7 @@
 		895692A512D4ED240072C313 /* objects-printer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8946827412C26EB700C914BC /* objects-printer.cc */; };
 		8956B6CF0F5D86730033B5A2 /* debug-agent.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8956B6CD0F5D86570033B5A2 /* debug-agent.cc */; };
 		895FA753107FFED3006F39D4 /* constants-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 895FA748107FFE73006F39D4 /* constants-arm.cc */; };
+		896FA1E5130F93D300042054 /* lithium-gap-resolver-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 896FA1E3130F93D300042054 /* lithium-gap-resolver-arm.cc */; };
 		896FD03A0E78D717003DFB6A /* libv8-arm.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 89F23C870E78D5B2006B2466 /* libv8-arm.a */; };
 		897C77D012B68E3D000767A8 /* d8-debug.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893988150F2A3686007D5254 /* d8-debug.cc */; };
 		897C77D112B68E3D000767A8 /* d8-js.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893988320F2A3B8B007D5254 /* d8-js.cc */; };
@@ -647,6 +648,8 @@
 		895FA751107FFEAE006F39D4 /* register-allocator-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "register-allocator-arm.h"; path = "arm/register-allocator-arm.h"; sourceTree = "<group>"; };
 		8964482B0E9C00F700E7C516 /* codegen-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "codegen-ia32.h"; path = "ia32/codegen-ia32.h"; sourceTree = "<group>"; };
 		896448BC0E9D530500E7C516 /* codegen-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "codegen-arm.h"; path = "arm/codegen-arm.h"; sourceTree = "<group>"; };
+		896FA1E3130F93D300042054 /* lithium-gap-resolver-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lithium-gap-resolver-arm.cc"; path = "arm/lithium-gap-resolver-arm.cc"; sourceTree = "<group>"; };
+		896FA1E4130F93D300042054 /* lithium-gap-resolver-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lithium-gap-resolver-arm.h"; path = "arm/lithium-gap-resolver-arm.h"; sourceTree = "<group>"; };
 		8970F2F00E719FB2006AE7B5 /* libv8.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libv8.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		897C77D912B68E3D000767A8 /* d8-arm */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "d8-arm"; sourceTree = BUILT_PRODUCTS_DIR; };
 		897F767A0E71B4CC007ACF34 /* v8_shell */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = v8_shell; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1538,6 +1541,8 @@
 				893E24C812B14B510083370F /* lithium-arm.h */,
 				893E24C912B14B520083370F /* lithium-codegen-arm.cc */,
 				893E24CA12B14B520083370F /* lithium-codegen-arm.h */,
+				896FA1E3130F93D300042054 /* lithium-gap-resolver-arm.cc */,
+				896FA1E4130F93D300042054 /* lithium-gap-resolver-arm.h */,
 				897FF1540E719B8F00D62E90 /* macro-assembler-arm.cc */,
 				897FF1550E719B8F00D62E90 /* macro-assembler-arm.h */,
 				89A15C700EE466D000B48DEB /* regexp-macro-assembler-arm.cc */,
@@ -2290,6 +2295,7 @@
 				894A59EA12D777E80000766D /* lithium.cc in Sources */,
 				89D7DDDC12E8DE09001E2B82 /* gdb-jit.cc in Sources */,
 				89D7DDDD12E8DE09001E2B82 /* inspector.cc in Sources */,
+				896FA1E5130F93D300042054 /* lithium-gap-resolver-arm.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/tools/visual_studio/x64.vsprops b/tools/visual_studio/x64.vsprops
index 7990440..04d9c65 100644
--- a/tools/visual_studio/x64.vsprops
+++ b/tools/visual_studio/x64.vsprops
@@ -12,6 +12,7 @@
 	/>
 	<Tool
 		Name="VCLinkerTool"
+                StackReserveSize="2091752"
 		TargetMachine="17"
 	/>
 </VisualStudioPropertySheet>
diff --git a/tools/windows-tick-processor.py b/tools/windows-tick-processor.py
deleted file mode 100755
index ade2bf2..0000000
--- a/tools/windows-tick-processor.py
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2008 the V8 project authors. All rights reserved.
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-#       copyright notice, this list of conditions and the following
-#       disclaimer in the documentation and/or other materials provided
-#       with the distribution.
-#     * Neither the name of Google Inc. nor the names of its
-#       contributors may be used to endorse or promote products derived
-#       from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-# Usage: process-ticks.py <binary> <logfile>
-#
-# Where <binary> is the binary program name (eg, v8_shell.exe) and
-# <logfile> is the log file name (eg, v8.log).
-#
-# This tick processor expects to find a map file for the binary named
-# binary.map if the binary is named binary.exe. The tick processor
-# only works for statically linked executables - no information about
-# shared libraries is logged from v8 on Windows.
-
-import os, re, sys, tickprocessor
-
-class WindowsTickProcessor(tickprocessor.TickProcessor):
-
-  def Unmangle(self, name):
-    """Performs very simple unmangling of C++ names.
-
-    Does not handle arguments and template arguments. The mangled names have
-    the form:
-
-       ?LookupInDescriptor@JSObject@internal@v8@@...arguments info...
-
-    """
-    # Name is mangled if it starts with a question mark.
-    is_mangled = re.match("^\?(.*)", name)
-    if is_mangled:
-      substrings = is_mangled.group(1).split('@')
-      try:
-        # The function name is terminated by two @s in a row.  Find the
-        # substrings that are part of the function name.
-        index = substrings.index('')
-        substrings = substrings[0:index]
-      except ValueError:
-        # If we did not find two @s in a row, the mangled name is not in
-        # the format we expect and we give up.
-        return name
-      substrings.reverse()
-      function_name = "::".join(substrings)
-      return function_name
-    return name
-
-
-  def ParseMapFile(self, filename):
-    """Parse map file and add symbol information to the cpp entries."""
-    # Locate map file.
-    has_dot = re.match('^([a-zA-F0-9_-]*)[\.]?.*$', filename)
-    if has_dot:
-      map_file_name = has_dot.group(1) + '.map'
-      try:
-        map_file = open(map_file_name, 'rb')
-      except IOError:
-        sys.exit("Could not open map file: " + map_file_name)
-    else:
-      sys.exit("Could not find map file for executable: " + filename)
-    try:
-      max_addr = 0
-      min_addr = 2**30
-      # Process map file and search for function entries.
-      row_regexp = re.compile(' 0001:[0-9a-fA-F]{8}\s*([_\?@$0-9a-zA-Z]*)\s*([0-9a-fA-F]{8}).*')
-      for line in map_file:
-        row = re.match(row_regexp, line)
-        if row:
-          addr = int(row.group(2), 16)
-          if addr > max_addr:
-            max_addr = addr
-          if addr < min_addr:
-            min_addr = addr
-          mangled_name = row.group(1)
-          name = self.Unmangle(mangled_name)
-          self.cpp_entries.Insert(addr, tickprocessor.CodeEntry(addr, name));
-      i = min_addr
-      # Mark the pages for which there are functions in the map file.
-      while i < max_addr:
-        page = i >> 12
-        self.vm_extent[page] = 1
-        i += 4096
-    finally:
-      map_file.close()
-
-
-class WindowsCmdLineProcessor(tickprocessor.CmdLineProcessor):
-
-  def __init__(self):
-    super(WindowsCmdLineProcessor, self).__init__()
-    self.binary_file = None
-
-  def GetRequiredArgsNames(self):
-    return 'binary log_file'
-
-  def ProcessRequiredArgs(self, args):
-    if len(args) != 2:
-      self.PrintUsageAndExit()
-    else:
-      self.binary_file = args[0]
-      self.log_file = args[1]
-
-
-def Main():
-  cmdline_processor = WindowsCmdLineProcessor()
-  cmdline_processor.ProcessArguments()
-  tickprocessor = WindowsTickProcessor()
-  tickprocessor.ParseMapFile(cmdline_processor.binary_file)
-  cmdline_processor.RunLogfileProcessing(tickprocessor)
-  tickprocessor.PrintResults()
-
-if __name__ == '__main__':
-  Main()