src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
*** old/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Fri Oct 10 22:05:00 2014
--- new/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Fri Oct 10 22:05:00 2014
*** 705,725 ****
--- 705,811 ----
assert(test.type().equals(type.changeReturnType(boolean.class)) && fallback.type().equals(type));
MethodType basicType = type.basicType();
LambdaForm form = makeGuardWithTestForm(basicType);
BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
BoundMethodHandle mh;
+
try {
mh = (BoundMethodHandle)
data.constructor().invokeBasic(type, form,
! (Object) test, (Object) target, (Object) fallback);
! (Object) test, (Object) profile(target), (Object) profile(fallback));
} catch (Throwable ex) {
throw uncaughtException(ex);
}
assert(mh.type() == type);
return mh;
}
+
+ static
+ MethodHandle profile(MethodHandle target) {
+ if (DONT_INLINE_THRESHOLD > 0) {
+ return BlockInliningWrapper.make(target);
+ } else {
+ return target;
+ }
+ }
+
+ /**
+ * Block inlining during JIT-compilation of a target method handle if it hasn't been invoked enough times.
+ * Corresponding LambdaForm has @DontInline when compiled into bytecode.
+ */
+ static class BlockInliningWrapper extends DelegatingMethodHandle {
+ private final MethodHandle target;
+ private int count;
+ private volatile boolean isActivated = true;
+
+ private BlockInliningWrapper(MethodHandle target, LambdaForm lform, int count) {
+ super(target.type(), lform);
+ this.target = target;
+ this.count = count;
+ }
+
+ @Hidden
+ @Override
+ protected MethodHandle getTarget() {
+ return target;
+ }
+
+ @Override
+ public MethodHandle asTypeUncached(MethodType newType) {
+ MethodHandle newTarget = target.asType(newType);
+ return asTypeCache = isActivated ? make(newTarget)
+ : newTarget; // no need for a wrapper anymore
+ }
+
+ boolean unblock() {
+ if (count <= 0) {
+ // Try to limit number of updates. MethodHandle.updateForm() doesn't guarantee LF update visibility.
+ if (isActivated) {
+ isActivated = false;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ --count;
+ return false;
+ }
+ }
+
+ static MethodHandle make(MethodHandle target) {
+ LambdaForm lform = DelegatingMethodHandle.makeReinvokerForm(target,
+ MethodTypeForm.LF_DELEGATE_COUNTING, BlockInliningWrapper.class, "reinvoker.dontInline", false,
+ DelegatingMethodHandle.NF_getTarget, NF_maybeUnblock);
+ MethodHandle wrapper = new BlockInliningWrapper(target, lform, DONT_INLINE_THRESHOLD);
+ return wrapper;
+ }
+
+ @Hidden
+ static void maybeUnblock(Object o1) {
+ BlockInliningWrapper wrapper = (BlockInliningWrapper) o1;
+ if (wrapper.unblock()) {
+ // Reached invocation threshold. Replace counting/blocking wrapper with a reinvoker.
+ wrapper.isActivated = false;
+ MethodHandle target = wrapper.getTarget();
+ LambdaForm lform = DelegatingMethodHandle.makeReinvokerForm(
+ target, MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, NF_getTarget);
+ wrapper.updateForm(lform);
+ }
+ }
+
+ static final NamedFunction NF_maybeUnblock;
+ static {
+ Class<?> THIS_CLASS = BlockInliningWrapper.class;
+ try {
+ NF_maybeUnblock = new NamedFunction(THIS_CLASS.getDeclaredMethod("maybeUnblock", Object.class));
+ } catch (ReflectiveOperationException ex) {
+ throw newInternalError(ex);
+ }
+ }
+ }
+
static
LambdaForm makeGuardWithTestForm(MethodType basicType) {
LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWT);
if (lform != null) return lform;
final int THIS_MH = 0; // the BMH_LLL
src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File