Skip to content

Commit

Permalink
deps: backport 91ddb65d from upstream V8
Browse files Browse the repository at this point in the history
Original commit message:

    Revert promises optimizations due to regressions in async hooks

    Revert "[async-await] Eliminate throwaway promise in async functions."

    This reverts commit a840f1f8f7e6c9ab32dec456a954612619855093.

    Revert "[async-generators] Also avoid throwaway promise here."

    This reverts commit feb545ceba5cb477ba883b46b60142f441ad5a3d.

    Revert "[async-await] Turn await closures into intrinsics."

    This reverts commit d97bb317386506a6798386b74647cbe0502fce35.

    Revert "[async-generators] Add fast-path for primitives in AsyncGeneratorYield."

    This reverts commit e57b500eb26dc595609613963468910eb4bcae2e.

    Revert "[async-generators] Add fast-path to skip "then" lookup in AsyncGeneratorResolve."

    This reverts commit c15802e11e30976528d1b711a9b9e6ff6b490117.

    Revert "[promises] Correctly run before/after hooks for await."

    This reverts commit ca7639239fc13e992e857710cbf7dbaac87163bf.

    Bug: v8:7253, v8:7745
    Change-Id: I25ad0d2df3cfbc84dbb431aa25b268bce8a39e89
    Reviewed-on: https://chromium-review.googlesource.com/1049975
    Commit-Queue: Maya Lekova <mslekova@chromium.org>
    Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#53139}

Refs: v8/v8@91ddb65
Fixes: #20516
Co-authored-by: Matteo Collina <matteo.collina@gmail.com>

PR-URL: #19989
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matheus Marchini <matheus@sthima.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
  • Loading branch information
MayaLekova authored and MylesBorins committed Jun 1, 2018
1 parent fb26861 commit 4e788dc
Show file tree
Hide file tree
Showing 38 changed files with 688 additions and 612 deletions.
2 changes: 1 addition & 1 deletion common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

# Reset this number to 0 on major V8 upgrades.
# Increment by one for each non-official patch applied to deps/v8.
'v8_embedder_string': '-node.5',
'v8_embedder_string': '-node.6',

# Enable disassembler for `--print-code` v8 options
'v8_enable_disassembler': 1,
Expand Down
72 changes: 72 additions & 0 deletions deps/v8/src/bootstrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1584,6 +1584,50 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
native_context()->set_async_iterator_value_unwrap_shared_fun(*info);
}

{ // --- A s y n c G e n e r a t o r ---
Handle<JSFunction> await_caught =
SimpleCreateFunction(isolate, factory->empty_string(),
Builtins::kAsyncGeneratorAwaitCaught, 1, false);
native_context()->set_async_generator_await_caught(*await_caught);

Handle<JSFunction> await_uncaught =
SimpleCreateFunction(isolate, factory->empty_string(),
Builtins::kAsyncGeneratorAwaitUncaught, 1, false);
native_context()->set_async_generator_await_uncaught(*await_uncaught);

Handle<SharedFunctionInfo> info = SimpleCreateSharedFunctionInfo(
isolate, Builtins::kAsyncGeneratorAwaitResolveClosure,
factory->empty_string(), 1);
native_context()->set_async_generator_await_resolve_shared_fun(*info);

info = SimpleCreateSharedFunctionInfo(
isolate, Builtins::kAsyncGeneratorAwaitRejectClosure,
factory->empty_string(), 1);
native_context()->set_async_generator_await_reject_shared_fun(*info);

info = SimpleCreateSharedFunctionInfo(
isolate, Builtins::kAsyncGeneratorYieldResolveClosure,
factory->empty_string(), 1);
native_context()->set_async_generator_yield_resolve_shared_fun(*info);

info = SimpleCreateSharedFunctionInfo(
isolate, Builtins::kAsyncGeneratorReturnResolveClosure,
factory->empty_string(), 1);
native_context()->set_async_generator_return_resolve_shared_fun(*info);

info = SimpleCreateSharedFunctionInfo(
isolate, Builtins::kAsyncGeneratorReturnClosedResolveClosure,
factory->empty_string(), 1);
native_context()->set_async_generator_return_closed_resolve_shared_fun(
*info);

info = SimpleCreateSharedFunctionInfo(
isolate, Builtins::kAsyncGeneratorReturnClosedRejectClosure,
factory->empty_string(), 1);
native_context()->set_async_generator_return_closed_reject_shared_fun(
*info);
}

