Revision: 24608
Author:   [email protected]
Date:     Tue Oct 14 14:46:11 2014 UTC
Log:      Catch exceptions thrown when enqueuing change records.

[email protected]
BUG=chromium:417709
LOG=N

Review URL: https://codereview.chromium.org/653593002
https://code.google.com/p/v8/source/detail?r=24608

Added:
 /branches/bleeding_edge/test/mjsunit/regress/regress-417709a.js
Modified:
 /branches/bleeding_edge/src/accessors.cc
 /branches/bleeding_edge/src/accessors.h
 /branches/bleeding_edge/src/bootstrapper.cc
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/runtime/runtime-function.cc
 /branches/bleeding_edge/src/runtime/runtime-object.cc

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/regress/regress-417709a.js Tue Oct 14 14:46:11 2014 UTC
@@ -0,0 +1,16 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --stack-size=100
+
+var a = [];
+
+Object.observe(a, function() {});
+
+function f(a, x) {
+  a.length = x;
+  f(a, x + 1);
+}
+
+assertThrows(function() { f(a, 1); }, RangeError);
=======================================
--- /branches/bleeding_edge/src/accessors.cc    Thu Oct  2 10:52:12 2014 UTC
+++ /branches/bleeding_edge/src/accessors.cc    Tue Oct 14 14:46:11 2014 UTC
@@ -172,7 +172,10 @@
   LookupIterator it(object, Utils::OpenHandle(*name));
   CHECK_EQ(LookupIterator::ACCESSOR, it.state());
   DCHECK(it.HolderIsReceiverOrHiddenPrototype());
-  Object::SetDataProperty(&it, value);
+
+  if (Object::SetDataProperty(&it, value).is_null()) {
+    isolate->OptionalRescheduleException(false);
+  }
 }


@@ -247,7 +250,7 @@

   if (uint32_v->Number() == number_v->Number()) {
     maybe = JSArray::SetElementsLength(array_handle, uint32_v);
-    maybe.Check();
+    if (maybe.is_null()) isolate->OptionalRescheduleException(false);
     return;
   }

@@ -881,9 +884,8 @@
 }


-static Handle<Object> SetFunctionPrototype(Isolate* isolate,
-                                           Handle<JSFunction> function,
-                                           Handle<Object> value) {
+MUST_USE_RESULT static MaybeHandle<Object> SetFunctionPrototype(
+    Isolate* isolate, Handle<JSFunction> function, Handle<Object> value) {
   Handle<Object> old_value;
   bool is_observed = function->map()->is_observed();
   if (is_observed) {
@@ -897,16 +899,17 @@
   DCHECK(function->prototype() == *value);

   if (is_observed && !old_value->SameValue(*value)) {
-    JSObject::EnqueueChangeRecord(
+    MaybeHandle<Object> result = JSObject::EnqueueChangeRecord(
function, "update", isolate->factory()->prototype_string(), old_value);
+    if (result.is_null()) return MaybeHandle<Object>();
   }

   return function;
 }


-Handle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function,
-                                               Handle<Object> prototype) {
+MaybeHandle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function, + Handle<Object> prototype) {
   DCHECK(function->should_have_prototype());
   Isolate* isolate = function->GetIsolate();
   return SetFunctionPrototype(isolate, function, prototype);
@@ -937,7 +940,9 @@
   }
   Handle<JSFunction> object =
       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
-  SetFunctionPrototype(isolate, object, value);
+  if (SetFunctionPrototype(isolate, object, value).is_null()) {
+    isolate->OptionalRescheduleException(false);
+  }
 }


=======================================
--- /branches/bleeding_edge/src/accessors.h     Thu Oct  2 10:52:12 2014 UTC
+++ /branches/bleeding_edge/src/accessors.h     Tue Oct 14 14:46:11 2014 UTC
@@ -66,8 +66,8 @@
   };

   // Accessor functions called directly from the runtime system.
-  static Handle<Object> FunctionSetPrototype(Handle<JSFunction> object,
-                                             Handle<Object> value);
+  MUST_USE_RESULT static MaybeHandle<Object> FunctionSetPrototype(
+      Handle<JSFunction> object, Handle<Object> value);
   static Handle<Object> FunctionGetArguments(Handle<JSFunction> object);

   // Accessor infos.
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Wed Oct  8 14:42:31 2014 UTC
+++ /branches/bleeding_edge/src/bootstrapper.cc Tue Oct 14 14:46:11 2014 UTC
@@ -509,7 +509,7 @@
     // prototype, otherwise the missing initial_array_prototype will cause
     // assertions during startup.
     native_context()->set_initial_array_prototype(*prototype);
