Diff
Modified: trunk/JSTests/ChangeLog (251670 => 251671)
--- trunk/JSTests/ChangeLog 2019-10-28 20:50:47 UTC (rev 251670)
+++ trunk/JSTests/ChangeLog 2019-10-28 21:13:57 UTC (rev 251671)
@@ -1,3 +1,13 @@
+2019-10-28 Yusuke Suzuki <ysuz...@apple.com>
+
+ [JSC] Optimize Promise runtime functions
+ https://bugs.webkit.org/show_bug.cgi?id=203454
+
+ Reviewed by Keith Miller.
+
+ * microbenchmarks/promise-reject.js: Added.
+ * microbenchmarks/promise-resolve.js: Added.
+
2019-10-25 Ross Kirsling <ross.kirsl...@sony.com>
test262-runner should be able to pass JSC a feature flag
Added: trunk/JSTests/microbenchmarks/promise-reject.js (0 => 251671)
--- trunk/JSTests/microbenchmarks/promise-reject.js (rev 0)
+++ trunk/JSTests/microbenchmarks/promise-reject.js 2019-10-28 21:13:57 UTC (rev 251671)
@@ -0,0 +1,2 @@
+for (var i = 0; i < 1e6; ++i)
+ Promise.reject(42);
Added: trunk/JSTests/microbenchmarks/promise-resolve.js (0 => 251671)
--- trunk/JSTests/microbenchmarks/promise-resolve.js (rev 0)
+++ trunk/JSTests/microbenchmarks/promise-resolve.js 2019-10-28 21:13:57 UTC (rev 251671)
@@ -0,0 +1,2 @@
+for (var i = 0; i < 1e6; ++i)
+ Promise.resolve(42);
Modified: trunk/LayoutTests/ChangeLog (251670 => 251671)
--- trunk/LayoutTests/ChangeLog 2019-10-28 20:50:47 UTC (rev 251670)
+++ trunk/LayoutTests/ChangeLog 2019-10-28 21:13:57 UTC (rev 251671)
@@ -1,3 +1,12 @@
+2019-10-28 Yusuke Suzuki <ysuz...@apple.com>
+
+ [JSC] Optimize Promise runtime functions
+ https://bugs.webkit.org/show_bug.cgi?id=203454
+
+ Reviewed by Keith Miller.
+
+ * inspector/console/message-stack-trace-expected.txt:
+
2019-10-28 Truitt Savell <tsav...@apple.com>
Two imported tests from r251591 are failing
Modified: trunk/LayoutTests/inspector/console/message-stack-trace-expected.txt (251670 => 251671)
--- trunk/LayoutTests/inspector/console/message-stack-trace-expected.txt 2019-10-28 20:50:47 UTC (rev 251670)
+++ trunk/LayoutTests/inspector/console/message-stack-trace-expected.txt 2019-10-28 21:13:57 UTC (rev 251671)
@@ -27,8 +27,9 @@
CALL STACK:
0: [N] (anonymous function)
1: [N] rejectPromise
-2: [N] reject
-3: [F] triggerUnhandledRejectionPromiseReject
+2: [N] rejectPromiseWithFirstResolvingFunctionCallCheck
+3: [N] reject
+4: [F] triggerUnhandledRejectionPromiseReject
-- Running test case: Console.StackTrace.UnhandledPromiseRejection.ExplicitReject
CALL STACK:
Modified: trunk/Source/_javascript_Core/ChangeLog (251670 => 251671)
--- trunk/Source/_javascript_Core/ChangeLog 2019-10-28 20:50:47 UTC (rev 251670)
+++ trunk/Source/_javascript_Core/ChangeLog 2019-10-28 21:13:57 UTC (rev 251671)
@@ -1,5 +1,46 @@
2019-10-28 Yusuke Suzuki <ysuz...@apple.com>
+ [JSC] Optimize Promise runtime functions
+ https://bugs.webkit.org/show_bug.cgi?id=203454
+
+ Reviewed by Keith Miller.
+
+ This patch optimizes Promise runtime functions a bit.
+
+ 1. Add fast paths to Promise.resolve / Promise.reject.
+ 2. Remove state check in async-functions. Unlike generators, async-function's next function is not exposed to users.
+ It is called by runtime so we can control state perfectly.
+ 3. Add "enqueueJob" name to make sampling profiler work for this function.
+ 4. Make Promise/InternalPromise constructor inlinable size
+
+ ToT Patched
+
+ promise-creation-many 25.5794+-0.3681 ^ 22.5410+-0.3229 ^ definitely 1.1348x faster
+ promise-resolve 32.3793+-0.4252 ^ 9.4219+-0.1114 ^ definitely 3.4366x faster
+ promise-reject 108.5968+-0.7741 ^ 36.9383+-0.3770 ^ definitely 2.9400x faster
+
+ * builtins/AsyncFunctionPrototype.js:
+ (globalPrivate.asyncFunctionResume):
+ * builtins/PromiseConstructor.js:
+ (reject):
+ (resolve):
+ (nakedConstructor.Promise.reject):
+ (nakedConstructor.Promise):
+ (nakedConstructor.InternalPromise.reject):
+ (nakedConstructor.InternalPromise):
+ (nakedConstructor.Promise.resolve): Deleted.
+ (nakedConstructor.InternalPromise.resolve): Deleted.
+ * builtins/PromiseOperations.js:
+ (globalPrivate.newPromiseCapability.resolve):
+ (globalPrivate.newPromiseCapability.reject):
+ (globalPrivate.newPromiseCapability):
+ (globalPrivate.promiseResolveSlow):
+ (globalPrivate.promiseRejectSlow):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::init):
+
+2019-10-28 Yusuke Suzuki <ysuz...@apple.com>
+
[JSC] Use FTLOutput::callWithoutSideEffects if operation does not have side effects
https://bugs.webkit.org/show_bug.cgi?id=203485
Modified: trunk/Source/_javascript_Core/builtins/AsyncFunctionPrototype.js (251670 => 251671)
--- trunk/Source/_javascript_Core/builtins/AsyncFunctionPrototype.js 2019-10-28 20:50:47 UTC (rev 251670)
+++ trunk/Source/_javascript_Core/builtins/AsyncFunctionPrototype.js 2019-10-28 21:13:57 UTC (rev 251671)
@@ -34,26 +34,23 @@
var state = @getGeneratorInternalField(generator, @generatorFieldState);
var value = @undefined;
- if (state === @GeneratorStateCompleted || (resumeMode !== @GeneratorResumeModeNormal && resumeMode !== @GeneratorResumeModeThrow))
- @throwTypeError("Async function illegally resumed");
-
try {
@putGeneratorInternalField(generator, @generatorFieldState, @GeneratorStateExecuting);
value = @getGeneratorInternalField(generator, @generatorFieldNext).@call(@getGeneratorInternalField(generator, @generatorFieldThis), generator, state, sentValue, resumeMode, @getGeneratorInternalField(generator, @generatorFieldFrame));
if (@getGeneratorInternalField(generator, @generatorFieldState) === @GeneratorStateExecuting) {
- @putGeneratorInternalField(generator, @generatorFieldState, @GeneratorStateCompleted);
@resolvePromiseWithFirstResolvingFunctionCallCheck(promise, value);
return promise;
}
} catch (error) {
- @putGeneratorInternalField(generator, @generatorFieldState, @GeneratorStateCompleted);
@rejectPromiseWithFirstResolvingFunctionCallCheck(promise, error);
return promise;
}
+ var capturedGenerator = generator;
+ var capturedPromise = promise;
@resolveWithoutPromise(value,
- function(value) { @asyncFunctionResume(generator, promise, value, @GeneratorResumeModeNormal); },
- function(error) { @asyncFunctionResume(generator, promise, error, @GeneratorResumeModeThrow); });
+ function(value) { @asyncFunctionResume(capturedGenerator, capturedPromise, value, @GeneratorResumeModeNormal); },
+ function(error) { @asyncFunctionResume(capturedGenerator, capturedPromise, error, @GeneratorResumeModeThrow); });
return promise;
}
Modified: trunk/Source/_javascript_Core/builtins/PromiseConstructor.js (251670 => 251671)
--- trunk/Source/_javascript_Core/builtins/PromiseConstructor.js 2019-10-28 20:50:47 UTC (rev 251670)
+++ trunk/Source/_javascript_Core/builtins/PromiseConstructor.js 2019-10-28 21:13:57 UTC (rev 251671)
@@ -195,11 +195,13 @@
if (!@isObject(this))
@throwTypeError("|this| is not an object");
- var promiseCapability = @newPromiseCapability(this);
+ if (this === @Promise) {
+ var promise = @newPromise();
+ @rejectPromiseWithFirstResolvingFunctionCallCheck(promise, reason);
+ return promise;
+ }
- promiseCapability.@reject.@call(@undefined, reason);
-
- return promiseCapability.@promise;
+ return @promiseRejectSlow(this, reason);
}
function resolve(value)
@@ -215,11 +217,13 @@
return value;
}
- var promiseCapability = @newPromiseCapability(this);
+ if (this === @Promise) {
+ var promise = @newPromise();
+ @resolvePromiseWithFirstResolvingFunctionCallCheck(promise, value);
+ return promise;
+ }
- promiseCapability.@resolve.@call(@undefined, value);
-
- return promiseCapability.@promise;
+ return @promiseResolveSlow(this, value);
}
@nakedConstructor
@@ -230,19 +234,20 @@
if (typeof executor !== "function")
@throwTypeError("Promise constructor takes a function argument");
- var promise = @createPromise(new.target, /* isInternalPromise */ false);
+ var promise = @createPromise(this, /* isInternalPromise */ false);
var capturedPromise = promise;
- function @resolve(resolution) {
- return @resolvePromiseWithFirstResolvingFunctionCallCheck(capturedPromise, resolution);
- }
-
- function @reject(reason) {
+ // FIXME: We should allow using function-declaration here.
+ // https://bugs.webkit.org/show_bug.cgi?id=203502
+ var @reject = function @reject(reason) {
return @rejectPromiseWithFirstResolvingFunctionCallCheck(capturedPromise, reason);
- }
+ };
try {
- executor(@resolve, @reject);
+ executor(
+ function @resolve(resolution) {
+ return @resolvePromiseWithFirstResolvingFunctionCallCheck(capturedPromise, resolution);
+ }, @reject);
} catch (error) {
@reject(error);
}
@@ -258,19 +263,20 @@
if (typeof executor !== "function")
@throwTypeError("InternalPromise constructor takes a function argument");
- var promise = @createPromise(new.target, /* isInternalPromise */ true);
+ var promise = @createPromise(this, /* isInternalPromise */ true);
var capturedPromise = promise;
- function @resolve(resolution) {
- return @resolvePromiseWithFirstResolvingFunctionCallCheck(capturedPromise, resolution);
- }
-
- function @reject(reason) {
+ // FIXME: We should allow using function-declaration here.
+ // https://bugs.webkit.org/show_bug.cgi?id=203502
+ var @reject = function @reject(reason) {
return @rejectPromiseWithFirstResolvingFunctionCallCheck(capturedPromise, reason);
- }
+ };
try {
- executor(@resolve, @reject);
+ executor(
+ function @resolve(resolution) {
+ return @resolvePromiseWithFirstResolvingFunctionCallCheck(capturedPromise, resolution);
+ }, @reject);
} catch (error) {
@reject(error);
}
Modified: trunk/Source/_javascript_Core/builtins/PromiseOperations.js (251670 => 251671)
--- trunk/Source/_javascript_Core/builtins/PromiseOperations.js 2019-10-28 20:50:47 UTC (rev 251670)
+++ trunk/Source/_javascript_Core/builtins/PromiseOperations.js 2019-10-28 21:13:57 UTC (rev 251671)
@@ -82,9 +82,14 @@
if (constructor === @Promise) {
var promise = @newPromise();
- var resolvingFunctions = @createResolvingFunctions(promise);
- @putByIdDirectPrivate(resolvingFunctions, "promise", promise);
- return resolvingFunctions;
+ var capturedPromise = promise;
+ function @resolve(resolution) {
+ return @resolvePromiseWithFirstResolvingFunctionCallCheck(capturedPromise, resolution);
+ }
+ function @reject(reason) {
+ return @rejectPromiseWithFirstResolvingFunctionCallCheck(capturedPromise, reason);
+ }
+ return { @resolve, @reject, @promise: promise };
}
return @newPromiseCapabilitySlow(constructor);
@@ -91,6 +96,24 @@
}
@globalPrivate
+function promiseResolveSlow(constructor, value)
+{
+ @assert(constructor !== @Promise);
+ var promiseCapability = @newPromiseCapabilitySlow(constructor);
+ promiseCapability.@resolve.@call(@undefined, value);
+ return promiseCapability.@promise;
+}
+
+@globalPrivate
+function promiseRejectSlow(constructor, reason)
+{
+ @assert(constructor !== @Promise);
+ var promiseCapability = @newPromiseCapabilitySlow(constructor);
+ promiseCapability.@reject.@call(@undefined, reason);
+ return promiseCapability.@promise;
+}
+
+@globalPrivate
function newHandledRejectedPromise(error)
{
"use strict";
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (251670 => 251671)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2019-10-28 20:50:47 UTC (rev 251670)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2019-10-28 21:13:57 UTC (rev 251671)
@@ -990,7 +990,7 @@
GlobalPropertyInfo(vm.propertyNames->builtinNames().propertyIsEnumerablePrivateName(), privateFuncPropertyIsEnumerable, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
GlobalPropertyInfo(vm.propertyNames->builtinNames().ownKeysPrivateName(), privateFuncOwnKeys, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
GlobalPropertyInfo(vm.propertyNames->builtinNames().importModulePrivateName(), privateFuncImportModule, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
- GlobalPropertyInfo(vm.propertyNames->builtinNames().enqueueJobPrivateName(), JSFunction::create(vm, this, 0, String(), enqueueJob), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
+ GlobalPropertyInfo(vm.propertyNames->builtinNames().enqueueJobPrivateName(), JSFunction::create(vm, this, 0, "enqueueJob"_s, enqueueJob), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
GlobalPropertyInfo(vm.propertyNames->builtinNames().makeTypeErrorPrivateName(), privateFuncMakeTypeError, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
GlobalPropertyInfo(vm.propertyNames->builtinNames().typedArrayLengthPrivateName(), privateFuncTypedArrayLength, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
GlobalPropertyInfo(vm.propertyNames->builtinNames().typedArrayGetOriginalConstructorPrivateName(), privateFuncTypedArrayGetOriginalConstructor, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),