diff options
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) => |