Index: lib/filterClasses.js
===================================================================
--- a/lib/filterClasses.js
+++ b/lib/filterClasses.js
@@ -803,16 +803,26 @@
 
     Object.defineProperty(
       this, "sitekeys", {value: sitekeys, enumerable: true}
     );
     return this.sitekeys;
   },
 
   /**
+   * Tests whether the filter only has a location.
+   * @return {boolean}
+   */
+  isLocationOnly()
+  {
+    return this.contentType == RegExpFilter.prototype.contentType &&
+           this.thirdParty == null && !this.domains && !this.sitekeys;
+  },
+
+  /**
    * Tests whether the URL matches this filter
    * @param {string} location URL to be tested
    * @param {number} typeMask bitmask of content / request types to match
    * @param {string} [docDomain] domain name of the document that loads the URL
    * @param {boolean} [thirdParty] should be true if the URL is a third-party
    *                               request
    * @param {string} [sitekey] public key provided by the document
    * @return {boolean} true in case of a match
Index: lib/matcher.js
===================================================================
--- a/lib/matcher.js
+++ b/lib/matcher.js
@@ -66,72 +66,87 @@
   constructor()
   {
     /**
      * Lookup table for filters by their associated keyword
      * @type {Map.<string,(Filter|Set.<Filter>)>}
      * @private
      */
     this._filterByKeyword = new Map();
+
+    /**
+     * Lookup table for location only filters by their associated keyword
+     * for shortcut matching.
+     * @private
+     * @type {Map.<string,(Filter|Set.<Filter>)>}
+     */
+    this._fastFilterByKeyword = new Map();
   }
 
   /**
    * Removes all known filters
    */
   clear()
   {
     this._filterByKeyword.clear();
+    this._fastFilterByKeyword.clear();
   }
 
   /**
    * Adds a filter to the matcher
    * @param {RegExpFilter} filter
    */
   add(filter)
   {
     // Look for a suitable keyword
     let keyword = this.findKeyword(filter);
-    let set = this._filterByKeyword.get(keyword);
+    let filterMap = filter.isLocationOnly() ? this._fastFilterByKeyword :
+      this._filterByKeyword;
+    let set = filterMap.get(keyword);
+
     if (typeof set == "undefined")
     {
-      this._filterByKeyword.set(keyword, filter);
+      filterMap.set(keyword, filter);
     }
     else if (set.size == 1)
     {
       if (filter != set)
-        this._filterByKeyword.set(keyword, new Set([set, filter]));
+        filterMap.set(keyword, new Set([set, filter]));
     }
     else
     {
       set.add(filter);
     }
   }
 
   /**
    * Removes a filter from the matcher
    * @param {RegExpFilter} filter
    */
   remove(filter)
   {
     let keyword = this.findKeyword(filter);
-    let set = this._filterByKeyword.get(keyword);
+    let filterMap = filter.isLocationOnly() ? this._fastFilterByKeyword :
+      this._filterByKeyword;
+    let set = filterMap.get(keyword);
+
     if (typeof set == "undefined")
       return;
 
     if (set.size == 1)
     {
       if (filter == set)
-        this._filterByKeyword.delete(keyword);
+        filterMap.delete(keyword);
     }
     else
     {
       set.delete(filter);
 
       if (set.size == 1)
-        this._filterByKeyword.set(keyword, [...set][0]);
+        filterMap.set(keyword, [...set][0]);
     }
   }
 
   /**
    * Chooses a keyword to be associated with the filter
    * @param {Filter} filter
    * @returns {string} keyword or an empty string if no keyword could be found
    * @protected
@@ -142,17 +157,19 @@
     let {pattern} = filter;
     if (pattern == null)
       return result;
 
     let candidates = pattern.toLowerCase().match(allKeywordsRegExp);
     if (!candidates)
       return result;
 
-    let hash = this._filterByKeyword;
+    let hash = filter.isLocationOnly() ? this._fastFilterByKeyword :
+      this._filterByKeyword;
+
     let resultCount = 0xFFFFFF;
     let resultLength = 0;
     for (let i = 0, l = candidates.length; i < l; i++)
     {
       let candidate = candidates[i].substr(1);
       let filters = hash.get(candidate);
       let count = typeof filters != "undefined" ? filters.size : 0;
       if (count < resultCount ||
@@ -178,17 +195,32 @@
    * @returns {?Filter}
    * @protected
    */
   checkEntryMatch(keyword, location, typeMask, docDomain, thirdParty, sitekey,
                   specificOnly)
   {
     let set = this._filterByKeyword.get(keyword);
     if (typeof set == "undefined")
+    {
+      let fastSet = this._fastFilterByKeyword.get(keyword);
+      if (typeof fastSet == "undefined")
+        return null;
+
+      for (let filter of fastSet)
+      {
+        if (specificOnly && filter.isGeneric() &&
+            !(filter instanceof WhitelistFilter))
+          continue;
+
+        if (filter.matchesLocation(location))
+          return filter;
+      }
       return null;
+    }
 
     for (let filter of set)
     {
       if (specificOnly && filter.isGeneric() &&
           !(filter instanceof WhitelistFilter))
         continue;
 
       if (filter.matches(location, typeMask, docDomain, thirdParty, sitekey))
Index: test/filterListener.js
===================================================================
--- a/test/filterListener.js
+++ b/test/filterListener.js
@@ -70,16 +70,25 @@
     {
       for (let filter of set)
       {
         test.equal(matcher.findKeyword(filter), keyword,
                    "Keyword of filter " + filter.text);
         filters.push(filter.text);
       }
     }
+    for (let [keyword, set] of matcher._fastFilterByKeyword)
+    {
+      for (let filter of set)
+      {
+        test.equal(matcher.findKeyword(filter), keyword,
+                   "Keyword of filter " + filter.text);
+        filters.push(filter.text);
+      }
+    }
     result[type] = filters;
   }
 
   let elemHide = sandboxedRequire("../lib/elemHide");
   result.elemhide = [];
   for (let filter of elemHide.knownFilters)
     result.elemhide.push(filter.text);
 
