diff options
Diffstat (limited to 'deps/v8/src/builtins/builtins-async-gen.cc')
-rw-r--r-- | deps/v8/src/builtins/builtins-async-gen.cc | 211 |
1 files changed, 52 insertions, 159 deletions
diff --git a/deps/v8/src/builtins/builtins-async-gen.cc b/deps/v8/src/builtins/builtins-async-gen.cc index 0cdcb57a3f..7958afba00 100644 --- a/deps/v8/src/builtins/builtins-async-gen.cc +++ b/deps/v8/src/builtins/builtins-async-gen.cc @@ -13,6 +13,58 @@ namespace internal { using compiler::Node; +void AsyncBuiltinsAssembler::Await(Node* context, Node* generator, Node* value, + Node* outer_promise, + Builtins::Name fulfill_builtin, + Builtins::Name reject_builtin, + Node* is_predicted_as_caught) { + CSA_SLOW_ASSERT(this, Word32Or(IsJSAsyncGeneratorObject(generator), + IsJSGeneratorObject(generator))); + CSA_SLOW_ASSERT(this, IsJSPromise(outer_promise)); + CSA_SLOW_ASSERT(this, IsBoolean(is_predicted_as_caught)); + + Node* const native_context = LoadNativeContext(context); + + // TODO(bmeurer): This could be optimized and folded into a single allocation. + Node* const promise = AllocateAndInitJSPromise(native_context); + Node* const promise_reactions = + LoadObjectField(promise, JSPromise::kReactionsOrResultOffset); + Node* const fulfill_handler = + HeapConstant(Builtins::CallableFor(isolate(), fulfill_builtin).code()); + Node* const reject_handler = + HeapConstant(Builtins::CallableFor(isolate(), reject_builtin).code()); + Node* const reaction = AllocatePromiseReaction( + promise_reactions, generator, fulfill_handler, reject_handler); + StoreObjectField(promise, JSPromise::kReactionsOrResultOffset, reaction); + PromiseSetHasHandler(promise); + + // Perform ! Call(promiseCapability.[[Resolve]], undefined, « value »). + CallBuiltin(Builtins::kResolvePromise, native_context, promise, value); + + // When debugging, we need to link from the {generator} to the + // {outer_promise} of the async function/generator. + Label done(this); + GotoIfNot(IsDebugActive(), &done); + CallRuntime(Runtime::kSetProperty, native_context, generator, + LoadRoot(Heap::kgenerator_outer_promise_symbolRootIndex), + outer_promise, SmiConstant(LanguageMode::kStrict)); + GotoIf(IsFalse(is_predicted_as_caught), &done); + GotoIf(TaggedIsSmi(value), &done); + GotoIfNot(IsJSPromise(value), &done); + PromiseSetHandledHint(value); + Goto(&done); + BIND(&done); +} + +void AsyncBuiltinsAssembler::Await(Node* context, Node* generator, Node* value, + Node* outer_promise, + Builtins::Name fulfill_builtin, + Builtins::Name reject_builtin, + bool is_predicted_as_caught) { + return Await(context, generator, value, outer_promise, fulfill_builtin, + reject_builtin, BooleanConstant(is_predicted_as_caught)); +} + namespace { // Describe fields of Context associated with the AsyncIterator unwrap closure. class ValueUnwrapContext { @@ -22,165 +74,6 @@ class ValueUnwrapContext { } // namespace -Node* AsyncBuiltinsAssembler::Await( - 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); - - static const int kWrappedPromiseOffset = FixedArray::SizeFor(context_length); - static const int kThrowawayPromiseOffset = - kWrappedPromiseOffset + JSPromise::kSizeWithEmbedderFields; - static const int kResolveClosureOffset = - kThrowawayPromiseOffset + JSPromise::kSizeWithEmbedderFields; - static const int kRejectClosureOffset = - kResolveClosureOffset + JSFunction::kSizeWithoutPrototype; - static const int kTotalSize = - kRejectClosureOffset + JSFunction::kSizeWithoutPrototype; - - 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); - } - - // Let promiseCapability be ! NewPromiseCapability(%Promise%). - Node* const promise_fun = - LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); - CSA_ASSERT(this, IsFunctionWithPrototypeSlotMap(LoadMap(promise_fun))); - 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 wrapped_value = InnerAllocate(base, kWrappedPromiseOffset); - { - // Initialize Promise - StoreMapNoWriteBarrier(wrapped_value, promise_map); - InitializeJSObjectFromMap( - wrapped_value, promise_map, - IntPtrConstant(JSPromise::kSizeWithEmbedderFields)); - PromiseInit(wrapped_value); - } - - 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(IsPromiseHookEnabledOrDebugIsActive(), &next); - CallRuntime(Runtime::kPromiseHookInit, context, wrapped_value, - outer_promise); - CallRuntime(Runtime::kPromiseHookInit, context, throwaway, wrapped_value); - Goto(&next); - BIND(&next); - } - - // Perform ! Call(promiseCapability.[[Resolve]], undefined, « promise »). - CallBuiltin(Builtins::kResolveNativePromise, context, wrapped_value, value); - - // 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); - - CallBuiltin(Builtins::kPerformNativePromiseThen, context, wrapped_value, - on_resolve, on_reject, throwaway); - - return wrapped_value; -} - -void AsyncBuiltinsAssembler::InitializeNativeClosure(Node* context, - Node* native_context, - Node* function, - Node* context_index) { - Node* const function_map = LoadContextElement( - native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); - // Ensure that we don't have to initialize prototype_or_initial_map field of - // JSFunction. - CSA_ASSERT(this, WordEqual(LoadMapInstanceSizeInWords(function_map), - IntPtrConstant(JSFunction::kSizeWithoutPrototype / - kPointerSize))); - STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kPointerSize); - StoreMapNoWriteBarrier(function, function_map); - StoreObjectFieldRoot(function, JSObject::kPropertiesOrHashOffset, - Heap::kEmptyFixedArrayRootIndex); - StoreObjectFieldRoot(function, JSObject::kElementsOffset, - Heap::kEmptyFixedArrayRootIndex); - StoreObjectFieldRoot(function, JSFunction::kFeedbackVectorOffset, - Heap::kUndefinedCellRootIndex); - - Node* shared_info = LoadContextElement(native_context, context_index); - CSA_ASSERT(this, IsSharedFunctionInfo(shared_info)); - StoreObjectFieldNoWriteBarrier( - function, JSFunction::kSharedFunctionInfoOffset, shared_info); - StoreObjectFieldNoWriteBarrier(function, JSFunction::kContextOffset, context); - - Node* const code = - LoadObjectField(shared_info, SharedFunctionInfo::kCodeOffset); - StoreObjectFieldNoWriteBarrier(function, JSFunction::kCodeOffset, code); -} - Node* AsyncBuiltinsAssembler::CreateUnwrapClosure(Node* native_context, Node* done) { Node* const map = LoadContextElement( |