@Override
    protected void rehash(int newN) {
      // rehash should discard gced keys
      // because otherwise there is a remote probability of
      // having two (Weak|Soft)Keys with accidentally equal hashCodes and different but gced key values
      assert newN != 0;
      Object[] key = this.key;
      Object[] value = this.value;
      int mask = newN - 1; // Note that this is used by the hashing macro
      //noinspection unchecked
      Key<K>[] newKey = new Key[newN + 1];
      Object[] newValue = new Object[newN + 1];
      int pos;
      int keysToProcess = size;
      for (int i = n; i >= 0 && keysToProcess > 0; i--) {
        //noinspection unchecked
        Key<K> k = (Key<K>)key[i];
        if (k == null) {
          continue;
        }
        keysToProcess--;
        K referent = k.get();
        if (referent == null) {
          size--;
          continue;
        }
        if (!(newKey[pos = HashCommon.mix(k.hashCode()) & mask] == null)) {
          while (!(newKey[pos = (pos + 1) & mask] == null)) ;
        }
        newKey[pos] = k;
        newValue[pos] = value[i];
        // avoid inserting gced keys into new table
        ObjectUtilsRt.reachabilityFence(referent);
      }
      newValue[newN] = value[n];
      n = newN;
      this.mask = mask;
      maxFill = HashCommon.maxFill(n, f);
      this.key = newKey;
      this.value = (V[])newValue;
    }
@Override
    protected void rehash(int newN)