-    Accessors::FunctionSetPrototype(object_fun, prototype);
+    Accessors::FunctionSetPrototype(object_fun, prototype).Assert();
   }

   // Allocate the empty function as the prototype for function ECMAScript
@@ -1673,7 +1673,7 @@
         isolate()->initial_object_prototype(), Builtins::kIllegal);
     Handle<JSObject> prototype =
         factory()->NewJSObject(isolate()->object_function(), TENURED);
-    Accessors::FunctionSetPrototype(script_fun, prototype);
+    Accessors::FunctionSetPrototype(script_fun, prototype).Assert();
     native_context()->set_script_function(*script_fun);

     Handle<Map> script_map = Handle<Map>(script_fun->initial_map());
@@ -1815,7 +1815,7 @@
         isolate()->initial_object_prototype(), Builtins::kIllegal);
     Handle<JSObject> prototype =
         factory()->NewJSObject(isolate()->object_function(), TENURED);
-    Accessors::FunctionSetPrototype(opaque_reference_fun, prototype);
+ Accessors::FunctionSetPrototype(opaque_reference_fun, prototype).Assert();
     native_context()->set_opaque_reference_function(*opaque_reference_fun);
   }

=======================================
--- /branches/bleeding_edge/src/objects.cc      Tue Oct 14 14:43:45 2014 UTC
+++ /branches/bleeding_edge/src/objects.cc      Tue Oct 14 14:46:11 2014 UTC
@@ -1811,10 +1811,10 @@
 }


-void JSObject::EnqueueChangeRecord(Handle<JSObject> object,
-                                   const char* type_str,
-                                   Handle<Name> name,
-                                   Handle<Object> old_value) {
+MaybeHandle<Object> JSObject::EnqueueChangeRecord(Handle<JSObject> object,
+                                                  const char* type_str,
+                                                  Handle<Name> name,
+ Handle<Object> old_value) {
   DCHECK(!object->IsJSGlobalProxy());
   DCHECK(!object->IsJSGlobalObject());
   Isolate* isolate = object->GetIsolate();
@@ -1823,10 +1823,9 @@
   Handle<Object> args[] = { type, object, name, old_value };
   int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;

-  Execution::Call(isolate,
-                  Handle<JSFunction>(isolate->observers_notify_change()),
-                  isolate->factory()->undefined_value(),
-                  argc, args).Assert();
+  return Execution::Call(isolate,
+ Handle<JSFunction>(isolate->observers_notify_change()), + isolate->factory()->undefined_value(), argc, args);
 }


@@ -2933,8 +2932,8 @@
 }


-Handle<Object> Object::SetDataProperty(LookupIterator* it,
-                                       Handle<Object> value) {
+MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
+                                            Handle<Object> value) {
// Proxies are handled on the WithHandler path. Other non-JSObjects cannot
   // have own properties.
   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
@@ -2960,8 +2959,10 @@

   // Send the change record if there are observers.
   if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
-    JSObject::EnqueueChangeRecord(receiver, "update", it->name(),
-                                  maybe_old.ToHandleChecked());
+    RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord(
+                                           receiver, "update", it->name(),
+                                           maybe_old.ToHandleChecked()),
+                        Object);
   }

   return value;
@@ -3012,8 +3013,10 @@
   // Send the change record if there are observers.
   if (receiver->map()->is_observed() &&
       !it->name().is_identical_to(it->factory()->hidden_string())) {
-    JSObject::EnqueueChangeRecord(receiver, "add", it->name(),
-                                  it->factory()->the_hole_value());
+    RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord(
+                                           receiver, "add", it->name(),
+ it->factory()->the_hole_value()),
+                        Object);
   }

   return value;
@@ -3862,7 +3865,10 @@
                   !Name::Equals(it.isolate()->factory()->prototype_string(),
                                 name) ||
!Handle<JSFunction>::cast(object)->should_have_prototype()) {
-                EnqueueChangeRecord(object, "update", name, old_value);
+                RETURN_ON_EXCEPTION(
+                    it.isolate(),
+                    EnqueueChangeRecord(object, "update", name, old_value),
+                    Object);
               }
             }
             return value;
