Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Various cleanups in the backend.

all.clean test-opt: all pass.
  • Loading branch information...
commit 0735fd9c94af1a5e8d9ffd37d1b8abfaca191aa6 1 parent 0b22588
Paul Phillips paulp authored
12 src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -59,6 +59,11 @@ trait Trees extends reflect.generic.Trees { self: SymbolTable =>
59 59
60 60 /** Apply `f' to each subtree */
61 61 def foreach(f: Tree => Unit) { new ForeachTreeTraverser(f).traverse(tree) }
  62 +
  63 + /** If 'pf' is defined for a given subtree, call super.traverse(pf(tree)),
  64 + * otherwise super.traverse(tree).
  65 + */
  66 + def foreachWithHook(pf: PartialFunction[Tree, Tree]) { new ForeachWithHookTreeTraverser(pf).traverse(tree) }
62 67
63 68 /** Find all subtrees matching predicate `p' */
64 69 def filter(f: Tree => Boolean): List[Tree] = {
@@ -1003,6 +1008,13 @@ trait Trees extends reflect.generic.Trees { self: SymbolTable =>
1003 1008 posAssigner.traverse(tree)
1004 1009 tree
1005 1010 }
  1011 +
  1012 + class ForeachWithHookTreeTraverser(pf: PartialFunction[Tree, Tree]) extends Traverser {
  1013 + override def traverse(tree: Tree) {
  1014 + val t = if (pf isDefinedAt tree) pf(tree) else tree
  1015 + super.traverse(t)
  1016 + }
  1017 + }
1006 1018
1007 1019 class ForeachTreeTraverser(f: Tree => Unit) extends Traverser {
1008 1020 override def traverse(t: Tree) {
221 src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
@@ -8,11 +8,9 @@ package scala.tools.nsc
8 8 package backend
9 9 package icode
10 10
11   -//import scala.tools.nsc.ast._
12   -import scala.collection.mutable.{Map, Set}
13   -import scala.collection.mutable.LinkedHashSet
14   -import scala.tools.nsc.util.{Position,NoPosition}
15   -import scala.tools.nsc.backend.icode.analysis.ProgramPoint
  11 +import scala.collection.{ mutable, immutable }
  12 +import util.{ Position, NoPosition }
  13 +import backend.icode.analysis.ProgramPoint
16 14
17 15 trait BasicBlocks {
18 16 self: ICodes =>
@@ -79,7 +77,7 @@ trait BasicBlocks {
79 77 /** Local variables that are in scope at entry of this basic block. Used
80 78 * for debugging information.
81 79 */
82   - var varsInScope: Set[Local] = new LinkedHashSet()
  80 + var varsInScope: mutable.Set[Local] = new mutable.LinkedHashSet()
83 81
84 82 /** ICode instructions, used as temporary storage while emitting code.
85 83 * Once closed is called, only the `instrs' array should be used.
@@ -90,11 +88,8 @@ trait BasicBlocks {
90 88
91 89 private var instrs: Array[Instruction] = _
92 90
93   - override def toList: List[Instruction] = {
94   - if (closed)
95   - instrs.toList
96   - else instructionList
97   - }
  91 + override def toList: List[Instruction] =
  92 + if (closed) instrs.toList else instructionList
98 93
99 94 /** Return an iterator over the instructions in this basic block. */
100 95 def iterator: Iterator[Instruction] =
@@ -108,7 +103,7 @@ trait BasicBlocks {
108 103
109 104 def fromList(is: List[Instruction]) {
110 105 code.touched = true
111   - instrs = toInstructionArray(is)
  106 + instrs = is.toArray
112 107 closed = true
113 108 }
114 109
@@ -117,17 +112,9 @@ trait BasicBlocks {
117 112 */
118 113 def indexOf(inst: Instruction): Int = {
119 114 assert(closed)
120   - var i = 0
121   - while (i < instrs.length) {
122   - if (instrs(i) eq inst) return i
123   - i += 1
124   - }
125   - -1
  115 + instrs indexWhere (_ eq inst)
126 116 }
127 117
128   - /** Compute an hashCode for the block */
129   -// override def hashCode() = label;
130   -
131 118 /** Apply a function to all the instructions of the block. */
132 119 override def foreach[U](f: Instruction => U) = {
133 120 if (!closed) {
@@ -138,26 +125,7 @@ trait BasicBlocks {
138 125 }
139 126
140 127 /** The number of instructions in this basic block so far. */
141   - def length: Int =
142   - if (closed) instrs.length else instructionList.length
143   -
144   - /** Return the index of the instruction which produced the value
145   - * consumed by the given instruction.
146   - */
147   - def findDef(pos: Int): Option[Int] = {
148   - assert(closed)
149   - var i = pos
150   - var d = 0
151   - while (i > 0) {
152   - i -= 1
153   - val prod = instrs(i).produced
154   - if (prod > 0 && d == 0)
155   - return Some(i)
156   - d += (instrs(i).consumed - instrs(i).produced)
157   - }
158   - None
159   - }
160   -
  128 + def length = if (closed) instrs.length else instructionList.length
161 129
162 130 /** Return the n-th instruction. */
163 131 def apply(n: Int): Instruction =
@@ -184,22 +152,18 @@ trait BasicBlocks {
184 152 */
185 153 def replaceInstruction(oldInstr: Instruction, newInstr: Instruction): Boolean = {
186 154 assert(closed, "Instructions can be replaced only after the basic block is closed")
187   -
188   - var i = 0
189   - var changed = false
190   - while (i < instrs.length && !changed) {
191   - if (instrs(i) eq oldInstr) {
192   - newInstr.setPos(oldInstr.pos)
193   - instrs(i) = newInstr
194   - changed = true
  155 +
  156 + indexOf(oldInstr) match {
  157 + case -1 => false
  158 + case idx =>
  159 + newInstr setPos oldInstr.pos
  160 + instrs(idx) = newInstr
195 161 code.touched = true
196   - }
197   - i += 1
  162 + true
198 163 }
199   - changed
200 164 }
201 165
202   - /** Replaces <code>iold</code> with <code>is</code>. It does not update
  166 + /** Replaces <code>oldInstr</code> with <code>is</code>. It does not update
203 167 * the position field in the newly inserted instructions, so it behaves
204 168 * differently than the one-instruction versions of this function.
205 169 *
@@ -207,51 +171,23 @@ trait BasicBlocks {
207 171 * @param is ..
208 172 * @return ..
209 173 */
210   - def replaceInstruction(iold: Instruction, is: List[Instruction]): Boolean = {
  174 + def replaceInstruction(oldInstr: Instruction, is: List[Instruction]): Boolean = {
211 175 assert(closed, "Instructions can be replaced only after the basic block is closed")
212   -
213   - var i = 0
214   - var changed = false
215   -
216   - while (i < instrs.length && (instrs(i) ne iold))
217   - i += 1
218   -
219   - if (i < instrs.length) {
220   - val newInstrs = new Array[Instruction](instrs.length + is.length - 1);
221   - changed = true
222   - code.touched = true
223   -
224   - Array.copy(instrs, 0, newInstrs, 0, i)
225   - var j = i
226   - for (x <- is) {
227   - newInstrs(j) = x
228   - j += 1
229   - }
230   - if (i + 1 < instrs.length)
231   - Array.copy(instrs, i + 1, newInstrs, j, instrs.length - i - 1)
232   - instrs = newInstrs;
  176 +
  177 + indexOf(oldInstr) match {
  178 + case -1 => false
  179 + case idx =>
  180 + instrs = instrs.patch(idx, is, 1)
  181 + code.touched = true
  182 + true
233 183 }
234   -
235   - changed
236 184 }
237 185
238 186 /** Insert instructions in 'is' immediately after index 'idx'. */
239 187 def insertAfter(idx: Int, is: List[Instruction]) {
240 188 assert(closed, "Instructions can be replaced only after the basic block is closed")
241   -
242   - var i = idx + 1
243   - if (i < instrs.length) {
244   - val newInstrs = new Array[Instruction](instrs.length + is.length);
245   - Array.copy(instrs, 0, newInstrs, 0, i)
246   - var j = i
247   - for (x <- is) {
248   - newInstrs(j) = x
249   - j += 1
250   - }
251   - if (i + 1 < instrs.length)
252   - Array.copy(instrs, i + 1, newInstrs, j, instrs.length - i)
253   - instrs = newInstrs;
254   - }
  189 +
  190 + instrs = instrs.patch(idx + 1, is, 0)
255 191 code.touched = true
256 192 }
257 193
@@ -261,18 +197,7 @@ trait BasicBlocks {
261 197 */
262 198 def removeInstructionsAt(positions: Int*) {
263 199 assert(closed)
264   - val removed = positions.toList
265   - val newInstrs = new Array[Instruction](instrs.length - positions.length)
266   - var i = 0
267   - var j = 0
268   - while (i < instrs.length) {
269   - if (!removed.contains(i)) {
270   - newInstrs(j) = instrs(i)
271   - j += 1
272   - }
273   - i += 1
274   - }
275   - instrs = newInstrs
  200 + instrs = instrs.indices.toArray filterNot positions.toSet map instrs
276 201 code.touched = true
277 202 }
278 203
@@ -292,33 +217,14 @@ trait BasicBlocks {
292 217 *
293 218 * @param map ...
294 219 */
295   - def subst(map: Map[Instruction, Instruction]) {
296   - if (!closed) substOnList(map) else {
297   - var i = 0
298   - while (i < instrs.length) {
299   - map get instrs(i) match {
300   - case Some(instr) =>
301   - val changed = replaceInstruction(i, instr)
302   - code.touched |= changed
303   - case None => ()
304   - }
305   - i += 1
  220 + def subst(map: Map[Instruction, Instruction]): Unit =
  221 + if (!closed)
  222 + instructionList = instructionList map (x => map.getOrElse(x, x))
  223 + else
  224 + instrs.zipWithIndex collect {
  225 + case (oldInstr, i) if map contains oldInstr =>
  226 + code.touched |= replaceInstruction(i, map(oldInstr))
306 227 }
307   - }
308   - }
309   -
310   - private def substOnList(map: Map[Instruction, Instruction]) {
311   - def subst(l: List[Instruction]): List[Instruction] = l match {
312   - case Nil => Nil
313   - case x :: xs =>
314   - map.get(x) match {
315   - case Some(newInstr) => newInstr :: subst(xs)
316   - case None => x :: subst(xs)
317   - }
318   - }
319   -
320   - instructionList = subst(instructionList)
321   - }
322 228
323 229 ////////////////////// Emit //////////////////////
324 230
@@ -327,10 +233,8 @@ trait BasicBlocks {
327 233 * using the same source position as the last emitted instruction
328 234 */
329 235 def emit(instr: Instruction) {
330   - if (!instructionList.isEmpty)
331   - emit(instr, instructionList.head.pos)
332   - else
333   - emit(instr, NoPosition)
  236 + val pos = if (instructionList.isEmpty) NoPosition else instructionList.head.pos
  237 + emit(instr, pos)
334 238 }
335 239
336 240 /** Emitting does not set touched to true. During code generation this is a hotspot and
@@ -374,7 +278,7 @@ trait BasicBlocks {
374 278 closed = true
375 279 setFlag(DIRTYSUCCS)
376 280 instructionList = instructionList.reverse
377   - instrs = toInstructionArray(instructionList)
  281 + instrs = instructionList.toArray
378 282 }
379 283
380 284 def open {
@@ -406,34 +310,20 @@ trait BasicBlocks {
406 310
407 311 /** Return the last instruction of this basic block. */
408 312 def lastInstruction =
409   - if (closed)
410   - instrs(instrs.length - 1)
411   - else
412   - instructionList.head
  313 + if (closed) instrs.last
  314 + else instructionList.head
413 315
414 316 def firstInstruction =
415   - if (closed)
416   - instrs(0)
417   - else
418   - instructionList.last
419   -
420   - /** Convert the list to an array */
421   - private def toInstructionArray(l: List[Instruction]): Array[Instruction] = {
422   - var array = new Array[Instruction](l.length)
423   - var i: Int = 0
424   -
425   - l foreach (x => { array(i) = x; i += 1 })
426   - array
427   - }
  317 + if (closed) instrs(0)
  318 + else instructionList.last
428 319
429 320 /** Cached value of successors. Must be recomputed whenver a block in the current method is changed. */
430 321 private var succs: List[BasicBlock] = Nil
431   -
432   - def successors : List[BasicBlock] = {
433   - if (touched) {
434   - resetFlag(DIRTYSUCCS)
435   - succs = if (isEmpty) Nil else {
436   - var res = lastInstruction match {
  322 + private def updateSuccs() {
  323 + resetFlag(DIRTYSUCCS)
  324 + succs =
  325 + if (isEmpty) Nil else {
  326 + val last = lastInstruction match {
437 327 case JUMP(whereto) => List(whereto)
438 328 case CJUMP(success, failure, _, _) => failure :: success :: Nil
439 329 case CZJUMP(success, failure, _, _) => failure :: success :: Nil
@@ -447,15 +337,14 @@ trait BasicBlocks {
447 337 }
448 338 else Nil
449 339 }
450   - method.exh.foreach {
451   - e: ExceptionHandler =>
452   - if (e.covers(this)) res = e.startBlock :: res
453   - }
454   - val res1 = res ++ exceptionalSucc(this, res)
455   - res1
  340 +
  341 + val res = (method.exh.reverse collect { case x if x covers this => x.startBlock }) ++ last
  342 + res ++ exceptionalSucc(this, res)
456 343 }
457   - }
458   -// println("reusing cached successors for " + this + " in method " + method)
  344 + }
  345 +
  346 + def successors : List[BasicBlock] = {
  347 + if (touched) updateSuccs()
459 348 succs
460 349 }
461 350
@@ -496,7 +385,7 @@ trait BasicBlocks {
496 385 def predecessors: List[BasicBlock] = {
497 386 if (hasFlag(DIRTYPREDS)) {
498 387 resetFlag(DIRTYPREDS)
499   - preds = code.blocks.iterator.filter (_.successors.contains(this)).toList
  388 + preds = code.blocks filter (_.successors contains this) toList
500 389 }
501 390 preds
502 391 }
22 src/compiler/scala/tools/nsc/backend/icode/Checkers.scala
@@ -573,24 +573,16 @@ abstract class Checkers {
573 573
574 574 def error(msg: String) {
575 575 Console.println(method.toString() + " in block: " + basicBlock.label)
576   - printLastIntructions
  576 + printLastInstructions
577 577
578 578 Checkers.this.global.error("ICode checker: " + method + ": " + msg)
579 579 }
580 580
581 581 /** Prints the last 4 instructions. */
582   - def printLastIntructions {
583   - var printed = 0
584   - var buf: List[Instruction] = Nil
585   -
586   - for (i <- basicBlock.reverse) {
587   - if (i == instruction || (printed > 0 && printed < 3)) {
588   - buf = i :: buf
589   - printed += 1
590   - }
591   - }
592   - buf foreach Console.println
593   - Console.println("at: " + (buf.head.pos))
  582 + def printLastInstructions {
  583 + val buf = basicBlock.reverse dropWhile (_ != instruction) take 4 reverse;
  584 + buf foreach (Console println _)
  585 + Console.println("at: " + buf.head.pos)
594 586 }
595 587
596 588 def error(msg: String, stack: TypeStack) {
@@ -602,8 +594,6 @@ abstract class Checkers {
602 594 /** Return true if <code>k1</code> is a subtype of any of the following
603 595 * types.
604 596 */
605   - def isOneOf(k1: TypeKind, kinds: TypeKind*) =
606   - kinds.exists( k => k1 <:< k)
607   -
  597 + def isOneOf(k1: TypeKind, kinds: TypeKind*) = kinds exists (k1 <:< _)
608 598 }
609 599 }
196 src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -26,10 +26,10 @@ abstract class GenICode extends SubComponent {
26 26 import icodes._
27 27 import icodes.opcodes._
28 28 import definitions.{
29   - ArrayClass, ObjectClass, ThrowableClass, StringClass, NothingClass, NullClass,
  29 + ArrayClass, ObjectClass, ThrowableClass, StringClass, NothingClass, NullClass, AnyRefClass,
30 30 Object_equals, Object_isInstanceOf, Object_asInstanceOf, ScalaRunTimeModule,
31 31 BoxedNumberClass, BoxedCharacterClass,
32   - getMember
  32 + getMember, getPrimitiveCompanion
33 33 }
34 34 import scalaPrimitives.{
35 35 isArrayOp, isComparisonOp, isLogicalOp,
@@ -727,10 +727,10 @@ abstract class GenICode extends SubComponent {
727 727 } else { // normal method call
728 728 if (settings.debug.value)
729 729 log("Gen CALL_METHOD with sym: " + sym + " isStaticSymbol: " + sym.isStaticMember);
730   - var invokeStyle =
  730 + val invokeStyle =
731 731 if (sym.isStaticMember)
732 732 Static(false)
733   - else if (sym.hasFlag(Flags.PRIVATE) || sym.isClassConstructor)
  733 + else if (sym.isPrivate || sym.isClassConstructor)
734 734 Static(true)
735 735 else
736 736 Dynamic
@@ -987,58 +987,44 @@ abstract class GenICode extends SubComponent {
987 987 * Generate code that loads args into label parameters.
988 988 */
989 989 private def genLoadLabelArguments(args: List[Tree], label: Label, ctx: Context): Context = {
990   - if (settings.debug.value)
  990 + if (settings.debug.value) {
991 991 assert(args.length == label.params.length,
992 992 "Wrong number of arguments in call to label " + label.symbol)
  993 + }
  994 +
993 995 var ctx1 = ctx
994   - var arg = args
995   - var param = label.params
996   - val stores: ListBuffer[Instruction] = new ListBuffer
997 996
998   - // store arguments in reverse order on the stack
999   - while (arg != Nil) {
1000   - arg.head match {
1001   - case This(_) if param.head.name == nme.THIS =>
1002   - //println("skipping trivial argument for " + param.head)
1003   - () // skip trivial arguments
1004   - case Ident(_) if arg.head.symbol == param.head =>
1005   - //println("skipping trivial argument for " + param.head)
1006   - () // skip trivial arguments
1007   - case _ =>
1008   - val Some(l) = ctx.method.lookupLocal(param.head)
1009   - ctx1 = genLoad(arg.head, ctx1, l.kind)
1010   - if (param.head.name == nme.THIS)
1011   - STORE_THIS(toTypeKind(ctx1.clazz.symbol.tpe)).setPos(arg.head.pos) +=: stores
1012   - else {
1013   - STORE_LOCAL(l).setPos(arg.head.pos) +=: stores
1014   - }
1015   - }
1016   - arg = arg.tail
1017   - param = param.tail
  997 + def isTrivial(kv: (Tree, Symbol)) = kv match {
  998 + case (This(_), p) if p.name == nme.THIS => true
  999 + case (arg @ Ident(_), p) if arg.symbol == p => true
  1000 + case _ => false
1018 1001 }
1019   -
1020   - //println("stores: " + stores)
1021   - ctx1.bb.emit(stores)
  1002 +
  1003 + val stores = args zip label.params filterNot isTrivial map {
  1004 + case (arg, param) =>
  1005 + val local = ctx.method.lookupLocal(param).get
  1006 + ctx1 = genLoad(arg, ctx1, local.kind)
  1007 +
  1008 + val store =
  1009 + if (param.name == nme.THIS) STORE_THIS(toTypeKind(ctx1.clazz.symbol.tpe))
  1010 + else STORE_LOCAL(local)
  1011 +
  1012 + store setPos arg.pos
  1013 + }
  1014 +
  1015 + // store arguments in reverse order on the stack
  1016 + ctx1.bb.emit(stores.reverse)
1022 1017 ctx1
1023 1018 }
1024 1019
1025   - private def genLoadArguments(args: List[Tree], tpes: List[Type], ctx: Context): Context = {
1026   - var ctx1 = ctx
1027   - var arg = args
1028   - var tpe = tpes
1029   - while (arg != Nil) {
1030   - ctx1 = genLoad(arg.head, ctx1, toTypeKind(tpe.head))
1031   - arg = arg.tail
1032   - tpe = tpe.tail
  1020 + private def genLoadArguments(args: List[Tree], tpes: List[Type], ctx: Context): Context =
  1021 + (args zip tpes).foldLeft(ctx) {
  1022 + case (res, (arg, tpe)) =>
  1023 + genLoad(arg, res, toTypeKind(tpe))
1033 1024 }
1034   - ctx1
1035   - }
1036 1025
1037 1026 private def genLoadModule(ctx: Context, sym: Symbol, pos: Position) {
1038   - if (definitions.primitiveCompanions(sym))
1039   - ctx.bb.emit(LOAD_MODULE(definitions.getModule("scala.runtime." + sym.name)), pos)
1040   - else
1041   - ctx.bb.emit(LOAD_MODULE(sym), pos)
  1027 + ctx.bb.emit(LOAD_MODULE(getPrimitiveCompanion(sym) getOrElse sym), pos)
1042 1028 }
1043 1029
1044 1030 def genConversion(from: TypeKind, to: TypeKind, ctx: Context, cast: Boolean) = {
@@ -1228,22 +1214,18 @@ abstract class GenICode extends SubComponent {
1228 1214 * TODO: restrict the scanning to smaller subtrees than the whole method.
1229 1215 * It is sufficient to scan the trees of the innermost enclosing block.
1230 1216 */
1231   - private def scanForLabels(tree: Tree, ctx: Context): Unit =
1232   - new Traverser() {
1233   - override def traverse(tree: Tree): Unit = tree match {
1234   -
1235   - case LabelDef(name, params, rhs) =>
1236   - if (!ctx.labels.contains(tree.symbol)) {
1237   - ctx.labels += (tree.symbol -> (new Label(tree.symbol) setParams(params map (_.symbol))));
1238   - ctx.method.addLocals(params map (p => new Local(p.symbol, toTypeKind(p.symbol.info), false)));
1239   - }
1240   - super.traverse(rhs)
  1217 + //
  1218 + private def scanForLabels(tree: Tree, ctx: Context): Unit = tree foreachWithHook {
  1219 + case t @ LabelDef(_, params, rhs) =>
  1220 + ctx.labels.getOrElseUpdate(t.symbol, {
  1221 + val locals = params map (p => new Local(p.symbol, toTypeKind(p.symbol.info), false))
  1222 + ctx.method addLocals locals
  1223 +
  1224 + new Label(t.symbol) setParams (params map (_.symbol))
  1225 + })
  1226 + rhs
  1227 + }
1241 1228
1242   - case _ =>
1243   - super.traverse(tree)
1244   - }
1245   - } traverse(tree);
1246   -
1247 1229 /**
1248 1230 * Generate code for conditional expressions. The two basic blocks
1249 1231 * represent the continuation in case of success/failure of the
@@ -1354,7 +1336,7 @@ abstract class GenICode extends SubComponent {
1354 1336 def getTempLocal: Local = ctx.method.lookupLocal(eqEqTempName) match {
1355 1337 case Some(local) => local
1356 1338 case None =>
1357   - val local = ctx.makeLocal(l.pos, definitions.AnyRefClass.typeConstructor, eqEqTempName.toString)
  1339 + val local = ctx.makeLocal(l.pos, AnyRefClass.typeConstructor, eqEqTempName.toString)
1358 1340 //assert(!l.pos.source.isEmpty, "bad position, unit = "+unit+", tree = "+l+", pos = "+l.pos.source)
1359 1341 // Note - I commented these out because they were crashing the test case in ticket #2426
1360 1342 // (and I have also had to comment them out at various times while working on equality.)
@@ -1486,15 +1468,9 @@ abstract class GenICode extends SubComponent {
1486 1468 }
1487 1469
1488 1470 /** Does this tree have a try-catch block? */
1489   - def mayCleanStack(tree: Tree): Boolean = {
1490   - var hasTry = false
1491   - new Traverser() {
1492   - override def traverse(t: Tree) = t match {
1493   - case Try(_, _, _) => hasTry = true
1494   - case _ => super.traverse(t)
1495   - }
1496   - }.traverse(tree);
1497   - hasTry
  1471 + def mayCleanStack(tree: Tree): Boolean = tree exists {
  1472 + case Try(_, _, _) => true
  1473 + case _ => false
1498 1474 }
1499 1475
1500 1476 /**
@@ -1589,13 +1565,8 @@ abstract class GenICode extends SubComponent {
1589 1565 log("Prune fixpoint reached in " + n + " iterations.");
1590 1566 }
1591 1567
1592   - def getMaxType(ts: List[Type]): TypeKind = {
1593   - def maxType(a: TypeKind, b: TypeKind): TypeKind =
1594   - a maxType b;
1595   -
1596   - val kinds = ts map toTypeKind
1597   - kinds reduceLeft maxType
1598   - }
  1568 + def getMaxType(ts: List[Type]): TypeKind =
  1569 + ts map toTypeKind reduceLeft (_ maxType _)
1599 1570
1600 1571 def isLoopHeaderLabel(name: Name): Boolean =
1601 1572 name.startsWith("while$") || name.startsWith("doWhile$")
@@ -1615,7 +1586,7 @@ abstract class GenICode extends SubComponent {
1615 1586 * All LabelDefs are entered into the context label map, since it makes no sense
1616 1587 * to delay it any more: they will be used at some point.
1617 1588 */
1618   - class DuplicateLabels(boundLabels: collection.Set[Symbol]) extends Transformer {
  1589 + class DuplicateLabels(boundLabels: Set[Symbol]) extends Transformer {
1619 1590 val labels: mutable.Map[Symbol, Symbol] = new HashMap
1620 1591 var method: Symbol = _
1621 1592 var ctx: Context = _
@@ -1627,31 +1598,26 @@ abstract class GenICode extends SubComponent {
1627 1598 }
1628 1599
1629 1600 override def transform(t: Tree): Tree = {
  1601 + val sym = t.symbol
  1602 + def getLabel(pos: Position, name: Name) =
  1603 + labels.getOrElseUpdate(sym,
  1604 + method.newLabel(sym.pos, unit.fresh.newName(pos, name.toString)) setInfo sym.tpe
  1605 + )
  1606 +
1630 1607 t match {
1631   - case t @ Apply(fun, args) if (t.symbol.isLabel && !boundLabels(t.symbol)) =>
1632   - if (!labels.isDefinedAt(t.symbol)) {
1633   - val oldLabel = t.symbol
1634   - val sym = method.newLabel(oldLabel.pos, unit.fresh.newName(oldLabel.pos, oldLabel.name.toString))
1635   - sym.setInfo(oldLabel.tpe)
1636   - labels(oldLabel) = sym
1637   - }
1638   - val tree = Apply(global.gen.mkAttributedRef(labels(t.symbol)), transformTrees(args)).setPos(t.pos)
  1608 + case t @ Apply(_, args) if sym.isLabel && !boundLabels(sym) =>
  1609 + val newSym = getLabel(sym.pos, sym.name)
  1610 + val tree = Apply(global.gen.mkAttributedRef(newSym), transformTrees(args)) setPos t.pos
1639 1611 tree.tpe = t.tpe
1640 1612 tree
1641 1613
1642 1614 case t @ LabelDef(name, params, rhs) =>
1643   - val name1 = unit.fresh.newName(t.pos, name.toString)
1644   - if (!labels.isDefinedAt(t.symbol)) {
1645   - val oldLabel = t.symbol
1646   - val sym = method.newLabel(oldLabel.pos, name1)
1647   - sym.setInfo(oldLabel.tpe)
1648   - labels(oldLabel) = sym
1649   - }
1650   - val tree = treeCopy.LabelDef(t, name1, params, transform(rhs))
1651   - tree.symbol = labels(t.symbol)
  1615 + val newSym = getLabel(t.pos, name)
  1616 + val tree = treeCopy.LabelDef(t, newSym.name, params, transform(rhs))
  1617 + tree.symbol = newSym
1652 1618
1653   - ctx.labels += (tree.symbol -> (new Label(tree.symbol) setParams(params map (_.symbol))));
1654   - ctx.method.addLocals(params map (p => new Local(p.symbol, toTypeKind(p.symbol.info), false)));
  1619 + ctx.labels += (newSym -> (new Label(newSym) setParams (params map (_.symbol))))
  1620 + ctx.method.addLocals(params map (p => new Local(p.symbol, toTypeKind(p.symbol.info), false)))
1655 1621
1656 1622 tree
1657 1623
@@ -1672,7 +1638,7 @@ abstract class GenICode extends SubComponent {
1672 1638 override def equals(other: Any) = f == other;
1673 1639 }
1674 1640
1675   - def duplicateFinalizer(boundLabels: collection.Set[Symbol], targetCtx: Context, finalizer: Tree) = {
  1641 + def duplicateFinalizer(boundLabels: Set[Symbol], targetCtx: Context, finalizer: Tree) = {
1676 1642 (new DuplicateLabels(boundLabels))(targetCtx, finalizer)
1677 1643 }
1678 1644
@@ -1806,10 +1772,9 @@ abstract class GenICode extends SubComponent {
1806 1772 /** Return a new context for a new basic block. */
1807 1773 def newBlock: Context = {
1808 1774 val block = method.code.newBlock
1809   - handlers foreach (h => h addCoveredBlock block)
1810   - currentExceptionHandlers foreach (h => h.addBlock(block))
1811   - block.varsInScope = new HashSet()
1812   - block.varsInScope ++= scope.varsInScope
  1775 + handlers foreach (_ addCoveredBlock block)
  1776 + currentExceptionHandlers foreach (_ addBlock block)
  1777 + block.varsInScope = new HashSet() ++= scope.varsInScope
1813 1778 new Context(this) setBasicBlock block
1814 1779 }
1815 1780
@@ -1854,7 +1819,7 @@ abstract class GenICode extends SubComponent {
1854 1819 * exception handler.
1855 1820 */
1856 1821 def enterHandler(exh: ExceptionHandler): Context = {
1857   - currentExceptionHandlers = exh :: currentExceptionHandlers
  1822 + currentExceptionHandlers ::= exh
1858 1823 val ctx = newBlock
1859 1824 exh.setStartBlock(ctx.bb)
1860 1825 ctx
@@ -1905,7 +1870,7 @@ abstract class GenICode extends SubComponent {
1905 1870 * } ))</code>
1906 1871 */
1907 1872 def Try(body: Context => Context,
1908   - handlers: List[(Symbol, TypeKind, (Context => Context))],
  1873 + handlers: List[(Symbol, TypeKind, Context => Context)],
1909 1874 finalizer: Tree,
1910 1875 tree: Tree) = if (forMSIL) TryMsil(body, handlers, finalizer, tree) else {
1911 1876
@@ -1918,7 +1883,7 @@ abstract class GenICode extends SubComponent {
1918 1883 // we need to save bound labels before any code generation is performed on
1919 1884 // the current context (otherwise, any new labels in the finalizer that need to
1920 1885 // be duplicated would be incorrectly considered bound -- see #2850).
1921   - val boundLabels: collection.Set[Symbol] = Set.empty ++ labels.keySet
  1886 + val boundLabels: Set[Symbol] = Set.empty ++ labels.keySet
1922 1887
1923 1888 if (guardResult) {
1924 1889 tmp = this.makeLocal(tree.pos, tree.tpe, "tmp")
@@ -2086,15 +2051,8 @@ abstract class GenICode extends SubComponent {
2086 2051 * jumps to the given basic block.
2087 2052 */
2088 2053 def patch(code: Code) {
2089   - def substMap: mutable.Map[Instruction, Instruction] = {
2090   - val map = new HashMap[Instruction, Instruction]()
2091   -
2092   - toPatch foreach (i => map += (i -> patch(i)))
2093   - map
2094   - }
2095   -
2096   - val map = substMap
2097   - code.blocks foreach (_.subst(map))
  2054 + val map = toPatch map (i => (i -> patch(i))) toMap;
  2055 + code.blocks foreach (_ subst map)
2098 2056 }
2099 2057
2100 2058 /**
@@ -2177,17 +2135,13 @@ abstract class GenICode extends SubComponent {
2177 2135 class Scope(val outer: Scope) {
2178 2136 val locals: ListBuffer[Local] = new ListBuffer
2179 2137
2180   - def add(l: Local) =
2181   - locals += l
2182   -
2183   - def remove(l: Local) =
2184   - locals -= l
  2138 + def add(l: Local) = locals += l
  2139 + def remove(l: Local) = locals -= l
2185 2140
2186 2141 /** Return all locals that are in scope. */
2187 2142 def varsInScope: Buffer[Local] = outer.varsInScope.clone() ++= locals
2188 2143
2189   - override def toString() =
2190   - outer.toString() + locals.mkString("[", ", ", "]")
  2144 + override def toString() = locals.mkString(outer.toString + "[", ", ", "]")
2191 2145 }
2192 2146
2193 2147 object EmptyScope extends Scope(null) {
121 src/compiler/scala/tools/nsc/backend/icode/Members.scala
@@ -10,11 +10,9 @@ package icode
10 10
11 11 import java.io.PrintWriter
12 12
13   -import scala.collection.mutable.HashMap
14   -import scala.collection.mutable.{Set, HashSet, ListBuffer}
15   -import scala.{Symbol => scala_Symbol}
16   -
17   -import scala.tools.nsc.symtab.Flags
  13 +import scala.collection.{ mutable, immutable }
  14 +import mutable.{ HashMap, ListBuffer }
  15 +import symtab.Flags.{ DEFERRED }
18 16
19 17 trait Members { self: ICodes =>
20 18 import global._
@@ -38,31 +36,32 @@ trait Members { self: ICodes =>
38 36 private var _touched = false
39 37
40 38 def touched = _touched
41   - def touched_=(b: Boolean): Unit = if (b) {
42   - blocks foreach (_.touched = true)
43   - _touched = true
44   - } else
45   - _touched = false
  39 + def touched_=(b: Boolean): Unit = {
  40 + if (b)
  41 + blocks foreach (_.touched = true)
  42 +
  43 + _touched = b
  44 + }
46 45
47 46 // Constructor code
48 47 startBlock = newBlock
49 48
50 49 def removeBlock(b: BasicBlock) {
51 50 if (settings.debug.value) {
52   - assert(blocks.forall(p => !(p.successors.contains(b))),
53   - "Removing block that is still referenced in method code " + b + "preds: " + b.predecessors);
54   - if (b == startBlock)
55   - assert(b.successors.length == 1,
56   - "Removing start block with more than one successor.");
  51 + assert(blocks forall (p => !(p.successors contains b)),
  52 + "Removing block that is still referenced in method code " + b + "preds: " + b.predecessors
  53 + )
  54 + assert(b != startBlock || b.successors.length == 1,
  55 + "Removing start block with more than one successor."
  56 + )
57 57 }
58 58
59 59 if (b == startBlock)
60   - startBlock = b.successors.head;
61   - blocks -= b
  60 + startBlock = b.successors.head
  61 +
  62 + blocks -= b
62 63 assert(!blocks.contains(b))
63   - for (handler <- method.exh if handler.covers(b))
64   - handler.covered -= b
65   -
  64 + method.exh filter (_ covers b) foreach (_.covered -= b)
66 65 touched = true
67 66 }
68 67
@@ -114,9 +113,9 @@ trait Members { self: ICodes =>
114 113 def lookupMethod(s: Name) = methods find (_.symbol.name == s)
115 114
116 115 /* determines whether or not this class contains a static ctor. */
117   - def containsStaticCtor: Boolean = methods.exists(_.isStaticCtor)
  116 + def containsStaticCtor: Boolean = methods exists (_.isStaticCtor)
118 117 /* returns this methods static ctor if it has one. */
119   - def lookupStaticCtor: Option[IMethod] = methods.find(_.isStaticCtor)
  118 + def lookupStaticCtor: Option[IMethod] = methods find (_.isStaticCtor)
120 119 }
121 120
122 121 /** Represent a field in ICode */
@@ -150,72 +149,61 @@ trait Members { self: ICodes =>
150 149 /** method parameters */
151 150 var params: List[Local] = Nil
152 151
  152 + def hasCode = code != null
153 153 def setCode(code: Code): IMethod = {
154 154 this.code = code;
155 155 this
156 156 }
157 157
158 158 def addLocal(l: Local): Local =
159   - locals find (l.==) match {
160   - case Some(loc) => loc
161   - case None =>
162   - locals = l :: locals;
163   - l
  159 + locals find (_ == l) getOrElse {
  160 + locals ::= l
  161 + l
164 162 }
165 163
166   - def addLocals(ls: List[Local]) {
167   - ls foreach addLocal
168   - }
169 164
170   - def addParam(p: Local) {
171   - if (!(params contains p)) {
172   - params = p :: params;
173   - locals = p :: locals;
  165 + def addParam(p: Local): Unit =
  166 + if (params contains p) ()
  167 + else {
  168 + params ::= p
  169 + locals ::= p
174 170 }
175   - }
176   -
177   - def addParams(as: List[Local]) {
178   - as foreach addParam
179   - }
180 171
181   - def lookupLocal(n: Name): Option[Local] =
182   - locals find ((l) => l.sym.name == n);
  172 + def addLocals(ls: List[Local]) = ls foreach addLocal
  173 + def addParams(as: List[Local]) = as foreach addParam
183 174
184   - def lookupLocal(sym: Symbol): Option[Local] =
185   - locals find ((l) => l.sym == sym);
  175 + def lookupLocal(n: Name): Option[Local] = locals find (_.sym.name == n)
  176 + def lookupLocal(sym: Symbol): Option[Local] = locals find (_.sym == sym)
186 177
187   - def addHandler(e: ExceptionHandler) {
188   - exh = e :: exh
189   - }
  178 + def addHandler(e: ExceptionHandler) = exh ::= e
190 179
191 180 /** Is this method deferred ('abstract' in Java sense) */
192   - def isDeferred = (
193   - symbol.hasFlag(Flags.DEFERRED) ||
194   - symbol.owner.hasFlag(Flags.INTERFACE) ||
195   - native
196   - );
  181 + /** XXX How is this distinct from symbol.isDeferred? */
  182 + def isDeferred = (symbol hasFlag DEFERRED) || symbol.owner.isInterface || native
197 183
198 184 def isStatic: Boolean = symbol.isStaticMember
199 185
200 186 /* determines whether or not this method is the class static constructor. */
  187 + /* XXX Why rawname? */
201 188 def isStaticCtor: Boolean = isStatic && symbol.rawname == nme.CONSTRUCTOR
202 189
203 190 override def toString() = symbol.fullName
204 191
205 192 import opcodes._
206   - def checkLocals: Unit = if (code ne null) {
207   - Console.println("[checking locals of " + this + "]")
208   - for (bb <- code.blocks; i <- bb) i match {
209   - case LOAD_LOCAL(l) =>
210   - if (!this.locals.contains(l))
211   - Console.println("Local " + l + " is not declared in " + this)
212   - case STORE_LOCAL(l) =>
213   - if (!this.locals.contains(l))
214   - Console.println("Local " + l + " is not declared in " + this)
215   - case _ => ()
  193 + def checkLocals: Unit = {
  194 + def localsSet = code.blocks.flatten collect {
  195 + case LOAD_LOCAL(l) => l
  196 + case STORE_LOCAL(l) => l
  197 + } toSet
  198 +
  199 + if (code != null) {
  200 + Console.println("[checking locals of " + this + "]")
  201 + locals filterNot localsSet foreach { l =>
  202 + Console.println("Local " + l + " is not declared in " + this)
  203 + }
216 204 }
217 205 }
218   -
  206 +
219 207 /** Merge together blocks that have a single successor which has a
220 208 * single predecessor. Exception handlers are taken into account (they
221 209 * might force to break a block of straight line code like that).
@@ -275,11 +263,10 @@ trait Members { self: ICodes =>
275 263 /** PC-based ranges for this local variable's visibility */
276 264 var ranges: List[(Int, Int)] = Nil
277 265
278   - override def equals(other: Any): Boolean = (
279   - other.isInstanceOf[Local] &&
280   - other.asInstanceOf[Local].sym == this.sym
281   - );
282   -
  266 + override def equals(other: Any): Boolean = other match {
  267 + case x: Local => sym == x.sym
  268 + case _ => false
  269 + }
283 270 override def hashCode = sym.hashCode
284 271
285 272 override def toString(): String = sym.toString()
39 src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
@@ -321,7 +321,7 @@ trait Opcodes { self: ICodes =>
321 321 override def toString(): String =
322 322 "CALL_METHOD " + hostClass.fullName + method.fullName +" ("+style.toString()+")";
323 323
324   - var hostClass: Symbol = method.owner;
  324 + var hostClass: Symbol = method.owner
325 325 def setHostClass(cls: Symbol): this.type = { hostClass = cls; this }
326 326
327 327 /** This is specifically for preserving the target native Array type long
@@ -330,29 +330,27 @@ trait Opcodes { self: ICodes =>
330 330 var targetTypeKind: TypeKind = UNIT // the default should never be used, so UNIT should fail fast.
331 331 def setTargetTypeKind(tk: TypeKind) = targetTypeKind = tk
332 332
333   - override def consumed = method.tpe.paramTypes.length + (
334   - style match {
335   - case Dynamic | InvokeDynamic => 1
336   - case Static(true) => 1
337   - case Static(false) => 0
338   - case SuperCall(_) => 1
339   - }
340   - )
  333 + private def params = method.info.paramTypes
  334 + private def consumesInstance = style match {
  335 + case Static(false) => 0
  336 + case _ => 1
  337 + }
341 338
  339 + override def consumed = params.length + consumesInstance
342 340 override def consumedTypes = {
343   - val args = method.tpe.paramTypes map toTypeKind
344   - style match {
345   - case Dynamic | Static(true) => AnyRefReference :: args
346   - case _ => args
347   - }
  341 + val args = params map toTypeKind
  342 + if (consumesInstance > 0) AnyRefReference :: args
  343 + else args
348 344 }
349   -
350   - override def produced =
351   - if(toTypeKind(method.tpe.resultType) == UNIT)
352   - 0
353   - else if(method.isConstructor)
354   - 0
  345 +
  346 + override def produced =
  347 + if (producedType == UNIT || method.isConstructor) 0
355 348 else 1
  349 +
  350 + private def producedType: TypeKind = toTypeKind(method.info.resultType)
  351 + override def producedTypes =
  352 + if (produced == 0) Nil
  353 + else List(producedType)
356 354
357 355 /** object identity is equality for CALL_METHODs. Needed for
358 356 * being able to store such instructions into maps, when more
@@ -611,7 +609,6 @@ trait Opcodes { self: ICodes =>
611 609
612 610 /** This class represents a method invocation style. */
613 611 sealed abstract class InvokeStyle {
614   -
615 612 /** Is this a dynamic method call? */
616 613 def isDynamic: Boolean = this match {
617 614 case Dynamic => true
13 src/compiler/scala/tools/nsc/backend/icode/Repository.scala
@@ -24,17 +24,13 @@ trait Repository {
24 24 def available(sym: Symbol) = classes.contains(sym) || loaded.contains(sym)
25 25
26 26 /** The icode of the given class, if available */
27   - def icode(sym: Symbol): Option[IClass] =
28   - if (classes.contains(sym)) Some(classes(sym))
29   - else if (loaded.contains(sym)) Some(loaded(sym))
30   - else None
  27 + def icode(sym: Symbol): Option[IClass] = (classes get sym) orElse (loaded get sym)
31 28
32 29 /** The icode of the given class. If not available, it loads
33 30 * its bytecode.
34 31 */
35   - def icode(sym: Symbol, force: Boolean): IClass =
36   - if (available(sym)) icode(sym).get
37   - else {
  32 + def icode(sym: Symbol, force: Boolean): IClass =
  33 + icode(sym) getOrElse {
38 34 log("loading " + sym)
39 35 load(sym)
40 36 assert(available(sym))
@@ -46,7 +42,6 @@ trait Repository {
46 42 val (c1, c2) = icodeReader.readClass(sym)
47 43
48 44 assert(c1.symbol == sym || c2.symbol == sym)
49   - loaded += (c1.symbol -> c1)
50   - loaded += (c2.symbol -> c2)
  45 + loaded += (c1.symbol -> c1, c2.symbol -> c2)
51 46 }
52 47 }
70 src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
@@ -84,30 +84,20 @@ abstract class CopyPropagation {
84 84
85 85 /* Return the value bound to the given local. */
86 86 def getBinding(l: Local): Value = {
87   - var target = l
88   - var stop = false
89   - var value: Value = Deref(LocalVar(target))
90   -
91   - while (bindings.isDefinedAt(LocalVar(target)) && !stop) {
92   -// Console.println("finding binding for " + target)
93   - value = bindings(LocalVar(target))