# HG changeset patch # Parent 201359ac37c0f92cdc35789cffb8c9bc929b18ec diff --git a/src/share/classes/java/lang/invoke/CallSite.java b/src/share/classes/java/lang/invoke/CallSite.java --- a/src/share/classes/java/lang/invoke/CallSite.java +++ b/src/share/classes/java/lang/invoke/CallSite.java @@ -114,6 +114,7 @@ CallSite(MethodHandle target) { target.type(); // null check this.target = target; + target.maybeCompileToBytecode(); } /** @@ -133,6 +134,7 @@ MethodHandle boundTarget = (MethodHandle) createTargetHook.invokeWithArguments(selfCCS); checkTargetChange(this.target, boundTarget); this.target = boundTarget; + boundTarget.maybeCompileToBytecode(); } /** @@ -188,6 +190,7 @@ MethodType newType = newTarget.type(); // null check! if (!newType.equals(oldType)) throw wrongTargetType(newTarget, oldType); + newTarget.maybeCompileToBytecode(); } private static WrongMethodTypeException wrongTargetType(MethodHandle target, MethodType type) { diff --git a/src/share/classes/java/lang/invoke/LambdaForm.java b/src/share/classes/java/lang/invoke/LambdaForm.java --- a/src/share/classes/java/lang/invoke/LambdaForm.java +++ b/src/share/classes/java/lang/invoke/LambdaForm.java @@ -607,10 +607,17 @@ if (TRACE_INTERPRETER) traceInterpreter("compileToBytecode", this); isCompiled = true; - return vmentry; } catch (Error | Exception ex) { throw newInternalError(this.toString(), ex); } + // Also compile functions used inside: + for (Name n : names) { + if (n.isParam()) continue; + MethodHandle fn = n.function.resolvedHandle; + if (fn != null) + fn.form.compileToBytecode(); + } + return vmentry; } private static void computeInitialPreparedForms() { @@ -719,11 +726,20 @@ } /** If the invocation count hits the threshold we spin bytecodes and call that subsequently. */ - private static final int COMPILE_THRESHOLD; + static final int COMPILE_THRESHOLD; static { COMPILE_THRESHOLD = Math.max(-1, MethodHandleStatics.COMPILE_THRESHOLD); } private int invocationCounter = 0; + int getInvocationsRemaining() { + return Math.max(0, COMPILE_THRESHOLD - invocationCounter); + } + void setInvocationsRemaining(int n) { + if (invocationCounter >= COMPILE_THRESHOLD) return; + if (n < 0) n = 0; + if (n > COMPILE_THRESHOLD) n = COMPILE_THRESHOLD; + invocationCounter = Math.max(invocationCounter, COMPILE_THRESHOLD - n); + } @Hidden @DontInline diff --git a/src/share/classes/java/lang/invoke/MethodHandle.java b/src/share/classes/java/lang/invoke/MethodHandle.java --- a/src/share/classes/java/lang/invoke/MethodHandle.java +++ b/src/share/classes/java/lang/invoke/MethodHandle.java @@ -1413,6 +1413,15 @@ form.compileToBytecode(); } + /*non-public*/ + void maybeCompileToBytecode() { + final int NEW_THRESH = Math.max(1, LambdaForm.COMPILE_THRESHOLD / 10); + if (form.getInvocationsRemaining() < NEW_THRESH) + compileToBytecode(); + else + form.setInvocationsRemaining(NEW_THRESH); + } + /** * Replace the old lambda form of this method handle with a new one. * The new one must be functionally equivalent to the old one. diff --git a/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/src/share/classes/java/lang/invoke/MethodHandleNatives.java --- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -309,6 +309,8 @@ type, staticArguments, caller); + // eagerly generate bytecodes for invokedynamic bindings + callSite.getTarget().compileToBytecode(); if (callSite instanceof ConstantCallSite) { appendixResult[0] = callSite.dynamicInvoker(); return Invokers.linkToTargetMethod(type);