diff options
author | Iulian Dragos <jaguarul@gmail.com> | 2008-05-22 17:33:09 +0000 |
---|---|---|
committer | Iulian Dragos <jaguarul@gmail.com> | 2008-05-22 17:33:09 +0000 |
commit | 04185de550741dd13cfb0843af3a132afa9a1c0e (patch) | |
tree | ab7553e03989894811de81ddb6e89d75e0c5d24e | |
parent | 6ec528fcec4fadb188c093cddbd5bda8de7a22d1 (diff) | |
download | scala-04185de550741dd13cfb0843af3a132afa9a1c0e.tar.gz scala-04185de550741dd13cfb0843af3a132afa9a1c0e.tar.bz2 scala-04185de550741dd13cfb0843af3a132afa9a1c0e.zip |
Reorganized BasicBlocks a bit:
- they are now Seq[Instruction]
- all booleans have been packed into an int
- removed non-standard iteration methods, and switched to Seq methods.
9 files changed, 79 insertions, 51 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala index 6aea42cf42..52ebe21a93 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala @@ -20,27 +20,53 @@ trait BasicBlocks { /** This class represents a basic block. Each * basic block contains a list of instructions that are * either executed all, or none. No jumps - * to/from the "middle" of the basic block are allowed. + * to/from the "middle" of the basic block are allowed (modulo exceptions). */ - class BasicBlock (theLabel: Int, val method: IMethod) + class BasicBlock(val label: Int, val method: IMethod) extends AnyRef - with ProgramPoint[BasicBlock] { + with ProgramPoint[BasicBlock] + with Seq[Instruction] { + + import BBFlags._ def code = method.code - /** The label of the block */ - val label = theLabel + /** Flags of this basic block. */ + private var flags: Int = 0 - /** When set, the <code>emit</code> methods will be ignored. */ - var ignore: Boolean = false + /** Does this block have the given flag? */ + def hasFlag(flag: Int): Boolean = (flags & flag) != 0 - var preds: List[BasicBlock] = null + /** Set the given flag. */ + def setFlag(flag: Int): Unit = flags |= flag + def resetFlag(flag: Int) { + flags &= ~flag + } + + /** Is this block closed? */ + def closed: Boolean = hasFlag(CLOSED) + def closed_=(b: Boolean) = if (b) setFlag(CLOSED) else resetFlag(CLOSED) + + /** When set, the <code>emit</code> methods will be ignored. */ + def ignore: Boolean = hasFlag(IGNORING) + def ignore_=(b: Boolean) = if (b) setFlag(IGNORING) else resetFlag(IGNORING) /** Is this block the head of a while? */ - var loopHeader = false + def loopHeader = hasFlag(LOOP_HEADER) + def loopHeader_=(b: Boolean) = + if (b) setFlag(LOOP_HEADER) else resetFlag(LOOP_HEADER) /** Is this block the start block of an exception handler? */ - var exceptionHandlerHeader = false + def exceptionHandlerHeader = hasFlag(EX_HEADER) + def exceptionHandlerHeader_=(b: Boolean) = + if (b) setFlag(EX_HEADER) else resetFlag(EX_HEADER) + + /** Has this basic block been modified since the last call to 'toList'? */ + private def touched = hasFlag(TOUCHED) + private def touched_=(b: Boolean) = if (b) setFlag(TOUCHED) else resetFlag(TOUCHED) + + /** Cached predecessors. */ + var preds: List[BasicBlock] = null /** Local variables that are in scope at entry of this basic block. Used * for debugging information. @@ -54,17 +80,18 @@ trait BasicBlocks { private var _lastInstruction: Instruction = null - private var closed: Boolean = false - private var instrs: Array[Instruction] = _ - private var touched = false - def toList: List[Instruction] = { + override def toList: List[Instruction] = { if (closed && touched) instructionList = List.fromArray(instrs) instructionList } + /** Return an iterator over the instructions in this basic block. */ + def elements: Iterator[Instruction] = + if (closed) instrs.elements else instructionList.elements + /** return the underlying array of instructions */ def getArray: Array[Instruction] = { assert(closed) @@ -95,7 +122,7 @@ trait BasicBlocks { // override def hashCode() = label; /** Apply a function to all the instructions of the block. */ - def traverse(f: Instruction => Unit) = { + override def foreach(f: Instruction => Unit) = { if (!closed) { dump global.abort("Traversing an open block!: " + label) @@ -103,20 +130,9 @@ trait BasicBlocks { instrs foreach f } - def traverseBackwards(f: Instruction => Unit) = { - var i = instrs.length - 1 - while (i >= 0) { - f(instrs(i)) - i -= 1 - } - } - /** The number of instructions in this basic block so far. */ - def size: Int = - if (isClosed) - instrs.length - else - instructionList.length + def length: Int = + if (closed) instrs.length else instructionList.length /** Return the index of the instruction which produced the value * consumed by the given instruction. @@ -138,10 +154,7 @@ trait BasicBlocks { /** Return the n-th instruction. */ def apply(n: Int): Instruction = - if (closed) - instrs(n) - else - instructionList.reverse(n) + if (closed) instrs(n) else instructionList.reverse(n) ///////////////////// Substitutions /////////////////////// @@ -345,7 +358,7 @@ trait BasicBlocks { preds = null } - def isEmpty: Boolean = instructionList.isEmpty + override def isEmpty: Boolean = instructionList.isEmpty /** Enter ignore mode: new 'emit'ted instructions will not be * added to this basic block. It makes the generation of THROW @@ -372,7 +385,7 @@ trait BasicBlocks { instructionList.last /** Convert the list to an array */ - def toInstructionArray(l: List[Instruction]): Array[Instruction] = { + private def toInstructionArray(l: List[Instruction]): Array[Instruction] = { var array = new Array[Instruction](l.length) var i: Int = 0 @@ -380,8 +393,6 @@ trait BasicBlocks { array } - def isClosed = closed - def successors : List[BasicBlock] = if (isEmpty) Nil else { var res = lastInstruction match { case JUMP (whereto) => List(whereto) @@ -391,7 +402,7 @@ trait BasicBlocks { case RETURN(_) => Nil case THROW() => Nil case _ => - if (isClosed) { + if (closed) { dump global.abort("The last instruction is not a control flow instruction: " + lastInstruction) } @@ -442,3 +453,20 @@ trait BasicBlocks { } } + +object BBFlags { + /** This block is a loop header (was translated from a while). */ + final val LOOP_HEADER = 0x00000001 + + /** Ignoring mode: emit instructions are dropped. */ + final val IGNORING = 0x00000002 + + /** This block is the header of an exception handler. */ + final val EX_HEADER = 0x00000004 + + /** This block is closed. No new instructions can be added. */ + final val CLOSED = 0x00000008 + + /** This block has been changed, chached results are recomputed. */ + final val TOUCHED = 0x00000010 +} diff --git a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala index c311be4aad..c42c0536f4 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala @@ -178,7 +178,7 @@ abstract class Checkers { error(" expected: " + k1 + " but " + k2 + " found") } - b traverse (instr => { + for (instr <- b) { def checkStack(len: Int) { if (stack.length < len) @@ -557,7 +557,7 @@ abstract class Checkers { case _ => abort("Unknown instruction: " + instr) } - }); + } stack } @@ -575,11 +575,12 @@ abstract class Checkers { var printed = 0 var buf: List[Instruction] = Nil - basicBlock.traverseBackwards( (i) => + for (i <- basicBlock.reverse) { if (i == instruction || (printed > 0 && printed < 3)) { buf = i :: buf printed += 1 - }); + } + } buf foreach Console.println Console.println("at: " + (buf.head.pos)) } diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 7ae791566b..95c7876408 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -798,7 +798,7 @@ abstract class GenICode extends SubComponent { })), EmptyTree); if (settings.debug.value) log("synchronized block end with block " + ctx1.bb + - " closed=" + ctx1.bb.isClosed); + " closed=" + ctx1.bb.closed); ctx1.exitSynchronized(monitor) } else if (scalaPrimitives.isCoercion(code)) { ctx1 = genLoad(receiver, ctx1, toTypeKind(receiver.tpe)) diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala index 52044e3c63..63fad0b917 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala @@ -196,7 +196,7 @@ abstract class ReachingDefinitions { * value found below the topmost element of the stack. */ def findDefs(bb: BasicBlock, idx: Int, m: Int, depth: Int): List[(BasicBlock, Int)] = if (idx > 0) { - assert(bb.isClosed) + assert(bb.closed) var instrs = bb.getArray var res: List[(BasicBlock, Int)] = Nil var i = idx diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 82631a5c2d..06106c6d03 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -777,7 +777,7 @@ abstract class GenJVM extends SubComponent { var crtPC = 0 varsInBlock.clear - b traverse ( instr => { + for (instr <- b) { class CompilationError(msg: String) extends Error { override def toString: String = { msg + @@ -1133,8 +1133,7 @@ abstract class GenJVM extends SubComponent { lastMappedPC = crtPC lastLineNr = crtLine } - - }); // b.traverse + } // local vars that survived this basic block for (val lv <- varsInBlock) { diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala index 8ed5871a95..3c8000a101 100644 --- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala +++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala @@ -1217,7 +1217,7 @@ abstract class GenMSIL extends SubComponent { var lastLineNr: Int = 0 - b traverse ( instr => { + for (instr <- b) { needAdditionalRet = false @@ -1606,7 +1606,7 @@ abstract class GenMSIL extends SubComponent { () } - }) // end b traverse instr => { .. } + } // end for (instr <- b) { .. } lastBlock = b // this way, saveResult knows lastBlock diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala index 04b23ed493..05f959886d 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala @@ -219,7 +219,7 @@ abstract class DeadCodeElimination extends SubComponent { val compensations: mutable.Map[(BasicBlock, Int), List[Instruction]] = new mutable.HashMap for (bb <- m.code.blocks.toList) { - assert(bb.isClosed, "Open block in computeCompensations") + assert(bb.closed, "Open block in computeCompensations") for ((i, idx) <- bb.toList.zipWithIndex) { if (!useful(bb)(idx)) { for ((consumedType, depth) <- i.consumedTypes.reverse.zipWithIndex) { diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index 84ef98b31e..5f4a444692 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -233,7 +233,7 @@ abstract class Inliners extends SubComponent { // duplicate the other blocks in the callee linearizer.linearize(callee).foreach { bb => var info = a.in(bb); - bb traverse { i => + for (i <- bb) { i match { case RETURN(kind) => kind match { case UNIT => diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index 724049cb3a..f945809e72 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -683,7 +683,7 @@ abstract class ICodeReader extends ClassfileParser { // Console.println("> " + pc + ": " + instr); if (jmpTargets contains pc) { otherBlock = blocks(pc) - if (!bb.isClosed && otherBlock != bb) { + if (!bb.closed && otherBlock != bb) { bb.emit(JUMP(otherBlock)) bb.close // Console.println("\t> closing bb: " + bb) |