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 <fo...@univ-mlv.fr> 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@openjdk.java.net > https://mail.openjdk.java.net/mailman/listinfo/mlvm-dev _______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net https://mail.openjdk.java.net/mailman/listinfo/mlvm-dev