You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ro...@apache.org on 2018/01/05 15:55:18 UTC

[2/2] lucene-solr:master: LUCENE-8133: Rename TermContext to TermStates, and load TermState lazily if term stats are not required

LUCENE-8133: Rename TermContext to TermStates, and load TermState lazily if term stats are not required


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/d250a146
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/d250a146
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/d250a146

Branch: refs/heads/master
Commit: d250a1463d87380420afc90e381623c0dc470695
Parents: 0c18acb
Author: Alan Woodward <ro...@apache.org>
Authored: Tue Jan 2 09:52:21 2018 +0000
Committer: Alan Woodward <ro...@apache.org>
Committed: Fri Jan 5 14:17:15 2018 +0000

----------------------------------------------------------------------
 lucene/CHANGES.txt                              |   3 +
 .../classification/utils/NearestFuzzyQuery.java |  12 +-
 .../org/apache/lucene/index/TermContext.java    | 197 ----------------
 .../org/apache/lucene/index/TermStates.java     | 234 +++++++++++++++++++
 .../apache/lucene/search/BlendedTermQuery.java  |  28 +--
 .../org/apache/lucene/search/IndexSearcher.java |   4 +-
 .../org/apache/lucene/search/LeafSimScorer.java |   2 +-
 .../apache/lucene/search/MultiPhraseQuery.java  |  22 +-
 .../apache/lucene/search/MultiTermQuery.java    |   8 +-
 .../MultiTermQueryConstantScoreWrapper.java     |   8 +-
 .../org/apache/lucene/search/PhraseQuery.java   |  18 +-
 .../apache/lucene/search/ScoringRewrite.java    |  14 +-
 .../org/apache/lucene/search/SynonymQuery.java  |  14 +-
 .../lucene/search/TermCollectingRewrite.java    |   4 +-
 .../apache/lucene/search/TermInSetQuery.java    |   8 +-
 .../org/apache/lucene/search/TermQuery.java     |  56 ++---
 .../apache/lucene/search/TopTermsRewrite.java   |  10 +-
 .../lucene/search/spans/SpanContainQuery.java   |  10 +-
 .../search/spans/SpanContainingQuery.java       |  10 +-
 .../search/spans/SpanMultiTermQueryWrapper.java |   6 +-
 .../lucene/search/spans/SpanNearQuery.java      |  14 +-
 .../lucene/search/spans/SpanNotQuery.java       |  12 +-
 .../apache/lucene/search/spans/SpanOrQuery.java |  12 +-
 .../search/spans/SpanPositionCheckQuery.java    |  12 +-
 .../apache/lucene/search/spans/SpanQuery.java   |  18 +-
 .../lucene/search/spans/SpanTermQuery.java      |  36 +--
 .../apache/lucene/search/spans/SpanWeight.java  |  24 +-
 .../lucene/search/spans/SpanWithinQuery.java    |  10 +-
 .../lucene/search/TestMinShouldMatch2.java      |   4 +-
 .../org/apache/lucene/search/TestTermQuery.java |   6 +-
 .../highlight/WeightedSpanTermExtractor.java    |   2 +-
 .../apache/lucene/queries/CommonTermsQuery.java |  40 ++--
 .../queries/payloads/PayloadScoreQuery.java     |   6 +-
 .../queries/payloads/SpanPayloadCheckQuery.java |  14 +-
 .../lucene/queries/CommonTermsQueryTest.java    |   6 +-
 .../sandbox/queries/FuzzyLikeThisQuery.java     |   8 +-
 .../lucene/search/TermAutomatonQuery.java       |  18 +-
 .../lucene/search/ShardSearchingTestBase.java   |   8 +-
 .../search/spans/AssertingSpanWeight.java       |   6 +-
 .../solr/handler/component/TermsComponent.java  |  26 +--
 .../org/apache/solr/query/SolrRangeQuery.java   |   8 +-
 .../solr/search/GraphTermsQParserPlugin.java    |  38 +--
 .../apache/solr/search/SolrIndexSearcher.java   |   6 +-
 .../solr/search/stats/ExactStatsCache.java      |   8 +-
 .../apache/solr/search/stats/LRUStatsCache.java |   4 +-
 .../solr/search/stats/LocalStatsSource.java     |   4 +-
 .../apache/solr/search/stats/StatsSource.java   |   4 +-
 47 files changed, 522 insertions(+), 500 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/CHANGES.txt
----------------------------------------------------------------------
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 16050d1..89afdfd 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -35,6 +35,9 @@ API Changes
 * LUCENE-8116: SimScorer now only takes a frequency and a norm as per-document
   scoring factors. (Adrien Grand)
 
