Commit a5f3c4d1 authored by gsathya's avatar gsathya Committed by Commit bot

[promises] Move various promise reject functions to TF

BUG=v8:5343

Review-Url: https://codereview.chromium.org/2616673003
Cr-Commit-Position: refs/heads/master@{#42113}
parent 45c11887
...@@ -1899,6 +1899,9 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object, ...@@ -1899,6 +1899,9 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(promise_fun, "resolve", Builtins::kPromiseResolve, 1, SimpleInstallFunction(promise_fun, "resolve", Builtins::kPromiseResolve, 1,
true, DONT_ENUM); true, DONT_ENUM);
SimpleInstallFunction(promise_fun, "reject", Builtins::kPromiseReject, 1,
true, DONT_ENUM);
Handle<Map> prototype_map(prototype->map()); Handle<Map> prototype_map(prototype->map());
Map::SetShouldBeFastPrototypeMap(prototype_map, true, isolate); Map::SetShouldBeFastPrototypeMap(prototype_map, true, isolate);
...@@ -1914,14 +1917,6 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object, ...@@ -1914,14 +1917,6 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
isolate, function, Context::PROMISE_INTERNAL_CONSTRUCTOR_INDEX); isolate, function, Context::PROMISE_INTERNAL_CONSTRUCTOR_INDEX);
} }
{ // Internal: PromiseCreateAndSet
Handle<JSFunction> function =
SimpleCreateFunction(isolate, factory->empty_string(),
Builtins::kPromiseCreateAndSet, 2, false);
InstallWithIntrinsicDefaultProto(isolate, function,
Context::PROMISE_CREATE_AND_SET_INDEX);
}
{ // Internal: IsPromise { // Internal: IsPromise
Handle<JSFunction> function = SimpleCreateFunction( Handle<JSFunction> function = SimpleCreateFunction(
isolate, factory->empty_string(), Builtins::kIsPromise, 1, false); isolate, factory->empty_string(), Builtins::kIsPromise, 1, false);
...@@ -1981,7 +1976,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object, ...@@ -1981,7 +1976,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
isolate); isolate);
info = info =
factory->NewSharedFunctionInfo(factory->empty_string(), code, false); factory->NewSharedFunctionInfo(factory->empty_string(), code, false);
info->set_internal_formal_parameter_count(2); info->set_internal_formal_parameter_count(1);
info->set_length(1); info->set_length(1);
native_context()->set_promise_reject_shared_fun(*info); native_context()->set_promise_reject_shared_fun(*info);
} }
......
...@@ -898,27 +898,36 @@ void PromiseBuiltinsAssembler::PromiseFulfill( ...@@ -898,27 +898,36 @@ void PromiseBuiltinsAssembler::PromiseFulfill(
// ES#sec-promise-reject-functions // ES#sec-promise-reject-functions
// Promise Reject Functions // Promise Reject Functions
BUILTIN(PromiseRejectClosure) { TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) {
HandleScope scope(isolate); Node* const value = Parameter(1);
Node* const context = Parameter(4);
Label out(this);
Handle<Context> context(isolate->context(), isolate); // 3. Let alreadyResolved be F.[[AlreadyResolved]].
int has_already_visited_slot = PromiseUtils::kAlreadyVisitedSlot;
if (PromiseUtils::HasAlreadyVisited(context)) { Node* const has_already_visited =
return isolate->heap()->undefined_value(); LoadContextElement(context, has_already_visited_slot);
}
// 4. If alreadyResolved.[[Value]] is true, return undefined.
GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out);
// 5.Set alreadyResolved.[[Value]] to true.
StoreContextElementNoWriteBarrier(context, has_already_visited_slot,
SmiConstant(1));
PromiseUtils::SetAlreadyVisited(context); // 2. Let promise be F.[[Promise]].
Handle<Object> value = args.atOrUndefined(isolate, 1); Node* const promise =
Handle<JSObject> promise = handle(PromiseUtils::GetPromise(context), isolate); LoadContextElement(context, IntPtrConstant(PromiseUtils::kPromiseSlot));
Handle<Object> debug_event = Node* const debug_event = LoadContextElement(
handle(PromiseUtils::GetDebugEvent(context), isolate); context, IntPtrConstant(PromiseUtils::kDebugEventSlot));
MaybeHandle<Object> maybe_result;
Handle<Object> argv[] = {promise, value, debug_event}; CallRuntime(Runtime::kPromiseReject, context, promise, value, debug_event);
RETURN_FAILURE_ON_EXCEPTION( Return(UndefinedConstant());
isolate, Execution::Call(isolate, isolate->promise_internal_reject(),
isolate->factory()->undefined_value(), Bind(&out);
arraysize(argv), argv)); Return(UndefinedConstant());
return isolate->heap()->undefined_value();
} }
TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) {
...@@ -1037,15 +1046,6 @@ TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { ...@@ -1037,15 +1046,6 @@ TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) {
Return(AllocateAndInitJSPromise(context, parent)); Return(AllocateAndInitJSPromise(context, parent));
} }
TF_BUILTIN(PromiseCreateAndSet, PromiseBuiltinsAssembler) {
Node* const status = Parameter(1);
Node* const result = Parameter(2);
Node* const context = Parameter(5);
Node* const instance = AllocateAndSetJSPromise(context, status, result);
Return(instance);
}
TF_BUILTIN(IsPromise, PromiseBuiltinsAssembler) { TF_BUILTIN(IsPromise, PromiseBuiltinsAssembler) {
Node* const maybe_promise = Parameter(1); Node* const maybe_promise = Parameter(1);
Label if_notpromise(this, Label::kDeferred); Label if_notpromise(this, Label::kDeferred);
...@@ -1100,21 +1100,21 @@ TF_BUILTIN(PromiseResolveClosure, PromiseBuiltinsAssembler) { ...@@ -1100,21 +1100,21 @@ TF_BUILTIN(PromiseResolveClosure, PromiseBuiltinsAssembler) {
Label out(this); Label out(this);
// 3. Let alreadyResolved be F.[[AlreadyResolved]]. // 3. Let alreadyResolved be F.[[AlreadyResolved]].
Node* const has_already_visited_slot = int has_already_visited_slot = PromiseUtils::kAlreadyVisitedSlot;
IntPtrConstant(PromiseUtils::kAlreadyVisitedSlot);
Node* const has_already_visited = Node* const has_already_visited =
LoadFixedArrayElement(context, has_already_visited_slot); LoadContextElement(context, has_already_visited_slot);
// 4. If alreadyResolved.[[Value]] is true, return undefined. // 4. If alreadyResolved.[[Value]] is true, return undefined.
GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out); GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out);
// 5.Set alreadyResolved.[[Value]] to true. // 5.Set alreadyResolved.[[Value]] to true.
StoreFixedArrayElement(context, has_already_visited_slot, SmiConstant(1)); StoreContextElementNoWriteBarrier(context, has_already_visited_slot,
SmiConstant(1));
// 2. Let promise be F.[[Promise]]. // 2. Let promise be F.[[Promise]].
Node* const promise = LoadFixedArrayElement( Node* const promise =
context, IntPtrConstant(PromiseUtils::kPromiseSlot)); LoadContextElement(context, IntPtrConstant(PromiseUtils::kPromiseSlot));
InternalResolvePromise(context, promise, value); InternalResolvePromise(context, promise, value);
Return(UndefinedConstant()); Return(UndefinedConstant());
...@@ -1402,5 +1402,49 @@ TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) { ...@@ -1402,5 +1402,49 @@ TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) {
Return(NewPromiseCapability(context, constructor, debug_event)); Return(NewPromiseCapability(context, constructor, debug_event));
} }
TF_BUILTIN(PromiseReject, PromiseBuiltinsAssembler) {
// 1. Let C be the this value.
Node* const receiver = Parameter(0);
Node* const reason = Parameter(1);
Node* const context = Parameter(4);
// 2. If Type(C) is not Object, throw a TypeError exception.
ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
"PromiseReject");
Label if_nativepromise(this), if_custompromise(this, Label::kDeferred);
Node* const native_context = LoadNativeContext(context);
Node* const promise_fun =
LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
Branch(WordEqual(promise_fun, receiver), &if_nativepromise,
&if_custompromise);
Bind(&if_nativepromise);
{
Node* const promise = AllocateAndSetJSPromise(
context, SmiConstant(v8::Promise::kRejected), reason);
CallRuntime(Runtime::kPromiseRejectEventFromStack, context, promise,
reason);
Return(promise);
}
Bind(&if_custompromise);
{
// 3. Let promiseCapability be ? NewPromiseCapability(C).
Node* const capability = NewPromiseCapability(context, receiver);
// 4. Perform ? Call(promiseCapability.[[Reject]], undefined, « r »).
Node* const reject =
LoadObjectField(capability, JSPromiseCapability::kRejectOffset);
Callable call_callable = CodeFactory::Call(isolate());
CallJS(call_callable, context, reject, UndefinedConstant(), reason);
// 5. Return promiseCapability.[[Promise]].
Node* const promise =
LoadObjectField(capability, JSPromiseCapability::kPromiseOffset);
Return(promise);
}
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -626,15 +626,15 @@ namespace internal { ...@@ -626,15 +626,15 @@ namespace internal {
TFJ(PromiseInternalConstructor, 1) \ TFJ(PromiseInternalConstructor, 1) \
TFJ(IsPromise, 1) \ TFJ(IsPromise, 1) \
TFJ(PromiseResolveClosure, 1) \ TFJ(PromiseResolveClosure, 1) \
CPP(PromiseRejectClosure) \ TFJ(PromiseRejectClosure, 1) \
TFJ(PromiseThen, 2) \ TFJ(PromiseThen, 2) \
TFJ(PromiseCatch, 1) \ TFJ(PromiseCatch, 1) \
TFJ(PromiseCreateAndSet, 2) \
TFJ(PerformPromiseThen, 4) \ TFJ(PerformPromiseThen, 4) \
TFJ(ResolvePromise, 2) \ TFJ(ResolvePromise, 2) \
TFS(PromiseHandleReject, BUILTIN, kNoExtraICState, PromiseHandleReject) \ TFS(PromiseHandleReject, BUILTIN, kNoExtraICState, PromiseHandleReject) \
TFJ(PromiseHandle, 6) \ TFJ(PromiseHandle, 6) \
TFJ(PromiseResolve, 1) \ TFJ(PromiseResolve, 1) \
TFJ(PromiseReject, 1) \
\ \
/* Proxy */ \ /* Proxy */ \
CPP(ProxyConstructor) \ CPP(ProxyConstructor) \
......
...@@ -106,7 +106,6 @@ enum ContextLookupFlags { ...@@ -106,7 +106,6 @@ enum ContextLookupFlags {
V(PROMISE_CREATE_INDEX, JSFunction, promise_create) \ V(PROMISE_CREATE_INDEX, JSFunction, promise_create) \
V(PROMISE_FUNCTION_INDEX, JSFunction, promise_function) \ V(PROMISE_FUNCTION_INDEX, JSFunction, promise_function) \
V(PROMISE_REJECT_INDEX, JSFunction, promise_reject) \ V(PROMISE_REJECT_INDEX, JSFunction, promise_reject) \
V(PROMISE_INTERNAL_REJECT_INDEX, JSFunction, promise_internal_reject) \
V(PROMISE_ID_RESOLVE_HANDLER_INDEX, JSFunction, promise_id_resolve_handler) \ V(PROMISE_ID_RESOLVE_HANDLER_INDEX, JSFunction, promise_id_resolve_handler) \
V(PROMISE_ID_REJECT_HANDLER_INDEX, JSFunction, promise_id_reject_handler) \ V(PROMISE_ID_REJECT_HANDLER_INDEX, JSFunction, promise_id_reject_handler) \
V(RANGE_ERROR_FUNCTION_INDEX, JSFunction, range_error_function) \ V(RANGE_ERROR_FUNCTION_INDEX, JSFunction, range_error_function) \
......
...@@ -46,26 +46,6 @@ function DoRejectPromise(promise, reason) { ...@@ -46,26 +46,6 @@ function DoRejectPromise(promise, reason) {
%PromiseReject(promise, reason, true); %PromiseReject(promise, reason, true);
} }
// ES#sec-promise.reject
// Promise.reject ( x )
function PromiseReject(r) {
if (!IS_RECEIVER(this)) {
throw %make_type_error(kCalledOnNonObject, PromiseReject);
}
if (this === GlobalPromise) {
// Optimized case, avoid extra closure.
var promise = %promise_create_and_set(kRejected, r);
// Trigger debug events if the debugger is on, as Promise.reject is
// equivalent to throwing an exception directly.
%PromiseRejectEventFromStack(promise, r);
return promise;
} else {
var promiseCapability = %new_promise_capability(this, true);
%_Call(promiseCapability.reject, UNDEFINED, r);
return promiseCapability.promise;
}
}
// Combinators. // Combinators.
// ES#sec-promise.all // ES#sec-promise.all
...@@ -174,7 +154,6 @@ function MarkPromiseAsHandled(promise) { ...@@ -174,7 +154,6 @@ function MarkPromiseAsHandled(promise) {
// Install exported functions. // Install exported functions.
utils.InstallFunctions(GlobalPromise, DONT_ENUM, [ utils.InstallFunctions(GlobalPromise, DONT_ENUM, [
"reject", PromiseReject,
"all", PromiseAll, "all", PromiseAll,
"race", PromiseRace, "race", PromiseRace,
]); ]);
...@@ -182,8 +161,6 @@ utils.InstallFunctions(GlobalPromise, DONT_ENUM, [ ...@@ -182,8 +161,6 @@ utils.InstallFunctions(GlobalPromise, DONT_ENUM, [
%InstallToContext([ %InstallToContext([
"promise_create", PromiseCreate, "promise_create", PromiseCreate,
"promise_reject", DoRejectPromise, "promise_reject", DoRejectPromise,
// TODO(gsathya): Remove this once we update the promise builtin.
"promise_internal_reject", RejectPromise,
"promise_id_resolve_handler", PromiseIdResolveHandler, "promise_id_resolve_handler", PromiseIdResolveHandler,
"promise_id_reject_handler", PromiseIdRejectHandler "promise_id_reject_handler", PromiseIdRejectHandler
]); ]);
......
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