summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2016-06-06 14:24:38 +1000
committerAdriaan Moors <adriaan.moors@typesafe.com>2016-06-28 09:18:34 -0700
commit7d51b3fd1569917cb804363bd418466a306f5c89 (patch)
treeede84e6a0dda8750276d7c0986ffc6d15c9fb1dc /src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala
parent91b066aac5edf53ca18603f8486eb255514b3118 (diff)
downloadscala-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.scala28
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)