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