Commit 21c0d77e authored by Maya Lekova's avatar Maya Lekova Committed by Commit Bot

[async] Optimize await and AsyncFromSyncIterator

Simplify the promise wrapping in await and
%AsyncFromSyncIteratorPrototype%.next/return/throw to reuse the PromiseResolve
primitive. Now await takes 1 tick instead of 3 on the microtask queue.

Change-Id: I7e99b8689eb8fcb09c48915b11c1e06684dc0f1a
Reviewed-on: https://chromium-review.googlesource.com/1090272
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: 's avatarAleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarMathias Bynens <mathias@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53853}
parent eafcdc96
......@@ -4531,6 +4531,56 @@ void Genesis::InitializeGlobal_harmony_bigint() {
Builtins::kDataViewPrototypeSetBigUint64, 2, false);
}
void Genesis::InitializeGlobal_harmony_await_optimization() {
if (!FLAG_harmony_await_optimization) return;
// async/await
Handle<JSFunction> await_caught_function = SimpleCreateFunction(
isolate(), factory()->empty_string(),
Builtins::kAsyncFunctionAwaitCaughtOptimized, 2, false);
native_context()->set_async_function_await_caught(*await_caught_function);
Handle<JSFunction> await_uncaught_function = SimpleCreateFunction(
isolate(), factory()->empty_string(),
Builtins::kAsyncFunctionAwaitUncaughtOptimized, 2, false);
native_context()->set_async_function_await_uncaught(*await_uncaught_function);
// async generators
Handle<JSObject> async_iterator_prototype =
factory()->NewJSObject(isolate()->object_function(), TENURED);
SimpleInstallFunction(
isolate(), async_iterator_prototype, factory()->async_iterator_symbol(),
"[Symbol.asyncIterator]", Builtins::kReturnReceiver, 0, true);
Handle<JSObject> async_from_sync_iterator_prototype =
factory()->NewJSObject(isolate()->object_function(), TENURED);
SimpleInstallFunction(
isolate(), async_from_sync_iterator_prototype, factory()->next_string(),
Builtins::kAsyncFromSyncIteratorPrototypeNextOptimized, 1, true);
SimpleInstallFunction(
isolate(), async_from_sync_iterator_prototype, factory()->return_string(),
Builtins::kAsyncFromSyncIteratorPrototypeReturnOptimized, 1, true);
SimpleInstallFunction(
isolate(), async_from_sync_iterator_prototype, factory()->throw_string(),
Builtins::kAsyncFromSyncIteratorPrototypeThrowOptimized, 1, true);
JSObject::AddProperty(
async_from_sync_iterator_prototype, factory()->to_string_tag_symbol(),
factory()->NewStringFromAsciiChecked("Async-from-Sync Iterator"),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
JSObject::ForceSetPrototype(async_from_sync_iterator_prototype,
async_iterator_prototype);
Handle<Map> async_from_sync_iterator_map = factory()->NewMap(
JS_ASYNC_FROM_SYNC_ITERATOR_TYPE, JSAsyncFromSyncIterator::kSize);
Map::SetPrototype(async_from_sync_iterator_map,
async_from_sync_iterator_prototype);
native_context()->set_async_from_sync_iterator_map(
*async_from_sync_iterator_map);
}
#ifdef V8_INTL_SUPPORT
void Genesis::InitializeGlobal_harmony_locale() {
......
......@@ -20,6 +20,10 @@ class AsyncFunctionBuiltinsAssembler : public AsyncBuiltinsAssembler {
void AsyncFunctionAwait(Node* const context, Node* const generator,
Node* const awaited, Node* const outer_promise,
const bool is_predicted_as_caught);
void AsyncFunctionAwaitOptimized(Node* const context, Node* const generator,
Node* const awaited,
Node* const outer_promise,
const bool is_predicted_as_caught);
void AsyncFunctionAwaitResumeClosure(
Node* const context, Node* const sent_value,
......@@ -139,6 +143,43 @@ void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwait(
Goto(&after_debug_hook);
}
void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwaitOptimized(
Node* const context, Node* const generator, Node* const awaited,
Node* const outer_promise, const bool 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.
Label after_debug_hook(this), call_debug_hook(this, Label::kDeferred);
GotoIf(HasAsyncEventDelegate(), &call_debug_hook);
Goto(&after_debug_hook);
BIND(&after_debug_hook);
AwaitOptimized(
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.
Return(outer_promise);
BIND(&call_debug_hook);
CallRuntime(Runtime::kDebugAsyncFunctionSuspended, context, outer_promise);
Goto(&after_debug_hook);
}
// 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) {
......@@ -154,6 +195,19 @@ TF_BUILTIN(AsyncFunctionAwaitCaught, AsyncFunctionBuiltinsAssembler) {
kIsPredictedAsCaught);
}
TF_BUILTIN(AsyncFunctionAwaitCaughtOptimized, AsyncFunctionBuiltinsAssembler) {
CSA_ASSERT_JS_ARGC_EQ(this, 3);
Node* const generator = Parameter(Descriptor::kGenerator);
Node* const awaited = Parameter(Descriptor::kAwaited);
Node* const outer_promise = Parameter(Descriptor::kOuterPromise);
Node* const context = Parameter(Descriptor::kContext);
static const bool kIsPredictedAsCaught = true;
AsyncFunctionAwaitOptimized(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) {
......@@ -169,6 +223,20 @@ TF_BUILTIN(AsyncFunctionAwaitUncaught, AsyncFunctionBuiltinsAssembler) {
kIsPredictedAsCaught);
}
TF_BUILTIN(AsyncFunctionAwaitUncaughtOptimized,
AsyncFunctionBuiltinsAssembler) {
CSA_ASSERT_JS_ARGC_EQ(this, 3);
Node* const generator = Parameter(Descriptor::kGenerator);
Node* const awaited = Parameter(Descriptor::kAwaited);
Node* const outer_promise = Parameter(Descriptor::kOuterPromise);
Node* const context = Parameter(Descriptor::kContext);
static const bool kIsPredictedAsCaught = false;
AsyncFunctionAwaitOptimized(context, generator, awaited, outer_promise,
kIsPredictedAsCaught);
}
TF_BUILTIN(AsyncFunctionPromiseCreate, AsyncFunctionBuiltinsAssembler) {
CSA_ASSERT_JS_ARGC_EQ(this, 0);
Node* const context = Parameter(Descriptor::kContext);
......
......@@ -147,6 +147,120 @@ Node* AsyncBuiltinsAssembler::Await(
on_resolve, on_reject, throwaway);
}
Node* AsyncBuiltinsAssembler::AwaitOptimized(
Node* context, Node* generator, Node* value, Node* outer_promise,
int context_length, const ContextInitializer& init_closure_context,
Node* on_resolve_context_index, Node* on_reject_context_index,
Node* is_predicted_as_caught) {
DCHECK_GE(context_length, Context::MIN_CONTEXT_SLOTS);
Node* const native_context = LoadNativeContext(context);
Node* const promise_fun =
LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
CSA_ASSERT(this, IsFunctionWithPrototypeSlotMap(LoadMap(promise_fun)));
CSA_ASSERT(this, IsConstructor(promise_fun));
static const int kThrowawayPromiseOffset =
FixedArray::SizeFor(context_length);
static const int kResolveClosureOffset =
kThrowawayPromiseOffset + JSPromise::kSizeWithEmbedderFields;
static const int kRejectClosureOffset =
kResolveClosureOffset + JSFunction::kSizeWithoutPrototype;
static const int kTotalSize =
kRejectClosureOffset + JSFunction::kSizeWithoutPrototype;
// 2. Let promise be ? PromiseResolve(« promise »).
Node* const promise =
CallBuiltin(Builtins::kPromiseResolve, context, promise_fun, value);
Node* const base = AllocateInNewSpace(kTotalSize);
Node* const closure_context = base;
{
// Initialize closure context
InitializeFunctionContext(native_context, closure_context, context_length);
init_closure_context(closure_context);
}
Node* const promise_map =
LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
// Assert that the JSPromise map has an instance size is
// JSPromise::kSizeWithEmbedderFields.
CSA_ASSERT(this, WordEqual(LoadMapInstanceSizeInWords(promise_map),
IntPtrConstant(JSPromise::kSizeWithEmbedderFields /
kPointerSize)));
Node* const throwaway = InnerAllocate(base, kThrowawayPromiseOffset);
{
// Initialize throwawayPromise
StoreMapNoWriteBarrier(throwaway, promise_map);
InitializeJSObjectFromMap(
throwaway, promise_map,
IntPtrConstant(JSPromise::kSizeWithEmbedderFields));
PromiseInit(throwaway);
}
Node* const on_resolve = InnerAllocate(base, kResolveClosureOffset);
{
// Initialize resolve handler
InitializeNativeClosure(closure_context, native_context, on_resolve,
on_resolve_context_index);
}
Node* const on_reject = InnerAllocate(base, kRejectClosureOffset);
{
// Initialize reject handler
InitializeNativeClosure(closure_context, native_context, on_reject,
on_reject_context_index);
}
{
// Add PromiseHooks if needed
Label next(this);
GotoIfNot(IsPromiseHookEnabledOrHasAsyncEventDelegate(), &next);
CallRuntime(Runtime::kAwaitPromisesInit, context, promise, outer_promise,
throwaway);
Goto(&next);
BIND(&next);
}
// The Promise will be thrown away and not handled, but it shouldn't trigger
// unhandled reject events as its work is done
PromiseSetHasHandler(throwaway);
Label do_perform_promise_then(this);
GotoIfNot(IsDebugActive(), &do_perform_promise_then);
{
Label common(this);
GotoIf(TaggedIsSmi(value), &common);
GotoIfNot(HasInstanceType(value, JS_PROMISE_TYPE), &common);
{
// Mark the reject handler callback to be a forwarding edge, rather
// than a meaningful catch handler
Node* const key =
HeapConstant(factory()->promise_forwarding_handler_symbol());
CallRuntime(Runtime::kSetProperty, context, on_reject, key,
TrueConstant(), SmiConstant(LanguageMode::kStrict));
GotoIf(IsFalse(is_predicted_as_caught), &common);
PromiseSetHandledHint(value);
}
Goto(&common);
BIND(&common);
// Mark the dependency to outer Promise in case the throwaway Promise is
// found on the Promise stack
CSA_SLOW_ASSERT(this, HasInstanceType(outer_promise, JS_PROMISE_TYPE));
Node* const key = HeapConstant(factory()->promise_handled_by_symbol());
CallRuntime(Runtime::kSetProperty, context, throwaway, key, outer_promise,
SmiConstant(LanguageMode::kStrict));
}
Goto(&do_perform_promise_then);
BIND(&do_perform_promise_then);
return CallBuiltin(Builtins::kPerformPromiseThen, native_context, promise,
on_resolve, on_reject, throwaway);
}
void AsyncBuiltinsAssembler::InitializeNativeClosure(Node* context,
Node* native_context,
Node* function,
......
......@@ -28,6 +28,12 @@ class AsyncBuiltinsAssembler : public PromiseBuiltinsAssembler {
const ContextInitializer& init_closure_context,
Node* on_resolve_context_index, Node* on_reject_context_index,
Node* is_predicted_as_caught);
Node* AwaitOptimized(Node* context, Node* generator, Node* value,
Node* outer_promise, int context_length,
const ContextInitializer& init_closure_context,
Node* on_resolve_context_index,
Node* on_reject_context_index,
Node* is_predicted_as_caught);
Node* Await(Node* context, Node* generator, Node* value, Node* outer_promise,
int context_length,
const ContextInitializer& init_closure_context,
......@@ -38,6 +44,17 @@ class AsyncBuiltinsAssembler : public PromiseBuiltinsAssembler {
IntPtrConstant(on_reject_context_index),
is_predicted_as_caught);
}
Node* AwaitOptimized(Node* context, Node* generator, Node* value,
Node* outer_promise, int context_length,
const ContextInitializer& init_closure_context,
int on_resolve_context_index,
int on_reject_context_index,
Node* is_predicted_as_caught) {
return AwaitOptimized(
context, generator, value, outer_promise, context_length,
init_closure_context, IntPtrConstant(on_resolve_context_index),
IntPtrConstant(on_reject_context_index), is_predicted_as_caught);
}
Node* Await(Node* context, Node* generator, Node* value, Node* outer_promise,
int context_length,
const ContextInitializer& init_closure_context,
......@@ -48,6 +65,17 @@ class AsyncBuiltinsAssembler : public PromiseBuiltinsAssembler {
on_reject_context_index,
BooleanConstant(is_predicted_as_caught));
}
Node* AwaitOptimized(Node* context, Node* generator, Node* value,
Node* outer_promise, int context_length,
const ContextInitializer& init_closure_context,
int on_resolve_context_index,
int on_reject_context_index,
bool is_predicted_as_caught) {
return AwaitOptimized(context, generator, value, outer_promise,
context_length, init_closure_context,
on_resolve_context_index, on_reject_context_index,
BooleanConstant(is_predicted_as_caught));
}
// Return a new built-in function object as defined in
// Async Iterator Value Unwrap Functions
......
......@@ -36,6 +36,13 @@ class AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler {
const char* operation_name,
Label::Type reject_label_type = Label::kDeferred,
Node* const initial_exception_value = nullptr);
void Generate_AsyncFromSyncIteratorMethodOptimized(
Node* const context, Node* const iterator, Node* const sent_value,
const SyncIteratorNodeGenerator& get_method,
const UndefinedMethodHandler& if_method_undefined,
const char* operation_name,
Label::Type reject_label_type = Label::kDeferred,
Node* const initial_exception_value = nullptr);
void Generate_AsyncFromSyncIteratorMethod(
Node* const context, Node* const iterator, Node* const sent_value,
......@@ -50,6 +57,19 @@ class AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler {
context, iterator, sent_value, get_method, if_method_undefined,
operation_name, reject_label_type, initial_exception_value);
}
void Generate_AsyncFromSyncIteratorMethodOptimized(
Node* const context, Node* const iterator, Node* const sent_value,
Handle<String> name, const UndefinedMethodHandler& if_method_undefined,
const char* operation_name,
Label::Type reject_label_type = Label::kDeferred,
Node* const initial_exception_value = nullptr) {
auto get_method = [=](Node* const sync_iterator) {
return GetProperty(context, sync_iterator, name);
};
return Generate_AsyncFromSyncIteratorMethodOptimized(
context, iterator, sent_value, get_method, if_method_undefined,
operation_name, reject_label_type, initial_exception_value);
}
// Load "value" and "done" from an iterator result object. If an exception
// is thrown at any point, jumps to te `if_exception` label with exception
......@@ -157,6 +177,73 @@ void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod(
}
}
void AsyncFromSyncBuiltinsAssembler::
Generate_AsyncFromSyncIteratorMethodOptimized(
Node* const context, Node* const iterator, Node* const sent_value,
const SyncIteratorNodeGenerator& get_method,
const UndefinedMethodHandler& if_method_undefined,
const char* operation_name, Label::Type reject_label_type,
Node* const initial_exception_value) {
Node* const native_context = LoadNativeContext(context);
Node* const promise = AllocateAndInitJSPromise(context);
VARIABLE(var_exception, MachineRepresentation::kTagged,
initial_exception_value == nullptr ? UndefinedConstant()
: initial_exception_value);
Label reject_promise(this, reject_label_type);
ThrowIfNotAsyncFromSyncIterator(context, iterator, &reject_promise,
&var_exception, operation_name);
Node* const sync_iterator =
LoadObjectField(iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset);
Node* const method = get_method(sync_iterator);
if (if_method_undefined) {
Label if_isnotundefined(this);
GotoIfNot(IsUndefined(method), &if_isnotundefined);
if_method_undefined(native_context, promise, &reject_promise);
BIND(&if_isnotundefined);
}
Node* const iter_result = CallJS(CodeFactory::Call(isolate()), context,
method, sync_iterator, sent_value);
GotoIfException(iter_result, &reject_promise, &var_exception);
Node* value;
Node* done;
std::tie(value, done) = LoadIteratorResult(
context, native_context, iter_result, &reject_promise, &var_exception);
Node* const promise_fun =
LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
CSA_ASSERT(this, IsConstructor(promise_fun));
// Let valueWrapper be ? PromiseResolve(« value »).
Node* const valueWrapper = CallBuiltin(Builtins::kPromiseResolve,
native_context, promise_fun, value);
// Let onFulfilled be a new built-in function object as defined in
// Async Iterator Value Unwrap Functions.
// Set onFulfilled.[[Done]] to throwDone.
Node* const on_fulfilled = CreateUnwrapClosure(native_context, done);
// Perform ! PerformPromiseThen(valueWrapper,
// onFulfilled, undefined, promiseCapability).
Return(CallBuiltin(Builtins::kPerformPromiseThen, context, valueWrapper,
on_fulfilled, UndefinedConstant(), promise));
BIND(&reject_promise);
{
Node* const exception = var_exception.value();
CallBuiltin(Builtins::kRejectPromise, context, promise, exception,
TrueConstant());
Return(promise);
}
}
std::pair<Node*, Node*> AsyncFromSyncBuiltinsAssembler::LoadIteratorResult(
Node* const context, Node* const native_context, Node* const iter_result,
Label* if_exception, Variable* var_exception) {
......@@ -246,6 +333,20 @@ TF_BUILTIN(AsyncFromSyncIteratorPrototypeNext, AsyncFromSyncBuiltinsAssembler) {
"[Async-from-Sync Iterator].prototype.next");
}
TF_BUILTIN(AsyncFromSyncIteratorPrototypeNextOptimized,
AsyncFromSyncBuiltinsAssembler) {
Node* const iterator = Parameter(Descriptor::kReceiver);
Node* const value = Parameter(Descriptor::kValue);
Node* const context = Parameter(Descriptor::kContext);
auto get_method = [=](Node* const unused) {
return LoadObjectField(iterator, JSAsyncFromSyncIterator::kNextOffset);
};
Generate_AsyncFromSyncIteratorMethodOptimized(
context, iterator, value, get_method, UndefinedMethodHandler(),
"[Async-from-Sync Iterator].prototype.next");
}
// https://tc39.github.io/proposal-async-iteration/
// Section #sec-%asyncfromsynciteratorprototype%.return
TF_BUILTIN(AsyncFromSyncIteratorPrototypeReturn,
......@@ -273,6 +374,31 @@ TF_BUILTIN(AsyncFromSyncIteratorPrototypeReturn,
"[Async-from-Sync Iterator].prototype.return");
}
TF_BUILTIN(AsyncFromSyncIteratorPrototypeReturnOptimized,
AsyncFromSyncBuiltinsAssembler) {
Node* const iterator = Parameter(Descriptor::kReceiver);
Node* const value = Parameter(Descriptor::kValue);
Node* const context = Parameter(Descriptor::kContext);
auto if_return_undefined = [=](Node* const native_context,
Node* const promise, Label* if_exception) {
// If return is undefined, then
// Let iterResult be ! CreateIterResultObject(value, true)
Node* const iter_result = CallBuiltin(Builtins::kCreateIterResultObject,
context, value, TrueConstant());
// Perform ! Call(promiseCapability.[[Resolve]], undefined, « iterResult »).
// IfAbruptRejectPromise(nextDone, promiseCapability).
// Return promiseCapability.[[Promise]].
CallBuiltin(Builtins::kResolvePromise, context, promise, iter_result);
Return(promise);
};
Generate_AsyncFromSyncIteratorMethodOptimized(
context, iterator, value, factory()->return_string(), if_return_undefined,
"[Async-from-Sync Iterator].prototype.return");
}
// https://tc39.github.io/proposal-async-iteration/
// Section #sec-%asyncfromsynciteratorprototype%.throw
TF_BUILTIN(AsyncFromSyncIteratorPrototypeThrow,
......@@ -290,5 +416,20 @@ TF_BUILTIN(AsyncFromSyncIteratorPrototypeThrow,
reason);
}
TF_BUILTIN(AsyncFromSyncIteratorPrototypeThrowOptimized,
AsyncFromSyncBuiltinsAssembler) {
Node* const iterator = Parameter(Descriptor::kReceiver);
Node* const reason = Parameter(Descriptor::kReason);
Node* const context = Parameter(Descriptor::kContext);
auto if_throw_undefined = [=](Node* const native_context, Node* const promise,
Label* if_exception) { Goto(if_exception); };
Generate_AsyncFromSyncIteratorMethodOptimized(
context, iterator, reason, factory()->throw_string(), if_throw_undefined,
"[Async-from-Sync Iterator].prototype.throw", Label::kNonDeferred,
reason);
}
} // namespace internal
} // namespace v8
......@@ -420,8 +420,12 @@ namespace internal {
/* AsyncFunction */ \
TFJ(AsyncFunctionAwaitCaught, 3, kReceiver, kGenerator, kAwaited, \
kOuterPromise) \
TFJ(AsyncFunctionAwaitCaughtOptimized, 3, kReceiver, kGenerator, kAwaited, \
kOuterPromise) \
TFJ(AsyncFunctionAwaitUncaught, 3, kReceiver, kGenerator, kAwaited, \
kOuterPromise) \
TFJ(AsyncFunctionAwaitUncaughtOptimized, 3, kReceiver, kGenerator, kAwaited, \
kOuterPromise) \
TFJ(AsyncFunctionAwaitRejectClosure, 1, kReceiver, kSentError) \
TFJ(AsyncFunctionAwaitResolveClosure, 1, kReceiver, kSentValue) \
TFJ(AsyncFunctionPromiseCreate, 0, kReceiver) \
......@@ -1271,10 +1275,13 @@ namespace internal {
/* See tc39.github.io/proposal-async-iteration/ */ \
/* #sec-%asyncfromsynciteratorprototype%-object) */ \
TFJ(AsyncFromSyncIteratorPrototypeNext, 1, kReceiver, kValue) \
TFJ(AsyncFromSyncIteratorPrototypeNextOptimized, 1, kReceiver, kValue) \
/* #sec-%asyncfromsynciteratorprototype%.throw */ \
TFJ(AsyncFromSyncIteratorPrototypeThrow, 1, kReceiver, kReason) \
TFJ(AsyncFromSyncIteratorPrototypeThrowOptimized, 1, kReceiver, kReason) \
/* #sec-%asyncfromsynciteratorprototype%.return */ \
TFJ(AsyncFromSyncIteratorPrototypeReturn, 1, kReceiver, kValue) \
TFJ(AsyncFromSyncIteratorPrototypeReturnOptimized, 1, kReceiver, kValue) \
/* #sec-async-iterator-value-unwrap-functions */ \
TFJ(AsyncIteratorValueUnwrap, 1, kReceiver, kValue) \
\
......@@ -1355,9 +1362,14 @@ namespace internal {
#define BUILTIN_PROMISE_REJECTION_PREDICTION_LIST(V) \
V(AsyncFromSyncIteratorPrototypeNext) \
V(AsyncFromSyncIteratorPrototypeReturn) \
V(AsyncFromSyncIteratorPrototypeNextOptimized) \
V(AsyncFromSyncIteratorPrototypeThrowOptimized) \
V(AsyncFromSyncIteratorPrototypeReturnOptimized) \
V(AsyncFromSyncIteratorPrototypeThrow) \
V(AsyncFunctionAwaitCaught) \
V(AsyncFunctionAwaitCaughtOptimized) \
V(AsyncFunctionAwaitUncaught) \
V(AsyncFunctionAwaitUncaughtOptimized) \
V(AsyncGeneratorResolve) \
V(AsyncGeneratorAwaitCaught) \
V(AsyncGeneratorAwaitUncaught) \
......
......@@ -208,10 +208,11 @@ DEFINE_IMPLICATION(harmony_class_fields, harmony_private_fields)
// Update bootstrapper.cc whenever adding a new feature flag.
// Features that are still work in progress (behind individual flags).
#define HARMONY_INPROGRESS_BASE(V) \
V(harmony_do_expressions, "harmony do-expressions") \
V(harmony_class_fields, "harmony fields in class literals") \
V(harmony_static_fields, "harmony static fields in class literals")
#define HARMONY_INPROGRESS_BASE(V) \
V(harmony_do_expressions, "harmony do-expressions") \
V(harmony_class_fields, "harmony fields in class literals") \
V(harmony_static_fields, "harmony static fields in class literals") \
V(harmony_await_optimization, "harmony await taking 1 tick")
#ifdef V8_INTL_SUPPORT
#define HARMONY_INPROGRESS(V) \
......
......@@ -2,209 +2,214 @@ stepOut async function
Running test: testTrivial
Check that we have proper async stack at return
bar (testTrivial.js:28:8)
bar (testTrivial.js:30:8)
-- async function --
bar (testTrivial.js:27:22)
foo (testTrivial.js:23:14)
bar (testTrivial.js:29:22)
foo (testTrivial.js:25:14)
-- async function --
foo (testTrivial.js:22:22)
test (testTrivial.js:18:14)
foo (testTrivial.js:24:22)
test (testTrivial.js:20:14)
-- async function --
test (testTrivial.js:17:22)
test (testTrivial.js:19:22)
(anonymous) (:0:0)
foo (testTrivial.js:24:6)
foo (testTrivial.js:26:6)
-- async function --
foo (testTrivial.js:22:22)
test (testTrivial.js:18:14)
foo (testTrivial.js:24:22)
test (testTrivial.js:20:14)
-- async function --
test (testTrivial.js:17:22)
test (testTrivial.js:19:22)
(anonymous) (:0:0)
test (testTrivial.js:19:6)
test (testTrivial.js:21:6)
-- async function --
test (testTrivial.js:17:22)
test (testTrivial.js:19:22)
(anonymous) (:0:0)
Running test: testStepOutPrecision
Check that stepOut go to resumed outer generator
bar (testStepOutPrecision.js:61:8)
bar (testStepOutPrecision.js:63:8)
-- async function --
bar (testStepOutPrecision.js:60:22)
foo (testStepOutPrecision.js:55:14)
bar (testStepOutPrecision.js:62:22)
foo (testStepOutPrecision.js:57:14)
-- async function --
foo (testStepOutPrecision.js:54:22)
test (testStepOutPrecision.js:48:14)
foo (testStepOutPrecision.js:56:22)
test (testStepOutPrecision.js:50:14)
-- async function --
test (testStepOutPrecision.js:47:14)
test (testStepOutPrecision.js:49:14)
(anonymous) (:0:0)
foo (testStepOutPrecision.js:56:8)
foo (testStepOutPrecision.js:58:8)
-- async function --
foo (testStepOutPrecision.js:54:22)
test (testStepOutPrecision.js:48:14)
foo (testStepOutPrecision.js:56:22)
test (testStepOutPrecision.js:50:14)
-- async function --
test (testStepOutPrecision.js:47:14)
test (testStepOutPrecision.js:49:14)
(anonymous) (:0:0)
test (testStepOutPrecision.js:49:8)
test (testStepOutPrecision.js:51:8)
-- async function --
test (testStepOutPrecision.js:47:14)
test (testStepOutPrecision.js:49:14)
(anonymous) (:0:0)
floodWithTimeouts (testStepOutPrecision.js:40:15)
floodWithTimeouts (testStepOutPrecision.js:42:15)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
floodWithTimeouts (testStepOutPrecision.js:43:10)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
floodWithTimeouts (testStepOutPrecision.js:43:10)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
floodWithTimeouts (testStepOutPrecision.js:43:10)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
test (testStepOutPrecision.js:46:8)
floodWithTimeouts (testStepOutPrecision.js:43:10)
test (testStepOutPrecision.js:48:8)
(anonymous) (:0:0)
test (testStepOutPrecision.js:50:8)
test (testStepOutPrecision.js:52:8)
-- async function --
test (testStepOutPrecision.js:47:14)
test (testStepOutPrecision.js:49:14)
(anonymous) (:0:0)
floodWithTimeouts (testStepOutPrecision.js:40:15)
floodWithTimeouts (testStepOutPrecision.js:42:15)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
floodWithTimeouts (testStepOutPrecision.js:43:10)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
floodWithTimeouts (testStepOutPrecision.js:43:10)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
floodWithTimeouts (testStepOutPrecision.js:43:10)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
floodWithTimeouts (testStepOutPrecision.js:43:10)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
test (testStepOutPrecision.js:46:8)
floodWithTimeouts (testStepOutPrecision.js:43:10)
test (testStepOutPrecision.js:48:8)
(anonymous) (:0:0)
Running test: testStepIntoAtReturn
Check that stepInto at return go to resumed outer generator
bar (testStepIntoAtReturn.js:93:8)
bar (testStepIntoAtReturn.js:95:8)
-- async function --
bar (testStepIntoAtReturn.js:92:22)
foo (testStepIntoAtReturn.js:88:14)
bar (testStepIntoAtReturn.js:94:22)
foo (testStepIntoAtReturn.js:90:14)
-- async function --
foo (testStepIntoAtReturn.js:87:22)
test (testStepIntoAtReturn.js:82:14)
foo (testStepIntoAtReturn.js:89:22)
test (testStepIntoAtReturn.js:84:14)
-- async function --
test (testStepIntoAtReturn.js:81:14)
test (testStepIntoAtReturn.js:83:14)
(anonymous) (:0:0)
bar (testStepIntoAtReturn.js:94:6)
bar (testStepIntoAtReturn.js:96:6)
-- async function --
bar (testStepIntoAtReturn.js:92:22)
foo (testStepIntoAtReturn.js:88:14)
bar (testStepIntoAtReturn.js:94:22)
foo (testStepIntoAtReturn.js:90:14)
-- async function --
foo (testStepIntoAtReturn.js:87:22)
test (testStepIntoAtReturn.js:82:14)
foo (testStepIntoAtReturn.js:89:22)
test (testStepIntoAtReturn.js:84:14)
-- async function --
test (testStepIntoAtReturn.js:81:14)
test (testStepIntoAtReturn.js:83:14)
(anonymous) (:0:0)
foo (testStepIntoAtReturn.js:89:6)
foo (testStepIntoAtReturn.js:91:6)
-- async function --
foo (testStepIntoAtReturn.js:87:22)
test (testStepIntoAtReturn.js:82:14)
foo (testStepIntoAtReturn.js:89:22)
test (testStepIntoAtReturn.js:84:14)
-- async function --
test (testStepIntoAtReturn.js:81:14)
test (testStepIntoAtReturn.js:83:14)
(anonymous) (:0:0)
test (testStepIntoAtReturn.js:83:8)
test (testStepIntoAtReturn.js:85:8)
-- async function --
test (testStepIntoAtReturn.js:81:14)
test (testStepIntoAtReturn.js:83:14)
(anonymous) (:0:0)
test (testStepIntoAtReturn.js:84:6)
test (testStepIntoAtReturn.js:86:6)
-- async function --
test (testStepIntoAtReturn.js:81:14)
test (testStepIntoAtReturn.js:83:14)
(anonymous) (:0:0)
floodWithTimeouts (testStepIntoAtReturn.js:74:15)
floodWithTimeouts (testStepIntoAtReturn.js:76:15)
-- setTimeout --
floodWithTimeouts (testStepIntoAtReturn.js:75:10)
floodWithTimeouts (testStepIntoAtReturn.js:77:10)
-- setTimeout --
floodWithTimeouts (testStepIntoAtReturn.js:75:10)
test (testStepIntoAtReturn.js:80:8)
floodWithTimeouts (testStepIntoAtReturn.js:77:10)
test (testStepIntoAtReturn.js:82:8)
(anonymous) (:0:0)
Running test: testStepOverAtReturn
Check that stepOver at return go to resumed outer generator
bar (testStepIntoAtReturn.js:124:8)
bar (testStepIntoAtReturn.js:126:8)
-- async function --
bar (testStepIntoAtReturn.js:123:22)
foo (testStepIntoAtReturn.js:119:14)
bar (testStepIntoAtReturn.js:125:22)
foo (testStepIntoAtReturn.js:121:14)
-- async function --
foo (testStepIntoAtReturn.js:118:22)
test (testStepIntoAtReturn.js:113:14)
foo (testStepIntoAtReturn.js:120:22)
test (testStepIntoAtReturn.js:115:14)
-- async function --
test (testStepIntoAtReturn.js:112:14)
test (testStepIntoAtReturn.js:114:14)
(anonymous) (:0:0)
bar (testStepIntoAtReturn.js:125:6)
bar (testStepIntoAtReturn.js:127:6)
-- async function --
bar (testStepIntoAtReturn.js:123:22)
foo (testStepIntoAtReturn.js:119:14)
bar (testStepIntoAtReturn.js:125:22)
foo (testStepIntoAtReturn.js:121:14)
-- async function --
foo (testStepIntoAtReturn.js:118:22)
test (testStepIntoAtReturn.js:113:14)
foo (testStepIntoAtReturn.js:120:22)
test (testStepIntoAtReturn.js:115:14)
-- async function --
test (testStepIntoAtReturn.js:112:14)
test (testStepIntoAtReturn.js:114:14)
(anonymous) (:0:0)
foo (testStepIntoAtReturn.js:120:6)
foo (testStepIntoAtReturn.js:122:6)
-- async function --
foo (testStepIntoAtReturn.js:118:22)
test (testStepIntoAtReturn.js:113:14)
foo (testStepIntoAtReturn.js:120:22)
test (testStepIntoAtReturn.js:115:14)
-- async function --
test (testStepIntoAtReturn.js:112:14)
test (testStepIntoAtReturn.js:114:14)
(anonymous) (:0:0)
test (testStepIntoAtReturn.js:114:8)
test (testStepIntoAtReturn.js:116:8)
-- async function --
test (testStepIntoAtReturn.js:112:14)
test (testStepIntoAtReturn.js:114:14)
(anonymous) (:0:0)
test (testStepIntoAtReturn.js:115:6)
test (testStepIntoAtReturn.js:117:6)
-- async function --
test (testStepIntoAtReturn.js:112:14)
test (testStepIntoAtReturn.js:114:14)
(anonymous) (:0:0)
floodWithTimeouts (testStepIntoAtReturn.js:105:15)
floodWithTimeouts (testStepIntoAtReturn.js:107:15)
-- setTimeout --
floodWithTimeouts (testStepIntoAtReturn.js:106:10)
floodWithTimeouts (testStepIntoAtReturn.js:108:10)
-- setTimeout --
floodWithTimeouts (testStepIntoAtReturn.js:106:10)
test (testStepIntoAtReturn.js:111:8)
floodWithTimeouts (testStepIntoAtReturn.js:108:10)
test (testStepIntoAtReturn.js:113:8)
(anonymous) (:0:0)
Running test: testStepOutFromNotAwaitedCall
Checks stepOut from not awaited call
bar (testStepIntoAtReturn.js:158:8)
bar (testStepIntoAtReturn.js:160:8)
-- async function --
bar (testStepIntoAtReturn.js:157:22)
foo (testStepIntoAtReturn.js:152:8)
bar (testStepIntoAtReturn.js:159:22)
foo (testStepIntoAtReturn.js:154:8)
-- async function --
foo (testStepIntoAtReturn.js:151:22)
test (testStepIntoAtReturn.js:144:14)
foo (testStepIntoAtReturn.js:153:22)
test (testStepIntoAtReturn.js:146:14)
-- async function --
test (testStepIntoAtReturn.js:143:14)
test (testStepIntoAtReturn.js:145:14)
(anonymous) (:0:0)
floodWithTimeouts (testStepIntoAtReturn.js:136:15)
test (testStepIntoAtReturn.js:147:8)
-- async function --
test (testStepIntoAtReturn.js:145:14)
(anonymous) (:0:0)
floodWithTimeouts (testStepIntoAtReturn.js:138:15)
-- setTimeout --
floodWithTimeouts (testStepIntoAtReturn.js:137:10)
floodWithTimeouts (testStepIntoAtReturn.js:139:10)
-- setTimeout --
floodWithTimeouts (testStepIntoAtReturn.js:137:10)
test (testStepIntoAtReturn.js:142:8)
floodWithTimeouts (testStepIntoAtReturn.js:139:10)
test (testStepIntoAtReturn.js:144:8)
(anonymous) (:0:0)
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-await-optimization
let {session, contextGroup, Protocol} =
InspectorTest.start('stepOut async function');
......
......@@ -153,6 +153,36 @@ asyncF (test.js:18:2)
#})();
return promise;
Promise.resolve.then.then.x (test.js:4:64)
var arr1 = [1];
var promise = Promise.resolve(1).then(x => x * 2).then(x => x #/ 2);
Promise.resolve(1).then(x => x * 2).then(x => x / 2);
Promise.resolve.then.then.x (test.js:4:67)
var arr1 = [1];
var promise = Promise.resolve(1).then(x => x * 2).then(x => x / 2#);
Promise.resolve(1).then(x => x * 2).then(x => x / 2);
Promise.resolve.then.then.x (test.js:5:50)
var promise = Promise.resolve(1).then(x => x * 2).then(x => x / 2);
Promise.resolve(1).then(x => x * 2).then(x => x #/ 2);
promise = Promise.resolve(1).then(x => x * 2).then(x => x / 2);
Promise.resolve.then.then.x (test.js:5:53)
var promise = Promise.resolve(1).then(x => x * 2).then(x => x / 2);
Promise.resolve(1).then(x => x * 2).then(x => x / 2#);
promise = Promise.resolve(1).then(x => x * 2).then(x => x / 2);
Promise.resolve.then.then.x (test.js:6:60)
Promise.resolve(1).then(x => x * 2).then(x => x / 2);
promise = Promise.resolve(1).then(x => x * 2).then(x => x #/ 2);
var a = 1;
Promise.resolve.then.then.x (test.js:6:63)
Promise.resolve(1).then(x => x * 2).then(x => x / 2);
promise = Promise.resolve(1).then(x => x * 2).then(x => x / 2#);
var a = 1;
Running test: testStepIntoAfterBreakpoint
testFunction (test.js:10:10)
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-await-optimization
let {session, contextGroup, Protocol} =
InspectorTest.start('Tests breakable locations in variable initializations.');
......
......@@ -8,7 +8,7 @@ var ran = false;
async function test() {
try {
let namespace = await import('modules-skip-5.js');
let namespace = await import('modules-skip-5.js').then(x => x);
assertSame(namespace.static_life, namespace.dynamic_life);
assertSame(namespace.relative_static_life, namespace.dynamic_life);
ran = true;
......
......@@ -15,13 +15,17 @@ async function f() {
}
f();
async function g() {
async function importUndefined() {
try {
let namespace = await import({ get toString() { return undefined; }});
await import({ get toString() { return undefined; }})
} catch(e) {
log(2);
}
}
function g() {
let namespace = Promise.resolve().then(importUndefined);
}
g();
%RunMicrotasks();
assertEquals(list, [1,2]);
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