assert: optimize code path for deepEqual Maps

PR-URL: https://github.com/nodejs/node/pull/14501
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
This commit is contained in:
Ruben Bridgewater 2017-07-26 08:58:26 -04:00 committed by Refael Ackermann
parent 95bbb68175
commit 9222fe64ad
No known key found for this signature in database
GPG Key ID: CD704BD80FDDDB64

View File

@ -360,10 +360,6 @@ function setEquiv(a, b, strict, memo) {
// This is a lazily initiated Set of entries which have to be compared // This is a lazily initiated Set of entries which have to be compared
// pairwise. // pairwise.
var set = null; var set = null;
// When the sets contain only value types (eg, lots of numbers), and we're in
// strict mode or if all entries strictly match, we don't need to match the
// entries in a pairwise way. In that case this initialization is done lazily
// to avoid the allocation & bookkeeping cost.
for (const val of a) { for (const val of a) {
// Note: Checking for the objects first improves the performance for object // Note: Checking for the objects first improves the performance for object
// heavy sets but it is a minor slow down for primitives. As they are fast // heavy sets but it is a minor slow down for primitives. As they are fast
@ -384,7 +380,7 @@ function setEquiv(a, b, strict, memo) {
if (set !== null) { if (set !== null) {
for (const val of b) { for (const val of b) {
// In non-strict-mode we have to check if a primitive value is already // We have to check if a primitive value is already
// matching and only if it's not, go hunting for it. // matching and only if it's not, go hunting for it.
if (typeof val === 'object' && val !== null) { if (typeof val === 'object' && val !== null) {
if (!setHasEqualElement(set, val, strict, memo)) if (!setHasEqualElement(set, val, strict, memo))
@ -460,10 +456,13 @@ function mapHasLoosePrim(a, b, key1, memo, item1, item2) {
return false; return false;
for (const val of setA) { for (const val of setA) {
if (!setHasEqualElement(setB, val, false, memo)) if (typeof val === 'object' && val !== null) {
if (!setHasEqualElement(setB, val, false, memo))
return false;
} else if (!setB.has(val) && !setHasLoosePrim(setA, setB, val)) {
return false; return false;
}
} }
return true; return true;
} }
@ -483,34 +482,26 @@ function mapHasEqualEntry(set, map, key1, item1, strict, memo) {
} }
function mapEquiv(a, b, strict, memo) { function mapEquiv(a, b, strict, memo) {
// Caveat: In non-strict mode, this implementation does not handle cases
// where maps contain two equivalent-but-not-reference-equal keys.
if (a.size !== b.size) if (a.size !== b.size)
return false; return false;
var set = null; var set = null;
for (const [key, item1] of a) { for (const [key, item1] of a) {
// By directly retrieving the value we prevent another b.has(key) check in if (typeof key === 'object' && key !== null) {
// almost all possible cases. if (set === null) {
const item2 = b.get(key); set = new Set();
if (item2 === undefined) { }
// Just like setEquiv above but in addition we have to make sure the set.add(key);
// values are also equal. } else {
if (typeof key === 'object' && key !== null) { // By directly retrieving the value we prevent another b.has(key) check in
if (set === null) { // almost all possible cases.
set = new Set(); const item2 = b.get(key);
} if ((item2 === undefined && !b.has(key) ||
set.add(key); !innerDeepEqual(item1, item2, strict, memo)) &&
// Note: we do not have to pass memo in this case as at least one item (strict || !mapHasLoosePrim(a, b, key, memo, item1, item2))) {
// is undefined.
} else if ((!innerDeepEqual(item1, item2, strict) || !b.has(key)) &&
(strict || !mapHasLoosePrim(a, b, key, memo, item1))) {
return false; return false;
} }
} else if (!innerDeepEqual(item1, item2, strict, memo) &&
(strict || !mapHasLoosePrim(a, b, key, memo, item1, item2))) {
return false;
} }
} }