Index: solr/src/java/org/apache/solr/search/MissingStringLastComparatorSource.java
===================================================================
--- solr/src/java/org/apache/solr/search/MissingStringLastComparatorSource.java	(revision 996730)
+++ solr/src/java/org/apache/solr/search/MissingStringLastComparatorSource.java	(working copy)
@@ -66,16 +66,11 @@
     private final BytesRef[] values;
     private final int[] readerGen;
 
-    private int currentReaderGen = -1;
     private FieldCache.DocTermsIndex termsIndex;
     private final String field;
 
-    private int bottomSlot = -1;
-    private int bottomOrd;
-    private boolean bottomSameReader;
-    private BytesRef bottomValue;
-    private final BytesRef tempBR = new BytesRef();
     private final BytesRef NULL_VAL;
+    private PerSegmentComparator current;
 
     public TermOrdValComparator_SML(int numHits, String field, int sortPos, boolean reversed, BytesRef nullVal) {
       ords = new int[numHits];
@@ -87,21 +82,12 @@
 
     @Override
     public int compare(int slot1, int slot2) {
-      if (readerGen[slot1] == readerGen[slot2]) {
-        return ords[slot1] - ords[slot2];
-      }
+      throw new UnsupportedOperationException();
+    }
 
-      final BytesRef val1 = values[slot1];
-      final BytesRef val2 = values[slot2];
-      if (val1 == null) {
-        if (val2 == null) {
-          return 0;
-        }
-        return 1;
-      } else if (val2 == null) {
-        return -1;
-      }
-      return val1.compareTo(val2);
+    @Override
+    public void setBottom(int slot) {
+      throw new UnsupportedOperationException();
     }
 
     @Override
@@ -114,43 +100,121 @@
       throw new UnsupportedOperationException();
     }
 
+    @Override
+    public Comparable<?> value(int slot) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public FieldComparator setNextReader(IndexReader reader, int docBase) throws IOException {
+      return TermOrdValComparator_SML.createComparator(reader, this);
+    }
+
     // Base class for specialized (per bit width of the
     // ords) per-segment comparator.  NOTE: this is messy;
     // we do this only because hotspot can't reliably inline
     // the underlying array access when looking up doc->ord
