From da6496142eba5a8a954d48018801fcebfe70990d Mon Sep 17 00:00:00 2001 From: Douglas Q Hawkins Date: Fri, 17 Jul 2026 09:54:59 -0400 Subject: [PATCH] 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 --- .../datadog/trace/api/function/Strategy.java | 38 +++++++++++++++++++ .../trace/api/function/StrategyConsumer.java | 22 +++++++++++ 2 files changed, 60 insertions(+) create mode 100644 internal-api/src/main/java/datadog/trace/api/function/Strategy.java create mode 100644 internal-api/src/main/java/datadog/trace/api/function/StrategyConsumer.java diff --git a/internal-api/src/main/java/datadog/trace/api/function/Strategy.java b/internal-api/src/main/java/datadog/trace/api/function/Strategy.java new file mode 100644 index 00000000000..f7ca5852122 --- /dev/null +++ b/internal-api/src/main/java/datadog/trace/api/function/Strategy.java @@ -0,0 +1,38 @@ +package datadog.trace.api.function; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marks a static-polymorphism strategy — a stateless, concrete-typed policy object the JIT + * can devirtualize and inline, so one shared algorithm specializes to straight-line code per caller + * (see the "static polymorphism" note on {@code FlatHashtable}). + * + *

This is a documentation-and-tooling marker; it changes no behavior. It exists to telegraph the + * pattern to readers and to give a future checker something to verify. The discipline it names is + * not yet enforced — hold to it by hand until the checker lands. + * + *

On a type ({@link ElementType#TYPE}): this type is a strategy. To get the + * specialization a caller must hold it in a {@code static final} field declared with the + * concrete type (not an abstract base or interface), and the consuming method must inline so + * the call site sees the exact type. Keep the methods small so they inline. + * + *

On a parameter ({@link ElementType#PARAMETER}): this parameter is a strategy slot. The + * argument at each call site should be a {@code static final} constant or a non-capturing + * lambda, so it stays a single monomorphic, allocation-free instance. A parameter can carry this + * marker even when its type cannot — e.g. a {@code java.util.function.Function} slot we don't own. + * + *

The failure mode is silent. Held at an abstract/interface type, filled with a capturing + * lambda, or called from a site that doesn't inline, it still compiles and runs correctly — it just + * stays megamorphic and/or allocates, quietly losing the win. Verify the hot ones with {@code + * -XX:+PrintInlining}. + */ +@Documented +@Inherited +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.TYPE, ElementType.PARAMETER}) +public @interface Strategy {} diff --git a/internal-api/src/main/java/datadog/trace/api/function/StrategyConsumer.java b/internal-api/src/main/java/datadog/trace/api/function/StrategyConsumer.java new file mode 100644 index 00000000000..448eba1ea7b --- /dev/null +++ b/internal-api/src/main/java/datadog/trace/api/function/StrategyConsumer.java @@ -0,0 +1,22 @@ +package datadog.trace.api.function; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marks a higher-order method that consumes {@link Strategy} objects — one whose strategy + * parameters only specialize if this method itself inlines, so each call site sees the exact + * strategy type (see {@link Strategy}). Keep it small so it inlines. + * + *

Documentation-and-tooling marker; it changes no behavior. It pairs with {@link Strategy}: a + * strategy type/parameter says "I am a strategy / a strategy slot," while this says "I am the site + * where they must specialize." A future checker can enforce that the arguments filling those slots + * at these call sites are {@code static final} constants or non-capturing lambdas. + */ +@Documented +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.METHOD) +public @interface StrategyConsumer {}