Skip to content

Commit

Permalink
Remove GenASM, merge remaining common code snippets
Browse files Browse the repository at this point in the history
With GenBCode being the default and only supported backend for Java 8,
we can get rid of GenASM.

This commit also fixes/migrates/moves to pending/deletes tests which
depended on GenASM before.
  • Loading branch information
soc committed Oct 27, 2015
1 parent 4321ea4 commit effe179
Show file tree
Hide file tree
Showing 94 changed files with 873 additions and 4,109 deletions.
8 changes: 0 additions & 8 deletions src/compiler/scala/tools/nsc/Global.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import transform._
import backend.icode.{ ICodes, GenICode, ICodeCheckers }
import backend.{ ScalaPrimitives, JavaPlatform }
import backend.jvm.GenBCode
import backend.jvm.GenASM
import backend.opt.{ Inliners, InlineExceptionHandlers, ConstantOptimization, ClosureElimination, DeadCodeElimination }
import backend.icode.analysis._
import scala.language.postfixOps
Expand Down Expand Up @@ -633,13 +632,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
val runsRightAfter = None
} with DeadCodeElimination

// phaseName = "jvm", ASM-based version
object genASM extends {
val global: Global.this.type = Global.this
val runsAfter = List("dce")
val runsRightAfter = None
} with GenASM

