aboutsummaryrefslogtreecommitdiff
path: root/src/jdk/internal/dynalink/ChainedCallSite.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jdk/internal/dynalink/ChainedCallSite.java')
-rw-r--r--src/jdk/internal/dynalink/ChainedCallSite.java74
1 files changed, 56 insertions, 18 deletions
diff --git a/src/jdk/internal/dynalink/ChainedCallSite.java b/src/jdk/internal/dynalink/ChainedCallSite.java
index c2ad4eb2..45f191a0 100644
--- a/src/jdk/internal/dynalink/ChainedCallSite.java
+++ b/src/jdk/internal/dynalink/ChainedCallSite.java
@@ -103,8 +103,27 @@ import jdk.internal.dynalink.support.Lookup;
* handle is always at the start of the chain.
*/
public class ChainedCallSite extends AbstractRelinkableCallSite {
- private static final MethodHandle PRUNE = Lookup.findOwnSpecial(MethodHandles.lookup(), "prune", MethodHandle.class,
- MethodHandle.class);
+ private static final MethodHandle PRUNE_CATCHES =
+ MethodHandles.insertArguments(
+ Lookup.findOwnSpecial(
+ MethodHandles.lookup(),
+ "prune",
+ MethodHandle.class,
+ MethodHandle.class,
+ boolean.class),
+ 2,
+ true);
+
+ private static final MethodHandle PRUNE_SWITCHPOINTS =
+ MethodHandles.insertArguments(
+ Lookup.findOwnSpecial(
+ MethodHandles.lookup(),
+ "prune",
+ MethodHandle.class,
+ MethodHandle.class,
+ boolean.class),
+ 2,
+ false);
private final AtomicReference<LinkedList<GuardedInvocation>> invocations = new AtomicReference<>();
@@ -112,7 +131,7 @@ public class ChainedCallSite extends AbstractRelinkableCallSite {
* Creates a new chained call site.
* @param descriptor the descriptor for the call site.
*/
- public ChainedCallSite(CallSiteDescriptor descriptor) {
+ public ChainedCallSite(final CallSiteDescriptor descriptor) {
super(descriptor);
}
@@ -126,24 +145,26 @@ public class ChainedCallSite extends AbstractRelinkableCallSite {
}
@Override
- public void relink(GuardedInvocation guardedInvocation, MethodHandle fallback) {
- relinkInternal(guardedInvocation, fallback, false);
+ public void relink(final GuardedInvocation guardedInvocation, final MethodHandle fallback) {
+ relinkInternal(guardedInvocation, fallback, false, false);
}
@Override
- public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle fallback) {
- relinkInternal(guardedInvocation, fallback, true);
+ public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle fallback) {
+ relinkInternal(guardedInvocation, fallback, true, false);
}
- private MethodHandle relinkInternal(GuardedInvocation invocation, MethodHandle relink, boolean reset) {
+ private MethodHandle relinkInternal(final GuardedInvocation invocation, final MethodHandle relink, final boolean reset, final boolean removeCatches) {
final LinkedList<GuardedInvocation> currentInvocations = invocations.get();
@SuppressWarnings({ "unchecked", "rawtypes" })
final LinkedList<GuardedInvocation> newInvocations =
currentInvocations == null || reset ? new LinkedList<>() : (LinkedList)currentInvocations.clone();
- // First, prune the chain of invalidated switchpoints.
- for(Iterator<GuardedInvocation> it = newInvocations.iterator(); it.hasNext();) {
- if(it.next().hasBeenInvalidated()) {
+ // First, prune the chain of invalidated switchpoints, we always do this
+ // We also remove any catches if the remove catches flag is set
+ for(final Iterator<GuardedInvocation> it = newInvocations.iterator(); it.hasNext();) {
+ final GuardedInvocation inv = it.next();
+ if(inv.hasBeenInvalidated() || (removeCatches && inv.getException() != null)) {
it.remove();
}
}
@@ -160,12 +181,13 @@ public class ChainedCallSite extends AbstractRelinkableCallSite {
// prune-and-invoke is used as the fallback for invalidated switchpoints. If a switchpoint gets invalidated, we
// rebuild the chain and get rid of all invalidated switchpoints instead of letting them linger.
- final MethodHandle pruneAndInvoke = makePruneAndInvokeMethod(relink);
+ final MethodHandle pruneAndInvokeSwitchPoints = makePruneAndInvokeMethod(relink, getPruneSwitchpoints());
+ final MethodHandle pruneAndInvokeCatches = makePruneAndInvokeMethod(relink, getPruneCatches());
// Fold the new chain
MethodHandle target = relink;
- for(GuardedInvocation inv: newInvocations) {
- target = inv.compose(pruneAndInvoke, target);
+ for(final GuardedInvocation inv: newInvocations) {
+ target = inv.compose(target, pruneAndInvokeSwitchPoints, pruneAndInvokeCatches);
}
// If nobody else updated the call site while we were rebuilding the chain, set the target to our chain. In case
@@ -178,14 +200,30 @@ public class ChainedCallSite extends AbstractRelinkableCallSite {
}
/**
+ * Get the switchpoint pruning function for a chained call site
+ * @return function that removes invalidated switchpoints tied to callsite guard chain and relinks
+ */
+ protected MethodHandle getPruneSwitchpoints() {
+ return PRUNE_SWITCHPOINTS;
+ }
+
+ /**
+ * Get the catch pruning function for a chained call site
+ * @return function that removes all catches tied to callsite guard chain and relinks
+ */
+ protected MethodHandle getPruneCatches() {
+ return PRUNE_CATCHES;
+ }
+
+ /**
* Creates a method that rebuilds our call chain, pruning it of any invalidated switchpoints, and then invokes that
* chain.
* @param relink the ultimate fallback for the chain (the {@code DynamicLinker}'s relink).
* @return a method handle for prune-and-invoke
*/
- private MethodHandle makePruneAndInvokeMethod(MethodHandle relink) {
+ private MethodHandle makePruneAndInvokeMethod(final MethodHandle relink, final MethodHandle prune) {
// Bind prune to (this, relink)
- final MethodHandle boundPrune = MethodHandles.insertArguments(PRUNE, 0, this, relink);
+ final MethodHandle boundPrune = MethodHandles.insertArguments(prune, 0, this, relink);
// Make it ignore all incoming arguments
final MethodHandle ignoreArgsPrune = MethodHandles.dropArguments(boundPrune, 0, type().parameterList());
// Invoke prune, then invoke the call site target with original arguments
@@ -193,7 +231,7 @@ public class ChainedCallSite extends AbstractRelinkableCallSite {
}
@SuppressWarnings("unused")
- private MethodHandle prune(MethodHandle relink) {
- return relinkInternal(null, relink, false);
+ private MethodHandle prune(final MethodHandle relink, final boolean catches) {
+ return relinkInternal(null, relink, false, catches);
}
}