diff options
author | Iulian Dragos <jaguarul@gmail.com> | 2009-09-18 17:11:11 +0000 |
---|---|---|
committer | Iulian Dragos <jaguarul@gmail.com> | 2009-09-18 17:11:11 +0000 |
commit | 03570027fe92307c20584cc8a6c33057a903f7f3 (patch) | |
tree | a33123bfcd749fb803dd5935d0f7a26ae2750063 | |
parent | b4c4f22b783d58e0916bd5c560a9e7246df000c0 (diff) | |
download | scala-03570027fe92307c20584cc8a6c33057a903f7f3.tar.gz scala-03570027fe92307c20584cc8a6c33057a903f7f3.tar.bz2 scala-03570027fe92307c20584cc8a6c33057a903f7f3.zip |
Fixed the crash in the optimizer for nested exc...
Fixed the crash in the optimizer for nested exception handlers that
apear as arguments to methods.
11 files changed, 38 insertions, 43 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala index eb2d4bef10..27c71e60a3 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala @@ -59,8 +59,8 @@ trait BasicBlocks { if (b) setFlag(LOOP_HEADER) else resetFlag(LOOP_HEADER) /** Is this block the start block of an exception handler? */ - def exceptionHandlerHeader = hasFlag(EX_HEADER) - def exceptionHandlerHeader_=(b: Boolean) = + def exceptionHandlerStart = hasFlag(EX_HEADER) + def exceptionHandlerStart_=(b: Boolean) = if (b) setFlag(EX_HEADER) else resetFlag(EX_HEADER) /** Has this basic block been modified since the last call to 'toList'? */ @@ -425,7 +425,7 @@ trait BasicBlocks { private def exceptionalSucc(b: BasicBlock, succs: List[BasicBlock]): List[BasicBlock] = { def findSucc(s: BasicBlock): List[BasicBlock] = { val ss = method.exh flatMap { h => - if (h.covers(s)) List(h.startBlock) else Nil + if (h.covers(s) /*&& mayThrow(h.startBlock.firstInstruction)*/) List(h.startBlock) else Nil } ss ++ (ss flatMap findSucc) } diff --git a/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala b/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala index a0a673439f..8168cc2c6e 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala @@ -30,7 +30,7 @@ trait ExceptionHandlers { self: ICodes => def setStartBlock(b: BasicBlock) = { _startBlock = b; - b.exceptionHandlerHeader = true + b.exceptionHandlerStart = true } def startBlock = _startBlock; diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala index 1bffe56289..07e9f07454 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala @@ -92,6 +92,12 @@ trait Opcodes { self: ICodes => object opcodes { + def mayThrow(i: Instruction): Boolean = i match { + case LOAD_LOCAL(_) | STORE_LOCAL(_) | CONSTANT(_) | THIS(_) | CZJUMP(_, _, _, _) + | DROP(_) | DUP(_) | RETURN(_) | LOAD_EXCEPTION() | JUMP(_) | CJUMP(_, _, _, _) => false + case _ => true + } + /** Loads "this" on top of the stack. * Stack: ... * ->: ...:ref diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala index 205b43eea6..6e7a81ac1e 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala @@ -79,24 +79,8 @@ trait TypeStacks { self: ICodes => (types.length == other.types.length) && List.forall2(types, other.types) ((t1, t2) => t1 <:< t2 || t2 <:< t1) - def mergeWith(that: TypeStack): TypeStack = { - def merge(a: TypeStack, b: TypeStack): TypeStack = { - val lst = List.map2(a.types, b.types) ((k1, k2) => k1 match { - case REFERENCE(cls1) => - val REFERENCE(cls2) = k2 - lub(k1,k2) - case _ => k1 - }) - new TypeStack(lst) - } - - assert(this agreesWith that, - "Incompatible type stacks: " + this + ", " + that) - merge(this, that) - } - /* This method returns a String representation of the stack */ - override def toString() = types.mkString("<", ",", ">") + override def toString() = types.mkString("\n", "\n", "\n") override def equals(other: Any): Boolean = other.isInstanceOf[TypeStack] && diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/CompleteLattice.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/CompleteLattice.scala index d7496f5db4..df4f9d70b1 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CompleteLattice.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CompleteLattice.scala @@ -28,7 +28,7 @@ trait CompleteLattice { } /** Return the least upper bound of <code>a</code> and <code>b</code> */ - def lub2(a: Elem, b: Elem): Elem + def lub2(exceptional: Boolean)(a: Elem, b: Elem): Elem /** Return the top element. */ def top: Elem @@ -37,8 +37,8 @@ trait CompleteLattice { def bottom: Elem /** Compute the least upper bound of a list of elements. */ - def lub(xs: List[Elem]): Elem = try { - if (xs == Nil) bottom else xs reduceLeft lub2 + def lub(xs: List[Elem], exceptional: Boolean): Elem = try { + if (xs == Nil) bottom else xs reduceLeft lub2(exceptional) } catch { case e: LubError => Console.println("Lub on blocks: " + xs) diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala index 7323508367..9ee628ef19 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala @@ -177,14 +177,14 @@ abstract class CopyPropagation { val exceptionHandlerStack = Unknown :: Nil - def lub2(a: Elem, b: Elem): Elem = { + def lub2(exceptional: Boolean)(a: Elem, b: Elem): Elem = { if (a eq bottom) b else if (b eq bottom) a else if (a == b) a else { + //assert(!(a.stack eq exceptionHandlerStack) && !(b.stack eq exceptionHandlerStack)) val resStack = - if (a.stack eq exceptionHandlerStack) a.stack - else if (b.stack eq exceptionHandlerStack) b.stack + if (exceptional) exceptionHandlerStack else { // if (a.stack.length != b.stack.length) // throw new LubError(a, b, "Invalid stacks in states: "); diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/DataFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/DataFlowAnalysis.scala index ff8a1dcdee..09a39f4280 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/DataFlowAnalysis.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/DataFlowAnalysis.scala @@ -70,7 +70,10 @@ trait DataFlowAnalysis[L <: CompleteLattice] { succs foreach { p => if (!worklist.contains(p)) worklist += p; - in(p) = lattice.lub(/*in(p) :: */(p.predecessors map out.apply)) +// if (!p.exceptionHandlerHeader) { +// println("lubbing " + p.predecessors + " outs: " + p.predecessors.map(out.apply).mkString("\n", "\n", "")) + in(p) = lattice.lub(/*in(p) :: */(p.predecessors map out.apply), p.exceptionHandlerStart) +// } } } } @@ -91,7 +94,7 @@ trait DataFlowAnalysis[L <: CompleteLattice] { if (stat) iterations += 1 val point = worklist.iterator.next; worklist -= point - out(point) = lattice.lub(point.successors map in.apply) + out(point) = lattice.lub(point.successors map in.apply, false) // TODO check for exception handlers val input = f(point, out(point)) if ((lattice.bottom == in(point)) || input != in(point)) { diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala index 243585a4b7..46e24c18ec 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala @@ -33,7 +33,7 @@ abstract class Liveness { override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] } - def lub2(a: Elem, b: Elem): Elem = a ++ b + def lub2(exceptional: Boolean)(a: Elem, b: Elem): Elem = a ++ b } final class LivenessAnalysis extends DataFlowAnalysis[livenessLattice.type] { diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/ProgramPoint.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/ProgramPoint.scala index eee4fe1741..1fa1e36799 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/ProgramPoint.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/ProgramPoint.scala @@ -15,4 +15,5 @@ package backend.icode.analysis trait ProgramPoint[a <: ProgramPoint[a]] { def predecessors: List[a] def successors: List[a] + def exceptionHandlerStart: Boolean } 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 ecb89cbe91..65065fe0d1 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala @@ -38,7 +38,7 @@ abstract class ReachingDefinitions { }, Nil) /** The least upper bound is set inclusion for locals, and pairwise set inclusion for stacks. */ - def lub2(a: Elem, b: Elem): Elem = + def lub2(exceptional: Boolean)(a: Elem, b: Elem): Elem = if (bottom == a) b else if (bottom == b) a else { diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala index b6fbef5e97..0dadd8980d 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala @@ -29,7 +29,7 @@ abstract class TypeFlowAnalysis { def top = Object def bottom = All - def lub2(a: Elem, b: Elem) = + def lub2(exceptional: Boolean)(a: Elem, b: Elem) = if (a eq bottom) b else if (b eq bottom) a else icodes.lub(a, b) @@ -46,11 +46,10 @@ abstract class TypeFlowAnalysis { override val bottom = new TypeStack val exceptionHandlerStack: TypeStack = new TypeStack(List(REFERENCE(definitions.AnyRefClass))) - def lub2(s1: TypeStack, s2: TypeStack) = { + def lub2(exceptional: Boolean)(s1: TypeStack, s2: TypeStack) = { if (s1 eq bottom) s2 else if (s2 eq bottom) s1 - else if (s1 eq exceptionHandlerStack) s1 - else if (s2 eq exceptionHandlerStack) s2 + else if ((s1 eq exceptionHandlerStack) || (s2 eq exceptionHandlerStack)) Predef.error("merging with exhan stack") else { // if (s1.length != s2.length) // throw new CheckerError("Incompatible stacks: " + s1 + " and " + s2); @@ -82,7 +81,7 @@ abstract class TypeFlowAnalysis { override val top = new Elem(new VarBinding, typeStackLattice.top) override val bottom = new Elem(new VarBinding, typeStackLattice.bottom) - def lub2(a: Elem, b: Elem) = { + def lub2(exceptional: Boolean)(a: Elem, b: Elem) = { val IState(env1, s1) = a val IState(env2, s2) = b @@ -90,15 +89,17 @@ abstract class TypeFlowAnalysis { for (binding1 <- env1.iterator) { val tp2 = env2(binding1._1) - resultingLocals += ((binding1._1, typeLattice.lub2(binding1._2, tp2))) + resultingLocals += ((binding1._1, typeLattice.lub2(exceptional)(binding1._2, tp2))) } for (binding2 <- env2.iterator if resultingLocals(binding2._1) eq typeLattice.bottom) { val tp1 = env1(binding2._1) - resultingLocals += ((binding2._1, typeLattice.lub2(binding2._2, tp1))) + resultingLocals += ((binding2._1, typeLattice.lub2(exceptional)(binding2._2, tp1))) } - IState(resultingLocals, typeStackLattice.lub2(a.stack, b.stack)) + IState(resultingLocals, + if (exceptional) typeStackLattice.exceptionHandlerStack + else typeStackLattice.lub2(exceptional)(a.stack, b.stack)) } } @@ -375,10 +376,10 @@ abstract class TypeFlowAnalysis { val bindings = out.vars val stack = out.stack -// if (settings.debug.value) { -// Console.println("Stack: " + stack); -// Console.println(i); -// } + if (settings.debug.value) { + Console.println("[before] Stack: " + stack); + Console.println(i); + } i match { case THIS(clasz) => |