// phaseName = "bcode"
object genBCode extends {
val global: Global.this.type = Global.this
Expand Down
8 changes: 2 additions & 6 deletions src/compiler/scala/tools/nsc/backend/JavaPlatform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,9 @@ trait JavaPlatform extends Platform {
def updateClassPath(subst: Map[ClassPath[AbstractFile], ClassPath[AbstractFile]]) =
currentClassPath = Some(new DeltaClassPath(currentClassPath.get, subst))

private def classEmitPhase =
if (settings.isBCodeActive) genBCode
else genASM

def platformPhases = List(
flatten, // get rid of inner classes
classEmitPhase // generate .class files
flatten, // get rid of inner classes
genBCode // generate .class files
)

lazy val externalEquals = getDecl(BoxesRunTimeClass, nme.equals_)
Expand Down
476 changes: 0 additions & 476 deletions src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala

This file was deleted.

501 changes: 494 additions & 7 deletions src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
import global._
import bTypes._
import coreBTypes._
import bCodeAsmCommon._

/*
* There's a dedicated PlainClassBuilder for each CompilationUnit,
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ abstract class BTypes {
/**
* Obtain the BType for a type descriptor or internal name. For class descriptors, the ClassBType
* is constructed by parsing the corresponding classfile.
*
*
* Some JVM operations use either a full descriptor or only an internal name. Example:
* ANEWARRAY java/lang/String // a new array of strings (internal name for the String class)
* ANEWARRAY [Ljava/lang/String; // a new array of array of string (full descriptor for the String class)
Expand Down Expand Up @@ -932,7 +932,7 @@ abstract class BTypes {
// the static flag in the InnerClass table has a special meaning, see InnerClass comment
i.flags & ~Opcodes.ACC_STATIC,
if (isStaticNestedClass) Opcodes.ACC_STATIC else 0
) & BCodeAsmCommon.INNER_CLASSES_FLAGS
) & BCodeHelpers.INNER_CLASSES_FLAGS
)
})

Expand Down Expand Up @@ -1192,4 +1192,4 @@ object BTypes {
// no static way (without symbol table instance) to get to nme.ScalaATTR / ScalaSignatureATTR
val ScalaAttributeName = "Scala"
val ScalaSigAttributeName = "ScalaSig"
}
}
97 changes: 95 additions & 2 deletions src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,9 @@ import scala.tools.nsc.settings.ScalaSettings
class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
import global._
import definitions._
import genBCode._

val bCodeICodeCommon: BCodeICodeCommon[global.type] = new BCodeICodeCommon(global)
val bCodeAsmCommon: BCodeAsmCommon[global.type] = new BCodeAsmCommon(global)
import bCodeAsmCommon._

val backendUtils: BackendUtils[this.type] = new BackendUtils(this)

Expand Down Expand Up @@ -220,7 +219,101 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
assert(!primitiveTypeMap.contains(sym) || isCompilingPrimitive, sym)
}

def implementedInterfaces(classSym: Symbol): List[Symbol] = {
// Additional interface parents based on annotations and other cues
def newParentForAnnotation(ann: AnnotationInfo): Option[Type] = ann.symbol match {
case RemoteAttr => Some(RemoteInterfaceClass.tpe)
case _ => None
}

// SI-9393: java annotations are interfaces, but the classfile / java source parsers make them look like classes.
def isInterfaceOrTrait(sym: Symbol) = sym.isInterface || sym.isTrait || sym.hasJavaAnnotationFlag

val classParents = {
val parents = classSym.info.parents
// SI-9393: the classfile / java source parsers add Annotation and ClassfileAnnotation to the
// parents of a java annotations. undo this for the backend (where we need classfile-level information).
if (classSym.hasJavaAnnotationFlag) parents.filterNot(c => c.typeSymbol == ClassfileAnnotationClass || c.typeSymbol == AnnotationClass)
else parents
}

val allParents = classParents ++ classSym.annotations.flatMap(newParentForAnnotation)

// We keep the superClass when computing minimizeParents to eliminate more interfaces.
// Example: T can be eliminated from D
// trait T
// class C extends T
// class D extends C with T
val interfaces = erasure.minimizeParents(allParents) match {
case superClass :: ifs if !isInterfaceOrTrait(superClass.typeSymbol) =>
ifs
case ifs =>
// minimizeParents removes the superclass if it's redundant, for example:
// trait A
// class C extends Object with A // minimizeParents removes Object
ifs
}
interfaces.map(_.typeSymbol)
}

/**
* The member classes of a class symbol. Note that the result of this method depends on the
* current phase, for example, after lambdalift, all local classes become member of the enclosing
* class.
*
* Impl classes are always considered top-level, see comment in BTypes.
*/
private def memberClassesForInnerClassTable(classSymbol: Symbol): List[Symbol] = classSymbol.info.decls.collect({
case sym if sym.isClass && !considerAsTopLevelImplementationArtifact(sym) =>
sym
case sym if sym.isModule && !considerAsTopLevelImplementationArtifact(sym) => // impl classes get the lateMODULE flag in mixin
val r = exitingPickler(sym.moduleClass)
assert(r != NoSymbol, sym.fullLocationString)
r
})(collection.breakOut)

private def setClassInfo(classSym: Symbol, classBType: ClassBType): ClassBType = {
/**
* Reconstruct the classfile flags from a Java defined class symbol.
*
* The implementation of this method is slightly different from `javaFlags` in BTypesFromSymbols.
* The javaFlags method is primarily used to map Scala symbol flags to sensible classfile flags
* that are used in the generated classfiles. For example, all classes emitted by the Scala
* compiler have ACC_PUBLIC.
*
* When building a [[ClassBType]] from a Java class symbol, the flags in the type's `info` have
* to correspond exactly to the flags in the classfile. For example, if the class is package
* protected (i.e., it doesn't have the ACC_PUBLIC flag), this needs to be reflected in the
* ClassBType. For example, the inliner needs the correct flags for access checks.
*
* Class flags are listed here:
* https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.1-200-E.1
*/
def javaClassfileFlags(classSym: Symbol): Int = {
assert(classSym.isJava, s"Expected Java class symbol, got ${classSym.fullName}")
import asm.Opcodes._
def enumFlags = ACC_ENUM | {
// Java enums have the `ACC_ABSTRACT` flag if they have a deferred method.
// We cannot trust `hasAbstractFlag`: the ClassfileParser adds `ABSTRACT` and `SEALED` to all
// Java enums for exhaustiveness checking.
val hasAbstractMethod = classSym.info.decls.exists(s => s.isMethod && s.isDeferred)
if (hasAbstractMethod) ACC_ABSTRACT else 0
}
GenBCode.mkFlags(
// SI-9393: the classfile / java source parser make java annotation symbols look like classes.
// here we recover the actual classfile flags.
if (classSym.hasJavaAnnotationFlag) ACC_ANNOTATION | ACC_INTERFACE | ACC_ABSTRACT else 0,
if (classSym.isPublic) ACC_PUBLIC else 0,
if (classSym.isFinal) ACC_FINAL else 0,
// see the link above. javac does the same: ACC_SUPER for all classes, but not interfaces.
if (classSym.isInterface) ACC_INTERFACE else ACC_SUPER,
// for Java enums, we cannot trust `hasAbstractFlag` (see comment in enumFlags)
if (!classSym.hasJavaEnumFlag && classSym.hasAbstractFlag) ACC_ABSTRACT else 0,
if (classSym.isArtifact) ACC_SYNTHETIC else 0,
if (classSym.hasJavaEnumFlag) enumFlags else 0
)
}

// Check for isImplClass: trait implementation classes have NoSymbol as superClass
// Check for hasAnnotationFlag for SI-9393: the classfile / java source parsers add
// scala.annotation.Annotation as superclass to java annotations. In reality, java
Expand Down
Loading

0 comments on commit effe179

Please sign in to comment.