summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRuben Bridgewater <ruben@bridgewater.de>2018-08-07 01:21:09 +0200
committerRuben Bridgewater <ruben@bridgewater.de>2018-08-20 02:11:46 +0200
commit3479b1ca8206c88bac1f1ee8925a2d30759747d7 (patch)
tree1e64f365138d989e9a526fc195c0278adb7b2e34 /lib
parent0bdb95f4cffa7d672c23c60cdb6b779451d2ea33 (diff)
downloadandroid-node-v8-3479b1ca8206c88bac1f1ee8925a2d30759747d7.tar.gz
android-node-v8-3479b1ca8206c88bac1f1ee8925a2d30759747d7.tar.bz2
android-node-v8-3479b1ca8206c88bac1f1ee8925a2d30759747d7.zip
util,assert: improve performance
This significantly improves regular and typed array performance by not checking the indices keys anymore. This can be done with a V8 API that allows to only retrieve the non indices property keys. PR-URL: https://github.com/nodejs/node/pull/22197 Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Diffstat (limited to 'lib')
-rw-r--r--lib/internal/util/comparisons.js81
1 files changed, 37 insertions, 44 deletions
diff --git a/lib/internal/util/comparisons.js b/lib/internal/util/comparisons.js
index 9f636f31a3..729bd1c31e 100644
--- a/lib/internal/util/comparisons.js
+++ b/lib/internal/util/comparisons.js
@@ -4,6 +4,7 @@ const { compare } = process.binding('buffer');
const { isArrayBufferView } = require('internal/util/types');
const { internalBinding } = require('internal/bootstrap/loaders');
const { isDate, isMap, isRegExp, isSet } = internalBinding('types');
+const { getOwnNonIndexProperties } = process.binding('util');
const ReflectApply = Reflect.apply;
@@ -106,24 +107,11 @@ function strictDeepEqual(val1, val2, memos) {
if (val1.length !== val2.length) {
return false;
}
- const keys = objectKeys(val1);
- if (keys.length !== objectKeys(val2).length) {
+ const keys1 = getOwnNonIndexProperties(val1);
+ if (keys1.length !== getOwnNonIndexProperties(val2).length) {
return false;
}
- // Fast path for non sparse arrays (no key comparison for indices
- // properties).
- // See https://tc39.github.io/ecma262/#sec-ordinaryownpropertykeys
- if (val1.length === keys.length) {
- if (keys.length === 0 || keys[val1.length - 1] === `${val1.length - 1}`) {
- return keyCheck(val1, val2, kStrict, memos, kIsArray, []);
- }
- } else if (keys.length > val1.length &&
- keys[val1.length - 1] === `${val1.length - 1}`) {
- const minimalKeys = keys.slice(val1.length);
- return keyCheck(val1, val2, kStrict, memos, kIsArray, minimalKeys);
- }
- // Only set this to kIsArray in case the array is not sparse!
- return keyCheck(val1, val2, kStrict, memos, kNoIterator, keys);
+ return keyCheck(val1, val2, kStrict, memos, kIsArray, keys1);
}
if (val1Tag === '[object Object]') {
return keyCheck(val1, val2, kStrict, memos, kNoIterator);
@@ -148,18 +136,14 @@ function strictDeepEqual(val1, val2, memos) {
if (!areSimilarTypedArrays(val1, val2)) {
return false;
}
- // Buffer.compare returns true, so val1.length === val2.length
- // if they both only contain numeric keys, we don't need to exam further.
- const keys = objectKeys(val1);
- if (keys.length !== objectKeys(val2).length) {
+ // Buffer.compare returns true, so val1.length === val2.length. If they both
+ // only contain numeric keys, we don't need to exam further than checking
+ // the symbols.
+ const keys1 = getOwnNonIndexProperties(val1);
+ if (keys1.length !== getOwnNonIndexProperties(val2).length) {
return false;
}
- if (keys.length === val1.length) {
- return keyCheck(val1, val2, kStrict, memos, kNoIterator, []);
- }
- // Only compare the special keys.
- const minimalKeys = keys.slice(val1.length);
- return keyCheck(val1, val2, kStrict, memos, kNoIterator, minimalKeys);
+ return keyCheck(val1, val2, kStrict, memos, kNoIterator, keys1);
} else if (isSet(val1)) {
if (!isSet(val2) || val1.size !== val2.size) {
return false;
@@ -173,21 +157,10 @@ function strictDeepEqual(val1, val2, memos) {
// TODO: Make the valueOf checks safe.
} else if (typeof val1.valueOf === 'function') {
const val1Value = val1.valueOf();
- if (val1Value !== val1) {
- if (typeof val2.valueOf !== 'function') {
- return false;
- }
- if (!innerDeepEqual(val1Value, val2.valueOf(), true))
- return false;
- // Fast path for boxed primitive strings.
- if (typeof val1Value === 'string') {
- const keys = objectKeys(val1);
- if (keys.length !== objectKeys(val2).length) {
- return false;
- }
- const minimalKeys = keys.slice(val1.length);
- return keyCheck(val1, val2, kStrict, memos, kNoIterator, minimalKeys);
- }
+ if (val1Value !== val1 &&
+ (typeof val2.valueOf !== 'function' ||
+ !innerDeepEqual(val1Value, val2.valueOf(), kStrict))) {
+ return false;
}
}
return keyCheck(val1, val2, kStrict, memos, kNoIterator);
@@ -277,7 +250,7 @@ function keyCheck(val1, val2, strict, memos, iterationType, aKeys) {
}
}
- if (strict) {
+ if (strict && arguments.length === 5) {
const symbolKeysA = getOwnPropertySymbols(val1);
if (symbolKeysA.length !== 0) {
let count = 0;
@@ -310,7 +283,7 @@ function keyCheck(val1, val2, strict, memos, iterationType, aKeys) {
if (aKeys.length === 0 &&
(iterationType === kNoIterator ||
iterationType === kIsArray && val1.length === 0 ||
- val1.size === 0)) {
+ val1.size === 0)) {
return true;
}
@@ -578,8 +551,28 @@ function objEquiv(a, b, strict, keys, memos, iterationType) {
}
} else if (iterationType === kIsArray) {
for (; i < a.length; i++) {
- if (!innerDeepEqual(a[i], b[i], strict, memos)) {
+ if (hasOwnProperty(a, i)) {
+ if (!hasOwnProperty(b, i) ||
+ !innerDeepEqual(a[i], b[i], strict, memos)) {
+ return false;
+ }
+ } else if (hasOwnProperty(b, i)) {
return false;
+ } else {
+ // Array is sparse.
+ const keysA = objectKeys(a);
+ i++;
+ for (; i < keysA.length; i++) {
+ const key = keysA[i];
+ if (!hasOwnProperty(b, key) ||
+ !innerDeepEqual(a[key], b[i], strict, memos)) {
+ return false;
+ }
+ }
+ if (keysA.length !== objectKeys(b).length) {
+ return false;
+ }
+ return true;
}
}
}