summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2008-05-22 17:33:09 +0000
committerIulian Dragos <jaguarul@gmail.com>2008-05-22 17:33:09 +0000
commit04185de550741dd13cfb0843af3a132afa9a1c0e (patch)
treeab7553e03989894811de81ddb6e89d75e0c5d24e /src/compiler/scala/tools
parent6ec528fcec4fadb188c093cddbd5bda8de7a22d1 (diff)
downloadscala-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.
Diffstat (limited to 'src/compiler/scala/tools')
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala102
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Checkers.scala9
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala5
-rw-r--r--src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala2
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)