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,
SimpleInstallFunction(promise_fun, "resolve", Builtins::kPromiseResolve, 1,
true, DONT_ENUM);
SimpleInstallFunction(promise_fun, "reject", Builtins::kPromiseReject, 1,
true, DONT_ENUM);
Handle<Map> prototype_map(prototype->map());
Map::SetShouldBeFastPrototypeMap(prototype_map, true, isolate);
......@@ -1914,14 +1917,6 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
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
Handle<JSFunction> function = SimpleCreateFunction(
isolate, factory->empty_string(), Builtins::kIsPromise, 1, false);
......@@ -1981,7 +1976,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
isolate);
info =
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);
native_context()->set_promise_reject_shared_fun(*info);
}
......
......@@ -898,27 +898,36 @@ void PromiseBuiltinsAssembler::PromiseFulfill(
// ES#sec-promise-reject-functions
// Promise Reject Functions
BUILTIN(PromiseRejectClosure) {
HandleScope scope(isolate);
TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) {
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)) {
return isolate->heap()->undefined_value();
}
Node* const has_already_visited =
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);
Handle<Object> value = args.atOrUndefined(isolate, 1);
Handle<JSObject> promise = handle(PromiseUtils::GetPromise(context), isolate);
Handle<Object> debug_event =
handle(PromiseUtils::GetDebugEvent(context), isolate);
MaybeHandle<Object> maybe_result;
Handle<Object> argv[] = {promise, value, debug_event};
RETURN_FAILURE_ON_EXCEPTION(
isolate, Execution::Call(isolate, isolate->promise_internal_reject(),
isolate->factory()->undefined_value(),
arraysize(argv), argv));
return isolate->heap()->undefined_value();
// 2. Let promise be F.[[Promise]].
Node* const promise =
LoadContextElement(context, IntPtrConstant(PromiseUtils::kPromiseSlot));
Node* const debug_event = LoadContextElement(
context, IntPtrConstant(PromiseUtils::kDebugEventSlot));
CallRuntime(Runtime::kPromiseReject, context, promise, value, debug_event);
Return(UndefinedConstant());
Bind(&out);
Return(UndefinedConstant());
}
TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) {
......@@ -1037,15 +1046,6 @@ TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) {
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) {
Node* const maybe_promise = Parameter(1);
Label if_notpromise(this, Label::kDeferred);
......@@ -1100,21 +1100,21 @@ TF_BUILTIN(PromiseResolveClosure, PromiseBuiltinsAssembler) {
Label out(this);
// 3. Let alreadyResolved be F.[[AlreadyResolved]].
Node* const has_already_visited_slot =
IntPtrConstant(PromiseUtils::kAlreadyVisitedSlot);
int has_already_visited_slot = PromiseUtils::kAlreadyVisitedSlot;
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.
GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out);
// 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]].
Node* const promise = LoadFixedArrayElement(
context, IntPtrConstant(PromiseUtils::kPromiseSlot));
Node* const promise =
LoadContextElement(context, IntPtrConstant(PromiseUtils::kPromiseSlot));
InternalResolvePromise(context, promise, value);
Return(UndefinedConstant());
......@@ -1402,5 +1402,49 @@ TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) {
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 v8
......@@ -626,15 +626,15 @@ namespace internal {
TFJ(PromiseInternalConstructor, 1) \
TFJ(IsPromise, 1) \
TFJ(PromiseResolveClosure, 1) \
CPP(PromiseRejectClosure) \
TFJ(PromiseRejectClosure, 1) \
TFJ(PromiseThen, 2) \
TFJ(PromiseCatch, 1) \
TFJ(PromiseCreateAndSet, 2) \
TFJ(PerformPromiseThen, 4) \
TFJ(ResolvePromise, 2) \
TFS(PromiseHandleReject, BUILTIN, kNoExtraICState, PromiseHandleReject) \
TFJ(PromiseHandle, 6) \
TFJ(PromiseResolve, 1) \
TFJ(PromiseReject, 1) \
\
/* Proxy */ \
CPP(ProxyConstructor) \
......
......@@ -106,7 +106,6 @@ enum ContextLookupFlags {
V(PROMISE_CREATE_INDEX, JSFunction, promise_create) \
V(PROMISE_FUNCTION_INDEX, JSFunction, promise_function) \
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_REJECT_HANDLER_INDEX, JSFunction, promise_id_reject_handler) \
V(RANGE_ERROR_FUNCTION_INDEX, JSFunction, range_error_function) \
......
......@@ -46,26 +46,6 @@ function DoRejectPromise(promise, reason) {
%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.
// ES#sec-promise.all
......@@ -174,7 +154,6 @@ function MarkPromiseAsHandled(promise) {
// Install exported functions.
utils.InstallFunctions(GlobalPromise, DONT_ENUM, [
"reject", PromiseReject,
"all", PromiseAll,
"race", PromiseRace,
]);
......@@ -182,8 +161,6 @@ utils.InstallFunctions(GlobalPromise, DONT_ENUM, [
%InstallToContext([
"promise_create", PromiseCreate,
"promise_reject", DoRejectPromise,
// TODO(gsathya): Remove this once we update the promise builtin.
"promise_internal_reject", RejectPromise,
"promise_id_resolve_handler", PromiseIdResolveHandler,
"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