Version 3.23.12

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@18076 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index fa508c8..aee6b50 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-11-26: Version 3.23.12
+
+        Performance and stability improvements on all platforms.
+
+
 2013-11-25: Version 3.23.11
 
         Deprecate old versions of Isolate::SetData and GetData.
diff --git a/include/v8.h b/include/v8.h
index 6e1ac3f..a15edf2 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -1137,6 +1137,8 @@
   bool IsSharedCrossOrigin() const;
 
   // TODO(1245381): Print to a string instead of on a FILE.
+  static void PrintCurrentStackTrace(Isolate* isolate, FILE* out);
+  // Will be deprecated soon.
   static void PrintCurrentStackTrace(FILE* out);
 
   static const int kNoLineNumberInfo = 0;
@@ -1192,6 +1194,11 @@
    *   StackFrame.
    */
   static Local<StackTrace> CurrentStackTrace(
+      Isolate* isolate,
+      int frame_limit,
+      StackTraceOptions options = kOverview);
+  // Will be deprecated soon.
+  static Local<StackTrace> CurrentStackTrace(
       int frame_limit,
       StackTraceOptions options = kOverview);
 };
@@ -1524,6 +1531,8 @@
 class V8_EXPORT Boolean : public Primitive {
  public:
   bool Value() const;
+  V8_INLINE static Handle<Boolean> New(Isolate* isolate, bool value);
+  // Will be deprecated soon.
   V8_INLINE static Handle<Boolean> New(bool value);
 };
 
@@ -1792,6 +1801,9 @@
    * should the underlying buffer be deallocated or modified except through the
    * destructor of the external string resource.
    */
+  static Local<String> NewExternal(Isolate* isolate,
+                                   ExternalStringResource* resource);
+  // Will be deprecated soon.
   static Local<String> NewExternal(ExternalStringResource* resource);
 
   /**
@@ -1813,6 +1825,9 @@
    * should the underlying buffer be deallocated or modified except through the
    * destructor of the external string resource.
    */
