Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
deps: backport 91ddb65d from upstream V8
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>
  • Loading branch information
2 people authored and targos committed May 31, 2018
commit f835b2ea3e01f9c6342e76e72d6ec175f3eeb987
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