From: yangguo@chromium.org Date: Tue, 14 Oct 2014 14:46:11 +0000 (+0000) Subject: Catch exceptions thrown when enqueuing change records. X-Git-Tag: upstream/4.7.83~6368 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9a21ba499c58f24f99d488c099337949951eaae8;p=platform%2Fupstream%2Fv8.git Catch exceptions thrown when enqueuing change records. R=ishell@chromium.org BUG=chromium:417709 LOG=N Review URL: https://codereview.chromium.org/653593002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24608 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/accessors.cc b/src/accessors.cc index 9bd6e5b..ed9d294 100644 --- a/src/accessors.cc +++ b/src/accessors.cc @@ -172,7 +172,10 @@ void Accessors::ArgumentsIteratorSetter( 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 @@ void Accessors::ArrayLengthSetter( 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 GetFunctionPrototype(Isolate* isolate, } -static Handle SetFunctionPrototype(Isolate* isolate, - Handle function, - Handle value) { +MUST_USE_RESULT static MaybeHandle SetFunctionPrototype( + Isolate* isolate, Handle function, Handle value) { Handle old_value; bool is_observed = function->map()->is_observed(); if (is_observed) { @@ -897,16 +899,17 @@ static Handle SetFunctionPrototype(Isolate* isolate, DCHECK(function->prototype() == *value); if (is_observed && !old_value->SameValue(*value)) { - JSObject::EnqueueChangeRecord( + MaybeHandle result = JSObject::EnqueueChangeRecord( function, "update", isolate->factory()->prototype_string(), old_value); + if (result.is_null()) return MaybeHandle(); } return function; } -Handle Accessors::FunctionSetPrototype(Handle function, - Handle prototype) { +MaybeHandle Accessors::FunctionSetPrototype(Handle function, + Handle prototype) { DCHECK(function->should_have_prototype()); Isolate* isolate = function->GetIsolate(); return SetFunctionPrototype(isolate, function, prototype); @@ -937,7 +940,9 @@ void Accessors::FunctionPrototypeSetter( } Handle object = Handle::cast(Utils::OpenHandle(*info.Holder())); - SetFunctionPrototype(isolate, object, value); + if (SetFunctionPrototype(isolate, object, value).is_null()) { + isolate->OptionalRescheduleException(false); + } } diff --git a/src/accessors.h b/src/accessors.h index 1677c1d..678064d 100644 --- a/src/accessors.h +++ b/src/accessors.h @@ -66,8 +66,8 @@ class Accessors : public AllStatic { }; // Accessor functions called directly from the runtime system. - static Handle FunctionSetPrototype(Handle object, - Handle value); + MUST_USE_RESULT static MaybeHandle FunctionSetPrototype( + Handle object, Handle value); static Handle FunctionGetArguments(Handle object); // Accessor infos. diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index c36156d..2dde719 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -509,7 +509,7 @@ Handle Genesis::CreateEmptyFunction(Isolate* isolate) { // 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 @@ bool Genesis::InstallNatives() { isolate()->initial_object_prototype(), Builtins::kIllegal); Handle 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 script_map = Handle(script_fun->initial_map()); @@ -1815,7 +1815,7 @@ bool Genesis::InstallNatives() { isolate()->initial_object_prototype(), Builtins::kIllegal); Handle 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); } diff --git a/src/objects.cc b/src/objects.cc index 3e9ae3e..4f23ea5 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1811,10 +1811,10 @@ Context* JSObject::GetCreationContext() { } -void JSObject::EnqueueChangeRecord(Handle object, - const char* type_str, - Handle name, - Handle old_value) { +MaybeHandle JSObject::EnqueueChangeRecord(Handle object, + const char* type_str, + Handle name, + Handle old_value) { DCHECK(!object->IsJSGlobalProxy()); DCHECK(!object->IsJSGlobalObject()); Isolate* isolate = object->GetIsolate(); @@ -1823,10 +1823,9 @@ void JSObject::EnqueueChangeRecord(Handle object, Handle args[] = { type, object, name, old_value }; int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4; - Execution::Call(isolate, - Handle(isolate->observers_notify_change()), - isolate->factory()->undefined_value(), - argc, args).Assert(); + return Execution::Call(isolate, + Handle(isolate->observers_notify_change()), + isolate->factory()->undefined_value(), argc, args); } @@ -2933,8 +2932,8 @@ MaybeHandle Object::WriteToReadOnlyProperty(LookupIterator* it, } -Handle Object::SetDataProperty(LookupIterator* it, - Handle value) { +MaybeHandle Object::SetDataProperty(LookupIterator* it, + Handle value) { // Proxies are handled on the WithHandler path. Other non-JSObjects cannot // have own properties. Handle receiver = Handle::cast(it->GetReceiver()); @@ -2960,8 +2959,10 @@ Handle Object::SetDataProperty(LookupIterator* it, // 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 @@ MaybeHandle Object::AddDataProperty(LookupIterator* it, // 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 @@ MaybeHandle JSObject::SetOwnPropertyIgnoreAttributes( !Name::Equals(it.isolate()->factory()->prototype_string(), name) || !Handle::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 @@ MaybeHandle JSObject::SetOwnPropertyIgnoreAttributes( 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 @@ MaybeHandle JSObject::SetOwnPropertyIgnoreAttributes( 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 @@ MaybeHandle JSObject::SetOwnPropertyIgnoreAttributes( 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 @@ MaybeHandle JSObject::DeleteElement(Handle object, if (!maybe.has_value) return MaybeHandle(); if (!maybe.value) { Handle 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 @@ MaybeHandle JSObject::DeleteProperty(Handle object, 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 @@ MaybeHandle JSObject::PreventExtensions(Handle object) { DCHECK(!object->map()->is_extensible()); if (object->map()->is_observed()) { - EnqueueChangeRecord(object, "preventExtensions", Handle(), - isolate->factory()->the_hole_value()); + RETURN_ON_EXCEPTION( + isolate, + EnqueueChangeRecord(object, "preventExtensions", Handle(), + isolate->factory()->the_hole_value()), + Object); } return object; } @@ -6168,7 +6190,8 @@ MaybeHandle JSObject::DefineAccessor(Handle object, 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 @@ MaybeHandle JSArray::SetElementsLength( // 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 @@ MaybeHandle JSObject::SetElement(Handle object, CHECK(new_length_handle->ToArrayIndex(&new_length)); BeginPerformSplice(Handle::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::cast(object)); Handle deleted = isolate->factory()->NewJSArray(0); EnqueueSpliceRecord(Handle::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 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); } } diff --git a/src/objects.h b/src/objects.h index a0741cc..6937557 100644 --- a/src/objects.h +++ b/src/objects.h @@ -1130,8 +1130,8 @@ class Object { StorePropertyMode data_store_mode = NORMAL_PROPERTY); MUST_USE_RESULT static MaybeHandle WriteToReadOnlyProperty( LookupIterator* it, Handle value, StrictMode strict_mode); - static Handle SetDataProperty(LookupIterator* it, - Handle value); + MUST_USE_RESULT static MaybeHandle SetDataProperty( + LookupIterator* it, Handle value); MUST_USE_RESULT static MaybeHandle AddDataProperty( LookupIterator* it, Handle value, PropertyAttributes attributes, StrictMode strict_mode, StoreFromKeyed store_mode); @@ -2215,10 +2215,9 @@ class JSObject: public JSReceiver { Context* GetCreationContext(); // Enqueue change record for Object.observe. May cause GC. - static void EnqueueChangeRecord(Handle object, - const char* type, - Handle name, - Handle old_value); + MUST_USE_RESULT static MaybeHandle EnqueueChangeRecord( + Handle object, const char* type, Handle name, + Handle old_value); private: friend class DictionaryElementsAccessor; diff --git a/src/runtime/runtime-function.cc b/src/runtime/runtime-function.cc index dfd9835..a720f81 100644 --- a/src/runtime/runtime-function.cc +++ b/src/runtime/runtime-function.cc @@ -201,7 +201,8 @@ RUNTIME_FUNCTION(Runtime_FunctionSetPrototype) { 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 } diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc index 3868011..b3e0b25 100644 --- a/src/runtime/runtime-object.cc +++ b/src/runtime/runtime-object.cc @@ -362,8 +362,10 @@ RUNTIME_FUNCTION(Runtime_SetPrototype) { Handle 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; } diff --git a/test/mjsunit/regress/regress-417709a.js b/test/mjsunit/regress/regress-417709a.js new file mode 100644 index 0000000..d210c10 --- /dev/null +++ b/test/mjsunit/regress/regress-417709a.js @@ -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);