Daniel Sun created GROOVY-12284:
-----------------------------------
Summary: Specialize indy sameClasses guards for arity 1-4
Key: GROOVY-12284
URL: https://issues.apache.org/jira/browse/GROOVY-12284
Project: Groovy
Issue Type: Improvement
Reporter: Daniel Sun
h3. Problem
When an invokedynamic site is linked with all arguments non-null and at least
one parameter type that is non-final (or a primitive wrapper — GROOVY-11782),
{{Selector}} installs a same-class guard:
{code:java}
SAME_CLASSES
.bindTo(expectedClasses)
.asCollector(Object[].class, n)
.asType(MethodType.methodType(boolean.class, pt));
{code}
{{asCollector}} of an {{Object}} array of length {{n}} allocates a fresh array
on *every later invocation* of that site; the array overload of {{sameClasses}}
then walks it.
That is the hot path for ordinary dynamic Groovy calls of the shapes
{{recv.foo()}}, {{recv.foo(a)}}, {{recv.foo(a, b)}}, {{recv.foo(a, b, c)}} —
arity 1-4 (receiver plus 0-3 arguments). Dynamic indy sites almost always have
{{Object}} parameter types, so this guard is the common case, not a rare
fallback.
(If any argument is {{null}} at link time, {{Selector}} already installs
per-slot {{SAME_CLASS}} / {{IS_NULL}} tests and does not use the collector.)
The classic MOP already specializes this check: {{MetaClassHelper.sameClasses}}
has overloads for 0-4 arguments so the call-site cache does not box arguments
into an array. The indy guard did not.
h3. Goal
Keep the same guard semantics (return {{false}} if any argument is {{null}} or
has a different runtime class) without allocating an {{Object}} array on the
common 1-4 arity shapes.
h3. Approach
||Arity (incl. receiver)||Guard||
|0|constant {{true}}|
|1|existing {{SAME_CLASS}}|
|2|new {{SAME_CLASSES_2}}|
|3|new {{SAME_CLASSES_3}}|
|4|new {{SAME_CLASSES_4}}|
|5 or more|existing {{SAME_CLASSES}} plus {{asCollector}} (unchanged)|
Expected classes are bound with {{bindTo}}. One {{guardWithTest}} at the site,
via a single {{Selector.sameClassesGuard(args, pt)}} helper.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)