Version 3.22.4

Function::Call and Object::CallAsFunction APIs should allow v8::Value as a receiver (issue 2915).

Removed unnecessary mutex (Chromium issue 291236).

Removed ArrayBufferView::BaseAddress method.

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@17010 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 153f45c..6a90e29 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2013-09-30: Version 3.22.4
+
+        Function::Call and Object::CallAsFunction APIs should allow v8::Value as
+        a receiver (issue 2915).
+
+        Removed unnecessary mutex (Chromium issue 291236).
+
+        Removed ArrayBufferView::BaseAddress method.
+
+        Performance and stability improvements on all platforms.
+
+
 2013-09-27: Version 3.22.3
 
         Added methods to enable configuration of ResourceConstraints based on
diff --git a/Makefile b/Makefile
index bcf3bcc..6f1de5c 100644
--- a/Makefile
+++ b/Makefile
@@ -76,10 +76,10 @@
 endif
 # extrachecks=on/off
 ifeq ($(extrachecks), on)
-  GYPFLAGS += -Dv8_enable_extra_checks=1
+  GYPFLAGS += -Dv8_enable_extra_checks=1 -Dv8_enable_handle_zapping=1
 endif
 ifeq ($(extrachecks), off)
-  GYPFLAGS += -Dv8_enable_extra_checks=0
+  GYPFLAGS += -Dv8_enable_extra_checks=0 -Dv8_enable_handle_zapping=0
 endif
 # gdbjit=on/off
 ifeq ($(gdbjit), on)
@@ -129,6 +129,10 @@
   GYPFLAGS += -Dv8_enable_i18n_support=0
   TESTFLAGS += --noi18n
 endif
+# deprecation_warnings=on
+ifeq ($(deprecationwarnings), on)
+  GYPFLAGS += -Dv8_deprecation_warnings=1
+endif 
 # arm specific flags.
 # armv7=false/true
 ifeq ($(armv7), false)
diff --git a/OWNERS b/OWNERS
index 6fe40e2..e69a7d5 100644
--- a/OWNERS
+++ b/OWNERS
@@ -3,11 +3,12 @@
 dslomov@chromium.org
 hpayer@chromium.org
 jkummerow@chromium.org
-mmassi@chromium.org
+machenbach@chromium.org
 mstarzinger@chromium.org
 mvstanton@chromium.org
 rossberg@chromium.org
 svenpanne@chromium.org
+titzer@chromium.org
 ulan@chromium.org
 vegorov@chromium.org
 verwaest@chromium.org
diff --git a/build/features.gypi b/build/features.gypi
index 5343284..7863b1c 100644
--- a/build/features.gypi
+++ b/build/features.gypi
@@ -55,6 +55,9 @@
     # Enable ECMAScript Internationalization API. Enabling this feature will
     # add a dependency on the ICU library.
     'v8_enable_i18n_support%': 1,
