summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala19
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala41
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala100
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala2
6 files changed, 87 insertions, 83 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 8a23bab19e..629701bfda 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -47,8 +47,6 @@ abstract class GenICode extends SubComponent {
val Comparator_equals = definitions.getMember(definitions.getModule("scala.runtime.Comparator"),
nme.equals_)
- ///////////////////////////////////////////////////////////
-
override def run: Unit = {
scalaPrimitives.init
classes.clear
@@ -106,8 +104,7 @@ abstract class GenICode extends SubComponent {
var ctx1 = ctx.enterMethod(m, tree.asInstanceOf[DefDef])
addMethodParams(ctx1, vparamss)
- val NativeAttr = atPhase(currentRun.typerPhase)(definitions.getClass("scala.native").tpe)
- m.native = m.symbol.hasAttribute(NativeAttr)
+ m.native = m.symbol.hasAttribute(definitions.NativeAttr)
if (!m.isDeferred && !m.native) {
ctx1 = genLoad(rhs, ctx1, m.returnType);
@@ -691,6 +688,20 @@ abstract class GenICode extends SubComponent {
val nativeKind = toTypeKind(expr.tpe)
ctx1.bb.emit(BOX(nativeKind), expr.pos)
generatedType = toTypeKind(fun.symbol.tpe.resultType)
+ if (settings.Xdce.value) {
+ // we store this boxed value to a local, even if not really needed.
+ // boxing optimization might use it, and dead code elimination will
+ // take care of unnecessary stores
+ var loc1 = new Local(ctx.method.symbol.newVariable(
+ tree.pos,
+ unit.fresh.newName("boxed"))
+ .setInfo(definitions.ObjectClass.tpe)
+ .setFlag(Flags.SYNTHETIC),
+ ANY_REF_CLASS, false)
+ loc1 = ctx.method.addLocal(loc1)
+ ctx1.bb.emit(DUP(ANY_REF_CLASS))
+ ctx1.bb.emit(STORE_LOCAL(loc1))
+ }
ctx1
case Apply(fun @ _, List(expr)) if (definitions.isUnbox(fun.symbol)) =>
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index c28fcd6c72..809ff80eb3 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -65,17 +65,14 @@ abstract class GenJVM extends SubComponent {
val stringBufferType = new JObjectType(StringBufferClass)
val toStringType = new JMethodType(JObjectType.JAVA_LANG_STRING, JType.EMPTY_ARRAY)
- def attributeType(name: String) =
- atPhase(currentRun.typerPhase)(definitions.getClass(name).tpe)
-
// Scala attributes
- val SerializableAttr = atPhase(currentRun.typerPhase)(definitions.SerializableAttr.tpe)
- val SerialVersionUID = attributeType("scala.SerialVersionUID")
- val CloneableAttr = attributeType("scala.cloneable")
- val TransientAtt = attributeType("scala.transient")
- val VolatileAttr = attributeType("scala.volatile")
- val RemoteAttr = attributeType("scala.remote")
- val ThrowsAttr = attributeType("scala.throws")
+ val SerializableAttr = definitions.SerializableAttr
+ val SerialVersionUID = definitions.getClass("scala.SerialVersionUID")
+ val CloneableAttr = definitions.getClass("scala.cloneable")
+ val TransientAtt = definitions.getClass("scala.transient")
+ val VolatileAttr = definitions.getClass("scala.volatile")
+ val RemoteAttr = definitions.getClass("scala.remote")
+ val ThrowsAttr = definitions.getClass("scala.throws")
val CloneableClass =
if (forCLDC) null else definitions.getClass("java.lang.Cloneable")
@@ -149,13 +146,13 @@ abstract class GenJVM extends SubComponent {
if (!forCLDC)
for (val attr <- c.symbol.attributes) attr match {
- case AnnotationInfo(SerializableAttr, _, _) =>
+ case AnnotationInfo(tp, _, _) if tp.typeSymbol == SerializableAttr =>
parents = parents ::: List(definitions.SerializableClass.tpe)
- case AnnotationInfo(CloneableAttr, _, _) =>
+ case AnnotationInfo(tp, _, _) if tp.typeSymbol == CloneableAttr =>
parents = parents ::: List(CloneableClass.tpe)
- case AnnotationInfo(SerialVersionUID, value :: _, _) =>
+ case AnnotationInfo(tp, value :: _, _) if tp.typeSymbol == SerialVersionUID =>
serialVUID = Some(value.constant.get.longValue)
- case AnnotationInfo(RemoteAttr, _, _) =>
+ case AnnotationInfo(tp, _, _) if tp.typeSymbol == RemoteAttr =>
parents = parents ::: List(RemoteInterface.tpe)
remoteClass = true
case _ => ()
@@ -204,7 +201,7 @@ abstract class GenJVM extends SubComponent {
def addExceptionsAttribute(sym: Symbol): Unit = {
val (excs, others) = sym.attributes.partition((a => a match {
- case AnnotationInfo(ThrowsAttr, _, _) => true
+ case AnnotationInfo(tp, _, _) if tp.typeSymbol == ThrowsAttr => true
case _ => false
}))
if (excs isEmpty) return;
@@ -217,7 +214,7 @@ abstract class GenJVM extends SubComponent {
// put some radom value; the actual number is determined at the end
buf.putShort(0xbaba.toShort)
- for (val AnnotationInfo(ThrowsAttr, List(exc), _) <- excs.removeDuplicates) {
+ for (val AnnotationInfo(tp, List(exc), _) <- excs.removeDuplicates; tp.typeSymbol == ThrowsAttr) {
buf.putShort(
cpool.addClass(
javaName(exc.constant.get.typeValue.typeSymbol)).shortValue)
@@ -379,9 +376,9 @@ abstract class GenJVM extends SubComponent {
var attributes = 0
f.symbol.attributes foreach { a => a match {
- case AnnotationInfo(TransientAtt, _, _) =>
+ case AnnotationInfo(tp, _, _) if tp.typeSymbol == TransientAtt =>
attributes = attributes | JAccessFlags.ACC_TRANSIENT
- case AnnotationInfo(VolatileAttr, _, _) =>
+ case AnnotationInfo(tp, _, _) if tp.typeSymbol == VolatileAttr =>
attributes = attributes | JAccessFlags.ACC_VOLATILE
case _ => ();
}}
@@ -420,11 +417,9 @@ abstract class GenJVM extends SubComponent {
if (m.symbol.hasFlag(Flags.BRIDGE))
jmethod.addAttribute(fjbgContext.JOtherAttribute(jclass, jmethod, "Bridge",
new Array[Byte](0)))
- if ((remoteClass ||
- (m.symbol.attributes contains AnnotationInfo(RemoteAttr, Nil, Nil))) &&
- jmethod.isPublic() && !forCLDC)
- {
- val ainfo = AnnotationInfo(ThrowsAttr, List(new AnnotationArgument(Constant(RemoteException))), List())
+ if (remoteClass ||
+ (m.symbol.hasAttribute(RemoteAttr) && jmethod.isPublic() && !forCLDC)) {
+ val ainfo = AnnotationInfo(ThrowsAttr.tpe, List(new AnnotationArgument(Constant(RemoteException))), List())
m.symbol.attributes = ainfo :: m.symbol.attributes;
}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index 039a16a5d5..6f52db1acc 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -29,13 +29,11 @@ abstract class Inliners extends SubComponent {
/** The Inlining phase.
*/
class InliningPhase(prev: Phase) extends ICodePhase(prev) {
-
def name = phaseName
val inliner = new Inliner
override def apply(c: IClass): Unit =
inliner.analyzeClass(c)
-
}
/**
@@ -58,6 +56,9 @@ abstract class Inliners extends SubComponent {
s + "0"
}
+ lazy val ScalaInlineAttr = definitions.getClass("scala.inline")
+ lazy val ScalaNoInlineAttr = definitions.getClass("scala.noinline")
+
/** Inline the 'callee' method inside the 'caller' in the given
* basic block, at the given instruction (which has to be a CALL_METHOD).
*/
@@ -262,12 +263,6 @@ abstract class Inliners extends SubComponent {
assert(pending.isEmpty, "Pending NEW elements: " + pending)
}
- val InlineAttr = if (settings.inline.value) try {
- global.definitions.getClass("scala.inline").tpe
- } catch {
- case e: FatalError => null
- } else null;
-
def analyzeClass(cls: IClass): Unit = if (settings.inline.value) {
if (settings.debug.value)
log("Analyzing " + cls);
@@ -316,15 +311,13 @@ abstract class Inliners extends SubComponent {
if ( classes.contains(receiver)
&& (isClosureClass(receiver)
- || concreteMethod.isFinal
- || msym.attributes.exists(a => a.atp == InlineAttr))) {
+ || concreteMethod.isFinal)) {
classes(receiver).lookupMethod(concreteMethod) match {
case Some(inc) =>
if (inc.symbol != m.symbol
&& (inlinedMethods(inc.symbol) < 2)
&& (inc.code ne null)
&& shouldInline(m, inc)
- && (inc.code.blocks.length <= MAX_INLINE_SIZE)
&& isSafeToInline(m, inc, info._2)) {
retry = true;
if (!isClosureClass(receiver)) // only count non-closures
@@ -423,56 +416,59 @@ abstract class Inliners extends SubComponent {
if (stack.length > (1 + callee.symbol.info.paramTypes.length) &&
callee.exh != Nil) {
-// (callee.exh exists (_.covered.contains(callee.code.startBlock)))) {
if (settings.debug.value) log("method " + callee.symbol + " is used on a non-empty stack with finalizer.");
false
} else
true
}
- } /* class Inliner */
-
- def isClosureClass(cls: Symbol): Boolean = {
- val res =
- cls.isFinal &&
- cls.tpe.parents.exists { t =>
- val TypeRef(_, sym, _) = t;
- definitions.FunctionClass exists sym.==
- }
- res
- }
-
- /** small method size (in blocks) */
- val SMALL_METHOD_SIZE = 4
+ /** small method size (in blocks) */
+ val SMALL_METHOD_SIZE = 4
- /** Decide whether to inline or not. Heuristics:
- * - it's bad to make the caller larger (> SMALL_METHOD_SIZE)
- * if it was small
- * - it's good to inline higher order functions
- * - it's good to inline closures functions.
- * - it's bad (useless) to inline inside bridge methods
- */
- def shouldInline(caller: IMethod, callee: IMethod): Boolean = {
- if (caller.symbol.hasFlag(Flags.BRIDGE)) return false;
- if (settings.debug.value)
- log("shouldInline: " + caller + " with " + callee)
- var score = 0
- if (callee.code.blocks.length <= SMALL_METHOD_SIZE) score = score + 1
- if (caller.code.blocks.length <= SMALL_METHOD_SIZE
- && ((caller.code.blocks.length + callee.code.blocks.length) > SMALL_METHOD_SIZE)) {
- score = score - 1
+ /** Decide whether to inline or not. Heuristics:
+ * - it's bad to make the caller larger (> SMALL_METHOD_SIZE)
+ * if it was small
+ * - it's bad to inline large methods
+ * - it's good to inline higher order functions
+ * - it's good to inline closures functions.
+ * - it's bad (useless) to inline inside bridge methods
+ */
+ def shouldInline(caller: IMethod, callee: IMethod): Boolean = {
+ if (caller.symbol.hasFlag(Flags.BRIDGE)) return false;
+ if (callee.symbol.hasAttribute(ScalaNoInlineAttr)) return false
+ if (callee.symbol.hasAttribute(ScalaInlineAttr)) return true
if (settings.debug.value)
- log("shouldInline: score decreased to " + score + " because small " + caller + " would become large")
- }
+ log("shouldInline: " + caller + " with " + callee)
+ var score = 0
+ if (callee.code.blocks.length <= SMALL_METHOD_SIZE) score = score + 1
+ if (caller.code.blocks.length <= SMALL_METHOD_SIZE
+ && ((caller.code.blocks.length + callee.code.blocks.length) > SMALL_METHOD_SIZE)) {
+ score = score - 1
+ if (settings.debug.value)
+ log("shouldInline: score decreased to " + score + " because small " + caller + " would become large")
+ }
+ if (callee.code.blocks.length > MAX_INLINE_SIZE)
+ score -= 1
- if (callee.symbol.tpe.paramTypes.exists(t => definitions.FunctionClass.contains(t.typeSymbol))) {
- if (settings.debug.value)
- log("increased score to: " + score)
- score = score + 2
+ if (callee.symbol.tpe.paramTypes.exists(t => definitions.FunctionClass.contains(t.typeSymbol))) {
+ if (settings.debug.value)
+ log("increased score to: " + score)
+ score = score + 2
+ }
+ if (isClosureClass(callee.symbol.owner))
+ score = score + 2
+
+ score > 0
}
- if (isClosureClass(callee.symbol.owner))
- score = score + 2
+ } /* class Inliner */
- score > 0
- }
+ /** Is the given class a subtype of a function trait? */
+ def isClosureClass(cls: Symbol): Boolean = {
+ val res = cls.isFinal &&
+ cls.tpe.parents.exists { t =>
+ val TypeRef(_, sym, _) = t;
+ definitions.FunctionClass exists sym.==
+ }
+ res
+ }
} /* class Inliners */
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 60296a970b..dd2ac94f49 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -82,9 +82,11 @@ trait Symbols {
}
var attributes: List[AnnotationInfo] = List()
- def hasAttribute(Tpe: Type): Boolean =
+
+ /** Does this symbol have an attribute of the given class? */
+ def hasAttribute(cls: Symbol): Boolean =
attributes.exists {
- case AnnotationInfo(Tpe, _, _) => true
+ case AnnotationInfo(tp, _, _) if tp.typeSymbol == cls => true
case _ => false
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index c5c6326806..605263a2a1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -789,7 +789,7 @@ trait Namers { self: Analyzer =>
sym.isValueParameter && sym.owner.isClass && sym.owner.hasFlag(CASE))
context.error(sym.pos, "pass-by-name arguments not allowed for case class parameters");
if ((sym.flags & DEFERRED) != 0) {
- if (sym.hasAttribute(definitions.NativeAttr.tpe))
+ if (sym.hasAttribute(definitions.NativeAttr))
sym.resetFlag(DEFERRED)
else if (!sym.isValueParameter && !sym.isTypeParameterOrSkolem &&
!context.tree.isInstanceOf[ExistentialTypeTree] &&
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 30ef88a17b..174485c6cb 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -727,7 +727,7 @@ abstract class RefChecks extends InfoTransform {
val sym = tree.symbol
var result = tree
tree match {
- case DefDef(mods, name, tparams, vparams, tpt, EmptyTree) if tree.symbol.hasAttribute(definitions.NativeAttr.tpe) =>
+ case DefDef(mods, name, tparams, vparams, tpt, EmptyTree) if tree.symbol.hasAttribute(definitions.NativeAttr) =>
tree.symbol.resetFlag(DEFERRED)
result = transform(copy.DefDef(tree, mods, name, tparams, vparams, tpt,
typed(Apply(gen.mkAttributedRef(definitions.Predef_error), List(Literal("native method stub"))))))