summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala8
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Members.scala16
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala3
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala3
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala16
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala56
9 files changed, 68 insertions, 40 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index be74fe4e78..e60ea9a341 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -633,10 +633,10 @@ abstract class GenICode extends SubComponent {
ctx1 = genLoadArguments(args, ctor.info.paramTypes, ctx)
ctx1.bb.emit(CREATE_ARRAY(elem), tree.pos)
- case REFERENCE(cls) =>
+ case rt @ REFERENCE(cls) =>
assert(ctor.owner == cls,
"Symbol " + ctor.owner.fullNameString + " is different than " + tpt)
- ctx1.bb.emit(NEW(generatedType), tree.pos)
+ ctx1.bb.emit(NEW(rt), tree.pos)
ctx1.bb.emit(DUP(generatedType))
ctx1 = genLoadArguments(args, ctor.info.paramTypes, ctx)
@@ -1101,6 +1101,8 @@ abstract class GenICode extends SubComponent {
case DOUBLE => Literal(0.0d)
case REFERENCE(cls) => Literal(null: Any)
case ARRAY(elem) => Literal(null: Any)
+ case BOXED(_) => Literal(null: Any)
+ case ConcatClass => abort("no zero of ConcatClass")
}
def getZeroOf(k: TypeKind): Instruction = k match {
@@ -1115,6 +1117,8 @@ abstract class GenICode extends SubComponent {
case DOUBLE => CONSTANT(Constant(0.0d))
case REFERENCE(cls) => CONSTANT(Constant(null: Any))
case ARRAY(elem) => CONSTANT(Constant(null: Any))
+ case BOXED(_) => CONSTANT(Constant(null: Any))
+ case ConcatClass => abort("no zero of ConcatClass")
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
index 0f8d1091a1..654da7762e 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
@@ -216,6 +216,20 @@ trait Members requires ICodes {
symbol.hasFlag(Flags.STATIC) || symbol.hasFlag(Flags.STATICMEMBER) || symbol.owner.isImplClass;
override def toString() = symbol.fullNameString;
+
+ import opcodes._
+ def checkLocals: Unit = if (code ne null) {
+ Console.println("[checking locals of " + this + "]")
+ for (val bb <- code.blocks; val i <- bb.toList) i match {
+ case LOAD_LOCAL(l) =>
+ if (!this.locals.contains(l))
+ Console.println("Local " + l + " is not declared in " + this)
+ case STORE_LOCAL(l) =>
+ if (!this.locals.contains(l))
+ Console.println("Local " + l + " is not declared in " + this)
+ case _ => ()
+ }
+ }
}
/** Represent local variables and parameters */
@@ -228,7 +242,7 @@ trait Members requires ICodes {
/** Ending PC for this local's visbility range. */
var end: Int = _
- /** PC-based ranges for this local variable's visibility range */
+ /** PC-based ranges for this local variable's visibility */
var ranges: List[Pair[Int, Int]] = Nil
override def equals(other: Any): Boolean = (
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
index e50bc65cc4..6002c3ea6d 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
@@ -322,7 +322,7 @@ trait Opcodes requires ICodes {
* Stack: ...:arg1:arg2:...:argn
* ->: ...:ref
*/
- case class NEW(kind: TypeKind) extends Instruction {
+ case class NEW(kind: REFERENCE) extends Instruction {
/** Returns a string representation of this instruction */
override def toString(): String = "NEW "+ kind;
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 7d6bb09ba3..4da3c1db2b 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
@@ -350,6 +350,9 @@ abstract class CopyPropagation {
case MONITOR_EXIT() =>
out.stack = out.stack.drop(1)
+ case SCOPE_ENTER(_) | SCOPE_EXIT(_) =>
+ ()
+
case _ =>
dump
abort("Unknown instruction: " + i)
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 abb79ef3e5..4be33c4ef1 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala
@@ -79,7 +79,7 @@ abstract class Liveness {
backwardAnalysis(blockTransfer)
if (settings.debug.value) {
linearizer.linearize(method).foreach(b => if (b != method.code.startBlock)
- assert(in(b) != lattice.bottom,
+ assert(lattice.bottom != in(b),
"Block " + b + " in " + this.method + " has input equal to bottom -- not visited?"));
}
}
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 fcb369615e..9d27858b0a 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
@@ -316,6 +316,9 @@ abstract class TypeFlowAnalysis {
case MONITOR_EXIT() =>
stack.pop
+ case SCOPE_ENTER(_) | SCOPE_EXIT(_) =>
+ ()
+
case _ =>
dump
abort("Unknown instruction: " + i)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 0a4de0e814..36a2307212 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -817,7 +817,7 @@ abstract class GenJVM extends SubComponent {
jcode.emitDUP()
jcode.emitIFNONNULL(nonNull)
jcode.emitPOP()
- boxKind match {
+ (boxKind: @unsealed) match {
case BYTE => jcode.emitPUSH(0: Byte)
case SHORT => jcode.emitPUSH(0: Short)
case CHAR => jcode.emitPUSH(0: Char)
@@ -909,7 +909,7 @@ abstract class GenJVM extends SubComponent {
}
case _ =>
- kind match {
+ (kind: @unsealed) match {
case LONG => jcode.emitLCMP()
case FLOAT => jcode.emitFCMPG()
case DOUBLE => jcode.emitDCMPG()
@@ -945,7 +945,7 @@ abstract class GenJVM extends SubComponent {
}
case _ =>
- kind match {
+ (kind: @unsealed) match {
case LONG => jcode.emitLCONST_0(); jcode.emitLCMP()
case FLOAT => jcode.emitFCONST_0(); jcode.emitFCMPL()
case DOUBLE => jcode.emitDCONST_0(); jcode.emitDCMPL()
@@ -1050,7 +1050,7 @@ abstract class GenJVM extends SubComponent {
op match {
case ADD => jcode.emitADD(javaType(kind))
case SUB =>
- kind match {
+ (kind: @unsealed) match {
case BOOL | BYTE | CHAR | SHORT | INT =>
jcode.emitISUB()
case LONG => jcode.emitLSUB()
@@ -1059,7 +1059,7 @@ abstract class GenJVM extends SubComponent {
}
case MUL =>
- kind match {
+ (kind: @unsealed) match {
case BOOL | BYTE | CHAR | SHORT | INT =>
jcode.emitIMUL()
case LONG => jcode.emitLMUL()
@@ -1068,7 +1068,7 @@ abstract class GenJVM extends SubComponent {
}
case DIV =>
- kind match {
+ (kind: @unsealed) match {
case BOOL | BYTE | CHAR | SHORT | INT =>
jcode.emitIDIV()
case LONG => jcode.emitLDIV()
@@ -1077,7 +1077,7 @@ abstract class GenJVM extends SubComponent {
}
case REM =>
- kind match {
+ (kind: @unsealed) match {
case BOOL | BYTE | CHAR | SHORT | INT =>
jcode.emitIREM()
case LONG => jcode.emitLREM()
@@ -1375,7 +1375,7 @@ abstract class GenJVM extends SubComponent {
sym.isNonBottomSubClass(definitions.ClassfileAnnotationClass))
- def javaType(t: TypeKind): JType = t match {
+ def javaType(t: TypeKind): JType = (t: @unsealed) match {
case UNIT => JType.VOID
case BOOL => JType.BOOLEAN
case BYTE => JType.BYTE
diff --git a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
index d4df49d05f..354bf647a8 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
@@ -154,7 +154,7 @@ abstract class ClosureElimination extends SubComponent {
}
/* Partial mapping from values to instructions that load them. */
- def valueToInstruction(v: Value): Instruction = v match {
+ def valueToInstruction(v: Value): Instruction = (v: @unsealed) match {
case Deref(LocalVar(v)) =>
LOAD_LOCAL(v)
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index 3afbbb56f0..ea3442222e 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -69,9 +69,6 @@ abstract class Inliners extends SubComponent {
/* Map 'original' blocks to the ones inlined in the caller. */
val inlinedBlock: Map[BasicBlock, BasicBlock] = new HashMap;
- /* Map callee's parameters to inlined local variables. */
- val argsToLocal: Map[Local, Local] = new HashMap;
-
val instrBefore = block.toList.takeWhile( i => i ne instr);
val instrAfter = block.toList.drop(instrBefore.length + 1);
@@ -91,6 +88,8 @@ abstract class Inliners extends SubComponent {
def newBlock = {
val b = caller.code.newBlock;
activeHandlers.foreach (.addBlock(b));
+ if (retVal ne null) b.varsInScope += retVal
+ b.varsInScope += inlinedThis
b
}
@@ -101,24 +100,15 @@ abstract class Inliners extends SubComponent {
handler
}
+ var inlinedLocals: Map[Local, Local] = new HashMap
+
/** alfa-rename `l' in caller's context. */
def dupLocal(l: Local): Local = {
val sym = caller.symbol.newVariable(l.sym.pos, freshName(l.sym.name.toString()));
- sym.setInfo(l.sym.tpe);
- new Local(sym, l.kind, false)
- }
-
- /** Adds parameters from another method as locals */
- def addParamsAsLocals(m: IMethod, ls: List[Local]): Unit = {
- m.locals = m.locals ::: (ls map { a =>
- if (a.arg) {
- //val l = new Local(a.sym, a.kind, false);
- val l = dupLocal(a);
- argsToLocal += a -> l;
- l
- } else
- a
- });
+// sym.setInfo(l.sym.tpe);
+ val dupped = new Local(sym, l.kind, false)
+ inlinedLocals(l) = dupped
+ dupped
}
def addLocals(m: IMethod, ls: List[Local]) =
@@ -148,23 +138,37 @@ abstract class Inliners extends SubComponent {
case RETURN(kind) =>
JUMP(afterBlock);
- case LOAD_LOCAL(l) if (argsToLocal.isDefinedAt(l)) =>
- Console.println("Replacing load_local");
- LOAD_LOCAL(argsToLocal(l))
+ case LOAD_LOCAL(l) if inlinedLocals.isDefinedAt(l) =>
+ LOAD_LOCAL(inlinedLocals(l))
+
+ case STORE_LOCAL(l) if inlinedLocals.isDefinedAt(l) =>
+ STORE_LOCAL(inlinedLocals(l))
+
+ case LOAD_LOCAL(l) =>
+ assert(caller.locals contains l,
+ "Could not find local '" + l + "' in locals, nor in inlinedLocals: " + inlinedLocals)
+ i
+ case STORE_LOCAL(l) =>
+ assert(caller.locals contains l,
+ "Could not find local '" + l + "' in locals, nor in inlinedLocals: " + inlinedLocals)
+ i
+
+ case SCOPE_ENTER(l) if inlinedLocals.isDefinedAt(l) =>
+ SCOPE_ENTER(inlinedLocals(l))
- case STORE_LOCAL(l) if (argsToLocal.isDefinedAt(l)) =>
- Console.println("Replacing store_local");
- STORE_LOCAL(argsToLocal(l))
+ case SCOPE_EXIT(l) if inlinedLocals.isDefinedAt(l) =>
+ SCOPE_EXIT(inlinedLocals(l))
case _ => i
}
- addLocals(caller, callee.locals);
+ addLocals(caller, callee.locals map dupLocal);
addLocal(caller, inlinedThis);
if (retVal ne null)
addLocal(caller, retVal);
callee.code.blocks.foreach { b =>
inlinedBlock += b -> newBlock;
+ inlinedBlock(b).varsInScope ++= (b.varsInScope map inlinedLocals)
}
// analyse callee
@@ -177,7 +181,7 @@ abstract class Inliners extends SubComponent {
// store the arguments into special locals
callee.params.reverse.foreach { param =>
- block.emit(STORE_LOCAL(param), targetPos);
+ block.emit(STORE_LOCAL(inlinedLocals(param)), targetPos);
}
block.emit(STORE_LOCAL(inlinedThis), targetPos);