[JSC] Merge PromiseReactions
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Dec 2016 15:32:27 +0000 (15:32 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Dec 2016 15:32:27 +0000 (15:32 +0000)
https://bugs.webkit.org/show_bug.cgi?id=165526

Reviewed by Sam Weinig.

Our promise implementation has two arrays per Promise; promiseFulfillReactions and promiseRejectReactions.
And everytime we call `promise.then`, we create two promise reactions for fullfill and reject.
However, these two reactions and the arrays for reactions can be merged into one array and one reaction.
It reduces the unnecessary object allocations.

No behavior change.

* builtins/BuiltinNames.h:
* builtins/PromiseOperations.js:
(globalPrivate.newPromiseReaction):
(globalPrivate.triggerPromiseReactions):
(globalPrivate.rejectPromise):
(globalPrivate.fulfillPromise):
(globalPrivate.promiseReactionJob):
(globalPrivate.initializePromise):
* builtins/PromisePrototype.js:
(then):
* runtime/JSPromise.cpp:
(JSC::JSPromise::finishCreation):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@209455 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/builtins/BuiltinNames.h
Source/JavaScriptCore/builtins/PromiseOperations.js
Source/JavaScriptCore/builtins/PromisePrototype.js
Source/JavaScriptCore/runtime/JSPromise.cpp

index 8bba55b..43673b0 100644 (file)
@@ -1,3 +1,30 @@
+2016-12-07  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [JSC] Merge PromiseReactions
+        https://bugs.webkit.org/show_bug.cgi?id=165526
+
+        Reviewed by Sam Weinig.
+
+        Our promise implementation has two arrays per Promise; promiseFulfillReactions and promiseRejectReactions.
+        And everytime we call `promise.then`, we create two promise reactions for fullfill and reject.
+        However, these two reactions and the arrays for reactions can be merged into one array and one reaction.
+        It reduces the unnecessary object allocations.
+
+        No behavior change.
+
+        * builtins/BuiltinNames.h:
+        * builtins/PromiseOperations.js:
+        (globalPrivate.newPromiseReaction):
+        (globalPrivate.triggerPromiseReactions):
+        (globalPrivate.rejectPromise):
+        (globalPrivate.fulfillPromise):
+        (globalPrivate.promiseReactionJob):
+        (globalPrivate.initializePromise):
+        * builtins/PromisePrototype.js:
+        (then):
+        * runtime/JSPromise.cpp:
+        (JSC::JSPromise::finishCreation):
+
 2016-12-06  Mark Lam  <mark.lam@apple.com>
 
         GetByID IC is wrongly unwrapping the global proxy this value for getter/setters.
index fd78a05..f9045bf 100644 (file)
@@ -83,11 +83,11 @@ namespace JSC {
     macro(getTemplateObject) \
     macro(templateRegistryKey) \
     macro(enqueueJob) \
-    macro(handler) \
     macro(promiseState) \
-    macro(promiseFulfillReactions) \
-    macro(promiseRejectReactions) \
+    macro(promiseReactions) \
     macro(promiseResult) \
+    macro(onFulfilled) \
+    macro(onRejected) \
     macro(push) \
     macro(repeatCharacter) \
     macro(capabilities) \
index f4a09d4..61564e7 100644 (file)
@@ -35,13 +35,14 @@ function isPromise(promise)
 }
 
 @globalPrivate
-function newPromiseReaction(capability, handler)
+function newPromiseReaction(capability, onFulfilled, onRejected)
 {
     "use strict";
 
     return {
         @capabilities: capability,
-        @handler: handler
+        @onFulfilled: onFulfilled,
+        @onRejected: onRejected,
     };
 }
 
@@ -84,12 +85,12 @@ function newPromiseCapability(constructor)
 }
 
 @globalPrivate
-function triggerPromiseReactions(reactions, argument)
+function triggerPromiseReactions(state, reactions, argument)
 {
     "use strict";
 
     for (var index = 0, length = reactions.length; index < length; ++index)
-        @enqueueJob(@promiseReactionJob, [reactions[index], argument]);
+        @enqueueJob(@promiseReactionJob, [state, reactions[index], argument]);
 }
 
 @globalPrivate