+
+    # Enable compiler warnings when using V8_DEPRECATED apis.
+    'v8_deprecation_warnings%': 0,
   },
   'target_defaults': {
     'conditions': [
@@ -76,6 +79,9 @@
       ['v8_interpreted_regexp==1', {
         'defines': ['V8_INTERPRETED_REGEXP',],
       }],
+      ['v8_deprecation_warnings==1', {
+        'defines': ['V8_DEPRECATION_WARNINGS',],
+      }],
       ['v8_enable_i18n_support==1', {
         'defines': ['V8_I18N_SUPPORT',],
       }],
@@ -89,21 +95,29 @@
       'Debug': {
         'variables': {
           'v8_enable_extra_checks%': 1,
+          'v8_enable_handle_zapping%': 1,
         },
         'conditions': [
           ['v8_enable_extra_checks==1', {
             'defines': ['ENABLE_EXTRA_CHECKS',],
           }],
+          ['v8_enable_handle_zapping==1', {
+            'defines': ['ENABLE_HANDLE_ZAPPING',],
+          }],
         ],
       },  # Debug
       'Release': {
         'variables': {
           'v8_enable_extra_checks%': 0,
+          'v8_enable_handle_zapping%': 0,
         },
         'conditions': [
           ['v8_enable_extra_checks==1', {
             'defines': ['ENABLE_EXTRA_CHECKS',],
           }],
+          ['v8_enable_handle_zapping==1', {
+            'defines': ['ENABLE_HANDLE_ZAPPING',],
+          }],
         ],  # conditions
       },  # Release
     },  # configurations
diff --git a/include/v8-profiler.h b/include/v8-profiler.h
index 217a938..c393039 100644
--- a/include/v8-profiler.h
+++ b/include/v8-profiler.h
@@ -62,11 +62,6 @@
     */
   const char* GetBailoutReason() const;
 
-  /** DEPRECATED. Please use GetHitCount instead.
-    * Returns the count of samples where function was currently executing.
-    */
-  V8_DEPRECATED(double GetSelfSamplesCount() const);
-
   /**
     * Returns the count of samples where the function was currently executing.
     */
diff --git a/include/v8.h b/include/v8.h
index 19abf0f..8e3fed6 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -586,7 +586,6 @@
   V8_INLINE void Reset(Isolate* isolate, const Persistent<S, M2>& other);
   // TODO(dcarney): deprecate
   V8_INLINE void Dispose() { Reset(); }
-  V8_DEPRECATED(V8_INLINE void Dispose(Isolate* isolate)) { Reset(); }
 
   V8_INLINE bool IsEmpty() const { return val_ == 0; }
 
@@ -656,8 +655,6 @@
 
   V8_INLINE void ClearWeak();
 
-  V8_DEPRECATED(V8_INLINE void ClearWeak(Isolate* isolate)) { ClearWeak(); }
-
   /**
    * Marks the reference to this object independent. Garbage collector is free
    * to ignore any object groups containing this object. Weak callback for an
@@ -666,10 +663,6 @@
    */
   V8_INLINE void MarkIndependent();
 
-  V8_DEPRECATED(V8_INLINE void MarkIndependent(Isolate* isolate)) {
-    MarkIndependent();
-  }
-
   /**
    * Marks the reference to this object partially dependent. Partially dependent
    * handles only depend on other partially dependent handles and these
@@ -680,51 +673,26 @@
    */
   V8_INLINE void MarkPartiallyDependent();
 
-  V8_DEPRECATED(V8_INLINE void MarkPartiallyDependent(Isolate* isolate)) {
-    MarkPartiallyDependent();
-  }
-
   V8_INLINE bool IsIndependent() const;
 
-  V8_DEPRECATED(V8_INLINE bool IsIndependent(Isolate* isolate) const) {
-    return IsIndependent();
-  }
-
   /** Checks if the handle holds the only reference to an object. */
   V8_INLINE bool IsNearDeath() const;
 
-  V8_DEPRECATED(V8_INLINE bool IsNearDeath(Isolate* isolate) const) {
-    return IsNearDeath();
-  }
-
   /** Returns true if the handle's reference is weak.  */
   V8_INLINE bool IsWeak() const;
 
-  V8_DEPRECATED(V8_INLINE bool IsWeak(Isolate* isolate) const) {
-    return IsWeak();
-  }
-
   /**
    * Assigns a wrapper class ID to the handle. See RetainedObjectInfo interface
    * description in v8-profiler.h for details.
    */
   V8_INLINE void SetWrapperClassId(uint16_t class_id);
 
-  V8_DEPRECATED(
-      V8_INLINE void SetWrapperClassId(Isolate * isolate, uint16_t class_id)) {
-    SetWrapperClassId(class_id);
-  }
-
   /**
    * Returns the class ID previously assigned to this handle or 0 if no class ID
    * was previously assigned.
    */
   V8_INLINE uint16_t WrapperClassId() const;
 
-  V8_DEPRECATED(V8_INLINE uint16_t WrapperClassId(Isolate* isolate) const) {
-    return WrapperClassId();
-  }
-
   // TODO(dcarney): remove
   V8_INLINE T* ClearAndLeak();
 
@@ -1573,11 +1541,6 @@
   int Utf8Length() const;
 
   /**
-   * This function is no longer useful.
-   */
-  V8_DEPRECATED(V8_INLINE bool MayContainNonAscii() const) { return true; }
-
-  /**
    * Returns whether this string is known to contain only one byte data.
    * Does not read the string.
    * False negatives are possible.
@@ -1627,11 +1590,6 @@
             int start = 0,
             int length = -1,
             int options = NO_OPTIONS) const;
-  // ASCII characters.
-  V8_DEPRECATED(int WriteAscii(char* buffer,
-                               int start = 0,
-                               int length = -1,
-                               int options = NO_OPTIONS) const);
   // One byte characters.
   int WriteOneByte(uint8_t* buffer,
                    int start = 0,
@@ -1762,24 +1720,29 @@
 
   V8_INLINE static String* Cast(v8::Value* obj);
 
-  // TODO(dcarney): deprecate
   /**
    * Allocates a new string from either UTF-8 encoded or ASCII data.
    * The second parameter 'length' gives the buffer length. If omitted,
    * the function calls 'strlen' to determine the buffer length.
    */
-  V8_INLINE static Local<String> New(const char* data, int length = -1);
+  V8_DEPRECATED(
+      "Use NewFromOneByte instead",
+      V8_INLINE static Local<String> New(const char* data, int length = -1));
 
-  // TODO(dcarney): deprecate
   /** Allocates a new string from 16-bit character codes.*/
-  V8_INLINE static Local<String> New(const uint16_t* data, int length = -1);
+  V8_DEPRECATED(
+      "Use NewFromTwoByte instead",
+      V8_INLINE static Local<String> New(
+          const uint16_t* data, int length = -1));
 
-  // TODO(dcarney): deprecate
   /**
    * Creates an internalized string (historically called a "symbol",
    * not to be confused with ES6 symbols). Returns one if it exists already.
    */
-  V8_INLINE static Local<String> NewSymbol(const char* data, int length = -1);
+  V8_DEPRECATED(
+      "Use NewFromUtf8 instead",
+      V8_INLINE static Local<String> NewSymbol(
+          const char* data, int length = -1));
 
   enum NewStringType {
     kNormalString, kInternalizedString, kUndetectableString
@@ -2322,7 +2285,7 @@
    * Call an Object as a function if a callback is set by the
    * ObjectTemplate::SetCallAsFunctionHandler method.
    */
-  Local<Value> CallAsFunction(Handle<Object> recv,
+  Local<Value> CallAsFunction(Handle<Value> recv,
                               int argc,
                               Handle<Value> argv[]);
 
@@ -2495,7 +2458,7 @@
 
   Local<Object> NewInstance() const;
   Local<Object> NewInstance(int argc, Handle<Value> argv[]) const;
-  Local<Value> Call(Handle<Object> recv, int argc, Handle<Value> argv[]);
+  Local<Value> Call(Handle<Value> recv, int argc, Handle<Value> argv[]);
   void SetName(Handle<String> name);
   Handle<Value> GetName() const;
 
@@ -2685,10 +2648,6 @@
    * Size of a view in bytes.
    */
   size_t ByteLength();
-  /**
-   * Base address of a view.
-   */
-  void* BaseAddress();
 
   V8_INLINE static ArrayBufferView* Cast(Value* obj);
 
@@ -4590,11 +4549,6 @@
       ReturnAddressLocationResolver return_address_resolver);
 
   /**
-   * Deprecated, use the variant with the Isolate parameter below instead.
-   */
-  V8_DEPRECATED(static bool SetFunctionEntryHook(FunctionEntryHook entry_hook));
-
-  /**
    * Allows the host application to provide the address of a function that's
    * invoked on entry to every V8-generated function.
    * Note that \p entry_hook is invoked at the very start of each
@@ -4691,9 +4645,6 @@
    */
   static bool Dispose();
 
-  /** Deprecated. Use Isolate::GetHeapStatistics instead. */
-  V8_DEPRECATED(static void GetHeapStatistics(HeapStatistics* heap_statistics));
-
   /**
    * Iterates through all external resources referenced from current isolate
    * heap.  GC is not invoked prior to iterating, therefore there is no
@@ -4991,17 +4942,14 @@
       Handle<ObjectTemplate> global_template = Handle<ObjectTemplate>(),
       Handle<Value> global_object = Handle<Value>());
 
-  // TODO(dcarney):  Remove this function.
-  /** Deprecated. Use Isolate::GetEnteredContext */
-  static Local<Context> GetEntered();
+  V8_DEPRECATED("Use Isolate::GetEnteredContext instead",
+                static Local<Context> GetEntered());
 
-  // TODO(dcarney) Remove this function.
-  /** Deprecated. Use Isolate::GetCurrentContext instead. */
-  static Local<Context> GetCurrent();
+  V8_DEPRECATED("Use Isolate::GetCurrentContext instead",
+                static Local<Context> GetCurrent());
 
-  // TODO(dcarney) Remove this function.
-  /** Deprecated. Use Isolate::GetCallingContext instead. */
-  static Local<Context> GetCalling();
+  V8_DEPRECATED("Use Isolate::GetCallingContext instead",
+                static Local<Context> GetCalling());
 
   /**
    * Sets the security token for the context.  To access an object in
@@ -5210,9 +5158,6 @@
    */
   V8_INLINE explicit Unlocker(Isolate* isolate) { Initialize(isolate); }
 
-  /** Deprecated. Use Isolate version instead. */
-  V8_DEPRECATED(Unlocker());
-
   ~Unlocker();
  private:
   void Initialize(Isolate* isolate);
@@ -5228,9 +5173,6 @@
    */
   V8_INLINE explicit Locker(Isolate* isolate) { Initialize(isolate); }
 
-  /** Deprecated. Use Isolate version instead. */
-  V8_DEPRECATED(Locker());
-
   ~Locker();
 
   /**
@@ -5240,12 +5182,12 @@
    * that will switch between multiple threads that are in contention
    * for the V8 lock.
    */
-  static void StartPreemption(int every_n_ms);
+  static void StartPreemption(Isolate* isolate, int every_n_ms);
 
   /**
    * Stop preemption.
    */
-  static void StopPreemption();
+  static void StopPreemption(Isolate* isolate);
 
   /**
    * Returns whether or not the locker for a given isolate, is locked by the
diff --git a/include/v8config.h b/include/v8config.h
index 6fe5c5a..834f9c5 100644
--- a/include/v8config.h
+++ b/include/v8config.h
@@ -245,6 +245,7 @@
 // older compilers.
 # define V8_HAS_ATTRIBUTE_ALWAYS_INLINE (V8_GNUC_PREREQ(4, 4, 0))
 # define V8_HAS_ATTRIBUTE_DEPRECATED (V8_GNUC_PREREQ(3, 4, 0))
+# define V8_HAS_ATTRIBUTE_DEPRECATED_MESSAGE (V8_GNUC_PREREQ(4, 5, 0))
 # define V8_HAS_ATTRIBUTE_NOINLINE (V8_GNUC_PREREQ(3, 4, 0))
 # define V8_HAS_ATTRIBUTE_VISIBILITY (V8_GNUC_PREREQ(4, 3, 0))
 # define V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT \
@@ -320,12 +321,16 @@
 
 
 // A macro to mark classes or functions as deprecated.
-#if !V8_DISABLE_DEPRECATIONS && V8_HAS_ATTRIBUTE_DEPRECATED
-# define V8_DEPRECATED(declarator) declarator __attribute__((deprecated))
-#elif !V8_DISABLE_DEPRECATIONS && V8_HAS_DECLSPEC_DEPRECATED
-# define V8_DEPRECATED(declarator) __declspec(deprecated) declarator
+#if defined(V8_DEPRECATION_WARNINGS) && V8_HAS_ATTRIBUTE_DEPRECATED_MESSAGE
+# define V8_DEPRECATED(message, declarator) \
+declarator __attribute__((deprecated(message)))
+#elif defined(V8_DEPRECATION_WARNINGS) && V8_HAS_ATTRIBUTE_DEPRECATED
+# define V8_DEPRECATED(message, declarator) \
+declarator __attribute__((deprecated))
+#elif defined(V8_DEPRECATION_WARNINGS) && V8_HAS_DECLSPEC_DEPRECATED
+# define V8_DEPRECATED(message, declarator) __declspec(deprecated) declarator
 #else
-# define V8_DEPRECATED(declarator) declarator
+# define V8_DEPRECATED(message, declarator) declarator
 #endif
 
 
diff --git a/src/api.cc b/src/api.cc
index 6d62749..f5daba4 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -3936,7 +3936,7 @@
 }
 
 
-Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv,
+Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Value> recv,
                                         int argc,
                                         v8::Handle<v8::Value> argv[]) {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
@@ -3964,7 +3964,7 @@
   }
   EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> returned = i::Execution::Call(
-      isolate, fun, recv_obj, argc, args, &has_pending_exception);
+      isolate, fun, recv_obj, argc, args, &has_pending_exception, true);
   EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
   return Utils::ToLocal(scope.CloseAndEscape(returned));
 }
@@ -4048,7 +4048,7 @@
 }
 
 
-Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
+Local<v8::Value> Function::Call(v8::Handle<v8::Value> recv, int argc,
                                 v8::Handle<v8::Value> argv[]) {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   ON_BAILOUT(isolate, "v8::Function::Call()", return Local<v8::Value>());
@@ -4065,7 +4065,7 @@
     i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
     EXCEPTION_PREAMBLE(isolate);
     i::Handle<i::Object> returned = i::Execution::Call(
-        isolate, fun, recv_obj, argc, args, &has_pending_exception);
+        isolate, fun, recv_obj, argc, args, &has_pending_exception, true);
     EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Object>());
     raw_result = *returned;
   }
@@ -4709,39 +4709,6 @@
 }
 
 
-int String::WriteAscii(char* buffer,
-                       int start,
-                       int length,
-                       int options) const {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  LOG_API(isolate, "String::WriteAscii");
-  ENTER_V8(isolate);
-  ASSERT(start >= 0 && length >= -1);
-  i::Handle<i::String> str = Utils::OpenHandle(this);
-  isolate->string_tracker()->RecordWrite(str);
-  if (options & HINT_MANY_WRITES_EXPECTED) {
-    FlattenString(str);  // Flatten the string for efficiency.
-  }
-
-  int end = length;
-  if ((length == -1) || (length > str->length() - start)) {
-    end = str->length() - start;
-  }
-  if (end < 0) return 0;
-  i::StringCharacterStream write_stream(*str, isolate->write_iterator(), start);
-  int i;
-  for (i = 0; i < end; i++) {
-    char c = static_cast<char>(write_stream.GetNext());
-    if (c == '\0' && !(options & PRESERVE_ASCII_NULL)) c = ' ';
-    buffer[i] = c;
-  }
-  if (!(options & NO_NULL_TERMINATION) && (length == -1 || i < length)) {
-    buffer[i] = '\0';
-  }
-  return i;
-}
-
-
 template<typename CharType>
 static inline int WriteHelper(const String* string,
                               CharType* buffer,
@@ -4983,11 +4950,6 @@
 }
 
 
-bool v8::V8::SetFunctionEntryHook(FunctionEntryHook entry_hook) {
-  return SetFunctionEntryHook(Isolate::GetCurrent(), entry_hook);
-}
-
-
 bool v8::V8::SetFunctionEntryHook(Isolate* ext_isolate,
                                   FunctionEntryHook entry_hook) {
   ASSERT(ext_isolate != NULL);
@@ -5048,22 +5010,6 @@
                                   heap_size_limit_(0) { }
 
 
-void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
-  i::Isolate* isolate = i::Isolate::UncheckedCurrent();
-  if (isolate == NULL || !isolate->IsInitialized()) {
-    // Isolate is unitialized thus heap is not configured yet.
-    heap_statistics->total_heap_size_ = 0;
-    heap_statistics->total_heap_size_executable_ = 0;
-    heap_statistics->total_physical_size_ = 0;
-    heap_statistics->used_heap_size_ = 0;
-    heap_statistics->heap_size_limit_ = 0;
-    return;
-  }
-  Isolate* ext_isolate = reinterpret_cast<Isolate*>(isolate);
-  return ext_isolate->GetHeapStatistics(heap_statistics);
-}
-
-
 void v8::V8::VisitExternalResources(ExternalResourceVisitor* visitor) {
   i::Isolate* isolate = i::Isolate::Current();
   isolate->heap()->VisitExternalResources(visitor);
@@ -6022,15 +5968,6 @@
 }
 
 
-void* v8::ArrayBufferView::BaseAddress() {
-  i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
-  i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(obj->buffer()));
-  void* buffer_data = buffer->backing_store();
-  size_t byte_offset = static_cast<size_t>(obj->byte_offset()->Number());
-  return static_cast<uint8_t*>(buffer_data) + byte_offset;
-}
-
-
 size_t v8::TypedArray::Length() {
   i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
   return static_cast<size_t>(obj->length()->Number());
@@ -6976,11 +6913,6 @@
 }
 
 
-double CpuProfileNode::GetSelfSamplesCount() const {
-  return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
-}
-
-
 unsigned CpuProfileNode::GetHitCount() const {
   return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
 }
@@ -7534,7 +7466,7 @@
   isolate_->UnlinkDeferredHandles(this);
 
   for (int i = 0; i < blocks_.length(); i++) {
-#ifdef ENABLE_EXTRA_CHECKS
+#ifdef ENABLE_HANDLE_ZAPPING
     HandleScope::ZapRange(blocks_[i], &blocks_[i][kHandleBlockSize]);
 #endif
     isolate_->handle_scope_implementer()->ReturnBlock(blocks_[i]);
diff --git a/src/api.h b/src/api.h
index 8fb17a0..9197baf 100644
--- a/src/api.h
+++ b/src/api.h
@@ -667,7 +667,7 @@
 #ifdef DEBUG
     // SealHandleScope may make the prev_limit to point inside the block.
     if (block_start <= prev_limit && prev_limit <= block_limit) {
-#ifdef ENABLE_EXTRA_CHECKS
+#ifdef ENABLE_HANDLE_ZAPPING
       internal::HandleScope::ZapRange(prev_limit, block_limit);
 #endif
       break;
@@ -677,7 +677,7 @@
 #endif
 
     blocks_.RemoveLast();
-#ifdef ENABLE_EXTRA_CHECKS
+#ifdef ENABLE_HANDLE_ZAPPING
     internal::HandleScope::ZapRange(block_start, block_limit);
 #endif
     if (spare_ != NULL) {
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index d7b8f02..47dda2a 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -115,22 +115,47 @@
 // mode. This way we get the compile-time error checking in debug mode
 // and best performance in optimized code.
 
+// These constants are used in several locations, including static initializers
+const int kRegister_no_reg_Code = -1;
+const int kRegister_r0_Code = 0;
+const int kRegister_r1_Code = 1;
+const int kRegister_r2_Code = 2;
+const int kRegister_r3_Code = 3;
+const int kRegister_r4_Code = 4;
+const int kRegister_r5_Code = 5;
+const int kRegister_r6_Code = 6;
+const int kRegister_r7_Code = 7;
+const int kRegister_r8_Code = 8;
+const int kRegister_r9_Code = 9;
+const int kRegister_r10_Code = 10;
+const int kRegister_fp_Code = 11;
+const int kRegister_ip_Code = 12;
+const int kRegister_sp_Code = 13;
+const int kRegister_lr_Code = 14;
+const int kRegister_pc_Code = 15;
+
 // Core register
 struct Register {
   static const int kNumRegisters = 16;
   static const int kMaxNumAllocatableRegisters =
-      FLAG_enable_ool_constant_pool ? 7 : 8;
+      FLAG_enable_ool_constant_pool ? 8 : 9;
   static const int kSizeInBytes = 4;
 
   inline static int NumAllocatableRegisters();
 
   static int ToAllocationIndex(Register reg) {
+    if (FLAG_enable_ool_constant_pool && (reg.code() >= kRegister_r8_Code)) {
+      return reg.code() - 1;
+    }
     ASSERT(reg.code() < kMaxNumAllocatableRegisters);
     return reg.code();
   }
 
   static Register FromAllocationIndex(int index) {
     ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
+    if (FLAG_enable_ool_constant_pool && (index >= 7)) {
+      return from_code(index + 1);
+    }
     return from_code(index);
   }
 
@@ -145,7 +170,11 @@
       "r5",
       "r6",
       "r7",
+      "r8",
     };
+    if (FLAG_enable_ool_constant_pool && (index >= 7)) {
+      return names[index + 1];
+    }
     return names[index];
   }
 
@@ -174,25 +203,6 @@
   int code_;
 };
 
-// These constants are used in several locations, including static initializers
-const int kRegister_no_reg_Code = -1;
-const int kRegister_r0_Code = 0;
-const int kRegister_r1_Code = 1;
-const int kRegister_r2_Code = 2;
-const int kRegister_r3_Code = 3;
-const int kRegister_r4_Code = 4;
-const int kRegister_r5_Code = 5;
-const int kRegister_r6_Code = 6;
-const int kRegister_r7_Code = 7;
-const int kRegister_r8_Code = 8;
-const int kRegister_r9_Code = 9;
-const int kRegister_r10_Code = 10;
-const int kRegister_fp_Code = 11;
-const int kRegister_ip_Code = 12;
-const int kRegister_sp_Code = 13;
-const int kRegister_lr_Code = 14;
-const int kRegister_pc_Code = 15;
-
 const Register no_reg = { kRegister_no_reg_Code };
 
 const Register r0  = { kRegister_r0_Code };
@@ -202,7 +212,7 @@
 const Register r4  = { kRegister_r4_Code };
 const Register r5  = { kRegister_r5_Code };
 const Register r6  = { kRegister_r6_Code };
-// Used as constant pool pointer register if FLAGS_enable_ool_constant_pool.
+// Used as constant pool pointer register if FLAG_enable_ool_constant_pool.
 const Register r7  = { kRegister_r7_Code };
 // Used as context register.
 const Register r8  = { kRegister_r8_Code };
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 6fdbbb5..0ea235c 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -412,18 +412,19 @@
 }
 
 
-int LPlatformChunk::GetNextSpillIndex(bool is_double) {
+int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
   // Skip a slot if for a double-width slot.
-  if (is_double) spill_slot_count_++;
+  if (kind == DOUBLE_REGISTERS) spill_slot_count_++;
   return spill_slot_count_++;
 }
 
 
-LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double)  {
-  int index = GetNextSpillIndex(is_double);
-  if (is_double) {
+LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind)  {
+  int index = GetNextSpillIndex(kind);
+  if (kind == DOUBLE_REGISTERS) {
     return LDoubleStackSlot::Create(index, zone());
   } else {
+    ASSERT(kind == GENERAL_REGISTERS);
     return LStackSlot::Create(index, zone());
   }
 }
@@ -439,7 +440,7 @@
   // which will be subsumed into this frame.
   if (graph()->has_osr()) {
     for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) {
-      chunk_->GetNextSpillIndex(false);
+      chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
     }
   }
 
@@ -779,10 +780,11 @@
   HValue* right = instr->right();
   ASSERT(left->representation().IsTagged());
   ASSERT(right->representation().IsTagged());
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* left_operand = UseFixed(left, r1);
   LOperand* right_operand = UseFixed(right, r0);
   LArithmeticT* result =
-      new(zone()) LArithmeticT(op, left_operand, right_operand);
+      new(zone()) LArithmeticT(op, context, left_operand, right_operand);
   return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
@@ -1044,9 +1046,10 @@
 
 
 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   LInstanceOf* result =
-      new(zone()) LInstanceOf(UseFixed(instr->left(), r0),
-                      UseFixed(instr->right(), r1));
+      new(zone()) LInstanceOf(context, UseFixed(instr->left(), r0),
+                              UseFixed(instr->right(), r1));
   return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
@@ -1054,8 +1057,10 @@
 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
     HInstanceOfKnownGlobal* instr) {
   LInstanceOfKnownGlobal* result =
-      new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), r0),
-                                         FixedTemp(r4));
+      new(zone()) LInstanceOfKnownGlobal(
+          UseFixed(instr->context(), cp),
+          UseFixed(instr->left(), r0),
+          FixedTemp(r4));
   return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
@@ -1119,14 +1124,13 @@
 
 
 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
-  // If there is a non-return use, the context must be allocated in a register.
-  for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
-    if (!it.value()->IsReturn()) {
-      return DefineAsRegister(new(zone()) LContext);
-    }
+  if (instr->HasNoUses()) return NULL;
+
+  if (info()->IsStub()) {
+    return DefineFixed(new(zone()) LContext, cp);
   }
 
-  return NULL;
+  return DefineAsRegister(new(zone()) LContext);
 }
 
 
@@ -1137,7 +1141,8 @@
 
 
 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
-  return MarkAsCall(new(zone()) LDeclareGlobals, instr);
+  LOperand* context = UseFixed(instr->context(), cp);
+  return MarkAsCall(new(zone()) LDeclareGlobals(context), instr);
 }
 
 
@@ -1161,9 +1166,10 @@
 
 
 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* function = UseFixed(instr->function(), r1);
   argument_count_ -= instr->argument_count();
-  LInvokeFunction* result = new(zone()) LInvokeFunction(function);
+  LInvokeFunction* result = new(zone()) LInvokeFunction(context, function);
   return MarkAsCall(DefineFixed(result, r0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
 }
 
@@ -1203,8 +1209,12 @@
 
 
 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
+  Representation r = instr->value()->representation();
+  LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32())
+      ? NULL
+      : UseFixed(instr->context(), cp);
   LOperand* input = UseRegister(instr->value());
-  LMathAbs* result = new(zone()) LMathAbs(input);
+  LMathAbs* result = new(zone()) LMathAbs(context, input);
   return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
 }
 
@@ -1266,21 +1276,25 @@
 
 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
   ASSERT(instr->key()->representation().IsTagged());
+  LOperand* context = UseFixed(instr->context(), cp);
   argument_count_ -= instr->argument_count();
   LOperand* key = UseFixed(instr->key(), r2);
-  return MarkAsCall(DefineFixed(new(zone()) LCallKeyed(key), r0), instr);
+  return MarkAsCall(
+        DefineFixed(new(zone()) LCallKeyed(context, key), r0), instr);
 }
 
 
 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   argument_count_ -= instr->argument_count();
-  return MarkAsCall(DefineFixed(new(zone()) LCallNamed, r0), instr);
+  return MarkAsCall(DefineFixed(new(zone()) LCallNamed(context), r0), instr);
 }
 
 
 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   argument_count_ -= instr->argument_count();
-  return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, r0), instr);
+  return MarkAsCall(DefineFixed(new(zone()) LCallGlobal(context), r0), instr);
 }
 
 
@@ -1291,32 +1305,36 @@
 
 
 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* constructor = UseFixed(instr->constructor(), r1);
   argument_count_ -= instr->argument_count();
-  LCallNew* result = new(zone()) LCallNew(constructor);
+  LCallNew* result = new(zone()) LCallNew(context, constructor);
   return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
 
 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* constructor = UseFixed(instr->constructor(), r1);
   argument_count_ -= instr->argument_count();
-  LCallNewArray* result = new(zone()) LCallNewArray(constructor);
+  LCallNewArray* result = new(zone()) LCallNewArray(context, constructor);
   return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
 
 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* function = UseFixed(instr->function(), r1);
   argument_count_ -= instr->argument_count();
-  return MarkAsCall(DefineFixed(new(zone()) LCallFunction(function), r0),
-                    instr);
+  return MarkAsCall(
+      DefineFixed(new(zone()) LCallFunction(context, function), r0), instr);
 }
 
 
 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
   argument_count_ -= instr->argument_count();
-  return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, r0), instr);
+  LOperand* context = UseFixed(instr->context(), cp);
+  return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), r0), instr);
 }
 
 
@@ -1719,9 +1737,10 @@
 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
   ASSERT(instr->left()->representation().IsTagged());
   ASSERT(instr->right()->representation().IsTagged());
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* left = UseFixed(instr->left(), r1);
   LOperand* right = UseFixed(instr->right(), r0);
-  LCmpT* result = new(zone()) LCmpT(left, right);
+  LCmpT* result = new(zone()) LCmpT(context, left, right);
   return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
@@ -1795,10 +1814,11 @@
     HStringCompareAndBranch* instr) {
   ASSERT(instr->left()->representation().IsTagged());
   ASSERT(instr->right()->representation().IsTagged());
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* left = UseFixed(instr->left(), r1);
   LOperand* right = UseFixed(instr->right(), r0);
   LStringCompareAndBranch* result =
-      new(zone()) LStringCompareAndBranch(left, right);
+      new(zone()) LStringCompareAndBranch(context, left, right);
   return MarkAsCall(result, instr);
 }
 
@@ -1885,9 +1905,17 @@
 }
 
 
+LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
+  // The control instruction marking the end of a block that completed
+  // abruptly (e.g., threw an exception).  There is nothing specific to do.
+  return NULL;
+}
+
+
 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* value = UseFixed(instr->value(), r0);
-  return MarkAsCall(new(zone()) LThrow(value), instr);
+  return MarkAsCall(new(zone()) LThrow(context, value), instr);
 }
 
 
@@ -2067,8 +2095,11 @@
 
 
 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
+  LOperand* context = info()->IsStub()
+      ? UseFixed(instr->context(), cp)
+      : NULL;
   LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
-  return new(zone()) LReturn(UseFixed(instr->value(), r0),
+  return new(zone()) LReturn(UseFixed(instr->value(), r0), context,
                              parameter_count);
 }
 
@@ -2101,8 +2132,10 @@
 
 
 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* global_object = UseFixed(instr->global_object(), r0);
-  LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object);
+  LLoadGlobalGeneric* result =
+      new(zone()) LLoadGlobalGeneric(context, global_object);
   return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
@@ -2118,10 +2151,11 @@
 
 
 LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* global_object = UseFixed(instr->global_object(), r1);
   LOperand* value = UseFixed(instr->value(), r0);
   LStoreGlobalGeneric* result =
-      new(zone()) LStoreGlobalGeneric(global_object, value);
+      new(zone()) LStoreGlobalGeneric(context, global_object, value);
   return MarkAsCall(result, instr);
 }
 
@@ -2156,8 +2190,10 @@
 
 
 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* object = UseFixed(instr->object(), r0);
-  LInstruction* result = DefineFixed(new(zone()) LLoadNamedGeneric(object), r0);
+  LInstruction* result =
+      DefineFixed(new(zone()) LLoadNamedGeneric(context, object), r0);
   return MarkAsCall(result, instr);
 }
 
@@ -2218,11 +2254,12 @@
 
 
 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* object = UseFixed(instr->object(), r1);
   LOperand* key = UseFixed(instr->key(), r0);
 
   LInstruction* result =
-      DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), r0);
+      DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), r0);
   return MarkAsCall(result, instr);
 }
 
@@ -2271,6 +2308,7 @@
 
 
 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* obj = UseFixed(instr->object(), r2);
   LOperand* key = UseFixed(instr->key(), r1);
   LOperand* val = UseFixed(instr->value(), r0);
@@ -2279,7 +2317,8 @@
   ASSERT(instr->key()->representation().IsTagged());
   ASSERT(instr->value()->representation().IsTagged());
 
-  return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr);
+  return MarkAsCall(
+      new(zone()) LStoreKeyedGeneric(context, obj, key, val), instr);
 }
 
 
@@ -2289,11 +2328,12 @@
   if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
     LOperand* new_map_reg = TempRegister();
     LTransitionElementsKind* result =
-        new(zone()) LTransitionElementsKind(object, new_map_reg);
+        new(zone()) LTransitionElementsKind(object, NULL, new_map_reg);
     return result;
   } else {
+    LOperand* context = UseFixed(instr->context(), cp);
     LTransitionElementsKind* result =
-        new(zone()) LTransitionElementsKind(object, NULL);
+        new(zone()) LTransitionElementsKind(object, context, NULL);
     return AssignPointerMap(result);
   }
 }
@@ -2352,56 +2392,68 @@
 
 
 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* obj = UseFixed(instr->object(), r1);
   LOperand* val = UseFixed(instr->value(), r0);
 
-  LInstruction* result = new(zone()) LStoreNamedGeneric(obj, val);
+  LInstruction* result = new(zone()) LStoreNamedGeneric(context, obj, val);
   return MarkAsCall(result, instr);
 }
 
 
 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* left = UseRegisterAtStart(instr->left());
   LOperand* right = UseRegisterAtStart(instr->right());
-  return MarkAsCall(DefineFixed(new(zone()) LStringAdd(left, right), r0),
-                    instr);
+  return MarkAsCall(
+      DefineFixed(new(zone()) LStringAdd(context, left, right), r0),
+      instr);
 }
 
 
 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
   LOperand* string = UseTempRegister(instr->string());
   LOperand* index = UseTempRegister(instr->index());
-  LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index);
+  LOperand* context = UseAny(instr->context());
+  LStringCharCodeAt* result =
+      new(zone()) LStringCharCodeAt(context, string, index);
   return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
 }
 
 
 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
   LOperand* char_code = UseRegister(instr->value());
-  LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code);
+  LOperand* context = UseAny(instr->context());
+  LStringCharFromCode* result =
+      new(zone()) LStringCharFromCode(context, char_code);
   return AssignPointerMap(DefineAsRegister(result));
 }
 
 
 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
   info()->MarkAsDeferredCalling();
+  LOperand* context = UseAny(instr->context());
   LOperand* size = instr->size()->IsConstant()
       ? UseConstant(instr->size())
       : UseTempRegister(instr->size());
   LOperand* temp1 = TempRegister();
   LOperand* temp2 = TempRegister();
-  LAllocate* result = new(zone()) LAllocate(size, temp1, temp2);
+  LAllocate* result = new(zone()) LAllocate(context, size, temp1, temp2);
   return AssignPointerMap(DefineAsRegister(result));
 }
 
 
 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
-  return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, r0), instr);
+  LOperand* context = UseFixed(instr->context(), cp);
+  return MarkAsCall(
+      DefineFixed(new(zone()) LRegExpLiteral(context), r0), instr);
 }
 
 
 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
-  return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, r0), instr);
+  LOperand* context = UseFixed(instr->context(), cp);
+  return MarkAsCall(
+      DefineFixed(new(zone()) LFunctionLiteral(context), r0), instr);
 }
 
 
@@ -2448,8 +2500,9 @@
 
 
 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   argument_count_ -= instr->argument_count();
-  return MarkAsCall(DefineFixed(new(zone()) LCallStub, r0), instr);
+  return MarkAsCall(DefineFixed(new(zone()) LCallStub(context), r0), instr);
 }
 
 
@@ -2494,7 +2547,8 @@
 
 
 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
-  LTypeof* result = new(zone()) LTypeof(UseFixed(instr->value(), r0));
+  LOperand* context = UseFixed(instr->context(), cp);
+  LTypeof* result = new(zone()) LTypeof(context, UseFixed(instr->value(), r0));
   return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
@@ -2533,10 +2587,13 @@
 
 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
   if (instr->is_function_entry()) {
-    return MarkAsCall(new(zone()) LStackCheck, instr);
+    LOperand* context = UseFixed(instr->context(), cp);
+    return MarkAsCall(new(zone()) LStackCheck(context), instr);
   } else {
     ASSERT(instr->is_backwards_branch());
-    return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck));
+    LOperand* context = UseAny(instr->context());
+    return AssignEnvironment(
+        AssignPointerMap(new(zone()) LStackCheck(context)));
   }
 }
 
@@ -2581,8 +2638,9 @@
 
 
 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
+  LOperand* context = UseFixed(instr->context(), cp);
   LOperand* object = UseFixed(instr->enumerable(), r0);
-  LForInPrepareMap* result = new(zone()) LForInPrepareMap(object);
+  LForInPrepareMap* result = new(zone()) LForInPrepareMap(context, object);
   return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
 }
 
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 76867c8..e82c7c2 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -483,8 +483,14 @@
 };
 
 
-class LCallStub V8_FINAL : public LTemplateInstruction<1, 0, 0> {
+class LCallStub V8_FINAL : public LTemplateInstruction<1, 1, 0> {
  public:
+  explicit LCallStub(LOperand* context) {
+    inputs_[0] = context;
+  }
+
+  LOperand* context() { return inputs_[0]; }
+
   DECLARE_CONCRETE_INSTRUCTION(CallStub, "call-stub")
   DECLARE_HYDROGEN_ACCESSOR(CallStub)
 
@@ -785,12 +791,14 @@
 };
 
 
-class LMathAbs V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+class LMathAbs V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
-  explicit LMathAbs(LOperand* value) {
+  LMathAbs(LOperand* context, LOperand* value) {
+    inputs_[1] = context;
     inputs_[0] = value;
   }
 
+  LOperand* context() { return inputs_[1]; }
   LOperand* value() { return inputs_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(MathAbs, "math-abs")
@@ -989,15 +997,17 @@
 };
 
 
-class LStringCompareAndBranch V8_FINAL : public LControlInstruction<2, 0> {
+class LStringCompareAndBranch V8_FINAL : public LControlInstruction<3, 0> {
  public:
-  LStringCompareAndBranch(LOperand* left, LOperand* right) {
-    inputs_[0] = left;
-    inputs_[1] = right;
+  LStringCompareAndBranch(LOperand* context, LOperand* left, LOperand* right) {
+    inputs_[0] = context;
+    inputs_[1] = left;
+    inputs_[2] = right;
   }
 
-  LOperand* left() { return inputs_[0]; }
-  LOperand* right() { return inputs_[1]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* left() { return inputs_[1]; }
+  LOperand* right() { return inputs_[2]; }
 
   DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,
                                "string-compare-and-branch")
@@ -1073,15 +1083,17 @@
 };
 
 
-class LCmpT V8_FINAL : public LTemplateInstruction<1, 2, 0> {
+class LCmpT V8_FINAL : public LTemplateInstruction<1, 3, 0> {
  public:
-  LCmpT(LOperand* left, LOperand* right) {
-    inputs_[0] = left;
-    inputs_[1] = right;
+  LCmpT(LOperand* context, LOperand* left, LOperand* right) {
+    inputs_[0] = context;
+    inputs_[1] = left;
+    inputs_[2] = right;
   }
 
-  LOperand* left() { return inputs_[0]; }
-  LOperand* right() { return inputs_[1]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* left() { return inputs_[1]; }
+  LOperand* right() { return inputs_[2]; }
 
   DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t")
   DECLARE_HYDROGEN_ACCESSOR(CompareGeneric)
@@ -1090,28 +1102,32 @@
 };
 
 
-class LInstanceOf V8_FINAL : public LTemplateInstruction<1, 2, 0> {
+class LInstanceOf V8_FINAL : public LTemplateInstruction<1, 3, 0> {
  public:
-  LInstanceOf(LOperand* left, LOperand* right) {
-    inputs_[0] = left;
-    inputs_[1] = right;
+  LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
+    inputs_[0] = context;
+    inputs_[1] = left;
+    inputs_[2] = right;
   }
 
-  LOperand* left() { return inputs_[0]; }
-  LOperand* right() { return inputs_[1]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* left() { return inputs_[1]; }
+  LOperand* right() { return inputs_[2]; }
 
   DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
 };
 
 
-class LInstanceOfKnownGlobal V8_FINAL : public LTemplateInstruction<1, 1, 1> {
+class LInstanceOfKnownGlobal V8_FINAL : public LTemplateInstruction<1, 2, 1> {
  public:
-  LInstanceOfKnownGlobal(LOperand* value, LOperand* temp) {
-    inputs_[0] = value;
+  LInstanceOfKnownGlobal(LOperand* context, LOperand* value, LOperand* temp) {
+    inputs_[0] = context;
+    inputs_[1] = value;
     temps_[0] = temp;
   }
 
-  LOperand* value() { return inputs_[0]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* value() { return inputs_[1]; }
   LOperand* temp() { return temps_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
@@ -1392,13 +1408,15 @@
 };
 
 
-class LThrow V8_FINAL : public LTemplateInstruction<0, 1, 0> {
+class LThrow V8_FINAL : public LTemplateInstruction<0, 2, 0> {
  public:
-  explicit LThrow(LOperand* value) {
-    inputs_[0] = value;
+  LThrow(LOperand* context, LOperand* value) {
+    inputs_[0] = context;
+    inputs_[1] = value;
   }
 
-  LOperand* value() { return inputs_[0]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* value() { return inputs_[1]; }
 
   DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
 };
@@ -1494,16 +1512,21 @@
 };
 
 
-class LArithmeticT V8_FINAL : public LTemplateInstruction<1, 2, 0> {
+class LArithmeticT V8_FINAL : public LTemplateInstruction<1, 3, 0> {
  public:
-  LArithmeticT(Token::Value op, LOperand* left, LOperand* right)
+  LArithmeticT(Token::Value op,
+               LOperand* context,
+               LOperand* left,
+               LOperand* right)
       : op_(op) {
-    inputs_[0] = left;
-    inputs_[1] = right;
+    inputs_[0] = context;
+    inputs_[1] = left;
+    inputs_[2] = right;
   }
 
-  LOperand* left() { return inputs_[0]; }
-  LOperand* right() { return inputs_[1]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* left() { return inputs_[1]; }
+  LOperand* right() { return inputs_[2]; }
   Token::Value op() const { return op_; }
 
   virtual Opcode opcode() const V8_OVERRIDE {
@@ -1517,11 +1540,12 @@
 };
 
 
-class LReturn V8_FINAL : public LTemplateInstruction<0, 2, 0> {
+class LReturn V8_FINAL : public LTemplateInstruction<0, 3, 0> {
  public:
-  explicit LReturn(LOperand* value, LOperand* parameter_count) {
+  LReturn(LOperand* value, LOperand* context, LOperand* parameter_count) {
     inputs_[0] = value;
-    inputs_[1] = parameter_count;
+    inputs_[1] = context;
+    inputs_[2] = parameter_count;
   }
 
   LOperand* value() { return inputs_[0]; }
@@ -1533,7 +1557,7 @@
     ASSERT(has_constant_parameter_count());
     return LConstantOperand::cast(parameter_count());
   }
-  LOperand* parameter_count() { return inputs_[1]; }
+  LOperand* parameter_count() { return inputs_[2]; }
 
   DECLARE_CONCRETE_INSTRUCTION(Return, "return")
 };
@@ -1552,13 +1576,15 @@
 };
 
 
-class LLoadNamedGeneric V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+class LLoadNamedGeneric V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
-  explicit LLoadNamedGeneric(LOperand* object) {
-    inputs_[0] = object;
+  LLoadNamedGeneric(LOperand* context, LOperand* object) {
+    inputs_[0] = context;
+    inputs_[1] = object;
   }
 
-  LOperand* object() { return inputs_[0]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* object() { return inputs_[1]; }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
   DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)
@@ -1627,15 +1653,17 @@
 };
 
 
-class LLoadKeyedGeneric V8_FINAL : public LTemplateInstruction<1, 2, 0> {
+class LLoadKeyedGeneric V8_FINAL : public LTemplateInstruction<1, 3, 0> {
  public:
-  LLoadKeyedGeneric(LOperand* object, LOperand* key) {
-    inputs_[0] = object;
-    inputs_[1] = key;
+  LLoadKeyedGeneric(LOperand* context, LOperand* object, LOperand* key) {
+    inputs_[0] = context;
+    inputs_[1] = object;
+    inputs_[2] = key;
   }
 
-  LOperand* object() { return inputs_[0]; }
-  LOperand* key() { return inputs_[1]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* object() { return inputs_[1]; }
+  LOperand* key() { return inputs_[2]; }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
 };
@@ -1648,13 +1676,15 @@
 };
 
 
-class LLoadGlobalGeneric V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+class LLoadGlobalGeneric V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
-  explicit LLoadGlobalGeneric(LOperand* global_object) {
-    inputs_[0] = global_object;
+  LLoadGlobalGeneric(LOperand* context, LOperand* global_object) {
+    inputs_[0] = context;
+    inputs_[1] = global_object;
   }
 
-  LOperand* global_object() { return inputs_[0]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* global_object() { return inputs_[1]; }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
   DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
@@ -1679,16 +1709,19 @@
 };
 
 
-class LStoreGlobalGeneric V8_FINAL : public LTemplateInstruction<0, 2, 0> {
+class LStoreGlobalGeneric V8_FINAL : public LTemplateInstruction<0, 3, 0> {
  public:
-  explicit LStoreGlobalGeneric(LOperand* global_object,
-                               LOperand* value) {
-    inputs_[0] = global_object;
-    inputs_[1] = value;
+  LStoreGlobalGeneric(LOperand* context,
+                      LOperand* global_object,
+                      LOperand* value) {
+    inputs_[0] = context;
+    inputs_[1] = global_object;
+    inputs_[2] = value;
   }
 
-  LOperand* global_object() { return inputs_[0]; }
-  LOperand* value() { return inputs_[1]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* global_object() { return inputs_[1]; }
+  LOperand* value() { return inputs_[2]; }
 
   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store-global-generic")
   DECLARE_HYDROGEN_ACCESSOR(StoreGlobalGeneric)
@@ -1818,8 +1851,14 @@
 };
 
 
-class LDeclareGlobals V8_FINAL : public LTemplateInstruction<0, 0, 0> {
+class LDeclareGlobals V8_FINAL : public LTemplateInstruction<0, 1, 0> {
  public:
+  explicit LDeclareGlobals(LOperand* context) {
+    inputs_[0] = context;
+  }
+
+  LOperand* context() { return inputs_[0]; }
+
   DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals")
   DECLARE_HYDROGEN_ACCESSOR(DeclareGlobals)
 };
@@ -1861,13 +1900,15 @@
 };
 
 
-class LInvokeFunction V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+class LInvokeFunction V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
-  explicit LInvokeFunction(LOperand* function) {
-    inputs_[0] = function;
+  LInvokeFunction(LOperand* context, LOperand* function) {
+    inputs_[0] = context;
+    inputs_[1] = function;
   }
 
-  LOperand* function() { return inputs_[0]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* function() { return inputs_[1]; }
 
   DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
   DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
@@ -1878,13 +1919,15 @@
 };
 
 
-class LCallKeyed V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+class LCallKeyed V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
-  explicit LCallKeyed(LOperand* key) {
-    inputs_[0] = key;
+  LCallKeyed(LOperand* context, LOperand* key) {
+    inputs_[0] = context;
+    inputs_[1] = key;
   }
 
-  LOperand* key() { return inputs_[0]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
 
   DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call-keyed")
   DECLARE_HYDROGEN_ACCESSOR(CallKeyed)
@@ -1896,8 +1939,14 @@
 
 
 
-class LCallNamed V8_FINAL : public LTemplateInstruction<1, 0, 0> {
+class LCallNamed V8_FINAL : public LTemplateInstruction<1, 1, 0> {
  public:
+  explicit LCallNamed(LOperand* context) {
+    inputs_[0] = context;
+  }
+
+  LOperand* context() { return inputs_[0]; }
+
   DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call-named")
   DECLARE_HYDROGEN_ACCESSOR(CallNamed)
 
@@ -1908,13 +1957,15 @@
 };
 
 
-class LCallFunction V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+class LCallFunction V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
-  explicit LCallFunction(LOperand* function) {
-    inputs_[0] = function;
+  LCallFunction(LOperand* context, LOperand* function) {
+    inputs_[0] = context;
+    inputs_[1] = function;
   }
 
-  LOperand* function() { return inputs_[0]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* function() { return inputs_[1]; }
 
   DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function")
   DECLARE_HYDROGEN_ACCESSOR(CallFunction)
@@ -1923,8 +1974,14 @@
 };
 
 
-class LCallGlobal V8_FINAL : public LTemplateInstruction<1, 0, 0> {
+class LCallGlobal V8_FINAL : public LTemplateInstruction<1, 1, 0> {
  public:
+  explicit LCallGlobal(LOperand* context) {
+    inputs_[0] = context;
+  }
+
+  LOperand* context() { return inputs_[0]; }
+
   DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call-global")
   DECLARE_HYDROGEN_ACCESSOR(CallGlobal)
 
@@ -1946,13 +2003,15 @@
 };
 
 
-class LCallNew V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+class LCallNew V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
-  explicit LCallNew(LOperand* constructor) {
-    inputs_[0] = constructor;
+  LCallNew(LOperand* context, LOperand* constructor) {
+    inputs_[0] = context;
+    inputs_[1] = constructor;
   }
 
-  LOperand* constructor() { return inputs_[0]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* constructor() { return inputs_[1]; }
 
   DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new")
   DECLARE_HYDROGEN_ACCESSOR(CallNew)
@@ -1963,13 +2022,15 @@
 };
 
 
-class LCallNewArray V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+class LCallNewArray V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
-  explicit LCallNewArray(LOperand* constructor) {
-    inputs_[0] = constructor;
+  LCallNewArray(LOperand* context, LOperand* constructor) {
+    inputs_[0] = context;
+    inputs_[1] = constructor;
   }
 
-  LOperand* constructor() { return inputs_[0]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* constructor() { return inputs_[1]; }
 
   DECLARE_CONCRETE_INSTRUCTION(CallNewArray, "call-new-array")
   DECLARE_HYDROGEN_ACCESSOR(CallNewArray)
@@ -1980,8 +2041,14 @@
 };
 
 
-class LCallRuntime V8_FINAL : public LTemplateInstruction<1, 0, 0> {
+class LCallRuntime V8_FINAL : public LTemplateInstruction<1, 1, 0> {
  public:
+  explicit LCallRuntime(LOperand* context) {
+    inputs_[0] = context;
+  }
+
+  LOperand* context() { return inputs_[0]; }
+
   DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
   DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
 
@@ -2187,15 +2254,17 @@
 };
 
 
-class LStoreNamedGeneric V8_FINAL : public LTemplateInstruction<0, 2, 0> {
+class LStoreNamedGeneric V8_FINAL : public LTemplateInstruction<0, 3, 0> {
  public:
-  LStoreNamedGeneric(LOperand* object, LOperand* value) {
-    inputs_[0] = object;
-    inputs_[1] = value;
+  LStoreNamedGeneric(LOperand* context, LOperand* object, LOperand* value) {
+    inputs_[0] = context;
+    inputs_[1] = object;
+    inputs_[2] = value;
   }
 
-  LOperand* object() { return inputs_[0]; }
-  LOperand* value() { return inputs_[1]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* object() { return inputs_[1]; }
+  LOperand* value() { return inputs_[2]; }
 
   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
   DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
@@ -2238,17 +2307,22 @@
 };
 
 
-class LStoreKeyedGeneric V8_FINAL : public LTemplateInstruction<0, 3, 0> {
+class LStoreKeyedGeneric V8_FINAL : public LTemplateInstruction<0, 4, 0> {
  public:
-  LStoreKeyedGeneric(LOperand* obj, LOperand* key, LOperand* value) {
-    inputs_[0] = obj;
-    inputs_[1] = key;
-    inputs_[2] = value;
+  LStoreKeyedGeneric(LOperand* context,
+                     LOperand* obj,
+                     LOperand* key,
+                     LOperand* value) {
+    inputs_[0] = context;
+    inputs_[1] = obj;
+    inputs_[2] = key;
+    inputs_[3] = value;
   }
 
-  LOperand* object() { return inputs_[0]; }
-  LOperand* key() { return inputs_[1]; }
-  LOperand* value() { return inputs_[2]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* object() { return inputs_[1]; }
+  LOperand* key() { return inputs_[2]; }
+  LOperand* value() { return inputs_[3]; }
 
   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
   DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
@@ -2259,14 +2333,17 @@
 };
 
 
-class LTransitionElementsKind V8_FINAL : public LTemplateInstruction<0, 1, 1> {
+class LTransitionElementsKind V8_FINAL : public LTemplateInstruction<0, 2, 1> {
  public:
   LTransitionElementsKind(LOperand* object,
+                          LOperand* context,
                           LOperand* new_map_temp) {
     inputs_[0] = object;
+    inputs_[1] = context;
     temps_[0] = new_map_temp;
   }
 
+  LOperand* context() { return inputs_[1]; }
   LOperand* object() { return inputs_[0]; }
   LOperand* new_map_temp() { return temps_[0]; }
 
@@ -2301,15 +2378,17 @@
 };
 
 
-class LStringAdd V8_FINAL : public LTemplateInstruction<1, 2, 0> {
+class LStringAdd V8_FINAL : public LTemplateInstruction<1, 3, 0> {
  public:
-  LStringAdd(LOperand* left, LOperand* right) {
-    inputs_[0] = left;
-    inputs_[1] = right;
+  LStringAdd(LOperand* context, LOperand* left, LOperand* right) {
+    inputs_[0] = context;
+    inputs_[1] = left;
+    inputs_[2] = right;
   }
 
-  LOperand* left() { return inputs_[0]; }
-  LOperand* right() { return inputs_[1]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* left() { return inputs_[1]; }
+  LOperand* right() { return inputs_[2]; }
 
   DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add")
   DECLARE_HYDROGEN_ACCESSOR(StringAdd)
@@ -2317,28 +2396,32 @@
 
 
 
-class LStringCharCodeAt V8_FINAL : public LTemplateInstruction<1, 2, 0> {
+class LStringCharCodeAt V8_FINAL : public LTemplateInstruction<1, 3, 0> {
  public:
-  LStringCharCodeAt(LOperand* string, LOperand* index) {
-    inputs_[0] = string;
-    inputs_[1] = index;
+  LStringCharCodeAt(LOperand* context, LOperand* string, LOperand* index) {
+    inputs_[0] = context;
+    inputs_[1] = string;
+    inputs_[2] = index;
   }
 
-  LOperand* string() { return inputs_[0]; }
-  LOperand* index() { return inputs_[1]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* string() { return inputs_[1]; }
+  LOperand* index() { return inputs_[2]; }
 
   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at")
   DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt)
 };
 
 
-class LStringCharFromCode V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+class LStringCharFromCode V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
-  explicit LStringCharFromCode(LOperand* char_code) {
-    inputs_[0] = char_code;
+  explicit LStringCharFromCode(LOperand* context, LOperand* char_code) {
+    inputs_[0] = context;
+    inputs_[1] = char_code;
   }
 
-  LOperand* char_code() { return inputs_[0]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* char_code() { return inputs_[1]; }
 
   DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
   DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
@@ -2449,12 +2532,17 @@
 
 class LAllocate V8_FINAL : public LTemplateInstruction<1, 2, 2> {
  public:
-  LAllocate(LOperand* size, LOperand* temp1, LOperand* temp2) {
+  LAllocate(LOperand* context,
+            LOperand* size,
+            LOperand* temp1,
+            LOperand* temp2) {
+    inputs_[0] = context;
     inputs_[1] = size;
     temps_[0] = temp1;
     temps_[1] = temp2;
   }
 
+  LOperand* context() { return inputs_[0]; }
   LOperand* size() { return inputs_[1]; }
   LOperand* temp1() { return temps_[0]; }
   LOperand* temp2() { return temps_[1]; }
@@ -2464,15 +2552,27 @@
 };
 
 
-class LRegExpLiteral V8_FINAL : public LTemplateInstruction<1, 0, 0> {
+class LRegExpLiteral V8_FINAL : public LTemplateInstruction<1, 1, 0> {
  public:
+  explicit LRegExpLiteral(LOperand* context) {
+    inputs_[0] = context;
+  }
+
+  LOperand* context() { return inputs_[0]; }
+
   DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp-literal")
   DECLARE_HYDROGEN_ACCESSOR(RegExpLiteral)
 };
 
 
-class LFunctionLiteral V8_FINAL : public LTemplateInstruction<1, 0, 0> {
+class LFunctionLiteral V8_FINAL : public LTemplateInstruction<1, 1, 0> {
  public:
+  explicit LFunctionLiteral(LOperand* context) {
+    inputs_[0] = context;
+  }
+
+  LOperand* context() { return inputs_[0]; }
+
   DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function-literal")
   DECLARE_HYDROGEN_ACCESSOR(FunctionLiteral)
 };
@@ -2491,13 +2591,15 @@
 };
 
 
-class LTypeof V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+class LTypeof V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
-  explicit LTypeof(LOperand* value) {
-    inputs_[0] = value;
+  LTypeof(LOperand* context, LOperand* value) {
+    inputs_[0] = context;
+    inputs_[1] = value;
   }
 
-  LOperand* value() { return inputs_[0]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* value() { return inputs_[1]; }
 
   DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
 };
@@ -2544,8 +2646,14 @@
 };
 
 
-class LStackCheck V8_FINAL : public LTemplateInstruction<0, 0, 0> {
+class LStackCheck V8_FINAL : public LTemplateInstruction<0, 1, 0> {
  public:
+  explicit LStackCheck(LOperand* context) {
+    inputs_[0] = context;
+  }
+
+  LOperand* context() { return inputs_[0]; }
+
   DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
   DECLARE_HYDROGEN_ACCESSOR(StackCheck)
 
@@ -2556,13 +2664,15 @@
 };
 
 
-class LForInPrepareMap V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+class LForInPrepareMap V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
-  explicit LForInPrepareMap(LOperand* object) {
-    inputs_[0] = object;
+  LForInPrepareMap(LOperand* context, LOperand* object) {
+    inputs_[0] = context;
+    inputs_[1] = object;
   }
 
-  LOperand* object() { return inputs_[0]; }
+  LOperand* context() { return inputs_[0]; }
+  LOperand* object() { return inputs_[1]; }
 
   DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map")
 };
@@ -2618,8 +2728,8 @@
   LPlatformChunk(CompilationInfo* info, HGraph* graph)
       : LChunk(info, graph) { }
 
-  int GetNextSpillIndex(bool is_double);
-  LOperand* GetNextSpillSlot(bool is_double);
+  int GetNextSpillIndex(RegisterKind kind);
+  LOperand* GetNextSpillSlot(RegisterKind kind);
 };
 
 
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index ca38743..e7734c1 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -248,6 +248,8 @@
 
   // Trace the call.
   if (FLAG_trace && info()->IsOptimizing()) {
+    // We have not executed any compiled code yet, so cp still holds the
+    // incoming context.
     __ CallRuntime(Runtime::kTraceEnter, 0);
   }
   return !is_aborted();
@@ -759,9 +761,22 @@
 }
 
 
+void LCodeGen::LoadContextFromDeferred(LOperand* context) {
+  if (context->IsRegister()) {
+    __ Move(cp, ToRegister(context));
+  } else if (context->IsStackSlot()) {
+    __ ldr(cp, ToMemOperand(context));
+  } else {
+    UNREACHABLE();
+  }
+}
+
+
 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
                                        int argc,
-                                       LInstruction* instr) {
+                                       LInstruction* instr,
+                                       LOperand* context) {
+  LoadContextFromDeferred(context);
   __ CallRuntimeSaveDoubles(id);
   RecordSafepointWithRegisters(
       instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
@@ -977,10 +992,6 @@
       safepoint.DefinePointerRegister(ToRegister(pointer), zone());
     }
   }
-  if (kind & Safepoint::kWithRegisters) {
-    // Register cp always contains a pointer to the context.
-    safepoint.DefinePointerRegister(cp, zone());
-  }
 }
 
 
@@ -1073,6 +1084,7 @@
 
 
 void LCodeGen::DoCallStub(LCallStub* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->result()).is(r0));
   switch (instr->hydrogen()->major_key()) {
     case CodeStub::RegExpConstructResult: {
@@ -2023,6 +2035,7 @@
 void LCodeGen::DoThrow(LThrow* instr) {
   Register input_reg = EmitLoadRegister(instr->value(), ip);
   __ push(input_reg);
+  ASSERT(ToRegister(instr->context()).is(cp));
   CallRuntime(Runtime::kThrow, 1, instr);
 
   if (FLAG_debug_code) {
@@ -2160,6 +2173,7 @@
 
 
 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->left()).is(r1));
   ASSERT(ToRegister(instr->right()).is(r0));
   ASSERT(ToRegister(instr->result()).is(r0));
@@ -2571,6 +2585,7 @@
 
 
 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   Token::Value op = instr->op();
 
   Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
@@ -2731,6 +2746,7 @@
 
 
 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->left()).is(r0));  // Object is in r0.
   ASSERT(ToRegister(instr->right()).is(r1));  // Function is in r1.
 
@@ -2840,6 +2856,7 @@
   InstanceofStub stub(flags);
 
   PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
+  LoadContextFromDeferred(instr->context());
 
   // Get the temp register reserved by the instruction. This needs to be r4 as
   // its slot of the pushing of safepoint registers is used to communicate the
@@ -2884,6 +2901,7 @@
 
 
 void LCodeGen::DoCmpT(LCmpT* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   Token::Value op = instr->op();
 
   Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
@@ -2904,8 +2922,11 @@
 void LCodeGen::DoReturn(LReturn* instr) {
   if (FLAG_trace && info()->IsOptimizing()) {
     // Push the return value on the stack as the parameter.
-    // Runtime::TraceExit returns its parameter in r0.
+    // Runtime::TraceExit returns its parameter in r0.  We're leaving the code
+    // managed by the register allocator and tearing down the frame, it's
+    // safe to write to the context register.
     __ push(r0);
+    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
     __ CallRuntime(Runtime::kTraceExit, 1);
   }
   if (info()->saves_caller_doubles()) {
@@ -2960,6 +2981,7 @@
 
 
 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->global_object()).is(r0));
   ASSERT(ToRegister(instr->result()).is(r0));
 
@@ -2997,6 +3019,7 @@
 
 
 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->global_object()).is(r1));
   ASSERT(ToRegister(instr->value()).is(r0));
 
@@ -3090,6 +3113,7 @@
 
 
 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->object()).is(r0));
   ASSERT(ToRegister(instr->result()).is(r0));
 
@@ -3383,6 +3407,7 @@
 
 
 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->object()).is(r1));
   ASSERT(ToRegister(instr->key()).is(r0));
 
@@ -3527,7 +3552,6 @@
   ParameterCount actual(receiver);
   __ InvokeFunction(function, actual, CALL_FUNCTION,
                     safepoint_generator, CALL_AS_METHOD);
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
 }
 
 
@@ -3556,11 +3580,11 @@
 void LCodeGen::DoContext(LContext* instr) {
   // If there is a non-return use, the context must be moved to a register.
   Register result = ToRegister(instr->result());
-  for (HUseIterator it(instr->hydrogen()->uses()); !it.Done(); it.Advance()) {
-    if (!it.value()->IsReturn()) {
-      __ mov(result, cp);
-      return;
-    }
+  if (info()->IsOptimizing()) {
+    __ ldr(result, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  } else {
+    // If there is no frame, the context must be in cp.
+    ASSERT(result.is(cp));
   }
 }
 
@@ -3574,6 +3598,7 @@
 
 
 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   __ push(cp);  // The context is the first argument.
   __ LoadHeapObject(scratch0(), instr->hydrogen()->pairs());
   __ push(scratch0());
@@ -3584,8 +3609,9 @@
 
 
 void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
+  Register context = ToRegister(instr->context());
   Register result = ToRegister(instr->result());
-  __ ldr(result, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
+  __ ldr(result, ContextOperand(context, Context::GLOBAL_OBJECT_INDEX));
 }
 
 
@@ -3638,9 +3664,6 @@
     __ InvokeFunction(
         function, expected, count, CALL_FUNCTION, generator, call_kind);
   }
-
-  // Restore context.
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
 }
 
 
@@ -3656,6 +3679,8 @@
 
 
 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
+  ASSERT(instr->context() != NULL);
+  ASSERT(ToRegister(instr->context()).is(cp));
   Register input = ToRegister(instr->value());
   Register result = ToRegister(instr->result());
   Register scratch = scratch0();
@@ -3699,7 +3724,8 @@
     // Slow case: Call the runtime system to do the number allocation.
     __ bind(&slow);
 
-    CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
+    CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr,
+                            instr->context());
     // 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.
@@ -3970,6 +3996,9 @@
 
 void LCodeGen::DoMathLog(LMathLog* instr) {
   ASSERT(ToDoubleRegister(instr->result()).is(d2));
+  // Set the context register to a GC-safe fake value. Clobbering it is
+  // OK because this instruction is marked as a call.
+  __ mov(cp, Operand::Zero());
   TranscendentalCacheStub stub(TranscendentalCache::LOG,
                                TranscendentalCacheStub::UNTAGGED);
   CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
@@ -3978,6 +4007,9 @@
 
 void LCodeGen::DoMathTan(LMathTan* instr) {
   ASSERT(ToDoubleRegister(instr->result()).is(d2));
+  // Set the context register to a GC-safe fake value. Clobbering it is
+  // OK because this instruction is marked as a call.
+  __ mov(cp, Operand::Zero());
   TranscendentalCacheStub stub(TranscendentalCache::TAN,
                                TranscendentalCacheStub::UNTAGGED);
   CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
@@ -3986,6 +4018,9 @@
 
 void LCodeGen::DoMathCos(LMathCos* instr) {
   ASSERT(ToDoubleRegister(instr->result()).is(d2));
+  // Set the context register to a GC-safe fake value. Clobbering it is
+  // OK because this instruction is marked as a call.
+  __ mov(cp, Operand::Zero());
   TranscendentalCacheStub stub(TranscendentalCache::COS,
                                TranscendentalCacheStub::UNTAGGED);
   CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
@@ -3994,6 +4029,9 @@
 
 void LCodeGen::DoMathSin(LMathSin* instr) {
   ASSERT(ToDoubleRegister(instr->result()).is(d2));
+  // Set the context register to a GC-safe fake value. Clobbering it is
+  // OK because this instruction is marked as a call.
+  __ mov(cp, Operand::Zero());
   TranscendentalCacheStub stub(TranscendentalCache::SIN,
                                TranscendentalCacheStub::UNTAGGED);
   CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
@@ -4001,6 +4039,7 @@
 
 
 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->function()).is(r1));
   ASSERT(instr->HasPointerMap());
 
@@ -4011,7 +4050,6 @@
     SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
     ParameterCount count(instr->arity());
     __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
-    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   } else {
     CallKnownFunction(known_function,
                       instr->hydrogen()->formal_parameter_count(),
@@ -4024,17 +4062,18 @@
 
 
 void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->result()).is(r0));
 
   int arity = instr->arity();
   Handle<Code> ic =
       isolate()->stub_cache()->ComputeKeyedCallInitialize(arity);
   CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
 }
 
 
 void LCodeGen::DoCallNamed(LCallNamed* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->result()).is(r0));
 
   int arity = instr->arity();
@@ -4043,23 +4082,22 @@
       isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
   __ mov(r2, Operand(instr->name()));
   CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS);
-  // Restore context register.
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
 }
 
 
 void LCodeGen::DoCallFunction(LCallFunction* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->function()).is(r1));
   ASSERT(ToRegister(instr->result()).is(r0));
 
   int arity = instr->arity();
   CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS);
   CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
 }
 
 
 void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->result()).is(r0));
 
   int arity = instr->arity();
@@ -4068,7 +4106,6 @@
       isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
   __ mov(r2, Operand(instr->name()));
   CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS);
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
 }
 
 
@@ -4084,6 +4121,7 @@
 
 
 void LCodeGen::DoCallNew(LCallNew* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->constructor()).is(r1));
   ASSERT(ToRegister(instr->result()).is(r0));
 
@@ -4097,6 +4135,7 @@
 
 
 void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->constructor()).is(r1));
   ASSERT(ToRegister(instr->result()).is(r0));
 
@@ -4248,6 +4287,7 @@
 
 
 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->object()).is(r1));
   ASSERT(ToRegister(instr->value()).is(r0));
 
@@ -4471,6 +4511,7 @@
 
 
 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   ASSERT(ToRegister(instr->object()).is(r2));
   ASSERT(ToRegister(instr->key()).is(r1));
   ASSERT(ToRegister(instr->value()).is(r0));
@@ -4504,6 +4545,7 @@
     __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
                         scratch, GetLinkRegisterState(), kDontSaveFPRegs);
   } else {
+    ASSERT(ToRegister(instr->context()).is(cp));
     PushSafepointRegistersScope scope(
         this, Safepoint::kWithRegistersAndDoubles);
     __ Move(r0, object_reg);
@@ -4526,6 +4568,7 @@
 
 
 void LCodeGen::DoStringAdd(LStringAdd* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   __ push(ToRegister(instr->left()));
   __ push(ToRegister(instr->right()));
   StringAddStub stub(instr->hydrogen()->flags());
@@ -4581,7 +4624,8 @@
     __ SmiTag(index);
     __ push(index);
   }
-  CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr);
+  CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr,
+                          instr->context());
   __ AssertSmi(r0);
   __ SmiUntag(r0);
   __ StoreToSafepointRegisterSlot(r0, result);
@@ -4633,7 +4677,7 @@
   PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
   __ SmiTag(char_code);
   __ push(char_code);
-  CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr);
+  CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context());
   __ StoreToSafepointRegisterSlot(r0, result);
 }
 
@@ -4772,7 +4816,15 @@
   // integer value.
   __ mov(ip, Operand::Zero());
   __ StoreToSafepointRegisterSlot(ip, dst);
-  CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
+  // NumberTagI and NumberTagD use the context from the frame, rather than
+  // the environment's HContext or HInlinedContext value.
+  // They only call Runtime::kAllocateHeapNumber.
+  // The corresponding HChange instructions are added in a phase that does
+  // not have easy access to the local context.
+  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
+  RecordSafepointWithRegisters(
+      instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
   __ Move(dst, r0);
   __ sub(dst, dst, Operand(kHeapObjectTag));
 
@@ -4828,7 +4880,15 @@
   __ mov(reg, Operand::Zero());
 
   PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
-  CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
+  // NumberTagI and NumberTagD use the context from the frame, rather than
+  // the environment's HContext or HInlinedContext value.
+  // They only call Runtime::kAllocateHeapNumber.
+  // The corresponding HChange instructions are added in a phase that does
+  // not have easy access to the local context.
+  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
+  RecordSafepointWithRegisters(
+      instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
   __ sub(r0, r0, Operand(kHeapObjectTag));
   __ StoreToSafepointRegisterSlot(r0, reg);
 }
@@ -5157,7 +5217,10 @@
   {
     PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
     __ push(object);
-    CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr);
+    __ mov(cp, Operand::Zero());
+    __ CallRuntimeSaveDoubles(Runtime::kMigrateInstance);
+    RecordSafepointWithRegisters(
+        instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
     __ StoreToSafepointRegisterSlot(r0, scratch0());
   }
   __ tst(scratch0(), Operand(kSmiTagMask));
@@ -5360,12 +5423,15 @@
   if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
     ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation());
     ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
-    CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr);
+    CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr,
+                            instr->context());
   } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
     ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
-    CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr);
+    CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr,
+                            instr->context());
   } else {
-    CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
+    CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr,
+                            instr->context());
   }
   __ StoreToSafepointRegisterSlot(r0, result);
 }
@@ -5379,6 +5445,7 @@
 
 
 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   Label materialized;
   // Registers will be used as follows:
   // r6 = literals array.
@@ -5422,6 +5489,7 @@
 
 
 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
+  ASSERT(ToRegister(instr->context()).is(cp));
   // Use the fast case closure allocation code that allocates in new
   // space for nested functions that don't need literals cloning.
   bool pretenure = instr->hydrogen()->pretenure();
@@ -5616,6 +5684,7 @@
 
 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
   PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
+  LoadContextFromDeferred(instr->context());
   __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
   RecordSafepointWithLazyDeopt(
       instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
@@ -5649,9 +5718,11 @@
     __ cmp(sp, Operand(ip));
     __ b(hs, &done);
     PredictableCodeSizeScope predictable(masm_, 2 * Assembler::kInstrSize);
+    ASSERT(instr->context()->IsRegister());
+    ASSERT(ToRegister(instr->context()).is(cp));
     CallCode(isolate()->builtins()->StackCheck(),
-             RelocInfo::CODE_TARGET,
-             instr);
+              RelocInfo::CODE_TARGET,
+              instr);
     EnsureSpaceForLazyDeopt();
     last_lazy_deopt_pc_ = masm()->pc_offset();
     __ bind(&done);
diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h
index 4b6b5ca..3016b45 100644
--- a/src/arm/lithium-codegen-arm.h
+++ b/src/arm/lithium-codegen-arm.h
@@ -258,9 +258,11 @@
     CallRuntime(function, num_arguments, instr);
   }
 
+  void LoadContextFromDeferred(LOperand* context);
   void CallRuntimeFromDeferred(Runtime::FunctionId id,
                                int argc,
-                               LInstruction* instr);
+                               LInstruction* instr,
+                               LOperand* context);
 
   enum R1State {
     R1_UNINITIALIZED,
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index fd51521..8fcde6b 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -478,11 +478,6 @@
                                  SaveFPRegsMode fp_mode,
                                  RememberedSetAction remembered_set_action,
                                  SmiCheck smi_check) {
-  // The compiled code assumes that record write doesn't change the
-  // context register, so we check that none of the clobbered
-  // registers are cp.
-  ASSERT(!address.is(cp) && !value.is(cp));
-
   if (emit_debug_code()) {
     ldr(ip, MemOperand(address));
     cmp(ip, value);
diff --git a/src/compiler.h b/src/compiler.h
index dc7c19f..84416fe 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -534,7 +534,7 @@
   }
 
   void WaitForInstall() {
-    ASSERT(!info_->osr_ast_id().IsNone());
+    ASSERT(info_->is_osr());
     awaiting_install_ = true;
   }
 
diff --git a/src/d8.cc b/src/d8.cc
index 1c6e453..6eb7248 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -1528,7 +1528,7 @@
     // Start preemption if threads have been created and preemption is enabled.
     if (threads.length() > 0
         && options.use_preemption) {
-      Locker::StartPreemption(options.preemption_interval);
+      Locker::StartPreemption(isolate, options.preemption_interval);
     }
 #endif  // V8_SHARED
   }
@@ -1546,7 +1546,7 @@
 
   if (threads.length() > 0 && options.use_preemption) {
     Locker lock(isolate);
-    Locker::StopPreemption();
+    Locker::StopPreemption(isolate);
   }
 #endif  // V8_SHARED
   return 0;
diff --git a/src/global-handles.cc b/src/global-handles.cc
index 1a98e49..2ebe1c0 100644
--- a/src/global-handles.cc
+++ b/src/global-handles.cc
@@ -79,7 +79,7 @@
                   Internals::kNodeIsPartiallyDependentShift);
   }
 
-#ifdef ENABLE_EXTRA_CHECKS
+#ifdef ENABLE_HANDLE_ZAPPING
   ~Node() {
     // TODO(1428): if it's a weak handle we should have invoked its callback.
     // Zap the values for eager trapping.
diff --git a/src/handles-inl.h b/src/handles-inl.h
index 5b879d8..ec69c3f 100644
--- a/src/handles-inl.h
+++ b/src/handles-inl.h
@@ -130,16 +130,17 @@
   v8::ImplementationUtilities::HandleScopeData* current =
       isolate->handle_scope_data();
 
-  current->next = prev_next;
+  std::swap(current->next, prev_next);
   current->level--;
   if (current->limit != prev_limit) {
     current->limit = prev_limit;
     DeleteExtensions(isolate);
-  }
-
-#ifdef ENABLE_EXTRA_CHECKS
-  ZapRange(prev_next, prev_limit);
+#ifdef ENABLE_HANDLE_ZAPPING
+    ZapRange(current->next, prev_limit);
+  } else {
+    ZapRange(current->next, prev_next);
 #endif
+  }
 }
 
 
diff --git a/src/handles.cc b/src/handles.cc
index 6b9025d..054dde3 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -101,7 +101,7 @@
 }
 
 
-#ifdef ENABLE_EXTRA_CHECKS
+#ifdef ENABLE_HANDLE_ZAPPING
 void HandleScope::ZapRange(Object** start, Object** end) {
   ASSERT(end - start <= kHandleBlockSize);
   for (Object** p = start; p != end; p++) {
diff --git a/src/handles.h b/src/handles.h
index 0f619d5..05b0c5e 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -177,7 +177,7 @@
   // Extend the handle scope making room for more handles.
   static internal::Object** Extend(Isolate* isolate);
 
-#ifdef ENABLE_EXTRA_CHECKS
+#ifdef ENABLE_HANDLE_ZAPPING
   // Zaps the handles in the half-open interval [start, end).
   static void ZapRange(Object** start, Object** end);
 #endif
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 97e1b0e..382dc16 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -64,6 +64,7 @@
 
 
 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)  \
+  V(AbnormalExit)                              \
   V(AccessArgumentsAt)                         \
   V(Add)                                       \
   V(Allocate)                                  \
@@ -1457,6 +1458,16 @@
 };
 
 
+class HAbnormalExit V8_FINAL : public HTemplateControlInstruction<0, 0> {
+ public:
+  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
+    return Representation::None();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
+};
+
+
 class HUnaryOperation : public HTemplateInstruction<1> {
  public:
   HUnaryOperation(HValue* value, HType type = HType::Tagged())
diff --git a/src/hydrogen-osr.cc b/src/hydrogen-osr.cc
index e95967e..3492deb 100644
--- a/src/hydrogen-osr.cc
+++ b/src/hydrogen-osr.cc
@@ -37,19 +37,8 @@
 }
 
 
-// Build a new loop header block and set it as the current block.
-HBasicBlock *HOsrBuilder::BuildLoopEntry() {
-  HBasicBlock* loop_entry = builder_->CreateLoopHeaderBlock();
-  builder_->current_block()->Goto(loop_entry);
-  builder_->set_current_block(loop_entry);
-  return loop_entry;
-}
-
-
-HBasicBlock* HOsrBuilder::BuildPossibleOsrLoopEntry(
-    IterationStatement* statement) {
-  // Check if there is an OSR here first.
-  if (!HasOsrEntryAt(statement)) return BuildLoopEntry();
+HBasicBlock* HOsrBuilder::BuildOsrLoopEntry(IterationStatement* statement) {
+  ASSERT(HasOsrEntryAt(statement));
 
   Zone* zone = builder_->zone();
   HGraph* graph = builder_->graph();
@@ -113,7 +102,7 @@
   builder_->set_current_block(loop_predecessor);
 
   // Create the final loop entry
-  osr_loop_entry_ = BuildLoopEntry();
+  osr_loop_entry_ = builder_->BuildLoopEntry();
   return osr_loop_entry_;
 }
 
diff --git a/src/hydrogen-osr.h b/src/hydrogen-osr.h
index 5014a75..ae72ce6 100644
--- a/src/hydrogen-osr.h
+++ b/src/hydrogen-osr.h
@@ -45,9 +45,10 @@
       osr_entry_(NULL),
       osr_loop_entry_(NULL),
       osr_values_(NULL) { }
+
   // Creates the loop entry block for the given statement, setting up OSR
   // entries as necessary, and sets the current block to the new block.
-  HBasicBlock* BuildPossibleOsrLoopEntry(IterationStatement* statement);
+  HBasicBlock* BuildOsrLoopEntry(IterationStatement* statement);
 
   // Process the hydrogen graph after it has been completed, performing
   // any OSR-specific cleanups or changes.
@@ -61,10 +62,9 @@
     return unoptimized_frame_slots_;
   }
 
- private:
-  HBasicBlock* BuildLoopEntry();
   bool HasOsrEntryAt(IterationStatement* statement);
 
+ private:
   int unoptimized_frame_slots_;
   HOptimizedGraphBuilder* builder_;
   HBasicBlock* osr_entry_;
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 57ea173..8681026 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -2246,6 +2246,24 @@
 }
 
 
+// Build a new loop header block and set it as the current block.
+HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() {
+  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
+  current_block()->Goto(loop_entry);
+  set_current_block(loop_entry);
+  return loop_entry;
+}
+
+
+HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
+    IterationStatement* statement) {
+  HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement)
+      ? osr()->BuildOsrLoopEntry(statement)
+      : BuildLoopEntry();
+  return loop_entry;
+}
+
+
 void HBasicBlock::FinishExit(HControlInstruction* instruction) {
   Finish(instruction);
   ClearEnvironment();
@@ -3087,7 +3105,7 @@
   type_info->set_inlined_type_change_checksum(composite_checksum);
 
   // Perform any necessary OSR-specific cleanups or changes to the graph.
-  osr_->FinishGraph();
+  osr()->FinishGraph();
 
   return true;
 }
@@ -3670,7 +3688,7 @@
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
   ASSERT(current_block() != NULL);
-  HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
+  HBasicBlock* loop_entry = BuildLoopEntry(stmt);
 
   BreakAndContinueInfo break_info(stmt);
   CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
@@ -3709,7 +3727,7 @@
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
   ASSERT(current_block() != NULL);
-  HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
+  HBasicBlock* loop_entry = BuildLoopEntry(stmt);
 
   // If the condition is constant true, do not generate a branch.
   HBasicBlock* loop_successor = NULL;
@@ -3751,7 +3769,7 @@
     CHECK_ALIVE(Visit(stmt->init()));
   }
   ASSERT(current_block() != NULL);
-  HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
+  HBasicBlock* loop_entry = BuildLoopEntry(stmt);
 
   HBasicBlock* loop_successor = NULL;
   if (stmt->cond() != NULL) {
@@ -3834,7 +3852,7 @@
   HForInCacheArray::cast(array)->set_index_cache(
       HForInCacheArray::cast(index_cache));
 
-  HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
+  HBasicBlock* loop_entry = BuildLoopEntry(stmt);
 
   HValue* index = environment()->ExpressionStackAt(0);
   HValue* limit = environment()->ExpressionStackAt(1);
@@ -5473,6 +5491,14 @@
   HThrow* instr = Add<HThrow>(value);
   instr->set_position(expr->position());
   Add<HSimulate>(expr->id());
+
+  // If the throw definitely exits the function, we can finish with a dummy
+  // control flow at this point.  This is not the case if the throw is inside
+  // an inlined function which may be replaced.
+  if (call_context() == NULL) {
+    current_block()->FinishExit(new(zone()) HAbnormalExit);
+    set_current_block(NULL);
+  }
 }
 
 
diff --git a/src/hydrogen.h b/src/hydrogen.h
index be23fa8..9b998c9 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -1781,6 +1781,8 @@
 
   HValue* context() { return environment()->context(); }
 
+  HOsrBuilder* osr() const { return osr_; }
+
   void Bailout(BailoutReason reason);
 
   HBasicBlock* CreateJoin(HBasicBlock* first,
@@ -1886,6 +1888,12 @@
                           HBasicBlock* loop_successor,
                           HBasicBlock* break_block);
 
+  // Build a loop entry
+  HBasicBlock* BuildLoopEntry();
+
+  // Builds a loop entry respectful of OSR requirements
+  HBasicBlock* BuildLoopEntry(IterationStatement* statement);
+
   HBasicBlock* JoinContinue(IterationStatement* statement,
                             HBasicBlock* exit_block,
                             HBasicBlock* continue_block);
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 86ac466..385ad2c 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -5741,6 +5741,7 @@
 
   ASSERT(instr->unclamped()->Equals(instr->result()));
   Register input_reg = ToRegister(instr->unclamped());
+  XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp_xmm());
   XMMRegister xmm_scratch = double_scratch0();
   Label is_smi, done, heap_number;
 
@@ -5761,7 +5762,7 @@
   // Heap number
   __ bind(&heap_number);
   __ movdbl(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset));
-  __ ClampDoubleToUint8(xmm_scratch, xmm1, input_reg);
+  __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg);
   __ jmp(&done, Label::kNear);
 
   // smi
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index c73d073..bfcbfb9 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -386,9 +386,9 @@
 }
 
 
-int LPlatformChunk::GetNextSpillIndex(bool is_double) {
+int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
   // Skip a slot if for a double-width slot.
-  if (is_double) {
+  if (kind == DOUBLE_REGISTERS) {
     spill_slot_count_++;
     spill_slot_count_ |= 1;
     num_double_slots_++;
@@ -397,11 +397,12 @@
 }
 
 
-LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double) {
-  int index = GetNextSpillIndex(is_double);
-  if (is_double) {
+LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
+  int index = GetNextSpillIndex(kind);
+  if (kind == DOUBLE_REGISTERS) {
     return LDoubleStackSlot::Create(index, zone());
   } else {
+    ASSERT(kind == GENERAL_REGISTERS);
     return LStackSlot::Create(index, zone());
   }
 }
@@ -479,7 +480,7 @@
 
   // Reserve the first spill slot for the state of dynamic alignment.
   if (info()->IsOptimizing()) {
-    int alignment_state_index = chunk_->GetNextSpillIndex(false);
+    int alignment_state_index = chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
     ASSERT_EQ(alignment_state_index, 0);
     USE(alignment_state_index);
   }
@@ -488,7 +489,7 @@
   // which will be subsumed into this frame.
   if (graph()->has_osr()) {
     for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) {
-      chunk_->GetNextSpillIndex(false);
+      chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
     }
   }
 
@@ -1883,6 +1884,13 @@
 }
 
 
+LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
+  // The control instruction marking the end of a block that completed
+  // abruptly (e.g., threw an exception).  There is nothing specific to do.
+  return NULL;
+}
+
+
 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
   LOperand* context = UseFixed(instr->context(), esi);
   LOperand* value = UseFixed(instr->value(), eax);
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index 379d64b..27d432f 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -2508,12 +2508,13 @@
 
 class LClampTToUint8 V8_FINAL : public LTemplateInstruction<1, 1, 1> {
  public:
-  LClampTToUint8(LOperand* value, LOperand* temp) {
+  LClampTToUint8(LOperand* value, LOperand* temp_xmm) {
     inputs_[0] = value;
-    temps_[0] = temp;
+    temps_[0] = temp_xmm;
   }
 
   LOperand* unclamped() { return inputs_[0]; }
+  LOperand* temp_xmm() { return temps_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8")
 };
@@ -2735,8 +2736,8 @@
       : LChunk(info, graph),
         num_double_slots_(0) { }
 
-  int GetNextSpillIndex(bool is_double);
-  LOperand* GetNextSpillSlot(bool is_double);
+  int GetNextSpillIndex(RegisterKind kind);
+  LOperand* GetNextSpillSlot(RegisterKind kind);
 
   int num_double_slots() const { return num_double_slots_; }
 
diff --git a/src/isolate.cc b/src/isolate.cc
index 3e5d2b9..de67a1c 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -1929,7 +1929,7 @@
     deoptimizer_data_ = NULL;
     if (FLAG_preemption) {
       v8::Locker locker(reinterpret_cast<v8::Isolate*>(this));
-      v8::Locker::StopPreemption();
+      v8::Locker::StopPreemption(reinterpret_cast<v8::Isolate*>(this));
     }
     builtins_.TearDown();
     bootstrapper_->TearDown();
@@ -2271,7 +2271,7 @@
 
   if (FLAG_preemption) {
     v8::Locker locker(reinterpret_cast<v8::Isolate*>(this));
-    v8::Locker::StartPreemption(100);
+    v8::Locker::StartPreemption(reinterpret_cast<v8::Isolate*>(this), 100);
   }
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
diff --git a/src/lithium-allocator-inl.h b/src/lithium-allocator-inl.h
index 8cca19b..deee988 100644
--- a/src/lithium-allocator-inl.h
+++ b/src/lithium-allocator-inl.h
@@ -145,16 +145,14 @@
 }
 
 
-void LAllocator::SetLiveRangeAssignedRegister(
-    LiveRange* range,
-    int reg,
-    RegisterKind register_kind) {
-  if (register_kind == DOUBLE_REGISTERS) {
+void LAllocator::SetLiveRangeAssignedRegister(LiveRange* range, int reg) {
+  if (range->Kind() == DOUBLE_REGISTERS) {
     assigned_double_registers_->Add(reg);
   } else {
+    ASSERT(range->Kind() == GENERAL_REGISTERS);
     assigned_registers_->Add(reg);
   }
-  range->set_assigned_register(reg, register_kind, chunk()->zone());
+  range->set_assigned_register(reg, chunk()->zone());
 }
 
 
diff --git a/src/lithium-allocator.cc b/src/lithium-allocator.cc
index 3c5abd1..29c3194 100644
--- a/src/lithium-allocator.cc
+++ b/src/lithium-allocator.cc
@@ -131,7 +131,7 @@
 LiveRange::LiveRange(int id, Zone* zone)
     : id_(id),
       spilled_(false),
-      is_double_(false),
+      kind_(UNALLOCATED_REGISTERS),
       assigned_register_(kInvalidAssignment),
       last_interval_(NULL),
       first_interval_(NULL),
@@ -145,12 +145,9 @@
       spill_start_index_(kMaxInt) { }
 
 
-void LiveRange::set_assigned_register(int reg,
-                                      RegisterKind register_kind,
-                                      Zone* zone) {
+void LiveRange::set_assigned_register(int reg, Zone* zone) {
   ASSERT(!HasRegisterAssigned() && !IsSpilled());
   assigned_register_ = reg;
-  is_double_ = (register_kind == DOUBLE_REGISTERS);
   ConvertOperands(zone);
 }
 
@@ -234,10 +231,15 @@
   LOperand* op = NULL;
   if (HasRegisterAssigned()) {
     ASSERT(!IsSpilled());
-    if (IsDouble()) {
-      op = LDoubleRegister::Create(assigned_register(), zone);
-    } else {
-      op = LRegister::Create(assigned_register(), zone);
+    switch (Kind()) {
+      case GENERAL_REGISTERS:
+        op = LRegister::Create(assigned_register(), zone);
+        break;
+      case DOUBLE_REGISTERS:
+        op = LDoubleRegister::Create(assigned_register(), zone);
+        break;
+      default:
+        UNREACHABLE();
     }
   } else if (IsSpilled()) {
     ASSERT(!HasRegisterAssigned());
@@ -352,6 +354,7 @@
   // Link the new live range in the chain before any of the other
   // ranges linked from the range before the split.
   result->parent_ = (parent_ == NULL) ? this : parent_;
+  result->kind_ = result->parent_->kind_;
   result->next_ = next_;
   next_ = result;
 
@@ -553,7 +556,7 @@
       reusable_slots_(8, zone()),
       next_virtual_register_(num_values),
       first_artificial_register_(num_values),
-      mode_(GENERAL_REGISTERS),
+      mode_(UNALLOCATED_REGISTERS),
       num_registers_(-1),
       graph_(graph),
       has_osr_entry_(false),
@@ -653,7 +656,8 @@
   if (result == NULL) {
     result = new(zone()) LiveRange(FixedLiveRangeID(index), chunk()->zone());
     ASSERT(result->IsFixed());
-    SetLiveRangeAssignedRegister(result, index, GENERAL_REGISTERS);
+    result->kind_ = GENERAL_REGISTERS;
+    SetLiveRangeAssignedRegister(result, index);
     fixed_live_ranges_[index] = result;
   }
   return result;
@@ -667,7 +671,8 @@
     result = new(zone()) LiveRange(FixedDoubleLiveRangeID(index),
                                    chunk()->zone());
     ASSERT(result->IsFixed());
-    SetLiveRangeAssignedRegister(result, index, DOUBLE_REGISTERS);
+    result->kind_ = DOUBLE_REGISTERS;
+    SetLiveRangeAssignedRegister(result, index);
     fixed_double_live_ranges_[index] = result;
   }
   return result;
@@ -1375,6 +1380,12 @@
     }
 #endif
   }
+
+  for (int i = 0; i < live_ranges_.length(); ++i) {
+    if (live_ranges_[i] != NULL) {
+      live_ranges_[i]->kind_ = RequiredRegisterKind(live_ranges_[i]->id());
+    }
+  }
 }
 
 
@@ -1481,6 +1492,7 @@
 void LAllocator::AllocateGeneralRegisters() {
   LAllocatorPhase phase("L_Allocate general registers", this);
   num_registers_ = Register::NumAllocatableRegisters();
+  mode_ = GENERAL_REGISTERS;
   AllocateRegisters();
 }
 
@@ -1498,7 +1510,7 @@
 
   for (int i = 0; i < live_ranges_.length(); ++i) {
     if (live_ranges_[i] != NULL) {
-      if (RequiredRegisterKind(live_ranges_[i]->id()) == mode_) {
+      if (live_ranges_[i]->Kind() == mode_) {
         AddToUnhandledUnsorted(live_ranges_[i]);
       }
     }
@@ -1518,6 +1530,7 @@
       }
     }
   } else {
+    ASSERT(mode_ == GENERAL_REGISTERS);
     for (int i = 0; i < fixed_live_ranges_.length(); ++i) {
       LiveRange* current = fixed_live_ranges_.at(i);
       if (current != NULL) {
@@ -1812,7 +1825,7 @@
       TraceAlloc("Assigning preferred reg %s to live range %d\n",
                  RegisterName(register_index),
                  current->id());
-      SetLiveRangeAssignedRegister(current, register_index, mode_);
+      SetLiveRangeAssignedRegister(current, register_index);
       return true;
     }
   }
@@ -1847,7 +1860,7 @@
   TraceAlloc("Assigning free reg %s to live range %d\n",
              RegisterName(reg),
              current->id());
-  SetLiveRangeAssignedRegister(current, reg, mode_);
+  SetLiveRangeAssignedRegister(current, reg);
 
   return true;
 }
@@ -1932,7 +1945,7 @@
   TraceAlloc("Assigning blocked reg %s to live range %d\n",
              RegisterName(reg),
              current->id());
-  SetLiveRangeAssignedRegister(current, reg, mode_);
+  SetLiveRangeAssignedRegister(current, reg);
 
   // This register was not free. Thus we need to find and spill
   // parts of active and inactive live regions that use the same register
@@ -2149,7 +2162,7 @@
 
   if (!first->HasAllocatedSpillOperand()) {
     LOperand* op = TryReuseSpillSlot(range);
-    if (op == NULL) op = chunk_->GetNextSpillSlot(mode_ == DOUBLE_REGISTERS);
+    if (op == NULL) op = chunk_->GetNextSpillSlot(range->Kind());
     first->SetSpillOperand(op);
   }
   range->MakeSpilled(chunk()->zone());
diff --git a/src/lithium-allocator.h b/src/lithium-allocator.h
index e5edd3c..9908ea8 100644
--- a/src/lithium-allocator.h
+++ b/src/lithium-allocator.h
@@ -146,6 +146,7 @@
 
 
 enum RegisterKind {
+  UNALLOCATED_REGISTERS,
   GENERAL_REGISTERS,
   DOUBLE_REGISTERS
 };
@@ -290,9 +291,7 @@
   LOperand* CreateAssignedOperand(Zone* zone);
   int assigned_register() const { return assigned_register_; }
   int spill_start_index() const { return spill_start_index_; }
-  void set_assigned_register(int reg,
-                             RegisterKind register_kind,
-                             Zone* zone);
+  void set_assigned_register(int reg, Zone* zone);
   void MakeSpilled(Zone* zone);
 
   // Returns use position in this live range that follows both start
@@ -323,7 +322,7 @@
   // live range to the result live range.
   void SplitAt(LifetimePosition position, LiveRange* result, Zone* zone);
 
-  bool IsDouble() const { return is_double_; }
+  RegisterKind Kind() const { return kind_; }
   bool HasRegisterAssigned() const {
     return assigned_register_ != kInvalidAssignment;
   }
@@ -392,7 +391,7 @@
 
   int id_;
   bool spilled_;
-  bool is_double_;
+  RegisterKind kind_;
   int assigned_register_;
   UseInterval* last_interval_;
   UseInterval* first_interval_;
@@ -406,6 +405,8 @@
   LOperand* current_hint_operand_;
   LOperand* spill_operand_;
   int spill_start_index_;
+
+  friend class LAllocator;  // Assigns to kind_.
 };
 
 
@@ -568,9 +569,7 @@
                           HBasicBlock* block,
                           HBasicBlock* pred);
 
-  inline void SetLiveRangeAssignedRegister(LiveRange* range,
-                                           int reg,
-                                           RegisterKind register_kind);
+  inline void SetLiveRangeAssignedRegister(LiveRange* range, int reg);
 
   // Return parallel move that should be used to connect ranges split at the
   // given position.
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index c869184..97dcd16 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -1403,11 +1403,11 @@
   Register left = ToRegister(instr->left());
   LOperand* right_op = instr->right();
 
-  bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
   bool bailout_on_minus_zero =
     instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
+  bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
 
-  if (right_op->IsConstantOperand() && !can_overflow) {
+  if (right_op->IsConstantOperand()) {
     int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
 
     if (bailout_on_minus_zero && (constant < 0)) {
@@ -1418,7 +1418,12 @@
 
     switch (constant) {
       case -1:
-        __ Subu(result, zero_reg, left);
+        if (overflow) {
+          __ SubuAndCheckForOverflow(result, zero_reg, left, scratch);
+          DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg));
+        } else {
+          __ Subu(result, zero_reg, left);
+        }
         break;
       case 0:
         if (bailout_on_minus_zero) {
@@ -1439,27 +1444,23 @@
         int32_t mask = constant >> 31;
         uint32_t constant_abs = (constant + mask) ^ mask;
 
-        if (IsPowerOf2(constant_abs) ||
-            IsPowerOf2(constant_abs - 1) ||
-            IsPowerOf2(constant_abs + 1)) {
-          if (IsPowerOf2(constant_abs)) {
-            int32_t shift = WhichPowerOf2(constant_abs);
-            __ sll(result, left, shift);
-          } else if (IsPowerOf2(constant_abs - 1)) {
-            int32_t shift = WhichPowerOf2(constant_abs - 1);
-            __ sll(scratch, left, shift);
-            __ Addu(result, scratch, left);
-          } else if (IsPowerOf2(constant_abs + 1)) {
-            int32_t shift = WhichPowerOf2(constant_abs + 1);
-            __ sll(scratch, left, shift);
-            __ Subu(result, scratch, left);
-          }
-
-          // Correct the sign of the result is the constant is negative.
-          if (constant < 0)  {
-            __ Subu(result, zero_reg, result);
-          }
-
+        if (IsPowerOf2(constant_abs)) {
+          int32_t shift = WhichPowerOf2(constant_abs);
+          __ sll(result, left, shift);
+          // Correct the sign of the result if the constant is negative.
+          if (constant < 0)  __ Subu(result, zero_reg, result);
+        } else if (IsPowerOf2(constant_abs - 1)) {
+          int32_t shift = WhichPowerOf2(constant_abs - 1);
+          __ sll(scratch, left, shift);
+          __ Addu(result, scratch, left);
+          // Correct the sign of the result if the constant is negative.
+          if (constant < 0)  __ Subu(result, zero_reg, result);
+        } else if (IsPowerOf2(constant_abs + 1)) {
+          int32_t shift = WhichPowerOf2(constant_abs + 1);
+          __ sll(scratch, left, shift);
+          __ Subu(result, scratch, left);
+          // Correct the sign of the result if the constant is negative.
+          if (constant < 0)  __ Subu(result, zero_reg, result);
         } else {
           // Generate standard code.
           __ li(at, constant);
@@ -1468,12 +1469,10 @@
     }
 
   } else {
-    Register right = EmitLoadRegister(right_op, scratch);
-    if (bailout_on_minus_zero) {
-      __ Or(ToRegister(instr->temp()), left, right);
-    }
+    ASSERT(right_op->IsRegister());
+    Register right = ToRegister(right_op);
 
-    if (can_overflow) {
+    if (overflow) {
       // hi:lo = left * right.
       if (instr->hydrogen()->representation().IsSmi()) {
         __ SmiUntag(result, left);
@@ -1497,12 +1496,13 @@
     }
 
     if (bailout_on_minus_zero) {
-      // Bail out if the result is supposed to be negative zero.
       Label done;
-      __ Branch(&done, ne, result, Operand(zero_reg));
-      DeoptimizeIf(lt,
+      __ Xor(at, left, right);
+      __ Branch(&done, ge, at, Operand(zero_reg));
+      // Bail out if the result is minus zero.
+      DeoptimizeIf(eq,
                    instr->environment(),
-                   ToRegister(instr->temp()),
+                   result,
                    Operand(zero_reg));
       __ bind(&done);
     }
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index 730c1d0..8a34912 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -417,18 +417,19 @@
 }
 
 
-int LPlatformChunk::GetNextSpillIndex(bool is_double) {
+int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
   // Skip a slot if for a double-width slot.
-  if (is_double) spill_slot_count_++;
+  if (kind == DOUBLE_REGISTERS) spill_slot_count_++;
   return spill_slot_count_++;
 }
 
 
-LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double)  {
-  int index = GetNextSpillIndex(is_double);
-  if (is_double) {
+LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind)  {
+  int index = GetNextSpillIndex(kind);
+  if (kind == DOUBLE_REGISTERS) {
     return LDoubleStackSlot::Create(index, zone());
   } else {
+    ASSERT(kind == GENERAL_REGISTERS);
     return LStackSlot::Create(index, zone());
   }
 }
@@ -444,7 +445,7 @@
   // which will be subsumed into this frame.
   if (graph()->has_osr()) {
     for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) {
-      chunk_->GetNextSpillIndex(false);
+      chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
     }
   }
 
@@ -1469,20 +1470,39 @@
   if (instr->representation().IsSmiOrInteger32()) {
     ASSERT(instr->left()->representation().Equals(instr->representation()));
     ASSERT(instr->right()->representation().Equals(instr->representation()));
-    LOperand* left;
-    LOperand* right = UseOrConstant(instr->BetterRightOperand());
-    LOperand* temp = NULL;
-    if (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
-        (instr->CheckFlag(HValue::kCanOverflow) ||
-        !right->IsConstantOperand())) {
-      left = UseRegister(instr->BetterLeftOperand());
-      temp = TempRegister();
+    HValue* left = instr->BetterLeftOperand();
+    HValue* right = instr->BetterRightOperand();
+    LOperand* left_op;
+    LOperand* right_op;
+    bool can_overflow = instr->CheckFlag(HValue::kCanOverflow);
+    bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero);
+
+    if (right->IsConstant()) {
+      HConstant* constant = HConstant::cast(right);
+      int32_t constant_value = constant->Integer32Value();
+      // Constants -1, 0 and 1 can be optimized if the result can overflow.
+      // For other constants, it can be optimized only without overflow.
+      if (!can_overflow || ((constant_value >= -1) && (constant_value <= 1))) {
+        left_op = UseRegisterAtStart(left);
+        right_op = UseConstant(right);
+      } else {
+        if (bailout_on_minus_zero) {
+          left_op = UseRegister(left);
+        } else {
+          left_op = UseRegisterAtStart(left);
+        }
+        right_op = UseRegister(right);
+      }
     } else {
-      left = UseRegisterAtStart(instr->BetterLeftOperand());
+      if (bailout_on_minus_zero) {
+        left_op = UseRegister(left);
+      } else {
+        left_op = UseRegisterAtStart(left);
+      }
+      right_op = UseRegister(right);
     }
-    LMulI* mul = new(zone()) LMulI(left, right, temp);
-    if (instr->CheckFlag(HValue::kCanOverflow) ||
-        instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    LMulI* mul = new(zone()) LMulI(left_op, right_op);
+    if (can_overflow || bailout_on_minus_zero) {
       AssignEnvironment(mul);
     }
     return DefineAsRegister(mul);
@@ -1786,6 +1806,13 @@
 }
 
 
+LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
+  // The control instruction marking the end of a block that completed
+  // abruptly (e.g., threw an exception).  There is nothing specific to do.
+  return NULL;
+}
+
+
 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
   LOperand* value = UseFixed(instr->value(), a0);
   return MarkAsCall(new(zone()) LThrow(value), instr);
diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h
index a8ca620..a48422e 100644
--- a/src/mips/lithium-mips.h
+++ b/src/mips/lithium-mips.h
@@ -688,17 +688,15 @@
 };
 
 
-class LMulI V8_FINAL : public LTemplateInstruction<1, 2, 1> {
+class LMulI V8_FINAL : public LTemplateInstruction<1, 2, 0> {
  public:
-  LMulI(LOperand* left, LOperand* right, LOperand* temp) {
+  LMulI(LOperand* left, LOperand* right) {
     inputs_[0] = left;
     inputs_[1] = right;
-    temps_[0] = temp;
   }
 
   LOperand* left() { return inputs_[0]; }
   LOperand* right() { return inputs_[1]; }
-  LOperand* temp() { return temps_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
   DECLARE_HYDROGEN_ACCESSOR(Mul)
@@ -2594,8 +2592,8 @@
   LPlatformChunk(CompilationInfo* info, HGraph* graph)
       : LChunk(info, graph) { }
 
-  int GetNextSpillIndex(bool is_double);
-  LOperand* GetNextSpillSlot(bool is_double);
+  int GetNextSpillIndex(RegisterKind kind);
+  LOperand* GetNextSpillSlot(RegisterKind kind);
 };
 
 
diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
index ea8b659..5a96efe 100644
--- a/src/mips/simulator-mips.cc
+++ b/src/mips/simulator-mips.cc
@@ -2274,9 +2274,13 @@
           break;
         case DIV:
           // Divide by zero and overflow was not checked in the configuration
-          // step - div and divu do not raise exceptions. On division by 0 and
-          // on overflow (INT_MIN/-1), the result will be UNPREDICTABLE.
-          if (rt != 0 && !(rs == INT_MIN && rt == -1)) {
+          // step - div and divu do not raise exceptions. On division by 0
+          // the result will be UNPREDICTABLE. On overflow (INT_MIN/-1),
+          // return INT_MIN which is what the hardware does.
+          if (rs == INT_MIN && rt == -1) {
+            set_register(LO, INT_MIN);
+            set_register(HI, 0);
+          } else if (rt != 0) {
             set_register(LO, rs / rt);
             set_register(HI, rs % rt);
           }
diff --git a/src/objects.cc b/src/objects.cc
index 1399e33..6ca8bdf 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -5583,7 +5583,53 @@
 }
 
 
-Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object) {
+class JSObjectWalkVisitor {
+ public:
+  explicit JSObjectWalkVisitor() {}
+  virtual ~JSObjectWalkVisitor() {}
+
+  Handle<JSObject> Visit(Handle<JSObject> object) {
+    return StructureWalk(object);
+  }
+
+  // Returns true if the visitor is a copying visitor.
+  virtual bool is_copying() = 0;
+
+ protected:
+  Handle<JSObject> StructureWalk(Handle<JSObject> object);
+
+  // The returned handle should point to a new object if the visitor is a
+  // copying visitor, otherwise it should be the same as the input object.
+  virtual Handle<JSObject> VisitObject(Handle<JSObject> object) = 0;
+
+  // The returned handle should point to a new value if the visitor is a
+  // copying visitor, otherwise it should be the same as the input value.
+  virtual Handle<JSObject> VisitElementOrProperty(Handle<JSObject> object,
+                                                  Handle<JSObject> value) = 0;
+};
+
+
+class JSObjectCopyVisitor: public JSObjectWalkVisitor {
+ public:
+  explicit JSObjectCopyVisitor() {}
+
+  virtual bool is_copying() V8_OVERRIDE { return true; }
+
+ protected:
+  virtual Handle<JSObject> VisitObject(Handle<JSObject> object) V8_OVERRIDE {
+    return JSObject::Copy(object);
+  }
+
+  virtual Handle<JSObject> VisitElementOrProperty(
+      Handle<JSObject> object,
+      Handle<JSObject> value) V8_OVERRIDE {
+    return StructureWalk(value);
+  }
+};
+
+
+Handle<JSObject> JSObjectWalkVisitor::StructureWalk(Handle<JSObject> object) {
+  bool copying = is_copying();
   Isolate* isolate = object->GetIsolate();
   StackLimitCheck check(isolate);
   if (check.HasOverflowed()) {
@@ -5592,10 +5638,11 @@
   }
 
   if (object->map()->is_deprecated()) {
-    MigrateInstance(object);
+    JSObject::MigrateInstance(object);
   }
 
-  Handle<JSObject> copy = Copy(object);
+  Handle<JSObject> copy = VisitObject(object);
+  ASSERT(copying || copy.is_identical_to(object));
 
   HandleScope scope(isolate);
 
@@ -5609,13 +5656,15 @@
       int index = descriptors->GetFieldIndex(i);
       Handle<Object> value(object->RawFastPropertyAt(index), isolate);
       if (value->IsJSObject()) {
-        value = DeepCopy(Handle<JSObject>::cast(value));
+        value = VisitElementOrProperty(copy, Handle<JSObject>::cast(value));
         RETURN_IF_EMPTY_HANDLE_VALUE(isolate, value, Handle<JSObject>());
       } else {
         Representation representation = details.representation();
         value = NewStorageFor(isolate, value, representation);
       }
-      copy->FastPropertyAtPut(index, *value);
+      if (copying) {
+        copy->FastPropertyAtPut(index, *value);
+      }
     }
   } else {
     Handle<FixedArray> names =
@@ -5634,11 +5683,14 @@
           copy->GetProperty(*key_string, &attributes)->ToObjectUnchecked(),
           isolate);
       if (value->IsJSObject()) {
-        Handle<Object> result = DeepCopy(Handle<JSObject>::cast(value));
+        Handle<JSObject> result = VisitElementOrProperty(
+            copy, Handle<JSObject>::cast(value));
         RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
-        // Creating object copy for literals. No strict mode needed.
-        CHECK_NOT_EMPTY_HANDLE(isolate, SetProperty(
-            copy, key_string, result, NONE, kNonStrictMode));
+        if (copying) {
+          // Creating object copy for literals. No strict mode needed.
+          CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetProperty(
+              copy, key_string, result, NONE, kNonStrictMode));
+        }
       }
     }
   }
@@ -5666,9 +5718,12 @@
                  value->IsTheHole() ||
                  (IsFastObjectElementsKind(copy->GetElementsKind())));
           if (value->IsJSObject()) {
-            Handle<Object> result = DeepCopy(Handle<JSObject>::cast(value));
+            Handle<JSObject> result = VisitElementOrProperty(
+                copy, Handle<JSObject>::cast(value));
             RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
-            elements->set(i, *result);
+            if (copying) {
+              elements->set(i, *result);
+            }
           }
         }
       }
@@ -5683,9 +5738,12 @@
         if (element_dictionary->IsKey(k)) {
           Handle<Object> value(element_dictionary->ValueAt(i), isolate);
           if (value->IsJSObject()) {
-            Handle<Object> result = DeepCopy(Handle<JSObject>::cast(value));
+            Handle<JSObject> result = VisitElementOrProperty(
+                copy, Handle<JSObject>::cast(value));
             RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
-            element_dictionary->ValueAtPut(i, *result);
+            if (copying) {
+              element_dictionary->ValueAtPut(i, *result);
+            }
           }
         }
       }
@@ -5712,6 +5770,14 @@
 }
 
 
+Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object) {
+  JSObjectCopyVisitor v;
+  Handle<JSObject> copy = v.Visit(object);
+  ASSERT(v.is_copying() && !copy.is_identical_to(object));
+  return copy;
+}
+
+
 // Tests for the fast common case for property enumeration:
 // - This object and all prototypes has an enum cache (which means that
 //   it is no proxy, has no interceptors and needs no access checks).
diff --git a/src/optimizing-compiler-thread.cc b/src/optimizing-compiler-thread.cc
index e6467f1..202e6e5 100644
--- a/src/optimizing-compiler-thread.cc
+++ b/src/optimizing-compiler-thread.cc
@@ -108,19 +108,22 @@
   // The function may have already been optimized by OSR.  Simply continue.
   // Use a mutex to make sure that functions marked for install
   // are always also queued.
-  LockGuard<Mutex> access_queue(&queue_mutex_);
   output_queue_.Enqueue(job);
   isolate_->stack_guard()->RequestInstallCode();
 }
 
 
-static void DisposeRecompileJob(RecompileJob* compiler,
+static void DisposeRecompileJob(RecompileJob* job,
                                 bool restore_function_code) {
   // The recompile job is allocated in the CompilationInfo's zone.
-  CompilationInfo* info = compiler->info();
+  CompilationInfo* info = job->info();
   if (restore_function_code) {
-    Handle<JSFunction> function = info->closure();
-    function->ReplaceCode(function->shared()->code());
+    if (info->is_osr()) {
+      if (!job->IsWaitingForInstall()) BackEdgeTable::RemoveStackCheck(info);
+    } else {
+      Handle<JSFunction> function = info->closure();
+      function->ReplaceCode(function->shared()->code());
+    }
   }
   delete info;
 }
@@ -132,8 +135,8 @@
     // This should not block, since we have one signal on the input queue
     // semaphore corresponding to each element in the input queue.
     input_queue_semaphore_.Wait();
-    if (job->info()->osr_ast_id().IsNone()) {
-      // OSR jobs are dealt with separately.
+    // OSR jobs are dealt with separately.
+    if (!job->info()->is_osr()) {
       DisposeRecompileJob(job, restore_function_code);
     }
   }
@@ -143,12 +146,9 @@
 
 void OptimizingCompilerThread::FlushOutputQueue(bool restore_function_code) {
   RecompileJob* job;
-  while (true) {
-    { LockGuard<Mutex> access_queue(&queue_mutex_);
-      if (!output_queue_.Dequeue(&job)) break;
-    }
-    if (job->info()->osr_ast_id().IsNone()) {
-      // OSR jobs are dealt with separately.
+  while (output_queue_.Dequeue(&job)) {
+    // OSR jobs are dealt with separately.
+    if (!job->info()->is_osr()) {
       DisposeRecompileJob(job, restore_function_code);
     }
   }
@@ -216,14 +216,9 @@
   HandleScope handle_scope(isolate_);
 
   RecompileJob* job;
-  while (true) {
-    { LockGuard<Mutex> access_queue(&queue_mutex_);
-      if (!output_queue_.Dequeue(&job)) break;
-    }
+  while (output_queue_.Dequeue(&job)) {
     CompilationInfo* info = job->info();
-    if (info->osr_ast_id().IsNone()) {
-      Compiler::InstallOptimizedCode(job);
-    } else {
+    if (info->is_osr()) {
       if (FLAG_trace_osr) {
         PrintF("[COSR - ");
         info->closure()->PrintName();
@@ -232,6 +227,8 @@
       }
       job->WaitForInstall();
       BackEdgeTable::RemoveStackCheck(info);
+    } else {
+      Compiler::InstallOptimizedCode(job);
     }
   }
 }
@@ -242,9 +239,7 @@
   ASSERT(!IsOptimizerThread());
   Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(1));
   CompilationInfo* info = job->info();
-  if (info->osr_ast_id().IsNone()) {
-    info->closure()->MarkInRecompileQueue();
-  } else {
+  if (info->is_osr()) {
     if (FLAG_trace_concurrent_recompilation) {
       PrintF("  ** Queueing ");
       info->closure()->PrintName();
@@ -253,6 +248,8 @@
     AddToOsrBuffer(job);
     osr_attempts_++;
     BackEdgeTable::AddStackCheck(info);
+  } else {
+    info->closure()->MarkInRecompileQueue();
   }
   input_queue_.Enqueue(job);
   input_queue_semaphore_.Signal();
@@ -317,7 +314,6 @@
         info->closure()->PrintName();
         PrintF(", AST id %d]\n", info->osr_ast_id().ToInt());
       }
-      BackEdgeTable::RemoveStackCheck(info);
       DisposeRecompileJob(stale, false);
       break;
     }
diff --git a/src/optimizing-compiler-thread.h b/src/optimizing-compiler-thread.h
index 2165a4f..d98a8b2 100644
--- a/src/optimizing-compiler-thread.h
+++ b/src/optimizing-compiler-thread.h
@@ -139,8 +139,6 @@
   TimeDelta time_spent_compiling_;
   TimeDelta time_spent_total_;
 
-  // TODO(yangguo): remove this once the memory leak has been figured out.
-  Mutex queue_mutex_;
   int osr_hits_;
   int osr_attempts_;
 };
diff --git a/src/v8threads.cc b/src/v8threads.cc
index 94a5e80..cc4f439 100644
--- a/src/v8threads.cc
+++ b/src/v8threads.cc
@@ -42,11 +42,6 @@
 bool Locker::active_ = false;
 
 
-Locker::Locker() {
-  Initialize(i::Isolate::GetDefaultIsolateForLocking());
-}
-
-
 // Once the Locker is initialized, the current thread will be guaranteed to have
 // the lock for a given isolate.
 void Locker::Initialize(v8::Isolate* isolate) {
@@ -116,11 +111,6 @@
 }
 
 
-Unlocker::Unlocker() {
-  Initialize(i::Isolate::GetDefaultIsolateForLocking());
-}
-
-
 void Unlocker::Initialize(v8::Isolate* isolate) {
   ASSERT(isolate != NULL);
   isolate_ = reinterpret_cast<i::Isolate*>(isolate);
@@ -143,14 +133,15 @@
 }
 
 
-void Locker::StartPreemption(int every_n_ms) {
+void Locker::StartPreemption(v8::Isolate* isolate, int every_n_ms) {
   v8::internal::ContextSwitcher::StartPreemption(
-      i::Isolate::Current(), every_n_ms);
+      reinterpret_cast<i::Isolate*>(isolate), every_n_ms);
 }
 
 
-void Locker::StopPreemption() {
-  v8::internal::ContextSwitcher::StopPreemption(i::Isolate::Current());
+void Locker::StopPreemption(v8::Isolate* isolate) {
+  v8::internal::ContextSwitcher::StopPreemption(
+      reinterpret_cast<i::Isolate*>(isolate));
 }
 
 
diff --git a/src/version.cc b/src/version.cc
index e310df0..be3b9cb 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     22
-#define BUILD_NUMBER      3
-#define PATCH_LEVEL       2
+#define BUILD_NUMBER      4
+#define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 27d064d..df168b8 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -4523,16 +4523,17 @@
   Label slow;
   Register reg = ToRegister(instr->value());
   Register tmp = reg.is(rax) ? rcx : rax;
+  XMMRegister temp_xmm = ToDoubleRegister(instr->temp());
 
   // Preserve the value of all registers.
   PushSafepointRegistersScope scope(this);
 
   Label done;
-  // Load value into xmm1 which will be preserved across potential call to
+  // Load value into temp_xmm which will be preserved across potential call to
   // runtime (MacroAssembler::EnterExitFrameEpilogue preserves only allocatable
   // XMM registers on x64).
   XMMRegister xmm_scratch = double_scratch0();
-  __ LoadUint32(xmm1, reg, xmm_scratch);
+  __ LoadUint32(temp_xmm, reg, xmm_scratch);
 
   if (FLAG_inline_new) {
     __ AllocateHeapNumber(reg, tmp, &slow);
@@ -4550,10 +4551,10 @@
   CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
   if (!reg.is(rax)) __ movq(reg, rax);
 
-  // Done. Put the value in xmm1 into the value of the allocated heap
+  // Done. Put the value in temp_xmm into the value of the allocated heap
   // number.
   __ bind(&done);
-  __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm1);
+  __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), temp_xmm);
   __ StoreToSafepointRegisterSlot(reg, reg);
 }
 
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index ddaae82..7487603 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -353,19 +353,20 @@
 }
 
 
-int LPlatformChunk::GetNextSpillIndex(bool is_double) {
+int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
   return spill_slot_count_++;
 }
 
 
-LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double) {
+LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
   // All stack slots are Double stack slots on x64.
   // Alternatively, at some point, start using half-size
   // stack slots for int32 values.
-  int index = GetNextSpillIndex(is_double);
-  if (is_double) {
+  int index = GetNextSpillIndex(kind);
+  if (kind == DOUBLE_REGISTERS) {
     return LDoubleStackSlot::Create(index, zone());
   } else {
+    ASSERT(kind == GENERAL_REGISTERS);
     return LStackSlot::Create(index, zone());
   }
 }
@@ -445,7 +446,7 @@
   // which will be subsumed into this frame.
   if (graph()->has_osr()) {
     for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) {
-      chunk_->GetNextSpillIndex(false);
+      chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
     }
   }
 
@@ -1780,6 +1781,13 @@
 }
 
 
+LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
+  // The control instruction marking the end of a block that completed
+  // abruptly (e.g., threw an exception).  There is nothing specific to do.
+  return NULL;
+}
+
+
 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
   LOperand* value = UseFixed(instr->value(), rax);
   return MarkAsCall(new(zone()) LThrow(value), instr);
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index 0ccbeb8..e0c4458 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -2542,8 +2542,8 @@
   LPlatformChunk(CompilationInfo* info, HGraph* graph)
       : LChunk(info, graph) { }
 
-  int GetNextSpillIndex(bool is_double);
-  LOperand* GetNextSpillSlot(bool is_double);
+  int GetNextSpillIndex(RegisterKind kind);
+  LOperand* GetNextSpillSlot(RegisterKind kind);
 };
 
 
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 96fa4fc..0809ccd 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -1447,28 +1447,6 @@
 }
 
 
-void MacroAssembler::SmiTryAddConstant(Register dst,
-                                       Register src,
-                                       Smi* constant,
-                                       Label* on_not_smi_result,
-                                       Label::Distance near_jump) {
-  // Does not assume that src is a smi.
-  ASSERT_EQ(static_cast<int>(1), static_cast<int>(kSmiTagMask));
-  STATIC_ASSERT(kSmiTag == 0);
-  ASSERT(!dst.is(kScratchRegister));
-  ASSERT(!src.is(kScratchRegister));
-
-  JumpIfNotSmi(src, on_not_smi_result, near_jump);
-  Register tmp = (dst.is(src) ? kScratchRegister : dst);
-  LoadSmiConstant(tmp, constant);
-  addq(tmp, src);
-  j(overflow, on_not_smi_result, near_jump);
-  if (dst.is(src)) {
-    movq(dst, tmp);
-  }
-}
-
-
 void MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) {
   if (constant->value() == 0) {
     if (!dst.is(src)) {
@@ -1699,6 +1677,29 @@
 }
 
 
+template<class T>
+static void SmiSubHelper(MacroAssembler* masm,
+                         Register dst,
+                         Register src1,
+                         T src2,
+                         Label* on_not_smi_result,
+                         Label::Distance near_jump) {
+  if (dst.is(src1)) {
+    Label done;
+    masm->subq(dst, src2);
+    masm->j(no_overflow, &done, Label::kNear);
+    // Restore src1.
+    masm->addq(dst, src2);
+    masm->jmp(on_not_smi_result, near_jump);
+    masm->bind(&done);
+  } else {
+    masm->movq(dst, src1);
+    masm->subq(dst, src2);
+    masm->j(overflow, on_not_smi_result, near_jump);
+  }
+}
+
+
 void MacroAssembler::SmiSub(Register dst,
                             Register src1,
                             Register src2,
@@ -1706,27 +1707,7 @@
                             Label::Distance near_jump) {
   ASSERT_NOT_NULL(on_not_smi_result);
   ASSERT(!dst.is(src2));
-  if (dst.is(src1)) {
-    cmpq(dst, src2);
-    j(overflow, on_not_smi_result, near_jump);
-    subq(dst, src2);
-  } else {
-    movq(dst, src1);
-    subq(dst, src2);
-    j(overflow, on_not_smi_result, near_jump);
-  }
-}
-
-
-void MacroAssembler::SmiSub(Register dst, Register src1, Register src2) {
-  // No overflow checking. Use only when it's known that
-  // overflowing is impossible (e.g., subtracting two positive smis).
-  ASSERT(!dst.is(src2));
-  if (!dst.is(src1)) {
-    movq(dst, src1);
-  }
-  subq(dst, src2);
-  Assert(no_overflow, kSmiSubtractionOverflow);
+  SmiSubHelper<Register>(this, dst, src1, src2, on_not_smi_result, near_jump);
 }
 
 
@@ -1736,29 +1717,36 @@
                             Label* on_not_smi_result,
                             Label::Distance near_jump) {
   ASSERT_NOT_NULL(on_not_smi_result);
-  if (dst.is(src1)) {
-    movq(kScratchRegister, src2);
-    cmpq(src1, kScratchRegister);
-    j(overflow, on_not_smi_result, near_jump);
-    subq(src1, kScratchRegister);
-  } else {
-    movq(dst, src1);
-    subq(dst, src2);
-    j(overflow, on_not_smi_result, near_jump);
+  ASSERT(!src2.AddressUsesRegister(dst));
+  SmiSubHelper<Operand>(this, dst, src1, src2, on_not_smi_result, near_jump);
+}
+
+
+template<class T>
+static void SmiSubNoOverflowHelper(MacroAssembler* masm,
+                                   Register dst,
+                                   Register src1,
+                                   T src2) {
+  // No overflow checking. Use only when it's known that
+  // overflowing is impossible (e.g., subtracting two positive smis).
+  if (!dst.is(src1)) {
+    masm->movq(dst, src1);
   }
+  masm->subq(dst, src2);
+  masm->Assert(no_overflow, kSmiSubtractionOverflow);
+}
+
+
+void MacroAssembler::SmiSub(Register dst, Register src1, Register src2) {
+  ASSERT(!dst.is(src2));
+  SmiSubNoOverflowHelper<Register>(this, dst, src1, src2);
 }
 
 
 void MacroAssembler::SmiSub(Register dst,
                             Register src1,
                             const Operand& src2) {
-  // No overflow checking. Use only when it's known that
-  // overflowing is impossible (e.g., subtracting two positive smis).
-  if (!dst.is(src1)) {
-    movq(dst, src1);
-  }
-  subq(dst, src2);
-  Assert(no_overflow, kSmiSubtractionOverflow);
+  SmiSubNoOverflowHelper<Operand>(this, dst, src1, src2);
 }
 
 
@@ -3728,7 +3716,7 @@
 #endif
   // Optionally save all XMM registers.
   if (save_doubles) {
-    int space = XMMRegister::kMaxNumRegisters * kDoubleSize +
+    int space = XMMRegister::kMaxNumAllocatableRegisters * kDoubleSize +
         arg_stack_space * kPointerSize;
     subq(rsp, Immediate(space));
     int offset = -2 * kPointerSize;
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index 09dae3e..8c73dd9 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -532,15 +532,6 @@
   // Smis represent a subset of integers. The subset is always equivalent to
   // a two's complement interpretation of a fixed number of bits.
 
-  // Optimistically adds an integer constant to a supposed smi.
-  // If the src is not a smi, or the result is not a smi, jump to
-  // the label.
-  void SmiTryAddConstant(Register dst,
-                         Register src,
-                         Smi* constant,
-                         Label* on_not_smi_result,
-                         Label::Distance near_jump = Label::kFar);
-
   // Add an integer constant to a tagged smi, giving a tagged smi as result.
   // No overflow testing on the result is done.
   void SmiAddConstant(Register dst, Register src, Smi* constant);
@@ -596,13 +587,18 @@
               Register src2);
 
   // Subtracts smi values and return the result as a smi.
-  // If dst is src1, then src1 will be destroyed, even if
-  // the operation is unsuccessful.
+  // If dst is src1, then src1 will be destroyed if the operation is
+  // successful, otherwise kept intact.
   void SmiSub(Register dst,
               Register src1,
               Register src2,
               Label* on_not_smi_result,
               Label::Distance near_jump = Label::kFar);
+  void SmiSub(Register dst,
+              Register src1,
+              const Operand& src2,
+              Label* on_not_smi_result,
+              Label::Distance near_jump = Label::kFar);
 
   void SmiSub(Register dst,
               Register src1,
@@ -610,12 +606,6 @@
 
   void SmiSub(Register dst,
               Register src1,
-              const Operand& src2,
-              Label* on_not_smi_result,
-              Label::Distance near_jump = Label::kFar);
-
-  void SmiSub(Register dst,
-              Register src1,
               const Operand& src2);
 
   // Multiplies smi values and return the result as a smi,
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 7a2f9de..5caa6ae 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -4011,7 +4011,8 @@
 
 THREADED_TEST(FunctionCall) {
   LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
   CompileRun(
     "function Foo() {"
     "  var result = [];"
@@ -4019,9 +4020,20 @@
     "    result.push(arguments[i]);"
     "  }"
     "  return result;"
+    "}"
+    "function ReturnThisSloppy() {"
+    "  return this;"
+    "}"
+    "function ReturnThisStrict() {"
+    "  'use strict';"
+    "  return this;"
     "}");
   Local<Function> Foo =
       Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
+  Local<Function> ReturnThisSloppy =
+      Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisSloppy")));
+  Local<Function> ReturnThisStrict =
+      Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisStrict")));
 
   v8::Handle<Value>* args0 = NULL;
   Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
@@ -4058,6 +4070,31 @@
   CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
   CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
   CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
+
+  Local<v8::Value> r1 = ReturnThisSloppy->Call(v8::Undefined(isolate), 0, NULL);
+  CHECK(r1->StrictEquals(context->Global()));
+  Local<v8::Value> r2 = ReturnThisSloppy->Call(v8::Null(isolate), 0, NULL);
+  CHECK(r2->StrictEquals(context->Global()));
+  Local<v8::Value> r3 = ReturnThisSloppy->Call(v8_num(42), 0, NULL);
+  CHECK(r3->IsNumberObject());
+  CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
+  Local<v8::Value> r4 = ReturnThisSloppy->Call(v8_str("hello"), 0, NULL);
+  CHECK(r4->IsStringObject());
+  CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
+  Local<v8::Value> r5 = ReturnThisSloppy->Call(v8::True(isolate), 0, NULL);
+  CHECK(r5->IsBooleanObject());
+  CHECK(r5.As<v8::BooleanObject>()->ValueOf());
+
+  Local<v8::Value> r6 = ReturnThisStrict->Call(v8::Undefined(isolate), 0, NULL);
+  CHECK(r6->IsUndefined());
+  Local<v8::Value> r7 = ReturnThisStrict->Call(v8::Null(isolate), 0, NULL);
+  CHECK(r7->IsNull());
+  Local<v8::Value> r8 = ReturnThisStrict->Call(v8_num(42), 0, NULL);
+  CHECK(r8->StrictEquals(v8_num(42)));
+  Local<v8::Value> r9 = ReturnThisStrict->Call(v8_str("hello"), 0, NULL);
+  CHECK(r9->StrictEquals(v8_str("hello")));
+  Local<v8::Value> r10 = ReturnThisStrict->Call(v8::True(isolate), 0, NULL);
+  CHECK(r10->StrictEquals(v8::True(isolate)));
 }
 
 
@@ -10177,6 +10214,11 @@
 }
 
 
+static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  args.GetReturnValue().Set(args.This());
+}
+
+
 // Test that a call handler can be set for objects which will allow
 // non-function objects created through the API to be called as
 // functions.
@@ -10289,6 +10331,81 @@
     CHECK_EQ("23", *exception_value2);
     try_catch.Reset();
   }
+
+  { v8::Isolate* isolate = context->GetIsolate();
+    Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
+    Local<ObjectTemplate> instance_template = t->InstanceTemplate();
+    instance_template->SetCallAsFunctionHandler(ReturnThis);
+    Local<v8::Object> instance = t->GetFunction()->NewInstance();
+
+    Local<v8::Value> a1 =
+        instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
+    CHECK(a1->StrictEquals(instance));
+    Local<v8::Value> a2 =
+        instance->CallAsFunction(v8::Null(isolate), 0, NULL);
+    CHECK(a2->StrictEquals(instance));
+    Local<v8::Value> a3 =
+        instance->CallAsFunction(v8_num(42), 0, NULL);
+    CHECK(a3->StrictEquals(instance));
+    Local<v8::Value> a4 =
+        instance->CallAsFunction(v8_str("hello"), 0, NULL);
+    CHECK(a4->StrictEquals(instance));
+    Local<v8::Value> a5 =
+        instance->CallAsFunction(v8::True(isolate), 0, NULL);
+    CHECK(a5->StrictEquals(instance));
+  }
+
+  { v8::Isolate* isolate = context->GetIsolate();
+    CompileRun(
+      "function ReturnThisSloppy() {"
+      "  return this;"
+      "}"
+      "function ReturnThisStrict() {"
+      "  'use strict';"
+      "  return this;"
+      "}");
+    Local<Function> ReturnThisSloppy =
+        Local<Function>::Cast(
+            context->Global()->Get(v8_str("ReturnThisSloppy")));
+    Local<Function> ReturnThisStrict =
+        Local<Function>::Cast(
+            context->Global()->Get(v8_str("ReturnThisStrict")));
+
+    Local<v8::Value> a1 =
+        ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
+    CHECK(a1->StrictEquals(context->Global()));
+    Local<v8::Value> a2 =
+        ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
+    CHECK(a2->StrictEquals(context->Global()));
+    Local<v8::Value> a3 =
+        ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
+    CHECK(a3->IsNumberObject());
+    CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
+    Local<v8::Value> a4 =
+        ReturnThisSloppy->CallAsFunction(v8_str("hello"), 0, NULL);
+    CHECK(a4->IsStringObject());
+    CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
+    Local<v8::Value> a5 =
+        ReturnThisSloppy->CallAsFunction(v8::True(isolate), 0, NULL);
+    CHECK(a5->IsBooleanObject());
+    CHECK(a5.As<v8::BooleanObject>()->ValueOf());
+
+    Local<v8::Value> a6 =
+        ReturnThisStrict->CallAsFunction(v8::Undefined(isolate), 0, NULL);
+    CHECK(a6->IsUndefined());
+    Local<v8::Value> a7 =
+        ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
+    CHECK(a7->IsNull());
+    Local<v8::Value> a8 =
+        ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
+    CHECK(a8->StrictEquals(v8_num(42)));
+    Local<v8::Value> a9 =
+        ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
+    CHECK(a9->StrictEquals(v8_str("hello")));
+    Local<v8::Value> a10 =
+        ReturnThisStrict->CallAsFunction(v8::True(isolate), 0, NULL);
+    CHECK(a10->StrictEquals(v8::True(isolate)));
+  }
 }
 
 
@@ -14218,14 +14335,15 @@
     gc_success_ = false;
     GCThread gc_thread(this);
     gc_thread.Start();
-    v8::Locker::StartPreemption(1);
+    v8::Isolate* isolate = CcTest::isolate();
+    v8::Locker::StartPreemption(isolate, 1);
 
     LongRunningRegExp();
     {
-      v8::Unlocker unlock(CcTest::isolate());
+      v8::Unlocker unlock(isolate);
       gc_thread.Join();
     }
-    v8::Locker::StopPreemption();
+    v8::Locker::StopPreemption(isolate);
     CHECK(regexp_success_);
     CHECK(gc_success_);
   }
@@ -14340,14 +14458,15 @@
     gc_success_ = false;
     GCThread gc_thread(this);
     gc_thread.Start();
-    v8::Locker::StartPreemption(1);
+    v8::Isolate* isolate = CcTest::isolate();
+    v8::Locker::StartPreemption(isolate, 1);
 
     LongRunningApply();
     {
-      v8::Unlocker unlock(CcTest::isolate());
+      v8::Unlocker unlock(isolate);
       gc_thread.Join();
     }
-    v8::Locker::StopPreemption();
+    v8::Locker::StopPreemption(isolate);
     CHECK(apply_success_);
     CHECK(gc_success_);
   }
@@ -14627,6 +14746,7 @@
         uc16_resource_(i::Vector<const uint16_t>(two_byte_content_, 15)) {}
   ~RegExpStringModificationTest() {}
   void RunTest() {
+    v8::Isolate* isolate = CcTest::isolate();
     i::Factory* factory = CcTest::i_isolate()->factory();
 
     regexp_success_ = false;
@@ -14655,13 +14775,13 @@
 
     MorphThread morph_thread(this);
     morph_thread.Start();
-    v8::Locker::StartPreemption(1);
+    v8::Locker::StartPreemption(isolate, 1);
     LongRunningRegExp();
     {
-      v8::Unlocker unlock(CcTest::isolate());
+      v8::Unlocker unlock(isolate);
       morph_thread.Join();
     }
-    v8::Locker::StopPreemption();
+    v8::Locker::StopPreemption(isolate);
     CHECK(regexp_success_);
     CHECK(morph_success_);
   }
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index df6d1f5..d24f28e 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -29,7 +29,6 @@
 
 #include <stdlib.h>
 
-#define V8_DISABLE_DEPRECATIONS 1
 #include "v8.h"
 
 #include "api.h"
@@ -43,7 +42,6 @@
 #include "platform/socket.h"
 #include "stub-cache.h"
 #include "utils.h"
-#undef V8_DISABLE_DEPRECATIONS
 
 
 using ::v8::internal::Mutex;
diff --git a/test/cctest/test-threads.cc b/test/cctest/test-threads.cc
index 518d460..4709961 100644
--- a/test/cctest/test-threads.cc
+++ b/test/cctest/test-threads.cc
@@ -41,14 +41,14 @@
   v8::Handle<v8::Context> context = v8::Context::New(isolate);
   v8::Context::Scope context_scope(context);
 
-  v8::Locker::StartPreemption(100);
+  v8::Locker::StartPreemption(isolate, 100);
 
   v8::Handle<v8::Script> script = v8::Script::Compile(
       v8::String::New("var count = 0; var obj = new Object(); count++;\n"));
 
   script->Run();
 
-  v8::Locker::StopPreemption();
+  v8::Locker::StopPreemption(isolate);
   v8::internal::OS::Sleep(500);  // Make sure the timer fires.
 
   script->Run();
diff --git a/test/mjsunit/big-array-literal.js b/test/mjsunit/big-array-literal.js
index 9f06179..13f91f8 100644
--- a/test/mjsunit/big-array-literal.js
+++ b/test/mjsunit/big-array-literal.js
@@ -92,16 +92,25 @@
   testLiteral(sizes[i], true);
 }
 
+
+function checkExpectedException(e) {
+  assertInstanceof(e, RangeError);
+  assertTrue(e.message.indexOf("Maximum call stack size exceeded") >= 0);
+}
+
+
 function testLiteralAndCatch(size) {
   var big_enough = false;
   try {
     testLiteral(size, false);
   } catch (e) {
+    checkExpectedException(e);
     big_enough = true;
   }
   try {
     testLiteral(size, true);
   } catch (e) {
+    checkExpectedException(e);
     big_enough = true;
   }
   return big_enough;
diff --git a/test/mjsunit/big-object-literal.js b/test/mjsunit/big-object-literal.js
index c937f54..92c6ab7 100644
--- a/test/mjsunit/big-object-literal.js
+++ b/test/mjsunit/big-object-literal.js
@@ -92,16 +92,25 @@
   testLiteral(sizes[i], true);
 }
 
+
+function checkExpectedException(e) {
+  assertInstanceof(e, RangeError);
+  assertTrue(e.message.indexOf("Maximum call stack size exceeded") >= 0);
+}
+
+
 function testLiteralAndCatch(size) {
   var big_enough = false;
   try {
     testLiteral(size, false);
   } catch (e) {
+    checkExpectedException(e);
     big_enough = true;
   }
   try {
     testLiteral(size, true);
   } catch (e) {
+    checkExpectedException(e);
     big_enough = true;
   }
   return big_enough;
diff --git a/test/mjsunit/timer.js b/test/mjsunit/timer.js
index bac474c..0b03550 100644
--- a/test/mjsunit/timer.js
+++ b/test/mjsunit/timer.js
@@ -25,8 +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.
 
+// Flags: --allow-natives-syntax
+
 // Tests timer milliseconds granularity.
 
+// Don't run this test in gc stress mode. Time differences may be long
+// due to garbage collections.
+%SetFlags("--gc-interval=-1");
+%SetFlags("--nostress-compaction");
+
 (function run() {
   var start_test = Date.now();
   // Let the retry run for maximum 100ms to reduce flakiness.
diff --git a/tools/profviz/composer.js b/tools/profviz/composer.js
index 44dd763..0c9437f 100644
--- a/tools/profviz/composer.js
+++ b/tools/profviz/composer.js
@@ -497,6 +497,8 @@
     }
 
     // Label the longest pauses.
+    execution_pauses =
+        RestrictRangesTo(execution_pauses, range_start, range_end);
     execution_pauses.sort(
         function(a, b) { return b.duration() - a.duration(); });
 
diff --git a/tools/status-file-converter.py b/tools/status-file-converter.py
deleted file mode 100755
index ba063ee..0000000
--- a/tools/status-file-converter.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2012 the V8 project authors. All rights reserved.
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-#       copyright notice, this list of conditions and the following
-#       disclaimer in the documentation and/or other materials provided
-#       with the distribution.
-#     * Neither the name of Google Inc. nor the names of its
-#       contributors may be used to endorse or promote products derived
-#       from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-import sys
-from testrunner.local import old_statusfile
-
-if len(sys.argv) != 2:
-  print "Usage: %s foo.status" % sys.argv[0]
-  print "Will read foo.status and print the converted version to stdout."
-  sys.exit(1)
-
-print old_statusfile.ConvertNotation(sys.argv[1]).GetOutput()
diff --git a/tools/testrunner/README b/tools/testrunner/README
index 8f0c01f..0771ef9 100644
--- a/tools/testrunner/README
+++ b/tools/testrunner/README
@@ -87,12 +87,6 @@
   Implementation needed to run tests locally. Used by run-tests.py. Inspired by
   (and partly copied verbatim from) the original test.py script.
 
-./testrunner/local/old_statusfile.py:
-  Provides functionality to read an old-style <testsuite>.status file and
-  convert it to new-style syntax. This can be removed once the new-style
-  syntax becomes authoritative (and old-style syntax is no longer supported).
-  ./status-file-converter.py provides a stand-alone interface to this.
-
 ./testrunner/objects/*:
   A bunch of data container classes, used by the scripts in the various other
   directories; serializable for transmission over the network.