Commit 0389df51 authored by jochen's avatar jochen Committed by Commit bot

Assert that context creation doesn't throw

Instead, it is supposed to just return an empty context if it failed.
Also don't invoke interceptors (we don't for the parts that deserialize
from the snapshot anyways).

BUG=v8:5830
R=yangguo@chromium.org

Review-Url: https://codereview.chromium.org/2636903002
Cr-Commit-Position: refs/heads/master@{#42404}
parent bb71555e
...@@ -151,6 +151,10 @@ namespace v8 { ...@@ -151,6 +151,10 @@ namespace v8 {
PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \ PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \
false, i::HandleScope, false) false, i::HandleScope, false)
#define ENTER_V8_FOR_NEW_CONTEXT(isolate) \
i::VMState<v8::OTHER> __state__((isolate)); \
i::DisallowExceptions __no_exceptions__((isolate))
#define EXCEPTION_BAILOUT_CHECK_SCOPED(isolate, value) \ #define EXCEPTION_BAILOUT_CHECK_SCOPED(isolate, value) \
do { \ do { \
if (has_pending_exception) { \ if (has_pending_exception) { \
...@@ -6203,12 +6207,15 @@ static i::Handle<ObjectType> CreateEnvironment( ...@@ -6203,12 +6207,15 @@ static i::Handle<ObjectType> CreateEnvironment(
v8::DeserializeInternalFieldsCallback internal_fields_deserializer) { v8::DeserializeInternalFieldsCallback internal_fields_deserializer) {
i::Handle<ObjectType> result; i::Handle<ObjectType> result;
// Enter V8 via an ENTER_V8 scope.
{ {
ENTER_V8(isolate); ENTER_V8_FOR_NEW_CONTEXT(isolate);
v8::Local<ObjectTemplate> proxy_template; v8::Local<ObjectTemplate> proxy_template;
i::Handle<i::FunctionTemplateInfo> proxy_constructor; i::Handle<i::FunctionTemplateInfo> proxy_constructor;
i::Handle<i::FunctionTemplateInfo> global_constructor; i::Handle<i::FunctionTemplateInfo> global_constructor;
i::Handle<i::Object> named_interceptor(
isolate->factory()->undefined_value());
i::Handle<i::Object> indexed_interceptor(
isolate->factory()->undefined_value());
if (!maybe_global_template.IsEmpty()) { if (!maybe_global_template.IsEmpty()) {
v8::Local<v8::ObjectTemplate> global_template = v8::Local<v8::ObjectTemplate> global_template =
...@@ -6241,6 +6248,24 @@ static i::Handle<ObjectType> CreateEnvironment( ...@@ -6241,6 +6248,24 @@ static i::Handle<ObjectType> CreateEnvironment(
global_constructor->set_access_check_info( global_constructor->set_access_check_info(
isolate->heap()->undefined_value()); isolate->heap()->undefined_value());
} }
// Same for other interceptors. If the global constructor has
// interceptors, we need to replace them temporarily with noop
// interceptors, so the map is correctly marked as having interceptors,
// but we don't invoke any.
if (!global_constructor->named_property_handler()->IsUndefined(isolate)) {
named_interceptor =
handle(global_constructor->named_property_handler(), isolate);
global_constructor->set_named_property_handler(
isolate->heap()->noop_interceptor_info());
}
if (!global_constructor->indexed_property_handler()->IsUndefined(
isolate)) {
indexed_interceptor =
handle(global_constructor->indexed_property_handler(), isolate);
global_constructor->set_indexed_property_handler(
isolate->heap()->noop_interceptor_info());
}
} }
i::MaybeHandle<i::JSGlobalProxy> maybe_proxy; i::MaybeHandle<i::JSGlobalProxy> maybe_proxy;
...@@ -6254,7 +6279,7 @@ static i::Handle<ObjectType> CreateEnvironment( ...@@ -6254,7 +6279,7 @@ static i::Handle<ObjectType> CreateEnvironment(
invoke.Invoke(isolate, maybe_proxy, proxy_template, extensions, invoke.Invoke(isolate, maybe_proxy, proxy_template, extensions,
context_snapshot_index, internal_fields_deserializer); context_snapshot_index, internal_fields_deserializer);
// Restore the access check info on the global template. // Restore the access check info and interceptors on the global template.
if (!maybe_global_template.IsEmpty()) { if (!maybe_global_template.IsEmpty()) {
DCHECK(!global_constructor.is_null()); DCHECK(!global_constructor.is_null());
DCHECK(!proxy_constructor.is_null()); DCHECK(!proxy_constructor.is_null());
...@@ -6262,6 +6287,8 @@ static i::Handle<ObjectType> CreateEnvironment( ...@@ -6262,6 +6287,8 @@ static i::Handle<ObjectType> CreateEnvironment(
proxy_constructor->access_check_info()); proxy_constructor->access_check_info());
global_constructor->set_needs_access_check( global_constructor->set_needs_access_check(
proxy_constructor->needs_access_check()); proxy_constructor->needs_access_check());
global_constructor->set_named_property_handler(*named_interceptor);
global_constructor->set_indexed_property_handler(*indexed_interceptor);
} }
} }
// Leave V8. // Leave V8.
......
...@@ -155,6 +155,8 @@ template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, false>; ...@@ -155,6 +155,8 @@ template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, false>;
template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, true>; template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, true>;
template class PerIsolateAssertScope<COMPILATION_ASSERT, false>; template class PerIsolateAssertScope<COMPILATION_ASSERT, false>;
template class PerIsolateAssertScope<COMPILATION_ASSERT, true>; template class PerIsolateAssertScope<COMPILATION_ASSERT, true>;
template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, false>;
template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, true>;
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -26,12 +26,12 @@ enum PerThreadAssertType { ...@@ -26,12 +26,12 @@ enum PerThreadAssertType {
LAST_PER_THREAD_ASSERT_TYPE LAST_PER_THREAD_ASSERT_TYPE
}; };
enum PerIsolateAssertType { enum PerIsolateAssertType {
JAVASCRIPT_EXECUTION_ASSERT, JAVASCRIPT_EXECUTION_ASSERT,
JAVASCRIPT_EXECUTION_THROWS, JAVASCRIPT_EXECUTION_THROWS,
DEOPTIMIZATION_ASSERT, DEOPTIMIZATION_ASSERT,
COMPILATION_ASSERT COMPILATION_ASSERT,
NO_EXCEPTION_ASSERT
}; };
template <PerThreadAssertType kType, bool kAllow> template <PerThreadAssertType kType, bool kAllow>
...@@ -150,6 +150,14 @@ typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false> ...@@ -150,6 +150,14 @@ typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>
typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true> typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>
AllowJavascriptExecution; AllowJavascriptExecution;
// Scope to document where we do not expect javascript execution (debug only)
typedef PerIsolateAssertScopeDebugOnly<JAVASCRIPT_EXECUTION_ASSERT, false>
DisallowJavascriptExecutionDebugOnly;
// Scope to introduce an exception to DisallowJavascriptExecutionDebugOnly.
typedef PerIsolateAssertScopeDebugOnly<JAVASCRIPT_EXECUTION_ASSERT, true>
AllowJavascriptExecutionDebugOnly;
// Scope in which javascript execution leads to exception being thrown. // Scope in which javascript execution leads to exception being thrown.
typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false> typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>
ThrowOnJavascriptExecution; ThrowOnJavascriptExecution;
...@@ -173,6 +181,14 @@ typedef PerIsolateAssertScopeDebugOnly<COMPILATION_ASSERT, false> ...@@ -173,6 +181,14 @@ typedef PerIsolateAssertScopeDebugOnly<COMPILATION_ASSERT, false>
// Scope to introduce an exception to DisallowDeoptimization. // Scope to introduce an exception to DisallowDeoptimization.
typedef PerIsolateAssertScopeDebugOnly<COMPILATION_ASSERT, true> typedef PerIsolateAssertScopeDebugOnly<COMPILATION_ASSERT, true>
AllowCompilation; AllowCompilation;
// Scope to document where we do not expect exceptions.
typedef PerIsolateAssertScopeDebugOnly<NO_EXCEPTION_ASSERT, false>
DisallowExceptions;
// Scope to introduce an exception to DisallowExceptions.
typedef PerIsolateAssertScopeDebugOnly<NO_EXCEPTION_ASSERT, true>
AllowExceptions;
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -2996,12 +2996,16 @@ bool Bootstrapper::CompileNative(Isolate* isolate, Vector<const char> name, ...@@ -2996,12 +2996,16 @@ bool Bootstrapper::CompileNative(Isolate* isolate, Vector<const char> name,
// For non-extension scripts, run script to get the function wrapper. // For non-extension scripts, run script to get the function wrapper.
Handle<Object> wrapper; Handle<Object> wrapper;
if (!Execution::Call(isolate, fun, receiver, 0, NULL).ToHandle(&wrapper)) { if (!Execution::TryCall(isolate, fun, receiver, 0, nullptr,
Execution::MessageHandling::kKeepPending, nullptr)
.ToHandle(&wrapper)) {
return false; return false;
} }
// Then run the function wrapper. // Then run the function wrapper.
return !Execution::Call(isolate, Handle<JSFunction>::cast(wrapper), receiver, return !Execution::TryCall(isolate, Handle<JSFunction>::cast(wrapper),
argc, argv).is_null(); receiver, argc, argv,
Execution::MessageHandling::kKeepPending, nullptr)
.is_null();
} }
...@@ -3013,7 +3017,9 @@ bool Genesis::CallUtilsFunction(Isolate* isolate, const char* name) { ...@@ -3013,7 +3017,9 @@ bool Genesis::CallUtilsFunction(Isolate* isolate, const char* name) {
Handle<Object> fun = JSObject::GetDataProperty(utils, name_string); Handle<Object> fun = JSObject::GetDataProperty(utils, name_string);
Handle<Object> receiver = isolate->factory()->undefined_value(); Handle<Object> receiver = isolate->factory()->undefined_value();
Handle<Object> args[] = {utils}; Handle<Object> args[] = {utils};
return !Execution::Call(isolate, fun, receiver, 1, args).is_null(); return !Execution::TryCall(isolate, fun, receiver, 1, args,
Execution::MessageHandling::kKeepPending, nullptr)
.is_null();
} }
...@@ -3055,7 +3061,9 @@ bool Genesis::CompileExtension(Isolate* isolate, v8::Extension* extension) { ...@@ -3055,7 +3061,9 @@ bool Genesis::CompileExtension(Isolate* isolate, v8::Extension* extension) {
// Call function using either the runtime object or the global // Call function using either the runtime object or the global
// object as the receiver. Provide no parameters. // object as the receiver. Provide no parameters.
Handle<Object> receiver = isolate->global_object(); Handle<Object> receiver = isolate->global_object();
return !Execution::Call(isolate, fun, receiver, 0, NULL).is_null(); return !Execution::TryCall(isolate, fun, receiver, 0, nullptr,
Execution::MessageHandling::kKeepPending, nullptr)
.is_null();
} }
......
...@@ -1615,7 +1615,7 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript( ...@@ -1615,7 +1615,7 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
} }
if (result.is_null()) { if (result.is_null()) {
isolate->ReportPendingMessages(); if (natives != EXTENSION_CODE) isolate->ReportPendingMessages();
} else { } else {
isolate->debug()->OnAfterCompile(script); isolate->debug()->OnAfterCompile(script);
} }
......
...@@ -655,7 +655,10 @@ MaybeHandle<Object> Debug::CallFunction(const char* name, int argc, ...@@ -655,7 +655,10 @@ MaybeHandle<Object> Debug::CallFunction(const char* name, int argc,
Handle<JSFunction> fun = Handle<JSFunction>::cast( Handle<JSFunction> fun = Handle<JSFunction>::cast(
JSReceiver::GetProperty(isolate_, holder, name).ToHandleChecked()); JSReceiver::GetProperty(isolate_, holder, name).ToHandleChecked());
Handle<Object> undefined = isolate_->factory()->undefined_value(); Handle<Object> undefined = isolate_->factory()->undefined_value();
return Execution::TryCall(isolate_, fun, undefined, argc, args); MaybeHandle<Object> maybe_exception;
return Execution::TryCall(isolate_, fun, undefined, argc, args,
Execution::MessageHandling::kReport,
&maybe_exception);
} }
...@@ -2091,9 +2094,9 @@ void Debug::NotifyMessageHandler(v8::DebugEvent event, ...@@ -2091,9 +2094,9 @@ void Debug::NotifyMessageHandler(v8::DebugEvent event,
Handle<Object> answer_value; Handle<Object> answer_value;
Handle<String> answer; Handle<String> answer;
MaybeHandle<Object> maybe_exception; MaybeHandle<Object> maybe_exception;
MaybeHandle<Object> maybe_result = MaybeHandle<Object> maybe_result = Execution::TryCall(
Execution::TryCall(isolate_, process_debug_request, cmd_processor, 1, isolate_, process_debug_request, cmd_processor, 1, request_args,
request_args, &maybe_exception); Execution::MessageHandling::kReport, &maybe_exception);
if (maybe_result.ToHandle(&answer_value)) { if (maybe_result.ToHandle(&answer_value)) {
if (answer_value->IsUndefined(isolate_)) { if (answer_value->IsUndefined(isolate_)) {
...@@ -2491,8 +2494,10 @@ v8::Local<v8::String> MessageImpl::GetJSON() const { ...@@ -2491,8 +2494,10 @@ v8::Local<v8::String> MessageImpl::GetJSON() const {
return v8::Local<v8::String>(); return v8::Local<v8::String>();
} }
MaybeHandle<Object> maybe_json = MaybeHandle<Object> maybe_exception;
Execution::TryCall(isolate, fun, event_data_, 0, NULL); MaybeHandle<Object> maybe_json = Execution::TryCall(
isolate, fun, event_data_, 0, nullptr,
Execution::MessageHandling::kReport, &maybe_exception);
Handle<Object> json; Handle<Object> json;
if (!maybe_json.ToHandle(&json) || !json->IsString()) { if (!maybe_json.ToHandle(&json) || !json->IsString()) {
return v8::Local<v8::String>(); return v8::Local<v8::String>();
......
...@@ -54,11 +54,10 @@ static void PrintDeserializedCodeInfo(Handle<JSFunction> function) { ...@@ -54,11 +54,10 @@ static void PrintDeserializedCodeInfo(Handle<JSFunction> function) {
namespace { namespace {
MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct, MUST_USE_RESULT MaybeHandle<Object> Invoke(
Handle<Object> target, Isolate* isolate, bool is_construct, Handle<Object> target,
Handle<Object> receiver, int argc, Handle<Object> receiver, int argc, Handle<Object> args[],
Handle<Object> args[], Handle<Object> new_target, Execution::MessageHandling message_handling) {
Handle<Object> new_target) {
DCHECK(!receiver->IsJSGlobalObject()); DCHECK(!receiver->IsJSGlobalObject());
#ifdef USE_SIMULATOR #ifdef USE_SIMULATOR
...@@ -69,7 +68,9 @@ MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct, ...@@ -69,7 +68,9 @@ MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct,
StackLimitCheck check(isolate); StackLimitCheck check(isolate);
if (check.HasOverflowed()) { if (check.HasOverflowed()) {
isolate->StackOverflow(); isolate->StackOverflow();
isolate->ReportPendingMessages(); if (message_handling == Execution::MessageHandling::kReport) {
isolate->ReportPendingMessages();
}
return MaybeHandle<Object>(); return MaybeHandle<Object>();
} }
#endif #endif
...@@ -89,7 +90,9 @@ MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct, ...@@ -89,7 +90,9 @@ MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct,
bool has_exception = value.is_null(); bool has_exception = value.is_null();
DCHECK(has_exception == isolate->has_pending_exception()); DCHECK(has_exception == isolate->has_pending_exception());
if (has_exception) { if (has_exception) {
isolate->ReportPendingMessages(); if (message_handling == Execution::MessageHandling::kReport) {
isolate->ReportPendingMessages();
}
return MaybeHandle<Object>(); return MaybeHandle<Object>();
} else { } else {
isolate->clear_pending_message(); isolate->clear_pending_message();
...@@ -103,7 +106,9 @@ MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct, ...@@ -103,7 +106,9 @@ MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct,
CHECK(AllowJavascriptExecution::IsAllowed(isolate)); CHECK(AllowJavascriptExecution::IsAllowed(isolate));
if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) { if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) {
isolate->ThrowIllegalOperation(); isolate->ThrowIllegalOperation();
isolate->ReportPendingMessages(); if (message_handling == Execution::MessageHandling::kReport) {
isolate->ReportPendingMessages();
}
return MaybeHandle<Object>(); return MaybeHandle<Object>();
} }
...@@ -150,7 +155,9 @@ MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct, ...@@ -150,7 +155,9 @@ MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct,
bool has_exception = value->IsException(isolate); bool has_exception = value->IsException(isolate);
DCHECK(has_exception == isolate->has_pending_exception()); DCHECK(has_exception == isolate->has_pending_exception());
if (has_exception) { if (has_exception) {
isolate->ReportPendingMessages(); if (message_handling == Execution::MessageHandling::kReport) {
isolate->ReportPendingMessages();
}
return MaybeHandle<Object>(); return MaybeHandle<Object>();
} else { } else {
isolate->clear_pending_message(); isolate->clear_pending_message();
...@@ -159,13 +166,10 @@ MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct, ...@@ -159,13 +166,10 @@ MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct,
return Handle<Object>(value, isolate); return Handle<Object>(value, isolate);
} }
} // namespace MaybeHandle<Object> CallInternal(Isolate* isolate, Handle<Object> callable,
Handle<Object> receiver, int argc,
Handle<Object> argv[],
// static Execution::MessageHandling message_handling) {
MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
Handle<Object> receiver, int argc,
Handle<Object> argv[]) {
// Convert calls on global objects to be calls on the global // Convert calls on global objects to be calls on the global
// receiver instead to avoid having a 'this' pointer which refers // receiver instead to avoid having a 'this' pointer which refers
// directly to a global object. // directly to a global object.
...@@ -174,7 +178,17 @@ MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable, ...@@ -174,7 +178,17 @@ MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
handle(Handle<JSGlobalObject>::cast(receiver)->global_proxy(), isolate); handle(Handle<JSGlobalObject>::cast(receiver)->global_proxy(), isolate);
} }
return Invoke(isolate, false, callable, receiver, argc, argv, return Invoke(isolate, false, callable, receiver, argc, argv,
isolate->factory()->undefined_value()); isolate->factory()->undefined_value(), message_handling);
}
} // namespace
// static
MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
Handle<Object> receiver, int argc,
Handle<Object> argv[]) {
return CallInternal(isolate, callable, receiver, argc, argv,
MessageHandling::kReport);
} }
...@@ -190,18 +204,21 @@ MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor, ...@@ -190,18 +204,21 @@ MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor,
Handle<Object> new_target, int argc, Handle<Object> new_target, int argc,
Handle<Object> argv[]) { Handle<Object> argv[]) {
return Invoke(isolate, true, constructor, return Invoke(isolate, true, constructor,
isolate->factory()->undefined_value(), argc, argv, new_target); isolate->factory()->undefined_value(), argc, argv, new_target,
MessageHandling::kReport);
} }
MaybeHandle<Object> Execution::TryCall(Isolate* isolate, MaybeHandle<Object> Execution::TryCall(Isolate* isolate,
Handle<Object> callable, Handle<Object> callable,
Handle<Object> receiver, int argc, Handle<Object> receiver, int argc,
Handle<Object> args[], Handle<Object> args[],
MessageHandling message_handling,
MaybeHandle<Object>* exception_out) { MaybeHandle<Object>* exception_out) {
bool is_termination = false; bool is_termination = false;
MaybeHandle<Object> maybe_result; MaybeHandle<Object> maybe_result;
if (exception_out != NULL) *exception_out = MaybeHandle<Object>(); if (exception_out != NULL) *exception_out = MaybeHandle<Object>();
DCHECK_IMPLIES(message_handling == MessageHandling::kKeepPending,
exception_out == nullptr);
// Enter a try-block while executing the JavaScript code. To avoid // Enter a try-block while executing the JavaScript code. To avoid
// duplicate error printing it must be non-verbose. Also, to avoid // duplicate error printing it must be non-verbose. Also, to avoid
// creating message objects during stack overflow we shouldn't // creating message objects during stack overflow we shouldn't
...@@ -211,24 +228,25 @@ MaybeHandle<Object> Execution::TryCall(Isolate* isolate, ...@@ -211,24 +228,25 @@ MaybeHandle<Object> Execution::TryCall(Isolate* isolate,
catcher.SetVerbose(false); catcher.SetVerbose(false);
catcher.SetCaptureMessage(false); catcher.SetCaptureMessage(false);
maybe_result = Call(isolate, callable, receiver, argc, args); maybe_result =
CallInternal(isolate, callable, receiver, argc, args, message_handling);
if (maybe_result.is_null()) { if (maybe_result.is_null()) {
DCHECK(catcher.HasCaught());
DCHECK(isolate->has_pending_exception()); DCHECK(isolate->has_pending_exception());
DCHECK(isolate->external_caught_exception());
if (isolate->pending_exception() == if (isolate->pending_exception() ==
isolate->heap()->termination_exception()) { isolate->heap()->termination_exception()) {
is_termination = true; is_termination = true;
} else { } else {
if (exception_out != NULL) { if (exception_out != nullptr) {
DCHECK(catcher.HasCaught());
DCHECK(isolate->external_caught_exception());
*exception_out = v8::Utils::OpenHandle(*catcher.Exception()); *exception_out = v8::Utils::OpenHandle(*catcher.Exception());
} }
} }
isolate->OptionalRescheduleException(true); if (message_handling == MessageHandling::kReport) {
isolate->OptionalRescheduleException(true);
}
} }
DCHECK(!isolate->has_pending_exception());
} }
// Re-request terminate execution interrupt to trigger later. // Re-request terminate execution interrupt to trigger later.
......
...@@ -15,6 +15,9 @@ namespace internal { ...@@ -15,6 +15,9 @@ namespace internal {
class Execution final : public AllStatic { class Execution final : public AllStatic {
public: public:
// Whether to report pending messages, or keep them pending on the isolate.
enum class MessageHandling { kReport, kKeepPending };
// Call a function, the caller supplies a receiver and an array // Call a function, the caller supplies a receiver and an array
// of arguments. // of arguments.
// //
...@@ -36,16 +39,18 @@ class Execution final : public AllStatic { ...@@ -36,16 +39,18 @@ class Execution final : public AllStatic {
int argc, int argc,
Handle<Object> argv[]); Handle<Object> argv[]);
// Call a function, just like Call(), but make sure to silently catch // Call a function, just like Call(), but handle don't report exceptions
// any thrown exceptions. The return value is either the result of // externally.
// calling the function (if caught exception is false) or the exception // The return value is either the result of calling the function (if no
// that occurred (if caught exception is true). // exception occurred), or an empty handle.
// In the exception case, exception_out holds the caught exceptions, unless // If message_handling is MessageHandling::kReport, exceptions (except for
// it is a termination exception. // termination exceptions) will be stored in exception_out (if not a
// nullptr).
static MaybeHandle<Object> TryCall(Isolate* isolate, Handle<Object> callable, static MaybeHandle<Object> TryCall(Isolate* isolate, Handle<Object> callable,
Handle<Object> receiver, int argc, Handle<Object> receiver, int argc,
Handle<Object> argv[], Handle<Object> argv[],
MaybeHandle<Object>* exception_out = NULL); MessageHandling message_handling,
MaybeHandle<Object>* exception_out);
}; };
......
...@@ -2524,10 +2524,18 @@ AllocationResult Heap::AllocateTransitionArray(int capacity) { ...@@ -2524,10 +2524,18 @@ AllocationResult Heap::AllocateTransitionArray(int capacity) {
return array; return array;
} }
bool Heap::CreateApiObjects() {
void Heap::CreateApiObjects() {
HandleScope scope(isolate()); HandleScope scope(isolate());
set_message_listeners(*TemplateList::New(isolate(), 2)); set_message_listeners(*TemplateList::New(isolate(), 2));
HeapObject* obj = nullptr;
{
AllocationResult allocation = AllocateStruct(INTERCEPTOR_INFO_TYPE);
if (!allocation.To(&obj)) return false;
}
InterceptorInfo* info = InterceptorInfo::cast(obj);
info->set_flags(0);
set_noop_interceptor_info(info);
return true;
} }
...@@ -5581,7 +5589,7 @@ bool Heap::SetUp() { ...@@ -5581,7 +5589,7 @@ bool Heap::SetUp() {
bool Heap::CreateHeapObjects() { bool Heap::CreateHeapObjects() {
// Create initial maps. // Create initial maps.
if (!CreateInitialMaps()) return false; if (!CreateInitialMaps()) return false;
CreateApiObjects(); if (!CreateApiObjects()) return false;
// Create initial objects // Create initial objects
CreateInitialObjects(); CreateInitialObjects();
......
...@@ -216,6 +216,7 @@ using v8::MemoryPressureLevel; ...@@ -216,6 +216,7 @@ using v8::MemoryPressureLevel;
V(FixedArray, serialized_global_proxy_sizes, SerializedGlobalProxySizes) \ V(FixedArray, serialized_global_proxy_sizes, SerializedGlobalProxySizes) \
/* Configured values */ \ /* Configured values */ \
V(TemplateList, message_listeners, MessageListeners) \ V(TemplateList, message_listeners, MessageListeners) \
V(InterceptorInfo, noop_interceptor_info, NoOpInterceptorInfo) \
V(Code, js_entry_code, JsEntryCode) \ V(Code, js_entry_code, JsEntryCode) \
V(Code, js_construct_entry_code, JsConstructEntryCode) \ V(Code, js_construct_entry_code, JsConstructEntryCode) \
/* Oddball maps */ \ /* Oddball maps */ \
...@@ -838,7 +839,7 @@ class Heap { ...@@ -838,7 +839,7 @@ class Heap {
// Support for the API. // Support for the API.
// //
void CreateApiObjects(); bool CreateApiObjects();
// Implements the corresponding V8 API function. // Implements the corresponding V8 API function.
bool IdleNotification(double deadline_in_seconds); bool IdleNotification(double deadline_in_seconds);
......
...@@ -1694,6 +1694,8 @@ bool Isolate::IsExternalHandlerOnTop(Object* exception) { ...@@ -1694,6 +1694,8 @@ bool Isolate::IsExternalHandlerOnTop(Object* exception) {
void Isolate::ReportPendingMessages() { void Isolate::ReportPendingMessages() {
DCHECK(AllowExceptions::IsAllowed(this));
Object* exception = pending_exception(); Object* exception = pending_exception();
// Try to propagate the exception to an external v8::TryCatch handler. If // Try to propagate the exception to an external v8::TryCatch handler. If
...@@ -3317,8 +3319,9 @@ void Isolate::PromiseReactionJob(Handle<PromiseReactionJobInfo> info, ...@@ -3317,8 +3319,9 @@ void Isolate::PromiseReactionJob(Handle<PromiseReactionJobInfo> info,
handle(deferred_promise_arr->get(i), this), handle(deferred_promise_arr->get(i), this),
handle(deferred_on_resolve_arr->get(i), this), handle(deferred_on_resolve_arr->get(i), this),
handle(deferred_on_reject_arr->get(i), this)}; handle(deferred_on_reject_arr->get(i), this)};
*result = Execution::TryCall(this, promise_handle_fn, undefined, *result = Execution::TryCall(
arraysize(argv), argv, maybe_exception); this, promise_handle_fn, undefined, arraysize(argv), argv,
Execution::MessageHandling::kReport, maybe_exception);
// If execution is terminating, just bail out. // If execution is terminating, just bail out.
if (result->is_null() && maybe_exception->is_null()) { if (result->is_null() && maybe_exception->is_null()) {
return; return;
...@@ -3328,8 +3331,9 @@ void Isolate::PromiseReactionJob(Handle<PromiseReactionJobInfo> info, ...@@ -3328,8 +3331,9 @@ void Isolate::PromiseReactionJob(Handle<PromiseReactionJobInfo> info,
Handle<Object> argv[] = {value, tasks, deferred_promise, Handle<Object> argv[] = {value, tasks, deferred_promise,
handle(info->deferred_on_resolve(), this), handle(info->deferred_on_resolve(), this),
handle(info->deferred_on_reject(), this)}; handle(info->deferred_on_reject(), this)};
*result = Execution::TryCall(this, promise_handle_fn, undefined, *result = Execution::TryCall(
arraysize(argv), argv, maybe_exception); this, promise_handle_fn, undefined, arraysize(argv), argv,
Execution::MessageHandling::kReport, maybe_exception);
} }
} }
...@@ -3343,16 +3347,17 @@ void Isolate::PromiseResolveThenableJob( ...@@ -3343,16 +3347,17 @@ void Isolate::PromiseResolveThenableJob(
Handle<JSFunction> reject(info->reject(), this); Handle<JSFunction> reject(info->reject(), this);
Handle<JSReceiver> then(info->then(), this); Handle<JSReceiver> then(info->then(), this);
Handle<Object> argv[] = {resolve, reject}; Handle<Object> argv[] = {resolve, reject};
*result = Execution::TryCall(this, then, thenable, arraysize(argv), argv, *result =
maybe_exception); Execution::TryCall(this, then, thenable, arraysize(argv), argv,
Execution::MessageHandling::kReport, maybe_exception);
Handle<Object> reason; Handle<Object> reason;
if (maybe_exception->ToHandle(&reason)) { if (maybe_exception->ToHandle(&reason)) {
DCHECK(result->is_null()); DCHECK(result->is_null());
Handle<Object> reason_arg[] = {reason}; Handle<Object> reason_arg[] = {reason};
*result = *result = Execution::TryCall(
Execution::TryCall(this, reject, factory()->undefined_value(), this, reject, factory()->undefined_value(), arraysize(reason_arg),
arraysize(reason_arg), reason_arg, maybe_exception); reason_arg, Execution::MessageHandling::kReport, maybe_exception);
} }
} }
...@@ -3432,9 +3437,9 @@ void Isolate::RunMicrotasksInternal() { ...@@ -3432,9 +3437,9 @@ void Isolate::RunMicrotasksInternal() {
if (microtask->IsJSFunction()) { if (microtask->IsJSFunction()) {
Handle<JSFunction> microtask_function = Handle<JSFunction> microtask_function =
Handle<JSFunction>::cast(microtask); Handle<JSFunction>::cast(microtask);
result = Execution::TryCall(this, microtask_function, result = Execution::TryCall(
factory()->undefined_value(), 0, NULL, this, microtask_function, factory()->undefined_value(), 0,
&maybe_exception); nullptr, Execution::MessageHandling::kReport, &maybe_exception);
} else if (microtask->IsPromiseResolveThenableJobInfo()) { } else if (microtask->IsPromiseResolveThenableJobInfo()) {
PromiseResolveThenableJob( PromiseResolveThenableJob(
Handle<PromiseResolveThenableJobInfo>::cast(microtask), &result, Handle<PromiseResolveThenableJobInfo>::cast(microtask), &result,
......
...@@ -530,9 +530,11 @@ void InnerTryCallTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) { ...@@ -530,9 +530,11 @@ void InnerTryCallTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Local<v8::Function> loop = v8::Local<v8::Function>::Cast( v8::Local<v8::Function> loop = v8::Local<v8::Function>::Cast(
global->Get(CcTest::isolate()->GetCurrentContext(), v8_str("loop")) global->Get(CcTest::isolate()->GetCurrentContext(), v8_str("loop"))
.ToLocalChecked()); .ToLocalChecked());
i::MaybeHandle<i::Object> exception;
i::MaybeHandle<i::Object> result = i::MaybeHandle<i::Object> result =
i::Execution::TryCall(CcTest::i_isolate(), v8::Utils::OpenHandle((*loop)), i::Execution::TryCall(CcTest::i_isolate(), v8::Utils::OpenHandle((*loop)),
v8::Utils::OpenHandle((*global)), 0, NULL, NULL); v8::Utils::OpenHandle((*global)), 0, nullptr,
i::Execution::MessageHandling::kReport, &exception);
CHECK(result.is_null()); CHECK(result.is_null());
// TryCall ignores terminate execution, but rerequests the interrupt. // TryCall ignores terminate execution, but rerequests the interrupt.
CHECK(!args.GetIsolate()->IsExecutionTerminating()); CHECK(!args.GetIsolate()->IsExecutionTerminating());
......
...@@ -104,7 +104,8 @@ TEST(CollectDetailedWasmStack_ExplicitThrowFromJs) { ...@@ -104,7 +104,8 @@ TEST(CollectDetailedWasmStack_ExplicitThrowFromJs) {
MaybeHandle<Object> maybe_exc; MaybeHandle<Object> maybe_exc;
Handle<Object> args[] = {js_wasm_wrapper}; Handle<Object> args[] = {js_wasm_wrapper};
MaybeHandle<Object> returnObjMaybe = MaybeHandle<Object> returnObjMaybe =
Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc); Execution::TryCall(isolate, js_trampoline, global, 1, args,
Execution::MessageHandling::kReport, &maybe_exc);
CHECK(returnObjMaybe.is_null()); CHECK(returnObjMaybe.is_null());
// Line and column are 1-based, so add 1 for the expected wasm output. // Line and column are 1-based, so add 1 for the expected wasm output.
...@@ -145,7 +146,8 @@ TEST(CollectDetailedWasmStack_WasmError) { ...@@ -145,7 +146,8 @@ TEST(CollectDetailedWasmStack_WasmError) {
MaybeHandle<Object> maybe_exc; MaybeHandle<Object> maybe_exc;
Handle<Object> args[] = {js_wasm_wrapper}; Handle<Object> args[] = {js_wasm_wrapper};
MaybeHandle<Object> maybe_return_obj = MaybeHandle<Object> maybe_return_obj =
Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc); Execution::TryCall(isolate, js_trampoline, global, 1, args,
Execution::MessageHandling::kReport, &maybe_exc);
CHECK(maybe_return_obj.is_null()); CHECK(maybe_return_obj.is_null());
// Line and column are 1-based, so add 1 for the expected wasm output. // Line and column are 1-based, so add 1 for the expected wasm output.
......
...@@ -83,7 +83,8 @@ TEST(Unreachable) { ...@@ -83,7 +83,8 @@ TEST(Unreachable) {
MaybeHandle<Object> maybe_exc; MaybeHandle<Object> maybe_exc;
Handle<Object> args[] = {js_wasm_wrapper}; Handle<Object> args[] = {js_wasm_wrapper};
MaybeHandle<Object> returnObjMaybe = MaybeHandle<Object> returnObjMaybe =
Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc); Execution::TryCall(isolate, js_trampoline, global, 1, args,
Execution::MessageHandling::kReport, &maybe_exc);
CHECK(returnObjMaybe.is_null()); CHECK(returnObjMaybe.is_null());
// Line and column are 1-based, so add 1 for the expected wasm output. // Line and column are 1-based, so add 1 for the expected wasm output.
...@@ -124,7 +125,8 @@ TEST(IllegalLoad) { ...@@ -124,7 +125,8 @@ TEST(IllegalLoad) {
MaybeHandle<Object> maybe_exc; MaybeHandle<Object> maybe_exc;
Handle<Object> args[] = {js_wasm_wrapper}; Handle<Object> args[] = {js_wasm_wrapper};
MaybeHandle<Object> returnObjMaybe = MaybeHandle<Object> returnObjMaybe =
Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc); Execution::TryCall(isolate, js_trampoline, global, 1, args,
Execution::MessageHandling::kReport, &maybe_exc);
CHECK(returnObjMaybe.is_null()); CHECK(returnObjMaybe.is_null());
// Line and column are 1-based, so add 1 for the expected wasm output. // Line and column are 1-based, so add 1 for the expected wasm output.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment