66 MethodHandle worker = spt.guardWithTest(worker1, worker2);
67 assertEquals("method", (String) worker.invokeExact("met", "hod"));
68 SwitchPoint.invalidateAll(new SwitchPoint[]{ spt });
69 assert(spt.hasBeenInvalidated());
70 assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
71 * }</pre></blockquote>
72 * <p style="font-size:smaller;">
73 * <em>Discussion:</em>
74 * Switch points are useful without subclassing. They may also be subclassed.
75 * This may be useful in order to associate application-specific invalidation logic
76 * with the switch point.
77 * Notice that there is no permanent association between a switch point and
78 * the method handles it produces and consumes.
79 * The garbage collector may collect method handles produced or consumed
80 * by a switch point independently of the lifetime of the switch point itself.
81 * <p style="font-size:smaller;">
82 * <em>Implementation Note:</em>
83 * A switch point behaves as if implemented on top of {@link MutableCallSite},
84 * approximately as follows:
85 * <blockquote><pre>{@code
86 public class SwitchPoint {
87 private static final MethodHandle
88 K_true = MethodHandles.constant(boolean.class, true),
89 K_false = MethodHandles.constant(boolean.class, false);
90 private final MutableCallSite mcs;
91 private final MethodHandle mcsInvoker;
92 public SwitchPoint() {
93 this.mcs = new MutableCallSite(K_true);
94 this.mcsInvoker = mcs.dynamicInvoker();
95 }
96 public MethodHandle guardWithTest(
97 MethodHandle target, MethodHandle fallback) {
98 // Note: mcsInvoker is of type ()boolean.
99 // Target and fallback may take any arguments, but must have the same type.
100 return MethodHandles.guardWithTest(this.mcsInvoker, target, fallback);
101 }
102 public static void invalidateAll(SwitchPoint[] spts) {
103 List<MutableCallSite> mcss = new ArrayList<>();
104 for (SwitchPoint spt : spts) mcss.add(spt.mcs);
105 for (MutableCallSite mcs : mcss) mcs.setTarget(K_false);
106 MutableCallSite.syncAll(mcss.toArray(new MutableCallSite[0]));
107 }
108 }
109 * }</pre></blockquote>
110 * @author Remi Forax, JSR 292 EG
111 */
112 public class SwitchPoint {
113 private static final MethodHandle
114 K_true = MethodHandles.constant(boolean.class, true),
115 K_false = MethodHandles.constant(boolean.class, false);
116
117 private final MutableCallSite mcs;
118 private final MethodHandle mcsInvoker;
119
120 /**
121 * Creates a new switch point.
122 */
123 public SwitchPoint() {
124 this.mcs = new MutableCallSite(K_true);
125 this.mcsInvoker = mcs.dynamicInvoker();
126 }
127
128 /**
|
66 MethodHandle worker = spt.guardWithTest(worker1, worker2);
67 assertEquals("method", (String) worker.invokeExact("met", "hod"));
68 SwitchPoint.invalidateAll(new SwitchPoint[]{ spt });
69 assert(spt.hasBeenInvalidated());
70 assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
71 * }</pre></blockquote>
72 * <p style="font-size:smaller;">
73 * <em>Discussion:</em>
74 * Switch points are useful without subclassing. They may also be subclassed.
75 * This may be useful in order to associate application-specific invalidation logic
76 * with the switch point.
77 * Notice that there is no permanent association between a switch point and
78 * the method handles it produces and consumes.
79 * The garbage collector may collect method handles produced or consumed
80 * by a switch point independently of the lifetime of the switch point itself.
81 * <p style="font-size:smaller;">
82 * <em>Implementation Note:</em>
83 * A switch point behaves as if implemented on top of {@link MutableCallSite},
84 * approximately as follows:
85 * <blockquote><pre>{@code
86 * public class SwitchPoint {
87 * private static final MethodHandle
88 * K_true = MethodHandles.constant(boolean.class, true),
89 * K_false = MethodHandles.constant(boolean.class, false);
90 * private final MutableCallSite mcs;
91 * private final MethodHandle mcsInvoker;
92 * public SwitchPoint() {
93 * this.mcs = new MutableCallSite(K_true);
94 * this.mcsInvoker = mcs.dynamicInvoker();
95 * }
96 * public MethodHandle guardWithTest(
97 * MethodHandle target, MethodHandle fallback) {
98 * // Note: mcsInvoker is of type ()boolean.
99 * // Target and fallback may take any arguments, but must have the same type.
100 * return MethodHandles.guardWithTest(this.mcsInvoker, target, fallback);
101 * }
102 * public static void invalidateAll(SwitchPoint[] spts) {
103 * List<MutableCallSite> mcss = new ArrayList<>();
104 * for (SwitchPoint spt : spts) mcss.add(spt.mcs);
105 * for (MutableCallSite mcs : mcss) mcs.setTarget(K_false);
106 * MutableCallSite.syncAll(mcss.toArray(new MutableCallSite[0]));
107 * }
108 * }
109 * }</pre></blockquote>
110 * @author Remi Forax, JSR 292 EG
111 */
112 public class SwitchPoint {
113 private static final MethodHandle
114 K_true = MethodHandles.constant(boolean.class, true),
115 K_false = MethodHandles.constant(boolean.class, false);
116
117 private final MutableCallSite mcs;
118 private final MethodHandle mcsInvoker;
119
120 /**
121 * Creates a new switch point.
122 */
123 public SwitchPoint() {
124 this.mcs = new MutableCallSite(K_true);
125 this.mcsInvoker = mcs.dynamicInvoker();
126 }
127
128 /**
|