+* LUCENE-8113: TermContext has been renamed to TermStates, and can now be 
+  constructed lazily if term statistics are not required (Alan Woodward)
+
 Changes in Runtime Behavior
 
 * LUCENE-7837: Indices that were created before the previous major version

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/classification/src/java/org/apache/lucene/classification/utils/NearestFuzzyQuery.java
----------------------------------------------------------------------
diff --git a/lucene/classification/src/java/org/apache/lucene/classification/utils/NearestFuzzyQuery.java b/lucene/classification/src/java/org/apache/lucene/classification/utils/NearestFuzzyQuery.java
index d4a2634..308dcdc 100644
--- a/lucene/classification/src/java/org/apache/lucene/classification/utils/NearestFuzzyQuery.java
+++ b/lucene/classification/src/java/org/apache/lucene/classification/utils/NearestFuzzyQuery.java
@@ -29,7 +29,7 @@ import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.search.BooleanClause;
@@ -210,20 +210,20 @@ public class NearestFuzzyQuery extends Query {
   }
 
   private Query newTermQuery(IndexReader reader, Term term) throws IOException {
-    // we build an artificial TermContext that will give an overall df and ttf
+    // we build an artificial TermStates that will give an overall df and ttf
     // equal to 1
-    TermContext context = new TermContext(reader.getContext());
+    TermStates termStates = new TermStates(reader.getContext());
     for (LeafReaderContext leafContext : reader.leaves()) {
       Terms terms = leafContext.reader().terms(term.field());
       if (terms != null) {
         TermsEnum termsEnum = terms.iterator();
         if (termsEnum.seekExact(term.bytes())) {
-          int freq = 1 - context.docFreq(); // we want the total df and ttf to be 1
-          context.register(termsEnum.termState(), leafContext.ord, freq, freq);
+          int freq = 1 - termStates.docFreq(); // we want the total df and ttf to be 1
+          termStates.register(termsEnum.termState(), leafContext.ord, freq, freq);
         }
       }
     }
-    return new TermQuery(term, context);
+    return new TermQuery(term, termStates);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/index/TermContext.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/TermContext.java b/lucene/core/src/java/org/apache/lucene/index/TermContext.java
deleted file mode 100644
index 3ba8dd9..0000000
--- a/lucene/core/src/java/org/apache/lucene/index/TermContext.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.lucene.index;
-
-
-import org.apache.lucene.util.BytesRef;
-
-import java.io.IOException;
-import java.util.Arrays;
-
-/**
- * Maintains a {@link IndexReader} {@link TermState} view over
- * {@link IndexReader} instances containing a single term. The
- * {@link TermContext} doesn't track if the given {@link TermState}
- * objects are valid, neither if the {@link TermState} instances refer to the
- * same terms in the associated readers.
- * 
- * @lucene.experimental
- */
-public final class TermContext {
-
-  // Important: do NOT keep hard references to index readers
-  private final Object topReaderContextIdentity;
-  private final TermState[] states;
-  private int docFreq;
-  private long totalTermFreq;
-
-  //public static boolean DEBUG = BlockTreeTermsWriter.DEBUG;
-
-  /**
-   * Creates an empty {@link TermContext} from a {@link IndexReaderContext}
-   */
-  public TermContext(IndexReaderContext context) {
-    assert context != null && context.isTopLevel;
-    topReaderContextIdentity = context.identity;
-    docFreq = 0;
-    totalTermFreq = 0;
-    final int len;
-    if (context.leaves() == null) {
-      len = 1;
-    } else {
-      len = context.leaves().size();
-    }
-    states = new TermState[len];
-  }
-
-  /**
-   * Expert: Return whether this {@link TermContext} was built for the given
-   * {@link IndexReaderContext}. This is typically used for assertions.
-   * @lucene.internal
-   */
-  public boolean wasBuiltFor(IndexReaderContext context) {
-    return topReaderContextIdentity == context.identity;
-  }
-
-  /**
-   * Creates a {@link TermContext} with an initial {@link TermState},
-   * {@link IndexReader} pair.
-   */
-  public TermContext(IndexReaderContext context, TermState state, int ord, int docFreq, long totalTermFreq) {
-    this(context);
-    register(state, ord, docFreq, totalTermFreq);
-  }
-
-  /**
-   * Creates a {@link TermContext} from a top-level {@link IndexReaderContext} and the
-   * given {@link Term}. This method will lookup the given term in all context's leaf readers 
-   * and register each of the readers containing the term in the returned {@link TermContext}
-   * using the leaf reader's ordinal.
-   * <p>
-   * Note: the given context must be a top-level context.
-   */
-  public static TermContext build(IndexReaderContext context, Term term)
-      throws IOException {
-    assert context != null && context.isTopLevel;
-    final String field = term.field();
-    final BytesRef bytes = term.bytes();
-    final TermContext perReaderTermState = new TermContext(context);
-    //if (DEBUG) System.out.println("prts.build term=" + term);
-    for (final LeafReaderContext ctx : context.leaves()) {
-      //if (DEBUG) System.out.println("  r=" + leaves[i].reader);
-      final Terms terms = ctx.reader().terms(field);
-      if (terms != null) {
-        final TermsEnum termsEnum = terms.iterator();
-        if (termsEnum.seekExact(bytes)) { 
-          final TermState termState = termsEnum.termState();
-          //if (DEBUG) System.out.println("    found");
-          perReaderTermState.register(termState, ctx.ord, termsEnum.docFreq(), termsEnum.totalTermFreq());
-        }
-      }
-    }
-    return perReaderTermState;
-  }
-
-  /**
-   * Clears the {@link TermContext} internal state and removes all
-   * registered {@link TermState}s
-   */
-  public void clear() {
-    docFreq = 0;
-    totalTermFreq = 0;
-    Arrays.fill(states, null);
-  }
-
-  /**
-   * Registers and associates a {@link TermState} with an leaf ordinal. The leaf ordinal
-   * should be derived from a {@link IndexReaderContext}'s leaf ord.
-   */
-  public void register(TermState state, final int ord, final int docFreq, final long totalTermFreq) {
-    register(state, ord);
-    accumulateStatistics(docFreq, totalTermFreq);
-  }
-
-  /**
-   * Expert: Registers and associates a {@link TermState} with an leaf ordinal. The
-   * leaf ordinal should be derived from a {@link IndexReaderContext}'s leaf ord.
-   * On the contrary to {@link #register(TermState, int, int, long)} this method
-   * does NOT update term statistics.
-   */
-  public void register(TermState state, final int ord) {
-    assert state != null : "state must not be null";
-    assert ord >= 0 && ord < states.length;
-    assert states[ord] == null : "state for ord: " + ord
-        + " already registered";
-    states[ord] = state;
-  }
-
-  /** Expert: Accumulate term statistics. */
-  public void accumulateStatistics(final int docFreq, final long totalTermFreq) {
-    assert docFreq >= 0;
-    assert totalTermFreq >= 0;
-    assert docFreq <= totalTermFreq;
-    this.docFreq += docFreq;
-    this.totalTermFreq += totalTermFreq;
-  }
-
-  /**
-   * Returns the {@link TermState} for an leaf ordinal or <code>null</code> if no
-   * {@link TermState} for the ordinal was registered.
-   * 
-   * @param ord
-   *          the readers leaf ordinal to get the {@link TermState} for.
-   * @return the {@link TermState} for the given readers ord or <code>null</code> if no
-   *         {@link TermState} for the reader was registered
-   */
-  public TermState get(int ord) {
-    assert ord >= 0 && ord < states.length;
-    return states[ord];
-  }
-
-  /**
-   *  Returns the accumulated document frequency of all {@link TermState}
-   *         instances passed to {@link #register(TermState, int, int, long)}.
-   * @return the accumulated document frequency of all {@link TermState}
-   *         instances passed to {@link #register(TermState, int, int, long)}.
-   */
-  public int docFreq() {
-    return docFreq;
-  }
-  
-  /**
-   *  Returns the accumulated term frequency of all {@link TermState}
-   *         instances passed to {@link #register(TermState, int, int, long)}.
-   * @return the accumulated term frequency of all {@link TermState}
-   *         instances passed to {@link #register(TermState, int, int, long)}.
-   */
-  public long totalTermFreq() {
-    return totalTermFreq;
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder sb = new StringBuilder();
-    sb.append("TermContext\n");
-    for(TermState termState : states) {
-      sb.append("  state=");
-      sb.append(termState.toString());
-      sb.append('\n');
-    }
-
-    return sb.toString();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/index/TermStates.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/TermStates.java b/lucene/core/src/java/org/apache/lucene/index/TermStates.java
new file mode 100644
index 0000000..3282ac8
--- /dev/null
+++ b/lucene/core/src/java/org/apache/lucene/index/TermStates.java
@@ -0,0 +1,234 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.lucene.index;
+
+
+import java.io.IOException;
+import java.util.Arrays;
+
+/**
+ * Maintains a {@link IndexReader} {@link TermState} view over
+ * {@link IndexReader} instances containing a single term. The
+ * {@link TermStates} doesn't track if the given {@link TermState}
+ * objects are valid, neither if the {@link TermState} instances refer to the
+ * same terms in the associated readers.
+ * 
+ * @lucene.experimental
+ */
+public final class TermStates {
+
+  private static final TermState EMPTY_TERMSTATE = new TermState() {
+    @Override
+    public void copyFrom(TermState other) {
+
+    }
+  };
+
+  // Important: do NOT keep hard references to index readers
+  private final Object topReaderContextIdentity;
+  private final TermState[] states;
+  private final Term term;  // null if stats are to be used
+  private int docFreq;
+  private long totalTermFreq;
+
+  //public static boolean DEBUG = BlockTreeTermsWriter.DEBUG;
+
+  private TermStates(Term term, IndexReaderContext context) {
+    assert context != null && context.isTopLevel;
+    topReaderContextIdentity = context.identity;
+    docFreq = 0;
+    totalTermFreq = 0;
+    final int len;
+    if (context.leaves() == null) {
+      len = 1;
+    } else {
+      len = context.leaves().size();
+    }
+    states = new TermState[len];
+    this.term = term;
+  }
+
+  /**
+   * Creates an empty {@link TermStates} from a {@link IndexReaderContext}
+   */
+  public TermStates(IndexReaderContext context) {
+    this(null, context);
+  }
+
+  /**
+   * Expert: Return whether this {@link TermStates} was built for the given
+   * {@link IndexReaderContext}. This is typically used for assertions.
+   * @lucene.internal
+   */
+  public boolean wasBuiltFor(IndexReaderContext context) {
+    return topReaderContextIdentity == context.identity;
+  }
+
+  /**
+   * Creates a {@link TermStates} with an initial {@link TermState},
+   * {@link IndexReader} pair.
+   */
+  public TermStates(IndexReaderContext context, TermState state, int ord, int docFreq, long totalTermFreq) {
+    this(null, context);
+    register(state, ord, docFreq, totalTermFreq);
+  }
+
+  /**
+   * Creates a {@link TermStates} from a top-level {@link IndexReaderContext} and the
+   * given {@link Term}. This method will lookup the given term in all context's leaf readers 
+   * and register each of the readers containing the term in the returned {@link TermStates}
+   * using the leaf reader's ordinal.
+   * <p>
+   * Note: the given context must be a top-level context.
+   *
+   * @param needsStats if {@code true} then all leaf contexts will be visited up-front to
+   *                   collect term statistics.  Otherwise, the {@link TermState} objects
+   *                   will be built only when requested
+   */
+  public static TermStates build(IndexReaderContext context, Term term, boolean needsStats)
+      throws IOException {
+    assert context != null && context.isTopLevel;
+    final TermStates perReaderTermState = new TermStates(needsStats ? null : term, context);
+    if (needsStats) {
+      for (final LeafReaderContext ctx : context.leaves()) {
+        //if (DEBUG) System.out.println("  r=" + leaves[i].reader);
+        TermsEnum termsEnum = loadTermsEnum(ctx, term);
+        if (termsEnum != null) {
+          final TermState termState = termsEnum.termState();
+          //if (DEBUG) System.out.println("    found");
+          perReaderTermState.register(termState, ctx.ord, termsEnum.docFreq(), termsEnum.totalTermFreq());
+        }
+      }
+    }
+    return perReaderTermState;
+  }
+
+  private static TermsEnum loadTermsEnum(LeafReaderContext ctx, Term term) throws IOException {
+    final Terms terms = ctx.reader().terms(term.field());
+    if (terms != null) {
+      final TermsEnum termsEnum = terms.iterator();
+      if (termsEnum.seekExact(term.bytes())) {
+        return termsEnum;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Clears the {@link TermStates} internal state and removes all
+   * registered {@link TermState}s
+   */
+  public void clear() {
+    docFreq = 0;
+    totalTermFreq = 0;
+    Arrays.fill(states, null);
+  }
+
+  /**
+   * Registers and associates a {@link TermState} with an leaf ordinal. The leaf ordinal
+   * should be derived from a {@link IndexReaderContext}'s leaf ord.
+   */
+  public void register(TermState state, final int ord, final int docFreq, final long totalTermFreq) {
+    register(state, ord);
+    accumulateStatistics(docFreq, totalTermFreq);
+  }
+
+  /**
+   * Expert: Registers and associates a {@link TermState} with an leaf ordinal. The
+   * leaf ordinal should be derived from a {@link IndexReaderContext}'s leaf ord.
+   * On the contrary to {@link #register(TermState, int, int, long)} this method
+   * does NOT update term statistics.
+   */
+  public void register(TermState state, final int ord) {
+    assert state != null : "state must not be null";
+    assert ord >= 0 && ord < states.length;
+    assert states[ord] == null : "state for ord: " + ord
+        + " already registered";
+    states[ord] = state;
+  }
+
+  /** Expert: Accumulate term statistics. */
+  public void accumulateStatistics(final int docFreq, final long totalTermFreq) {
+    assert docFreq >= 0;
+    assert totalTermFreq >= 0;
+    assert docFreq <= totalTermFreq;
+    this.docFreq += docFreq;
+    this.totalTermFreq += totalTermFreq;
+  }
+
+  /**
+   * Returns the {@link TermState} for a leaf reader context or <code>null</code> if no
+   * {@link TermState} for the context was registered.
+   * 
+   * @param ctx
+   *          the {@link LeafReaderContext} to get the {@link TermState} for.
+   * @return the {@link TermState} for the given readers ord or <code>null</code> if no
+   *         {@link TermState} for the reader was registered
+   */
+  public TermState get(LeafReaderContext ctx) throws IOException {
+    assert ctx.ord >= 0 && ctx.ord < states.length;
+    if (term == null)
+      return states[ctx.ord];
+    if (this.states[ctx.ord] == null) {
+      TermsEnum te = loadTermsEnum(ctx, term);
+      this.states[ctx.ord] = te == null ? EMPTY_TERMSTATE : te.termState();
+    }
+    if (this.states[ctx.ord] == EMPTY_TERMSTATE)
+      return null;
+    return this.states[ctx.ord];
+  }
+
+  /**
+   *  Returns the accumulated document frequency of all {@link TermState}
+   *         instances passed to {@link #register(TermState, int, int, long)}.
+   * @return the accumulated document frequency of all {@link TermState}
+   *         instances passed to {@link #register(TermState, int, int, long)}.
+   */
+  public int docFreq() {
+    if (term != null) {
+      throw new IllegalStateException("Cannot call docFreq() when needsStats=false");
+    }
+    return docFreq;
+  }
+  
+  /**
+   *  Returns the accumulated term frequency of all {@link TermState}
+   *         instances passed to {@link #register(TermState, int, int, long)}.
+   * @return the accumulated term frequency of all {@link TermState}
+   *         instances passed to {@link #register(TermState, int, int, long)}.
+   */
+  public long totalTermFreq() {
+    if (term != null) {
+      throw new IllegalStateException("Cannot call totalTermFreq() when needsStats=false");
+    }
+    return totalTermFreq;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("TermStates\n");
+    for(TermState termState : states) {
+      sb.append("  state=");
+      sb.append(termState.toString());
+      sb.append('\n');
+    }
+
+    return sb.toString();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/BlendedTermQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/BlendedTermQuery.java b/lucene/core/src/java/org/apache/lucene/search/BlendedTermQuery.java
index 219d453..cca6675 100644
--- a/lucene/core/src/java/org/apache/lucene/search/BlendedTermQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/BlendedTermQuery.java
@@ -25,7 +25,7 @@ import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReaderContext;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.index.TermState;
 import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.util.ArrayUtil;
@@ -53,7 +53,7 @@ public final class BlendedTermQuery extends Query {
     private int numTerms = 0;
     private Term[] terms = new Term[0];
     private float[] boosts = new float[0];
-    private TermContext[] contexts = new TermContext[0];
+    private TermStates[] contexts = new TermStates[0];
     private RewriteMethod rewriteMethod = DISJUNCTION_MAX_REWRITE;
 
     /** Sole constructor. */
@@ -82,10 +82,10 @@ public final class BlendedTermQuery extends Query {
 
     /**
      * Expert: Add a {@link Term} with the provided boost and context.
-     * This method is useful if you already have a {@link TermContext}
+     * This method is useful if you already have a {@link TermStates}
      * object constructed for the given term.
      */
-    public Builder add(Term term, float boost, TermContext context) {
+    public Builder add(Term term, float boost, TermStates context) {
       if (numTerms >= BooleanQuery.getMaxClauseCount()) {
         throw new BooleanQuery.TooManyClauses();
       }
@@ -184,10 +184,10 @@ public final class BlendedTermQuery extends Query {
 
   private final Term[] terms;
   private final float[] boosts;
-  private final TermContext[] contexts;
+  private final TermStates[] contexts;
   private final RewriteMethod rewriteMethod;
 
-  private BlendedTermQuery(Term[] terms, float[] boosts, TermContext[] contexts,
+  private BlendedTermQuery(Term[] terms, float[] boosts, TermStates[] contexts,
       RewriteMethod rewriteMethod) {
     assert terms.length == boosts.length;
     assert terms.length == contexts.length;
@@ -205,7 +205,7 @@ public final class BlendedTermQuery extends Query {
         terms[i] = terms[j];
         terms[j] = tmpTerm;
 
-        TermContext tmpContext = contexts[i];
+        TermStates tmpContext = contexts[i];
         contexts[i] = contexts[j];
         contexts[j] = tmpContext;
 
@@ -263,10 +263,10 @@ public final class BlendedTermQuery extends Query {
 
   @Override
   public final Query rewrite(IndexReader reader) throws IOException {
-    final TermContext[] contexts = Arrays.copyOf(this.contexts, this.contexts.length);
+    final TermStates[] contexts = Arrays.copyOf(this.contexts, this.contexts.length);
     for (int i = 0; i < contexts.length; ++i) {
       if (contexts[i] == null || contexts[i].wasBuiltFor(reader.getContext()) == false) {
-        contexts[i] = TermContext.build(reader.getContext(), terms[i]);
+        contexts[i] = TermStates.build(reader.getContext(), terms[i], true);
       }
     }
 
@@ -275,7 +275,7 @@ public final class BlendedTermQuery extends Query {
     // ttf will be the sum of all total term freqs
     int df = 0;
     long ttf = 0;
-    for (TermContext ctx : contexts) {
+    for (TermStates ctx : contexts) {
       df = Math.max(df, ctx.docFreq());
       ttf += ctx.totalTermFreq();
     }
@@ -294,8 +294,8 @@ public final class BlendedTermQuery extends Query {
     return rewriteMethod.rewrite(termQueries);
   }
 
-  private static TermContext adjustFrequencies(IndexReaderContext readerContext,
-      TermContext ctx, int artificialDf, long artificialTtf) {
+  private static TermStates adjustFrequencies(IndexReaderContext readerContext,
+                                              TermStates ctx, int artificialDf, long artificialTtf) throws IOException {
     List<LeafReaderContext> leaves = readerContext.leaves();
     final int len;
     if (leaves == null) {
@@ -303,9 +303,9 @@ public final class BlendedTermQuery extends Query {
     } else {
       len = leaves.size();
     }
-    TermContext newCtx = new TermContext(readerContext);
+    TermStates newCtx = new TermStates(readerContext);
     for (int i = 0; i < len; ++i) {
-      TermState termState = ctx.get(i);
+      TermState termState = ctx.get(leaves.get(i));
       if (termState == null) {
         continue;
       }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java b/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java
index fc87563..da5ed03 100644
--- a/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java
+++ b/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java
@@ -39,7 +39,7 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.ReaderUtil;
 import org.apache.lucene.index.StoredFieldVisitor;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.search.similarities.BM25Similarity;
 import org.apache.lucene.search.similarities.Similarity;
@@ -739,7 +739,7 @@ public class IndexSearcher {
    * across a distributed collection.
    * @lucene.experimental
    */
-  public TermStatistics termStatistics(Term term, TermContext context) throws IOException {
+  public TermStatistics termStatistics(Term term, TermStates context) throws IOException {
     if (context.docFreq() == 0) {
       return null;
     } else {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/LeafSimScorer.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/LeafSimScorer.java b/lucene/core/src/java/org/apache/lucene/search/LeafSimScorer.java
index 52b7d92..46f9dc2 100644
--- a/lucene/core/src/java/org/apache/lucene/search/LeafSimScorer.java
+++ b/lucene/core/src/java/org/apache/lucene/search/LeafSimScorer.java
@@ -37,7 +37,7 @@ public final class LeafSimScorer {
   public LeafSimScorer(SimScorer scorer, LeafReader reader, boolean needsScores, float maxFreq) throws IOException {
     this.scorer = scorer;
     norms = needsScores ? reader.getNormValues(scorer.getField()) : null;
-    maxScore = scorer.maxScore(maxFreq);
+    maxScore = needsScores ? scorer.maxScore(maxFreq) : Integer.MAX_VALUE;
   }
 
   private long getNormValue(int doc) throws IOException {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java b/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java
index 941416e..c76f7ea 100644
--- a/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java
@@ -34,7 +34,7 @@ import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.PostingsEnum;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.index.TermState;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
@@ -191,7 +191,7 @@ public class MultiPhraseQuery extends Query {
   private class MultiPhraseWeight extends Weight {
     private final Similarity similarity;
     private final Similarity.SimScorer stats;
-    private final Map<Term,TermContext> termContexts = new HashMap<>();
+    private final Map<Term,TermStates> termStates = new HashMap<>();
     private final ScoreMode scoreMode;
 
     public MultiPhraseWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost)
@@ -205,14 +205,16 @@ public class MultiPhraseQuery extends Query {
       ArrayList<TermStatistics> allTermStats = new ArrayList<>();
       for(final Term[] terms: termArrays) {
         for (Term term: terms) {
-          TermContext termContext = termContexts.get(term);
-          if (termContext == null) {
-            termContext = TermContext.build(context, term);
-            termContexts.put(term, termContext);
+          TermStates ts = termStates.get(term);
+          if (ts == null) {
+            ts = TermStates.build(context, term, scoreMode.needsScores());
+            termStates.put(term, ts);
           }
-          TermStatistics termStatistics = searcher.termStatistics(term, termContext);
-          if (termStatistics != null) {
-            allTermStats.add(termStatistics);
+          if (scoreMode.needsScores()) {
+            TermStatistics termStatistics = searcher.termStatistics(term, ts);
+            if (termStatistics != null) {
+              allTermStats.add(termStatistics);
+            }
           }
         }
       }
@@ -260,7 +262,7 @@ public class MultiPhraseQuery extends Query {
         List<PostingsEnum> postings = new ArrayList<>();
 
         for (Term term : terms) {
-          TermState termState = termContexts.get(term).get(context.ord);
+          TermState termState = termStates.get(term).get(context);
           if (termState != null) {
             termsEnum.seekExact(term.bytes(), termState);
             postings.add(termsEnum.postings(null, PostingsEnum.POSITIONS));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/MultiTermQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/MultiTermQuery.java b/lucene/core/src/java/org/apache/lucene/search/MultiTermQuery.java
index d0869d6..636a7d6 100644
--- a/lucene/core/src/java/org/apache/lucene/search/MultiTermQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/MultiTermQuery.java
@@ -24,7 +24,7 @@ import org.apache.lucene.index.FilteredTermsEnum; // javadocs
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.SingleTermsEnum;   // javadocs
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.search.BooleanQuery.Builder;
@@ -166,7 +166,7 @@ public abstract class MultiTermQuery extends Query {
     }
     
     @Override
-    protected void addClause(BooleanQuery.Builder topLevel, Term term, int docCount, float boost, TermContext states) {
+    protected void addClause(BooleanQuery.Builder topLevel, Term term, int docCount, float boost, TermStates states) {
       final TermQuery tq = new TermQuery(term, states);
       topLevel.add(new BoostQuery(tq, boost), BooleanClause.Occur.SHOULD);
     }
@@ -218,7 +218,7 @@ public abstract class MultiTermQuery extends Query {
 
     @Override
     protected void addClause(BlendedTermQuery.Builder topLevel, Term term, int docCount,
-        float boost, TermContext states) {
+        float boost, TermStates states) {
       topLevel.add(term, boost, states);
     }
   }
@@ -262,7 +262,7 @@ public abstract class MultiTermQuery extends Query {
     }
     
     @Override
-    protected void addClause(BooleanQuery.Builder topLevel, Term term, int docFreq, float boost, TermContext states) {
+    protected void addClause(BooleanQuery.Builder topLevel, Term term, int docFreq, float boost, TermStates states) {
       final Query q = new ConstantScoreQuery(new TermQuery(term, states));
       topLevel.add(new BoostQuery(q, boost), BooleanClause.Occur.SHOULD);
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/MultiTermQueryConstantScoreWrapper.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/MultiTermQueryConstantScoreWrapper.java b/lucene/core/src/java/org/apache/lucene/search/MultiTermQueryConstantScoreWrapper.java
index f82316d..3a46b96 100644
--- a/lucene/core/src/java/org/apache/lucene/search/MultiTermQueryConstantScoreWrapper.java
+++ b/lucene/core/src/java/org/apache/lucene/search/MultiTermQueryConstantScoreWrapper.java
@@ -25,7 +25,7 @@ import java.util.Objects;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.PostingsEnum;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.index.TermState;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
@@ -148,9 +148,9 @@ final class MultiTermQueryConstantScoreWrapper<Q extends MultiTermQuery> extends
           // build a boolean query
           BooleanQuery.Builder bq = new BooleanQuery.Builder();
           for (TermAndState t : collectedTerms) {
-            final TermContext termContext = new TermContext(searcher.getTopReaderContext());
-            termContext.register(t.state, context.ord, t.docFreq, t.totalTermFreq);
-            bq.add(new TermQuery(new Term(query.field, t.term), termContext), Occur.SHOULD);
+            final TermStates termStates = new TermStates(searcher.getTopReaderContext());
+            termStates.register(t.state, context.ord, t.docFreq, t.totalTermFreq);
+            bq.add(new TermQuery(new Term(query.field, t.term), termStates), Occur.SHOULD);
           }
           Query q = new ConstantScoreQuery(bq.build());
           final Weight weight = searcher.rewrite(q).createWeight(searcher, scoreMode, score());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java b/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
index 295cc90..011771e 100644
--- a/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
@@ -32,7 +32,7 @@ import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.PostingsEnum;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.index.TermState;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
@@ -353,7 +353,7 @@ public class PhraseQuery extends Query {
     private final Similarity similarity;
     private final Similarity.SimScorer stats;
     private final ScoreMode scoreMode;
-    private transient TermContext states[];
+    private transient TermStates states[];
 
     public PhraseWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost)
       throws IOException {
@@ -367,15 +367,17 @@ public class PhraseQuery extends Query {
       this.scoreMode = scoreMode;
       this.similarity = searcher.getSimilarity();
       final IndexReaderContext context = searcher.getTopReaderContext();
-      states = new TermContext[terms.length];
+      states = new TermStates[terms.length];
       TermStatistics termStats[] = new TermStatistics[terms.length];
       int termUpTo = 0;
       for (int i = 0; i < terms.length; i++) {
         final Term term = terms[i];
-        states[i] = TermContext.build(context, term);
-        TermStatistics termStatistics = searcher.termStatistics(term, states[i]);
-        if (termStatistics != null) {
-          termStats[termUpTo++] = termStatistics;
+        states[i] = TermStates.build(context, term, scoreMode.needsScores());
+        if (scoreMode.needsScores()) {
+          TermStatistics termStatistics = searcher.termStatistics(term, states[i]);
+          if (termStatistics != null) {
+            termStats[termUpTo++] = termStatistics;
+          }
         }
       }
       if (termUpTo > 0) {
@@ -414,7 +416,7 @@ public class PhraseQuery extends Query {
       
       for (int i = 0; i < terms.length; i++) {
         final Term t = terms[i];
-        final TermState state = states[i].get(context.ord);
+        final TermState state = states[i].get(context);
         if (state == null) { /* term doesnt exist in this segment */
           assert termNotInReader(reader, t): "no termstate found but term exists in reader";
           return null;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/ScoringRewrite.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/ScoringRewrite.java b/lucene/core/src/java/org/apache/lucene/search/ScoringRewrite.java
index 6f54a86..9d02b35 100644
--- a/lucene/core/src/java/org/apache/lucene/search/ScoringRewrite.java
+++ b/lucene/core/src/java/org/apache/lucene/search/ScoringRewrite.java
@@ -20,7 +20,7 @@ import java.io.IOException;
 
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.index.TermState;
 import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.search.MultiTermQuery.RewriteMethod;
@@ -64,7 +64,7 @@ public abstract class ScoringRewrite<B> extends TermCollectingRewrite<B> {
     
     @Override
     protected void addClause(BooleanQuery.Builder topLevel, Term term, int docCount,
-        float boost, TermContext states) {
+        float boost, TermStates states) {
       final TermQuery tq = new TermQuery(term, states);
       topLevel.add(new BoostQuery(tq, boost), BooleanClause.Occur.SHOULD);
     }
@@ -109,7 +109,7 @@ public abstract class ScoringRewrite<B> extends TermCollectingRewrite<B> {
     if (size > 0) {
       final int sort[] = col.terms.sort();
       final float[] boost = col.array.boost;
-      final TermContext[] termStates = col.array.termState;
+      final TermStates[] termStates = col.array.termState;
       for (int i = 0; i < size; i++) {
         final int pos = sort[i];
         final Term term = new Term(query.getField(), col.terms.get(pos, new BytesRef()));
@@ -146,7 +146,7 @@ public abstract class ScoringRewrite<B> extends TermCollectingRewrite<B> {
       } else {
         // new entry: we populate the entry initially
         array.boost[e] = boostAtt.getBoost();
-        array.termState[e] = new TermContext(topReaderContext, state, readerContext.ord, termsEnum.docFreq(), termsEnum.totalTermFreq());
+        array.termState[e] = new TermStates(topReaderContext, state, readerContext.ord, termsEnum.docFreq(), termsEnum.totalTermFreq());
         ScoringRewrite.this.checkMaxClauseCount(terms.size());
       }
       return true;
@@ -156,7 +156,7 @@ public abstract class ScoringRewrite<B> extends TermCollectingRewrite<B> {
   /** Special implementation of BytesStartArray that keeps parallel arrays for boost and docFreq */
   static final class TermFreqBoostByteStart extends DirectBytesStartArray  {
     float[] boost;
-    TermContext[] termState;
+    TermStates[] termState;
     
     public TermFreqBoostByteStart(int initSize) {
       super(initSize);
@@ -166,7 +166,7 @@ public abstract class ScoringRewrite<B> extends TermCollectingRewrite<B> {
     public int[] init() {
       final int[] ord = super.init();
       boost = new float[ArrayUtil.oversize(ord.length, Float.BYTES)];
-      termState = new TermContext[ArrayUtil.oversize(ord.length, RamUsageEstimator.NUM_BYTES_OBJECT_REF)];
+      termState = new TermStates[ArrayUtil.oversize(ord.length, RamUsageEstimator.NUM_BYTES_OBJECT_REF)];
       assert termState.length >= ord.length && boost.length >= ord.length;
       return ord;
     }
@@ -176,7 +176,7 @@ public abstract class ScoringRewrite<B> extends TermCollectingRewrite<B> {
       final int[] ord = super.grow();
       boost = ArrayUtil.grow(boost, ord.length);
       if (termState.length < ord.length) {
-        TermContext[] tmpTermState = new TermContext[ArrayUtil.oversize(ord.length, RamUsageEstimator.NUM_BYTES_OBJECT_REF)];
+        TermStates[] tmpTermState = new TermStates[ArrayUtil.oversize(ord.length, RamUsageEstimator.NUM_BYTES_OBJECT_REF)];
         System.arraycopy(termState, 0, tmpTermState, 0, termState.length);
         termState = tmpTermState;
       }     

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/SynonymQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/SynonymQuery.java b/lucene/core/src/java/org/apache/lucene/search/SynonymQuery.java
index 3f4c06d..10a5d42 100644
--- a/lucene/core/src/java/org/apache/lucene/search/SynonymQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/SynonymQuery.java
@@ -31,7 +31,7 @@ import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.PostingsEnum;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.index.TermState;
 import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.search.similarities.Similarity;
@@ -126,7 +126,7 @@ public final class SynonymQuery extends Query {
   }
   
   class SynonymWeight extends Weight {
-    private final TermContext termContexts[];
+    private final TermStates termStates[];
     private final Similarity similarity;
     private final Similarity.SimScorer simWeight;
 
@@ -135,10 +135,10 @@ public final class SynonymQuery extends Query {
       CollectionStatistics collectionStats = searcher.collectionStatistics(terms[0].field());
       long docFreq = 0;
       long totalTermFreq = 0;
-      termContexts = new TermContext[terms.length];
-      for (int i = 0; i < termContexts.length; i++) {
-        termContexts[i] = TermContext.build(searcher.getTopReaderContext(), terms[i]);
-        TermStatistics termStats = searcher.termStatistics(terms[i], termContexts[i]);
+      termStates = new TermStates[terms.length];
+      for (int i = 0; i < termStates.length; i++) {
+        termStates[i] = TermStates.build(searcher.getTopReaderContext(), terms[i], true);
+        TermStatistics termStats = searcher.termStatistics(terms[i], termStates[i]);
         if (termStats != null) {
           docFreq = Math.max(termStats.docFreq(), docFreq);
           totalTermFreq += termStats.totalTermFreq();
@@ -202,7 +202,7 @@ public final class SynonymQuery extends Query {
       List<Scorer> subScorers = new ArrayList<>();
       long totalMaxFreq = 0;
       for (int i = 0; i < terms.length; i++) {
-        TermState state = termContexts[i].get(context.ord);
+        TermState state = termStates[i].get(context);
         if (state != null) {
           TermsEnum termsEnum = context.reader().terms(terms[i].field()).iterator();
           termsEnum.seekExact(terms[i].bytes(), state);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/TermCollectingRewrite.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/TermCollectingRewrite.java b/lucene/core/src/java/org/apache/lucene/search/TermCollectingRewrite.java
index fffa5a8..86bf34f 100644
--- a/lucene/core/src/java/org/apache/lucene/search/TermCollectingRewrite.java
+++ b/lucene/core/src/java/org/apache/lucene/search/TermCollectingRewrite.java
@@ -23,7 +23,7 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReaderContext;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.util.AttributeSource;
@@ -43,7 +43,7 @@ abstract class TermCollectingRewrite<B> extends MultiTermQuery.RewriteMethod {
     addClause(topLevel, term, docCount, boost, null);
   }
   
-  protected abstract void addClause(B topLevel, Term term, int docCount, float boost, TermContext states) throws IOException;
+  protected abstract void addClause(B topLevel, Term term, int docCount, float boost, TermStates states) throws IOException;
 
   
   final void collectTerms(IndexReader reader, MultiTermQuery query, TermCollector collector) throws IOException {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/TermInSetQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/TermInSetQuery.java b/lucene/core/src/java/org/apache/lucene/search/TermInSetQuery.java
index 4049e10..a8bf5b0 100644
--- a/lucene/core/src/java/org/apache/lucene/search/TermInSetQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/TermInSetQuery.java
@@ -33,7 +33,7 @@ import org.apache.lucene.index.PostingsEnum;
 import org.apache.lucene.index.PrefixCodedTerms;
 import org.apache.lucene.index.PrefixCodedTerms.TermIterator;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.index.TermState;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
@@ -268,9 +268,9 @@ public class TermInSetQuery extends Query implements Accountable {
           assert builder == null;
           BooleanQuery.Builder bq = new BooleanQuery.Builder();
           for (TermAndState t : matchingTerms) {
-            final TermContext termContext = new TermContext(searcher.getTopReaderContext());
-            termContext.register(t.state, context.ord, t.docFreq, t.totalTermFreq);
-            bq.add(new TermQuery(new Term(t.field, t.term), termContext), Occur.SHOULD);
+            final TermStates termStates = new TermStates(searcher.getTopReaderContext());
+            termStates.register(t.state, context.ord, t.docFreq, t.totalTermFreq);
+            bq.add(new TermQuery(new Term(t.field, t.term), termStates), Occur.SHOULD);
           }
           Query q = new ConstantScoreQuery(bq.build());
           final Weight weight = searcher.rewrite(q).createWeight(searcher, scoreMode, score());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/TermQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/TermQuery.java b/lucene/core/src/java/org/apache/lucene/search/TermQuery.java
index 3fa465d..d629acd 100644
--- a/lucene/core/src/java/org/apache/lucene/search/TermQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/TermQuery.java
@@ -28,9 +28,8 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.PostingsEnum;
 import org.apache.lucene.index.ReaderUtil;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.index.TermState;
-import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.search.similarities.Similarity;
 
@@ -41,16 +40,16 @@ import org.apache.lucene.search.similarities.Similarity;
 public class TermQuery extends Query {
 
   private final Term term;
-  private final TermContext perReaderTermState;
+  private final TermStates perReaderTermState;
 
   final class TermWeight extends Weight {
     private final Similarity similarity;
     private final Similarity.SimScorer simScorer;
-    private final TermContext termStates;
+    private final TermStates termStates;
     private final boolean needsScores;
 
     public TermWeight(IndexSearcher searcher, boolean needsScores,
-        float boost, TermContext termStates) throws IOException {
+        float boost, TermStates termStates) throws IOException {
       super(TermQuery.this);
       if (needsScores && termStates == null) {
         throw new IllegalStateException("termStates are required when scores are needed");
@@ -125,30 +124,17 @@ public class TermQuery extends Query {
      * the term does not exist in the given context
      */
     private TermsEnum getTermsEnum(LeafReaderContext context) throws IOException {
-      if (termStates != null) {
-        // TermQuery either used as a Query or the term states have been provided at construction time
-        assert termStates.wasBuiltFor(ReaderUtil.getTopLevelContext(context)) : "The top-reader used to create Weight is not the same as the current reader's top-reader (" + ReaderUtil.getTopLevelContext(context);
-        final TermState state = termStates.get(context.ord);
-        if (state == null) { // term is not present in that reader
-          assert termNotInReader(context.reader(), term) : "no termstate found but term exists in reader term=" + term;
-          return null;
-        }
-        final TermsEnum termsEnum = context.reader().terms(term.field()).iterator();
-        termsEnum.seekExact(term.bytes(), state);
-        return termsEnum;
-      } else {
-        // TermQuery used as a filter, so the term states have not been built up front
-        Terms terms = context.reader().terms(term.field());
-        if (terms == null) {
-          return null;
-        }
-        final TermsEnum termsEnum = terms.iterator();
-        if (termsEnum.seekExact(term.bytes())) {
-          return termsEnum;
-        } else {
-          return null;
-        }
+      assert termStates != null;
+      assert termStates.wasBuiltFor(ReaderUtil.getTopLevelContext(context)) :
+          "The top-reader used to create Weight is not the same as the current reader's top-reader (" + ReaderUtil.getTopLevelContext(context);
+      final TermState state = termStates.get(context);
+      if (state == null) { // term is not present in that reader
+        assert termNotInReader(context.reader(), term) : "no termstate found but term exists in reader term=" + term;
+        return null;
       }
+      final TermsEnum termsEnum = context.reader().terms(term.field()).iterator();
+      termsEnum.seekExact(term.bytes(), state);
+      return termsEnum;
     }
 
     private boolean termNotInReader(LeafReader reader, Term term) throws IOException {
@@ -189,7 +175,7 @@ public class TermQuery extends Query {
    * Expert: constructs a TermQuery that will use the provided docFreq instead
    * of looking up the docFreq against the searcher.
    */
-  public TermQuery(Term t, TermContext states) {
+  public TermQuery(Term t, TermStates states) {
     assert states != null;
     term = Objects.requireNonNull(t);
     perReaderTermState = Objects.requireNonNull(states);
@@ -203,18 +189,10 @@ public class TermQuery extends Query {
   @Override
   public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
     final IndexReaderContext context = searcher.getTopReaderContext();
-    final TermContext termState;
+    final TermStates termState;
     if (perReaderTermState == null
         || perReaderTermState.wasBuiltFor(context) == false) {
-      if (scoreMode.needsScores()) {
-        // make TermQuery single-pass if we don't have a PRTS or if the context
-        // differs!
-        termState = TermContext.build(context, term);
-      } else {
-        // do not compute the term state, this will help save seeks in the terms
-        // dict on segments that have a cache entry for this query
-        termState = null;
-      }
+      termState = TermStates.build(context, term, scoreMode.needsScores());
     } else {
       // PRTS was pre-build for this IS
       termState = this.perReaderTermState;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/TopTermsRewrite.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/TopTermsRewrite.java b/lucene/core/src/java/org/apache/lucene/search/TopTermsRewrite.java
index b75836e..dea4b0e 100644
--- a/lucene/core/src/java/org/apache/lucene/search/TopTermsRewrite.java
+++ b/lucene/core/src/java/org/apache/lucene/search/TopTermsRewrite.java
@@ -25,7 +25,7 @@ import java.util.PriorityQueue;
 
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.index.TermState;
 import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.util.ArrayUtil;
@@ -82,7 +82,7 @@ public abstract class TopTermsRewrite<B> extends TermCollectingRewrite<B> {
 
         // lazy init the initial ScoreTerm because comparator is not known on ctor:
         if (st == null)
-          st = new ScoreTerm(new TermContext(topReaderContext));
+          st = new ScoreTerm(new TermStates(topReaderContext));
         boostAtt = termsEnum.attributes().addAttribute(BoostAttribute.class);
       }
     
@@ -139,7 +139,7 @@ public abstract class TopTermsRewrite<B> extends TermCollectingRewrite<B> {
             visitedTerms.remove(st.bytes.get());
             st.termState.clear(); // reset the termstate! 
           } else {
-            st = new ScoreTerm(new TermContext(topReaderContext));
+            st = new ScoreTerm(new TermStates(topReaderContext));
           }
           assert stQueue.size() <= maxSize : "the PQ size must be limited to maxSize";
           // set maxBoostAtt with values to help FuzzyTermsEnum to optimize
@@ -193,8 +193,8 @@ public abstract class TopTermsRewrite<B> extends TermCollectingRewrite<B> {
   static final class ScoreTerm implements Comparable<ScoreTerm> {
     public final BytesRefBuilder bytes = new BytesRefBuilder();
     public float boost;
-    public final TermContext termState;
-    public ScoreTerm(TermContext termState) {
+    public final TermStates termState;
+    public ScoreTerm(TermStates termState) {
       this.termState = termState;
     }
     

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainQuery.java
index 8bb2633..23c1e2b 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainQuery.java
@@ -20,7 +20,7 @@ package org.apache.lucene.search.spans;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
 
@@ -61,7 +61,7 @@ abstract class SpanContainQuery extends SpanQuery implements Cloneable {
     final SpanWeight bigWeight;
     final SpanWeight littleWeight;
 
-    public SpanContainWeight(IndexSearcher searcher, Map<Term, TermContext> terms,
+    public SpanContainWeight(IndexSearcher searcher, Map<Term, TermStates> terms,
                              SpanWeight bigWeight, SpanWeight littleWeight, float boost) throws IOException {
       super(SpanContainQuery.this, searcher, terms, boost);
       this.bigWeight = bigWeight;
@@ -93,9 +93,9 @@ abstract class SpanContainQuery extends SpanQuery implements Cloneable {
     }
 
     @Override
-    public void extractTermContexts(Map<Term, TermContext> contexts) {
-      bigWeight.extractTermContexts(contexts);
-      littleWeight.extractTermContexts(contexts);
+    public void extractTermStates(Map<Term, TermStates> contexts) {
+      bigWeight.extractTermStates(contexts);
+      littleWeight.extractTermStates(contexts);
     }
 
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainingQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainingQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainingQuery.java
index 0d62f74..6366299 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainingQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainingQuery.java
@@ -23,7 +23,7 @@ import java.util.Map;
 
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.ScoreMode;
 
@@ -45,15 +45,15 @@ public final class SpanContainingQuery extends SpanContainQuery {
 
   @Override
   public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
-    SpanWeight bigWeight = big.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost);
-    SpanWeight littleWeight = little.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost);
-    return new SpanContainingWeight(searcher, scoreMode.needsScores() ? getTermContexts(bigWeight, littleWeight) : null,
+    SpanWeight bigWeight = big.createWeight(searcher, scoreMode, boost);
+    SpanWeight littleWeight = little.createWeight(searcher, scoreMode, boost);
+    return new SpanContainingWeight(searcher, scoreMode.needsScores() ? getTermStates(bigWeight, littleWeight) : null,
                                       bigWeight, littleWeight, boost);
   }
 
   public class SpanContainingWeight extends SpanContainWeight {
 
-    public SpanContainingWeight(IndexSearcher searcher, Map<Term, TermContext> terms,
+    public SpanContainingWeight(IndexSearcher searcher, Map<Term, TermStates> terms,
                                 SpanWeight bigWeight, SpanWeight littleWeight, float boost) throws IOException {
       super(searcher, terms, bigWeight, littleWeight, boost);
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/spans/SpanMultiTermQueryWrapper.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanMultiTermQueryWrapper.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanMultiTermQueryWrapper.java
index ee3f5de..088e730 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanMultiTermQueryWrapper.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanMultiTermQueryWrapper.java
@@ -24,7 +24,7 @@ import java.util.Objects;
 
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.MultiTermQuery;
@@ -163,7 +163,7 @@ public class SpanMultiTermQueryWrapper<Q extends MultiTermQuery> extends SpanQue
       }
     
       @Override
-      protected void addClause(List<SpanQuery> topLevel, Term term, int docCount, float boost, TermContext states) {
+      protected void addClause(List<SpanQuery> topLevel, Term term, int docCount, float boost, TermStates states) {
         final SpanTermQuery q = new SpanTermQuery(term, states);
         topLevel.add(q);
       }
@@ -211,7 +211,7 @@ public class SpanMultiTermQueryWrapper<Q extends MultiTermQuery> extends SpanQue
         }
 
         @Override
-        protected void addClause(List<SpanQuery> topLevel, Term term, int docFreq, float boost, TermContext states) {
+        protected void addClause(List<SpanQuery> topLevel, Term term, int docFreq, float boost, TermStates states) {
           final SpanTermQuery q = new SpanTermQuery(term, states);
           topLevel.add(q);
         }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/spans/SpanNearQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanNearQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanNearQuery.java
index 24a047f..17b9e51 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanNearQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanNearQuery.java
@@ -29,7 +29,7 @@ import java.util.Set;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
@@ -181,24 +181,24 @@ public class SpanNearQuery extends SpanQuery implements Cloneable {
   public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
     List<SpanWeight> subWeights = new ArrayList<>();
     for (SpanQuery q : clauses) {
-      subWeights.add(q.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost));
+      subWeights.add(q.createWeight(searcher, scoreMode, boost));
     }
-    return new SpanNearWeight(subWeights, searcher, scoreMode.needsScores() ? getTermContexts(subWeights) : null, boost);
+    return new SpanNearWeight(subWeights, searcher, scoreMode.needsScores() ? getTermStates(subWeights) : null, boost);
   }
 
   public class SpanNearWeight extends SpanWeight {
 
     final List<SpanWeight> subWeights;
 
-    public SpanNearWeight(List<SpanWeight> subWeights, IndexSearcher searcher, Map<Term, TermContext> terms, float boost) throws IOException {
+    public SpanNearWeight(List<SpanWeight> subWeights, IndexSearcher searcher, Map<Term, TermStates> terms, float boost) throws IOException {
       super(SpanNearQuery.this, searcher, terms, boost);
       this.subWeights = subWeights;
     }
 
     @Override
-    public void extractTermContexts(Map<Term, TermContext> contexts) {
+    public void extractTermStates(Map<Term, TermStates> contexts) {
       for (SpanWeight w : subWeights) {
-        w.extractTermContexts(contexts);
+        w.extractTermStates(contexts);
       }
     }
 
@@ -318,7 +318,7 @@ public class SpanNearQuery extends SpanQuery implements Cloneable {
       }
 
       @Override
-      public void extractTermContexts(Map<Term, TermContext> contexts) {
+      public void extractTermStates(Map<Term, TermStates> contexts) {
 
       }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/spans/SpanNotQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanNotQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanNotQuery.java
index 5b97f8d..6c56df3 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanNotQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanNotQuery.java
@@ -25,7 +25,7 @@ import java.util.Set;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
@@ -99,9 +99,9 @@ public final class SpanNotQuery extends SpanQuery {
 
   @Override
   public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
-    SpanWeight includeWeight = include.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost);
+    SpanWeight includeWeight = include.createWeight(searcher, scoreMode, boost);
     SpanWeight excludeWeight = exclude.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost);
-    return new SpanNotWeight(searcher, scoreMode.needsScores() ? getTermContexts(includeWeight, excludeWeight) : null,
+    return new SpanNotWeight(searcher, scoreMode.needsScores() ? getTermStates(includeWeight) : null,
                                   includeWeight, excludeWeight, boost);
   }
 
@@ -110,7 +110,7 @@ public final class SpanNotQuery extends SpanQuery {
     final SpanWeight includeWeight;
     final SpanWeight excludeWeight;
 
-    public SpanNotWeight(IndexSearcher searcher, Map<Term, TermContext> terms,
+    public SpanNotWeight(IndexSearcher searcher, Map<Term, TermStates> terms,
                          SpanWeight includeWeight, SpanWeight excludeWeight, float boost) throws IOException {
       super(SpanNotQuery.this, searcher, terms, boost);
       this.includeWeight = includeWeight;
@@ -118,8 +118,8 @@ public final class SpanNotQuery extends SpanQuery {
     }
 
     @Override
-    public void extractTermContexts(Map<Term, TermContext> contexts) {
-      includeWeight.extractTermContexts(contexts);
+    public void extractTermStates(Map<Term, TermStates> contexts) {
+      includeWeight.extractTermStates(contexts);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/spans/SpanOrQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanOrQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanOrQuery.java
index 2e15c92..849edaa 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanOrQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanOrQuery.java
@@ -27,7 +27,7 @@ import java.util.Set;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.search.DisiPriorityQueue;
 import org.apache.lucene.search.DisiWrapper;
 import org.apache.lucene.search.DisjunctionDISIApproximation;
@@ -119,16 +119,16 @@ public final class SpanOrQuery extends SpanQuery {
   public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
     List<SpanWeight> subWeights = new ArrayList<>(clauses.size());
     for (SpanQuery q : clauses) {
-      subWeights.add(q.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost));
+      subWeights.add(q.createWeight(searcher, scoreMode, boost));
     }
-    return new SpanOrWeight(searcher, scoreMode.needsScores() ? getTermContexts(subWeights) : null, subWeights, boost);
+    return new SpanOrWeight(searcher, scoreMode.needsScores() ? getTermStates(subWeights) : null, subWeights, boost);
   }
 
   public class SpanOrWeight extends SpanWeight {
 
     final List<SpanWeight> subWeights;
 
-    public SpanOrWeight(IndexSearcher searcher, Map<Term, TermContext> terms, List<SpanWeight> subWeights, float boost) throws IOException {
+    public SpanOrWeight(IndexSearcher searcher, Map<Term, TermStates> terms, List<SpanWeight> subWeights, float boost) throws IOException {
       super(SpanOrQuery.this, searcher, terms, boost);
       this.subWeights = subWeights;
     }
@@ -150,9 +150,9 @@ public final class SpanOrQuery extends SpanQuery {
     }
 
     @Override
-    public void extractTermContexts(Map<Term, TermContext> contexts) {
+    public void extractTermStates(Map<Term, TermStates> contexts) {
       for (SpanWeight w : subWeights) {
-        w.extractTermContexts(contexts);
+        w.extractTermStates(contexts);
       }
     }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/spans/SpanPositionCheckQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanPositionCheckQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanPositionCheckQuery.java
index f9b7697..099b627 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanPositionCheckQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanPositionCheckQuery.java
@@ -25,7 +25,7 @@ import java.util.Set;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.ScoreMode;
@@ -69,15 +69,15 @@ public abstract class SpanPositionCheckQuery extends SpanQuery implements Clonea
 
   @Override
   public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
-    SpanWeight matchWeight = match.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost);
-    return new SpanPositionCheckWeight(matchWeight, searcher, scoreMode.needsScores() ? getTermContexts(matchWeight) : null, boost);
+    SpanWeight matchWeight = match.createWeight(searcher, scoreMode, boost);
+    return new SpanPositionCheckWeight(matchWeight, searcher, scoreMode.needsScores() ? getTermStates(matchWeight) : null, boost);
   }
 
   public class SpanPositionCheckWeight extends SpanWeight {
 
     final SpanWeight matchWeight;
 
-    public SpanPositionCheckWeight(SpanWeight matchWeight, IndexSearcher searcher, Map<Term, TermContext> terms, float boost) throws IOException {
+    public SpanPositionCheckWeight(SpanWeight matchWeight, IndexSearcher searcher, Map<Term, TermStates> terms, float boost) throws IOException {
       super(SpanPositionCheckQuery.this, searcher, terms, boost);
       this.matchWeight = matchWeight;
     }
@@ -93,8 +93,8 @@ public abstract class SpanPositionCheckQuery extends SpanQuery implements Clonea
     }
 
     @Override
-    public void extractTermContexts(Map<Term, TermContext> contexts) {
-      matchWeight.extractTermContexts(contexts);
+    public void extractTermStates(Map<Term, TermStates> contexts) {
+      matchWeight.extractTermStates(contexts);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/spans/SpanQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanQuery.java
index 607a375..ca657b6 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanQuery.java
@@ -23,7 +23,7 @@ import java.util.Map;
 import java.util.TreeMap;
 
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.ScoreMode;
@@ -40,25 +40,25 @@ public abstract class SpanQuery extends Query {
   public abstract SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException;
 
   /**
-   * Build a map of terms to termcontexts, for use in constructing SpanWeights
+   * Build a map of terms to {@link TermStates}, for use in constructing SpanWeights
    * @lucene.internal
    */
-  public static Map<Term, TermContext> getTermContexts(SpanWeight... weights) {
-    Map<Term, TermContext> terms = new TreeMap<>();
+  public static Map<Term, TermStates> getTermStates(SpanWeight... weights) {
+    Map<Term, TermStates> terms = new TreeMap<>();
     for (SpanWeight w : weights) {
-      w.extractTermContexts(terms);
+      w.extractTermStates(terms);
     }
     return terms;
   }
 
   /**
-   * Build a map of terms to termcontexts, for use in constructing SpanWeights
+   * Build a map of terms to {@link TermStates}, for use in constructing SpanWeights
    * @lucene.internal
    */
-  public static Map<Term, TermContext> getTermContexts(Collection<SpanWeight> weights) {
-    Map<Term, TermContext> terms = new TreeMap<>();
+  public static Map<Term, TermStates> getTermStates(Collection<SpanWeight> weights) {
+    Map<Term, TermStates> terms = new TreeMap<>();
     for (SpanWeight w : weights) {
-      w.extractTermContexts(terms);
+      w.extractTermStates(terms);
     }
     return terms;
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java
index 9eea3aa..9ac7afb 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java
@@ -28,7 +28,7 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.PostingsEnum;
 import org.apache.lucene.index.ReaderUtil;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.index.TermState;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
@@ -41,21 +41,21 @@ import org.apache.lucene.search.ScoreMode;
 public class SpanTermQuery extends SpanQuery {
 
   protected final Term term;
-  protected final TermContext termContext;
+  protected final TermStates termStates;
 
   /** Construct a SpanTermQuery matching the named term's spans. */
   public SpanTermQuery(Term term) {
     this.term = Objects.requireNonNull(term);
-    this.termContext = null;
+    this.termStates = null;
   }
 
   /**
    * Expert: Construct a SpanTermQuery matching the named term's spans, using
-   * the provided TermContext
+   * the provided TermStates
    */
-  public SpanTermQuery(Term term, TermContext context) {
+  public SpanTermQuery(Term term, TermStates termStates) {
     this.term = Objects.requireNonNull(term);
-    this.termContext = context;
+    this.termStates = termStates;
   }
 
   /** Return the term whose spans are matched. */
@@ -66,25 +66,25 @@ public class SpanTermQuery extends SpanQuery {
 
   @Override
   public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
-    final TermContext context;
+    final TermStates context;
     final IndexReaderContext topContext = searcher.getTopReaderContext();
-    if (termContext == null || termContext.wasBuiltFor(topContext) == false) {
-      context = TermContext.build(topContext, term);
+    if (termStates == null || termStates.wasBuiltFor(topContext) == false) {
+      context = TermStates.build(topContext, term, scoreMode.needsScores());
     }
     else {
-      context = termContext;
+      context = termStates;
     }
     return new SpanTermWeight(context, searcher, scoreMode.needsScores() ? Collections.singletonMap(term, context) : null, boost);
   }
 
   public class SpanTermWeight extends SpanWeight {
 
-    final TermContext termContext;
+    final TermStates termStates;
 
-    public SpanTermWeight(TermContext termContext, IndexSearcher searcher, Map<Term, TermContext> terms, float boost) throws IOException {
+    public SpanTermWeight(TermStates termStates, IndexSearcher searcher, Map<Term, TermStates> terms, float boost) throws IOException {
       super(SpanTermQuery.this, searcher, terms, boost);
-      this.termContext = termContext;
-      assert termContext != null : "TermContext must not be null";
+      this.termStates = termStates;
+      assert termStates != null : "TermStates must not be null";
     }
 
     @Override
@@ -98,16 +98,16 @@ public class SpanTermQuery extends SpanQuery {
     }
 
     @Override
-    public void extractTermContexts(Map<Term, TermContext> contexts) {
-      contexts.put(term, termContext);
+    public void extractTermStates(Map<Term, TermStates> contexts) {
+      contexts.put(term, termStates);
     }
 
     @Override
     public Spans getSpans(final LeafReaderContext context, Postings requiredPostings) throws IOException {
 
-      assert termContext.wasBuiltFor(ReaderUtil.getTopLevelContext(context)) : "The top-reader used to create Weight is not the same as the current reader's top-reader (" + ReaderUtil.getTopLevelContext(context);
+      assert termStates.wasBuiltFor(ReaderUtil.getTopLevelContext(context)) : "The top-reader used to create Weight is not the same as the current reader's top-reader (" + ReaderUtil.getTopLevelContext(context);
 
-      final TermState state = termContext.get(context.ord);
+      final TermState state = termStates.get(context);
       if (state == null) { // term is not present in that reader
         assert context.reader().docFreq(term) == 0 : "no termstate found but term exists in reader term=" + term;
         return null;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java
index f1d8894..e971610 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java
@@ -24,7 +24,7 @@ import java.util.Map;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.PostingsEnum;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.search.CollectionStatistics;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.IndexSearcher;
@@ -79,24 +79,24 @@ public abstract class SpanWeight extends Weight {
    * Create a new SpanWeight
    * @param query the parent query
    * @param searcher the IndexSearcher to query against
-   * @param termContexts a map of terms to termcontexts for use in building the similarity.  May
+   * @param termStates a map of terms to {@link TermStates} for use in building the similarity.  May
    *                     be null if scores are not required
    * @throws IOException on error
    */
-  public SpanWeight(SpanQuery query, IndexSearcher searcher, Map<Term, TermContext> termContexts, float boost) throws IOException {
+  public SpanWeight(SpanQuery query, IndexSearcher searcher, Map<Term, TermStates> termStates, float boost) throws IOException {
     super(query);
     this.field = query.getField();
     this.similarity = searcher.getSimilarity();
-    this.simScorer = buildSimWeight(query, searcher, termContexts, boost);
+    this.simScorer = buildSimWeight(query, searcher, termStates, boost);
   }
 
-  private Similarity.SimScorer buildSimWeight(SpanQuery query, IndexSearcher searcher, Map<Term, TermContext> termContexts, float boost) throws IOException {
-    if (termContexts == null || termContexts.size() == 0 || query.getField() == null)
+  private Similarity.SimScorer buildSimWeight(SpanQuery query, IndexSearcher searcher, Map<Term, TermStates> termStates, float boost) throws IOException {
+    if (termStates == null || termStates.size() == 0 || query.getField() == null)
       return null;
-    TermStatistics[] termStats = new TermStatistics[termContexts.size()];
+    TermStatistics[] termStats = new TermStatistics[termStates.size()];
     int termUpTo = 0;
-    for (Term term : termContexts.keySet()) {
-      TermStatistics termStatistics = searcher.termStatistics(term, termContexts.get(term));
+    for (Term term : termStates.keySet()) {
+      TermStatistics termStatistics = searcher.termStatistics(term, termStates.get(term));
       if (termStatistics != null) {
         termStats[termUpTo++] = termStatistics;
       }
@@ -110,10 +110,10 @@ public abstract class SpanWeight extends Weight {
   }
 
   /**
-   * Collect all TermContexts used by this Weight
-   * @param contexts a map to add the TermContexts to
+   * Collect all TermStates used by this Weight
+   * @param contexts a map to add the TermStates to
    */
-  public abstract void extractTermContexts(Map<Term, TermContext> contexts);
+  public abstract void extractTermStates(Map<Term, TermStates> contexts);
 
   /**
    * Expert: Return a Spans object iterating over matches from this Weight

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/java/org/apache/lucene/search/spans/SpanWithinQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanWithinQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanWithinQuery.java
index 9c618dd..fba85fe 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanWithinQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanWithinQuery.java
@@ -23,7 +23,7 @@ import java.util.Map;
 
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.ScoreMode;
 
@@ -46,15 +46,15 @@ public final class SpanWithinQuery extends SpanContainQuery {
 
   @Override
   public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
-    SpanWeight bigWeight = big.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost);
-    SpanWeight littleWeight = little.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost);
-    return new SpanWithinWeight(searcher, scoreMode.needsScores() ? getTermContexts(bigWeight, littleWeight) : null,
+    SpanWeight bigWeight = big.createWeight(searcher, scoreMode, boost);
+    SpanWeight littleWeight = little.createWeight(searcher, scoreMode, boost);
+    return new SpanWithinWeight(searcher, scoreMode.needsScores() ? getTermStates(bigWeight, littleWeight) : null,
                                       bigWeight, littleWeight, boost);
   }
 
   public class SpanWithinWeight extends SpanContainWeight {
 
-    public SpanWithinWeight(IndexSearcher searcher, Map<Term, TermContext> terms,
+    public SpanWithinWeight(IndexSearcher searcher, Map<Term, TermStates> terms,
                             SpanWeight bigWeight, SpanWeight littleWeight, float boost) throws IOException {
       super(searcher, terms, bigWeight, littleWeight, boost);
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d250a146/lucene/core/src/test/org/apache/lucene/search/TestMinShouldMatch2.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestMinShouldMatch2.java b/lucene/core/src/test/org/apache/lucene/search/TestMinShouldMatch2.java
index 268e8fc..30b03ac 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestMinShouldMatch2.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestMinShouldMatch2.java
@@ -34,7 +34,7 @@ import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.SortedSetDocValues;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermStates;
 import org.apache.lucene.search.similarities.ClassicSimilarity;
 import org.apache.lucene.search.similarities.Similarity.SimScorer;
 import org.apache.lucene.store.Directory;
@@ -329,7 +329,7 @@ public class TestMinShouldMatch2 extends LuceneTestCase {
         if (ord >= 0) {
           boolean success = ords.add(ord);
           assert success; // no dups
-          TermContext context = TermContext.build(reader.getContext(), term);
+          TermStates context = TermStates.build(reader.getContext(), term, true);
           SimScorer w = weight.similarity.scorer(1f,
                         searcher.collectionStatistics("field"),
                         searcher.termStatistics(term, context));