Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Unified Diff: src/builtins/builtins-promise.cc

Issue 2567333002: [promises] port NewPromiseCapability to TF (Closed)
Patch Set: fix cctests and stuff Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/builtins/builtins-promise.cc
diff --git a/src/builtins/builtins-promise.cc b/src/builtins/builtins-promise.cc
index 46f6043bd3c85350d81ea25da6940d0219a4b0ef..ad7c0ce8333439244a01be4450639adb305ef0dd 100644
--- a/src/builtins/builtins-promise.cc
+++ b/src/builtins/builtins-promise.cc
@@ -16,6 +16,152 @@ typedef compiler::Node Node;
typedef CodeStubAssembler::ParameterMode ParameterMode;
typedef compiler::CodeAssemblerState CodeAssemblerState;
+Node* PromiseBuiltinsAssembler::CreatePromiseGetCapabilitiesExecutorContext(
+ Node* promise_capability, Node* native_context) {
+ Node* context = Allocate(
+ FixedArray::SizeFor(GetPromiseCapabilityExecutor::kContextLength));
+ Node* map = HeapConstant(isolate()->factory()->function_context_map());
+ StoreMapNoWriteBarrier(context, map);
+ StoreObjectFieldNoWriteBarrier(
+ context, FixedArray::kLengthOffset,
+ SmiConstant(GetPromiseCapabilityExecutor::kContextLength));
+
+ Node* script = LoadContextElement(native_context, Context::CLOSURE_INDEX);
+ StoreContextElement(context, Context::CLOSURE_INDEX, script);
+ StoreContextElement(context, Context::PREVIOUS_INDEX, UndefinedConstant());
+ StoreContextElement(context, Context::EXTENSION_INDEX, TheHoleConstant());
+ StoreContextElement(context, Context::NATIVE_CONTEXT_INDEX, native_context);
gsathya 2016/12/21 01:02:33 You refactor this to reuse CreatePromiseResolvingF
+ StoreContextElement(context, GetPromiseCapabilityExecutor::kCapabilitySlot,
gsathya 2016/12/21 01:02:33 StoreContextElementNoWriteBarrier
Igor Sheludko 2016/12/21 12:00:45 We can use it for all the stores because the objec
+ promise_capability);
+ return context;
+}
+
+Node* PromiseBuiltinsAssembler::NewPromiseCapability(Node* context,
+ Node* constructor,
+ Node* debug_event) {
+ if (debug_event == nullptr) {
+ debug_event = TrueConstant();
+ }
+
+ Node* native_context = LoadNativeContext(context);
+
+ Node* capability = Allocate(JSPromiseCapability::kSize);
+ StoreMapNoWriteBarrier(capability, Heap::kJSPromiseCapabilityMapRootIndex);
gsathya 2016/12/21 01:02:33 Why not use AllocateJSObjectFromMap here?
caitp 2016/12/21 21:01:13 Done.
+ StoreObjectFieldNoWriteBarrier(capability, JSObject::kPropertiesOffset,
+ EmptyFixedArrayConstant());
+ StoreObjectFieldNoWriteBarrier(capability, JSObject::kElementsOffset,
+ EmptyFixedArrayConstant());
+ StoreObjectFieldNoWriteBarrier(
+ capability, JSPromiseCapability::kPromiseOffset, UndefinedConstant());
+ StoreObjectFieldNoWriteBarrier(
+ capability, JSPromiseCapability::kResolveOffset, UndefinedConstant());
+ StoreObjectFieldNoWriteBarrier(capability, JSPromiseCapability::kRejectOffset,
+ UndefinedConstant());
+
+ Variable var_result(this, MachineRepresentation::kTagged);
+ var_result.Bind(capability);
+
+ Label if_builtin_promise(this), if_custom_promise(this), out(this);
+ Branch(WordEqual(constructor,
+ LoadContextElement(native_context,
+ Context::PROMISE_FUNCTION_INDEX)),
+ &if_builtin_promise, &if_custom_promise);
+
+ Bind(&if_builtin_promise);
+ {
+ Node* promise = AllocateJSPromise(context);
+ PromiseInit(promise);
+ StoreObjectFieldNoWriteBarrier(
+ capability, JSPromiseCapability::kPromiseOffset, promise);
+
+ Node* resolve = nullptr;
+ Node* reject = nullptr;
+
+ std::tie(resolve, reject) =
+ CreatePromiseResolvingFunctions(promise, debug_event, native_context);
+ StoreObjectField(capability, JSPromiseCapability::kResolveOffset, resolve);
+ StoreObjectField(capability, JSPromiseCapability::kRejectOffset, reject);
+
+ GotoUnless(IsPromiseHookEnabled(), &out);
+ CallRuntime(Runtime::kPromiseHookInit, context, promise,
+ UndefinedConstant());
+ Goto(&out);
+ }
+
+ Bind(&if_custom_promise);
+ {
+ Label if_notcallable(this, Label::kDeferred);
+ Node* executor_context =
+ CreatePromiseGetCapabilitiesExecutorContext(capability, native_context);
+ Node* executor_info = LoadContextElement(
+ native_context, Context::PROMISE_GET_CAPABILITIES_EXECUTOR_SHARED_FUN);
+ Node* function_map = LoadContextElement(
+ native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
+ Node* executor = AllocateFunctionWithMapAndContext(
+ function_map, executor_info, executor_context);
+
+ Node* promise = ConstructJS(CodeFactory::Construct(isolate()), context,
+ constructor, executor);
+
+ Node* resolve =
+ LoadObjectField(capability, JSPromiseCapability::kResolveOffset);
+ GotoIf(TaggedIsSmi(resolve), &if_notcallable);
+ GotoUnless(IsCallableMap(LoadMap(resolve)), &if_notcallable);
+
+ Node* reject =
+ LoadObjectField(capability, JSPromiseCapability::kRejectOffset);
+ GotoIf(TaggedIsSmi(reject), &if_notcallable);
+ GotoUnless(IsCallableMap(LoadMap(reject)), &if_notcallable);
+
+ StoreObjectField(capability, JSPromiseCapability::kPromiseOffset, promise);
+
+ Goto(&out);
+
+ Bind(&if_notcallable);
+ Node* message = SmiConstant(MessageTemplate::kPromiseNonCallable);
+ StoreObjectField(capability, JSPromiseCapability::kPromiseOffset,
+ UndefinedConstant());
+ StoreObjectField(capability, JSPromiseCapability::kResolveOffset,
+ UndefinedConstant());
+ StoreObjectField(capability, JSPromiseCapability::kRejectOffset,
+ UndefinedConstant());
+ CallRuntime(Runtime::kThrowTypeError, context, message);
+ var_result.Bind(UndefinedConstant());
+ Goto(&out);
+ }
+
+ Bind(&out);
+ return var_result.value();
+}
+
+Node* PromiseBuiltinsAssembler::NewInternalPromiseCapability(Node* context,
+ Node* parent) {
+ Node* promise = AllocateJSPromise(context);
+ PromiseInit(promise);
+
+ Label out(this);
+
+ Node* capability = Allocate(JSPromiseCapability::kSize);
+ StoreMapNoWriteBarrier(capability, Heap::kJSPromiseCapabilityMapRootIndex);
+ StoreObjectFieldNoWriteBarrier(capability, JSObject::kPropertiesOffset,
+ EmptyFixedArrayConstant());
+ StoreObjectFieldNoWriteBarrier(capability, JSObject::kElementsOffset,
+ EmptyFixedArrayConstant());
+ StoreObjectFieldNoWriteBarrier(capability,
+ JSPromiseCapability::kPromiseOffset, promise);
+ StoreObjectFieldNoWriteBarrier(
+ capability, JSPromiseCapability::kResolveOffset, UndefinedConstant());
+ StoreObjectFieldNoWriteBarrier(capability, JSPromiseCapability::kRejectOffset,
+ UndefinedConstant());
+
+ GotoUnless(IsPromiseHookEnabled(), &out);
+ CallRuntime(Runtime::kPromiseHookInit, context, promise, parent);
+ Goto(&out);
+
+ Bind(&out);
+ return capability;
+}
+
Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext(
Node* promise, Node* debug_event, Node* native_context) {
Node* const context =
@@ -338,15 +484,10 @@ Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context,
Bind(&out);
PromiseSetHasHandler(promise);
- // TODO(gsathya): This call will be removed once we don't have to
- // deal with deferred objects.
- Isolate* isolate = this->isolate();
- Callable getproperty_callable = CodeFactory::GetProperty(isolate);
- Node* const key =
- HeapConstant(isolate->factory()->NewStringFromAsciiChecked("promise"));
- Node* const result = CallStub(getproperty_callable, context, deferred, key);
-
- return result;
+ CSA_ASSERT(this, HasInstanceType(deferred, JS_PROMISE_CAPABILITY_TYPE));
+ Node* then_promise =
+ LoadObjectField(deferred, JSPromiseCapability::kPromiseOffset);
+ return then_promise;
}
// Promise fast path implementations rely on unmodified JSPromise instances.
@@ -795,24 +936,14 @@ TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) {
// NewPromiseCapabability functions to TF.
Bind(&fast_promise_capability);
{
- // TODO(gsathya): Move this to TF.
- Node* const promise_internal_capability = LoadContextElement(
- native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX);
- Node* const capability =
- CallJS(call_callable, context, promise_internal_capability,
- UndefinedConstant(), promise);
+ Node* const capability = NewInternalPromiseCapability(context, promise);
var_deferred.Bind(capability);
Goto(&perform_promise_then);
}
Bind(&promise_capability);
{
- // TODO(gsathya): Move this to TF.
- Node* const new_promise_capability = LoadContextElement(
- native_context, Context::NEW_PROMISE_CAPABILITY_INDEX);
- Node* const capability =
- CallJS(call_callable, context, new_promise_capability,
- UndefinedConstant(), constructor);
+ Node* const capability = NewPromiseCapability(context, constructor);
var_deferred.Bind(capability);
Goto(&perform_promise_then);
}
@@ -905,11 +1036,9 @@ TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) {
Isolate* isolate = this->isolate();
// Get promise from deferred
- // TODO(gsathya): Remove this lookup by getting rid of the deferred object.
- Callable getproperty_callable = CodeFactory::GetProperty(isolate);
- Node* const key = HeapConstant(isolate->factory()->promise_string());
+ CSA_ASSERT(this, HasInstanceType(deferred, JS_PROMISE_CAPABILITY_TYPE));
Node* const deferred_promise =
- CallStub(getproperty_callable, context, deferred, key);
+ LoadObjectField(deferred, JSPromiseCapability::kPromiseOffset);
Variable var_reason(this, MachineRepresentation::kTagged);
@@ -937,10 +1066,8 @@ TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) {
GotoIfException(result, &if_rejectpromise, &var_reason);
- // TODO(gsathya): Remove this lookup by getting rid of the deferred object.
- Node* const key = HeapConstant(isolate->factory()->resolve_string());
Node* const on_resolve =
- CallStub(getproperty_callable, context, deferred, key);
+ LoadObjectField(deferred, JSPromiseCapability::kResolveOffset);
Label if_internalhandler(this), if_customhandler(this, Label::kDeferred);
Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler);
@@ -960,10 +1087,8 @@ TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) {
Bind(&if_rejectpromise);
{
- // TODO(gsathya): Remove this lookup by getting rid of the deferred object.
- Node* const key = HeapConstant(isolate->factory()->reject_string());
Node* const on_reject =
- CallStub(getproperty_callable, context, deferred, key);
+ LoadObjectField(deferred, JSPromiseCapability::kRejectOffset);
Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate);
CallStub(promise_handle_reject, context, deferred_promise, on_reject,
@@ -991,5 +1116,51 @@ TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) {
}
}
+TF_BUILTIN(PromiseGetCapabilitiesExecutor, PromiseBuiltinsAssembler) {
+ Node* const resolve = Parameter(1);
+ Node* const reject = Parameter(2);
+ Node* const context = Parameter(5);
+
+ Node* const capability = LoadContextElement(
+ context, GetPromiseCapabilityExecutor::kCapabilitySlot);
+
+ Label if_alreadyinvoked(this, Label::kDeferred);
+ GotoIf(WordNotEqual(
+ LoadObjectField(capability, JSPromiseCapability::kResolveOffset),
+ UndefinedConstant()),
+ &if_alreadyinvoked);
+ GotoIf(WordNotEqual(
+ LoadObjectField(capability, JSPromiseCapability::kRejectOffset),
+ UndefinedConstant()),
+ &if_alreadyinvoked);
+
+ StoreObjectField(capability, JSPromiseCapability::kResolveOffset, resolve);
+ StoreObjectField(capability, JSPromiseCapability::kRejectOffset, reject);
+
+ Return(UndefinedConstant());
+
+ Bind(&if_alreadyinvoked);
+ Node* message = SmiConstant(MessageTemplate::kPromiseExecutorAlreadyInvoked);
+ Return(CallRuntime(Runtime::kThrowTypeError, context, message));
+}
+
+TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) {
+ Node* constructor = Parameter(1);
+ Node* debug_event = Parameter(2);
+ Node* context = Parameter(5);
+
+ CSA_ASSERT_JS_ARGC_EQ(this, 2);
+
+ Return(NewPromiseCapability(context, constructor, debug_event));
+}
+
+TF_BUILTIN(NewInternalPromiseCapability, PromiseBuiltinsAssembler) {
+ Node* parent = Parameter(1);
+ Node* context = Parameter(4);
+ CSA_ASSERT_JS_ARGC_EQ(this, 1);
+
+ Return(NewInternalPromiseCapability(context, parent));
+}
+
} // namespace internal
} // namespace v8

Powered by Google App Engine
This is Rietveld 408576698