src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
*** old/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java Tue Dec 2 20:15:04 2014
--- new/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java Tue Dec 2 20:15:04 2014
*** 23,32 ****
--- 23,33 ----
* questions.
*/
package java.lang.invoke;
+ import java.lang.ref.SoftReference;
import java.util.Arrays;
import static java.lang.invoke.LambdaForm.*;
import static java.lang.invoke.LambdaForm.BasicType.*;
import static java.lang.invoke.MethodHandleImpl.Intrinsic;
import java.util.Collections;
*** 56,69 ****
--- 57,69 ----
/** A description of a cached transform, possibly associated with the result of the transform.
* The logical content is a sequence of byte values, starting with a Kind.ordinal value.
* The sequence is unterminated, ending with an indefinite number of zero bytes.
* Sequences that are simple (short enough and with small enough values) pack into a 64-bit long.
*/
! private static final class Transform extends SoftReference<LambdaForm> {
final long packedBytes;
final byte[] fullBytes;
final LambdaForm result; // result of transform, or null, if there is none available
private enum Kind {
NO_KIND, // necessary because ordinal must be greater than zero
BIND_ARG, ADD_ARG, DUP_ARG,
SPREAD_ARGS,
*** 138,150 ****
--- 138,150 ----
}
Kind kind() { return Kind.values()[byteAt(0)]; }
private Transform(long packedBytes, byte[] fullBytes, LambdaForm result) {
+ super(result);
this.packedBytes = packedBytes;
this.fullBytes = fullBytes;
this.result = result;
}
private Transform(long packedBytes) {
this(packedBytes, null, null);
assert(packedBytes != 0);
}
*** 241,261 ****
--- 241,262 ----
}
if (fullBytes != null) {
buf.append("unpacked");
buf.append(Arrays.toString(fullBytes));
}
+ LambdaForm result = get();
if (result != null) {
buf.append(" result=");
buf.append(result);
}
return buf.toString();
}
}
/** Find a previously cached transform equivalent to the given one, and return its result. */
private LambdaForm getInCache(Transform key) {
! assert(key.result == null);
! assert(key.get() == null);
// The transformCache is one of null, Transform, Transform[], or ConcurrentHashMap.
Object c = lambdaForm.transformCache;
Transform k = null;
if (c instanceof ConcurrentHashMap) {
@SuppressWarnings("unchecked")
*** 274,284 ****
--- 275,285 ----
if (t == null) break;
if (t.equals(key)) { k = t; break; }
}
}
assert(k == null || key.equals(k));
! return k == null ? null : k.result;
! return (k != null) ? k.get() : null;
}
/** Arbitrary but reasonable limits on Transform[] size for cache. */
private static final int MIN_CACHE_ARRAY_SIZE = 4, MAX_CACHE_ARRAY_SIZE = 16;
*** 291,301 ****
--- 292,312 ----
Object c = lambdaForm.transformCache;
if (c instanceof ConcurrentHashMap) {
@SuppressWarnings("unchecked")
ConcurrentHashMap<Transform,Transform> m = (ConcurrentHashMap<Transform,Transform>) c;
Transform k = m.putIfAbsent(key, key);
! return k != null ? k.result : form;
! if (k == null) return form;
+ LambdaForm result = k.get();
+ if (result != null) {
+ return result;
+ } else {
+ if (m.replace(key, k, key)) {
+ return form;
+ } else {
+ continue;
+ }
+ }
}
assert(pass == 0);
synchronized (lambdaForm) {
c = lambdaForm.transformCache;
if (c instanceof ConcurrentHashMap)
*** 306,337 ****
--- 317,366 ----
}
Transform[] ta;
if (c instanceof Transform) {
Transform k = (Transform)c;
if (k.equals(key)) {
! return k.result;
! LambdaForm result = k.get();
+ if (result == null) {
+ lambdaForm.transformCache = key;
+ return form;
+ } else {
+ return result;
+ }
+ } else if (k.get() == null) { // overwrite stale entry
+ lambdaForm.transformCache = key;
+ return form;
}
// expand one-element cache to small array
ta = new Transform[MIN_CACHE_ARRAY_SIZE];
ta[0] = k;
- lambdaForm.transformCache = c = ta;
} else {
// it is already expanded
ta = (Transform[])c;
}
int len = ta.length;
+ int stale = -1;
int i;
for (i = 0; i < len; i++) {
Transform k = ta[i];
if (k == null) {
break;
}
if (k.equals(key)) {
! return k.result;
! LambdaForm result = k.get();
+ if (result == null) {
+ ta[i] = key;
+ return form;
+ } else {
+ return result;
}
+ } else if (stale < 0 && k.get() == null) {
+ stale = i; // remember 1st stale entry index
}
if (i < len) {
+ }
+ if (i < len || stale >= 0) {
// just fall through to cache update
} else if (len < MAX_CACHE_ARRAY_SIZE) {
len = Math.min(len * 2, MAX_CACHE_ARRAY_SIZE);
ta = Arrays.copyOf(ta, len);
lambdaForm.transformCache = ta;
*** 342,352 ****
--- 371,382 ----
}
lambdaForm.transformCache = m;
// The second iteration will update for this query, concurrently.
continue;
}
! ta[i] = key;
! int idx = (stale >= 0) ? stale : i;
+ ta[idx] = key;
return form;
}
}
}
src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File