summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormichelou <michelou@epfl.ch>2010-12-30 23:53:00 +0000
committermichelou <michelou@epfl.ch>2010-12-30 23:53:00 +0000
commitbf375f7d6375a2e437342a6d3b935048fa3ec545 (patch)
tree34a6d17021ee734f365c6044c4ceea1ad3cde8ea
parent096bc81a90b746ea3fa8a5bd8eb9009c08a71082 (diff)
downloadscala-bf375f7d6375a2e437342a6d3b935048fa3ec545.tar.gz
scala-bf375f7d6375a2e437342a6d3b935048fa3ec545.tar.bz2
scala-bf375f7d6375a2e437342a6d3b935048fa3ec545.zip
fixed issue with EnclosingMethod attribute.
The above issue was made explicit using the dx tool for the Android SDK to convert Java bytecode to Dalvik bytecode.
-rw-r--r--src/compiler/scala/tools/nsc/ScriptRunner.scala38
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala20
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala83
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala13
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala59
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala5
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala39
-rw-r--r--src/library/scala/collection/TraversableLike.scala91
-rw-r--r--test/files/jvm/cf-attributes.check50
-rw-r--r--test/files/jvm/cf-attributes.scala146
-rw-r--r--test/files/run/t1167.check4
-rw-r--r--test/files/run/t1167.scala7
12 files changed, 389 insertions, 166 deletions
diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala
index c8085e58a1..a3a04e34b9 100644
--- a/src/compiler/scala/tools/nsc/ScriptRunner.scala
+++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala
@@ -236,11 +236,11 @@ object ScriptRunner {
*/
private def runCompiled(
settings: GenericRunnerSettings,
- compiledLocation: String,
- scriptArgs: List[String]): Boolean =
- {
- val pr = new PathResolver(settings)
- val classpath = File(compiledLocation).toURL +: pr.asURLs
+ compiledLocation: String,
+ scriptArgs: List[String]): Boolean =
+ {
+ val pr = new PathResolver(settings)
+ val classpath = File(compiledLocation).toURL +: pr.asURLs
ObjectRunner.runAndCatch(classpath, scriptMain(settings), scriptArgs) match {
case Left(ex) => ex.printStackTrace() ; false
@@ -255,13 +255,13 @@ object ScriptRunner {
*/
def runScript(
settings: GenericRunnerSettings,
- scriptFile: String,
- scriptArgs: List[String]): Boolean =
- {
- if (File(scriptFile).isFile)
- withCompiledScript(settings, scriptFile) { runCompiled(settings, _, scriptArgs) }
- else
- throw new IOException("no such file: " + scriptFile)
+ scriptFile: String,
+ scriptArgs: List[String]): Boolean =
+ {
+ if (File(scriptFile).isFile)
+ withCompiledScript(settings, scriptFile) { runCompiled(settings, _, scriptArgs) }
+ else
+ throw new IOException("no such file: " + scriptFile)
}
/** Calls runScript and catches the enumerated exceptions, routing
@@ -269,11 +269,11 @@ object ScriptRunner {
*/
def runScriptAndCatch(
settings: GenericRunnerSettings,
- scriptFile: String,
- scriptArgs: List[String]): Either[Throwable, Boolean] =
- {
- try Right(runScript(settings, scriptFile, scriptArgs))
- catch { case e => Left(unwrap(e)) }
+ scriptFile: String,
+ scriptArgs: List[String]): Either[Throwable, Boolean] =
+ {
+ try Right(runScript(settings, scriptFile, scriptArgs))
+ catch { case e => Left(unwrap(e)) }
}
/** Run a command
@@ -283,8 +283,8 @@ object ScriptRunner {
def runCommand(
settings: GenericRunnerSettings,
command: String,
- scriptArgs: List[String]) : Boolean =
- {
+ scriptArgs: List[String]): Boolean =
+ {
val scriptFile = File.makeTemp("scalacmd", ".scala")
// save the command to the file
scriptFile writeAll command
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala
index e0a06fa076..301dbd18d6 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala
@@ -1,7 +1,9 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2010 LAMP/EPFL
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Stephane Micheloud
*/
+
package scala.tools.nsc
package backend.jvm
@@ -15,20 +17,27 @@ trait GenAndroid {
import icodes._
import opcodes._
+ /** From the reference documentation of the Android SDK:
+ * The `Parcelable` interface identifies classes whose instances can be
+ * written to and restored from a `Parcel`. Classes implementing the
+ * `Parcelable` interface must also have a static field called `CREATOR`,
+ * which is an object implementing the `Parcelable.Creator` interface.
+ */
private val fieldName = "CREATOR"
+
private lazy val AndroidParcelableInterface =
try definitions.getClass("android.os.Parcelable")
catch { case _: FatalError => NoSymbol }
+
private lazy val AndroidCreatorClass =
if (AndroidParcelableInterface == NoSymbol) NoSymbol
else definitions.getClass("android.os.Parcelable$Creator")
- def isAndroidParcelableClass(sym: Symbol) = (
+ def isAndroidParcelableClass(sym: Symbol) =
(AndroidParcelableInterface != NoSymbol) &&
(sym.info.parents contains AndroidParcelableInterface.tpe)
- )
- def addCreatorCode(codegen: BytecodeGenerator, block: BasicBlock) = {
+ def addCreatorCode(codegen: BytecodeGenerator, block: BasicBlock) {
import codegen._
val fieldSymbol = clasz.symbol.newValue(NoPosition, newTermName(fieldName))
.setFlag(Flags.STATIC | Flags.FINAL)
@@ -39,7 +48,7 @@ trait GenAndroid {
block emit STORE_FIELD(fieldSymbol, true)
}
- def legacyAddCreatorCode(codegen: BytecodeGenerator, clinit: JExtendedCode) = {
+ def legacyAddCreatorCode(codegen: BytecodeGenerator, clinit: JExtendedCode) {
import codegen._
val creatorType = javaType(AndroidCreatorClass)
jclass.addNewField(PublicStaticFinal,
@@ -53,4 +62,5 @@ trait GenAndroid {
new JMethodType(creatorType, Array()))
clinit.emitPUTSTATIC(jclass.getName(), fieldName, creatorType)
}
+
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 18f82d51be..df0220ffe3 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -1,5 +1,5 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2010 LAMP/EPFL
+ * Copyright 2005-2011 LAMP/EPFL
* @author Iulian Dragos
*/
@@ -7,9 +7,11 @@
package scala.tools.nsc
package backend.jvm
+import java.io.DataOutputStream
import java.nio.ByteBuffer
import scala.collection.{ mutable, immutable }
import mutable.{ ListBuffer, LinkedHashSet }
+import scala.reflect.generic.{ PickleFormat, PickleBuffer }
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.symtab._
import scala.tools.nsc.symtab.classfile.ClassfileConstants._
@@ -17,8 +19,6 @@ import scala.tools.nsc.symtab.classfile.ClassfileConstants._
import ch.epfl.lamp.fjbg._
import JAccessFlags._
import JObjectType.{ JAVA_LANG_STRING, JAVA_LANG_OBJECT }
-import java.io.{ DataOutputStream }
-import reflect.generic.{ PickleFormat, PickleBuffer }
/** This class ...
*
@@ -91,7 +91,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid {
def label = if (ok) "[ OK ] " else "[BAD!] "
if (settings.verbose.value || !ok)
- Console.println(label + sym + " in " + sym.owner.skipPackageObject.fullName + "\n " + sig)
+ println(label + sym + " in " + sym.owner.skipPackageObject.fullName + "\n " + sig)
}
val MIN_SWITCH_DENSITY = 0.7
@@ -194,7 +194,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid {
val sigBytes = ScalaSigBytes(pickle.bytes.take(pickle.writeIndex))
AnnotationInfo(sigBytes.sigAnnot, Nil, List((nme.bytes, sigBytes)))
}
- pickledBytes = pickledBytes + pickle.writeIndex
+ pickledBytes += pickle.writeIndex
currentRun.symData -= sym
currentRun.symData -= sym.companionSymbol
Some(scalaAnnot)
@@ -212,9 +212,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid {
private val innerClassBuffer = new ListBuffer[Symbol]
def genClass(c: IClass) {
- val needsEnclosingMethod: Boolean =
- c.symbol.isClass && (c.symbol.originalEnclosingMethod != NoSymbol)
-
clasz = c
innerClassBuffer.clear()
@@ -294,23 +291,34 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid {
val ssa = scalaSignatureAddingMarker(jclass, c.symbol)
addGenericSignature(jclass, c.symbol, c.symbol.owner)
addAnnotations(jclass, c.symbol.annotations ++ ssa)
- if (needsEnclosingMethod) addEnclosingMethodAttribute(jclass, c.symbol)
+ addEnclosingMethodAttribute(jclass, c.symbol)
emitClass(jclass, c.symbol)
if (c.symbol hasAnnotation BeanInfoAttr)
genBeanInfoClass(c)
}
- def addEnclosingMethodAttribute(jclass: JClass, clazz: Symbol) {
+ private def addEnclosingMethodAttribute(jclass: JClass, clazz: Symbol) {
val sym = clazz.originalEnclosingMethod
if (sym.isMethod) {
- log("enclosing method for %s is %s".format(clazz, sym))
+ log("enclosing method for %s is %s (%s)".format(clazz, sym, sym.enclClass))
jclass addAttribute fjbgContext.JEnclosingMethodAttribute(
jclass,
javaName(sym.enclClass),
javaName(sym),
javaType(sym)
)
+ } else if (clazz.isAnonymousClass) {
+ val enclClass = clazz.rawowner
+ assert(enclClass.isClass)
+ val sym = enclClass.primaryConstructor
+ log("enclosing method for %s is %s (%s)".format(clazz, sym, enclClass))
+ jclass addAttribute fjbgContext.JEnclosingMethodAttribute(
+ jclass,
+ javaName(enclClass),
+ javaName(sym),
+ JMethodType.ARGLESS_VOID_FUNCTION
+ )
}
}
@@ -601,7 +609,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid {
* That means non-member classes (anonymous). See Section 4.7.5 in the JVMS.
*/
def outerName(innerSym: Symbol): String = {
- if (innerSym.isAnonymousClass || innerSym.isAnonymousFunction || innerSym.originalEnclosingMethod != NoSymbol)
+ if (innerSym.originalEnclosingMethod != NoSymbol)
null
else {
val outerName = javaName(innerSym.rawowner)
@@ -629,19 +637,16 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid {
// to satisfy the Eclipse Java compiler
//for (innerSym <- innerClasses.toList sortBy (_.name.length)) {
for (innerSym <- allInners.distinct sortBy (_.name.length)) {
- val outer = outerName(innerSym)
- if (outer != null) {
- var flags = javaFlags(innerSym)
- if (innerSym.rawowner.hasModuleFlag)
- flags |= ACC_STATIC
-
- innerClassesAttr.addEntry(
- javaName(innerSym),
- outer,
- innerName(innerSym),
- (flags & INNER_CLASSES_FLAGS)
- )
- }
+ var flags = javaFlags(innerSym)
+ if (innerSym.rawowner.hasModuleFlag)
+ flags |= ACC_STATIC
+
+ innerClassesAttr.addEntry(
+ javaName(innerSym),
+ outerName(innerSym),
+ innerName(innerSym),
+ flags & INNER_CLASSES_FLAGS
+ )
}
}
}
@@ -729,7 +734,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid {
genCode(m)
if (emitVars)
- genLocalVariableTable(m, jcode);
+ genLocalVariableTable(m, jcode)
}
addGenericSignature(jmethod, m.symbol, clasz.symbol)
@@ -1142,7 +1147,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid {
else
jcode.emitGETSTATIC(javaName(module) /* + "$" */ ,
nme.MODULE_INSTANCE_FIELD.toString,
- javaType(module));
+ javaType(module))
case STORE_ARRAY_ITEM(kind) =>
jcode emitASTORE javaType(kind)
@@ -1283,7 +1288,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid {
case JUMP(whereto) =>
if (nextBlock != whereto)
- jcode.emitGOTO_maybe_W(labels(whereto), false); // default to short jumps
+ jcode.emitGOTO_maybe_W(labels(whereto), false) // default to short jumps
case CJUMP(success, failure, cond, kind) =>
kind match {
@@ -1594,12 +1599,12 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid {
case Conversion(src, dst) =>
if (settings.debug.value)
- log("Converting from: " + src + " to: " + dst);
+ log("Converting from: " + src + " to: " + dst)
if (dst == BOOL) {
- Console.println("Illegal conversion at: " + clasz +
- " at: " + pos.source + ":" + pos.line);
+ println("Illegal conversion at: " + clasz +
+ " at: " + pos.source + ":" + pos.line)
} else
- jcode.emitT2T(javaType(src), javaType(dst));
+ jcode.emitT2T(javaType(src), javaType(dst))
case ArrayLength(_) =>
jcode.emitARRAYLENGTH()
@@ -1657,11 +1662,11 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid {
val lvTab = ByteBuffer.allocate(2 + 10 * entries)
def emitEntry(name: String, signature: String, idx: Short, start: Short, end: Short) {
- lvTab.putShort(start)
- lvTab.putShort(end)
- lvTab.putShort(pool.addUtf8(name).toShort)
- lvTab.putShort(pool.addUtf8(signature).toShort)
- lvTab.putShort(idx)
+ lvTab putShort start
+ lvTab putShort end
+ lvTab putShort pool.addUtf8(name).toShort
+ lvTab putShort pool.addUtf8(signature).toShort
+ lvTab putShort idx
}
lvTab.putShort(entries.toShort)
@@ -1684,7 +1689,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid {
}
val attr =
fjbgContext.JOtherAttribute(jclass,
- jmethod,
+ jcode,
tpnme.LocalVariableTableATTR.toString,
lvTab.array())
jcode addAttribute attr
@@ -1704,7 +1709,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid {
}
def indexOf(m: IMethod, sym: Symbol): Int = {
- val Some(local) = m.lookupLocal(sym)
+ val Some(local) = m lookupLocal sym
indexOf(local)
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala
index 13c802b2e4..5700236062 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala
@@ -1,5 +1,5 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2010 LAMP/EPFL
+ * Copyright 2005-2011 LAMP/EPFL
* @author Iulian Dragos
*/
@@ -7,18 +7,9 @@
package scala.tools.nsc
package backend.jvm
-import java.nio.ByteBuffer
-
import scala.collection.{ mutable, immutable }
-import scala.tools.nsc.io.AbstractFile
-import scala.tools.nsc.symtab._
-import scala.tools.nsc.symtab.classfile.ClassfileConstants._
import ch.epfl.lamp.fjbg._
-import JAccessFlags._
-import JObjectType.{ JAVA_LANG_STRING, JAVA_LANG_OBJECT }
-import java.io.{ DataOutputStream }
-import reflect.generic.{ PickleFormat, PickleBuffer }
trait GenJVMUtil {
self: GenJVM =>
@@ -158,4 +149,4 @@ trait GenJVMUtil {
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
index d5bb6e0f88..cd38a2a4a7 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
@@ -1,15 +1,15 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2010 LAMP/EPFL
+ * Copyright 2005-2011 LAMP/EPFL
* @author Iulian Dragos
*/
package scala.tools.nsc
-package backend.opt;
+package backend.opt
-import scala.collection.mutable.{Map, HashMap};
-import scala.tools.nsc.backend.icode.analysis.LubException;
-import scala.tools.nsc.symtab._;
+import scala.collection.mutable.{Map, HashMap}
+import scala.tools.nsc.backend.icode.analysis.LubException
+import scala.tools.nsc.symtab._
/**
* @author Iulian Dragos
@@ -29,10 +29,7 @@ abstract class ClosureElimination extends SubComponent {
def peep(bb: BasicBlock, i1: Instruction, i2: Instruction) = (i1, i2) match {
case (CONSTANT(c), DROP(_)) =>
- if (c.tag == UnitTag)
- Some(List(i2))
- else
- Some(Nil);
+ if (c.tag == UnitTag) Some(List(i2)) else Some(Nil)
case (LOAD_LOCAL(x), STORE_LOCAL(y)) =>
if (x eq y) Some(Nil) else None
@@ -64,7 +61,7 @@ abstract class ClosureElimination extends SubComponent {
if (isStatic)
Some(Nil)
else
- Some(DROP(REFERENCE(definitions.ObjectClass)) :: Nil);
+ Some(DROP(REFERENCE(definitions.ObjectClass)) :: Nil)
case _ => None
}
@@ -78,7 +75,7 @@ abstract class ClosureElimination extends SubComponent {
val closser = new ClosureElim
override def apply(c: IClass): Unit =
- closser.analyzeClass(c)
+ closser analyzeClass c
}
/**
@@ -89,12 +86,11 @@ abstract class ClosureElimination extends SubComponent {
*/
class ClosureElim {
def analyzeClass(cls: IClass): Unit = if (settings.Xcloselim.value) {
- cls.methods.foreach { m =>
+ cls.methods foreach { m =>
analyzeMethod(m)
- peephole(m);
+ peephole(m)
}}
-
val cpp = new copyPropagation.CopyAnalysis
import copyPropagation._
@@ -111,7 +107,7 @@ abstract class ClosureElimination extends SubComponent {
for (i <- bb) {
i match {
- case LOAD_LOCAL(l) if (info.bindings.isDefinedAt(LocalVar(l))) =>
+ case LOAD_LOCAL(l) if info.bindings isDefinedAt LocalVar(l) =>
val t = info.getBinding(l)
t match {
case Deref(LocalVar(_)) | Deref(This) | Const(_) =>
@@ -119,7 +115,7 @@ abstract class ClosureElimination extends SubComponent {
log("replaced " + i + " with " + t)
case _ =>
- bb.replaceInstruction(i, LOAD_LOCAL(info.getAlias(l)));
+ bb.replaceInstruction(i, LOAD_LOCAL(info.getAlias(l)))
log("replaced " + i + " with " + info.getAlias(l))
}
@@ -132,23 +128,23 @@ abstract class ClosureElimination extends SubComponent {
bb.replaceInstruction(i,
DROP(REFERENCE(cls)) :: valueToInstruction(v) :: Nil);
log("Replaced " + i + " with " + info.getFieldNonRecordValue(r, f));
- case None => ();
+ case None =>
}
}
info.stack(0) match {
- case r @ Record(_, bindings) if bindings.isDefinedAt(f) =>
+ case r @ Record(_, bindings) if bindings isDefinedAt f =>
replaceFieldAccess(r)
case Deref(LocalVar(l)) =>
info.getBinding(l) match {
- case r @ Record(_, bindings) if bindings.isDefinedAt(f) =>
+ case r @ Record(_, bindings) if bindings isDefinedAt f =>
replaceFieldAccess(r)
case _ =>
}
case Deref(Field(r1, f1)) =>
info.getFieldValue(r1, f1) match {
- case Some(r @ Record(_, bindings)) if bindings.isDefinedAt(f) =>
+ case Some(r @ Record(_, bindings)) if bindings isDefinedAt f =>
replaceFieldAccess(r)
case _ =>
}
@@ -158,7 +154,7 @@ abstract class ClosureElimination extends SubComponent {
case UNBOX(_) =>
info.stack match {
- case Deref(LocalVar(loc1)) :: _ if (info.bindings.isDefinedAt(LocalVar(loc1))) =>
+ case Deref(LocalVar(loc1)) :: _ if info.bindings isDefinedAt LocalVar(loc1) =>
val value = info.getBinding(loc1)
value match {
case Boxed(LocalVar(loc2)) =>
@@ -172,10 +168,9 @@ abstract class ClosureElimination extends SubComponent {
bb.replaceInstruction(i, DROP(icodes.ObjectReference) :: valueToInstruction(Deref(LocalVar(loc2))) :: Nil)
log("replaced " + i + " with " + LocalVar(loc2))
case _ =>
- ()
}
- case _ => ();
+ case _ =>
}
info = cpp.interpret(info, i)
}
@@ -225,31 +220,31 @@ abstract class ClosureElimination extends SubComponent {
}
def transformBlock(b: BasicBlock): Unit = if (b.size >= 2) {
- var newInstructions: List[Instruction] = Nil;
+ var newInstructions: List[Instruction] = Nil
newInstructions = b.toList
var redo = false
do {
- var h = newInstructions.head;
- var t = newInstructions.tail;
- var seen: List[Instruction] = Nil;
- redo = false;
+ var h = newInstructions.head
+ var t = newInstructions.tail
+ var seen: List[Instruction] = Nil
+ redo = false
while (t != Nil) {
peep(b, h, t.head) match {
case Some(newInstrs) =>
newInstructions = seen.reverse ::: newInstrs ::: t.tail;
- redo = true;
+ redo = true
case None =>
()
}
- seen = h :: seen;
- h = t.head;
+ seen = h :: seen
+ h = t.head
t = t.tail
}
} while (redo);
- b.fromList(newInstructions)
+ b fromList newInstructions
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index 0db14d5e59..66dc3c78b2 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -1,5 +1,5 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2010 LAMP/EPFL
+ * Copyright 2005-2011 LAMP/EPFL
* @author Iulian Dragos
*/
@@ -113,7 +113,7 @@ abstract class Inliners extends SubComponent {
override def default(k: Symbol) = 0
}
- def analyzeMethod(m: IMethod): Unit = {
+ def analyzeMethod(m: IMethod) {
var sizeBeforeInlining = if (m.code ne null) m.code.blocks.length else 0
var instrBeforeInlining = if (m.code ne null) m.code.blocks.foldLeft(0)(_ + _.length) else 0
var retry = false
@@ -240,6 +240,7 @@ abstract class Inliners extends SubComponent {
case nme.foreach | nme.filter | nme.withFilter | nme.map | nme.flatMap => true
case _ => false
}
+
private def isHigherOrderMethod(sym: Symbol) =
sym.isMethod && atPhase(currentRun.erasurePhase.prev)(sym.info.paramTypes exists isFunctionType)
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index c170469016..934622bea0 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -1,5 +1,5 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2010 LAMP/EPFL
+ * Copyright 2005-2011 LAMP/EPFL
* @author Martin Odersky
*/
@@ -1196,13 +1196,17 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
else packSym
}
- /** Return the original enclosing method of this symbol. It
- * should return the same thing as enclMethod when called before
- * lambda lift, but it preserves the original nesting when called afterwards.
+ /** Return the original enclosing method of this symbol. It should return
+ * the same thing as enclMethod when called before lambda lift,
+ * but it preserves the original nesting when called afterwards.
*/
def originalEnclosingMethod: Symbol = {
if (isMethod) this
- else originalOwner.getOrElse(this, rawowner).originalEnclosingMethod
+ else {
+ val owner = originalOwner.getOrElse(this, rawowner)
+ if (isLocalDummy) owner.enclClass.primaryConstructor
+ else owner.originalEnclosingMethod
+ }
}
/** The top-level class containing this symbol */
@@ -1260,16 +1264,19 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
else NoSymbol
}
- /** A helper method that factors the common code used the discover a companion module of a class.
- * If a companion module exists, its symbol is returned, otherwise, `NoSymbol` is returned.
- * The method assumes that `this` symbol has already been checked to be a class (using `isClass`).
+ /** A helper method that factors the common code used the discover a
+ * companion module of a class. If a companion module exists, its symbol is
+ * returned, otherwise, `NoSymbol` is returned. The method assumes that
+ * `this` symbol has already been checked to be a class (using `isClass`).
*
- * After refchecks nested objects get transformed to lazy vals so we filter on LAZY flag as well.
- * @note The resident compiler may run many times over, and symbols may be reused. Therefore, a
- * module symbol that has been translated to a lazy val by refchecks is not guaranteed to
- * have MODULE set on the next run (even before refcheck). Flags are not part of symbol
- * history. Instead we rely on the fact that a synthetic lazy value must have been a
- * module.
+ * After refchecks nested objects get transformed to lazy vals so we
+ * filter on LAZY flag as well.
+ * @note The resident compiler may run many times over, and symbols may be
+ * reused. Therefore, a module symbol that has been translated to a
+ * lazy val by refchecks is not guaranteed to have MODULE set on the
+ * next run (even before refcheck). Flags are not part of symbol
+ * history. Instead we rely on the fact that a synthetic lazy value
+ * must have been a module.
*/
private final def companionModule0: Symbol = {
def isSyntheticLazy(sym: Symbol) =
@@ -1310,8 +1317,8 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
if (isModuleClass) companionClass else companionModule.moduleClass
/**
- * Returns the rawInfo of the owner. If the current phase has flat classes, it first
- * applies all pending type maps to this symbol.
+ * Returns the rawInfo of the owner. If the current phase has flat classes,
+ * it first applies all pending type maps to this symbol.
*
* assume this is the ModuleSymbol for B in the following definition:
* package p { class A { object B { val x = 1 } } }
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala
index 9c6b4531d4..bc155d4e88 100644
--- a/src/library/scala/collection/TraversableLike.scala
+++ b/src/library/scala/collection/TraversableLike.scala
@@ -19,8 +19,8 @@ import annotation.unchecked.{ uncheckedVariance => uV }
* $traversableInfo
* @define mutability
* @define traversableInfo
- * This is a base trait of all kinds of $mutability Scala collections. It implements
- * the behavior common to all collections, in terms of a method
+ * This is a base trait of all kinds of $mutability Scala collections. It
+ * implements the behavior common to all collections, in terms of a method
* `foreach` with signature:
* {{{
* def foreach[U](f: Elem => U): Unit
@@ -69,8 +69,8 @@ import annotation.unchecked.{ uncheckedVariance => uV }
* depends on the element type `B` being admissible for that class,
* which means that an implicit instance of type `CanBuildFrom[Repr, B, That]`
* is found.
- * @define bfinfo an implicit value of class `CanBuildFrom` which determines the
- * result class `That` from the current representation type `Repr` and
+ * @define bfinfo an implicit value of class `CanBuildFrom` which determines
+ * the result class `That` from the current representation type `Repr` and
* and the new element type `B`.
* @define orderDependent
*
@@ -97,7 +97,8 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
protected type Self = Repr
/** The collection of type $coll underlying this `TraversableLike` object.
- * By default this is implemented as the `TraversableLike` object itself, but this can be overridden.
+ * By default this is implemented as the `TraversableLike` object itself,
+ * but this can be overridden.
*/
def repr: Repr = this.asInstanceOf[Repr]
@@ -170,10 +171,10 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
* @tparam B the element type of the returned collection.
* @tparam That $thatinfo
* @param bf $bfinfo
- * @return a new collection of type `That` which contains all elements of this $coll
- * followed by all elements of `that`.
+ * @return a new collection of type `That` which contains all elements
+ * of this $coll followed by all elements of `that`.
*
- * @usecase def ++(that: TraversableOnce[A]): $Coll[A]
+ * @usecase def ++[B](that: TraversableOnce[B]): $Coll[B]
*
* @return a new $coll which contains all elements of this $coll
* followed by all elements of `that`.
@@ -186,18 +187,18 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
b.result
}
- /** Concatenates this $coll with the elements of a traversable collection. It
- * differs from ++ in that the right operand determines the type of the resulting
- * collection rather than the left one.
+ /** Concatenates this $coll with the elements of a traversable collection.
+ * It differs from ++ in that the right operand determines the type of the
+ * resulting collection rather than the left one.
*
* @param that the traversable to append.
* @tparam B the element type of the returned collection.
* @tparam That $thatinfo
* @param bf $bfinfo
- * @return a new collection of type `That` which contains all elements of this $coll
- * followed by all elements of `that`.
+ * @return a new collection of type `That` which contains all elements
+ * of this $coll followed by all elements of `that`.
*
- * @usecase def ++(that: TraversableOnce[A]): $Coll[A]
+ * @usecase def ++:[B](that: TraversableOnce[B]): $Coll[B]
*
* @return a new $coll which contains all elements of this $coll
* followed by all elements of `that`.
@@ -304,8 +305,8 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
b.result
}
- /** Builds a new collection by applying an option-valued function to all elements of this $coll
- * on which the function is defined.
+ /** Builds a new collection by applying an option-valued function to all
+ * elements of this $coll on which the function is defined.
*
* @param f the option-valued function which filters and maps the $coll.
* @tparam B the element type of the returned collection.
@@ -398,8 +399,8 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
* $mayNotTerminateInf
*
* @param p the predicate used to test elements.
- * @return `true` if the given predicate `p` holds for some of the elements
- * of this $coll, otherwise `false`.
+ * @return `true` if the given predicate `p` holds for some of the
+ * elements of this $coll, otherwise `false`.
*/
def exists(p: A => Boolean): Boolean = {
var result = false
@@ -429,7 +430,9 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
}
/**
- * Produces a collection containing cummulative results of applying the operator going left to right.
+ * Produces a collection containing cummulative results of applying the
+ * operator going left to right.
+ *
* $willNotTerminateInf
* $orderDependent
*
@@ -506,7 +509,8 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
/** Selects the last element.
* $orderDependent
* @return The last element of this $coll.
- * @throws NoSuchElementException If the $coll is empty. */
+ * @throws NoSuchElementException If the $coll is empty.
+ */
def last: A = {
var lst = head
for (x <- this)
@@ -543,8 +547,8 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
/** Selects first ''n'' elements.
* $orderDependent
* @param n Tt number of elements to take from this $coll.
- * @return a $coll consisting only of the first `n` elements of this $coll, or else the
- * whole $coll, if it has less than `n` elements.
+ * @return a $coll consisting only of the first `n` elements of this $coll,
+ * or else the whole $coll, if it has less than `n` elements.
*/
def take(n: Int): Repr = {
val b = newBuilder
@@ -638,8 +642,8 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
/** Splits this $coll into a prefix/suffix pair according to a predicate.
*
* Note: `c span p` is equivalent to (but possibly more efficient than)
- * `(c takeWhile p, c dropWhile p)`, provided the evaluation of the predicate `p`
- * does not cause any side-effects.
+ * `(c takeWhile p, c dropWhile p)`, provided the evaluation of the
+ * predicate `p` does not cause any side-effects.
* $orderDependent
*
* @param p the test predicate
@@ -728,6 +732,7 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
def toStream: Stream[A] = toBuffer.toStream
/** Converts this $coll to a string.
+ *
* @return a string representation of this collection. By default this
* string consists of the `stringPrefix` of this $coll,
* followed by all elements separated by commas and enclosed in parentheses.
@@ -735,8 +740,10 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
override def toString = mkString(stringPrefix + "(", ", ", ")")
/** Defines the prefix of this object's `toString` representation.
- * @return a string representation which starts the result of `toString` applied to this $coll.
- * By default the string prefix is the simple name of the collection class $coll.
+ *
+ * @return a string representation which starts the result of `toString`
+ * applied to this $coll. By default the string prefix is the
+ * simple name of the collection class $coll.
*/
def stringPrefix : String = {
var string = repr.asInstanceOf[AnyRef].getClass.getName
@@ -774,8 +781,9 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
/** Creates a non-strict filter of this $coll.
*
* Note: the difference between `c filter p` and `c withFilter p` is that
- * the former creates a new collection, whereas the latter only restricts
- * the domain of subsequent `map`, `flatMap`, `foreach`, and `withFilter` operations.
+ * the former creates a new collection, whereas the latter only
+ * restricts the domain of subsequent `map`, `flatMap`, `foreach`,
+ * and `withFilter` operations.
* $orderDependent
*
* @param p the predicate used to test elements.
@@ -786,8 +794,8 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
*/
def withFilter(p: A => Boolean): FilterMonadic[A, Repr] = new WithFilter(p)
- /** A class supporting filtered operations. Instances of this class are returned by
- * method `withFilter`.
+ /** A class supporting filtered operations. Instances of this class are
+ * returned by method `withFilter`.
*/
class WithFilter(p: A => Boolean) extends FilterMonadic[A, Repr] {
@@ -798,15 +806,15 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
* @tparam B the element type of the returned collection.
* @tparam That $thatinfo
* @param bf $bfinfo
- * @return a new collection of type `That` resulting from applying the given function
- * `f` to each element of the outer $coll that satisfies predicate `p`
- * and collecting the results.
+ * @return a new collection of type `That` resulting from applying
+ * the given function `f` to each element of the outer $coll
+ * that satisfies predicate `p` and collecting the results.
*
* @usecase def map[B](f: A => B): $Coll[B]
*
* @return a new $coll resulting from applying the given function
- * `f` to each element of the outer $coll that satisfies predicate `p`
- * and collecting the results.
+ * `f` to each element of the outer $coll that satisfies
+ * predicate `p` and collecting the results.
*/
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
val b = bf(repr)
@@ -816,14 +824,17 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
}
/** Builds a new collection by applying a function to all elements of the
- * outer $coll containing this `WithFilter` instance that satisfy predicate `p` and concatenating the results.
+ * outer $coll containing this `WithFilter` instance that satisfy
+ * predicate `p` and concatenating the results.
*
* @param f the function to apply to each element.
* @tparam B the element type of the returned collection.
* @tparam That $thatinfo
* @param bf $bfinfo
- * @return a new collection of type `That` resulting from applying the given collection-valued function
- * `f` to each element of the outer $coll that satisfies predicate `p` and concatenating the results.
+ * @return a new collection of type `That` resulting from applying
+ * the given collection-valued function `f` to each element
+ * of the outer $coll that satisfies predicate `p` and
+ * concatenating the results.
*
* @usecase def flatMap[B](f: A => TraversableOnce[B]): $Coll[B]
*
@@ -837,8 +848,8 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
b.result
}
- /** Applies a function `f` to all elements of the outer $coll containing this `WithFilter` instance
- * that satisfy predicate `p`.
+ /** Applies a function `f` to all elements of the outer $coll containing
+ * this `WithFilter` instance that satisfy predicate `p`.
*
* @param f the function that is applied for its side-effect to every element.
* The result of function `f` is discarded.
diff --git a/test/files/jvm/cf-attributes.check b/test/files/jvm/cf-attributes.check
new file mode 100644
index 0000000000..018febb81b
--- /dev/null
+++ b/test/files/jvm/cf-attributes.check
@@ -0,0 +1,50 @@
+
+{{ anonymousFunctions$ }}
+
+{{ anonymousFunctions$bar$ }}
+ public final class anonymousFunctions$bar$$anonfun$4 of class anonymousFunctions$bar$
+anonymousClasses$$anon$1
+
+{{ anonymousClasses$ }}
+
+[[ anonymousFunctions$ ]]
+ InnerClass:
+ public final #66 of #90; //class anonymousFunctions$$anonfun$1 of class anonymousFunctions
+ public final #77; //class anonymousFunctions$$anonfun$2
+ public final #24; //class anonymousFunctions$$anonfun$3
+ public final #49; //class anonymousFunctions$$anonfun$foo$1
+
+
+[[ anonymousFunctions$bar$ ]]
+ InnerClass:
+ public final #28 of #9; //class anonymousFunctions$bar$$anonfun$4 of class anonymousFunctions$bar$
+ public final #52; //class anonymousFunctions$bar$$anonfun$5
+
+
+[[ anonymousClasses$ ]]
+ InnerClass:
+ public abstract #33= #30 of #32; //Foo=class anonymousClasses$Foo of class anonymousClasses
+ public final #25 of #32; //class anonymousClasses$$anon$1 of class anonymousClasses
+ public abstract #36= #35 of #32; //Foo$class=class anonymousClasses$Foo$class of class anonymousClasses
+
+
+[[ anonymousFunctions$$anonfun$3 ]]
+ InnerClass:
+ public final #8; //class anonymousFunctions$$anonfun$3
+
+
+[[ anonymousFunctions$$anonfun$foo$1 ]]
+ InnerClass:
+ public final #8; //class anonymousFunctions$$anonfun$foo$1
+
+
+[[ anonymousFunctions$bar$$anonfun$4 ]]
+ InnerClass:
+ public final #8 of #41; //class anonymousFunctions$bar$$anonfun$4 of class anonymousFunctions$bar$
+
+
+[[ anonymousClasses$$anon$1 ]]
+ InnerClass:
+ public abstract #46= #43 of #45; //Foo=class anonymousClasses$Foo of class anonymousClasses
+ public final #48 of #45; //class anonymousClasses$$anon$1 of class anonymousClasses
+
diff --git a/test/files/jvm/cf-attributes.scala b/test/files/jvm/cf-attributes.scala
new file mode 100644
index 0000000000..b5dd7eb386
--- /dev/null
+++ b/test/files/jvm/cf-attributes.scala
@@ -0,0 +1,146 @@
+object Test extends Application {
+ InnerClassTest1
+ InnerClassTest2
+}
+
+object InnerClassTest1 extends Test1 {
+ printClass(anonymousFunctions.getClass)
+ printClass(anonymousFunctions.bar.getClass)
+ println(anonymousClasses.x) // see run/t1167.scala
+ printClass(anonymousClasses.getClass)
+}
+
+object InnerClassTest2 extends Test2 {
+ printClass(anonymousFunctions.getClass)
+ printClass(anonymousFunctions.bar.getClass)
+ printClass(anonymousClasses.getClass)
+ // not accessible via the Java reflection API
+ printClass("anonymousFunctions$$anonfun$3")
+ printClass("anonymousFunctions$$anonfun$foo$1")
+ printClass("anonymousFunctions$bar$$anonfun$4")
+ printClass("anonymousClasses$$anon$1")
+}
+
+object anonymousFunctions {
+ //InnerClass:
+ // public final #_ of #_; //class anonymousFunctions$$anonfun$1 of class InnerClass$
+ val twice = (x: Int) => 2*x
+
+ //InnerClass:
+ // public final #_ of #_; //class anonymousFunctions$$anonfun$2
+ List(0).map(x => x+1)
+
+ def foo {
+ //InnerClass:
+ // public final #_ of #_; class anonymousFunctions$$anonfun$3
+ val square = (x: Int) => x*x
+
+ //InnerClass:
+ // public final #_ of #_; class anonymousFunctions$$anonfun$foo$1
+ Array(1).filter(_ % 2 == 0)
+ }
+
+ object bar {
+ //InnerClass:
+ // public final #_ of #_; class anonymousFunctions$bar$$anonfun$4 of class anonymousFunctions$bar$
+ val cube = (x: Int) => x*x*x
+
+ //InnerClass:
+ // public final #_ of #_; class anonymousFunctions$bar$$anonfun$5
+ Set(1, 2, 3).exists(_ == 2)
+ }
+}
+
+object anonymousClasses {
+ //InnerClass:
+ // public abstract #_= #_ of #_; //Foo=class anonymousClasses$Foo of class anonymousClasses$
+ // public abstract #_= #_ of #_; //Foo$class=class anonymousClasses$Foo$class of class anonymousClasses$
+ trait Foo {
+ def foo() { println("foo"); }
+ override def toString = getClass.getName
+ }
+ //InnerClass:
+ // public final #_; //class anonymousClasses$$anon$1 of class anonymousClasses$
+ val x = new Foo() {
+ override def foo() { println("foo (overriden)"); }
+ def dummy = 0
+ }
+}
+
+// Auxiliary functions
+
+trait Test1 {
+ private var kind: String = _
+ private var mods: String = _
+ def printInnerClasses(cls: Class[_]) {
+ for (c <- cls.getDeclaredClasses) {
+ mods = AccessFlags.asString(c.getModifiers)
+ kind = if (c.isInterface) "interface" else "class"
+ println(" "+mods+kind+" "+c.getName+
+ " of class "+c.getEnclosingClass.getName)
+ }
+ }
+ def printClass(cls: Class[_]) {
+ println("\n{{ "+cls.getName+" }}")
+ printInnerClasses(cls)
+ }
+}
+
+trait Test2 {
+ @throws(classOf[Exception])
+ def printInnerClasses(cls: Class[_]) {
+ import java.io._, ch.epfl.lamp.fjbg._
+ val fjbgContext = new FJBGContext(49, 0)
+ val outDir = System.getProperty("partest.output", "cf-attributes.obj")
+ val fileName = outDir+File.separator+cls.getName+".class"
+ val in = new DataInputStream(new FileInputStream(fileName))
+ val jclass = fjbgContext.JClass(in)
+ println(jclass.getInnerClasses)
+ in.close()
+ }
+ def printClass(name: String) {
+ try { printClass(Class.forName(name)) }
+ catch { case e: Exception => println(e) }
+ }
+ def printClass(cls: Class[_]) {
+ println("\n[[ "+cls.getName+" ]]");
+ try { printInnerClasses(cls) }
+ catch { case e: Exception => println(e) }
+ }
+}
+
+object AccessFlags {
+ val ACC_PUBLIC = 0x0001
+ val ACC_PRIVATE = 0x0002
+ val ACC_PROTECTED = 0x0004
+ val ACC_STATIC = 0x0008
+ val ACC_FINAL = 0x0010
+ val ACC_ABSTRACT = 0x0400
+
+ def asString(accessFlags: Int): String = {
+ val buf = new StringBuilder()
+ if ((accessFlags & ACC_PUBLIC) != 0) buf.append("public ")
+ else if ((accessFlags & ACC_PROTECTED) != 0) buf.append("protected ")
+ else if ((accessFlags & ACC_PRIVATE) != 0) buf.append("private ")
+ if ((accessFlags & ACC_ABSTRACT) != 0) buf.append("abstract ")
+ else if ((accessFlags & ACC_FINAL) != 0) buf.append("final ")
+ buf.toString
+ }
+}
+
+/*
+ implicit def stringToLines(s: String) = new {
+ def lines(n: Int): String = {
+ val buf = new StringBuilder();
+ var i = 0
+ var from = 0
+ while (i < n && 0 <= from && from < s.length) {
+ val pos = s.indexOf('\n', from)
+ if (pos >= 0) { i += 1; buf.append(s.substring(from, pos + 1)); }
+ from = pos + 1
+ }
+ buf.toString()
+ }
+ }
+*/
+
diff --git a/test/files/run/t1167.check b/test/files/run/t1167.check
index 41e4dc4b70..06fedebe71 100644
--- a/test/files/run/t1167.check
+++ b/test/files/run/t1167.check
@@ -1,3 +1,3 @@
-Test$$anon$1
-Test$$anon$2
+anon$1
+anon$2
$anonfun$testFunc$1
diff --git a/test/files/run/t1167.scala b/test/files/run/t1167.scala
index 25e42ffd4d..7386d09a6c 100644
--- a/test/files/run/t1167.scala
+++ b/test/files/run/t1167.scala
@@ -8,6 +8,13 @@ trait Test1 {
}
}
+/* getName
+ * Returns the binary name of the class if this class object represents a
+ * reference type that is not an array type.
+ * getSimpleName
+ * Returns the simple name of the underlying class as given in the source
+ * code. Returns an empty string if the underlying class is anonymous.
+ */
abstract class Foo {
override def toString = getClass.getSimpleName