This is very similar to a "growable switch" combinator,
which would call the provider for each distinct selector
value.  A key difference is that non-constant values
go through the fallback, where a "growable switch"
doesn't need a fallback, since the provider MH is
always free to just return a standard fallback as
its result (as is the case with your combinator).

I wonder if the concepts can be combined somehow?

Here's a test question:  When the JIT, after heroic
effort, discovers that an argument is constant, can
it run the provider (in the compiler thread???) to
determine a custom handler for the newly discovered
branch of constant code?  The answer is probably,
"sorry, no", although the JIT might set up an uncommon
trap (and/or an execution counter) that can revisit
the question at some point.

Here's a close point of correspondence between the
idea of a growable switch and your combinator:  Both
need a memory.  Both want to remember the appearance
of constants, so a later optimization phase can use the
full historical knowledge.

— John

> On Apr 10, 2019, at 2:47 PM, Remi Forax <> wrote:
> The problem is the following,
> with the java compiler intrinsic of amber, String.format() is optimized using 
> invokedynamic in the case the format (the first argument) is constant (and 
> some other conditions on the format), this is great, perf are like 25x in 
> simple benchmarks, and that all because in a lot of code, the format is not 
> constant for the Java compiler. 
> By example,
>  class Logger {
>    public static void log(String format, String message) {
>      System.err.println(String.format(format, message));
>    }
>  }
>  ...
>  logger.log("%s", "hello");
> The format is not a constant inside Logger::log for the Java compiler but 
> when the code is JITed, due to inlining, logger.log("hello") calls 
> String.format() with a constant.
> I propose a way to fix that, by providing a method handle combiner 
> (guardIfConstant) that detects if an argument is a constant and do something 
> different if it's a constant or not.
> It's a little more complex than that, we don't only want to have a separate 
> path if the argument is a constant, we also want to be able to build a method 
> handle tree depending on the value of that constant.
>  MethodHandle guardIfConstant(int argument, MethodHandle targetProvider, 
> MethodHandle fallback)
> the semantics: if the nth argument is a constant, the target provider is 
> called with that argument and the return value, a method handle, is called 
> with all the arguments, otherwise the fallback is called.
> in term of method type:
>  - the method type of the return value of guardIfConstant is the same as 
> fallback
>  - the method type of targetProvider returns a MethodHandle and takes a 
> single parameter which is the nth parameter type of the fallback method type,
>    the returned method handle as to have the same method type as the fallback.
> Rémi
> _______________________________________________
> mlvm-dev mailing list

mlvm-dev mailing list

Reply via email to