summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2006-11-14 10:15:34 +0000
committerIulian Dragos <jaguarul@gmail.com>2006-11-14 10:15:34 +0000
commit258064826d62478fa6fb431ffd8f195272824e3a (patch)
treeaa98688c10658695babd412cd1256a0a383e97b7
parentd0dd6b7eee6bf0321fd39d43ececb54fe8761334 (diff)
downloadscala-258064826d62478fa6fb431ffd8f195272824e3a.tar.gz
scala-258064826d62478fa6fb431ffd8f195272824e3a.tar.bz2
scala-258064826d62478fa6fb431ffd8f195272824e3a.zip
Changed BOX/UNBOX to use TypeKind instead of Type.
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala13
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Checkers.scala14
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala56
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala8
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala16
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala18
9 files changed, 102 insertions, 37 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
index 00a1cc4c95..6c46e01af3 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
@@ -61,6 +61,19 @@ trait BasicBlocks requires ICodes {
// public:
+ /** Return the index of inst. Uses reference equality.
+ * Returns -1 if not found.
+ */
+ def indexOf(inst: Instruction): Int = {
+ assert(closed)
+ var i = 0;
+ while (i < instrs.length) {
+ if (instrs(i) eq inst) return i
+ i = i + 1
+ }
+ -1
+ }
+
/** Compute an hashCode for the block */
override def hashCode() = label;
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala
index a6a3f2c2d8..e7a456aee6 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala
@@ -67,7 +67,7 @@ abstract class Checkers {
val STRING = REFERENCE(definitions.StringClass)
val SCALA_ALL = REFERENCE(definitions.AllClass)
val SCALA_ALL_REF = REFERENCE(definitions.AllRefClass)
- val CASE_CLASS = REFERENCE(definitions.getClass("scala.CaseClass"))
+// val CASE_CLASS = REFERENCE(definitions.getClass("scala.CaseClass"))
def checkICodes: Unit = {
Console.println("[[consistency check at beginning of phase " + globalPhase.name + "]]")
@@ -200,7 +200,7 @@ abstract class Checkers {
/** Checks that tpe is a subtype of one of the allowed types */
def checkType(tpe: TypeKind, allowed: TypeKind*) =
- if (isOneOf(tpe, allowed: _*) || tpe <:< CASE_CLASS) /* hack */
+ if (isOneOf(tpe, allowed: _*))
()
else
error(tpe.toString() + " is not one of: " + allowed.toList.mkString("{", ", ", "}"));
@@ -318,7 +318,7 @@ abstract class Checkers {
val actualType = stack.pop;
if (!(actualType <:< local.kind) &&
- actualType != CASE_CLASS &&
+ //actualType != CASE_CLASS &&
local.kind != SCALA_ALL_REF)
typeError(local.kind, actualType);
@@ -327,8 +327,8 @@ abstract class Checkers {
checkStack(1);
val fieldType = toTypeKind(field.tpe);
val actualType = stack.pop;
- if (!(actualType <:< fieldType) &&
- actualType != CASE_CLASS)
+ if (!(actualType <:< fieldType))
+ // && actualType != CASE_CLASS)
typeError(fieldType, actualType);
} else {
checkStack(2);
@@ -336,8 +336,8 @@ abstract class Checkers {
case Pair(value, obj) =>
checkField(obj, field);
val fieldType = toTypeKind(field.tpe);
- if (fieldType != SCALA_ALL_REF && !(value <:< fieldType)
- && value != CASE_CLASS)
+ if (fieldType != SCALA_ALL_REF && !(value <:< fieldType))
+ //&& value != CASE_CLASS)
typeError(fieldType, value);
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 4ecd9c7012..298fdc7ee4 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -640,7 +640,7 @@ abstract class GenICode extends SubComponent {
log("BOX : " + fun.symbol.fullNameString);
val ctx1 = genLoad(expr, ctx, toTypeKind(expr.tpe))
val boxType = fun.symbol.owner.linkedClassOfClass.tpe
- ctx1.bb.emit(BOX(boxType), expr.pos)
+ ctx1.bb.emit(BOX(toTypeKind(boxType)), expr.pos)
ctx1
case Apply(fun @ _, List(expr)) if (definitions.isUnbox(fun.symbol)) =>
@@ -648,7 +648,7 @@ abstract class GenICode extends SubComponent {
log("UNBOX : " + fun.symbol.fullNameString)
val ctx1 = genLoad(expr, ctx, toTypeKind(expr.tpe))
assert(expectedType.isValueType)
- ctx1.bb.emit(UNBOX(expectedType.toType), expr.pos)
+ ctx1.bb.emit(UNBOX(expectedType), expr.pos)
ctx1
case Apply(fun, args) =>
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
index f814aaa04f..d92106e52e 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
@@ -306,13 +306,13 @@ trait Opcodes requires ICodes {
else 1
}
- case class BOX(boxType: Type) extends Instruction {
+ case class BOX(boxType: TypeKind) extends Instruction {
override def toString(): String = "BOX " + boxType
override def consumed = 1
override def produced = 1
}
- case class UNBOX(boxType: Type) extends Instruction {
+ case class UNBOX(boxType: TypeKind) extends Instruction {
override def toString(): String = "UNBOX " + boxType
override def consumed = 1
override def produced = 1
diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
index e06fd5e2e4..238f9319a7 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
@@ -51,15 +51,15 @@ trait TypeKinds requires ICodes {
}
def toType: Type = this match {
- case UNIT => definitions.UnitClass.info
- case BOOL => definitions.BooleanClass.info
- case BYTE => definitions.ByteClass.info
- case SHORT => definitions.ShortClass.info
- case CHAR => definitions.CharClass.info
- case INT => definitions.IntClass.info
- case LONG => definitions.LongClass.info
- case FLOAT => definitions.FloatClass.info
- case DOUBLE => definitions.DoubleClass.info
+ case UNIT => definitions.UnitClass.tpe
+ case BOOL => definitions.BooleanClass.tpe
+ case BYTE => definitions.ByteClass.tpe
+ case SHORT => definitions.ShortClass.tpe
+ case CHAR => definitions.CharClass.tpe
+ case INT => definitions.IntClass.tpe
+ case LONG => definitions.LongClass.tpe
+ case FLOAT => definitions.FloatClass.tpe
+ case DOUBLE => definitions.DoubleClass.tpe
case REFERENCE(cls) => typeRef(cls.typeConstructor.prefix, cls, Nil)
case ARRAY(elem) => typeRef(definitions.ArrayClass.typeConstructor.prefix,
definitions.ArrayClass,
@@ -295,6 +295,44 @@ trait TypeKinds requires ICodes {
}
+ /** A boxed value. */
+ case class BOXED(kind: TypeKind) extends TypeKind {
+ override def toString(): String =
+ "BOXED(" + kind + ")"
+
+ /**
+ * Approximate `lub'. The common type of two references is
+ * always AnyRef. For 'real' least upper bound wrt to subclassing
+ * use method 'lub'.
+ */
+ override def maxType(other: TypeKind): TypeKind =
+ other match {
+ case REFERENCE(_) | ARRAY(_) | BOXED(_) =>
+ REFERENCE(definitions.AnyRefClass)
+ case _ =>
+ abort("Uncomparbale type kinds: ARRAY with " + other)
+ }
+
+ /** Checks subtyping relationship. */
+ override def <:<(other: TypeKind): Boolean =
+ other match {
+ case REFERENCE(sym) =>
+ (sym == definitions.AnyRefClass ||
+ sym == definitions.ObjectClass) // TODO: platform dependent!
+
+ case BOXED(other) =>
+ kind == other
+
+ case _ => false
+ }
+
+ override def equals(other: Any): Boolean = other match {
+ case BOXED(kind2) => kind == kind2
+ case _ => false
+ }
+
+ }
+
/**
* Dummy TypeKind to represent the ConcatClass in a platform-independent
* way. For JVM it would have been a REFERENCE to 'StringBuffer'.
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 00f1763945..3364f94e28 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
@@ -291,6 +291,12 @@ abstract class CopyPropagation {
out = simulateCall(in, method, false);
}
+ case BOX(tpe) =>
+ out.stack = Unknown :: out.stack.drop(1)
+
+ case UNBOX(tpe) =>
+ out.stack = Unknown :: out.stack.drop(1)
+
case NEW(kind) =>
val v1 =
kind match {
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 79cc091f4f..45e5a8b61e 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
@@ -253,6 +253,14 @@ abstract class TypeFlowAnalysis {
stack.push(toTypeKind(method.info.resultType));
}
+ case BOX(kind) =>
+ stack.pop
+ stack.push(BOXED(kind))
+
+ case UNBOX(kind) =>
+ stack.pop
+ stack.push(kind)
+
case NEW(kind) =>
stack.push(kind);
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 979ed831c9..272d8c7d75 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -789,12 +789,12 @@ abstract class GenJVM extends SubComponent {
}
- case BOX(boxType) =>
- val boxedClass = definitions.boxedClass(boxType.symbol)
- val mtype = new JMethodType(javaType(boxedClass), Array(javaType(boxType)))
+ case BOX(kind) =>
+ val boxedClass = definitions.boxedClass(kind.toType.symbol)
+ val mtype = new JMethodType(javaType(boxedClass), Array(javaType(kind)))
jcode.emitINVOKESTATIC(javaName(boxedClass), "box", mtype)
- case UNBOX(boxType) if (boxType.symbol == definitions.BooleanClass) =>
+ case UNBOX(BOOL) /* if (boxType.symbol == definitions.BooleanClass) */=>
// if null emit false
val nonNull = jcode.newLabel()
jcode.emitDUP()
@@ -810,13 +810,13 @@ abstract class GenJVM extends SubComponent {
jcode.emitGETFIELD(boxedBoolean, "value", JType.BOOLEAN)
lexit.anchorToNext()
- case UNBOX(boxType) =>
+ case UNBOX(boxKind) =>
// if null emit a zero of the appropriate kind
val nonNull = jcode.newLabel()
jcode.emitDUP()
jcode.emitIFNONNULL(nonNull)
jcode.emitPOP()
- toTypeKind(boxType) match {
+ boxKind match {
case BYTE => jcode.emitPUSH(0: Byte)
case SHORT => jcode.emitPUSH(0: Short)
case CHAR => jcode.emitPUSH(0: Char)
@@ -830,9 +830,9 @@ abstract class GenJVM extends SubComponent {
nonNull.anchorToNext()
// else unbox the reference at the top of the stack
jcode.emitCHECKCAST(new JObjectType(BOXED_NUMBER))
- val clazzName = boxType.symbol.name.toString()
+ val clazzName = boxKind.toType.symbol.name.toString()
val unboxMethod = clazzName.toLowerCase() + "Value"
- val mtype = new JMethodType(javaType(boxType), new Array[JType](0))
+ val mtype = new JMethodType(javaType(boxKind), new Array[JType](0))
jcode.emitINVOKEVIRTUAL(BOXED_NUMBER, unboxMethod, mtype)
lexit.anchorToNext()
diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
index 791dcd50c2..c23f7fcf07 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
@@ -62,7 +62,7 @@ abstract class DeadCodeElimination extends SubComponent {
i match {
case STORE_LOCAL(l) if (!live(l)) =>
- removeDefUse(bb, pos);
+ removeDefUse(bb, i);
case _ => ()
}
live = a.interpret(live, i);
@@ -73,24 +73,24 @@ abstract class DeadCodeElimination extends SubComponent {
* in the basic block. The `def' is the closest previous instruction which
* produced the top value on the stack.
*/
- def removeDefUse(bb: BasicBlock, use: Int): Unit = {
- bb.findDef(use) match {
+ def removeDefUse(bb: BasicBlock, use: Instruction): Unit = {
+ val usePos = bb.indexOf(use)
+ bb.findDef(usePos) match {
case Some(defPos) =>
val definition = bb(defPos);
if (isSafeToRemove(definition)) {
- log("Removing instructions at BB " + bb + " def: " + definition + ", use: " + bb(use));
+ log("Removing instructions at BB " + bb + " def: " + definition + ", use: " + use);
if (definition.consumed == 0) {
- bb.removeInstructionsAt(defPos, use)
+ bb.removeInstructionsAt(defPos, usePos)
} else {
bb.replaceInstruction(definition, definition.consumedTypes map DROP);
- bb.removeInstructionsAt(use);
+ bb.removeInstructionsAt(usePos);
}
}
case None =>
- val i = bb(use);
- bb.replaceInstruction(i, i.consumedTypes map DROP);
- log("Replaced dead " + i + " by DROP in bb " + bb);
+ bb.replaceInstruction(use, use.consumedTypes map DROP);
+ log("Replaced dead " + use + " by DROP in bb " + bb);
}
}