+  static Local<String> NewExternal(Isolate* isolate,
+                                   ExternalAsciiStringResource* resource);
+  // Will be deprecated soon.
   static Local<String> NewExternal(ExternalAsciiStringResource* resource);
 
   /**
@@ -1966,8 +1981,9 @@
 class V8_EXPORT Number : public Primitive {
  public:
   double Value() const;
-  static Local<Number> New(double value);
   static Local<Number> New(Isolate* isolate, double value);
+  // Will be deprecated soon.
+  static Local<Number> New(double value);
   V8_INLINE static Number* Cast(v8::Value* obj);
  private:
   Number();
@@ -1980,10 +1996,13 @@
  */
 class V8_EXPORT Integer : public Number {
  public:
-  static Local<Integer> New(int32_t value);
-  static Local<Integer> NewFromUnsigned(uint32_t value);
+  static Local<Integer> New(Isolate* isolate, int32_t value);
+  static Local<Integer> NewFromUnsigned(Isolate* isolate, uint32_t value);
+  // Will be deprecated soon.
   static Local<Integer> New(int32_t value, Isolate*);
   static Local<Integer> NewFromUnsigned(uint32_t value, Isolate*);
+  static Local<Integer> New(int32_t value);
+  static Local<Integer> NewFromUnsigned(uint32_t value);
   int64_t Value() const;
   V8_INLINE static Integer* Cast(v8::Value* obj);
  private:
@@ -2336,6 +2355,8 @@
    */
   Local<Value> CallAsConstructor(int argc, Handle<Value> argv[]);
 
+  static Local<Object> New(Isolate* isolate);
+  // Will be deprecated soon.
   static Local<Object> New();
   V8_INLINE static Object* Cast(Value* obj);
 
@@ -2364,6 +2385,8 @@
    * Creates a JavaScript array with the given length. If the length
    * is negative the returned array will have length 0.
    */
+  static Local<Array> New(Isolate* isolate, int length = 0);
+  // Will be deprecated soon.
   static Local<Array> New(int length = 0);
 
   V8_INLINE static Array* Cast(Value* obj);
@@ -2627,6 +2650,8 @@
    * will be deallocated when it is garbage-collected,
    * unless the object is externalized.
    */
+  static Local<ArrayBuffer> New(Isolate* isolate, size_t byte_length);
+  // Will be deprecated soon.
   static Local<ArrayBuffer> New(size_t byte_length);
 
   /**
@@ -2635,6 +2660,9 @@
    * The memory block will not be reclaimed when a created ArrayBuffer
    * is garbage-collected.
    */
+  static Local<ArrayBuffer> New(Isolate* isolate, void* data,
+                                size_t byte_length);
+  // Will be deprecated soon.
   static Local<ArrayBuffer> New(void* data, size_t byte_length);
 
   /**
@@ -2895,6 +2923,8 @@
  */
 class V8_EXPORT Date : public Object {
  public:
+  static Local<Value> New(Isolate* isolate, double time);
+  // Will be deprecated soon.
   static Local<Value> New(double time);
 
   V8_DEPRECATED(
@@ -2921,6 +2951,8 @@
    * This API should not be called more than needed as it will
    * negatively impact the performance of date operations.
    */
+  static void DateTimeConfigurationChangeNotification(Isolate* isolate);
+  // Will be deprecated soon.
   static void DateTimeConfigurationChangeNotification();
 
  private:
@@ -2933,6 +2965,8 @@
  */
 class V8_EXPORT NumberObject : public Object {
  public:
+  static Local<Value> New(Isolate* isolate, double value);
+  // Will be deprecated soon.
   static Local<Value> New(double value);
 
   V8_DEPRECATED(
@@ -3094,6 +3128,8 @@
   /** Adds a property to each instance created by this template.*/
   void Set(Handle<String> name, Handle<Data> value,
            PropertyAttribute attributes = None);
+  V8_INLINE void Set(Isolate* isolate, const char* name, Handle<Data> value);
+  // Will be deprecated soon.
   V8_INLINE void Set(const char* name, Handle<Data> value);
 
   void SetAccessorProperty(
@@ -3377,6 +3413,13 @@
  public:
   /** Creates a function template.*/
   static Local<FunctionTemplate> New(
+      Isolate* isolate,
+      FunctionCallback callback = 0,
+      Handle<Value> data = Handle<Value>(),
+      Handle<Signature> signature = Handle<Signature>(),
+      int length = 0);
+  // Will be deprecated soon.
+  static Local<FunctionTemplate> New(
       FunctionCallback callback = 0,
       Handle<Value> data = Handle<Value>(),
       Handle<Signature> signature = Handle<Signature>(),
@@ -3463,6 +3506,8 @@
 class V8_EXPORT ObjectTemplate : public Template {
  public:
   /** Creates an ObjectTemplate. */
+  static Local<ObjectTemplate> New(Isolate* isolate);
+  // Will be deprecated soon.
   static Local<ObjectTemplate> New();
 
   /** Creates a new instance of this template.*/
@@ -3604,7 +3649,8 @@
 
  private:
   ObjectTemplate();
-  static Local<ObjectTemplate> New(Handle<FunctionTemplate> constructor);
+  static Local<ObjectTemplate> New(internal::Isolate* isolate,
+                                   Handle<FunctionTemplate> constructor);
   friend class FunctionTemplate;
 };
 
@@ -3615,6 +3661,12 @@
  */
 class V8_EXPORT Signature : public Data {
  public:
+  static Local<Signature> New(Isolate* isolate,
+                              Handle<FunctionTemplate> receiver =
+                                  Handle<FunctionTemplate>(),
+                              int argc = 0,
+                              Handle<FunctionTemplate> argv[] = 0);
+  // Will be deprecated soon.
   static Local<Signature> New(Handle<FunctionTemplate> receiver =
                                   Handle<FunctionTemplate>(),
                               int argc = 0,
@@ -3630,8 +3682,13 @@
  */
 class V8_EXPORT AccessorSignature : public Data {
  public:
+  static Local<AccessorSignature> New(Isolate* isolate,
+                                      Handle<FunctionTemplate> receiver =
+                                          Handle<FunctionTemplate>());
+  // Will be deprecated soon.
   static Local<AccessorSignature> New(Handle<FunctionTemplate> receiver =
                                           Handle<FunctionTemplate>());
+
  private:
   AccessorSignature();
 };
@@ -3735,6 +3792,11 @@
             const char** deps = 0,
             int source_length = -1);
   virtual ~Extension() { }
+  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
+      v8::Isolate* isolate, v8::Handle<v8::String> name) {
+    return GetNativeFunction(name);
+  }
+  // Will be deprecated soon.
   virtual v8::Handle<v8::FunctionTemplate>
       GetNativeFunction(v8::Handle<v8::String> name) {
     return v8::Handle<v8::FunctionTemplate>();
@@ -3779,17 +3841,17 @@
 
 // --- Statics ---
 
-
-Handle<Primitive> V8_EXPORT Undefined();
-Handle<Primitive> V8_EXPORT Null();
-Handle<Boolean> V8_EXPORT True();
-Handle<Boolean> V8_EXPORT False();
-
 V8_INLINE Handle<Primitive> Undefined(Isolate* isolate);
 V8_INLINE Handle<Primitive> Null(Isolate* isolate);
 V8_INLINE Handle<Boolean> True(Isolate* isolate);
 V8_INLINE Handle<Boolean> False(Isolate* isolate);
 
+// Will be removed soon.
+Handle<Primitive> V8_EXPORT Undefined();
+Handle<Primitive> V8_EXPORT Null();
+Handle<Boolean> V8_EXPORT True();
+Handle<Boolean> V8_EXPORT False();
+
 
 /**
  * A set of constraints that specifies the limits of the runtime's memory use.
@@ -6031,14 +6093,23 @@
 }
 
 
-Handle<Boolean> Boolean::New(bool value) {
-  Isolate* isolate = Isolate::GetCurrent();
+Handle<Boolean> Boolean::New(Isolate* isolate, bool value) {
   return value ? True(isolate) : False(isolate);
 }
 
 
+Handle<Boolean> Boolean::New(bool value) {
+  return Boolean::New(Isolate::GetCurrent(), value);
+}
+
+
+void Template::Set(Isolate* isolate, const char* name, v8::Handle<Data> value) {
+  Set(v8::String::NewFromUtf8(isolate, name), value);
+}
+
+
 void Template::Set(const char* name, v8::Handle<Data> value) {
-  Set(v8::String::NewFromUtf8(Isolate::GetCurrent(), name), value);
+  Set(Isolate::GetCurrent(), name, value);
 }
 
 
diff --git a/src/allocation-site-scopes.cc b/src/allocation-site-scopes.cc
index 8097045..31120b9 100644
--- a/src/allocation-site-scopes.cc
+++ b/src/allocation-site-scopes.cc
@@ -82,27 +82,4 @@
   }
 }
 
-
-Handle<AllocationSite> AllocationSiteUsageContext::EnterNewScope() {
-  if (top().is_null()) {
-    InitializeTraversal(top_site_);
-  } else {
-    // Advance current site
-    Object* nested_site = current()->nested_site();
-    // Something is wrong if we advance to the end of the list here.
-    ASSERT(nested_site->IsAllocationSite());
-    update_current_site(AllocationSite::cast(nested_site));
-  }
-  return Handle<AllocationSite>(*current(), isolate());
-}
-
-
-void AllocationSiteUsageContext::ExitScope(
-    Handle<AllocationSite> scope_site,
-    Handle<JSObject> object) {
-  // This assert ensures that we are pointing at the right sub-object in a
-  // recursive walk of a nested literal.
-  ASSERT(object.is_null() || *object == scope_site->transition_info());
-}
-
 } }  // namespace v8::internal
diff --git a/src/allocation-site-scopes.h b/src/allocation-site-scopes.h
index 1c3afdf..f106c5e 100644
--- a/src/allocation-site-scopes.h
+++ b/src/allocation-site-scopes.h
@@ -45,7 +45,6 @@
     isolate_ = isolate;
     activated_ = activated;
   };
-  virtual ~AllocationSiteContext() {}
 
   Handle<AllocationSite> top() { return top_; }
   Handle<AllocationSite> current() { return current_; }
@@ -53,19 +52,13 @@
   // If activated, then recursively create mementos
   bool activated() const { return activated_; }
 
-  // Returns the AllocationSite that matches this scope.
-  virtual Handle<AllocationSite> EnterNewScope() = 0;
-
-  // scope_site should be the handle returned by the matching EnterNewScope()
-  virtual void ExitScope(Handle<AllocationSite> scope_site,
-                         Handle<JSObject> object) = 0;
+  Isolate* isolate() { return isolate_; }
 
  protected:
   void update_current_site(AllocationSite* site) {
     *(current_.location()) = site;
   }
 
-  Isolate* isolate() { return isolate_; }
   void InitializeTraversal(Handle<AllocationSite> site) {
     top_ = site;
     current_ = Handle<AllocationSite>(*top_, isolate());
@@ -86,9 +79,8 @@
   explicit AllocationSiteCreationContext(Isolate* isolate)
       : AllocationSiteContext(isolate, true) { }
 
-  virtual Handle<AllocationSite> EnterNewScope() V8_OVERRIDE;
-  virtual void ExitScope(Handle<AllocationSite> site,
-                         Handle<JSObject> object) V8_OVERRIDE;
+  Handle<AllocationSite> EnterNewScope();
+  void ExitScope(Handle<AllocationSite> site, Handle<JSObject> object);
 };
 
 
@@ -101,9 +93,25 @@
       : AllocationSiteContext(isolate, activated),
         top_site_(site) { }
 
-  virtual Handle<AllocationSite> EnterNewScope() V8_OVERRIDE;
-  virtual void ExitScope(Handle<AllocationSite> site,
-                         Handle<JSObject> object) V8_OVERRIDE;
+  inline Handle<AllocationSite> EnterNewScope() {
+    if (top().is_null()) {
+      InitializeTraversal(top_site_);
+    } else {
+      // Advance current site
+      Object* nested_site = current()->nested_site();
+      // Something is wrong if we advance to the end of the list here.
+      ASSERT(nested_site->IsAllocationSite());
+      update_current_site(AllocationSite::cast(nested_site));
+    }
+    return Handle<AllocationSite>(*current(), isolate());
+  }
+
+  inline void ExitScope(Handle<AllocationSite> scope_site,
+                        Handle<JSObject> object) {
+    // This assert ensures that we are pointing at the right sub-object in a
+    // recursive walk of a nested literal.
+    ASSERT(object.is_null() || *object == scope_site->transition_info());
+  }
 
  private:
   Handle<AllocationSite> top_site_;
diff --git a/src/api.cc b/src/api.cc
index 18aca94..30a7ef8 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1078,32 +1078,42 @@
 }
 
 Local<FunctionTemplate> FunctionTemplate::New(
+    Isolate* isolate,
     FunctionCallback callback,
     v8::Handle<Value> data,
     v8::Handle<Signature> signature,
     int length) {
-  i::Isolate* isolate = i::Isolate::Current();
-  EnsureInitializedForIsolate(isolate, "v8::FunctionTemplate::New()");
-  LOG_API(isolate, "FunctionTemplate::New");
-  ENTER_V8(isolate);
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  EnsureInitializedForIsolate(i_isolate, "v8::FunctionTemplate::New()");
+  LOG_API(i_isolate, "FunctionTemplate::New");
+  ENTER_V8(i_isolate);
   return FunctionTemplateNew(
-      isolate, callback, data, signature, length, false);
+      i_isolate, callback, data, signature, length, false);
 }
 
 
-Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
-      int argc, Handle<FunctionTemplate> argv[]) {
-  i::Isolate* isolate = i::Isolate::Current();
-  EnsureInitializedForIsolate(isolate, "v8::Signature::New()");
-  LOG_API(isolate, "Signature::New");
-  ENTER_V8(isolate);
+Local<FunctionTemplate> FunctionTemplate::New(
+    FunctionCallback callback,
+    v8::Handle<Value> data,
+    v8::Handle<Signature> signature,
+    int length) {
+  return New(Isolate::GetCurrent(), callback, data, signature, length);
+}
+
+Local<Signature> Signature::New(Isolate* isolate,
+                                Handle<FunctionTemplate> receiver, int argc,
+                                Handle<FunctionTemplate> argv[]) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  EnsureInitializedForIsolate(i_isolate, "v8::Signature::New()");
+  LOG_API(i_isolate, "Signature::New");
+  ENTER_V8(i_isolate);
   i::Handle<i::Struct> struct_obj =
-      isolate->factory()->NewStruct(i::SIGNATURE_INFO_TYPE);
+      i_isolate->factory()->NewStruct(i::SIGNATURE_INFO_TYPE);
   i::Handle<i::SignatureInfo> obj =
       i::Handle<i::SignatureInfo>::cast(struct_obj);
   if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
   if (argc > 0) {
-    i::Handle<i::FixedArray> args = isolate->factory()->NewFixedArray(argc);
+    i::Handle<i::FixedArray> args = i_isolate->factory()->NewFixedArray(argc);
     for (int i = 0; i < argc; i++) {
       if (!argv[i].IsEmpty())
         args->set(i, *Utils::OpenHandle(*argv[i]));
@@ -1114,6 +1124,20 @@
 }
 
 
+Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
+      int argc, Handle<FunctionTemplate> argv[]) {
+  return New(Isolate::GetCurrent(), receiver, argc, argv);
+}
+
+
+Local<AccessorSignature> AccessorSignature::New(
+      Isolate* isolate,
+      Handle<FunctionTemplate> receiver) {
+  return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver));
+}
+
+
+// While this is just a cast, it's lame not to use an Isolate parameter.
 Local<AccessorSignature> AccessorSignature::New(
       Handle<FunctionTemplate> receiver) {
   return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver));
@@ -1363,7 +1387,7 @@
   i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this);
   if (handle->instance_template()->IsUndefined()) {
     Local<ObjectTemplate> templ =
-        ObjectTemplate::New(ToApiHandle<FunctionTemplate>(handle));
+        ObjectTemplate::New(isolate, ToApiHandle<FunctionTemplate>(handle));
     handle->set_instance_template(*Utils::OpenHandle(*templ));
   }
   i::Handle<i::ObjectTemplateInfo> result(
@@ -1410,14 +1434,19 @@
 // --- O b j e c t T e m p l a t e ---
 
 
+Local<ObjectTemplate> ObjectTemplate::New(Isolate* isolate) {
+  return New(reinterpret_cast<i::Isolate*>(isolate), Local<FunctionTemplate>());
+}
+
+
 Local<ObjectTemplate> ObjectTemplate::New() {
-  return New(Local<FunctionTemplate>());
+  return New(i::Isolate::Current(), Local<FunctionTemplate>());
 }
 
 
 Local<ObjectTemplate> ObjectTemplate::New(
+      i::Isolate* isolate,
       v8::Handle<FunctionTemplate> constructor) {
-  i::Isolate* isolate = i::Isolate::Current();
   EnsureInitializedForIsolate(isolate, "v8::ObjectTemplate::New()");
   LOG_API(isolate, "ObjectTemplate::New");
   ENTER_V8(isolate);
@@ -2285,10 +2314,15 @@
 }
 
 
+void Message::PrintCurrentStackTrace(Isolate* isolate, FILE* out) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  ENTER_V8(i_isolate);
+  i_isolate->PrintCurrentStackTrace(out);
+}
+
+
 void Message::PrintCurrentStackTrace(FILE* out) {
-  i::Isolate* isolate = i::Isolate::Current();
-  ENTER_V8(isolate);
-  isolate->PrintCurrentStackTrace(out);
+  PrintCurrentStackTrace(Isolate::GetCurrent(), out);
 }
 
 
@@ -2319,13 +2353,21 @@
 }
 
 
+Local<StackTrace> StackTrace::CurrentStackTrace(
+    Isolate* isolate,
+    int frame_limit,
+    StackTraceOptions options) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  ENTER_V8(i_isolate);
+  i::Handle<i::JSArray> stackTrace =
+      i_isolate->CaptureCurrentStackTrace(frame_limit, options);
+  return Utils::StackTraceToLocal(stackTrace);
+}
+
+
 Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
     StackTraceOptions options) {
-  i::Isolate* isolate = i::Isolate::Current();
-  ENTER_V8(isolate);
-  i::Handle<i::JSArray> stackTrace =
-      isolate->CaptureCurrentStackTrace(frame_limit, options);
-  return Utils::StackTraceToLocal(stackTrace);
+  return CurrentStackTrace(Isolate::GetCurrent(), frame_limit, options);
 }
 
 
@@ -5646,18 +5688,25 @@
 
 
 Local<String> v8::String::NewExternal(
+      Isolate* isolate,
       v8::String::ExternalStringResource* resource) {
-  i::Isolate* isolate = i::Isolate::Current();
-  EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()");
-  LOG_API(isolate, "String::NewExternal");
-  ENTER_V8(isolate);
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()");
+  LOG_API(i_isolate, "String::NewExternal");
+  ENTER_V8(i_isolate);
   CHECK(resource && resource->data());
-  i::Handle<i::String> result = NewExternalStringHandle(isolate, resource);
-  isolate->heap()->external_string_table()->AddString(*result);
+  i::Handle<i::String> result = NewExternalStringHandle(i_isolate, resource);
+  i_isolate->heap()->external_string_table()->AddString(*result);
   return Utils::ToLocal(result);
 }
 
 
+Local<String> v8::String::NewExternal(
+      v8::String::ExternalStringResource* resource) {
+  return NewExternal(Isolate::GetCurrent(), resource);
+}
+
+
 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
   i::Handle<i::String> obj = Utils::OpenHandle(this);
   i::Isolate* isolate = obj->GetIsolate();
@@ -5695,18 +5744,26 @@
 
 
 Local<String> v8::String::NewExternal(
+      Isolate* isolate,
       v8::String::ExternalAsciiStringResource* resource) {
-  i::Isolate* isolate = i::Isolate::Current();
-  EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()");
-  LOG_API(isolate, "String::NewExternal");
-  ENTER_V8(isolate);
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()");
+  LOG_API(i_isolate, "String::NewExternal");
+  ENTER_V8(i_isolate);
   CHECK(resource && resource->data());
-  i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource);
-  isolate->heap()->external_string_table()->AddString(*result);
+  i::Handle<i::String> result =
+      NewExternalAsciiStringHandle(i_isolate, resource);
+  i_isolate->heap()->external_string_table()->AddString(*result);
   return Utils::ToLocal(result);
 }
 
 
+Local<String> v8::String::NewExternal(
+      v8::String::ExternalAsciiStringResource* resource) {
+  return NewExternal(Isolate::GetCurrent(), resource);
+}
+
+
 bool v8::String::MakeExternal(
     v8::String::ExternalAsciiStringResource* resource) {
   i::Handle<i::String> obj = Utils::OpenHandle(this);
@@ -5762,25 +5819,35 @@
 }
 
 
-Local<v8::Object> v8::Object::New() {
-  i::Isolate* isolate = i::Isolate::Current();
-  EnsureInitializedForIsolate(isolate, "v8::Object::New()");
-  LOG_API(isolate, "Object::New");
-  ENTER_V8(isolate);
+Local<v8::Object> v8::Object::New(Isolate* isolate) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  EnsureInitializedForIsolate(i_isolate, "v8::Object::New()");
+  LOG_API(i_isolate, "Object::New");
+  ENTER_V8(i_isolate);
   i::Handle<i::JSObject> obj =
-      isolate->factory()->NewJSObject(isolate->object_function());
+      i_isolate->factory()->NewJSObject(i_isolate->object_function());
+  return Utils::ToLocal(obj);
+}
+
+
+Local<v8::Object> v8::Object::New() {
+  return New(Isolate::GetCurrent());
+}
+
+
+Local<v8::Value> v8::NumberObject::New(Isolate* isolate, double value) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  EnsureInitializedForIsolate(i_isolate, "v8::NumberObject::New()");
+  LOG_API(i_isolate, "NumberObject::New");
+  ENTER_V8(i_isolate);
+  i::Handle<i::Object> number = i_isolate->factory()->NewNumber(value);
+  i::Handle<i::Object> obj = i_isolate->factory()->ToObject(number);
   return Utils::ToLocal(obj);
 }
 
 
 Local<v8::Value> v8::NumberObject::New(double value) {
-  i::Isolate* isolate = i::Isolate::Current();
-  EnsureInitializedForIsolate(isolate, "v8::NumberObject::New()");
-  LOG_API(isolate, "NumberObject::New");
-  ENTER_V8(isolate);
-  i::Handle<i::Object> number = isolate->factory()->NewNumber(value);
-  i::Handle<i::Object> obj = isolate->factory()->ToObject(number);
-  return Utils::ToLocal(obj);
+  return New(Isolate::GetCurrent(), value);
 }
 
 
@@ -5858,23 +5925,28 @@
 }
 
 
-Local<v8::Value> v8::Date::New(double time) {
-  i::Isolate* isolate = i::Isolate::Current();
-  EnsureInitializedForIsolate(isolate, "v8::Date::New()");
-  LOG_API(isolate, "Date::New");
+Local<v8::Value> v8::Date::New(Isolate* isolate, double time) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  EnsureInitializedForIsolate(i_isolate, "v8::Date::New()");
+  LOG_API(i_isolate, "Date::New");
   if (std::isnan(time)) {
     // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
     time = i::OS::nan_value();
   }
-  ENTER_V8(isolate);
-  EXCEPTION_PREAMBLE(isolate);
+  ENTER_V8(i_isolate);
+  EXCEPTION_PREAMBLE(i_isolate);
   i::Handle<i::Object> obj =
-      i::Execution::NewDate(isolate, time, &has_pending_exception);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Value>());
+      i::Execution::NewDate(i_isolate, time, &has_pending_exception);
+  EXCEPTION_BAILOUT_CHECK(i_isolate, Local<v8::Value>());
   return Utils::ToLocal(obj);
 }
 
 
+Local<v8::Value> v8::Date::New(double time) {
+  return New(Isolate::GetCurrent(), time);
+}
+
+
 double v8::Date::ValueOf() const {
   i::Isolate* isolate = i::Isolate::Current();
   LOG_API(isolate, "Date::NumberValue");
@@ -5884,22 +5956,22 @@
 }
 
 
-void v8::Date::DateTimeConfigurationChangeNotification() {
-  i::Isolate* isolate = i::Isolate::Current();
-  ON_BAILOUT(isolate, "v8::Date::DateTimeConfigurationChangeNotification()",
+void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  ON_BAILOUT(i_isolate, "v8::Date::DateTimeConfigurationChangeNotification()",
              return);
-  LOG_API(isolate, "Date::DateTimeConfigurationChangeNotification");
-  ENTER_V8(isolate);
+  LOG_API(i_isolate, "Date::DateTimeConfigurationChangeNotification");
+  ENTER_V8(i_isolate);
 
-  isolate->date_cache()->ResetDateCache();
+  i_isolate->date_cache()->ResetDateCache();
 
-  i::HandleScope scope(isolate);
+  i::HandleScope scope(i_isolate);
   // Get the function ResetDateCache (defined in date.js).
   i::Handle<i::String> func_name_str =
-      isolate->factory()->InternalizeOneByteString(
+      i_isolate->factory()->InternalizeOneByteString(
           STATIC_ASCII_VECTOR("ResetDateCache"));
   i::MaybeObject* result =
-      isolate->js_builtins_object()->GetProperty(*func_name_str);
+      i_isolate->js_builtins_object()->GetProperty(*func_name_str);
   i::Object* object_func;
   if (!result->ToObject(&object_func)) {
     return;
@@ -5912,7 +5984,7 @@
     // Call ResetDateCache(0 but expect no exceptions:
     bool caught_exception = false;
     i::Execution::TryCall(func,
-                          isolate->js_builtins_object(),
+                          i_isolate->js_builtins_object(),
                           0,
                           NULL,
                           &caught_exception);
@@ -5920,6 +5992,11 @@
 }
 
 
+void v8::Date::DateTimeConfigurationChangeNotification() {
+  DateTimeConfigurationChangeNotification(Isolate::GetCurrent());
+}
+
+
 static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
   i::Isolate* isolate = i::Isolate::Current();
   uint8_t flags_buf[3];
@@ -5971,20 +6048,25 @@
 }
 
 
-Local<v8::Array> v8::Array::New(int length) {
-  i::Isolate* isolate = i::Isolate::Current();
-  EnsureInitializedForIsolate(isolate, "v8::Array::New()");
-  LOG_API(isolate, "Array::New");
-  ENTER_V8(isolate);
+Local<v8::Array> v8::Array::New(Isolate* isolate, int length) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  EnsureInitializedForIsolate(i_isolate, "v8::Array::New()");
+  LOG_API(i_isolate, "Array::New");
+  ENTER_V8(i_isolate);
   int real_length = length > 0 ? length : 0;
-  i::Handle<i::JSArray> obj = isolate->factory()->NewJSArray(real_length);
+  i::Handle<i::JSArray> obj = i_isolate->factory()->NewJSArray(real_length);
   i::Handle<i::Object> length_obj =
-      isolate->factory()->NewNumberFromInt(real_length);
+      i_isolate->factory()->NewNumberFromInt(real_length);
   obj->set_length(*length_obj);
   return Utils::ToLocal(obj);
 }
 
 
+Local<v8::Array> v8::Array::New(int length) {
+  return New(Isolate::GetCurrent(), length);
+}
+
+
 uint32_t v8::Array::Length() const {
   i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
   i::Object* length = obj->length();
@@ -6068,27 +6150,38 @@
 }
 
 
-Local<ArrayBuffer> v8::ArrayBuffer::New(size_t byte_length) {
-  i::Isolate* isolate = i::Isolate::Current();
-  EnsureInitializedForIsolate(isolate, "v8::ArrayBuffer::New(size_t)");
-  LOG_API(isolate, "v8::ArrayBuffer::New(size_t)");
-  ENTER_V8(isolate);
+Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, size_t byte_length) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  EnsureInitializedForIsolate(i_isolate, "v8::ArrayBuffer::New(size_t)");
+  LOG_API(i_isolate, "v8::ArrayBuffer::New(size_t)");
+  ENTER_V8(i_isolate);
   i::Handle<i::JSArrayBuffer> obj =
-      isolate->factory()->NewJSArrayBuffer();
-  i::Runtime::SetupArrayBufferAllocatingData(isolate, obj, byte_length);
+      i_isolate->factory()->NewJSArrayBuffer();
+  i::Runtime::SetupArrayBufferAllocatingData(i_isolate, obj, byte_length);
+  return Utils::ToLocal(obj);
+}
+
+
+Local<ArrayBuffer> v8::ArrayBuffer::New(size_t byte_length) {
+  return New(Isolate::GetCurrent(), byte_length);
+}
+
+
+Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, void* data,
+                                        size_t byte_length) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  EnsureInitializedForIsolate(i_isolate, "v8::ArrayBuffer::New(void*, size_t)");
+  LOG_API(i_isolate, "v8::ArrayBuffer::New(void*, size_t)");
+  ENTER_V8(i_isolate);
+  i::Handle<i::JSArrayBuffer> obj =
+      i_isolate->factory()->NewJSArrayBuffer();
+  i::Runtime::SetupArrayBuffer(i_isolate, obj, true, data, byte_length);
   return Utils::ToLocal(obj);
 }
 
 
 Local<ArrayBuffer> v8::ArrayBuffer::New(void* data, size_t byte_length) {
-  i::Isolate* isolate = i::Isolate::Current();
-  EnsureInitializedForIsolate(isolate, "v8::ArrayBuffer::New(void*, size_t)");
-  LOG_API(isolate, "v8::ArrayBuffer::New(void*, size_t)");
-  ENTER_V8(isolate);
-  i::Handle<i::JSArrayBuffer> obj =
-      isolate->factory()->NewJSArrayBuffer();
-  i::Runtime::SetupArrayBuffer(isolate, obj, true, data, byte_length);
-  return Utils::ToLocal(obj);
+  return New(Isolate::GetCurrent(), data, byte_length);
 }
 
 
@@ -6280,18 +6373,28 @@
 Local<Integer> v8::Integer::New(int32_t value) {
   i::Isolate* isolate = i::Isolate::UncheckedCurrent();
   EnsureInitializedForIsolate(isolate, "v8::Integer::New()");
-  return v8::Integer::New(value, reinterpret_cast<Isolate*>(isolate));
+  return v8::Integer::New(reinterpret_cast<Isolate*>(isolate), value);
 }
 
 
 Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
   i::Isolate* isolate = i::Isolate::Current();
   EnsureInitializedForIsolate(isolate, "v8::Integer::NewFromUnsigned()");
-  return Integer::NewFromUnsigned(value, reinterpret_cast<Isolate*>(isolate));
+  return Integer::NewFromUnsigned(reinterpret_cast<Isolate*>(isolate), value);
 }
 
 
 Local<Integer> v8::Integer::New(int32_t value, Isolate* isolate) {
+  return Integer::New(isolate, value);
+}
+
+
+Local<Integer> v8::Integer::NewFromUnsigned(uint32_t value, Isolate* isolate) {
+  return Integer::NewFromUnsigned(isolate, value);
+}
+
+
+Local<Integer> v8::Integer::New(Isolate* isolate, int32_t value) {
   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
   ASSERT(internal_isolate->IsInitialized());
   if (i::Smi::IsValid(value)) {
@@ -6304,7 +6407,7 @@
 }
 
 
-Local<Integer> v8::Integer::NewFromUnsigned(uint32_t value, Isolate* isolate) {
+Local<Integer> v8::Integer::NewFromUnsigned(Isolate* isolate, uint32_t value) {
   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
   ASSERT(internal_isolate->IsInitialized());
   bool fits_into_int32_t = (value & (1 << 31)) == 0;
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index 24c5cca..3399958 100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -457,12 +457,6 @@
 }
 
 
-void Assembler::set_external_target_at(Address constant_pool_entry,
-                                       Address target) {
-  Memory::Address_at(constant_pool_entry) = target;
-}
-
-
 static Instr EncodeMovwImmediate(uint32_t immediate) {
   ASSERT(immediate < 0x10000);
   return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index 137dd73..afb0c62 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -803,11 +803,6 @@
   inline static void deserialization_set_special_target_at(
       Address constant_pool_entry, Address target);
 
-  // This sets the branch destination (which is in the constant pool on ARM).
-  // This is for calls and branches to runtime code.
-  inline static void set_external_target_at(Address constant_pool_entry,
-                                            Address target);
-
   // Here we are patching the address in the constant pool, not the actual call
   // instruction.  The address in the constant pool is the same size as a
   // pointer.
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 3473445..bfe6da0 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -77,7 +77,7 @@
   descriptor->register_param_count_ = 3;
   descriptor->register_params_ = registers;
   descriptor->deoptimization_handler_ =
-      Runtime::FunctionForId(Runtime::kCreateArrayLiteral)->entry;
+      Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry;
 }
 
 
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 4a39970..15bfba3 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -1770,6 +1770,10 @@
   Comment cmnt(masm_, "[ ArrayLiteral");
 
   expr->BuildConstantElements(isolate());
+  int flags = expr->depth() == 1
+      ? ArrayLiteral::kShallowElements
+      : ArrayLiteral::kNoFlags;
+
   ZoneList<Expression*>* subexprs = expr->values();
   int length = subexprs->length();
   Handle<FixedArray> constant_elements = expr->constant_elements();
@@ -1795,8 +1799,9 @@
         isolate()->counters()->cow_arrays_created_stub(), 1, r1, r2);
   } else if (expr->depth() > 1 || Serializer::enabled() ||
              length > FastCloneShallowArrayStub::kMaximumClonedLength) {
-    __ Push(r3, r2, r1);
-    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
+    __ mov(r0, Operand(Smi::FromInt(flags)));
+    __ Push(r3, r2, r1, r0);
+    __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
   } else {
     ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) ||
            FLAG_smi_only_arrays);
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index eeffc16..71c9dda 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1667,6 +1667,15 @@
       result = AssignEnvironment(result);
     }
     return result;
+  } else if (instr->representation().IsExternal()) {
+    ASSERT(instr->left()->representation().IsExternal());
+    ASSERT(instr->right()->representation().IsInteger32());
+    ASSERT(!instr->CheckFlag(HValue::kCanOverflow));
+    LOperand* left = UseRegisterAtStart(instr->left());
+    LOperand* right = UseOrConstantAtStart(instr->right());
+    LAddI* add = new(zone()) LAddI(left, right);
+    LInstruction* result = DefineAsRegister(add);
+    return result;
   } else if (instr->representation().IsDouble()) {
     if (instr->left()->IsMul()) {
       return DoMultiplyAdd(HMul::cast(instr->left()), instr->right());
@@ -2561,7 +2570,7 @@
   LInstruction* goto_instr = CheckElideControlInstruction(instr);
   if (goto_instr != NULL) return goto_instr;
 
-  return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
+  return new(zone()) LTypeofIsAndBranch(UseRegister(instr->value()));
 }
 
 
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 4b05db1..6dadef0 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -5557,22 +5557,21 @@
   Register scratch = scratch0();
   if (type_name->Equals(heap()->number_string())) {
     __ JumpIfSmi(input, true_label);
-    __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
-    __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
-    __ cmp(input, Operand(ip));
+    __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
+    __ CompareRoot(scratch, Heap::kHeapNumberMapRootIndex);
     final_branch_condition = eq;
 
   } else if (type_name->Equals(heap()->string_string())) {
     __ JumpIfSmi(input, false_label);
-    __ CompareObjectType(input, input, scratch, FIRST_NONSTRING_TYPE);
+    __ CompareObjectType(input, scratch, no_reg, FIRST_NONSTRING_TYPE);
     __ b(ge, false_label);
-    __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
-    __ tst(ip, Operand(1 << Map::kIsUndetectable));
+    __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
+    __ tst(scratch, Operand(1 << Map::kIsUndetectable));
     final_branch_condition = eq;
 
   } else if (type_name->Equals(heap()->symbol_string())) {
     __ JumpIfSmi(input, false_label);
-    __ CompareObjectType(input, input, scratch, SYMBOL_TYPE);
+    __ CompareObjectType(input, scratch, no_reg, SYMBOL_TYPE);
     final_branch_condition = eq;
 
   } else if (type_name->Equals(heap()->boolean_string())) {
@@ -5590,33 +5589,35 @@
     __ b(eq, true_label);
     __ JumpIfSmi(input, false_label);
     // Check for undetectable objects => true.
-    __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
-    __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
-    __ tst(ip, Operand(1 << Map::kIsUndetectable));
+    __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
+    __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
+    __ tst(scratch, Operand(1 << Map::kIsUndetectable));
     final_branch_condition = ne;
 
   } else if (type_name->Equals(heap()->function_string())) {
     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
+    Register type_reg = scratch;
     __ JumpIfSmi(input, false_label);
-    __ CompareObjectType(input, scratch, input, JS_FUNCTION_TYPE);
+    __ CompareObjectType(input, scratch, type_reg, JS_FUNCTION_TYPE);
     __ b(eq, true_label);
-    __ cmp(input, Operand(JS_FUNCTION_PROXY_TYPE));
+    __ cmp(type_reg, Operand(JS_FUNCTION_PROXY_TYPE));
     final_branch_condition = eq;
 
   } else if (type_name->Equals(heap()->object_string())) {
+    Register map = scratch;
     __ JumpIfSmi(input, false_label);
     if (!FLAG_harmony_typeof) {
       __ CompareRoot(input, Heap::kNullValueRootIndex);
       __ b(eq, true_label);
     }
-    __ CompareObjectType(input, input, scratch,
-                         FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
-    __ b(lt, false_label);
-    __ CompareInstanceType(input, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
-    __ b(gt, false_label);
+    __ CheckObjectTypeRange(input,
+                            map,
+                            FIRST_NONCALLABLE_SPEC_OBJECT_TYPE,
+                            LAST_NONCALLABLE_SPEC_OBJECT_TYPE,
+                            false_label);
     // Check for undetectable objects => false.
-    __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
-    __ tst(ip, Operand(1 << Map::kIsUndetectable));
+    __ ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset));
+    __ tst(scratch, Operand(1 << Map::kIsUndetectable));
     final_branch_condition = eq;
 
   } else {
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 65962e7..8bb1cb1 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -2022,14 +2022,36 @@
                                        Register map,
                                        Register type_reg,
                                        InstanceType type) {
+  const Register temp = type_reg.is(no_reg) ? ip : type_reg;
+
   ldr(map, FieldMemOperand(object, HeapObject::kMapOffset));
-  CompareInstanceType(map, type_reg, type);
+  CompareInstanceType(map, temp, type);
+}
+
+
+void MacroAssembler::CheckObjectTypeRange(Register object,
+                                          Register map,
+                                          InstanceType min_type,
+                                          InstanceType max_type,
+                                          Label* false_label) {
+  STATIC_ASSERT(Map::kInstanceTypeOffset < 4096);
+  STATIC_ASSERT(LAST_TYPE < 256);
+  ldr(map, FieldMemOperand(object, HeapObject::kMapOffset));
+  ldrb(ip, FieldMemOperand(map, Map::kInstanceTypeOffset));
+  sub(ip, ip, Operand(min_type));
+  cmp(ip, Operand(max_type - min_type));
+  b(hi, false_label);
 }
 
 
 void MacroAssembler::CompareInstanceType(Register map,
                                          Register type_reg,
                                          InstanceType type) {
+  // Registers map and type_reg can be ip. These two lines assert
+  // that ip can be used with the two instructions (the constants
+  // will never need ip).
+  STATIC_ASSERT(Map::kInstanceTypeOffset < 4096);
+  STATIC_ASSERT(LAST_TYPE < 256);
   ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
   cmp(type_reg, Operand(type));
 }
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 5e20eec..467a1ac 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -845,11 +845,21 @@
   // are the same register).  It leaves the heap object in the heap_object
   // register unless the heap_object register is the same register as one of the
   // other registers.
+  // Type_reg can be no_reg. In that case ip is used.
   void CompareObjectType(Register heap_object,
                          Register map,
                          Register type_reg,
                          InstanceType type);
 
+  // Compare object type for heap object. Branch to false_label if type
+  // is lower than min_type or greater than max_type.
+  // Load map into the register map.
+  void CheckObjectTypeRange(Register heap_object,
+                            Register map,
+                            InstanceType min_type,
+                            InstanceType max_type,
+                            Label* false_label);
+
   // Compare instance type in a map.  map contains a valid map object whose
   // object type should be compared with the given type.  This both
   // sets the flags and leaves the object type in the type_reg register.
diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h
index e392c5c..0af5162 100644
--- a/src/arm/simulator-arm.h
+++ b/src/arm/simulator-arm.h
@@ -269,7 +269,7 @@
 
   // Checks if the current instruction should be executed based on its
   // condition bits.
-  bool ConditionallyExecute(Instruction* instr);
+  inline bool ConditionallyExecute(Instruction* instr);
 
   // Helper functions to set the conditional flags in the architecture state.
   void SetNZFlags(int32_t val);
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 9b2ba53..00ea079 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -798,17 +798,12 @@
     Register receiver,
     Register holder,
     Register name,
-    Handle<JSObject> holder_obj) {
+    Handle<JSObject> holder_obj,
+    IC::UtilityId id) {
   PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
-
-  ExternalReference ref =
-      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
-                        masm->isolate());
-  __ mov(r0, Operand(StubCache::kInterceptorArgsLength));
-  __ mov(r1, Operand(ref));
-
-  CEntryStub stub(1);
-  __ CallStub(&stub);
+  __ CallExternalReference(
+      ExternalReference(IC_Utility(id), masm->isolate()),
+      StubCache::kInterceptorArgsLength);
 }
 
 
@@ -1113,11 +1108,11 @@
     FrameScope scope(masm, StackFrame::INTERNAL);
     // Save the name_ register across the call.
     __ push(name_);
-    PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
-    __ CallExternalReference(
-        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
-                          masm->isolate()),
-        StubCache::kInterceptorArgsLength);
+
+    CompileCallLoadPropertyWithInterceptor(
+        masm, receiver, holder, name_, interceptor_holder,
+        IC::kLoadPropertyWithInterceptorForCall);
+
     // Restore the name_ register.
     __ pop(name_);
     // Leave the internal frame.
@@ -1132,11 +1127,9 @@
     {
       FrameScope scope(masm, StackFrame::INTERNAL);
       __ Push(holder, name_);
-      CompileCallLoadPropertyWithInterceptor(masm,
-                                             receiver,
-                                             holder,
-                                             name_,
-                                             holder_obj);
+      CompileCallLoadPropertyWithInterceptor(
+          masm, receiver, holder, name_, holder_obj,
+          IC::kLoadPropertyWithInterceptorOnly);
       __ pop(name_);  // Restore the name.
       __ pop(receiver);  // Restore the holder.
     }
@@ -1503,11 +1496,10 @@
       // Invoke an interceptor.  Note: map checks from receiver to
       // interceptor's holder has been compiled before (see a caller
       // of this method.)
-      CompileCallLoadPropertyWithInterceptor(masm(),
-                                             receiver(),
-                                             holder_reg,
-                                             this->name(),
-                                             interceptor_holder);
+      CompileCallLoadPropertyWithInterceptor(
+          masm(), receiver(), holder_reg, this->name(), interceptor_holder,
+          IC::kLoadPropertyWithInterceptorOnly);
+
       // Check if interceptor provided a value for property.  If it's
       // the case, return immediately.
       Label interceptor_failed;
diff --git a/src/ast.h b/src/ast.h
index e3fc053..4158907 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1604,6 +1604,12 @@
   // Populate the constant elements fixed array.
   void BuildConstantElements(Isolate* isolate);
 
+  enum Flags {
+    kNoFlags = 0,
+    kShallowElements = 1,
+    kDisableMementos = 1 << 1
+  };
+
  protected:
   ArrayLiteral(Isolate* isolate,
                ZoneList<Expression*>* values,
diff --git a/src/debug.cc b/src/debug.cc
index f3c3764..23495c8 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -3137,7 +3137,7 @@
     v8::Local<v8::Function> fun =
         v8::Local<v8::Function>::Cast(api_exec_state->Get(fun_name));
 
-    v8::Handle<v8::Boolean> running = v8::Boolean::New(auto_continue);
+    v8::Handle<v8::Boolean> running = v8::Boolean::New(isolate, auto_continue);
     static const int kArgc = 1;
     v8::Handle<Value> argv[kArgc] = { running };
     cmd_processor = v8::Local<v8::Object>::Cast(
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index fec9ee5..483d1e3 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -1579,7 +1579,8 @@
   // Compute the function template for the native function.
   Handle<String> name = expr->name();
   v8::Handle<v8::FunctionTemplate> fun_template =
-      expr->extension()->GetNativeFunction(v8::Utils::ToLocal(name));
+      expr->extension()->GetNativeFunctionTemplate(
+          reinterpret_cast<v8::Isolate*>(isolate()), v8::Utils::ToLocal(name));
   ASSERT(!fun_template.IsEmpty());
 
   // Instantiate the function and create a shared function info from it.
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index e816471..5675c55 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -1262,6 +1262,26 @@
 }
 
 
+Representation HAdd::RepresentationFromInputs() {
+  Representation left_rep = left()->representation();
+  if (left_rep.IsExternal()) {
+    return Representation::External();
+  }
+  return HArithmeticBinaryOperation::RepresentationFromInputs();
+}
+
+
+Representation HAdd::RequiredInputRepresentation(int index) {
+  if (index == 2) {
+    Representation left_rep = left()->representation();
+    if (left_rep.IsExternal()) {
+      return Representation::Integer32();
+    }
+  }
+  return HArithmeticBinaryOperation::RequiredInputRepresentation(index);
+}
+
+
 static bool IsIdentityOperation(HValue* arg1, HValue* arg2, int32_t identity) {
   return arg1->representation().IsSpecialization() &&
     arg2->EqualsInteger32Constant(identity);
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index fba23fa..eac3c51 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -4732,8 +4732,9 @@
 
   // Add is only commutative if two integer values are added and not if two
   // tagged values are added (because it might be a String concatenation).
+  // We also do not commute (pointer + offset).
   virtual bool IsCommutative() const V8_OVERRIDE {
-    return !representation().IsTagged();
+    return !representation().IsTagged() && !representation().IsExternal();
   }
 
   virtual HValue* EnsureAndPropagateNotMinusZero(
@@ -4769,6 +4770,10 @@
     }
   }
 
+  virtual Representation RepresentationFromInputs() V8_OVERRIDE;
+
+  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE;
+
   DECLARE_CONCRETE_INSTRUCTION(Add)
 
  protected:
@@ -6062,6 +6067,43 @@
   // Create an access for the payload of a Cell or JSGlobalPropertyCell.
   static HObjectAccess ForCellPayload(Isolate* isolate);
 
+  static HObjectAccess ForJSTypedArrayLength() {
+    return HObjectAccess::ForJSObjectOffset(JSTypedArray::kLengthOffset);
+  }
+
+  static HObjectAccess ForJSArrayBufferBackingStore() {
+    return HObjectAccess::ForJSObjectOffset(
+        JSArrayBuffer::kBackingStoreOffset, Representation::External());
+  }
+
+  static HObjectAccess ForExternalArrayExternalPointer() {
+    return HObjectAccess::ForJSObjectOffset(
+        ExternalArray::kExternalPointerOffset, Representation::External());
+  }
+
+  static HObjectAccess ForJSArrayBufferViewWeakNext() {
+    return HObjectAccess::ForJSObjectOffset(JSArrayBufferView::kWeakNextOffset);
+  }
+
+  static HObjectAccess ForJSArrayBufferWeakFirstView() {
+    return HObjectAccess::ForJSObjectOffset(
+        JSArrayBuffer::kWeakFirstViewOffset);
+  }
+
+  static HObjectAccess ForJSArrayBufferViewBuffer() {
+    return HObjectAccess::ForJSObjectOffset(JSArrayBufferView::kBufferOffset);
+  }
+
+  static HObjectAccess ForJSArrayBufferViewByteOffset() {
+    return HObjectAccess::ForJSObjectOffset(
+        JSArrayBufferView::kByteOffsetOffset);
+  }
+
+  static HObjectAccess ForJSArrayBufferViewByteLength() {
+    return HObjectAccess::ForJSObjectOffset(
+        JSArrayBufferView::kByteLengthOffset);
+  }
+
   void PrintTo(StringStream* stream);
 
   inline bool Equals(HObjectAccess that) const {
@@ -6478,6 +6520,8 @@
       } else if (field_representation().IsDouble() ||
                  field_representation().IsSmi()) {
         return field_representation();
+      } else if (field_representation().IsExternal()) {
+        return Representation::External();
       }
     }
     return Representation::Tagged();
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 3e08b69..634acd7 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -58,6 +58,7 @@
 #include "hydrogen-uint32-analysis.h"
 #include "lithium-allocator.h"
 #include "parser.h"
+#include "runtime.h"
 #include "scopeinfo.h"
 #include "scopes.h"
 #include "stub-cache.h"
@@ -5107,10 +5108,15 @@
     // pass an empty fixed array to the runtime function instead.
     Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
     int literal_index = expr->literal_index();
+    int flags = expr->depth() == 1
+        ? ArrayLiteral::kShallowElements
+        : ArrayLiteral::kNoFlags;
+    flags |= ArrayLiteral::kDisableMementos;
 
     Add<HPushArgument>(Add<HConstant>(literals));
     Add<HPushArgument>(Add<HConstant>(literal_index));
     Add<HPushArgument>(Add<HConstant>(constants));
+    Add<HPushArgument>(Add<HConstant>(flags));
 
     // TODO(mvstanton): Consider a flag to turn off creation of any
     // AllocationMementos for this call: we are in crankshaft and should have
@@ -5118,7 +5124,7 @@
     Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral;
     literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
                                 Runtime::FunctionForId(function_id),
-                                3);
+                                4);
 
     // De-opt if elements kind changed from boilerplate_elements_kind.
     Handle<Map> map = Handle<Map>(boilerplate_object->map(), isolate());
@@ -8055,6 +8061,42 @@
 #undef INLINE_FUNCTION_GENERATOR_ADDRESS
 
 
+template <class ViewClass>
+void HGraphBuilder::BuildArrayBufferViewInitialization(
+    HValue* obj,
+    HValue* buffer,
+    HValue* byte_offset,
+    HValue* byte_length) {
+
+  for (int offset = ViewClass::kSize;
+       offset < ViewClass::kSizeWithInternalFields;
+       offset += kPointerSize) {
+    Add<HStoreNamedField>(obj,
+        HObjectAccess::ForJSObjectOffset(offset),
+        Add<HConstant>(static_cast<int32_t>(0)));
+  }
+
+  Add<HStoreNamedField>(
+      obj,
+      HObjectAccess::ForJSArrayBufferViewBuffer(), buffer);
+  Add<HStoreNamedField>(
+      obj,
+      HObjectAccess::ForJSArrayBufferViewByteOffset(),
+      byte_offset);
+  Add<HStoreNamedField>(
+      obj,
+      HObjectAccess::ForJSArrayBufferViewByteLength(),
+      byte_length);
+
+  HObjectAccess weak_first_view_access =
+      HObjectAccess::ForJSArrayBufferWeakFirstView();
+  Add<HStoreNamedField>(obj,
+      HObjectAccess::ForJSArrayBufferViewWeakNext(),
+      Add<HLoadNamedField>(buffer, weak_first_view_access));
+  Add<HStoreNamedField>(buffer, weak_first_view_access, obj);
+}
+
+
 void HOptimizedGraphBuilder::VisitDataViewInitialize(
     CallRuntime* expr) {
   ZoneList<Expression*>* arguments = expr->arguments();
@@ -8073,31 +8115,127 @@
   CHECK_ALIVE(VisitForValue(arguments->at(3)));
   HValue* byte_length = Pop();
 
-  for (int offset = JSDataView::kSize;
-        offset < JSDataView::kSizeWithInternalFields;
-        offset += kPointerSize) {
-    Add<HStoreNamedField>(obj,
-        HObjectAccess::ForJSObjectOffset(offset),
-        Add<HConstant>(static_cast<int32_t>(0)));
+  BuildArrayBufferViewInitialization<JSDataView>(
+      obj, buffer, byte_offset, byte_length);
+}
+
+
+void HOptimizedGraphBuilder::VisitTypedArrayInitialize(
+    CallRuntime* expr) {
+  ZoneList<Expression*>* arguments = expr->arguments();
+
+  NoObservableSideEffectsScope scope(this);
+  static const int kObjectArg = 0;
+  static const int kArrayIdArg = 1;
+  static const int kBufferArg = 2;
+  static const int kByteOffsetArg = 3;
+  static const int kByteLengthArg = 4;
+  static const int kArgsLength = 5;
+  ASSERT(arguments->length() == kArgsLength);
+
+
+  CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg)));
+  HValue* obj = Pop();
+
+  ASSERT(arguments->at(kArrayIdArg)->node_type() == AstNode::kLiteral);
+  Handle<Object> value =
+      static_cast<Literal*>(arguments->at(kArrayIdArg))->value();
+  ASSERT(value->IsSmi());
+  int array_id = Smi::cast(*value)->value();
+
+  CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg)));
+  HValue* buffer = Pop();
+
+  HValue* byte_offset;
+  bool is_zero_byte_offset;
+
+  if (arguments->at(kByteOffsetArg)->node_type() == AstNode::kLiteral
+      && Smi::FromInt(0) ==
+      *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) {
+    byte_offset = Add<HConstant>(static_cast<int32_t>(0));
+    is_zero_byte_offset = true;
+  } else {
+    CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg)));
+    byte_offset = Pop();
+    is_zero_byte_offset = false;
   }
 
-  Add<HStoreNamedField>(obj,
-      HObjectAccess::ForJSObjectOffset(JSDataView::kBufferOffset), buffer);
-  Add<HStoreNamedField>(obj,
-      HObjectAccess::ForJSObjectOffset(JSDataView::kByteOffsetOffset),
-      byte_offset);
-  Add<HStoreNamedField>(obj,
-      HObjectAccess::ForJSObjectOffset(JSDataView::kByteLengthOffset),
-      byte_length);
+  CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg)));
+  HValue* byte_length = Pop();
 
-  Add<HStoreNamedField>(obj,
-      HObjectAccess::ForJSObjectOffset(JSDataView::kWeakNextOffset),
-      Add<HLoadNamedField>(buffer,
-          HObjectAccess::ForJSObjectOffset(
-            JSArrayBuffer::kWeakFirstViewOffset)));
-  Add<HStoreNamedField>(buffer,
-      HObjectAccess::ForJSObjectOffset(JSArrayBuffer::kWeakFirstViewOffset),
-      obj);
+  IfBuilder byte_offset_smi(this);
+
+  if (!is_zero_byte_offset) {
+    byte_offset_smi.If<HIsSmiAndBranch>(byte_offset);
+    byte_offset_smi.Then();
+  }
+
+  { //  byte_offset is Smi.
+    BuildArrayBufferViewInitialization<JSTypedArray>(
+        obj, buffer, byte_offset, byte_length);
+
+    ExternalArrayType array_type = kExternalByteArray;  // Bogus initialization.
+    size_t element_size = 1;  // Bogus initialization.
+    Runtime::ArrayIdToTypeAndSize(array_id, &array_type, &element_size);
+
+    HInstruction* length = AddUncasted<HDiv>(byte_length,
+        Add<HConstant>(static_cast<int32_t>(element_size)));
+
+    Add<HStoreNamedField>(obj,
+        HObjectAccess::ForJSTypedArrayLength(),
+        length);
+
+    HValue* elements =
+        Add<HAllocate>(
+            Add<HConstant>(ExternalArray::kAlignedSize),
+            HType::JSArray(),
+            NOT_TENURED,
+            static_cast<InstanceType>(FIRST_EXTERNAL_ARRAY_TYPE + array_type));
+
+    Handle<Map> external_array_map(
+        isolate()->heap()->MapForExternalArrayType(array_type));
+    Add<HStoreNamedField>(elements,
+        HObjectAccess::ForMap(),
+        Add<HConstant>(external_array_map));
+
+    HValue* backing_store = Add<HLoadNamedField>(
+        buffer, HObjectAccess::ForJSArrayBufferBackingStore());
+
+    HValue* typed_array_start;
+    if (is_zero_byte_offset) {
+      typed_array_start = backing_store;
+    } else {
+      HInstruction* external_pointer =
+          AddUncasted<HAdd>(backing_store, byte_offset);
+      // Arguments are checked prior to call to TypedArrayInitialize,
+      // including byte_offset.
+      external_pointer->ClearFlag(HValue::kCanOverflow);
+      typed_array_start = external_pointer;
+    }
+
+    Add<HStoreNamedField>(elements,
+        HObjectAccess::ForExternalArrayExternalPointer(),
+        typed_array_start);
+    Add<HStoreNamedField>(elements,
+        HObjectAccess::ForFixedArrayLength(),
+        length);
+    Add<HStoreNamedField>(
+        obj, HObjectAccess::ForElementsPointer(), elements);
+  }
+
+  if (!is_zero_byte_offset) {
+    byte_offset_smi.Else();
+    { //  byte_offset is not Smi.
+      Push(Add<HPushArgument>(obj));
+      VisitArgument(arguments->at(kArrayIdArg));
+      Push(Add<HPushArgument>(buffer));
+      Push(Add<HPushArgument>(byte_offset));
+      Push(Add<HPushArgument>(byte_length));
+      Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength);
+      Drop(kArgsLength);
+    }
+  }
+  byte_offset_smi.End();
 }
 
 
@@ -8116,6 +8254,16 @@
       return VisitDataViewInitialize(expr);
   }
 
+  if (function->function_id == Runtime::kTypedArrayInitialize) {
+    return VisitTypedArrayInitialize(expr);
+  }
+
+  if (function->function_id == Runtime::kMaxSmi) {
+    ASSERT(expr->arguments()->length() == 0);
+    HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue));
+    return ast_context()->ReturnInstruction(max_smi, expr->id());
+  }
+
   if (function->intrinsic_type == Runtime::INLINE) {
     ASSERT(expr->name()->length() > 0);
     ASSERT(expr->name()->Get(0) == '_');
@@ -9175,7 +9323,7 @@
 
 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
     Handle<JSObject> boilerplate_object,
-    AllocationSiteContext* site_context) {
+    AllocationSiteUsageContext* site_context) {
   NoObservableSideEffectsScope no_effects(this);
   InstanceType instance_type = boilerplate_object->map()->instance_type();
   ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
@@ -9268,7 +9416,7 @@
 void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
     Handle<JSObject> boilerplate_object,
     HInstruction* object,
-    AllocationSiteContext* site_context) {
+    AllocationSiteUsageContext* site_context) {
   Handle<DescriptorArray> descriptors(
       boilerplate_object->map()->instance_descriptors());
   int limit = boilerplate_object->map()->NumberOfOwnDescriptors();
@@ -9340,7 +9488,7 @@
     Handle<JSObject> boilerplate_object,
     Handle<FixedArrayBase> elements,
     HValue* object_elements,
-    AllocationSiteContext* site_context) {
+    AllocationSiteUsageContext* site_context) {
   ElementsKind kind = boilerplate_object->map()->elements_kind();
   int elements_length = elements->length();
   HValue* object_elements_length = Add<HConstant>(elements_length);
@@ -9381,7 +9529,7 @@
     Handle<FixedArrayBase> elements,
     ElementsKind kind,
     HValue* object_elements,
-    AllocationSiteContext* site_context) {
+    AllocationSiteUsageContext* site_context) {
   HInstruction* boilerplate_elements = Add<HConstant>(elements);
   int elements_length = elements->length();
   Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
diff --git a/src/hydrogen.h b/src/hydrogen.h
index e0c5066..bd42896 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -1736,6 +1736,12 @@
     position_ = position;
   }
 
+  template <typename ViewClass>
+  void BuildArrayBufferViewInitialization(HValue* obj,
+                                          HValue* buffer,
+                                          HValue* byte_offset,
+                                          HValue* byte_length);
+
  private:
   HGraphBuilder();
 
@@ -2195,6 +2201,8 @@
                                        SmallMapList* types,
                                        Handle<String> name);
 
+  void VisitTypedArrayInitialize(CallRuntime* expr);
+
   bool IsCallNewArrayInlineable(CallNew* expr);
   void BuildInlinedCallNewArray(CallNew* expr);
 
@@ -2403,7 +2411,7 @@
   HInstruction* BuildThisFunction();
 
   HInstruction* BuildFastLiteral(Handle<JSObject> boilerplate_object,
-                                 AllocationSiteContext* site_context);
+                                 AllocationSiteUsageContext* site_context);
 
   void BuildEmitObjectHeader(Handle<JSObject> boilerplate_object,
                              HInstruction* object);
@@ -2414,12 +2422,12 @@
 
   void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object,
                                    HInstruction* object,
-                                   AllocationSiteContext* site_context);
+                                   AllocationSiteUsageContext* site_context);
 
   void BuildEmitElements(Handle<JSObject> boilerplate_object,
                          Handle<FixedArrayBase> elements,
                          HValue* object_elements,
-                         AllocationSiteContext* site_context);
+                         AllocationSiteUsageContext* site_context);
 
   void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements,
                                  ElementsKind kind,
@@ -2428,7 +2436,7 @@
   void BuildEmitFixedArray(Handle<FixedArrayBase> elements,
                            ElementsKind kind,
                            HValue* object_elements,
-                           AllocationSiteContext* site_context);
+                           AllocationSiteUsageContext* site_context);
 
   void AddCheckPrototypeMaps(Handle<JSObject> holder,
                              Handle<Map> receiver_map);
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index ed7b71f..6ed0bc6 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -638,13 +638,6 @@
     set_target_address_at(instruction_payload, target);
   }
 
-  // This sets the branch destination (which is in the instruction on x86).
-  // This is for calls and branches to runtime code.
-  inline static void set_external_target_at(Address instruction_payload,
-                                            Address target) {
-    set_target_address_at(instruction_payload, target);
-  }
-
   static const int kSpecialTargetSize = kPointerSize;
 
   // Distance between the address of the code target in the call instruction
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index f06cc5b..715feca 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -82,7 +82,7 @@
   descriptor->register_param_count_ = 3;
   descriptor->register_params_ = registers;
   descriptor->deoptimization_handler_ =
-      Runtime::FunctionForId(Runtime::kCreateArrayLiteral)->entry;
+      Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry;
 }
 
 
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index e067c90..909294e 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -1705,6 +1705,10 @@
   Comment cmnt(masm_, "[ ArrayLiteral");
 
   expr->BuildConstantElements(isolate());
+  int flags = expr->depth() == 1
+      ? ArrayLiteral::kShallowElements
+      : ArrayLiteral::kNoFlags;
+
   ZoneList<Expression*>* subexprs = expr->values();
   int length = subexprs->length();
   Handle<FixedArray> constant_elements = expr->constant_elements();
@@ -1737,7 +1741,8 @@
     __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
     __ push(Immediate(Smi::FromInt(expr->literal_index())));
     __ push(Immediate(constant_elements));
-    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
+    __ push(Immediate(Smi::FromInt(flags)));
+    __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
   } else {
     ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) ||
            FLAG_smi_only_arrays);
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 5343773..921b5aa 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -1653,6 +1653,21 @@
     return result;
   } else if (instr->representation().IsDouble()) {
     return DoArithmeticD(Token::ADD, instr);
+  } else if (instr->representation().IsExternal()) {
+    ASSERT(instr->left()->representation().IsExternal());
+    ASSERT(instr->right()->representation().IsInteger32());
+    ASSERT(!instr->CheckFlag(HValue::kCanOverflow));
+    bool use_lea = LAddI::UseLea(instr);
+    LOperand* left = UseRegisterAtStart(instr->left());
+    HValue* right_candidate = instr->right();
+    LOperand* right = use_lea
+        ? UseRegisterOrConstantAtStart(right_candidate)
+        : UseOrConstantAtStart(right_candidate);
+    LAddI* add = new(zone()) LAddI(left, right);
+    LInstruction* result = use_lea
+        ? DefineAsRegister(add)
+        : DefineSameAsFirst(add);
+    return result;
   } else {
     return DoArithmeticT(Token::ADD, instr);
   }
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index d26210d..1c98c98 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -405,11 +405,11 @@
     Register receiver,
     Register holder,
     Register name,
-    Handle<JSObject> holder_obj) {
+    Handle<JSObject> holder_obj,
+    IC::UtilityId id) {
   PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
   __ CallExternalReference(
-      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
-                        masm->isolate()),
+      ExternalReference(IC_Utility(id), masm->isolate()),
       StubCache::kInterceptorArgsLength);
 }
 
@@ -797,12 +797,9 @@
     // Save the name_ register across the call.
     __ push(name_);
 
-    PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
-
-    __ CallExternalReference(
-        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
-                          masm->isolate()),
-        StubCache::kInterceptorArgsLength);
+    CompileCallLoadPropertyWithInterceptor(
+        masm, receiver, holder, name_, interceptor_holder,
+        IC::kLoadPropertyWithInterceptorForCall);
 
     // Restore the name_ register.
     __ pop(name_);
@@ -820,11 +817,9 @@
       __ push(holder);  // Save the holder.
       __ push(name_);  // Save the name.
 
-      CompileCallLoadPropertyWithInterceptor(masm,
-                                             receiver,
-                                             holder,
-                                             name_,
-                                             holder_obj);
+      CompileCallLoadPropertyWithInterceptor(
+          masm, receiver, holder, name_, holder_obj,
+          IC::kLoadPropertyWithInterceptorOnly);
 
       __ pop(name_);  // Restore the name.
       __ pop(receiver);  // Restore the holder.
@@ -1553,11 +1548,9 @@
       // Invoke an interceptor.  Note: map checks from receiver to
       // interceptor's holder has been compiled before (see a caller
       // of this method.)
-      CompileCallLoadPropertyWithInterceptor(masm(),
-                                             receiver(),
-                                             holder_reg,
-                                             this->name(),
-                                             interceptor_holder);
+      CompileCallLoadPropertyWithInterceptor(
+          masm(), receiver(), holder_reg, this->name(), interceptor_holder,
+          IC::kLoadPropertyWithInterceptorOnly);
 
       // Check if interceptor provided a value for property.  If it's
       // the case, return immediately.
diff --git a/src/math.js b/src/math.js
index fb7d306..5cbe94a 100644
--- a/src/math.js
+++ b/src/math.js
@@ -74,7 +74,7 @@
 
 // ECMA 262 - 15.8.2.6
 function MathCeil(x) {
-  return %Math_ceil(TO_NUMBER_INLINE(x));
+  return -MathFloor(-x);
 }
 
 // ECMA 262 - 15.8.2.7
@@ -348,6 +348,8 @@
     "imul", MathImul
   ));
 
+  %SetInlineBuiltinFlag(MathCeil);
+  %SetInlineBuiltinFlag(MathRandom);
   %SetInlineBuiltinFlag(MathSin);
   %SetInlineBuiltinFlag(MathCos);
   %SetInlineBuiltinFlag(MathTan);
diff --git a/src/mips/assembler-mips.h b/src/mips/assembler-mips.h
index 49cce62..d9ef46c 100644
--- a/src/mips/assembler-mips.h
+++ b/src/mips/assembler-mips.h
@@ -537,13 +537,6 @@
         target);
   }
 
-  // This sets the branch destination.
-  // This is for calls and branches to runtime code.
-  inline static void set_external_target_at(Address instruction_payload,
-                                            Address target) {
-    set_target_address_at(instruction_payload, target);
-  }
-
   // Size of an instruction.
   static const int kInstrSize = sizeof(Instr);
 
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 47afeb4..0c5e35c 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -78,7 +78,7 @@
   descriptor->register_param_count_ = 3;
   descriptor->register_params_ = registers;
   descriptor->deoptimization_handler_ =
-      Runtime::FunctionForId(Runtime::kCreateArrayLiteral)->entry;
+      Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry;
 }
 
 
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 486eb9d..8b16e6c 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -1780,6 +1780,10 @@
   Comment cmnt(masm_, "[ ArrayLiteral");
 
   expr->BuildConstantElements(isolate());
+  int flags = expr->depth() == 1
+      ? ArrayLiteral::kShallowElements
+      : ArrayLiteral::kNoFlags;
+
   ZoneList<Expression*>* subexprs = expr->values();
   int length = subexprs->length();
 
@@ -1808,8 +1812,9 @@
         1, a1, a2);
   } else if (expr->depth() > 1 || Serializer::enabled() ||
              length > FastCloneShallowArrayStub::kMaximumClonedLength) {
-    __ Push(a3, a2, a1);
-    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
+    __ li(a0, Operand(Smi::FromInt(flags)));
+    __ Push(a3, a2, a1, a0);
+    __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
   } else {
     ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) ||
            FLAG_smi_only_arrays);
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index 34e5838..d26da4a 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -1587,6 +1587,15 @@
       result = AssignEnvironment(result);
     }
     return result;
+  } else if (instr->representation().IsExternal()) {
+    ASSERT(instr->left()->representation().IsExternal());
+    ASSERT(instr->right()->representation().IsInteger32());
+    ASSERT(!instr->CheckFlag(HValue::kCanOverflow));
+    LOperand* left = UseRegisterAtStart(instr->left());
+    LOperand* right = UseOrConstantAtStart(instr->right());
+    LAddI* add = new(zone()) LAddI(left, right);
+    LInstruction* result = DefineAsRegister(add);
+    return result;
   } else if (instr->representation().IsDouble()) {
     if (kArchVariant == kMips32r2) {
       if (instr->left()->IsMul())
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index a477250..e743701 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -785,17 +785,12 @@
     Register receiver,
     Register holder,
     Register name,
-    Handle<JSObject> holder_obj) {
+    Handle<JSObject> holder_obj,
+    IC::UtilityId id) {
   PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
-
-  ExternalReference ref =
-      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
-          masm->isolate());
-  __ PrepareCEntryArgs(StubCache::kInterceptorArgsLength);
-  __ PrepareCEntryFunction(ref);
-
-  CEntryStub stub(1);
-  __ CallStub(&stub);
+  __ CallExternalReference(
+      ExternalReference(IC_Utility(id), masm->isolate()),
+      StubCache::kInterceptorArgsLength);
 }
 
 
@@ -1101,13 +1096,10 @@
     // Save the name_ register across the call.
     __ push(name_);
 
-    PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
+    CompileCallLoadPropertyWithInterceptor(
+        masm, receiver, holder, name_, interceptor_holder,
+        IC::kLoadPropertyWithInterceptorForCall);
 
-    __ CallExternalReference(
-          ExternalReference(
-              IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
-              masm->isolate()),
-          StubCache::kInterceptorArgsLength);
     // Restore the name_ register.
     __ pop(name_);
     // Leave the internal frame.
@@ -1123,11 +1115,9 @@
       FrameScope scope(masm, StackFrame::INTERNAL);
 
       __ Push(holder, name_);
-      CompileCallLoadPropertyWithInterceptor(masm,
-                                             receiver,
-                                             holder,
-                                             name_,
-                                             holder_obj);
+      CompileCallLoadPropertyWithInterceptor(
+          masm, receiver, holder, name_, holder_obj,
+          IC::kLoadPropertyWithInterceptorOnly);
       __ pop(name_);  // Restore the name.
       __ pop(receiver);  // Restore the holder.
     }
@@ -1496,11 +1486,10 @@
       // Invoke an interceptor.  Note: map checks from receiver to
       // interceptor's holder has been compiled before (see a caller
       // of this method).
-      CompileCallLoadPropertyWithInterceptor(masm(),
-                                             receiver(),
-                                             holder_reg,
-                                             this->name(),
-                                             interceptor_holder);
+      CompileCallLoadPropertyWithInterceptor(
+          masm(), receiver(), holder_reg, this->name(), interceptor_holder,
+          IC::kLoadPropertyWithInterceptorOnly);
+
       // Check if interceptor provided a value for property.  If it's
       // the case, return immediately.
       Label interceptor_failed;
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 9f1b939..512f532 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -862,8 +862,13 @@
   shared()->name()->Print(out);
   PrintF(out, "\n - context = ");
   context()->ShortPrint(out);
-  PrintF(out, "\n - literals = ");
-  literals()->ShortPrint(out);
+  if (shared()->bound()) {
+    PrintF(out, "\n - bindings = ");
+    function_bindings()->ShortPrint(out);
+  } else {
+    PrintF(out, "\n - literals = ");
+    literals()->ShortPrint(out);
+  }
   PrintF(out, "\n - code = ");
   code()->ShortPrint(out);
   PrintF(out, "\n");
diff --git a/src/objects.cc b/src/objects.cc
index 2283581..6e25e62 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -5656,14 +5656,6 @@
 }
 
 
-Handle<JSObject> JSObject::Copy(Handle<JSObject> object,
-                                Handle<AllocationSite> site) {
-  Isolate* isolate = object->GetIsolate();
-  CALL_HEAP_FUNCTION(isolate,
-                     isolate->heap()->CopyJSObject(*object, *site), JSObject);
-}
-
-
 Handle<JSObject> JSObject::Copy(Handle<JSObject> object) {
   Isolate* isolate = object->GetIsolate();
   CALL_HEAP_FUNCTION(isolate,
@@ -5671,258 +5663,233 @@
 }
 
 
+template<class ContextObject>
 class JSObjectWalkVisitor {
  public:
-  explicit JSObjectWalkVisitor(AllocationSiteContext* site_context) :
-      site_context_(site_context) {}
-  virtual ~JSObjectWalkVisitor() {}
+  JSObjectWalkVisitor(ContextObject* site_context, bool copying,
+                      JSObject::DeepCopyHints hints)
+    : site_context_(site_context),
+      copying_(copying),
+      hints_(hints) {}
 
-  Handle<JSObject> Visit(Handle<JSObject> object) {
-    return StructureWalk(object);
-  }
-
-  virtual bool is_copying() = 0;
-
- protected:
   Handle<JSObject> StructureWalk(Handle<JSObject> object);
 
-  // The returned handle will be used for the object in all subsequent usages.
-  // This allows VisitObject to make a copy of the object if desired.
-  virtual Handle<JSObject> VisitObject(Handle<JSObject> object) = 0;
-  virtual Handle<JSObject> VisitElementOrProperty(Handle<JSObject> object,
-                                                  Handle<JSObject> value) = 0;
-
-  AllocationSiteContext* site_context() { return site_context_; }
-
- private:
-  AllocationSiteContext* site_context_;
-};
-
-
-class JSObjectCopyVisitor: public JSObjectWalkVisitor {
- public:
-  explicit JSObjectCopyVisitor(AllocationSiteContext* site_context)
-      : JSObjectWalkVisitor(site_context) {}
-
-  virtual bool is_copying() V8_OVERRIDE { return true; }
-
-  // The returned handle will be used for the object in all
-  // subsequent usages. This allows VisitObject to make a copy
-  // of the object if desired.
-  virtual Handle<JSObject> VisitObject(Handle<JSObject> object) V8_OVERRIDE {
-    // Only create a memento if
-    // 1) we have a JSArray, and
-    // 2) the elements kind is palatable
-    // 3) allow_mementos is true
-    Handle<JSObject> copy;
-    if (site_context()->activated() &&
-        AllocationSite::CanTrack(object->map()->instance_type()) &&
-        AllocationSite::GetMode(object->GetElementsKind()) ==
-        TRACK_ALLOCATION_SITE) {
-      copy = JSObject::Copy(object, site_context()->current());
-    } else {
-      copy = JSObject::Copy(object);
-    }
-
-    return copy;
-  }
-
-  virtual Handle<JSObject> VisitElementOrProperty(
-      Handle<JSObject> object,
-      Handle<JSObject> value) V8_OVERRIDE {
+ protected:
+  inline Handle<JSObject> VisitElementOrProperty(Handle<JSObject> object,
+                                                 Handle<JSObject> value) {
     Handle<AllocationSite> current_site = site_context()->EnterNewScope();
     Handle<JSObject> copy_of_value = StructureWalk(value);
     site_context()->ExitScope(current_site, value);
     return copy_of_value;
   }
+
+  inline ContextObject* site_context() { return site_context_; }
+  inline Isolate* isolate() { return site_context()->isolate(); }
+
+  inline bool copying() const { return copying_; }
+
+ private:
+  ContextObject* site_context_;
+  const bool copying_;
+  const JSObject::DeepCopyHints hints_;
 };
 
 
-class JSObjectCreateAllocationSitesVisitor: public JSObjectWalkVisitor {
- public:
-  explicit JSObjectCreateAllocationSitesVisitor(
-      AllocationSiteContext* site_context)
-      : JSObjectWalkVisitor(site_context) {}
+template <class ContextObject>
+Handle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
+    Handle<JSObject> object) {
+  Isolate* isolate = this->isolate();
+  bool copying = this->copying();
+  bool shallow = hints_ == JSObject::kObjectIsShallowArray;
 
-  virtual bool is_copying() V8_OVERRIDE { return false; }
+  if (!shallow) {
+    StackLimitCheck check(isolate);
 
-  // The returned handle will be used for the object in all
-  // subsequent usages. This allows VisitObject to make a copy
-  // of the object if desired.
-  virtual Handle<JSObject> VisitObject(Handle<JSObject> object) V8_OVERRIDE {
-    return object;
-  }
-
-  virtual Handle<JSObject> VisitElementOrProperty(
-      Handle<JSObject> object,
-      Handle<JSObject> value) V8_OVERRIDE {
-    Handle<AllocationSite> current_site = site_context()->EnterNewScope();
-    value = StructureWalk(value);
-    site_context()->ExitScope(current_site, value);
-    return value;
-  }
-};
-
-
-Handle<JSObject> JSObjectWalkVisitor::StructureWalk(Handle<JSObject> object) {
-  bool copying = is_copying();
-  Isolate* isolate = object->GetIsolate();
-  StackLimitCheck check(isolate);
-  if (check.HasOverflowed()) {
-    isolate->StackOverflow();
-    return Handle<JSObject>::null();
+    if (check.HasOverflowed()) {
+      isolate->StackOverflow();
+      return Handle<JSObject>::null();
+    }
   }
 
   if (object->map()->is_deprecated()) {
     JSObject::MigrateInstance(object);
   }
 
-  Handle<JSObject> copy = VisitObject(object);
+  Handle<JSObject> copy;
+  if (copying) {
+    Handle<AllocationSite> site_to_pass;
+    if (site_context()->activated() &&
+        AllocationSite::CanTrack(object->map()->instance_type()) &&
+        AllocationSite::GetMode(object->GetElementsKind()) ==
+        TRACK_ALLOCATION_SITE) {
+      site_to_pass = site_context()->current();
+    }
+    CALL_AND_RETRY_OR_DIE(isolate,
+                          isolate->heap()->CopyJSObject(*object,
+                              site_to_pass.is_null() ? NULL : *site_to_pass),
+                          { copy = Handle<JSObject>(JSObject::cast(__object__),
+                                                    isolate);
+                            break;
+                          },
+                          return Handle<JSObject>());
+  } else {
+    copy = object;
+  }
+
   ASSERT(copying || copy.is_identical_to(object));
 
-  HandleScope scope(isolate);
-
-  // Deep copy local properties.
-  if (copy->HasFastProperties()) {
-    Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
-    int limit = copy->map()->NumberOfOwnDescriptors();
-    for (int i = 0; i < limit; i++) {
-      PropertyDetails details = descriptors->GetDetails(i);
-      if (details.type() != FIELD) continue;
-      int index = descriptors->GetFieldIndex(i);
-      Handle<Object> value(object->RawFastPropertyAt(index), isolate);
-      if (value->IsJSObject()) {
-        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);
-      }
-      if (copying) {
-        copy->FastPropertyAtPut(index, *value);
-      }
-    }
-  } else {
-    Handle<FixedArray> names =
-        isolate->factory()->NewFixedArray(copy->NumberOfLocalProperties());
-    copy->GetLocalPropertyNames(*names, 0);
-    for (int i = 0; i < names->length(); i++) {
-      ASSERT(names->get(i)->IsString());
-      Handle<String> key_string(String::cast(names->get(i)));
-      PropertyAttributes attributes =
-          copy->GetLocalPropertyAttribute(*key_string);
-      // Only deep copy fields from the object literal expression.
-      // In particular, don't try to copy the length attribute of
-      // an array.
-      if (attributes != NONE) continue;
-      Handle<Object> value(
-          copy->GetProperty(*key_string, &attributes)->ToObjectUnchecked(),
-          isolate);
-      if (value->IsJSObject()) {
-        Handle<JSObject> result = VisitElementOrProperty(
-            copy, Handle<JSObject>::cast(value));
-        RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
-        if (copying) {
-          // Creating object copy for literals. No strict mode needed.
-          CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetProperty(
-              copy, key_string, result, NONE, kNonStrictMode));
-        }
-      }
-    }
+  ElementsKind kind = copy->GetElementsKind();
+  if (copying && IsFastSmiOrObjectElementsKind(kind) &&
+      FixedArray::cast(copy->elements())->map() ==
+        isolate->heap()->fixed_cow_array_map()) {
+    isolate->counters()->cow_arrays_created_runtime()->Increment();
   }
 
-  // Deep copy local elements.
-  // Pixel elements cannot be created using an object literal.
-  ASSERT(!copy->HasExternalArrayElements());
-  switch (copy->GetElementsKind()) {
-    case FAST_SMI_ELEMENTS:
-    case FAST_ELEMENTS:
-    case FAST_HOLEY_SMI_ELEMENTS:
-    case FAST_HOLEY_ELEMENTS: {
-      Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
-      if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
-        if (copying) {
-          isolate->counters()->cow_arrays_created_runtime()->Increment();
+  if (!shallow) {
+    HandleScope scope(isolate);
+
+    // Deep copy local properties.
+    if (copy->HasFastProperties()) {
+      Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
+      int limit = copy->map()->NumberOfOwnDescriptors();
+      for (int i = 0; i < limit; i++) {
+        PropertyDetails details = descriptors->GetDetails(i);
+        if (details.type() != FIELD) continue;
+        int index = descriptors->GetFieldIndex(i);
+        Handle<Object> value(object->RawFastPropertyAt(index), isolate);
+        if (value->IsJSObject()) {
+          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);
         }
+        if (copying) {
+          copy->FastPropertyAtPut(index, *value);
+        }
+      }
+    } else {
+      Handle<FixedArray> names =
+          isolate->factory()->NewFixedArray(copy->NumberOfLocalProperties());
+      copy->GetLocalPropertyNames(*names, 0);
+      for (int i = 0; i < names->length(); i++) {
+        ASSERT(names->get(i)->IsString());
+        Handle<String> key_string(String::cast(names->get(i)));
+        PropertyAttributes attributes =
+            copy->GetLocalPropertyAttribute(*key_string);
+        // Only deep copy fields from the object literal expression.
+        // In particular, don't try to copy the length attribute of
+        // an array.
+        if (attributes != NONE) continue;
+        Handle<Object> value(
+            copy->GetProperty(*key_string, &attributes)->ToObjectUnchecked(),
+            isolate);
+        if (value->IsJSObject()) {
+          Handle<JSObject> result = VisitElementOrProperty(
+              copy, Handle<JSObject>::cast(value));
+          RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
+          if (copying) {
+            // Creating object copy for literals. No strict mode needed.
+            CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetProperty(
+                copy, key_string, result, NONE, kNonStrictMode));
+          }
+        }
+      }
+    }
+
+    // Deep copy local elements.
+    // Pixel elements cannot be created using an object literal.
+    ASSERT(!copy->HasExternalArrayElements());
+    switch (kind) {
+      case FAST_SMI_ELEMENTS:
+      case FAST_ELEMENTS:
+      case FAST_HOLEY_SMI_ELEMENTS:
+      case FAST_HOLEY_ELEMENTS: {
+        Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
+        if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
 #ifdef DEBUG
-        for (int i = 0; i < elements->length(); i++) {
-          ASSERT(!elements->get(i)->IsJSObject());
-        }
+          for (int i = 0; i < elements->length(); i++) {
+            ASSERT(!elements->get(i)->IsJSObject());
+          }
 #endif
-      } else {
-        for (int i = 0; i < elements->length(); i++) {
-          Handle<Object> value(elements->get(i), isolate);
-          ASSERT(value->IsSmi() ||
-                 value->IsTheHole() ||
-                 (IsFastObjectElementsKind(copy->GetElementsKind())));
-          if (value->IsJSObject()) {
-            Handle<JSObject> result = VisitElementOrProperty(
-                copy, Handle<JSObject>::cast(value));
-            RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
-            if (copying) {
-              elements->set(i, *result);
+        } else {
+          for (int i = 0; i < elements->length(); i++) {
+            Handle<Object> value(elements->get(i), isolate);
+            ASSERT(value->IsSmi() ||
+                   value->IsTheHole() ||
+                   (IsFastObjectElementsKind(copy->GetElementsKind())));
+            if (value->IsJSObject()) {
+              Handle<JSObject> result = VisitElementOrProperty(
+                  copy, Handle<JSObject>::cast(value));
+              RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
+              if (copying) {
+                elements->set(i, *result);
+              }
             }
           }
         }
+        break;
       }
-      break;
-    }
-    case DICTIONARY_ELEMENTS: {
-      Handle<SeededNumberDictionary> element_dictionary(
-          copy->element_dictionary());
-      int capacity = element_dictionary->Capacity();
-      for (int i = 0; i < capacity; i++) {
-        Object* k = element_dictionary->KeyAt(i);
-        if (element_dictionary->IsKey(k)) {
-          Handle<Object> value(element_dictionary->ValueAt(i), isolate);
-          if (value->IsJSObject()) {
-            Handle<JSObject> result = VisitElementOrProperty(
-                copy, Handle<JSObject>::cast(value));
-            RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
-            if (copying) {
-              element_dictionary->ValueAtPut(i, *result);
+      case DICTIONARY_ELEMENTS: {
+        Handle<SeededNumberDictionary> element_dictionary(
+            copy->element_dictionary());
+        int capacity = element_dictionary->Capacity();
+        for (int i = 0; i < capacity; i++) {
+          Object* k = element_dictionary->KeyAt(i);
+          if (element_dictionary->IsKey(k)) {
+            Handle<Object> value(element_dictionary->ValueAt(i), isolate);
+            if (value->IsJSObject()) {
+              Handle<JSObject> result = VisitElementOrProperty(
+                  copy, Handle<JSObject>::cast(value));
+              RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
+              if (copying) {
+                element_dictionary->ValueAtPut(i, *result);
+              }
             }
           }
         }
+        break;
       }
-      break;
+      case NON_STRICT_ARGUMENTS_ELEMENTS:
+        UNIMPLEMENTED();
+        break;
+      case EXTERNAL_PIXEL_ELEMENTS:
+      case EXTERNAL_BYTE_ELEMENTS:
+      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+      case EXTERNAL_SHORT_ELEMENTS:
+      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+      case EXTERNAL_INT_ELEMENTS:
+      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+      case EXTERNAL_FLOAT_ELEMENTS:
+      case EXTERNAL_DOUBLE_ELEMENTS:
+      case FAST_DOUBLE_ELEMENTS:
+      case FAST_HOLEY_DOUBLE_ELEMENTS:
+        // No contained objects, nothing to do.
+        break;
     }
-    case NON_STRICT_ARGUMENTS_ELEMENTS:
-      UNIMPLEMENTED();
-      break;
-    case EXTERNAL_PIXEL_ELEMENTS:
-    case EXTERNAL_BYTE_ELEMENTS:
-    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
-    case EXTERNAL_SHORT_ELEMENTS:
-    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
-    case EXTERNAL_INT_ELEMENTS:
-    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
-    case EXTERNAL_FLOAT_ELEMENTS:
-    case EXTERNAL_DOUBLE_ELEMENTS:
-    case FAST_DOUBLE_ELEMENTS:
-    case FAST_HOLEY_DOUBLE_ELEMENTS:
-      // No contained objects, nothing to do.
-      break;
   }
+
   return copy;
 }
 
 
-Handle<JSObject> JSObject::DeepWalk(Handle<JSObject> object,
-                                    AllocationSiteContext* site_context) {
-  JSObjectCreateAllocationSitesVisitor v(site_context);
-  Handle<JSObject> result = v.Visit(object);
-  ASSERT(!v.is_copying() &&
-         (result.is_null() || result.is_identical_to(object)));
+Handle<JSObject> JSObject::DeepWalk(
+    Handle<JSObject> object,
+    AllocationSiteCreationContext* site_context) {
+  JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
+                                                       kNoHints);
+  Handle<JSObject> result = v.StructureWalk(object);
+  ASSERT(result.is_null() || result.is_identical_to(object));
   return result;
 }
 
 
 Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object,
-                                    AllocationSiteContext* site_context) {
-  JSObjectCopyVisitor v(site_context);
-  Handle<JSObject> copy = v.Visit(object);
-  ASSERT(v.is_copying() && !copy.is_identical_to(object));
+                                    AllocationSiteUsageContext* site_context,
+                                    DeepCopyHints hints) {
+  JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
+  Handle<JSObject> copy = v.StructureWalk(object);
+  ASSERT(!copy.is_identical_to(object));
   return copy;
 }
 
diff --git a/src/objects.h b/src/objects.h
index 93d35bf..2ae1429 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -861,7 +861,8 @@
 
 class AccessorPair;
 class AllocationSite;
-class AllocationSiteContext;
+class AllocationSiteCreationContext;
+class AllocationSiteUsageContext;
 class DictionaryElementsAccessor;
 class ElementsAccessor;
 class Failure;
@@ -2521,13 +2522,17 @@
   static void SetObserved(Handle<JSObject> object);
 
   // Copy object.
-  static Handle<JSObject> Copy(Handle<JSObject> object,
-                               Handle<AllocationSite> site);
+  enum DeepCopyHints {
+    kNoHints = 0,
+    kObjectIsShallowArray = 1
+  };
+
   static Handle<JSObject> Copy(Handle<JSObject> object);
   static Handle<JSObject> DeepCopy(Handle<JSObject> object,
-                                   AllocationSiteContext* site_context);
+                                   AllocationSiteUsageContext* site_context,
+                                   DeepCopyHints hints = kNoHints);
   static Handle<JSObject> DeepWalk(Handle<JSObject> object,
-                                   AllocationSiteContext* site_context);
+                                   AllocationSiteCreationContext* site_context);
 
   // Casting.
   static inline JSObject* cast(Object* obj);
diff --git a/src/property-details.h b/src/property-details.h
index 36f1406..617e9b2 100644
--- a/src/property-details.h
+++ b/src/property-details.h
@@ -131,6 +131,10 @@
   }
 
   bool is_more_general_than(const Representation& other) const {
+    if (kind_ == kExternal && other.kind_ == kNone) return true;
+    if (kind_ == kExternal && other.kind_ == kExternal) return false;
+    if (kind_ == kNone && other.kind_ == kExternal) return false;
+
     ASSERT(kind_ != kExternal);
     ASSERT(other.kind_ != kExternal);
     if (IsHeapObject()) return other.IsDouble() || other.IsNone();
diff --git a/src/runtime.cc b/src/runtime.cc
index 092e91e..fbe4426 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -554,24 +554,52 @@
 }
 
 
+static MaybeObject* CreateArrayLiteralImpl(Isolate* isolate,
+                                           Handle<FixedArray> literals,
+                                           int literals_index,
+                                           Handle<FixedArray> elements,
+                                           int flags) {
+  Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
+      literals_index, elements);
+  RETURN_IF_EMPTY_HANDLE(isolate, site);
+
+  bool enable_mementos = (flags & ArrayLiteral::kDisableMementos) == 0;
+  Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()));
+  AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
+  usage_context.EnterNewScope();
+  JSObject::DeepCopyHints hints = (flags & ArrayLiteral::kShallowElements) == 0
+      ? JSObject::kNoHints
+      : JSObject::kObjectIsShallowArray;
+  Handle<JSObject> copy = JSObject::DeepCopy(boilerplate, &usage_context,
+                                             hints);
+  usage_context.ExitScope(site, boilerplate);
+  RETURN_IF_EMPTY_HANDLE(isolate, copy);
+  return *copy;
+}
+
+
 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
   HandleScope scope(isolate);
+  ASSERT(args.length() == 4);
+  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
+  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
+  CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
+  CONVERT_SMI_ARG_CHECKED(flags, 3);
+
+  return CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
+                                flags);
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralStubBailout) {
+  HandleScope scope(isolate);
   ASSERT(args.length() == 3);
   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
 
-  Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
-      literals_index, elements);
-  RETURN_IF_EMPTY_HANDLE(isolate, site);
-
-  Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()));
-  AllocationSiteUsageContext usage_context(isolate, site, true);
-  usage_context.EnterNewScope();
-  Handle<JSObject> copy = JSObject::DeepCopy(boilerplate, &usage_context);
-  usage_context.ExitScope(site, boilerplate);
-  RETURN_IF_EMPTY_HANDLE(isolate, copy);
-  return *copy;
+  return CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
+                                ArrayLiteral::kShallowElements);
 }
 
 
@@ -835,20 +863,7 @@
 }
 
 
-enum TypedArrayId {
-  // arrayIds below should be synchromized with typedarray.js natives.
-  ARRAY_ID_UINT8 = 1,
-  ARRAY_ID_INT8 = 2,
-  ARRAY_ID_UINT16 = 3,
-  ARRAY_ID_INT16 = 4,
-  ARRAY_ID_UINT32 = 5,
-  ARRAY_ID_INT32 = 6,
-  ARRAY_ID_FLOAT32 = 7,
-  ARRAY_ID_FLOAT64 = 8,
-  ARRAY_ID_UINT8C = 9
-};
-
-static void ArrayIdToTypeAndSize(
+void Runtime::ArrayIdToTypeAndSize(
     int arrayId, ExternalArrayType* array_type, size_t* element_size) {
   switch (arrayId) {
     case ARRAY_ID_UINT8:
@@ -910,7 +925,7 @@
 
   ExternalArrayType array_type = kExternalByteArray;  // Bogus initialization.
   size_t element_size = 1;  // Bogus initialization.
-  ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
+  Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
 
   holder->set_buffer(*buffer);
   holder->set_byte_offset(*byte_offset_object);
@@ -962,7 +977,7 @@
 
   ExternalArrayType array_type = kExternalByteArray;  // Bogus initialization.
   size_t element_size = 1;  // Bogus initialization.
-  ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
+  Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
 
   Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
   size_t length = NumberToSize(isolate, *length_obj);
@@ -7686,16 +7701,6 @@
 }
 
 
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_ceil) {
-  SealHandleScope shs(isolate);
-  ASSERT(args.length() == 1);
-  isolate->counters()->math_ceil()->Increment();
-
-  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
-  return isolate->heap()->NumberFromDouble(ceiling(x));
-}
-
-
 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) {
   SealHandleScope shs(isolate);
   ASSERT(args.length() == 1);
diff --git a/src/runtime.h b/src/runtime.h
index 43d4065..62c52a7 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -179,7 +179,6 @@
   F(Math_asin, 1, 1) \
   F(Math_atan, 1, 1) \
   F(Math_atan2, 2, 1) \
-  F(Math_ceil, 1, 1) \
   F(Math_cos, 1, 1) \
   F(Math_exp, 1, 1) \
   F(Math_floor, 1, 1) \
@@ -300,7 +299,8 @@
   /* Literals */ \
   F(MaterializeRegExpLiteral, 4, 1)\
   F(CreateObjectLiteral, 4, 1) \
-  F(CreateArrayLiteral, 3, 1) \
+  F(CreateArrayLiteral, 4, 1) \
+  F(CreateArrayLiteralStubBailout, 3, 1) \
   \
   /* Harmony generators */ \
   F(CreateJSGeneratorObject, 0, 1) \
@@ -829,6 +829,22 @@
       Isolate* isolate,
       JSArrayBuffer* phantom_array_buffer);
 
+  enum TypedArrayId {
+    // arrayIds below should be synchromized with typedarray.js natives.
+    ARRAY_ID_UINT8 = 1,
+    ARRAY_ID_INT8 = 2,
+    ARRAY_ID_UINT16 = 3,
+    ARRAY_ID_INT16 = 4,
+    ARRAY_ID_UINT32 = 5,
+    ARRAY_ID_INT32 = 6,
+    ARRAY_ID_FLOAT32 = 7,
+    ARRAY_ID_FLOAT64 = 8,
+    ARRAY_ID_UINT8C = 9
+  };
+
+  static void ArrayIdToTypeAndSize(int array_id,
+      ExternalArrayType *type, size_t *element_size);
+
   // Helper functions used stubs.
   static void PerformGC(Object* result, Isolate* isolate);
 
diff --git a/src/typedarray.js b/src/typedarray.js
index fc3a608..ed9de23 100644
--- a/src/typedarray.js
+++ b/src/typedarray.js
@@ -78,7 +78,8 @@
       var newLength = ToPositiveInteger(length, "invalid_typed_array_length");
       newByteLength = newLength * ELEMENT_SIZE;
     }
-    if (offset + newByteLength > bufferByteLength) {
+    if ((offset + newByteLength > bufferByteLength)
+        || (newLength > %MaxSmi())) {
       throw MakeRangeError("invalid_typed_array_length");
     }
     %TypedArrayInitialize(obj, ARRAY_ID, buffer, offset, newByteLength);
diff --git a/src/v8-counters.h b/src/v8-counters.h
index 54e8100..9178046 100644
--- a/src/v8-counters.h
+++ b/src/v8-counters.h
@@ -242,7 +242,6 @@
   SC(math_asin, V8.MathAsin)                                          \
   SC(math_atan, V8.MathAtan)                                          \
   SC(math_atan2, V8.MathAtan2)                                        \
-  SC(math_ceil, V8.MathCeil)                                          \
   SC(math_cos, V8.MathCos)                                            \
   SC(math_exp, V8.MathExp)                                            \
   SC(math_floor, V8.MathFloor)                                        \
diff --git a/src/version.cc b/src/version.cc
index ce766ce..e03ed8d 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     23
-#define BUILD_NUMBER      11
+#define BUILD_NUMBER      12
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index ac69a24..709b61b 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -586,13 +586,6 @@
     set_target_address_at(instruction_payload, target);
   }
 
-  // This sets the branch destination (which is a load instruction on x64).
-  // This is for calls and branches to runtime code.
-  inline static void set_external_target_at(Address instruction_payload,
-                                            Address target) {
-    *reinterpret_cast<Address*>(instruction_payload) = target;
-  }
-
   inline Handle<Object> code_target_object_handle_at(Address pc);
   inline Address runtime_entry_at(Address pc);
   // Number of bytes taken up by the branch target in the code.
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 8712e27..4fb3a70 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -78,7 +78,7 @@
   descriptor->register_param_count_ = 3;
   descriptor->register_params_ = registers;
   descriptor->deoptimization_handler_ =
-      Runtime::FunctionForId(Runtime::kCreateArrayLiteral)->entry;
+      Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry;
 }
 
 
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index a62fde0..ed4c3ad 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -1726,6 +1726,10 @@
   Comment cmnt(masm_, "[ ArrayLiteral");
 
   expr->BuildConstantElements(isolate());
+  int flags = expr->depth() == 1
+      ? ArrayLiteral::kShallowElements
+      : ArrayLiteral::kNoFlags;
+
   ZoneList<Expression*>* subexprs = expr->values();
   int length = subexprs->length();
   Handle<FixedArray> constant_elements = expr->constant_elements();
@@ -1758,7 +1762,8 @@
     __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
     __ Push(Smi::FromInt(expr->literal_index()));
     __ Push(constant_elements);
-    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
+    __ Push(Smi::FromInt(flags));
+    __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
   } else {
     ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) ||
            FLAG_smi_only_arrays);
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index cf0632e..e56bb54 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -1781,14 +1781,22 @@
   LOperand* left = instr->left();
   LOperand* right = instr->right();
 
+  Representation target_rep = instr->hydrogen()->representation();
+  bool is_q = target_rep.IsSmi() || target_rep.IsExternal();
+
   if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) {
     if (right->IsConstantOperand()) {
       int32_t offset = ToInteger32(LConstantOperand::cast(right));
-      __ leal(ToRegister(instr->result()),
-              MemOperand(ToRegister(left), offset));
+      if (is_q) {
+        __ lea(ToRegister(instr->result()),
+               MemOperand(ToRegister(left), offset));
+      } else {
+        __ leal(ToRegister(instr->result()),
+                MemOperand(ToRegister(left), offset));
+      }
     } else {
       Operand address(ToRegister(left), ToRegister(right), times_1, 0);
-      if (instr->hydrogen()->representation().IsSmi()) {
+      if (is_q) {
         __ lea(ToRegister(instr->result()), address);
       } else {
         __ leal(ToRegister(instr->result()), address);
@@ -1796,16 +1804,21 @@
     }
   } else {
     if (right->IsConstantOperand()) {
-      __ addl(ToRegister(left),
-              Immediate(ToInteger32(LConstantOperand::cast(right))));
+      if (is_q) {
+        __ addq(ToRegister(left),
+                Immediate(ToInteger32(LConstantOperand::cast(right))));
+      } else {
+        __ addl(ToRegister(left),
+                Immediate(ToInteger32(LConstantOperand::cast(right))));
+      }
     } else if (right->IsRegister()) {
-      if (instr->hydrogen_value()->representation().IsSmi()) {
+      if (is_q) {
         __ addq(ToRegister(left), ToRegister(right));
       } else {
         __ addl(ToRegister(left), ToRegister(right));
       }
     } else {
-      if (instr->hydrogen_value()->representation().IsSmi()) {
+      if (is_q) {
         __ addq(ToRegister(left), ToOperand(right));
       } else {
         __ addl(ToRegister(left), ToOperand(right));
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index fa1bdaa..78bc5bb 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -1557,6 +1557,21 @@
       result = AssignEnvironment(result);
     }
     return result;
+  } else if (instr->representation().IsExternal()) {
+    ASSERT(instr->left()->representation().IsExternal());
+    ASSERT(instr->right()->representation().IsInteger32());
+    ASSERT(!instr->CheckFlag(HValue::kCanOverflow));
+    bool use_lea = LAddI::UseLea(instr);
+    LOperand* left = UseRegisterAtStart(instr->left());
+    HValue* right_candidate = instr->right();
+    LOperand* right = use_lea
+        ? UseRegisterOrConstantAtStart(right_candidate)
+        : UseOrConstantAtStart(right_candidate);
+    LAddI* add = new(zone()) LAddI(left, right);
+    LInstruction* result = use_lea
+        ? DefineAsRegister(add)
+        : DefineSameAsFirst(add);
+    return result;
   } else if (instr->representation().IsDouble()) {
     return DoArithmeticD(Token::ADD, instr);
   } else {
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 57c6a35..e64698c 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -379,17 +379,12 @@
     Register receiver,
     Register holder,
     Register name,
-    Handle<JSObject> holder_obj) {
+    Handle<JSObject> holder_obj,
+    IC::UtilityId id) {
   PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
-
-  ExternalReference ref =
-      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
-                        masm->isolate());
-  __ Set(rax, StubCache::kInterceptorArgsLength);
-  __ LoadAddress(rbx, ref);
-
-  CEntryStub stub(1);
-  __ CallStub(&stub);
+  __ CallExternalReference(
+      ExternalReference(IC_Utility(id), masm->isolate()),
+      StubCache::kInterceptorArgsLength);
 }
 
 
@@ -794,12 +789,9 @@
     // Save the name_ register across the call.
     __ push(name_);
 
-    PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
-
-    __ CallExternalReference(
-        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
-                          masm->isolate()),
-        StubCache::kInterceptorArgsLength);
+    CompileCallLoadPropertyWithInterceptor(
+        masm, receiver, holder, name_, interceptor_holder,
+        IC::kLoadPropertyWithInterceptorForCall);
 
     // Restore the name_ register.
     __ pop(name_);
@@ -817,11 +809,9 @@
       __ push(holder);  // Save the holder.
       __ push(name_);  // Save the name.
 
-      CompileCallLoadPropertyWithInterceptor(masm,
-                                             receiver,
-                                             holder,
-                                             name_,
-                                             holder_obj);
+      CompileCallLoadPropertyWithInterceptor(
+          masm, receiver, holder, name_, holder_obj,
+          IC::kLoadPropertyWithInterceptorOnly);
 
       __ pop(name_);  // Restore the name.
       __ pop(receiver);  // Restore the holder.
@@ -1501,11 +1491,9 @@
       // Invoke an interceptor.  Note: map checks from receiver to
       // interceptor's holder has been compiled before (see a caller
       // of this method.)
-      CompileCallLoadPropertyWithInterceptor(masm(),
-                                             receiver(),
-                                             holder_reg,
-                                             this->name(),
-                                             interceptor_holder);
+      CompileCallLoadPropertyWithInterceptor(
+          masm(), receiver(), holder_reg, this->name(), interceptor_holder,
+          IC::kLoadPropertyWithInterceptorOnly);
 
       // Check if interceptor provided a value for property.  If it's
       // the case, return immediately.
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 0db63c1..23756db 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -1631,7 +1631,7 @@
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
-  Local<Value> primitive_false = Boolean::New(false);
+  Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
   CHECK(primitive_false->IsBoolean());
   CHECK(!primitive_false->IsBooleanObject());
   CHECK(!primitive_false->BooleanValue());
@@ -1654,7 +1654,7 @@
   CHECK(!false_boolean_object->IsTrue());
   CHECK(!false_boolean_object->IsFalse());
 
-  Local<Value> primitive_true = Boolean::New(true);
+  Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
   CHECK(primitive_true->IsBoolean());
   CHECK(!primitive_true->IsBooleanObject());
   CHECK(primitive_true->BooleanValue());
@@ -2625,7 +2625,7 @@
   CheckEmbedderData(&env, 2, v8::String::NewFromUtf8(env->GetIsolate(),
                                                      "over the lazy dog."));
   CheckEmbedderData(&env, 1, v8::Number::New(1.2345));
-  CheckEmbedderData(&env, 0, v8::Boolean::New(true));
+  CheckEmbedderData(&env, 0, v8::Boolean::New(env->GetIsolate(), true));
 }
 
 
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index eb9789a..00e4020 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -7514,9 +7514,9 @@
   for (int i = 0; loop_bodies[i] != NULL; i++) {
     // Perform a lazy deoptimization after various numbers of breaks
     // have been hit.
-    for (int j = 0; j < 11; j++) {
+    for (int j = 0; j < 7; j++) {
       break_point_hit_count_deoptimize = j;
-      if (j == 10) {
+      if (j == 6) {
         break_point_hit_count_deoptimize = kBreaksPerTest;
       }
 
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index 86ed230..458493b 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -1936,8 +1936,8 @@
   CHECK_EQ(v8::internal::Context::MIN_CONTEXT_SLOTS + num_objects - 1,
            context_object->GetChildrenCount());
   // Check all the objects have got their names.
-  // ... well check just every 8th because otherwise it's too slow in debug.
-  for (int i = 0; i < num_objects - 1; i += 8) {
+  // ... well check just every 15th because otherwise it's too slow in debug.
+  for (int i = 0; i < num_objects - 1; i += 15) {
     i::EmbeddedVector<char, 100> var_name;
     i::OS::SNPrintF(var_name, "f_%d", i);
     const v8::HeapGraphNode* f_object = GetProperty(
diff --git a/test/cctest/test-representation.cc b/test/cctest/test-representation.cc
index 15321f3..95a65cb 100644
--- a/test/cctest/test-representation.cc
+++ b/test/cctest/test-representation.cc
@@ -121,4 +121,8 @@
   TestPairNegative(Representation::HeapObject(), Representation::Integer32());
   TestPairPositive(Representation::Double(), Representation::Integer32());
   TestPairPositive(Representation::Tagged(), Representation::Integer32());
+
+  TestPairNegative(Representation::None(), Representation::External());
+  TestPairNegative(Representation::External(), Representation::External());
+  TestPairPositive(Representation::External(), Representation::None());
 }
diff --git a/test/mjsunit/array-literal-feedback.js b/test/mjsunit/array-literal-feedback.js
index 93ed3bc..3e95eab 100644
--- a/test/mjsunit/array-literal-feedback.js
+++ b/test/mjsunit/array-literal-feedback.js
@@ -93,11 +93,15 @@
   }
 
   get_literal(3);
-  get_literal(3);
-  %OptimizeFunctionOnNextCall(get_literal);
+  // It's important to store a from before we crankshaft get_literal, because
+  // mementos won't be created from crankshafted code at all.
   a = get_literal(3);
+  %OptimizeFunctionOnNextCall(get_literal);
+  get_literal(3);
   assertOptimized(get_literal);
   assertTrue(%HasFastSmiElements(a));
+  // a has a memento so the transition caused by the store will affect the
+  // boilerplate.
   a[0] = 3.5;
 
   // We should have transitioned the boilerplate array to double, and
diff --git a/test/mjsunit/compiler/math-floor-global.js b/test/mjsunit/compiler/math-floor-global.js
index 9ec183f..3b9d125 100644
--- a/test/mjsunit/compiler/math-floor-global.js
+++ b/test/mjsunit/compiler/math-floor-global.js
@@ -25,7 +25,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Flags: --max-new-space-size=256 --allow-natives-syntax
+// Flags: --max-new-space-size=128 --allow-natives-syntax
 
 // Test inlining of Math.floor when assigned to a global.
 var flo = Math.floor;
@@ -140,8 +140,9 @@
 
 
 // Test in a loop to cover the custom IC and GC-related issues.
-for (var i = 0; i < 50; i++) {
+for (var i = 0; i < 10; i++) {
   test();
+  new Array(i * 10000);
 }
 
 
@@ -158,4 +159,4 @@
 %OptimizeFunctionOnNextCall(floorsum);
 // The optimized function will deopt.  Run it with enough iterations to try
 // to optimize via OSR (triggering the bug).
-assertEquals(-0, floorsum(100000, -0));
+assertEquals(-0, floorsum(50000, -0));
diff --git a/test/mjsunit/compiler/math-floor-local.js b/test/mjsunit/compiler/math-floor-local.js
index e44b15c..fef3347 100644
--- a/test/mjsunit/compiler/math-floor-local.js
+++ b/test/mjsunit/compiler/math-floor-local.js
@@ -25,7 +25,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Flags: --max-new-space-size=256 --allow-natives-syntax
+// Flags: --max-new-space-size=128 --allow-natives-syntax
 
 // Test inlining of Math.floor when assigned to a local.
 var test_id = 0;
@@ -140,8 +140,9 @@
 
 
 // Test in a loop to cover the custom IC and GC-related issues.
-for (var i = 0; i < 50; i++) {
+for (var i = 0; i < 10; i++) {
   test();
+  new Array(i * 10000);
 }
 
 
diff --git a/test/mjsunit/compiler/osr-with-args.js b/test/mjsunit/compiler/osr-with-args.js
index 44fa1cb..4817ad7 100644
--- a/test/mjsunit/compiler/osr-with-args.js
+++ b/test/mjsunit/compiler/osr-with-args.js
@@ -29,7 +29,7 @@
 
 function f() {
   var sum = 0;
-  for (var i = 0; i < 1000000; i++) {
+  for (var i = 0; i < 100000; i++) {
     var t = arguments[0] + 2;
     var x = arguments[1] + 2;
     var y = t + x + 5;
@@ -39,6 +39,6 @@
   return sum;
 }
 
-for (var i = 0; i < 4; i++) {
-  assertEquals(17000000, f(2, 3));
+for (var i = 0; i < 3; i++) {
+  assertEquals(1700000, f(2, 3));
 }
diff --git a/test/mjsunit/compiler/regress-4.js b/test/mjsunit/compiler/regress-4.js
index 0ec9a12..9a212ba 100644
--- a/test/mjsunit/compiler/regress-4.js
+++ b/test/mjsunit/compiler/regress-4.js
@@ -34,7 +34,7 @@
   return y+x;
 }
 
-for (var i=0; i<10000000; i++) f(42);
+for (var i=0; i<100000; i++) f(42);
 
 var result = f("foo");
 assertEquals("0foo6", result);
diff --git a/test/mjsunit/debug-step-4-in-frame.js b/test/mjsunit/debug-step-4-in-frame.js
index 65ac490..9388430 100644
--- a/test/mjsunit/debug-step-4-in-frame.js
+++ b/test/mjsunit/debug-step-4-in-frame.js
@@ -37,18 +37,18 @@
 
 function f() {
   var a = 1978;
-  for (state[2] = 0; state[2] < 5; state[2]++) {
+  for (state[2] = 0; state[2] < 3; state[2]++) {
     void String(a);
   }
 }
 function g() {
-  for (state[1] = 0; state[1] < 5; state[1]++) {
+  for (state[1] = 0; state[1] < 3; state[1]++) {
     f();
   }
 }
 function h() {
   state = [-1, -1, -1];
-  for (state[0] = 0; state[0] < 5; state[0]++) {
+  for (state[0] = 0; state[0] < 3; state[0]++) {
     g();
   }
 }
@@ -123,10 +123,10 @@
 TestCase(0, 8, "0,0,3");
 
 // Stepping in the frame #1.
-TestCase(1, 0, "0,0,5");
-TestCase(1, 3, "0,1,5");
-TestCase(1, 8, "0,4,5");
+TestCase(1, 0, "0,0,3");
+TestCase(1, 3, "0,1,3");
+TestCase(1, 7, "0,3,3");
 
 // Stepping in the frame #2.
-TestCase(2, 3, "1,5,5");
-TestCase(2, 8, "4,5,5");
+TestCase(2, 3, "1,3,3");
+TestCase(2, 7, "3,3,3");
diff --git a/test/mjsunit/fuzz-natives-part1.js b/test/mjsunit/fuzz-natives-part1.js
index c30069e..88d505a 100644
--- a/test/mjsunit/fuzz-natives-part1.js
+++ b/test/mjsunit/fuzz-natives-part1.js
@@ -204,6 +204,9 @@
   "_OneByteSeqStringSetChar": true,
   "_TwoByteSeqStringSetChar": true,
 
+  // Only applicable to TypedArrays.
+  "TypedArrayInitialize": true,
+
   // Only applicable to generators.
   "_GeneratorNext": true,
   "_GeneratorThrow": true,
diff --git a/test/mjsunit/fuzz-natives-part2.js b/test/mjsunit/fuzz-natives-part2.js
index e73f3bd..e86a05d 100644
--- a/test/mjsunit/fuzz-natives-part2.js
+++ b/test/mjsunit/fuzz-natives-part2.js
@@ -205,6 +205,9 @@
   "_OneByteSeqStringSetChar": true,
   "_TwoByteSeqStringSetChar": true,
 
+  // Only applicable to TypedArrays.
+  "TypedArrayInitialize": true,
+
   // Only applicable to generators.
   "_GeneratorNext": true,
   "_GeneratorThrow": true,
diff --git a/test/mjsunit/fuzz-natives-part3.js b/test/mjsunit/fuzz-natives-part3.js
index 6a73498..0d5ec6f 100644
--- a/test/mjsunit/fuzz-natives-part3.js
+++ b/test/mjsunit/fuzz-natives-part3.js
@@ -204,6 +204,9 @@
   "_OneByteSeqStringSetChar": true,
   "_TwoByteSeqStringSetChar": true,
 
+  // Only applicable to TypedArrays.
+  "TypedArrayInitialize": true,
+
   // Only applicable to generators.
   "_GeneratorNext": true,
   "_GeneratorThrow": true,
diff --git a/test/mjsunit/fuzz-natives-part4.js b/test/mjsunit/fuzz-natives-part4.js
index edeaa87..a17a840 100644
--- a/test/mjsunit/fuzz-natives-part4.js
+++ b/test/mjsunit/fuzz-natives-part4.js
@@ -204,6 +204,9 @@
   "_OneByteSeqStringSetChar": true,
   "_TwoByteSeqStringSetChar": true,
 
+  // Only applicable to TypedArrays.
+  "TypedArrayInitialize": true,
+
   // Only applicable to generators.
   "_GeneratorNext": true,
   "_GeneratorThrow": true,
diff --git a/test/mjsunit/harmony/private.js b/test/mjsunit/harmony/private.js
index 884e31b..09cf7f7 100644
--- a/test/mjsunit/harmony/private.js
+++ b/test/mjsunit/harmony/private.js
@@ -317,7 +317,7 @@
   var a = {};
   a[key] = "abc";
 
-  for (var i = 0; i < 1000000; i++) {
+  for (var i = 0; i < 100000; i++) {
     a[key] += "a";  // Allocations cause a scavenge.
   }
 }
diff --git a/test/mjsunit/harmony/symbols.js b/test/mjsunit/harmony/symbols.js
index 1fc3945..3fcd06d 100644
--- a/test/mjsunit/harmony/symbols.js
+++ b/test/mjsunit/harmony/symbols.js
@@ -345,7 +345,7 @@
   var a = {};
   a[key] = "abc";
 
-  for (var i = 0; i < 1000000; i++) {
+  for (var i = 0; i < 100000; i++) {
     a[key] += "a";  // Allocations cause a scavenge.
   }
 }
diff --git a/test/mjsunit/json2.js b/test/mjsunit/json2.js
index cf20b90..0894d77 100644
--- a/test/mjsunit/json2.js
+++ b/test/mjsunit/json2.js
@@ -40,12 +40,13 @@
 
 var array_1 = [];
 var array_2 = [];
-array_1[100000] = 1;
-array_2[100000] = function() { return 1; };
-var nulls = "";
-for (var i = 0; i < 100000; i++) {
-  nulls += 'null,';
+array_1[1<<17] = 1;
+array_2[1<<17] = function() { return 1; };
+var nulls = "null,";
+for (var i = 0; i < 17; i++) {
+  nulls += nulls;
 }
+
 expected_1 = '[' + nulls + '1]';
 expected_2 = '[' + nulls + 'null]';
 TestStringify(expected_1, array_1);
diff --git a/test/mjsunit/limit-locals.js b/test/mjsunit/limit-locals.js
index a166f30..1d36c80 100644
--- a/test/mjsunit/limit-locals.js
+++ b/test/mjsunit/limit-locals.js
@@ -34,9 +34,9 @@
   test_suffix = " suffix";
   var src = "test_prefix + (function () {"
   for (var i = 1; i <= n; i++) {
-    src += "var x" + i + ";";
+    src += "; var x" + i;
   }
-  src += "return " + n + ";})() + test_suffix";
+  src += "; return " + n + ";})() + test_suffix";
   return eval(src);
 }
 
diff --git a/test/mjsunit/math-floor-part1.js b/test/mjsunit/math-floor-part1.js
index 313f272..dd4deb0 100644
--- a/test/mjsunit/math-floor-part1.js
+++ b/test/mjsunit/math-floor-part1.js
@@ -25,7 +25,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Flags: --max-new-space-size=256 --allow-natives-syntax
+// Flags: --max-new-space-size=128 --allow-natives-syntax
 
 var test_id = 0;
 
@@ -83,6 +83,7 @@
 
 
 // Test in a loop to cover the custom IC and GC-related issues.
-for (var i = 0; i < 100; i++) {
+for (var i = 0; i < 10; i++) {
   test();
+  new Array(i * 10000);
 }
diff --git a/test/mjsunit/regress/regress-2318.js b/test/mjsunit/regress/regress-2318.js
index ca67ab2..5fa8a4f 100644
--- a/test/mjsunit/regress/regress-2318.js
+++ b/test/mjsunit/regress/regress-2318.js
@@ -25,7 +25,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Flags: --expose-debug-as debug --nostack-trace-on-abort
+// Flags: --expose-debug-as debug --nostack-trace-on-abort --stack-size=100
 
 function f() {
   var i = 0;
diff --git a/test/mjsunit/regress/regress-2790.js b/test/mjsunit/regress/regress-2790.js
index 86305b8..927f260 100644
--- a/test/mjsunit/regress/regress-2790.js
+++ b/test/mjsunit/regress/regress-2790.js
@@ -26,6 +26,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Test that we can create arrays of any size.
-for (var i = 1000; i < 1000000; i += 97) {
+for (var i = 1000; i < 1000000; i += 197) {
   new Array(i);
 }
diff --git a/test/mjsunit/regress/regress-json-stringify-gc.js b/test/mjsunit/regress/regress-json-stringify-gc.js
index 4b355ae..905ab40 100644
--- a/test/mjsunit/regress/regress-json-stringify-gc.js
+++ b/test/mjsunit/regress/regress-json-stringify-gc.js
@@ -26,9 +26,9 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 var a = [];
-var new_space_string = "";
-for (var i = 0; i < 128; i++) {
-  new_space_string += String.fromCharCode((Math.random() * 26 + 65) | 0);
+var new_space_string = "a";
+for (var i = 0; i < 8; i++) {
+  new_space_string += new_space_string;
 }
 for (var i = 0; i < 10000; i++) a.push(new_space_string);
 
@@ -40,12 +40,12 @@
 assertTrue(json1 == json2, "GC caused JSON.stringify to fail.");
 
 // Check that the slow path of JSON.stringify works correctly wrt GC.
-for (var i = 0; i < 100000; i++) {
+for (var i = 0; i < 10000; i++) {
   var s = i.toString();
   assertEquals('"' + s + '"', JSON.stringify(s, null, 0));
 }
 
-for (var i = 0; i < 100000; i++) {
+for (var i = 0; i < 10000; i++) {
   var s = i.toString() + "\u2603";
   assertEquals('"' + s + '"', JSON.stringify(s, null, 0));
 }
diff --git a/test/mozilla/mozilla.status b/test/mozilla/mozilla.status
index d5e851c..fdea0a9 100644
--- a/test/mozilla/mozilla.status
+++ b/test/mozilla/mozilla.status
@@ -81,23 +81,23 @@
 
   # This takes a long time to run (~100 seconds). It should only be run
   # by the really patient.
-  'js1_5/GC/regress-324278': [SLOW],
+  'js1_5/GC/regress-324278': [SKIP],
 
   # This takes a long time to run because our indexOf operation is
   # pretty slow - it causes a lot of GCs; see issue
   # #926379. We could consider marking this SKIP because it takes a
   # while to run to completion.
-  'js1_5/GC/regress-338653': [SLOW],
+  'js1_5/GC/regress-338653': [SKIP],
 
   # This test is designed to run until it runs out of memory. This takes
   # a very long time because it builds strings character by character
   # and compiles a lot of regular expressions. We could consider marking
   # this SKIP because it takes a while to run to completion.
-  'js1_5/GC/regress-346794': [SLOW],
+  'js1_5/GC/regress-346794': [SKIP],
 
   # Runs out of memory while trying to build huge string of 'x'
   # characters. This takes a long time to run (~32 seconds).
-  'js1_5/GC/regress-348532': [SLOW],
+  'js1_5/GC/regress-348532': [SKIP],
 
 
   ##################### FLAKY TESTS #####################
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 65d5fb8..37fd407 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -113,10 +113,15 @@
           'dependencies': [
             'mksnapshot.<(v8_target_arch)#host',
             'js2c#host',
+            'generate_trig_table#host',
           ],
         }, {
           'toolsets': ['target'],
-          'dependencies': ['mksnapshot.<(v8_target_arch)', 'js2c'],
+          'dependencies': [
+            'mksnapshot.<(v8_target_arch)',
+            'js2c',
+            'generate_trig_table',
+          ],
         }],
         ['component=="shared_library"', {
           'defines': [
@@ -189,10 +194,10 @@
       'conditions': [
         ['want_separate_host_toolset==1', {
           'toolsets': ['host', 'target'],
-          'dependencies': ['js2c#host'],
+          'dependencies': ['js2c#host', 'generate_trig_table#host'],
         }, {
           'toolsets': ['target'],
-          'dependencies': ['js2c'],
+          'dependencies': ['js2c', 'generate_trig_table'],
         }],
         ['component=="shared_library"', {
           'defines': [
@@ -206,7 +211,7 @@
       'type': 'none',
       'conditions': [
         ['want_separate_host_toolset==1', {
-          'toolsets': ['host', 'target'],
+          'toolsets': ['host'],
         }, {
           'toolsets': ['target'],
         }],
@@ -231,9 +236,6 @@
     {
       'target_name': 'v8_base.<(v8_target_arch)',
       'type': 'static_library',
-      'dependencies': [
-        'generate_trig_table',
-      ],
       'variables': {
         'optimize': 'max',
       },
diff --git a/tools/merge-to-branch.sh b/tools/merge-to-branch.sh
index 260dc8a..0314cb4 100755
--- a/tools/merge-to-branch.sh
+++ b/tools/merge-to-branch.sh
@@ -69,8 +69,9 @@
 }
 
 ########## Option parsing
+REVERT_FROM_BLEEDING_EDGE=0
 
-while getopts ":hs:fp:rm:" OPTION ; do
+while getopts ":hs:fp:rm:R" OPTION ; do
   case $OPTION in
     h)  usage
         exit 0
@@ -85,6 +86,9 @@
         ;;
     s)  START_STEP=$OPTARG
         ;;
+    R)  REVERSE_PATCH="--reverse"
+        REVERT_FROM_BLEEDING_EDGE=1
+        ;;
     ?)  echo "Illegal option: -$OPTARG"
         usage
         exit 1
@@ -104,7 +108,8 @@
 initial_environment_checks
 
 if [ $START_STEP -le $CURRENT_STEP ] ; then
-  if [ ${#@} -lt 2 ] ; then
+  let MIN_EXPECTED_ARGS=2-$REVERT_FROM_BLEEDING_EDGE
+  if [ ${#@} -lt $MIN_EXPECTED_ARGS ] ; then
     if [ -z "$EXTRA_PATCH" ] ; then
       die "Either a patch file or revision numbers must be specified"
     fi
@@ -113,9 +118,13 @@
     fi
   fi
   echo ">>> Step $CURRENT_STEP: Preparation"
-  MERGE_TO_BRANCH=$1
-  [[ -n "$MERGE_TO_BRANCH" ]] || die "Please specify a branch to merge to"
-  shift
+  if [ $REVERT_FROM_BLEEDING_EDGE==1 ] ; then
+    MERGE_TO_BRANCH="bleeding_edge"
+  else
+    MERGE_TO_BRANCH=$1
+    [[ -n "$MERGE_TO_BRANCH" ]] || die "Please specify a branch to merge to"
+    shift
+  fi
   persist "MERGE_TO_BRANCH"
   common_prepare
 fi
@@ -144,7 +153,11 @@
   done
   if [ -n "$REVISION_LIST" ] ; then
     if [ -n "$REVERSE_PATCH" ] ; then
-      NEW_COMMIT_MSG="Rollback of$REVISION_LIST in $MERGE_TO_BRANCH branch."
+      if [ $REVERT_FROM_BLEEDING_EDGE -eq 0 ] ; then
+        NEW_COMMIT_MSG="Rollback of$REVISION_LIST in $MERGE_TO_BRANCH branch."
+      else
+        NEW_COMMIT_MSG="Revert$REVISION_LIST."
+      fi
     else
       NEW_COMMIT_MSG="Merged$REVISION_LIST into $MERGE_TO_BRANCH branch."
     fi;
@@ -189,14 +202,14 @@
 fi
 
 let CURRENT_STEP+=1
-if [ $START_STEP -le $CURRENT_STEP ] ; then
+if [ $START_STEP -le $CURRENT_STEP ] && [ $REVERT_FROM_BLEEDING_EDGE -eq 0 ] ; then
   echo ">>> Step $CURRENT_STEP: Prepare $VERSION_FILE."
   # These version numbers are used again for creating the tag
   read_and_persist_version
 fi
 
 let CURRENT_STEP+=1
-if [ $START_STEP -le $CURRENT_STEP ] ; then
+if [ $START_STEP -le $CURRENT_STEP ] && [ $REVERT_FROM_BLEEDING_EDGE -eq 0 ] ; then
   echo ">>> Step $CURRENT_STEP: Increment version number."
   restore_if_unset "PATCH"
   NEWPATCH=$(($PATCH + 1))
@@ -234,7 +247,7 @@
 fi
 
 let CURRENT_STEP+=1
-if [ $START_STEP -le $CURRENT_STEP ] ; then
+if [ $START_STEP -le $CURRENT_STEP ] && [ $REVERT_FROM_BLEEDING_EDGE -eq 0 ] ; then
   echo ">>> Step $CURRENT_STEP: Determine svn commit revision"
   restore_if_unset "NEW_COMMIT_MSG"
   restore_if_unset "MERGE_TO_BRANCH"
@@ -248,7 +261,7 @@
 fi
 
 let CURRENT_STEP+=1
-if [ $START_STEP -le $CURRENT_STEP ] ; then
+if [ $START_STEP -le $CURRENT_STEP ] && [ $REVERT_FROM_BLEEDING_EDGE -eq 0 ] ; then
   echo ">>> Step $CURRENT_STEP: Create the tag."
   restore_if_unset "SVN_REVISION"
   restore_version_if_unset "NEW"
@@ -273,9 +286,11 @@
   restore_if_unset "REVISION_LIST"
   restore_version_if_unset "NEW"
   common_cleanup
-  echo "*** SUMMARY ***"
-  echo "version: $NEWMAJOR.$NEWMINOR.$NEWBUILD.$NEWPATCH"
-  echo "branch: $TO_URL"
-  echo "svn revision: $SVN_REVISION"
-  [[ -n "$REVISION_LIST" ]] && echo "patches:$REVISION_LIST"
+  if [ $REVERT_FROM_BLEEDING_EDGE==0 ] ; then
+    echo "*** SUMMARY ***"
+    echo "version: $NEWMAJOR.$NEWMINOR.$NEWBUILD.$NEWPATCH"
+    echo "branch: $TO_URL"
+    echo "svn revision: $SVN_REVISION"
+    [[ -n "$REVISION_LIST" ]] && echo "patches:$REVISION_LIST"
+  fi
 fi
diff --git a/tools/push-to-trunk/common_includes.py b/tools/push-to-trunk/common_includes.py
index eaa3d20..4f77c6b 100644
--- a/tools/push-to-trunk/common_includes.py
+++ b/tools/push-to-trunk/common_includes.py
@@ -99,8 +99,8 @@
   result = ""
   added_titles = set()
   for (title, body, author) in commit_messages:
-    # TODO(machenbach): Reload the commit description from rietveld in order to
-    # catch late changes.
+    # TODO(machenbach): Better check for reverts. A revert should remove the
+    # original CL from the actual log entry.
     title = title.strip()
     if auto_format:
       # Only add commits that set the LOG flag correctly.
@@ -114,16 +114,12 @@
       if title in added_titles:
         continue
 
-    # TODO(machenbach): Let python do all formatting. Get raw git title, attach
-    # issue and add/move dot to the end - all in one line. Make formatting and
-    # indentation afterwards.
-
-    # Add the commit's title line.
-    result += "%s\n" % Fill80(title)
+    # Add and format the commit's title and bug reference. Move dot to the end.
     added_titles.add(title)
-
-    # Add bug references.
-    result += MakeChangeLogBugReference(body)
+    raw_title = re.sub(r"(\.|\?|!)$", "", title)
+    bug_reference = MakeChangeLogBugReference(body)
+    space = " " if bug_reference else ""
+    result += "%s\n" % Fill80("%s%s%s." % (raw_title, space, bug_reference))
 
     # Append the commit's author for reference if not in auto-format mode.
     if not auto_format:
@@ -169,8 +165,7 @@
   FormatIssues("Chromium ", crbugs)
 
   if len(bug_groups) > 0:
-    # Format with 8 characters indentation and max 80 character lines.
-    return "%s\n" % Fill80("(%s)" % ", ".join(bug_groups))
+    return "(%s)" % ", ".join(bug_groups)
   else:
     return ""
 
diff --git a/tools/push-to-trunk/push_to_trunk.py b/tools/push-to-trunk/push_to_trunk.py
index 24dfb67..d78aacb 100755
--- a/tools/push-to-trunk/push_to_trunk.py
+++ b/tools/push-to-trunk/push_to_trunk.py
@@ -30,6 +30,7 @@
 import optparse
 import sys
 import tempfile
+import urllib2
 
 from common_includes import *
 
@@ -91,6 +92,21 @@
 class PrepareChangeLog(Step):
   MESSAGE = "Prepare raw ChangeLog entry."
 
+  def Reload(self, body):
+    """Attempts to reload the commit message from rietveld in order to allow
+    late changes to the LOG flag. Note: This is brittle to future changes of
+    the web page name or structure.
+    """
+    match = re.search(r"^Review URL: https://codereview\.chromium\.org/(\d+)$",
+                      body, flags=re.M)
+    if match:
+      cl_url = "https://codereview.chromium.org/%s/description" % match.group(1)
+      try:
+        body = self.ReadURL(cl_url)
+      except urllib2.URLError:
+        pass
+    return body
+
   def RunStep(self):
     self.RestoreIfUnset("last_push")
 
@@ -112,7 +128,7 @@
     commit_messages = [
       [
         self.Git("log -1 %s --format=\"%%s\"" % commit),
-        self.Git("log -1 %s --format=\"%%B\"" % commit),
+        self.Reload(self.Git("log -1 %s --format=\"%%B\"" % commit)),
         self.Git("log -1 %s --format=\"%%an\"" % commit),
       ] for commit in commits.splitlines()
     ]
@@ -151,6 +167,7 @@
     changelog_entry = FileToText(self.Config(CHANGELOG_ENTRY_FILE)).rstrip()
     changelog_entry = StripComments(changelog_entry)
     changelog_entry = "\n".join(map(Fill80, changelog_entry.splitlines()))
+    changelog_entry = changelog_entry.lstrip()
 
     if changelog_entry == "":
       self.Die("Empty ChangeLog entry.")
@@ -541,6 +558,12 @@
   if options.s < 0:
     print "Bad step number %d" % options.s
     return False
+  if options.f and not options.r:
+    print "A reviewer (-r) is required in forced mode."
+    return False
+  if options.f and not options.c:
+    print "A chromium checkout (-c) is required in forced mode."
+    return False
   return True
 
 
diff --git a/tools/push-to-trunk/test_scripts.py b/tools/push-to-trunk/test_scripts.py
index 5e2340e..f4d0c12 100644
--- a/tools/push-to-trunk/test_scripts.py
+++ b/tools/push-to-trunk/test_scripts.py
@@ -71,14 +71,13 @@
           ["Title text 1",
            "Title text 1\n\nBUG=\n",
            "author1@chromium.org"],
-          ["Title text 2",
+          ["Title text 2.",
            "Title text 2\n\nBUG=1234\n",
            "author2@chromium.org"],
         ]
-    self.assertEquals("        Title text 1\n"
+    self.assertEquals("        Title text 1.\n"
                       "        (author1@chromium.org)\n\n"
-                      "        Title text 2\n"
-                      "        (Chromium issue 1234)\n"
+                      "        Title text 2 (Chromium issue 1234).\n"
                       "        (author2@chromium.org)\n\n",
                       MakeChangeLogBody(commits))
 
@@ -87,7 +86,7 @@
 
   def testMakeChangeLogBodyAutoFormat(self):
     commits = [
-          ["Title text 1",
+          ["Title text 1!",
            "Title text 1\nLOG=y\nBUG=\n",
            "author1@chromium.org"],
           ["Title text 2",
@@ -100,9 +99,8 @@
            "Title text 4\n\nBUG=1234\nLOG=\n",
            "author4@chromium.org"],
         ]
-    self.assertEquals("        Title text 1\n\n"
-                      "        Title text 3\n"
-                      "        (Chromium issue 1234)\n\n",
+    self.assertEquals("        Title text 1.\n\n"
+                      "        Title text 3 (Chromium issue 1234).\n\n",
                       MakeChangeLogBody(commits, True))
 
   def testMakeChangeLogBugReferenceEmpty(self):
@@ -112,13 +110,13 @@
     self.assertEquals("", MakeChangeLogBugReference("BUG=none\t"))
 
   def testMakeChangeLogBugReferenceSimple(self):
-    self.assertEquals("        (issue 987654)\n",
+    self.assertEquals("(issue 987654)",
                       MakeChangeLogBugReference("BUG = v8:987654"))
-    self.assertEquals("        (Chromium issue 987654)\n",
+    self.assertEquals("(Chromium issue 987654)",
                       MakeChangeLogBugReference("BUG=987654 "))
 
   def testMakeChangeLogBugReferenceFromBody(self):
-    self.assertEquals("        (Chromium issue 1234567)\n",
+    self.assertEquals("(Chromium issue 1234567)",
                       MakeChangeLogBugReference("Title\n\nTBR=\nBUG=\n"
                                                 " BUG=\tchromium:1234567\t\n"
                                                 "R=somebody\n"))
@@ -126,54 +124,56 @@
   def testMakeChangeLogBugReferenceMultiple(self):
     # All issues should be sorted and grouped. Multiple references to the same
     # issue should be filtered.
-    self.assertEquals("        (issues 123, 234, Chromium issue 345)\n",
+    self.assertEquals("(issues 123, 234, Chromium issue 345)",
                       MakeChangeLogBugReference("Title\n\n"
                                                 "BUG=v8:234\n"
                                                 "  BUG\t= 345, \tv8:234,\n"
                                                 "BUG=v8:123\n"
                                                 "R=somebody\n"))
-    self.assertEquals("        (Chromium issues 123, 234)\n",
+    self.assertEquals("(Chromium issues 123, 234)",
                       MakeChangeLogBugReference("Title\n\n"
                                                 "BUG=234,,chromium:123 \n"
                                                 "R=somebody\n"))
-    self.assertEquals("        (Chromium issues 123, 234)\n",
+    self.assertEquals("(Chromium issues 123, 234)",
                       MakeChangeLogBugReference("Title\n\n"
                                                 "BUG=chromium:234, , 123\n"
                                                 "R=somebody\n"))
-    self.assertEquals("        (issues 345, 456)\n",
+    self.assertEquals("(issues 345, 456)",
                       MakeChangeLogBugReference("Title\n\n"
                                                 "\t\tBUG=v8:345,v8:456\n"
                                                 "R=somebody\n"))
-    self.assertEquals("        (issue 123, Chromium issues 345, 456)\n",
+    self.assertEquals("(issue 123, Chromium issues 345, 456)",
                       MakeChangeLogBugReference("Title\n\n"
                                                 "BUG=chromium:456\n"
                                                 "BUG = none\n"
                                                 "R=somebody\n"
                                                 "BUG=456,v8:123, 345"))
 
+  # TODO(machenbach): These test don't make much sense when the formatting is
+  # done later.
   def testMakeChangeLogBugReferenceLong(self):
     # -----------------00--------10--------20--------30--------
-    self.assertEquals("        (issues 234, 1234567890, 1234567"
-                      "8901234567890, Chromium issues 12345678,\n"
-                      "        123456789)\n",
+    self.assertEquals("(issues 234, 1234567890, 1234567"
+                      "8901234567890, Chromium issues 12345678,"
+                      " 123456789)",
                       MakeChangeLogBugReference("BUG=v8:234\n"
                                                 "BUG=v8:1234567890\n"
                                                 "BUG=v8:12345678901234567890\n"
                                                 "BUG=123456789\n"
                                                 "BUG=12345678\n"))
     # -----------------00--------10--------20--------30--------
-    self.assertEquals("        (issues 234, 1234567890, 1234567"
-                      "8901234567890, Chromium issues\n"
-                      "        123456789, 1234567890)\n",
+    self.assertEquals("(issues 234, 1234567890, 1234567"
+                      "8901234567890, Chromium issues"
+                      " 123456789, 1234567890)",
                       MakeChangeLogBugReference("BUG=v8:234\n"
                                                 "BUG=v8:12345678901234567890\n"
                                                 "BUG=v8:1234567890\n"
                                                 "BUG=123456789\n"
                                                 "BUG=1234567890\n"))
     # -----------------00--------10--------20--------30--------
-    self.assertEquals("        (Chromium issues 234, 1234567890"
-                      ", 12345678901234567,\n"
-                      "        1234567890123456789)\n",
+    self.assertEquals("(Chromium issues 234, 1234567890"
+                      ", 12345678901234567, "
+                      "1234567890123456789)",
                       MakeChangeLogBugReference("BUG=234\n"
                                                 "BUG=12345678901234567\n"
                                                 "BUG=1234567890123456789\n"
@@ -194,7 +194,7 @@
     try:
       expected_call = self._recipe[self._index]
     except IndexError:
-      raise Exception("Calling %s %s" % (name, " ".join(args)))
+      raise Exception("Calling %s %s" % (self._name, " ".join(args)))
 
     # Pack expectations without arguments into a list.
     if not isinstance(expected_call, list):
@@ -397,16 +397,27 @@
     TEST_CONFIG[CHANGELOG_ENTRY_FILE] = self.MakeEmptyTempFile()
 
     self.ExpectGit([
-      ["log 1234..HEAD --format=%H", "rev1\nrev2\nrev3"],
+      ["log 1234..HEAD --format=%H", "rev1\nrev2\nrev3\nrev4"],
       ["log -1 rev1 --format=\"%s\"", "Title text 1"],
       ["log -1 rev1 --format=\"%B\"", "Title\n\nBUG=\nLOG=y\n"],
       ["log -1 rev1 --format=\"%an\"", "author1@chromium.org"],
-      ["log -1 rev2 --format=\"%s\"", "Title text 2"],
+      ["log -1 rev2 --format=\"%s\"", "Title text 2."],
       ["log -1 rev2 --format=\"%B\"", "Title\n\nBUG=123\nLOG= \n"],
       ["log -1 rev2 --format=\"%an\"", "author2@chromium.org"],
       ["log -1 rev3 --format=\"%s\"", "Title text 3"],
       ["log -1 rev3 --format=\"%B\"", "Title\n\nBUG=321\nLOG=true\n"],
       ["log -1 rev3 --format=\"%an\"", "author3@chromium.org"],
+      ["log -1 rev4 --format=\"%s\"", "Title text 4"],
+      ["log -1 rev4 --format=\"%B\"",
+       ("Title\n\nBUG=456\nLOG=Y\n\n"
+        "Review URL: https://codereview.chromium.org/9876543210\n")],
+      ["log -1 rev4 --format=\"%an\"", "author4@chromium.org"],
+    ])
+
+    # The cl for rev4 on rietveld has an updated LOG flag.
+    self.ExpectReadURL([
+      ["https://codereview.chromium.org/9876543210/description",
+       "Title\n\nBUG=456\nLOG=N\n\n"],
     ])
 
     self.MakeStep().Persist("last_push", "1234")
@@ -418,10 +429,9 @@
     # comparison here instead of a regexp match.
     expected_cl = """\\d+\\-\\d+\\-\\d+: Version 3\\.22\\.5
 
-        Title text 1
+        Title text 1.
 
-        Title text 3
-        \\(Chromium issue 321\\)
+        Title text 3 \\(Chromium issue 321\\).
 
         Performance and stability improvements on all platforms\\.
 #
@@ -429,17 +439,18 @@
 # commit messages from the list below are included\\.
 # All lines starting with # will be stripped\\.
 #
-#       Title text 1
+#       Title text 1.
 #       \\(author1@chromium\\.org\\)
 #
-#       Title text 2
-#       \\(Chromium issue 123\\)
+#       Title text 2 \\(Chromium issue 123\\).
 #       \\(author2@chromium\\.org\\)
 #
-#       Title text 3
-#       \\(Chromium issue 321\\)
+#       Title text 3 \\(Chromium issue 321\\).
 #       \\(author3@chromium\\.org\\)
 #
+#       Title text 4 \\(Chromium issue 456\\).
+#       \\(author4@chromium\\.org\\)
+#
 #"""
 
     self.assertTrue(re.match(expected_cl, actual_cl))
@@ -461,7 +472,7 @@
 
     self.MakeStep(EditChangeLog).Run()
 
-    self.assertEquals("        New\n        Lines\n\n\n        Original CL",
+    self.assertEquals("New\n        Lines\n\n\n        Original CL",
                       FileToText(TEST_CONFIG[CHANGELOG_FILE]))
 
   def testIncrementVersion(self):
@@ -539,8 +550,7 @@
     def CheckPreparePush():
       cl = FileToText(TEST_CONFIG[CHANGELOG_FILE])
       self.assertTrue(re.search(r"Version 3.22.5", cl))
-      self.assertTrue(re.search(r"        Log text 1", cl))
-      self.assertTrue(re.search(r"        \(issue 321\)", cl))
+      self.assertTrue(re.search(r"        Log text 1 \(issue 321\).", cl))
       self.assertFalse(re.search(r"        \(author1@chromium\.org\)", cl))
 
       # Make sure all comments got stripped.
@@ -555,7 +565,7 @@
     def CheckSVNCommit():
       commit = FileToText(TEST_CONFIG[COMMITMSG_FILE])
       self.assertTrue(re.search(r"Version 3.22.5", commit))
-      self.assertTrue(re.search(r"Log text 1. \(issue 321\)", commit))
+      self.assertTrue(re.search(r"Log text 1 \(issue 321\).", commit))
       version = FileToText(TEST_CONFIG[VERSION_FILE])
       self.assertTrue(re.search(r"#define MINOR_VERSION\s+22", version))
       self.assertTrue(re.search(r"#define BUILD_NUMBER\s+5", version))
@@ -643,9 +653,8 @@
     self.assertTrue(re.search("\"v8_revision\": \"123456\"", deps))
 
     cl = FileToText(TEST_CONFIG[CHANGELOG_FILE])
-    self.assertTrue(re.search(r"\d\d\d\d\-\d+\-\d+: Version 3\.22\.5", cl))
-    self.assertTrue(re.search(r"        Log text 1", cl))
-    self.assertTrue(re.search(r"        \(issue 321\)", cl))
+    self.assertTrue(re.search(r"^\d\d\d\d\-\d+\-\d+: Version 3\.22\.5", cl))
+    self.assertTrue(re.search(r"        Log text 1 \(issue 321\).", cl))
     self.assertTrue(re.search(r"1999\-04\-05: Version 3\.22\.4", cl))
 
     # Note: The version file is on build number 5 again in the end of this test
@@ -686,3 +695,27 @@
 
     self.assertEquals("100", self.MakeStep().Restore("lkgr"))
     self.assertEquals("101", self.MakeStep().Restore("latest"))
+
+
+class SystemTest(unittest.TestCase):
+  def testReload(self):
+    step = MakeStep(step_class=PrepareChangeLog, number=0, state={}, config={},
+                    options=None,
+                    side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER)
+    body = step.Reload(
+"""------------------------------------------------------------------------
+r17997 | machenbach@chromium.org | 2013-11-22 11:04:04 +0100 (...) | 6 lines
+
+Prepare push to trunk.  Now working on version 3.23.11.
+
+R=danno@chromium.org
+
+Review URL: https://codereview.chromium.org/83173002
+
+------------------------------------------------------------------------""")
+    self.assertEquals(
+"""Prepare push to trunk.  Now working on version 3.23.11.
+
+R=danno@chromium.org
+
+Committed: https://code.google.com/p/v8/source/detail?r=17997""", body)
diff --git a/tools/run-tests.py b/tools/run-tests.py
index 2fdbeb9..32b3f49 100755
--- a/tools/run-tests.py
+++ b/tools/run-tests.py
@@ -53,9 +53,13 @@
                        "release" : 1 }
 
 # Use this to run several variants of the tests.
-VARIANT_FLAGS = [[],
-                 ["--stress-opt", "--always-opt"],
-                 ["--nocrankshaft"]]
+VARIANT_FLAGS = {
+    "default": [],
+    "stress": ["--stress-opt", "--always-opt"],
+    "nocrankshaft": ["--nocrankshaft"]}
+
+VARIANTS = ["default", "stress", "nocrankshaft"]
+
 MODE_FLAGS = {
     "debug"   : ["--nobreak-on-abort", "--nodead-code-elimination",
                  "--nofold-constants", "--enable-slow-asserts",
@@ -97,6 +101,12 @@
   result.add_option("--flaky-tests",
                     help="Regard tests marked as flaky (run|skip|dontcare)",
                     default="dontcare")
+  result.add_option("--slow-tests",
+                    help="Regard slow tests (run|skip|dontcare)",
+                    default="dontcare")
+  result.add_option("--pass-fail-tests",
+                    help="Regard pass|fail tests (run|skip|dontcare)",
+                    default="dontcare")
   result.add_option("--command-prefix",
                     help="Prepended to each shell command used to run a test",
                     default="")
@@ -128,6 +138,8 @@
   result.add_option("--no-variants", "--novariants",
                     help="Don't run any testing variants",
                     default=False, dest="no_variants", action="store_true")
+  result.add_option("--variants",
+                    help="Comma-separated list of testing variants")
   result.add_option("--outdir", help="Base directory with compile output",
                     default="out")
   result.add_option("-p", "--progress",
@@ -167,6 +179,7 @@
 
 def ProcessOptions(options):
   global VARIANT_FLAGS
+  global VARIANTS
 
   # Architecture and mode related stuff.
   if options.arch_and_mode:
@@ -205,26 +218,41 @@
     """Returns true if zero or one of multiple arguments are true."""
     return reduce(lambda x, y: x + y, args) <= 1
 
-  if not excl(options.no_stress, options.stress_only, options.no_variants):
-    print "Use only one of --no-stress, --stress-only or --no-variants."
+  if not excl(options.no_stress, options.stress_only, options.no_variants,
+              bool(options.variants)):
+    print("Use only one of --no-stress, --stress-only, --no-variants or "
+          "--variants.")
     return False
   if options.no_stress:
-    VARIANT_FLAGS = [[], ["--nocrankshaft"]]
+    VARIANTS = ["default", "nocrankshaft"]
   if options.no_variants:
-    VARIANT_FLAGS = [[]]
+    VARIANTS = ["default"]
+  if options.stress_only:
+    VARIANTS = ["stress"]
+  if options.variants:
+    VARIANTS = options.variants.split(",")
+    if not set(VARIANTS).issubset(VARIANT_FLAGS.keys()):
+      print "All variants must be in %s" % str(VARIANT_FLAGS.keys())
+      return False
   if not options.shell_dir:
     if options.shell:
       print "Warning: --shell is deprecated, use --shell-dir instead."
       options.shell_dir = os.path.dirname(options.shell)
-  if options.stress_only:
-    VARIANT_FLAGS = [["--stress-opt", "--always-opt"]]
   if options.valgrind:
     run_valgrind = os.path.join("tools", "run-valgrind.py")
     # This is OK for distributed running, so we don't need to set no_network.
     options.command_prefix = (["python", "-u", run_valgrind] +
                               options.command_prefix)
-  if not options.flaky_tests in ["run", "skip", "dontcare"]:
-    print "Unknown flaky test mode %s" % options.flaky_tests
+  def CheckTestMode(name, option):
+    if not option in ["run", "skip", "dontcare"]:
+      print "Unknown %s mode %s" % (name, option)
+      return False
+    return True
+  if not CheckTestMode("flaky test", options.flaky_tests):
+    return False
+  if not CheckTestMode("slow test", options.slow_tests):
+    return False
+  if not CheckTestMode("pass|fail test", options.pass_fail_tests):
     return False
   if not options.no_i18n:
     DEFAULT_TESTS.append("intl")
@@ -341,13 +369,15 @@
     if len(args) > 0:
       s.FilterTestCasesByArgs(args)
     all_tests += s.tests
-    s.FilterTestCasesByStatus(options.warn_unused, options.flaky_tests)
+    s.FilterTestCasesByStatus(options.warn_unused, options.flaky_tests,
+                              options.slow_tests, options.pass_fail_tests)
     if options.cat:
       verbose.PrintTestSource(s.tests)
       continue
+    variant_flags = [VARIANT_FLAGS[var] for var in VARIANTS]
     s.tests = [ t.CopyAddingFlags(v)
                 for t in s.tests
-                for v in s.VariantFlags(t, VARIANT_FLAGS) ]
+                for v in s.VariantFlags(t, variant_flags) ]
     s.tests = ShardTests(s.tests, options.shard_count, options.shard_run)
     num_tests += len(s.tests)
     for t in s.tests:
diff --git a/tools/testrunner/local/statusfile.py b/tools/testrunner/local/statusfile.py
index da0c797..e290122 100644
--- a/tools/testrunner/local/statusfile.py
+++ b/tools/testrunner/local/statusfile.py
@@ -59,7 +59,11 @@
 
 
 def DoSkip(outcomes):
-  return SKIP in outcomes or SLOW in outcomes
+  return SKIP in outcomes
+
+
+def IsSlow(outcomes):
+  return SLOW in outcomes
 
 
 def OnlyStandardVariant(outcomes):
diff --git a/tools/testrunner/local/testsuite.py b/tools/testrunner/local/testsuite.py
index 8517ce9..ff51196 100644
--- a/tools/testrunner/local/testsuite.py
+++ b/tools/testrunner/local/testsuite.py
@@ -93,11 +93,24 @@
   def _FilterFlaky(flaky, mode):
     return (mode == "run" and not flaky) or (mode == "skip" and flaky)
 
-  def FilterTestCasesByStatus(self, warn_unused_rules, flaky_tests="dontcare"):
+  @staticmethod
+  def _FilterSlow(slow, mode):
+    return (mode == "run" and not slow) or (mode == "skip" and slow)
+
+  @staticmethod
+  def _FilterPassFail(pass_fail, mode):
+    return (mode == "run" and not pass_fail) or (mode == "skip" and pass_fail)
+
+  def FilterTestCasesByStatus(self, warn_unused_rules,
+                              flaky_tests="dontcare",
+                              slow_tests="dontcare",
+                              pass_fail_tests="dontcare"):
     filtered = []
     used_rules = set()
     for t in self.tests:
       flaky = False
+      slow = False
+      pass_fail = False
       testname = self.CommonTestName(t)
       if testname in self.rules:
         used_rules.add(testname)
@@ -107,6 +120,8 @@
         if statusfile.DoSkip(t.outcomes):
           continue  # Don't add skipped tests to |filtered|.
         flaky = statusfile.IsFlaky(t.outcomes)
+        slow = statusfile.IsSlow(t.outcomes)
+        pass_fail = statusfile.IsPassOrFail(t.outcomes)
       skip = False
       for rule in self.wildcards:
         assert rule[-1] == '*'
@@ -117,7 +132,11 @@
             skip = True
             break  # "for rule in self.wildcards"
           flaky = flaky or statusfile.IsFlaky(t.outcomes)
-      if skip or self._FilterFlaky(flaky, flaky_tests):
+          slow = slow or statusfile.IsSlow(t.outcomes)
+          pass_fail = pass_fail or statusfile.IsPassOrFail(t.outcomes)
+      if (skip or self._FilterFlaky(flaky, flaky_tests)
+          or self._FilterSlow(slow, slow_tests)
+          or self._FilterPassFail(pass_fail, pass_fail_tests)):
         continue  # "for t in self.tests"
       filtered.append(t)
     self.tests = filtered