diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2016-06-06 14:24:38 +1000 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2016-06-28 09:18:34 -0700 |
commit | 7d51b3fd1569917cb804363bd418466a306f5c89 (patch) | |
tree | ede84e6a0dda8750276d7c0986ffc6d15c9fb1dc /src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala | |
parent | 91b066aac5edf53ca18603f8486eb255514b3118 (diff) | |
download | scala-7d51b3fd1569917cb804363bd418466a306f5c89.tar.gz scala-7d51b3fd1569917cb804363bd418466a306f5c89.tar.bz2 scala-7d51b3fd1569917cb804363bd418466a306f5c89.zip |
Emit trait method bodies in statics
And use this as the target of the default methods or
statically resolved super or $init calls.
The call-site change is predicated on `-Yuse-trait-statics`
as a stepping stone for experimentation / bootstrapping.
I have performed this transformation in the backend,
rather than trying to reflect this in the view from
Scala symbols + ASTs.
We also need to add an restriction related to invokespecial to Java
parents: to support a super call to one of these to implement a
super accessor, the interface must be listed as a direct parent
of the class.
The static method names has a trailing $ added to avoid duplicate
name and signature errors in classfiles.
Diffstat (limited to 'src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala index 7b4cfe2a18..9c5a1a9f98 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala @@ -106,6 +106,8 @@ class Inliner[BT <: BTypes](val btypes: BT) { val elided = mutable.Set.empty[InlineRequest] def nonElidedRequests(methodNode: MethodNode): Set[InlineRequest] = requestsByMethod(methodNode) diff elided + def allCallees(r: InlineRequest): Set[MethodNode] = r.post.flatMap(allCallees).toSet + r.callsite.callee.get.callee + /** * Break cycles in the inline request graph by removing callsites. * @@ -114,20 +116,20 @@ class Inliner[BT <: BTypes](val btypes: BT) { */ def breakInlineCycles: List[InlineRequest] = { // is there a path of inline requests from start to goal? - def isReachable(start: MethodNode, goal: MethodNode): Boolean = { - @tailrec def reachableImpl(check: List[MethodNode], visited: Set[MethodNode]): Boolean = check match { - case x :: xs => + def isReachable(start: Set[MethodNode], goal: MethodNode): Boolean = { + @tailrec def reachableImpl(check: Set[MethodNode], visited: Set[MethodNode]): Boolean = { + if (check.isEmpty) false + else { + val x = check.head if (x == goal) true - else if (visited(x)) reachableImpl(xs, visited) + else if (visited(x)) reachableImpl(check - x, visited) else { - val callees = nonElidedRequests(x).map(_.callsite.callee.get.callee) - reachableImpl(xs ::: callees.toList, visited + x) + val callees = nonElidedRequests(x).flatMap(allCallees) + reachableImpl(check - x ++ callees, visited + x) } - - case Nil => - false + } } - reachableImpl(List(start), Set.empty) + reachableImpl(start, Set.empty) } val result = new mutable.ListBuffer[InlineRequest]() @@ -136,7 +138,7 @@ class Inliner[BT <: BTypes](val btypes: BT) { java.util.Arrays.sort(requests, callsiteOrdering) for (r <- requests) { // is there a chain of inlining requests that would inline the callsite method into the callee? - if (isReachable(r.callsite.callee.get.callee, r.callsite.callsiteMethod)) + if (isReachable(allCallees(r), r.callsite.callsiteMethod)) elided += r else result += r @@ -150,8 +152,8 @@ class Inliner[BT <: BTypes](val btypes: BT) { if (requests.isEmpty) Nil else { val (leaves, others) = requests.partition(r => { - val inlineRequestsForCallee = nonElidedRequests(r.callsite.callee.get.callee) - inlineRequestsForCallee.forall(visited) + val inlineRequestsForCallees = allCallees(r).flatMap(nonElidedRequests) + inlineRequestsForCallees.forall(visited) }) assert(leaves.nonEmpty, requests) leaves ::: leavesFirst(others, visited ++ leaves) |