summaryrefslogtreecommitdiff
path: root/deps/v8/src/builtins/builtins-async-gen.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/builtins/builtins-async-gen.cc')
-rw-r--r--deps/v8/src/builtins/builtins-async-gen.cc211
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(