@@ -3881,7 +3887,10 @@
             if (old_value->SameValue(*value)) {
               old_value = it.isolate()->factory()->the_hole_value();
             }
-            EnqueueChangeRecord(object, "reconfigure", name, old_value);
+            RETURN_ON_EXCEPTION(
+                it.isolate(),
+ EnqueueChangeRecord(object, "reconfigure", name, old_value),
+                Object);
           }
           return value;
         }
@@ -3894,7 +3903,10 @@
           if (old_value->SameValue(*value)) {
             old_value = it.isolate()->factory()->the_hole_value();
           }
-          EnqueueChangeRecord(object, "reconfigure", name, old_value);
+          RETURN_ON_EXCEPTION(
+              it.isolate(),
+              EnqueueChangeRecord(object, "reconfigure", name, old_value),
+              Object);
         }

         return value;
@@ -3918,7 +3930,10 @@
           if (old_value->SameValue(*value)) {
             old_value = it.isolate()->factory()->the_hole_value();
           }
-          EnqueueChangeRecord(object, "reconfigure", name, old_value);
+          RETURN_ON_EXCEPTION(
+              it.isolate(),
+              EnqueueChangeRecord(object, "reconfigure", name, old_value),
+              Object);
         }

         return value;
@@ -4891,7 +4906,9 @@
     if (!maybe.has_value) return MaybeHandle<Object>();
     if (!maybe.value) {
       Handle<String> name = factory->Uint32ToString(index);
-      EnqueueChangeRecord(object, "delete", name, old_value);
+      RETURN_ON_EXCEPTION(
+          isolate, EnqueueChangeRecord(object, "delete", name, old_value),
+          Object);
     }
   }

@@ -4977,7 +4994,9 @@
         ReoptimizeIfPrototype(holder);

         if (is_observed) {
-          EnqueueChangeRecord(object, "delete", name, old_value);
+          RETURN_ON_EXCEPTION(
+              it.isolate(),
+ EnqueueChangeRecord(object, "delete", name, old_value), Object);
         }

         return result;
@@ -5194,8 +5213,11 @@
   DCHECK(!object->map()->is_extensible());

   if (object->map()->is_observed()) {
-    EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
-                        isolate->factory()->the_hole_value());
+    RETURN_ON_EXCEPTION(
+        isolate,
+        EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
+                            isolate->factory()->the_hole_value()),
+        Object);
   }
   return object;
 }
@@ -6168,7 +6190,8 @@

   if (is_observed) {
     const char* type = preexists ? "reconfigure" : "add";
-    EnqueueChangeRecord(object, type, name, old_value);
+    RETURN_ON_EXCEPTION(
+ isolate, EnqueueChangeRecord(object, type, name, old_value), Object);
   }

   return isolate->factory()->undefined_value();
@@ -11237,13 +11260,18 @@
     // For deletions where the property was an accessor, old_values[i]
     // will be the hole, which instructs EnqueueChangeRecord to elide
     // the "oldValue" property.
-    JSObject::EnqueueChangeRecord(
-        array, "delete", isolate->factory()->Uint32ToString(indices[i]),
-        old_values[i]);
+    RETURN_ON_EXCEPTION(
+        isolate,
+        JSObject::EnqueueChangeRecord(
+ array, "delete", isolate->factory()->Uint32ToString(indices[i]),
+            old_values[i]),
+        Object);
   }
-  JSObject::EnqueueChangeRecord(
-      array, "update", isolate->factory()->length_string(),
-      old_length_handle);
+  RETURN_ON_EXCEPTION(isolate,
+                      JSObject::EnqueueChangeRecord(
+ array, "update", isolate->factory()->length_string(),
+                          old_length_handle),
+                      Object);

   EndPerformSplice(array);

@@ -12451,27 +12479,38 @@
       CHECK(new_length_handle->ToArrayIndex(&new_length));

       BeginPerformSplice(Handle<JSArray>::cast(object));
-      EnqueueChangeRecord(object, "add", name, old_value);
- EnqueueChangeRecord(object, "update", isolate->factory()->length_string(),
-                          old_length_handle);
+      RETURN_ON_EXCEPTION(
+ isolate, EnqueueChangeRecord(object, "add", name, old_value), Object);
+      RETURN_ON_EXCEPTION(
+          isolate, EnqueueChangeRecord(object, "update",
+                                       isolate->factory()->length_string(),
+                                       old_length_handle),
+          Object);
       EndPerformSplice(Handle<JSArray>::cast(object));
       Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
