Chromium Code Reviews| Index: src/execution.cc |
| diff --git a/src/execution.cc b/src/execution.cc |
| index 2e164139c801e91a01c417a9e0b88dd0a60b8f50..b41c35d51e3245a5a2eefe2099d6f5341421af05 100644 |
| --- a/src/execution.cc |
| +++ b/src/execution.cc |
| @@ -36,12 +36,12 @@ void StackGuard::reset_limits(const ExecutionAccess& lock) { |
| } |
| -static Handle<Object> Invoke(bool is_construct, |
| - Handle<JSFunction> function, |
| - Handle<Object> receiver, |
| - int argc, |
| - Handle<Object> args[], |
| - bool* has_pending_exception) { |
| +MUST_USE_RESULT static MaybeHandle<Object> Invoke( |
| + bool is_construct, |
| + Handle<JSFunction> function, |
| + Handle<Object> receiver, |
| + int argc, |
| + Handle<Object> args[]) { |
| Isolate* isolate = function->GetIsolate(); |
| // Entering JavaScript. |
| @@ -49,9 +49,8 @@ static Handle<Object> Invoke(bool is_construct, |
| CHECK(AllowJavascriptExecution::IsAllowed(isolate)); |
| if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) { |
| isolate->ThrowIllegalOperation(); |
| - *has_pending_exception = true; |
| isolate->ReportPendingMessages(); |
| - return Handle<Object>(); |
| + return MaybeHandle<Object>(); |
| } |
| // Placeholder for return value. |
| @@ -100,9 +99,9 @@ static Handle<Object> Invoke(bool is_construct, |
| #endif |
| // Update the pending exception flag and return the value. |
| - *has_pending_exception = value->IsException(); |
| - ASSERT(*has_pending_exception == isolate->has_pending_exception()); |
| - if (*has_pending_exception) { |
| + bool has_exception = value->IsException(); |
| + ASSERT(has_exception == isolate->has_pending_exception()); |
| + if (has_exception) { |
| isolate->ReportPendingMessages(); |
| #ifdef ENABLE_DEBUGGER_SUPPORT |
| // Reset stepping state when script exits with uncaught exception. |
| @@ -110,7 +109,7 @@ static Handle<Object> Invoke(bool is_construct, |
| isolate->debug()->ClearStepping(); |
| } |
| #endif // ENABLE_DEBUGGER_SUPPORT |
| - return Handle<Object>(); |
| + return MaybeHandle<Object>(); |
| } else { |
| isolate->clear_pending_message(); |
| } |
| @@ -119,18 +118,15 @@ static Handle<Object> Invoke(bool is_construct, |
| } |
| -Handle<Object> Execution::Call(Isolate* isolate, |
| - Handle<Object> callable, |
| - Handle<Object> receiver, |
| - int argc, |
| - Handle<Object> argv[], |
| - bool* pending_exception, |
| - bool convert_receiver) { |
| - *pending_exception = false; |
| - |
| +MaybeHandle<Object> Execution::Call(Isolate* isolate, |
| + Handle<Object> callable, |
| + Handle<Object> receiver, |
| + int argc, |
| + Handle<Object> argv[], |
| + bool convert_receiver) { |
| if (!callable->IsJSFunction()) { |
| - callable = TryGetFunctionDelegate(isolate, callable, pending_exception); |
| - if (*pending_exception) return callable; |
| + ASSIGN_RETURN_ON_EXCEPTION( |
| + isolate, callable, TryGetFunctionDelegate(isolate, callable), Object); |
| } |
| Handle<JSFunction> func = Handle<JSFunction>::cast(callable); |
| @@ -147,29 +143,27 @@ Handle<Object> Execution::Call(Isolate* isolate, |
| receiver = Handle<Object>(global, func->GetIsolate()); |
| } |
| } else { |
| - receiver = ToObject(isolate, receiver, pending_exception); |
| + ASSIGN_RETURN_ON_EXCEPTION( |
| + isolate, receiver, ToObject(isolate, receiver), Object); |
| } |
| - if (*pending_exception) return callable; |
| } |
| - return Invoke(false, func, receiver, argc, argv, pending_exception); |
| + return Invoke(false, func, receiver, argc, argv); |
| } |
| -Handle<Object> Execution::New(Handle<JSFunction> func, |
| - int argc, |
| - Handle<Object> argv[], |
| - bool* pending_exception) { |
| - return Invoke(true, func, func->GetIsolate()->global_object(), argc, argv, |
| - pending_exception); |
| +MaybeHandle<Object> Execution::New(Handle<JSFunction> func, |
| + int argc, |
| + Handle<Object> argv[]) { |
| + return Invoke(true, func, func->GetIsolate()->global_object(), argc, argv); |
| } |
| -Handle<Object> Execution::TryCall(Handle<JSFunction> func, |
| - Handle<Object> receiver, |
| - int argc, |
| - Handle<Object> args[], |
| - bool* caught_exception) { |
| +MaybeHandle<Object> Execution::TryCall(Handle<JSFunction> func, |
| + Handle<Object> receiver, |
| + int argc, |
| + Handle<Object> args[], |
| + Handle<Object>* exception_out) { |
|
Igor Sheludko
2014/04/11 09:30:03
Good idea!
|
| // Enter a try-block while executing the JavaScript code. To avoid |
| // duplicate error printing it must be non-verbose. Also, to avoid |
| // creating message objects during stack overflow we shouldn't |
| @@ -177,30 +171,30 @@ Handle<Object> Execution::TryCall(Handle<JSFunction> func, |
| v8::TryCatch catcher; |
| catcher.SetVerbose(false); |
| catcher.SetCaptureMessage(false); |
| - *caught_exception = false; |
| // Get isolate now, because handle might be persistent |
| // and get destroyed in the next call. |
| Isolate* isolate = func->GetIsolate(); |
| - Handle<Object> result = Invoke(false, func, receiver, argc, args, |
| - caught_exception); |
| + MaybeHandle<Object> maybe_result = Invoke(false, func, receiver, argc, args); |
| - if (*caught_exception) { |
| + if (maybe_result.is_null()) { |
| ASSERT(catcher.HasCaught()); |
| ASSERT(isolate->has_pending_exception()); |
| ASSERT(isolate->external_caught_exception()); |
| - if (isolate->pending_exception() == |
| - isolate->heap()->termination_exception()) { |
| - result = isolate->factory()->termination_exception(); |
| - } else { |
| - result = v8::Utils::OpenHandle(*catcher.Exception()); |
| + if (exception_out != NULL) { |
| + if (isolate->pending_exception() == |
| + isolate->heap()->termination_exception()) { |
| + *exception_out = isolate->factory()->termination_exception(); |
| + } else { |
| + *exception_out = v8::Utils::OpenHandle(*catcher.Exception()); |
| + } |
| } |
| isolate->OptionalRescheduleException(true); |
| } |
| ASSERT(!isolate->has_pending_exception()); |
| ASSERT(!isolate->external_caught_exception()); |
| - return result; |
| + return maybe_result; |
| } |
| @@ -231,9 +225,8 @@ Handle<Object> Execution::GetFunctionDelegate(Isolate* isolate, |
| } |
| -Handle<Object> Execution::TryGetFunctionDelegate(Isolate* isolate, |
| - Handle<Object> object, |
| - bool* has_pending_exception) { |
| +MaybeHandle<Object> Execution::TryGetFunctionDelegate(Isolate* isolate, |
| + Handle<Object> object) { |
| ASSERT(!object->IsJSFunction()); |
| // If object is a function proxy, get its handler. Iterate if necessary. |
| @@ -255,10 +248,8 @@ Handle<Object> Execution::TryGetFunctionDelegate(Isolate* isolate, |
| // throw a non-callable exception. |
| i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError( |
| "called_non_callable", i::HandleVector<i::Object>(&object, 1)); |
| - isolate->Throw(*error_obj); |
| - *has_pending_exception = true; |
| - return isolate->factory()->undefined_value(); |
| + return isolate->Throw<Object>(error_obj); |
| } |
| @@ -288,10 +279,8 @@ Handle<Object> Execution::GetConstructorDelegate(Isolate* isolate, |
| } |
| -Handle<Object> Execution::TryGetConstructorDelegate( |
| - Isolate* isolate, |
| - Handle<Object> object, |
| - bool* has_pending_exception) { |
| +MaybeHandle<Object> Execution::TryGetConstructorDelegate( |
| + Isolate* isolate, Handle<Object> object) { |
| ASSERT(!object->IsJSFunction()); |
| // If you return a function from here, it will be called when an |
| @@ -316,38 +305,29 @@ Handle<Object> Execution::TryGetConstructorDelegate( |
| // throw a non-callable exception. |
| i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError( |
| "called_non_callable", i::HandleVector<i::Object>(&object, 1)); |
| - isolate->Throw(*error_obj); |
| - *has_pending_exception = true; |
| - |
| - return isolate->factory()->undefined_value(); |
| + return isolate->Throw<Object>(error_obj); |
| } |
| void Execution::RunMicrotasks(Isolate* isolate) { |
| ASSERT(isolate->microtask_pending()); |
| - bool threw = false; |
| Execution::Call( |
| isolate, |
| isolate->run_microtasks(), |
| isolate->factory()->undefined_value(), |
| 0, |
| - NULL, |
| - &threw); |
| - ASSERT(!threw); |
| + NULL).Assert(); |
| } |
| void Execution::EnqueueMicrotask(Isolate* isolate, Handle<Object> microtask) { |
| - bool threw = false; |
| Handle<Object> args[] = { microtask }; |
| Execution::Call( |
| isolate, |
| isolate->enqueue_external_microtask(), |
| isolate->factory()->undefined_value(), |
| 1, |
| - args, |
| - &threw); |
| - ASSERT(!threw); |
| + args).Assert(); |
| } |
| @@ -665,78 +645,78 @@ void StackGuard::InitThread(const ExecutionAccess& lock) { |
| // --- C a l l s t o n a t i v e s --- |
| -#define RETURN_NATIVE_CALL(name, args, has_pending_exception) \ |
| +#define RETURN_NATIVE_CALL(name, args) \ |
| do { \ |
| Handle<Object> argv[] = args; \ |
| - ASSERT(has_pending_exception != NULL); \ |
| return Call(isolate, \ |
| isolate->name##_fun(), \ |
| isolate->js_builtins_object(), \ |
| - ARRAY_SIZE(argv), argv, \ |
| - has_pending_exception); \ |
| + ARRAY_SIZE(argv), argv); \ |
| } while (false) |
| -Handle<Object> Execution::ToNumber( |
| - Isolate* isolate, Handle<Object> obj, bool* exc) { |
| - RETURN_NATIVE_CALL(to_number, { obj }, exc); |
| +MaybeHandle<Object> Execution::ToNumber( |
| + Isolate* isolate, Handle<Object> obj) { |
| + RETURN_NATIVE_CALL(to_number, { obj }); |
| } |
| -Handle<Object> Execution::ToString( |
| - Isolate* isolate, Handle<Object> obj, bool* exc) { |
| - RETURN_NATIVE_CALL(to_string, { obj }, exc); |
| +MaybeHandle<Object> Execution::ToString( |
| + Isolate* isolate, Handle<Object> obj) { |
| + RETURN_NATIVE_CALL(to_string, { obj }); |
| } |
| -Handle<Object> Execution::ToDetailString( |
| - Isolate* isolate, Handle<Object> obj, bool* exc) { |
| - RETURN_NATIVE_CALL(to_detail_string, { obj }, exc); |
| +MaybeHandle<Object> Execution::ToDetailString( |
| + Isolate* isolate, Handle<Object> obj) { |
| + RETURN_NATIVE_CALL(to_detail_string, { obj }); |
| } |
| -Handle<Object> Execution::ToObject( |
| - Isolate* isolate, Handle<Object> obj, bool* exc) { |
| +MaybeHandle<Object> Execution::ToObject( |
| + Isolate* isolate, Handle<Object> obj) { |
| if (obj->IsSpecObject()) return obj; |
| - RETURN_NATIVE_CALL(to_object, { obj }, exc); |
| + RETURN_NATIVE_CALL(to_object, { obj }); |
| } |
| -Handle<Object> Execution::ToInteger( |
| - Isolate* isolate, Handle<Object> obj, bool* exc) { |
| - RETURN_NATIVE_CALL(to_integer, { obj }, exc); |
| +MaybeHandle<Object> Execution::ToInteger( |
| + Isolate* isolate, Handle<Object> obj) { |
| + RETURN_NATIVE_CALL(to_integer, { obj }); |
| } |
| -Handle<Object> Execution::ToUint32( |
| - Isolate* isolate, Handle<Object> obj, bool* exc) { |
| - RETURN_NATIVE_CALL(to_uint32, { obj }, exc); |
| +MaybeHandle<Object> Execution::ToUint32( |
| + Isolate* isolate, Handle<Object> obj) { |
| + RETURN_NATIVE_CALL(to_uint32, { obj }); |
| } |
| -Handle<Object> Execution::ToInt32( |
| - Isolate* isolate, Handle<Object> obj, bool* exc) { |
| - RETURN_NATIVE_CALL(to_int32, { obj }, exc); |
| +MaybeHandle<Object> Execution::ToInt32( |
| + Isolate* isolate, Handle<Object> obj) { |
| + RETURN_NATIVE_CALL(to_int32, { obj }); |
| } |
| -Handle<Object> Execution::NewDate(Isolate* isolate, double time, bool* exc) { |
| +MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) { |
| Handle<Object> time_obj = isolate->factory()->NewNumber(time); |
| - RETURN_NATIVE_CALL(create_date, { time_obj }, exc); |
| + RETURN_NATIVE_CALL(create_date, { time_obj }); |
| } |
| #undef RETURN_NATIVE_CALL |
| -Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern, |
| - Handle<String> flags, |
| - bool* exc) { |
| +MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern, |
| + Handle<String> flags) { |
| + Isolate* isolate = pattern->GetIsolate(); |
| Handle<JSFunction> function = Handle<JSFunction>( |
| - pattern->GetIsolate()->native_context()->regexp_function()); |
| - Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral( |
| - function, pattern, flags, exc); |
| - if (*exc) return Handle<JSRegExp>(); |
| + isolate->native_context()->regexp_function()); |
| + Handle<Object> re_obj; |
| + ASSIGN_RETURN_ON_EXCEPTION( |
| + isolate, re_obj, |
| + RegExpImpl::CreateRegExpLiteral(function, pattern, flags), |
| + JSRegExp); |
| return Handle<JSRegExp>::cast(re_obj); |
| } |
| @@ -756,24 +736,22 @@ Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) { |
| return factory->undefined_value(); |
| } |
| - bool caught_exception; |
| Handle<Object> index_object = factory->NewNumberFromInt(int_index); |
| Handle<Object> index_arg[] = { index_object }; |
| - Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at), |
| - string, |
| - ARRAY_SIZE(index_arg), |
| - index_arg, |
| - &caught_exception); |
| - if (caught_exception) { |
| - return factory->undefined_value(); |
| - } |
| + Handle<Object> result; |
| + ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| + isolate, result, |
| + TryCall(Handle<JSFunction>::cast(char_at), |
| + string, |
| + ARRAY_SIZE(index_arg), |
| + index_arg), |
| + factory->undefined_value()); |
| return result; |
| } |
| -Handle<JSFunction> Execution::InstantiateFunction( |
| - Handle<FunctionTemplateInfo> data, |
| - bool* exc) { |
| +MaybeHandle<JSFunction> Execution::InstantiateFunction( |
| + Handle<FunctionTemplateInfo> data) { |
| Isolate* isolate = data->GetIsolate(); |
| if (!data->do_not_cache()) { |
| // Fast case: see if the function has already been instantiated |
| @@ -785,62 +763,57 @@ Handle<JSFunction> Execution::InstantiateFunction( |
| } |
| // The function has not yet been instantiated in this context; do it. |
| Handle<Object> args[] = { data }; |
| - Handle<Object> result = Call(isolate, |
| - isolate->instantiate_fun(), |
| - isolate->js_builtins_object(), |
| - ARRAY_SIZE(args), |
| - args, |
| - exc); |
| - if (*exc) return Handle<JSFunction>::null(); |
| + Handle<Object> result; |
| + ASSIGN_RETURN_ON_EXCEPTION( |
| + isolate, result, |
| + Call(isolate, |
| + isolate->instantiate_fun(), |
| + isolate->js_builtins_object(), |
| + ARRAY_SIZE(args), |
| + args), |
| + JSFunction); |
| return Handle<JSFunction>::cast(result); |
| } |
| -Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data, |
| - bool* exc) { |
| +MaybeHandle<JSObject> Execution::InstantiateObject( |
| + Handle<ObjectTemplateInfo> data) { |
| Isolate* isolate = data->GetIsolate(); |
| + Handle<Object> result; |
| if (data->property_list()->IsUndefined() && |
| !data->constructor()->IsUndefined()) { |
| - // Initialization to make gcc happy. |
| - Object* result = NULL; |
| - { |
| - HandleScope scope(isolate); |
| - Handle<FunctionTemplateInfo> cons_template = |
| - Handle<FunctionTemplateInfo>( |
| - FunctionTemplateInfo::cast(data->constructor())); |
| - Handle<JSFunction> cons = InstantiateFunction(cons_template, exc); |
| - if (*exc) return Handle<JSObject>::null(); |
| - Handle<Object> value = New(cons, 0, NULL, exc); |
| - if (*exc) return Handle<JSObject>::null(); |
| - result = *value; |
| - } |
| - ASSERT(!*exc); |
| - return Handle<JSObject>(JSObject::cast(result)); |
| + Handle<FunctionTemplateInfo> cons_template = |
| + Handle<FunctionTemplateInfo>( |
| + FunctionTemplateInfo::cast(data->constructor())); |
| + Handle<JSFunction> cons; |
| + ASSIGN_RETURN_ON_EXCEPTION( |
| + isolate, cons, InstantiateFunction(cons_template), JSObject); |
| + ASSIGN_RETURN_ON_EXCEPTION(isolate, result, New(cons, 0, NULL), JSObject); |
| } else { |
| Handle<Object> args[] = { data }; |
| - Handle<Object> result = Call(isolate, |
| - isolate->instantiate_fun(), |
| - isolate->js_builtins_object(), |
| - ARRAY_SIZE(args), |
| - args, |
| - exc); |
| - if (*exc) return Handle<JSObject>::null(); |
| - return Handle<JSObject>::cast(result); |
| + ASSIGN_RETURN_ON_EXCEPTION( |
| + isolate, result, |
| + Call(isolate, |
| + isolate->instantiate_fun(), |
| + isolate->js_builtins_object(), |
| + ARRAY_SIZE(args), |
| + args), |
| + JSObject); |
| } |
| + return Handle<JSObject>::cast(result); |
| } |
| -void Execution::ConfigureInstance(Isolate* isolate, |
| - Handle<Object> instance, |
| - Handle<Object> instance_template, |
| - bool* exc) { |
| +MaybeHandle<Object> Execution::ConfigureInstance( |
| + Isolate* isolate, |
| + Handle<Object> instance, |
| + Handle<Object> instance_template) { |
| Handle<Object> args[] = { instance, instance_template }; |
| - Execution::Call(isolate, |
| - isolate->configure_instance_fun(), |
| - isolate->js_builtins_object(), |
| - ARRAY_SIZE(args), |
| - args, |
| - exc); |
| + return Execution::Call(isolate, |
| + isolate->configure_instance_fun(), |
| + isolate->js_builtins_object(), |
| + ARRAY_SIZE(args), |
| + args); |
| } |
| @@ -850,14 +823,14 @@ Handle<String> Execution::GetStackTraceLine(Handle<Object> recv, |
| Handle<Object> is_global) { |
| Isolate* isolate = fun->GetIsolate(); |
| Handle<Object> args[] = { recv, fun, pos, is_global }; |
| - bool caught_exception; |
| - Handle<Object> result = TryCall(isolate->get_stack_trace_line_fun(), |
| - isolate->js_builtins_object(), |
| - ARRAY_SIZE(args), |
| - args, |
| - &caught_exception); |
| - if (caught_exception || !result->IsString()) { |
| - return isolate->factory()->empty_string(); |
| + MaybeHandle<Object> maybe_result = |
| + TryCall(isolate->get_stack_trace_line_fun(), |
| + isolate->js_builtins_object(), |
| + ARRAY_SIZE(args), |
| + args); |
| + Handle<Object> result; |
| + if (!maybe_result.ToHandle(&result) || !result->IsString()) { |
| + return isolate->factory()->empty_string(); |
| } |
| return Handle<String>::cast(result); |