@@ -97,15 +98,14 @@ function rejectPromise(promise, reason)
 {
     "use strict";
 
-    var reactions = promise.@promiseRejectReactions;
+    var reactions = promise.@promiseReactions;
     promise.@promiseResult = reason;
-    promise.@promiseFulfillReactions = @undefined;
-    promise.@promiseRejectReactions = @undefined;
+    promise.@promiseReactions = @undefined;
     promise.@promiseState = @promiseStateRejected;
 
     @InspectorInstrumentation.promiseRejected(promise, reason, reactions);
 
-    @triggerPromiseReactions(reactions, reason);
+    @triggerPromiseReactions(@promiseStateRejected, reactions, reason);
 }
 
 @globalPrivate
@@ -113,15 +113,14 @@ function fulfillPromise(promise, value)
 {
     "use strict";
 
-    var reactions = promise.@promiseFulfillReactions;
+    var reactions = promise.@promiseReactions;
     promise.@promiseResult = value;
-    promise.@promiseFulfillReactions = @undefined;
-    promise.@promiseRejectReactions = @undefined;
+    promise.@promiseReactions = @undefined;
     promise.@promiseState = @promiseStateFulfilled;
 
     @InspectorInstrumentation.promiseFulfilled(promise, value, reactions);
 
-    @triggerPromiseReactions(reactions, value);
+    @triggerPromiseReactions(@promiseStateFulfilled, reactions, value);
 }
 
 @globalPrivate
@@ -172,15 +171,16 @@ function createResolvingFunctions(promise)
 }
 
 @globalPrivate
-function promiseReactionJob(reaction, argument)
+function promiseReactionJob(state, reaction, argument)
 {
     "use strict";
 
     var promiseCapability = reaction.@capabilities;
 
     var result;
+    var handler = (state === @promiseStateFulfilled) ? reaction.@onFulfilled: reaction.@onRejected;
     try {
-        result = reaction.@handler.@call(@undefined, argument);
+        result = handler(argument);
     } catch (error) {
         return promiseCapability.@reject.@call(@undefined, error);
     }
@@ -211,8 +211,7 @@ function initializePromise(executor)
         @throwTypeError("Promise constructor takes a function argument");
 
     this.@promiseState = @promiseStatePending;
-    this.@promiseFulfillReactions = [];
-    this.@promiseRejectReactions = [];
+    this.@promiseReactions = [];
 
     var resolvingFunctions = @createResolvingFunctions(this);
     try {
index 184955a..6065ad8 100644 (file)
@@ -47,18 +47,13 @@ function then(onFulfilled, onRejected)
     if (typeof onRejected !== "function")
         onRejected = function (argument) { throw argument; };
 
-    var fulfillReaction = @newPromiseReaction(resultCapability, onFulfilled);
-    var rejectReaction = @newPromiseReaction(resultCapability, onRejected);
+    var reaction = @newPromiseReaction(resultCapability, onFulfilled, onRejected);
 
     var state = this.@promiseState;
-
-    if (state === @promiseStatePending) {
-        @putByValDirect(this.@promiseFulfillReactions, this.@promiseFulfillReactions.length, fulfillReaction)
-        @putByValDirect(this.@promiseRejectReactions, this.@promiseRejectReactions.length, rejectReaction)
-    } else if (state === @promiseStateFulfilled)
-        @enqueueJob(@promiseReactionJob, [fulfillReaction, this.@promiseResult]);
-    else if (state === @promiseStateRejected)
-        @enqueueJob(@promiseReactionJob, [rejectReaction, this.@promiseResult]);
+    if (state === @promiseStatePending)
+        @putByValDirect(this.@promiseReactions, this.@promiseReactions.length, reaction);
+    else
+        @enqueueJob(@promiseReactionJob, [state, reaction, this.@promiseResult]);
 
     return resultCapability.@promise;
 }
index 29b54ed..958d45b 100644 (file)
@@ -57,8 +57,7 @@ void JSPromise::finishCreation(VM& vm)
 {
     Base::finishCreation(vm);
     putDirect(vm, vm.propertyNames->builtinNames().promiseStatePrivateName(), jsNumber(static_cast<unsigned>(Status::Pending)));
-    putDirect(vm, vm.propertyNames->builtinNames().promiseFulfillReactionsPrivateName(), jsUndefined());
-    putDirect(vm, vm.propertyNames->builtinNames().promiseRejectReactionsPrivateName(), jsUndefined());
+    putDirect(vm, vm.propertyNames->builtinNames().promiseReactionsPrivateName(), jsUndefined());
     putDirect(vm, vm.propertyNames->builtinNames().promiseResultPrivateName(), jsUndefined());
 }