private void pushTerm(BytesRef text) throws IOException {
    int limit = Math.min(lastTerm.length(), text.length);
    //if (DEBUG) System.out.println("\nterm: " + text.utf8ToString());

    // Find common prefix between last term and current term:
    int pos = 0;
    while (pos < limit && lastTerm.byteAt(pos) == text.bytes[text.offset+pos]) {
      pos++;
    }

    //if (DEBUG) System.out.println("  shared=" + pos + "  lastTerm.length=" + lastTerm.length());

    // Close the "abandoned" suffix now:
    for(int i=lastTerm.length()-1;i>=pos;i--) {

      // How many items on top of the stack share the current suffix
      // we are closing:
      int prefixTopSize = pending.size() - prefixStarts[i];

      while (prefixTopSize >= minItemsInPrefix) {       
        //if (DEBUG) System.out.println("  pop: i=" + i + " prefixTopSize=" + prefixTopSize + " minItemsInBlock=" + minItemsInPrefix);
        savePrefixes(i+1, prefixTopSize);
        //prefixStarts[i] -= prefixTopSize;
        //if (DEBUG) System.out.println("    after savePrefixes: " + (pending.size() - prefixStarts[i]) + " pending.size()=" + pending.size() + " start=" + prefixStarts[i]);

        // For large floor blocks, it's possible we should now re-run on the new prefix terms we just created:
        prefixTopSize = pending.size() - prefixStarts[i];
      }
    }

    if (prefixStarts.length < text.length) {
      prefixStarts = ArrayUtil.grow(prefixStarts, text.length);
    }

    // Init new tail:
    for(int i=pos;i<text.length;i++) {
      prefixStarts[i] = pending.size();
    }

    lastTerm.copyBytes(text);

    // Only append the first (optional) empty string, no the fake last one used to close all prefixes:
    if (text.length > 0 || pending.isEmpty()) {
      byte[] termBytes = new byte[text.length];
      System.arraycopy(text.bytes, text.offset, termBytes, 0, text.length);
      pending.add(termBytes);
    }
  }