Skip to content

Commit da64961

Browse files
dougqhclaude
andcommitted
Add @strategy / @StrategyConsumer marker annotations for static-polymorphism strategies
Marker-only (no enforcement yet): telegraphs the static-polymorphism strategy pattern and gives a future checker targets. @strategy marks strategy types/parameters; @StrategyConsumer marks the higher-order methods that must inline for them to specialize. Contracts live in the javadoc. Applications land in stacked PRs (FlatHashtable first). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 53e0f60 commit da64961

2 files changed

Lines changed: 60 additions & 0 deletions

File tree

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package datadog.trace.api.function;
2+
3+
import java.lang.annotation.Documented;
4+
import java.lang.annotation.ElementType;
5+
import java.lang.annotation.Inherited;
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.RetentionPolicy;
8+
import java.lang.annotation.Target;
9+
10+
/**
11+
* Marks a <b>static-polymorphism strategy</b> — a stateless, concrete-typed policy object the JIT
12+
* can devirtualize and inline, so one shared algorithm specializes to straight-line code per caller
13+
* (see the "static polymorphism" note on {@code FlatHashtable}).
14+
*
15+
* <p>This is a documentation-and-tooling marker; it changes no behavior. It exists to telegraph the
16+
* pattern to readers and to give a future checker something to verify. The discipline it names is
17+
* <b>not yet enforced</b> — hold to it by hand until the checker lands.
18+
*
19+
* <p><b>On a type</b> ({@link ElementType#TYPE}): this type is a strategy. To get the
20+
* specialization a caller must hold it in a {@code static final} field <i>declared with the
21+
* concrete type</i> (not an abstract base or interface), and the consuming method must inline so
22+
* the call site sees the exact type. Keep the methods small so they inline.
23+
*
24+
* <p><b>On a parameter</b> ({@link ElementType#PARAMETER}): this parameter is a strategy slot. The
25+
* argument at each call site should be a {@code static final} constant or a <i>non-capturing</i>
26+
* lambda, so it stays a single monomorphic, allocation-free instance. A parameter can carry this
27+
* marker even when its type cannot — e.g. a {@code java.util.function.Function} slot we don't own.
28+
*
29+
* <p><b>The failure mode is silent.</b> Held at an abstract/interface type, filled with a capturing
30+
* lambda, or called from a site that doesn't inline, it still compiles and runs correctly — it just
31+
* stays megamorphic and/or allocates, quietly losing the win. Verify the hot ones with {@code
32+
* -XX:+PrintInlining}.
33+
*/
34+
@Documented
35+
@Inherited
36+
@Retention(RetentionPolicy.SOURCE)
37+
@Target({ElementType.TYPE, ElementType.PARAMETER})
38+
public @interface Strategy {}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package datadog.trace.api.function;
2+
3+
import java.lang.annotation.Documented;
4+
import java.lang.annotation.ElementType;
5+
import java.lang.annotation.Retention;
6+
import java.lang.annotation.RetentionPolicy;
7+
import java.lang.annotation.Target;
8+
9+
/**
10+
* Marks a higher-order method that <b>consumes</b> {@link Strategy} objects — one whose strategy
11+
* parameters only specialize if this method itself inlines, so each call site sees the exact
12+
* strategy type (see {@link Strategy}). Keep it small so it inlines.
13+
*
14+
* <p>Documentation-and-tooling marker; it changes no behavior. It pairs with {@link Strategy}: a
15+
* strategy type/parameter says "I am a strategy / a strategy slot," while this says "I am the site
16+
* where they must specialize." A future checker can enforce that the arguments filling those slots
17+
* at these call sites are {@code static final} constants or non-capturing lambdas.
18+
*/
19+
@Documented
20+
@Retention(RetentionPolicy.SOURCE)
21+
@Target(ElementType.METHOD)
22+
public @interface StrategyConsumer {}

0 commit comments

Comments
 (0)