Commit 36a22fe7 authored by Sathya Gunasekaran's avatar Sathya Gunasekaran Committed by Commit Bot

[debug] Add exception predictions to builtins where missing.

This fixes the catch predictions for the following builtins --
AsyncFunctionAwaitCaught
AsyncFunctionAwaitUncaught
PromiseResolveClosure
ResolvePromise
PromiseResolve

Added tests for each.

Added whitelist for builtins behind a flag.

BUG=chromium:691875

Change-Id: I816cafdb69f0c9f1eefc440a0a44c36713d0b7dc
Reviewed-on: https://chromium-review.googlesource.com/450894
Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43725}
parent fb147b0e
......@@ -2040,6 +2040,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(promise_fun, "resolve", Builtins::kPromiseResolve, 1,
true, DONT_ENUM);
isolate->builtins()->PromiseResolve()->set_is_promise_rejection(true);
SimpleInstallFunction(promise_fun, "reject", Builtins::kPromiseReject, 1,
true, DONT_ENUM);
......@@ -2075,6 +2076,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
function->shared()->set_native(false);
InstallWithIntrinsicDefaultProto(isolate, function,
Context::PROMISE_RESOLVE_INDEX);
isolate->builtins()->ResolvePromise()->set_is_promise_rejection(true);
}
{ // Internal: PromiseHandle
......@@ -2111,6 +2113,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Handle<Code> code =
handle(isolate->builtins()->builtin(Builtins::kPromiseResolveClosure),
isolate);
code->set_is_promise_rejection(true);
Handle<SharedFunctionInfo> info =
factory->NewSharedFunctionInfo(factory->empty_string(), code, false);
info->set_internal_formal_parameter_count(1);
......@@ -3537,6 +3540,8 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
Handle<JSFunction> function =
SimpleCreateFunction(isolate, factory->empty_string(),
Builtins::kAsyncFunctionAwaitCaught, 3, false);
isolate->builtins()->AsyncFunctionAwaitCaught()->set_is_promise_rejection(
true);
InstallWithIntrinsicDefaultProto(
isolate, function, Context::ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX);
}
......@@ -3545,6 +3550,9 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
Handle<JSFunction> function =
SimpleCreateFunction(isolate, factory->empty_string(),
Builtins::kAsyncFunctionAwaitUncaught, 3, false);
isolate->builtins()
->AsyncFunctionAwaitUncaught()
->set_is_promise_rejection(true);
InstallWithIntrinsicDefaultProto(
isolate, function, Context::ASYNC_FUNCTION_AWAIT_UNCAUGHT_INDEX);
}
......
......@@ -742,7 +742,7 @@ void PromiseBuiltinsAssembler::InternalResolvePromise(Node* context,
Goto(&reject);
Bind(&reject);
// Don't cause a debug event as this case is forwarding a rejection
// Don't cause a debug event as this case is forwarding a rejection.
InternalPromiseReject(context, promise, thenable_value, false);
PromiseSetHasHandler(result);
Goto(&out);
......@@ -825,7 +825,8 @@ void PromiseBuiltinsAssembler::InternalResolvePromise(Node* context,
// 9.a Return RejectPromise(promise, then.[[Value]]).
Bind(&if_rejectpromise);
{
InternalPromiseReject(context, promise, var_reason.value(), true);
// Don't cause a debug event as this case is forwarding a rejection.
InternalPromiseReject(context, promise, var_reason.value(), false);
Goto(&out);
}
......
......@@ -1351,6 +1351,9 @@ HandlerTable::CatchPrediction PredictException(JavaScriptFrame* frame) {
if (code->GetCode()->is_exception_caught()) {
return HandlerTable::CAUGHT;
}
// The built-in must be marked with an exception prediction.
UNREACHABLE();
}
if (code->kind() == AbstractCode::OPTIMIZED_FUNCTION) {
......
......@@ -26,6 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdlib.h>
#include <set>
#include "src/v8.h"
......@@ -6650,3 +6651,34 @@ TEST(DebugCoverage) {
CHECK_EQ(1, end.GetColumnNumber());
CHECK_EQ(2, function_data.Count());
}
TEST(BuiltinsExceptionPrediction) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope handle_scope(isolate);
v8::Context::New(isolate);
// TODO(gsathya): Fix catch prediction for the following.
std::set<int> whitelist({i::Builtins::kPromiseThenFinally,
i::Builtins::kPromiseCatchFinally,
i::Builtins::kAsyncFromSyncIteratorPrototypeNext,
i::Builtins::kAsyncFromSyncIteratorPrototypeThrow,
i::Builtins::kAsyncFromSyncIteratorPrototypeReturn});
i::Builtins* builtins = CcTest::i_isolate()->builtins();
bool fail = false;
for (int i = 0; i < i::Builtins::builtin_count; i++) {
Code* builtin = builtins->builtin(static_cast<i::Builtins::Name>(i));
if (i::HandlerTable::cast(builtin->handler_table())->length() == 0)
continue;
if (builtin->is_promise_rejection() || builtin->is_exception_caught())
continue;
if (whitelist.find(i) != whitelist.end()) continue;
fail = true;
i::PrintF("%s is missing exception predictions.\n", builtins->name(i));
}
CHECK(!fail);
}
// Copyright 2017 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.
Debug = debug.Debug
var exception = null;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Exception) return;
try {
var line = exec_state.frame(0).sourceLineText();
var match = /Exception/.exec(line);
assertNotNull(match);
} catch (e) {
exception = e;
}
}
// Caught throw, events on any exception.
Debug.setListener(listener);
Debug.setBreakOnException();
var thenable = {
get then() {
throw new Error(); // Exception
}
};
class MyPromise extends Promise {
get then() {
throw new Error();
}
}
MyPromise.resolve(thenable);
var p = Promise.resolve(thenable);
async function foo() {
return thenable;
}
foo();
async function foo() {
await thenable;
}
foo();
async function foo() {
try {
await thenable;
} catch (e) {}
}
foo();
%RunMicrotasks();
Debug.setListener(null);
Debug.clearBreakOnException();
assertNull(exception);
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