{ // --- A r r a y ---
Handle<JSFunction> array_function = InstallFunction(
global, "Array", JS_ARRAY_TYPE, JSArray::kSize, 0,
Expand Down Expand Up @@ -3998,6 +4042,34 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
JSFunction::SetPrototype(async_function_constructor,
async_function_prototype);

{
Handle<JSFunction> function =
SimpleCreateFunction(isolate, factory->empty_string(),
Builtins::kAsyncFunctionAwaitCaught, 2, false);
native_context->set_async_function_await_caught(*function);
}

{
Handle<JSFunction> function =
SimpleCreateFunction(isolate, factory->empty_string(),
Builtins::kAsyncFunctionAwaitUncaught, 2, false);
native_context->set_async_function_await_uncaught(*function);
}

{
Handle<SharedFunctionInfo> info = SimpleCreateSharedFunctionInfo(
isolate, Builtins::kAsyncFunctionAwaitRejectClosure,
factory->empty_string(), 1);
native_context->set_async_function_await_reject_shared_fun(*info);
}

{
Handle<SharedFunctionInfo> info = SimpleCreateSharedFunctionInfo(
isolate, Builtins::kAsyncFunctionAwaitResolveClosure,
factory->empty_string(), 1);
native_context->set_async_function_await_resolve_shared_fun(*info);
}

{
Handle<JSFunction> function =
SimpleCreateFunction(isolate, factory->empty_string(),
Expand Down
96 changes: 69 additions & 27 deletions deps/v8/src/builtins/builtins-async-function-gen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,37 @@ class AsyncFunctionBuiltinsAssembler : public AsyncBuiltinsAssembler {
Node* const awaited, Node* const outer_promise,
const bool is_predicted_as_caught);

void AsyncFunctionAwaitResume(Node* const context, Node* const argument,
Node* const generator,
JSGeneratorObject::ResumeMode resume_mode);
void AsyncFunctionAwaitResumeClosure(
Node* const context, Node* const sent_value,
JSGeneratorObject::ResumeMode resume_mode);
};

void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwaitResume(
Node* const context, Node* const argument, Node* const generator,
namespace {

// Describe fields of Context associated with AsyncFunctionAwait resume
// closures.
// TODO(jgruber): Refactor to reuse code for upcoming async-generators.
class AwaitContext {
public:
enum Fields { kGeneratorSlot = Context::MIN_CONTEXT_SLOTS, kLength };
};

} // anonymous namespace

void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwaitResumeClosure(
Node* context, Node* sent_value,
JSGeneratorObject::ResumeMode resume_mode) {
CSA_ASSERT(this, IsJSGeneratorObject(generator));
DCHECK(resume_mode == JSGeneratorObject::kNext ||
resume_mode == JSGeneratorObject::kThrow);

Node* const generator =
LoadContextElement(context, AwaitContext::kGeneratorSlot);
CSA_SLOW_ASSERT(this, HasInstanceType(generator, JS_GENERATOR_OBJECT_TYPE));

// Inline version of GeneratorPrototypeNext / GeneratorPrototypeReturn with
// unnecessary runtime checks removed.
// TODO(jgruber): Refactor to reuse code from builtins-generator.cc.

// Ensure that the generator is neither closed nor running.
CSA_SLOW_ASSERT(
this,
Expand All @@ -47,23 +66,31 @@ void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwaitResume(

// Resume the {receiver} using our trampoline.
Callable callable = CodeFactory::ResumeGenerator(isolate());
TailCallStub(callable, context, argument, generator);
CallStub(callable, context, sent_value, generator);

// The resulting Promise is a throwaway, so it doesn't matter what it
// resolves to. What is important is that we don't end up keeping the
// whole chain of intermediate Promises alive by returning the return value
// of ResumeGenerator, as that would create a memory leak.
}

TF_BUILTIN(AsyncFunctionAwaitFulfill, AsyncFunctionBuiltinsAssembler) {
Node* const argument = Parameter(Descriptor::kArgument);
Node* const generator = Parameter(Descriptor::kGenerator);
TF_BUILTIN(AsyncFunctionAwaitRejectClosure, AsyncFunctionBuiltinsAssembler) {
CSA_ASSERT_JS_ARGC_EQ(this, 1);
Node* const sentError = Parameter(Descriptor::kSentError);
Node* const context = Parameter(Descriptor::kContext);
AsyncFunctionAwaitResume(context, argument, generator,
JSGeneratorObject::kNext);

AsyncFunctionAwaitResumeClosure(context, sentError,
JSGeneratorObject::kThrow);
Return(UndefinedConstant());
}

TF_BUILTIN(AsyncFunctionAwaitReject, AsyncFunctionBuiltinsAssembler) {
Node* const argument = Parameter(Descriptor::kArgument);
Node* const generator = Parameter(Descriptor::kGenerator);
TF_BUILTIN(AsyncFunctionAwaitResolveClosure, AsyncFunctionBuiltinsAssembler) {
CSA_ASSERT_JS_ARGC_EQ(this, 1);
Node* const sentValue = Parameter(Descriptor::kSentValue);
Node* const context = Parameter(Descriptor::kContext);
AsyncFunctionAwaitResume(context, argument, generator,
JSGeneratorObject::kThrow);

AsyncFunctionAwaitResumeClosure(context, sentValue, JSGeneratorObject::kNext);
Return(UndefinedConstant());
}

// ES#abstract-ops-async-function-await
Expand All @@ -78,12 +105,25 @@ TF_BUILTIN(AsyncFunctionAwaitReject, AsyncFunctionBuiltinsAssembler) {
void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwait(
Node* const context, Node* const generator, Node* const awaited,
Node* const outer_promise, const bool is_predicted_as_caught) {
CSA_SLOW_ASSERT(this, IsJSGeneratorObject(generator));
CSA_SLOW_ASSERT(this, IsJSPromise(outer_promise));

Await(context, generator, awaited, outer_promise,
Builtins::kAsyncFunctionAwaitFulfill,
Builtins::kAsyncFunctionAwaitReject, is_predicted_as_caught);
CSA_SLOW_ASSERT(this, HasInstanceType(generator, JS_GENERATOR_OBJECT_TYPE));
CSA_SLOW_ASSERT(this, HasInstanceType(outer_promise, JS_PROMISE_TYPE));

ContextInitializer init_closure_context = [&](Node* context) {
StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot,
generator);
};

// TODO(jgruber): AsyncBuiltinsAssembler::Await currently does not reuse
// the awaited promise if it is already a promise. Reuse is non-spec compliant
// but part of our old behavior gives us a couple of percent
// performance boost.
// TODO(jgruber): Use a faster specialized version of
// InternalPerformPromiseThen.

Await(context, generator, awaited, outer_promise, AwaitContext::kLength,
init_closure_context, Context::ASYNC_FUNCTION_AWAIT_RESOLVE_SHARED_FUN,
Context::ASYNC_FUNCTION_AWAIT_REJECT_SHARED_FUN,
is_predicted_as_caught);

// Return outer promise to avoid adding an load of the outer promise before
// suspending in BytecodeGenerator.
Expand All @@ -93,28 +133,30 @@ void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwait(
// Called by the parser from the desugaring of 'await' when catch
// prediction indicates that there is a locally surrounding catch block.
TF_BUILTIN(AsyncFunctionAwaitCaught, AsyncFunctionBuiltinsAssembler) {
CSA_ASSERT_JS_ARGC_EQ(this, 3);
Node* const generator = Parameter(Descriptor::kGenerator);
Node* const value = Parameter(Descriptor::kValue);
Node* const awaited = Parameter(Descriptor::kAwaited);
Node* const outer_promise = Parameter(Descriptor::kOuterPromise);
Node* const context = Parameter(Descriptor::kContext);

static const bool kIsPredictedAsCaught = true;

AsyncFunctionAwait(context, generator, value, outer_promise,
AsyncFunctionAwait(context, generator, awaited, outer_promise,
kIsPredictedAsCaught);
}

// Called by the parser from the desugaring of 'await' when catch
// prediction indicates no locally surrounding catch block.
TF_BUILTIN(AsyncFunctionAwaitUncaught, AsyncFunctionBuiltinsAssembler) {
CSA_ASSERT_JS_ARGC_EQ(this, 3);
Node* const generator = Parameter(Descriptor::kGenerator);
Node* const value = Parameter(Descriptor::kValue);
Node* const awaited = Parameter(Descriptor::kAwaited);
Node* const outer_promise = Parameter(Descriptor::kOuterPromise);
Node* const context = Parameter(Descriptor::kContext);

static const bool kIsPredictedAsCaught = false;

AsyncFunctionAwait(context, generator, value, outer_promise,
AsyncFunctionAwait(context, generator, awaited, outer_promise,
kIsPredictedAsCaught);
}

Expand Down
Loading

0 comments on commit 4e788dc

Please sign in to comment.