summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2009-09-18 17:11:11 +0000
committerIulian Dragos <jaguarul@gmail.com>2009-09-18 17:11:11 +0000
commit03570027fe92307c20584cc8a6c33057a903f7f3 (patch)
treea33123bfcd749fb803dd5935d0f7a26ae2750063
parentb4c4f22b783d58e0916bd5c560a9e7246df000c0 (diff)
downloadscala-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.
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala18
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/CompleteLattice.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/DataFlowAnalysis.scala7
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/ProgramPoint.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala25
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) =>