diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2016-02-12 11:57:21 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2016-02-12 11:57:21 +1000 |
commit | a80f6a00a8519766599e5ca0db61570b7252b584 (patch) | |
tree | 9f758cc64badd074f526b040c233a01af49b95b3 /test | |
parent | 6d09a1ba5fffadd1d886afb66ab4496291fda3dd (diff) | |
parent | df0d105f90816960b711c35a3289ff460295d1cc (diff) | |
download | scala-a80f6a00a8519766599e5ca0db61570b7252b584.tar.gz scala-a80f6a00a8519766599e5ca0db61570b7252b584.tar.bz2 scala-a80f6a00a8519766599e5ca0db61570b7252b584.zip |
Merge pull request #4896 from retronym/topic/indy-all-the-things
Use invokedynamic for structural calls, symbol literals, lambda ser.
Diffstat (limited to 'test')
-rw-r--r-- | test/files/instrumented/indy-symbol-literal.scala | 19 | ||||
-rw-r--r-- | test/files/run/indy-via-macro-with-dynamic-args/Bootstrap.java | 17 | ||||
-rw-r--r-- | test/files/run/indy-via-macro-with-dynamic-args/Test_2.scala | 6 | ||||
-rw-r--r-- | test/files/run/indy-via-macro-with-dynamic-args/macro_1.scala | 33 | ||||
-rw-r--r-- | test/files/run/indy-via-macro/Bootstrap.java | 16 | ||||
-rw-r--r-- | test/files/run/indy-via-macro/Test_2.scala | 5 | ||||
-rw-r--r-- | test/files/run/indy-via-macro/macro_1.scala | 32 | ||||
-rw-r--r-- | test/files/run/t7974.check | 47 |
8 files changed, 152 insertions, 23 deletions
diff --git a/test/files/instrumented/indy-symbol-literal.scala b/test/files/instrumented/indy-symbol-literal.scala new file mode 100644 index 0000000000..a1c333cf95 --- /dev/null +++ b/test/files/instrumented/indy-symbol-literal.scala @@ -0,0 +1,19 @@ +import scala.tools.partest.instrumented._ +import scala.tools.partest.instrumented.Instrumentation._ + +object Test { + def main(args: Array[String]): Unit = { + 'warmup + startProfiling() + var i = 0; + while (i < 2) { + 'foo.name + i += 1 + } + stopProfiling() + // Only expect a single call to lookup the interned Symbol at each call site the defines + // a single literal. + val Symbol_apply = MethodCallTrace("scala/Symbol$", "apply", "(Ljava/lang/String;)Lscala/Symbol;") + assert(getStatistics.get(Symbol_apply) == Some(1), getStatistics); + } +} diff --git a/test/files/run/indy-via-macro-with-dynamic-args/Bootstrap.java b/test/files/run/indy-via-macro-with-dynamic-args/Bootstrap.java new file mode 100644 index 0000000000..5c9ce01cf4 --- /dev/null +++ b/test/files/run/indy-via-macro-with-dynamic-args/Bootstrap.java @@ -0,0 +1,17 @@ +package test; + +import java.lang.invoke.*; +import java.util.regex.Pattern; + +public final class Bootstrap { + private Bootstrap() { + } + + /** Pre-compile a regex */ + public static CallSite bootstrap(MethodHandles.Lookup lookup, String invokedName, + MethodType invokedType, + String value) throws Throwable { + MethodHandle Pattern_matcher = MethodHandles.lookup().findVirtual(java.util.regex.Pattern.class, "matcher", MethodType.fromMethodDescriptorString("(Ljava/lang/CharSequence;)Ljava/util/regex/Matcher;", lookup.lookupClass().getClassLoader())); + return new ConstantCallSite(Pattern_matcher.bindTo(Pattern.compile(value))); + } +} diff --git a/test/files/run/indy-via-macro-with-dynamic-args/Test_2.scala b/test/files/run/indy-via-macro-with-dynamic-args/Test_2.scala new file mode 100644 index 0000000000..77c2b522c7 --- /dev/null +++ b/test/files/run/indy-via-macro-with-dynamic-args/Test_2.scala @@ -0,0 +1,6 @@ +object Test { + def main(args: Array[String]) { + val s = "foo!bar" + assert(Macro.matcher("foo.bar", s).matches == true) + } +} diff --git a/test/files/run/indy-via-macro-with-dynamic-args/macro_1.scala b/test/files/run/indy-via-macro-with-dynamic-args/macro_1.scala new file mode 100644 index 0000000000..cb8719a235 --- /dev/null +++ b/test/files/run/indy-via-macro-with-dynamic-args/macro_1.scala @@ -0,0 +1,33 @@ +import java.util.regex._ + +import scala.reflect.internal.SymbolTable +import scala.reflect.macros.blackbox._ +import language.experimental.macros + +object Macro { + /** + * Equivalent to Pattern.compile(pat).matcher(text), but caches the compiled regex (using invokedynamic) if + * `pat` is a literal. + */ + def matcher(pat: String, text: CharSequence): Matcher = macro Macro.impl + def impl(c: Context)(pat: c.Tree, text: c.Tree): c.Tree = { + def Indy(bootstrapMethod: c.Symbol, bootstrapArgs: List[c.universe.Literal], dynArgs: List[c.Tree]): c.Tree = { + val symtab = c.universe.asInstanceOf[SymbolTable] + import symtab._ + val paramSym = NoSymbol.newTermSymbol(TermName("x")).setInfo(typeOf[CharSequence]) + val dummySymbol = NoSymbol.newTermSymbol(TermName("matcher")).setInfo(internal.methodType(paramSym :: Nil, typeOf[java.util.regex.Matcher])) + val bootstrapArgTrees: List[Tree] = Literal(Constant(bootstrapMethod)).setType(NoType) :: bootstrapArgs.asInstanceOf[List[Tree]] + val result = ApplyDynamic(Ident(dummySymbol).setType(dummySymbol.info), bootstrapArgTrees ::: dynArgs.asInstanceOf[List[Tree]]) + result.setType(dummySymbol.info.resultType) + result.asInstanceOf[c.Tree] + } + import c.universe._ + pat match { + case l @ Literal(Constant(pat: String)) => + val boostrapSym = typeOf[test.Bootstrap].companion.member(TermName("bootstrap")) + Indy(boostrapSym, l :: Nil, text :: Nil) + case _ => + q"_root_.java.util.regex.Pattern.compile($pat).matcher($text)" + } + } +} diff --git a/test/files/run/indy-via-macro/Bootstrap.java b/test/files/run/indy-via-macro/Bootstrap.java new file mode 100644 index 0000000000..af4f5dfd4f --- /dev/null +++ b/test/files/run/indy-via-macro/Bootstrap.java @@ -0,0 +1,16 @@ +package test; + +import java.lang.invoke.*; +import java.util.regex.Pattern; + +public final class Bootstrap { + private Bootstrap() { + } + + /** Pre-compile a regex */ + public static CallSite bootstrap(MethodHandles.Lookup lookup, String invokedName, + MethodType invokedType, + String value) throws Throwable { + return new ConstantCallSite(MethodHandles.constant(Pattern.class, Pattern.compile(value))); + } +} diff --git a/test/files/run/indy-via-macro/Test_2.scala b/test/files/run/indy-via-macro/Test_2.scala new file mode 100644 index 0000000000..830947a46b --- /dev/null +++ b/test/files/run/indy-via-macro/Test_2.scala @@ -0,0 +1,5 @@ +object Test { + def main(args: Array[String]) { + assert(Macro.compilePattern("foo.bar").matcher("foo!bar").matches) + } +}
\ No newline at end of file diff --git a/test/files/run/indy-via-macro/macro_1.scala b/test/files/run/indy-via-macro/macro_1.scala new file mode 100644 index 0000000000..66e319e262 --- /dev/null +++ b/test/files/run/indy-via-macro/macro_1.scala @@ -0,0 +1,32 @@ +import java.util.regex.Pattern + +import scala.reflect.internal.SymbolTable +import scala.reflect.macros.blackbox._ +import language.experimental.macros + +object Macro { + /** + * Equivalent to Pattern.compile(s), but caches the compiled regex (using invokedynamic) if + * `s` is a literal. + */ + def compilePattern(s: String): Pattern = macro Macro.impl + def impl(c: Context)(s: c.Tree): c.Tree = { + def Indy(bootstrapMethod: c.Symbol, bootstrapArgs: List[c.universe.Literal]): c.Tree = { + val symtab = c.universe.asInstanceOf[SymbolTable] + import symtab._ + val dummySymbol = NoSymbol.newTermSymbol(TermName("compile")).setInfo(NullaryMethodType(typeOf[Pattern])) + val args: List[Tree] = Literal(Constant(bootstrapMethod)).setType(NoType) :: bootstrapArgs.asInstanceOf[List[Tree]] + val result = ApplyDynamic(Ident(dummySymbol).setType(dummySymbol.info), args) + result.setType(dummySymbol.info.resultType) + result.asInstanceOf[c.Tree] + } + import c.universe._ + s match { + case l @ Literal(Constant(s: String)) => + val boostrapSym = typeOf[test.Bootstrap].companion.member(TermName("bootstrap")) + Indy(boostrapSym, l :: Nil) + case _ => + q"_root_.java.util.regex.Pattern.compile($s)" + } + } +} diff --git a/test/files/run/t7974.check b/test/files/run/t7974.check index 4eae5eb152..f649161ae9 100644 --- a/test/files/run/t7974.check +++ b/test/files/run/t7974.check @@ -1,26 +1,12 @@ - // access flags 0x9 - public static <clinit>()V - GETSTATIC scala/Symbol$.MODULE$ : Lscala/Symbol$; - LDC "Symbolic1" - INVOKEVIRTUAL scala/Symbol$.apply (Ljava/lang/String;)Lscala/Symbol; - PUTSTATIC Symbols.symbol$1 : Lscala/Symbol; - GETSTATIC scala/Symbol$.MODULE$ : Lscala/Symbol$; - LDC "Symbolic2" - INVOKEVIRTUAL scala/Symbol$.apply (Ljava/lang/String;)Lscala/Symbol; - PUTSTATIC Symbols.symbol$2 : Lscala/Symbol; - GETSTATIC scala/Symbol$.MODULE$ : Lscala/Symbol$; - LDC "Symbolic3" - INVOKEVIRTUAL scala/Symbol$.apply (Ljava/lang/String;)Lscala/Symbol; - PUTSTATIC Symbols.symbol$3 : Lscala/Symbol; - RETURN - MAXSTACK = 2 - MAXLOCALS = 0 - - // access flags 0x1 public someSymbol1()Lscala/Symbol; - GETSTATIC Symbols.symbol$1 : Lscala/Symbol; + INVOKEDYNAMIC apply()Lscala/Symbol; [ + // handle kind 0x6 : INVOKESTATIC + scala/runtime/SymbolLiteral.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;)Ljava/lang/invoke/CallSite; + // arguments: + "Symbolic1" + ] ARETURN MAXSTACK = 1 MAXLOCALS = 1 @@ -28,7 +14,12 @@ // access flags 0x1 public someSymbol2()Lscala/Symbol; - GETSTATIC Symbols.symbol$2 : Lscala/Symbol; + INVOKEDYNAMIC apply()Lscala/Symbol; [ + // handle kind 0x6 : INVOKESTATIC + scala/runtime/SymbolLiteral.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;)Ljava/lang/invoke/CallSite; + // arguments: + "Symbolic2" + ] ARETURN MAXSTACK = 1 MAXLOCALS = 1 @@ -36,7 +27,12 @@ // access flags 0x1 public sameSymbol1()Lscala/Symbol; - GETSTATIC Symbols.symbol$1 : Lscala/Symbol; + INVOKEDYNAMIC apply()Lscala/Symbol; [ + // handle kind 0x6 : INVOKESTATIC + scala/runtime/SymbolLiteral.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;)Ljava/lang/invoke/CallSite; + // arguments: + "Symbolic1" + ] ARETURN MAXSTACK = 1 MAXLOCALS = 1 @@ -56,7 +52,12 @@ ALOAD 0 INVOKESPECIAL java/lang/Object.<init> ()V ALOAD 0 - GETSTATIC Symbols.symbol$3 : Lscala/Symbol; + INVOKEDYNAMIC apply()Lscala/Symbol; [ + // handle kind 0x6 : INVOKESTATIC + scala/runtime/SymbolLiteral.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;)Ljava/lang/invoke/CallSite; + // arguments: + "Symbolic3" + ] PUTFIELD Symbols.someSymbol3 : Lscala/Symbol; RETURN MAXSTACK = 2 |