final V putVal(K key, V value, boolean onlyIfAbsent) {
if (key != null && value != null) {
int hash = spread(key.hashCode());
int binCount = 0;
ConcurrentHashMap.Node[] tab = this.table;
while(true) {
int n;
while(tab == null || (n = tab.length) == 0) {
tab = this.initTable();
}
ConcurrentHashMap.Node f;
int i;
if ((f = tabAt(tab, i = n - 1 & hash)) == null) {
if (casTabAt(tab, i, (ConcurrentHashMap.Node)null, new ConcurrentHashMap.Node(hash, key, value))) {
break;
}
} else {
int fh;
if ((fh = f.hash) == -1) {
tab = this.helpTransfer(tab, f);
} else {
Object fk;
Object fv;
if (onlyIfAbsent && fh == hash && ((fk = f.key) == key || fk != null && key.equals(fk)) && (fv = f.val) != null) {
return fv;
}
V oldVal = null;
synchronized(f) {
if (tabAt(tab, i) == f) {
if (fh < 0) {
if (f instanceof ConcurrentHashMap.TreeBin) {
binCount = 2;
ConcurrentHashMap.TreeNode p;
if ((p = ((ConcurrentHashMap.TreeBin)f).putTreeVal(hash, key, value)) != null) {
oldVal = p.val;
if (!onlyIfAbsent) {
p.val = value;
}
}
} else if (f instanceof ConcurrentHashMap.ReservationNode) {
throw new IllegalStateException("Recursive update");
}
} else {
label124: {
binCount = 1;
ConcurrentHashMap.Node e;
Object ek;
for(e = f; e.hash != hash || (ek = e.key) != key && (ek == null || !key.equals(ek)); ++binCount) {
ConcurrentHashMap.Node<K, V> pred = e;
if ((e = e.next) == null) {
pred.next = new ConcurrentHashMap.Node(hash, key, value);
break label124;
}
}
oldVal = e.val;
if (!onlyIfAbsent) {
e.val = value;
}
}
}
}
}
if (binCount != 0) {
if (binCount >= 8) {
this.treeifyBin(tab, i);
}
if (oldVal != null) {
return oldVal;
}
break;
}
}
}
}
this.addCount(1L, binCount);
return null;
} else {
throw new NullPointerException();
}
}