summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2009-03-30 08:45:39 +0000
committerIulian Dragos <jaguarul@gmail.com>2009-03-30 08:45:39 +0000
commit532147c333a8dab79fc77c20162a4d752c6f6780 (patch)
treed18c5275381e34655b0dad967f6304ba63c4416e /src/compiler
parent1c72ffaee5e0faeeb6d046216e5e76c86a6a41ff (diff)
downloadscala-532147c333a8dab79fc77c20162a4d752c6f6780.tar.gz
scala-532147c333a8dab79fc77c20162a4d752c6f6780.tar.bz2
scala-532147c333a8dab79fc77c20162a4d752c6f6780.zip
Code to support invoke-dynamic for structural t...
Code to support invoke-dynamic for structural types. Not yet complete, built around the JSR 292 spec of December 2008.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala26
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala7
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala21
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala5
6 files changed, 56 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index 8f8ddec2d9..f13e1cfa21 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -673,7 +673,7 @@ trait ScalacSettings
val stop = PhasesSetting ("-Ystop", "Stop after phase")
val refinementMethodDispatch =
ChoiceSetting ("-Ystruct-dispatch", "Selects dispatch method for structural refinement method calls",
- List("no-cache", "mono-cache", "poly-cache"), "poly-cache") .
+ List("no-cache", "mono-cache", "poly-cache", "invoke-dynamic"), "poly-cache") .
withHelpSyntax("-Ystruct-dispatch:<method>")
val Xwarndeadcode = BooleanSetting ("-Ywarn-dead-code", "Emit warnings for dead code")
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 69f0d1f826..471a7cc6f7 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -846,6 +846,7 @@ abstract class GenICode extends SubComponent {
}
case ApplyDynamic(qual, args) =>
+ ctx.clazz.bootstrapClass = Some("scala.runtime.DynamicDispatch")
val ctx1 = genLoad(qual, ctx, ANY_REF_CLASS)
genLoadArguments(args, tree.symbol.info.paramTypes, ctx1)
ctx1.bb.emit(CALL_METHOD(tree.symbol, InvokeDynamic), tree.pos)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index c2096fe161..8f17c000ee 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -72,7 +72,10 @@ abstract class GenJVM extends SubComponent {
val BoxesRunTime = "scala.runtime.BoxesRunTime"
val StringBuilderType = new JObjectType(StringBuilderClass)
- val toStringType = new JMethodType(JObjectType.JAVA_LANG_STRING, JType.EMPTY_ARRAY)
+ val toStringType = new JMethodType(JObjectType.JAVA_LANG_STRING, JType.EMPTY_ARRAY)
+ val MethodTypeType = new JObjectType("java.dyn.MethodType")
+ val JavaLangClassType = new JObjectType("java.lang.Class")
+ val MethodHandleType = new JObjectType("java.dyn.MethodHandle")
// Scala attributes
val SerializableAttr = definitions.SerializableAttr
@@ -191,7 +194,7 @@ abstract class GenJVM extends SubComponent {
if (jclass.getName.endsWith("$"))
jclass.addAttribute(getMarkerAttr(jclass))
- if (isStaticModule(c.symbol) || serialVUID != None) {
+ if (isStaticModule(c.symbol) || serialVUID != None || clasz.bootstrapClass.isDefined) {
if (isStaticModule(c.symbol))
addModuleInstanceField;
addStaticInit(jclass)
@@ -212,6 +215,7 @@ abstract class GenJVM extends SubComponent {
}
}
+ if (clasz.bootstrapClass.isDefined) jclass.setBootstrapClass(clasz.bootstrapClass.get)
clasz.fields foreach genField
clasz.methods foreach genMethod
@@ -675,9 +679,27 @@ abstract class GenJVM extends SubComponent {
case None => ()
}
+ if (clasz.bootstrapClass.isDefined) emitBootstrapMethodInstall(clinit)
+
clinit.emitRETURN()
}
+ /** Emit code that installs a boostrap method for invoke dynamic. It installs the default
+ * method, found in scala.runtime.DynamicDispatch.
+ */
+ def emitBootstrapMethodInstall(jcode: JExtendedCode) {
+ jcode.emitPUSH(jclass.getType.asInstanceOf[JReferenceType])
+ jcode.emitPUSH(new JObjectType("scala.runtime.DynamicDispatch"))
+ jcode.emitPUSH("bootstrapInvokeDynamic")
+ jcode.emitGETSTATIC("java.dyn.Linkage", "BOOTSTRAP_METHOD_TYPE", MethodTypeType)
+ jcode.emitDUP
+ jcode.emitINVOKESTATIC("scala.Console", "println", new JMethodType(JType.VOID, Array(JObjectType.JAVA_LANG_OBJECT)))
+ jcode.emitINVOKESTATIC("java.dyn.MethodHandles", "findStatic",
+ new JMethodType(MethodHandleType, Array(JavaLangClassType, JObjectType.JAVA_LANG_STRING, MethodTypeType)))
+ jcode.emitINVOKESTATIC("java.dyn.Linkage", "registerBootstrapMethod",
+ new JMethodType(JType.VOID, Array(JavaLangClassType, MethodHandleType)))
+ }
+
/** Add a forwarder for method m */
def addForwarder(jclass: JClass, module: Symbol, m: Symbol) {
import JAccessFlags._
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 0cecbc03c4..6623a41992 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -127,6 +127,13 @@ trait Definitions {
def methodCache_find = getMember(MethodCacheClass, nme.find_)
def methodCache_add = getMember(MethodCacheClass, nme.add_)
lazy val EmptyMethodCacheClass: Symbol = getClass("scala.runtime.EmptyMethodCache")
+
+ // invoke dynamic support
+ lazy val LinkageModule: Symbol = getModule("java.dyn.Linkage")
+ lazy val Linkage_invalidateCallerClass = getMember(LinkageModule, "invalidateCallerClass")
+ lazy val DynamicDispatchClass: Symbol = getModule("scala.runtime.DynamicDispatch")
+ lazy val DynamicDispatch_DontSetTarget: Symbol = getMember(DynamicDispatchClass, "DontSetTarget")
+
lazy val PredefModule: Symbol = getModule("scala.Predef")
def Predef_classOf = getMember(PredefModule, nme.classOf)
def Predef_classOfType(classType: Type): Type =
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index db88df5dc5..23496807d8 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -592,6 +592,25 @@ abstract class CleanUp extends Transform {
)
}
+ def getClass(q: Tree): Tree =
+ Apply(Select(q, nme.getClass_), List())
+
+ if (settings.refinementMethodDispatch.value == "invoke-dynamic") {
+/* val guardCallSite: Tree = {
+ val cachedClass = addStaticVariableToClass("cachedClass", definitions.ClassClass.tpe, EmptyTree)
+ val tmpVar = currentOwner.newVariable(ad.pos, unit.fresh.newName(ad.pos, "x")).setInfo(definitions.AnyRefClass.tpe)
+ atPos(ad.pos)(Block(List(
+ ValDef(tmpVar, transform(qual))),
+ If(Apply(Select(gen.mkAttributedRef(cachedClass), nme.EQ), List(getClass(Ident(tmpVar)))),
+ Block(List(Assign(gen.mkAttributedRef(cachedClass), getClass(Ident(tmpVar)))),
+ copy.ApplyDynamic(ad, Ident(tmpVar), transformTrees(params))),
+ EmptyTree)))
+ }
+ //println(guardCallSite)
+*/
+ localTyper.typed(copy.ApplyDynamic(ad, transform(qual), transformTrees(params)))
+ } else {
+
/* ### BODY OF THE TRANSFORMATION -> remember we're in case ad@ApplyDynamic(qual, params) ### */
/* This creates the tree that does the reflective call (see general comment
@@ -659,7 +678,7 @@ abstract class CleanUp extends Transform {
/* We return the dynamic call tree, after making sure no other
* clean-up transformation are to be applied on it. */
transform(t)
-
+ }
/* ### END OF DYNAMIC APPLY TRANSFORM ### */
/* Some cleanup transformations add members to templates (classes, traits, etc).
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index b14f6724e2..dec6d58b45 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3373,9 +3373,10 @@ trait Typers { self: Analyzer =>
typedApply(fun, args)
case ApplyDynamic(qual, args) =>
+ val reflectiveCalls = !(settings.refinementMethodDispatch.value == "invoke-dynamic")
val qual1 = typed(qual, AnyRefClass.tpe)
- val args1 = List.mapConserve(args)(arg => typed(arg, AnyRefClass.tpe))
- copy.ApplyDynamic(tree, qual1, args1) setType AnyRefClass.tpe
+ val args1 = List.mapConserve(args)(arg => if (reflectiveCalls) typed(arg, AnyRefClass.tpe) else typed(arg))
+ copy.ApplyDynamic(tree, qual1, args1) setType (if (reflectiveCalls) AnyRefClass.tpe else tree.symbol.info.resultType)
case Super(qual, mix) =>
typedSuper(qual, mix)