From 381498daa2a9ce089a69d044760190b1dd14b5ac Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Thu, 19 Mar 2020 13:42:06 -0400 Subject: [PATCH] Reorganize filter instances deduplication code Related commit: - https://github.com/gorhill/uBlock/commit/ab629b9e1093 --- src/js/static-net-filtering.js | 260 +++++++++++++++------------------ 1 file changed, 121 insertions(+), 139 deletions(-) diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js index 57314b6af..f00834292 100644 --- a/src/js/static-net-filtering.js +++ b/src/js/static-net-filtering.js @@ -345,6 +345,7 @@ const bidiTrieOptimize = function(shrink = false) { */ const filterClasses = []; +const filterArgsToUnit = new Map(); let filterClassIdGenerator = 0; const registerFilterClass = function(ctor) { @@ -365,7 +366,21 @@ const filterFromCtor = function(ctor, ...args) { const filterUnitFromCompiled = function(args) { const ctor = filterClasses[args[0]]; - return ctor.unitFromCompiled(args); + const keygen = ctor.keyFromArgs; + if ( keygen === undefined ) { + return filterUnits.push(ctor.fromCompiled(args)) - 1; + } + let key = `${ctor.fid}`; + const keyargs = keygen(args); + if ( keyargs !== undefined ) { + key += `\t${keyargs}`; + } + let iunit = filterArgsToUnit.get(key); + if ( iunit === undefined ) { + iunit = filterUnits.push(ctor.fromCompiled(args)) - 1; + filterArgsToUnit.set(key, iunit); + } + return iunit; }; const filterFromSelfie = function(args) { @@ -374,29 +389,6 @@ const filterFromSelfie = function(args) { /******************************************************************************/ -// Optional manager to be used to reuse filters instances. This is useful -// when deduplicating instances is worth it. For examples, filter instances -// which have a high likelihood of larger than average memory usage per -// instance. - -const filterInstanceManager = { - unitFromArgs: function(args, createFn) { - const key = JSON.stringify(args); - let iunit = this.argsToUnit.get(key); - if ( iunit === undefined ) { - iunit = createFn(args); - this.argsToUnit.set(key, iunit); - } - return iunit; - }, - reset: function() { - this.argsToUnit.clear(); - }, - argsToUnit: new Map(), -}; - -/******************************************************************************/ - const filterPattern = { compile: function(parsed, units) { if ( parsed.isRegex ) { @@ -501,18 +493,18 @@ const FilterTrue = class { return [ FilterTrue.fid ]; } - static unitFromCompiled() { - return FilterTrue.filterUnit; + static fromCompiled() { + return new FilterTrue(); } static fromSelfie() { - return FilterTrue.instance; + return new FilterTrue(); + } + + static keyFromArgs() { } }; -FilterTrue.instance = new FilterTrue(); -FilterTrue.filterUnit = filterUnits.push(FilterTrue.instance) - 1; - registerFilterClass(FilterTrue); /******************************************************************************/ @@ -562,18 +554,16 @@ const FilterPatternPlain = class { return [ FilterPatternPlain.fid, details.f, details.tokenBeg ]; } - static unitFromCompiled(args) { + static fromCompiled(args) { const i = bidiTrie.storeString(args[1]); const n = args[1].length; - let f; if ( args[2] === 0 ) { - f = new FilterPatternPlain(i, n); - } else if ( args[2] === 1 ) { - f = new FilterPatternPlain1(i, n); - } else { - f = new FilterPatternPlainX(i, n, args[2]); + return new FilterPatternPlain(i, n); } - return filterUnits.push(f) - 1; + if ( args[2] === 1 ) { + return new FilterPatternPlain1(i, n); + } + return new FilterPatternPlainX(i, n, args[2]); } static fromSelfie(args) { @@ -678,10 +668,9 @@ const FilterPatternLeft = class { ]; } - static unitFromCompiled(args) { + static fromCompiled(args) { const i = bidiTrie.storeString(args[1]); - const f = new FilterPatternLeft(i, args[1].length); - return filterUnits.push(f) - 1; + return new FilterPatternLeft(i, args[1].length); } static fromSelfie(args) { @@ -716,10 +705,9 @@ const FilterPatternLeftEx = class extends FilterPatternLeft { details.regex.unshift(restrFromPlainPattern(s), restrSeparator, '.*'); } - static unitFromCompiled(args) { + static fromCompiled(args) { const i = bidiTrie.storeString(args[1]); - const f = new FilterPatternLeftEx(i, args[1].length); - return filterUnits.push(f) - 1; + return new FilterPatternLeftEx(i, args[1].length); } static fromSelfie(args) { @@ -764,10 +752,9 @@ const FilterPatternRight = class { ]; } - static unitFromCompiled(args) { + static fromCompiled(args) { const i = bidiTrie.storeString(args[1]); - const f = new FilterPatternRight(i, args[1].length); - return filterUnits.push(f) - 1; + return new FilterPatternRight(i, args[1].length); } static fromSelfie(args) { @@ -799,10 +786,9 @@ const FilterPatternRightEx = class extends FilterPatternRight { details.regex.push(restrSeparator, '.*', restrFromPlainPattern(s)); } - static unitFromCompiled(args) { + static fromCompiled(args) { const i = bidiTrie.storeString(args[1]); - const f = new FilterPatternRightEx(i, args[1].length); - return filterUnits.push(f) - 1; + return new FilterPatternRightEx(i, args[1].length); } static fromSelfie(args) { @@ -856,16 +842,17 @@ const FilterPatternGeneric = class { return [ FilterPatternGeneric.fid, details.f, anchor ]; } - static unitFromCompiled(args) { - return filterInstanceManager.unitFromArgs(args, args => { - const f = new FilterPatternGeneric(args[1], args[2]); - return filterUnits.push(f) - 1; - }); + static fromCompiled(args) { + return new FilterPatternGeneric(args[1], args[2]); } static fromSelfie(args) { return new FilterPatternGeneric(args[1], args[2]); } + + static keyFromArgs(args) { + return `${args[1]}\t${args[2]}`; + } }; FilterPatternGeneric.prototype.re = null; @@ -902,9 +889,8 @@ const FilterPlainHostname = class { return [ FilterPlainHostname.fid, details.f ]; } - static unitFromCompiled(args) { - const f = new FilterPlainHostname(args[1]); - return filterUnits.push(f) - 1; + static fromCompiled(args) { + return new FilterPlainHostname(args[1]); } static fromSelfie(args) { @@ -970,19 +956,18 @@ const FilterAnchorHn = class { return [ FilterAnchorHn.fid ]; } - static unitFromCompiled() { - return FilterAnchorHn.filterUnit; + static fromCompiled() { + return new FilterAnchorHn(); } static fromSelfie() { - return FilterAnchorHn.instance; + return new FilterAnchorHn(); + } + + static keyFromArgs() { } }; -FilterAnchorHn.instance = new FilterAnchorHn(); -FilterAnchorHn.filterUnit = filterUnits.length; -filterUnits.push(FilterAnchorHn.instance); - registerFilterClass(FilterAnchorHn); /******************************************************************************/ @@ -1005,19 +990,18 @@ const FilterAnchorLeft = class { return [ FilterAnchorLeft.fid ]; } - static unitFromCompiled() { - return FilterAnchorLeft.filterUnit; + static fromCompiled() { + return new FilterAnchorLeft(); } static fromSelfie() { - return FilterAnchorLeft.instance; + return new FilterAnchorLeft(); + } + + static keyFromArgs() { } }; -FilterAnchorLeft.instance = new FilterAnchorLeft(); -FilterAnchorLeft.filterUnit = filterUnits.length; -filterUnits.push(FilterAnchorLeft.instance); - registerFilterClass(FilterAnchorLeft); /******************************************************************************/ @@ -1040,19 +1024,18 @@ const FilterAnchorRight = class { return [ FilterAnchorRight.fid ]; } - static unitFromCompiled() { - return FilterAnchorRight.filterUnit; + static fromCompiled() { + return new FilterAnchorRight(); } static fromSelfie() { - return FilterAnchorRight.instance; + return new FilterAnchorRight(); + } + + static keyFromArgs() { } }; -FilterAnchorRight.instance = new FilterAnchorRight(); -FilterAnchorRight.filterUnit = filterUnits.length; -filterUnits.push(FilterAnchorRight.instance); - registerFilterClass(FilterAnchorRight); /******************************************************************************/ @@ -1076,19 +1059,18 @@ const FilterTrailingSeparator = class { return [ FilterTrailingSeparator.fid ]; } - static unitFromCompiled() { - return FilterTrailingSeparator.filterUnit; + static fromCompiled() { + return new FilterTrailingSeparator(); } static fromSelfie() { - return FilterTrailingSeparator.instance; + return new FilterTrailingSeparator(); + } + + static keyFromArgs() { } }; -FilterTrailingSeparator.instance = new FilterTrailingSeparator(); -FilterTrailingSeparator.filterUnit = filterUnits.length; -filterUnits.push(FilterTrailingSeparator.instance); - registerFilterClass(FilterTrailingSeparator); /******************************************************************************/ @@ -1113,9 +1095,8 @@ const FilterType = class { return [ FilterType.fid, details.typeBits & allNetworkTypesBits ]; } - static unitFromCompiled(args) { - const f = new FilterType(args[1]); - return filterUnits.push(f) - 1; + static fromCompiled(args) { + return new FilterType(args[1]); } static fromSelfie(args) { @@ -1159,16 +1140,17 @@ const FilterRegex = class { return [ FilterRegex.fid, details.f ]; } - static unitFromCompiled(args) { - return filterInstanceManager.unitFromArgs(args, args => { - const f = new FilterRegex(args[1]); - return filterUnits.push(f) - 1; - }); + static fromCompiled(args) { + return new FilterRegex(args[1]); } static fromSelfie(args) { return new FilterRegex(args[1]); } + + static keyFromArgs(args) { + return args[1]; + } }; FilterRegex.prototype.re = null; @@ -1295,9 +1277,8 @@ const FilterOriginHit = class { return [ FilterOriginHit.fid, domainOpt ]; } - static unitFromCompiled(args) { - const f = new FilterOriginHit(args[1]); - return filterUnits.push(f) - 1; + static fromCompiled(args) { + return new FilterOriginHit(args[1]); } static fromSelfie(args) { @@ -1340,9 +1321,8 @@ const FilterOriginMiss = class { return [ FilterOriginMiss.fid, domainOpt ]; } - static unitFromCompiled(args) { - const f = new FilterOriginMiss(args[1]); - return filterUnits.push(f) - 1; + static fromCompiled(args) { + return new FilterOriginMiss(args[1]); } static fromSelfie(args) { @@ -1389,16 +1369,17 @@ const FilterOriginHitSet = class { return [ FilterOriginHitSet.fid, domainOpt ]; } - static unitFromCompiled(args) { - return filterInstanceManager.unitFromArgs(args, args => { - const f = new FilterOriginHitSet(args[1]); - return filterUnits.push(f) - 1; - }); + static fromCompiled(args) { + return new FilterOriginHitSet(args[1]); } static fromSelfie(args) { return new FilterOriginHitSet(args[1], args[2]); } + + static keyFromArgs(args) { + return args[1]; + } }; registerFilterClass(FilterOriginHitSet); @@ -1440,16 +1421,17 @@ const FilterOriginMissSet = class { return [ FilterOriginMissSet.fid, domainOpt ]; } - static unitFromCompiled(args) { - return filterInstanceManager.unitFromArgs(args, args => { - const f = new FilterOriginMissSet(args[1]); - return filterUnits.push(f) - 1; - }); + static fromCompiled(args) { + return new FilterOriginMissSet(args[1]); } static fromSelfie(args) { return new FilterOriginMissSet(args[1], args[2]); } + + static keyFromArgs(args) { + return args[1]; + } }; registerFilterClass(FilterOriginMissSet); @@ -1493,16 +1475,17 @@ const FilterDataHolder = class { return [ FilterDataHolder.fid, details.dataType, details.data ]; } - static unitFromCompiled(args) { - return filterInstanceManager.unitFromArgs(args, args => { - const f = new FilterDataHolder(args[1], args[2]); - return filterUnits.push(f) - 1; - }); + static fromCompiled(args) { + return new FilterDataHolder(args[1], args[2]); } static fromSelfie(args) { return new FilterDataHolder(args[1], args[2]); } + + static keyFromArgs(args) { + return `${args[1]}\t${args[2]}`; + } }; registerFilterClass(FilterDataHolder); @@ -1577,7 +1560,7 @@ const FilterCollection = class { return [ ctor.fid, fdata ]; } - static unitFromCompiled(ctor, args) { + static fromCompiled(ctor, args) { let iprev = 0, i0 = 0; const n = args[1].length; for ( let i = 0; i < n; i++ ) { @@ -1590,7 +1573,7 @@ const FilterCollection = class { } iprev = inext; } - return filterUnits.push(new ctor(i0, args[1].length)) - 1; + return new ctor(i0, args[1].length); } static fromSelfie(ctor, args) { @@ -1652,8 +1635,8 @@ const FilterComposite = class extends FilterCollection { return FilterCollection.compile(FilterComposite, fdata); } - static unitFromCompiled(args) { - return FilterCollection.unitFromCompiled(FilterComposite, args); + static fromCompiled(args) { + return FilterCollection.fromCompiled(FilterComposite, args); } static fromSelfie(args) { @@ -1754,20 +1737,22 @@ const FilterDenyAllow = class { return [ FilterDenyAllow.fid, details.denyallow ]; } - static unitFromCompiled(args) { - return filterInstanceManager.unitFromArgs(args, args => { - const f = new FilterDenyAllow(args[1]); - for ( const hn of args[1].split('|') ) { - if ( hn === '' ) { continue; } - f.hndict.add(hn); - } - return filterUnits.push(f) - 1; - }); + static fromCompiled(args) { + const f = new FilterDenyAllow(args[1]); + for ( const hn of args[1].split('|') ) { + if ( hn === '' ) { continue; } + f.hndict.add(hn); + } + return f; } static fromSelfie(args) { return new FilterDenyAllow(...args.slice(1)); } + + static keyFromArgs(args) { + return args[1]; + } }; registerFilterClass(FilterDenyAllow); @@ -1808,9 +1793,8 @@ const FilterJustOrigin = class { return [ this.fid, filterOrigin.trieContainer.compileOne(this.dict) ]; } - static unitFromCompiled(args) { - const f = new FilterJustOrigin(args[1]); - return filterUnits.push(f) - 1; + static fromCompiled(args) { + return new FilterJustOrigin(args[1]); } static fromSelfie(args) { @@ -1833,9 +1817,8 @@ const FilterHTTPSJustOrigin = class extends FilterJustOrigin { details.domains.push(this.$h); } - static unitFromCompiled(args) { - const f = new FilterHTTPSJustOrigin(args[1]); - return filterUnits.push(f) - 1; + static fromCompiled(args) { + return new FilterHTTPSJustOrigin(args[1]); } static fromSelfie(args) { @@ -1858,9 +1841,8 @@ const FilterHTTPJustOrigin = class extends FilterJustOrigin { details.domains.push(this.$h); } - static unitFromCompiled(args) { - const f = new FilterHTTPJustOrigin(args[1]); - return filterUnits.push(f) - 1; + static fromCompiled(args) { + return new FilterHTTPJustOrigin(args[1]); } static fromSelfie(args) { @@ -2740,7 +2722,7 @@ FilterContainer.prototype.reset = function() { FilterHostnameDict.reset(); filterOrigin.reset(); bidiTrie.reset(); - filterInstanceManager.reset(); + filterArgsToUnit.clear(); filterUnits = filterUnits.slice(0, FILTER_UNITS_MIN); filterSequenceWritePtr = FILTER_SEQUENCES_MIN; @@ -2863,7 +2845,7 @@ FilterContainer.prototype.freeze = function() { FilterHostnameDict.optimize(); bidiTrieOptimize(); - filterInstanceManager.reset(); + filterArgsToUnit.clear(); log.info(`staticNetFilteringEngine.freeze() took ${Date.now()-t0} ms`); };