-    private abstract class PerSegmentComparator extends FieldComparator {
+    private static abstract class PerSegmentComparator extends FieldComparator {
+      protected TermOrdValComparator_SML parent;
+      protected final int[] ords;
+      protected final BytesRef[] values;
+      protected final int[] readerGen;
 
+      protected int currentReaderGen = -1;
+      protected FieldCache.DocTermsIndex termsIndex;
+
+      protected int bottomSlot = -1;
+      protected int bottomOrd;
+      protected boolean bottomSameReader = false;
+      protected BytesRef bottomValue;
+      protected final BytesRef tempBR = new BytesRef();
+
+
+      public PerSegmentComparator(TermOrdValComparator_SML parent) {
+        this.parent = parent;
+        PerSegmentComparator previous = parent.current;
+        if (previous != null) {
+          currentReaderGen = previous.currentReaderGen;
+          bottomSlot = previous.bottomSlot;
+          bottomOrd = previous.bottomOrd;
+          bottomValue = previous.bottomValue;
+        }
+        ords = parent.ords;
+        values = parent.values;
+        readerGen = parent.readerGen;
+        termsIndex = parent.termsIndex;
+        currentReaderGen++;
+      }
+      
       @Override
       public FieldComparator setNextReader(IndexReader reader, int docBase) throws IOException {
-        return TermOrdValComparator_SML.this.setNextReader(reader, docBase);
+        return TermOrdValComparator_SML.createComparator(reader, parent);
       }
 
       @Override
       public int compare(int slot1, int slot2) {
-        return TermOrdValComparator_SML.this.compare(slot1, slot2);
+      if (readerGen[slot1] == readerGen[slot2]) {
+        return ords[slot1] - ords[slot2];
       }
 
+      final BytesRef val1 = values[slot1];
+      final BytesRef val2 = values[slot2];
+      if (val1 == null) {
+        if (val2 == null) {
+          return 0;
+        }
+        return 1;
+      } else if (val2 == null) {
+        return -1;
+      }
+      return val1.compareTo(val2);
+      }
+
       @Override
       public void setBottom(final int bottom) {
-        TermOrdValComparator_SML.this.setBottom(bottom);
+      bottomSlot = bottom;
+
+      bottomValue = values[bottomSlot];
+      if (currentReaderGen == readerGen[bottomSlot]) {
+        bottomOrd = ords[bottomSlot];
+        bottomSameReader = true;
+      } else {
+        if (bottomValue == null) {
+          // 0 ord is null for all segments
+          assert ords[bottomSlot] == NULL_ORD;
+          bottomOrd = NULL_ORD;
+          bottomSameReader = true;
+          readerGen[bottomSlot] = currentReaderGen;
+        } else {
+          final int index = binarySearch(tempBR, termsIndex, bottomValue);
+          if (index < 0) {
+            bottomOrd = -index - 2;
+            bottomSameReader = false;
+          } else {
+            bottomOrd = index;
+            // exact value match
+            bottomSameReader = true;
+          }
+        }
       }
+      if (bottomSameReader) {
+        readerGen[bottomSlot] = currentReaderGen;
+      }
+      }
 
       @Override
       public Comparable<?> value(int slot) {
-        return TermOrdValComparator_SML.this.value(slot);
+        return values==null ? parent.NULL_VAL : values[slot];
       }
     }
 
     // Used per-segment when bit width of doc->ord is 8:
-    private final class ByteOrdComparator extends PerSegmentComparator {
+    private static final class ByteOrdComparator extends PerSegmentComparator {
       private final byte[] readerOrds;
-      private final FieldCache.DocTermsIndex termsIndex;
-      private final int docBase;
 
-      public ByteOrdComparator(byte[] readerOrds, FieldCache.DocTermsIndex termsIndex, int docBase) {
+      public ByteOrdComparator(byte[] readerOrds, TermOrdValComparator_SML parent) {
+        super(parent);
         this.readerOrds = readerOrds;
-        this.termsIndex = termsIndex;
-        this.docBase = docBase;
       }
 
       @Override
@@ -198,15 +262,12 @@
     }
 
     // Used per-segment when bit width of doc->ord is 16:
-    private final class ShortOrdComparator extends PerSegmentComparator {
+    private static final class ShortOrdComparator extends PerSegmentComparator {
       private final short[] readerOrds;
-      private final FieldCache.DocTermsIndex termsIndex;
-      private final int docBase;
 
-      public ShortOrdComparator(short[] readerOrds, FieldCache.DocTermsIndex termsIndex, int docBase) {
+      public ShortOrdComparator(short[] readerOrds, TermOrdValComparator_SML parent) {
+        super(parent);
         this.readerOrds = readerOrds;
-        this.termsIndex = termsIndex;
-        this.docBase = docBase;
       }
 
       @Override
@@ -254,15 +315,12 @@
     }
 
     // Used per-segment when bit width of doc->ord is 32:
-    private final class IntOrdComparator extends PerSegmentComparator {
+    private static final class IntOrdComparator extends PerSegmentComparator {
       private final int[] readerOrds;
-      private final FieldCache.DocTermsIndex termsIndex;
-      private final int docBase;
 
-      public IntOrdComparator(int[] readerOrds, FieldCache.DocTermsIndex termsIndex, int docBase) {
+      public IntOrdComparator(int[] readerOrds, TermOrdValComparator_SML parent) {
+        super(parent);
         this.readerOrds = readerOrds;
-        this.termsIndex = termsIndex;
-        this.docBase = docBase;
       }
 
       @Override
@@ -311,15 +369,12 @@
 
     // Used per-segment when bit width is not a native array
     // size (8, 16, 32):
-    private final class AnyOrdComparator extends PerSegmentComparator {
+    private static final class AnyOrdComparator extends PerSegmentComparator {
       private final PackedInts.Reader readerOrds;
-      private final FieldCache.DocTermsIndex termsIndex;
-      private final int docBase;
 
-      public AnyOrdComparator(PackedInts.Reader readerOrds, FieldCache.DocTermsIndex termsIndex, int docBase) {
+      public AnyOrdComparator(PackedInts.Reader readerOrds, TermOrdValComparator_SML parent) {
+        super(parent);
         this.readerOrds = readerOrds;
-        this.termsIndex = termsIndex;
-        this.docBase = docBase;
       }
 
       @Override
@@ -368,64 +423,28 @@
     }
 
 
-    
-    @Override
-    public FieldComparator setNextReader(IndexReader reader, int docBase) throws IOException {
-      termsIndex = FieldCache.DEFAULT.getTermsIndex(reader, field);
-      final PackedInts.Reader docToOrd = termsIndex.getDocToOrd();
-      FieldComparator perSegComp;
+
+    public static FieldComparator createComparator(IndexReader reader, TermOrdValComparator_SML parent) throws IOException {
+      parent.termsIndex = FieldCache.DEFAULT.getTermsIndex(reader, parent.field);
+      final PackedInts.Reader docToOrd = parent.termsIndex.getDocToOrd();
+      PerSegmentComparator perSegComp;
+
       if (docToOrd instanceof Direct8) {
-        perSegComp = new ByteOrdComparator(((Direct8) docToOrd).getArray(), termsIndex, docBase);
+        perSegComp = new ByteOrdComparator(((Direct8) docToOrd).getArray(), parent);
       } else if (docToOrd instanceof Direct16) {
-        perSegComp = new ShortOrdComparator(((Direct16) docToOrd).getArray(), termsIndex, docBase);
+        perSegComp = new ShortOrdComparator(((Direct16) docToOrd).getArray(), parent);
       } else if (docToOrd instanceof Direct32) {
-        perSegComp = new IntOrdComparator(((Direct32) docToOrd).getArray(), termsIndex, docBase);
+        perSegComp = new IntOrdComparator(((Direct32) docToOrd).getArray(), parent);
       } else {
-        perSegComp = new AnyOrdComparator(docToOrd, termsIndex, docBase);
+        perSegComp = new AnyOrdComparator(docToOrd, parent);
       }
 
-      currentReaderGen++;
-      if (bottomSlot != -1) {
-        perSegComp.setBottom(bottomSlot);
+      if (perSegComp.bottomSlot != -1) {
+        perSegComp.setBottom(perSegComp.bottomSlot);
       }
 
+      parent.current = perSegComp;
       return perSegComp;
     }
 
-    @Override
-    public void setBottom(final int bottom) {
-      bottomSlot = bottom;
-
-      bottomValue = values[bottomSlot];
-      if (currentReaderGen == readerGen[bottomSlot]) {
-        bottomOrd = ords[bottomSlot];
-        bottomSameReader = true;
-      } else {
-        if (bottomValue == null) {
-          // 0 ord is null for all segments
-          assert ords[bottomSlot] == NULL_ORD;
-          bottomOrd = NULL_ORD;
-          bottomSameReader = true;
-          readerGen[bottomSlot] = currentReaderGen;
-        } else {
-          final int index = binarySearch(tempBR, termsIndex, bottomValue);
-          if (index < 0) {
-            bottomOrd = -index - 2;
-            bottomSameReader = false;
-          } else {
-            bottomOrd = index;
-            // exact value match
-            bottomSameReader = true;
-          }
-        }
-      }
-      if (bottomSameReader) {
-        readerGen[bottomSlot] = currentReaderGen;
-      }
-    }
-
-    @Override
-    public Comparable<?> value(int slot) {
-      return values==null ? NULL_VAL : values[slot];
-    }
   }
\ No newline at end of file
