Permalink
Browse files

[recommit] Backend optimization: Inline excepti...

[recommit] Backend optimization: Inline exception handlers. Review by
dragos.
  • Loading branch information...
VladUreche committed Aug 19, 2011
1 parent 64a2e30 commit 63f072fe9be341f2acac5609d7657bf2b444ceb6
@@ -29,7 +29,7 @@ import transform._
import backend.icode.{ ICodes, GenICode, ICodeCheckers }
import backend.{ ScalaPrimitives, Platform, MSILPlatform, JavaPlatform }
import backend.jvm.GenJVM
-import backend.opt.{ Inliners, ClosureElimination, DeadCodeElimination }
+import backend.opt.{ Inliners, InlineExceptionHandlers, ClosureElimination, DeadCodeElimination }
import backend.icode.analysis._
class Global(var currentSettings: Settings, var reporter: Reporter) extends SymbolTable
@@ -500,10 +500,17 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
val runsRightAfter = None
} with Inliners
+ // phaseName = "inlineExceptionHandlers"
+ object inlineExceptionHandlers extends {
+ val global: Global.this.type = Global.this
+ val runsAfter = List[String]("inliner")
+ val runsRightAfter = None
+ } with InlineExceptionHandlers
+
// phaseName = "closelim"
object closureElimination extends {
val global: Global.this.type = Global.this
- val runsAfter = List[String]("inliner")
+ val runsAfter = List[String]("inlineExceptionHandlers")
val runsRightAfter = None
} with ClosureElimination
@@ -601,6 +608,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
cleanup -> "platform-specific cleanups, generate reflective calls",
genicode -> "generate portable intermediate code",
inliner -> "optimization: do inlining",
+ inlineExceptionHandlers -> "optimization: inline exception handlers",
closureElimination -> "optimization: eliminate uncalled closures",
deadCode -> "optimization: eliminate dead code",
terminal -> "The last phase in the compiler chain"
@@ -217,7 +217,13 @@ abstract class ICodeCheckers {
throw new CheckerException(incompatibleString)
}
else {
- val newStack = new TypeStack((s1.types, s2.types).zipped map lub)
+ val newStack: TypeStack = try {
+ new TypeStack((s1.types, s2.types).zipped map lub)
+ } catch {
+ case t: Exception =>
+ checkerDebug(t.toString + ": " + s1.types.toString + " vs " + s2.types.toString)
+ new TypeStack(s1.types)
+ }
if (newStack.isEmpty || s1.types == s2.types) () // not interesting to report
else checkerDebug("Checker created new stack:\n (%s, %s) => %s".format(s1, s2, newStack))
@@ -705,7 +711,7 @@ abstract class ICodeCheckers {
//////////////// Error reporting /////////////////////////
def icodeError(msg: String) {
- ICodeCheckers.this.global.globalError(
+ ICodeCheckers.this.global.warning(
"!! ICode checker fatality in " + method +
"\n at: " + basicBlock.fullString +
"\n error message: " + msg
@@ -535,9 +535,9 @@ abstract class TypeFlowAnalysis {
case SCOPE_ENTER(_) | SCOPE_EXIT(_) =>
()
- case LOAD_EXCEPTION(_) =>
+ case LOAD_EXCEPTION(clasz) =>
stack.pop(stack.length)
- stack.push(typeLattice.top)
+ stack.push(toTypeKind(clasz.tpe))
case _ =>
dumpClassesAndAbort("Unknown instruction: " + i)
@@ -11,6 +11,7 @@ import java.io.{ DataOutputStream, OutputStream }
import java.nio.ByteBuffer
import scala.collection.{ mutable, immutable }
import scala.reflect.internal.pickling.{ PickleFormat, PickleBuffer }
+import scala.tools.reflect.SigParser
import scala.tools.nsc.util.ScalaClassLoader
import scala.tools.nsc.symtab._
import scala.reflect.internal.ClassfileConstants._
@@ -421,15 +422,11 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
c.cunit.source.toString)
var fieldList = List[String]()
- for {
- f <- clasz.fields
- if f.symbol.hasGetter
- g = f.symbol.getter(c.symbol)
- s = f.symbol.setter(c.symbol)
- if g.isPublic && !(f.symbol.name startsWith "$") // inserting $outer breaks the bean
- } {
+ for (f <- clasz.fields if f.symbol.hasGetter;
+ val g = f.symbol.getter(c.symbol);
+ val s = f.symbol.setter(c.symbol);
+ if g.isPublic && !(f.symbol.name startsWith "$")) // inserting $outer breaks the bean
fieldList = javaName(f.symbol) :: javaName(g) :: (if (s != NoSymbol) javaName(s) else null) :: fieldList
- }
val methodList =
for (m <- clasz.methods
if !m.symbol.isConstructor &&
@@ -606,6 +603,14 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
nannots
}
+ /** Run the signature parser to catch bogus signatures.
+ */
+ def isValidSignature(sym: Symbol, sig: String) = (
+ if (sym.isMethod) SigParser verifyMethod sig
+ else if (sym.isTerm) SigParser verifyType sig
+ else SigParser verifyClass sig
+ )
+
// @M don't generate java generics sigs for (members of) implementation
// classes, as they are monomorphic (TODO: ok?)
private def needsGenericSignature(sym: Symbol) = !(
@@ -627,8 +632,12 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
// println("addGenericSignature: "+ (sym.ownerChain map (x => (x.name, x.isImplClass))))
erasure.javaSig(sym, memberTpe) foreach { sig =>
debuglog("sig(" + jmember.getName + ", " + sym + ", " + owner + ") " + sig)
-
- if (settings.Xverify.value && !erasure.isValidSignature(sym, sig)) {
+ /** Since we're using a sun internal class for signature validation,
+ * we have to allow for it not existing or otherwise malfunctioning:
+ * in which case we treat every signature as valid. Medium term we
+ * should certainly write independent signature validation.
+ */
+ if (settings.Xverify.value && SigParser.isParserAvailable && !isValidSignature(sym, sig)) {
clasz.cunit.warning(sym.pos,
"""|compiler bug: created invalid generic signature for %s in %s
|signature: %s
@@ -652,10 +661,9 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
}
}
val index = jmember.getConstantPool.addUtf8(sig).toShort
- if (opt.verboseDebug || erasure.traceSignatures)
+ if (opt.verboseDebug)
atPhase(currentRun.erasurePhase) {
- log("new signature for " + sym+":"+sym.info)
- log(" " + sig)
+ println("add generic sig "+sym+":"+sym.info+" ==> "+sig+" @ "+index)
}
val buf = ByteBuffer.allocate(2)
buf putShort index
@@ -1818,14 +1826,20 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
/**
* Compute the indexes of each local variable of the given
- * method. Assumes parameters come first in the list of locals.
+ * method. *Does not assume the parameters come first!*
*/
def computeLocalVarsIndex(m: IMethod) {
var idx = 1
if (m.symbol.isStaticMember)
idx = 0;
- for (l <- m.locals) {
+ for (l <- m.params) {
+ debuglog("Index value for " + l + "{" + l.## + "}: " + idx)
+ l.index = idx
+ idx += sizeOf(l.kind)
+ }
+
+ for (l <- m.locals if !(m.params contains l)) {
debuglog("Index value for " + l + "{" + l.## + "}: " + idx)
l.index = idx
idx += sizeOf(l.kind)
@@ -68,7 +68,7 @@ abstract class DeadCodeElimination extends SubComponent {
var method: IMethod = _
/** Map instructions who have a drop on some control path, to that DROP instruction. */
- val dropOf: mutable.Map[(BasicBlock, Int), (BasicBlock, Int)] = perRunCaches.newMap()
+ val dropOf: mutable.Map[(BasicBlock, Int), List[(BasicBlock, Int)]] = perRunCaches.newMap()
def dieCodeDie(m: IMethod) {
if (m.code ne null) {
@@ -115,7 +115,7 @@ abstract class DeadCodeElimination extends SubComponent {
case CALL_METHOD(m1, _) if isSideEffecting(m1) => true
case LOAD_EXCEPTION(_) | DUP(_) | LOAD_MODULE(_) => true
case _ =>
- dropOf((bb1, idx1)) = (bb, idx)
+ dropOf((bb1, idx1)) = (bb,idx) :: dropOf.getOrElse((bb1, idx1), Nil)
// println("DROP is innessential: " + i + " because of: " + bb1(idx1) + " at " + bb1 + ":" + idx1)
false
}
@@ -141,9 +141,9 @@ abstract class DeadCodeElimination extends SubComponent {
val instr = bb(idx)
if (!useful(bb)(idx)) {
useful(bb) += idx
- dropOf.get(bb, idx) match {
- case Some((bb1, idx1)) => useful(bb1) += idx1
- case None => ()
+ dropOf.get(bb, idx) foreach {
+ for ((bb1, idx1) <- _)
+ useful(bb1) += idx1
}
instr match {
case LOAD_LOCAL(l1) =>
Oops, something went wrong.

0 comments on commit 63f072f

Please sign in to comment.