EnqueueSpliceRecord(Handle<JSArray>::cast(object), old_length, deleted,
                           new_length - old_length);
     } else {
-      EnqueueChangeRecord(object, "add", name, old_value);
+      RETURN_ON_EXCEPTION(
+ isolate, EnqueueChangeRecord(object, "add", name, old_value), Object);
     }
   } else if (old_value->IsTheHole()) {
-    EnqueueChangeRecord(object, "reconfigure", name, old_value);
+    RETURN_ON_EXCEPTION(
+ isolate, EnqueueChangeRecord(object, "reconfigure", name, old_value),
+        Object);
   } else {
     Handle<Object> new_value =
         Object::GetElement(isolate, object, index).ToHandleChecked();
     bool value_changed = !old_value->SameValue(*new_value);
     if (old_attributes != new_attributes) {
       if (!value_changed) old_value = isolate->factory()->the_hole_value();
-      EnqueueChangeRecord(object, "reconfigure", name, old_value);
+      RETURN_ON_EXCEPTION(
+ isolate, EnqueueChangeRecord(object, "reconfigure", name, old_value),
+          Object);
     } else if (value_changed) {
-      EnqueueChangeRecord(object, "update", name, old_value);
+      RETURN_ON_EXCEPTION(
+          isolate, EnqueueChangeRecord(object, "update", name, old_value),
+          Object);
     }
   }

=======================================
--- /branches/bleeding_edge/src/objects.h       Tue Oct 14 14:43:45 2014 UTC
+++ /branches/bleeding_edge/src/objects.h       Tue Oct 14 14:46:11 2014 UTC
@@ -1130,8 +1130,8 @@
       StorePropertyMode data_store_mode = NORMAL_PROPERTY);
   MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyProperty(
       LookupIterator* it, Handle<Object> value, StrictMode strict_mode);
-  static Handle<Object> SetDataProperty(LookupIterator* it,
-                                        Handle<Object> value);
+  MUST_USE_RESULT static MaybeHandle<Object> SetDataProperty(
+      LookupIterator* it, Handle<Object> value);
   MUST_USE_RESULT static MaybeHandle<Object> AddDataProperty(
LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
       StrictMode strict_mode, StoreFromKeyed store_mode);
@@ -2215,10 +2215,9 @@
   Context* GetCreationContext();

   // Enqueue change record for Object.observe. May cause GC.
-  static void EnqueueChangeRecord(Handle<JSObject> object,
-                                  const char* type,
-                                  Handle<Name> name,
-                                  Handle<Object> old_value);
+  MUST_USE_RESULT static MaybeHandle<Object> EnqueueChangeRecord(
+      Handle<JSObject> object, const char* type, Handle<Name> name,
+      Handle<Object> old_value);

  private:
   friend class DictionaryElementsAccessor;
=======================================
--- /branches/bleeding_edge/src/runtime/runtime-function.cc Tue Sep 30 10:46:04 2014 UTC +++ /branches/bleeding_edge/src/runtime/runtime-function.cc Tue Oct 14 14:46:11 2014 UTC
@@ -201,7 +201,8 @@
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
   RUNTIME_ASSERT(fun->should_have_prototype());
-  Accessors::FunctionSetPrototype(fun, value);
+  RETURN_FAILURE_ON_EXCEPTION(isolate,
+                              Accessors::FunctionSetPrototype(fun, value));
   return args[0];  // return TOS
 }

=======================================
--- /branches/bleeding_edge/src/runtime/runtime-object.cc Fri Oct 10 14:59:53 2014 UTC +++ /branches/bleeding_edge/src/runtime/runtime-object.cc Tue Oct 14 14:46:11 2014 UTC
@@ -362,8 +362,10 @@
     Handle<Object> new_value =
         Object::GetPrototypeSkipHiddenPrototypes(isolate, obj);
     if (!new_value->SameValue(*old_value)) {
-      JSObject::EnqueueChangeRecord(
- obj, "setPrototype", isolate->factory()->proto_string(), old_value);
+      RETURN_FAILURE_ON_EXCEPTION(
+          isolate, JSObject::EnqueueChangeRecord(
+ obj, "setPrototype", isolate->factory()->proto_string(),
+                       old_value));
     }
     return *result;
   }

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to