diff --git a/include/class.orm.php b/include/class.orm.php
index a9ae5fcf2c96aa6939dbdfdd047210ab29dccffa..5fcf7359cb258185ba12052403ed6f2ebf48af4b 100644
--- a/include/class.orm.php
+++ b/include/class.orm.php
@@ -1626,7 +1626,7 @@ extends CachedResultSet {
         foreach ($this as $record) {
             $matches = true;
             foreach ($criteria as $field=>$check) {
-                if (!SqlCompiler::evaluate($record, $field, $check)) {
+                if (!SqlCompiler::evaluate($record, $check, $field)) {
                     $matches = false;
                     break;
                 }
@@ -1855,82 +1855,6 @@ implements Iterator {
             $this->eoi = true;
         }
     }
-
-    /**
-     * Find the first item in the current set which matches the given criteria.
-     * This would be used in favor of ::filter() which might trigger another
-     * database query. See ::findAll() for more details.
-     *
-     * Example:
-     * >>> $a = new User();
-     * >>> $a->roles->add(Role::lookup(['name' => 'administator']));
-     * >>> $a->roles->findFirst(['roles__name__startswith' => 'admin']);
-     * <Role: administrator>
-     */
-    function findFirst(array $criteria) {
-        $records = $this->findAll($criteria, 1);
-        return @$records[0];
-    }
-
-    /**
-     * Find the first item in the current set which matches the given criteria.
-     * This would be used in favor of ::filter() which might trigger another
-     * database query. The criteria is intended to be quite simple and should
-     * not traverse relationships which have not already been fetched.
-     * Otherwise, the ::filter() or ::window() methods would provide better
-     * performance, as they can provide results with one more trip to the
-     * database.
-     */
-    function findAll(array $criteria, $limit=false) {
-        $records = new ListObject();
-        foreach ($this as $record) {
-            $matches = true;
-            foreach ($criteria as $field => $check) {
-                if (!SqlCompiler::evaluate($record, $field, $check)) {
-                    $matches = false;
-                    break;
-                }
-            }
-            if ($matches)
-                $records[] = $record;
-        }
-        return $records;
-    }
-
-    /**
-     * Sort the instrumented list in place. This would be useful to change the
-     * sorting order of the items in the list without fetching the list from
-     * the database again.
-     *
-     * Parameters:
-     * $key - (callable|int) A callable function to produce the sort keys
-     *      or one of the SORT_ constants used by the array_multisort
-     *      function
-     * $reverse - (bool) true if the list should be sorted descending
-     *
-     * Returns:
-     * This instrumented list for chaining and inlining.
-     */
-    function sort($key=false, $reverse=false) {
-        // Fetch all records into the cache
-        $this->asArray();
-        if (is_callable($key)) {
-            array_multisort(
-                array_map($key, $this->cache),
-                $reverse ? SORT_DESC : SORT_ASC,
-                $this->cache);
-        }
-        elseif ($key) {
-            array_multisort($this->cache,
-                $reverse ? SORT_DESC : SORT_ASC, $key);
-        }
-        elseif ($reverse) {
-            rsort($this->cache);
-        }
-        else
-            sort($this->cache);
-        return $this;
-    }
 }
 
 // Use a global variable, as constructing exceptions is expensive
@@ -2042,8 +1966,16 @@ extends ModelResultSet {
      * Reduce the list to a subset using a simply key/value constraint. New
      * items added to the subset will have the constraint automatically
      * added to all new items.
+     *
+     * Parameters:
+     * $criteria - (<Traversable>) criteria by which this list will be
+     *    constrained and filtered.
+     * $evaluate - (<bool>) if set to TRUE, the criteria will be evaluated
+     *    without making any more trips to the database. NOTE this may yield
+     *    unexpected results if this list does not contain all the records
+     *    from the database which would be matched by another query.
      */
-    function window($constraint) {
+    function window($constraint, $evaluate=false) {
         $model = $this->model;
         $fields = $model::getMeta()->getFieldNames();
         $key = $this->key;
@@ -2052,7 +1984,25 @@ extends ModelResultSet {
                 throw new OrmException('InstrumentedList windowing must be performed on local fields only');
             $key[$field] = $value;
         }
-        return new static(array($this->model, $key), $this->filter($constraint));
+        $list = new static(array($this->model, $key), $this->filter($constraint));
+        if ($evaluate) {
+            $list->setCache($this->findAll($constraint));
+        }
+        return $list;
+    }
+
+    /**
+     * Disable database fetching on this list by providing a static list of
+     * objects. ::add() and ::remove() are still supported.
+     * XXX: Move this to a parent class?
+     */
+    function setCache(array $cache) {
+        if (count($this->cache) > 0)
+            throw new Exception('Cache must be set before fetching records');
+        // Set cache and disable fetching
+        $this->reset();
+        $this->cache = $cache;
+        $this->resource = false;
     }
 
     // Save all changes made to any list items
@@ -2063,9 +2013,6 @@ extends ModelResultSet {
         return true;
     }
 
-    function count() {
-        return count($this->asArray());
-    }
     // QuerySet delegates
     function exists() {
         return $this->queryset->exists();
@@ -2148,10 +2095,21 @@ class SqlCompiler {
     /**
      * Check if the values match given the operator.
      *
+     * Parameters:
+     * $record - <ModelBase> An model instance representing a row from the
+     *      database
+     * $field - Field path including operator used as the evaluated
+     *      expression base. To check if field `name` startswith something,
+     *      $field would be `name__startswith`.
+     * $check - <mixed> value used as the comparison. This would be the RHS
+     *      of the condition expressed with $field. This can also be a Q
+     *      instance, in which case, $field is not considered, and the Q
+     *      will be used to evaluate the $record directly.
+     *
      * Throws:
      * OrmException - if $operator is not supported
      */
-    static function evaluate($record, $field, $check) {
+    static function evaluate($record, $check, $field) {
         static $ops; if (!isset($ops)) { $ops = array(
             'exact' => function($a, $b) { return is_string($a) ? strcasecmp($a, $b) == 0 : $a == $b; },
             'isnull' => function($a, $b) { return is_null($a) == $b; },
@@ -2167,7 +2125,7 @@ class SqlCompiler {
         ); }
         // TODO: Support Q expressions
         if ($check instanceof Q)
-            return $check->evaluate($record, $field);
+            return $check->evaluate($record);
 
         list($field, $path, $operator) = self::splitCriteria($field);
         if (!isset($ops[$operator]))
@@ -3389,11 +3347,11 @@ class Q implements Serializable {
         return new static($constraints);
     }
 
-    function evaluate($record, $field) {
+    function evaluate($record) {
         // Start with FALSE for OR and TRUE for AND
         $result = !$this->ored;
-        foreach ($this->constraints as $check) {
-            $R = SqlCompiler::evaluate($record, $field, $check);
+        foreach ($this->constraints as $field=>$check) {
+            $R = SqlCompiler::evaluate($record, $check, $field);
             if ($this->ored) {
                 if ($result |= $R)
                     break;