Skip to content

rewiring-dependencies on settings in the bytecode emitter #19

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 14, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 14 additions & 21 deletions src/dotty/tools/dotc/backend/jvm/BCodeHelpers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -209,26 +209,30 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
* must-single-thread
*/
def initBytecodeWriter(entryPoints: List[Symbol])(implicit ctx: Context): BytecodeWriter = {

import ctx.base.settings
import ctx.log

settings.outputDirs.getSingleOutput match {
case Some(f) if f hasExtension "jar" =>
// If no main class was specified, see if there's only one
// entry point among the classes going into the jar.
if (settings.mainClass.isDefault) {
entryPoints map (_.fullName('.')) match {
case Nil =>
ctx.log("No Main-Class designated or discovered.")
log("No Main-Class designated or discovered.")
case name :: Nil =>
ctx.log(s"Unique entry point: setting Main-Class to $name")
settings.mainClass.value = name
log(s"Unique entry point: setting Main-Class to $name")
settings.mainClass.update(name)
case names =>
ctx.log(s"No Main-Class due to multiple entry points:\n ${names.mkString("\n ")}")
log(s"No Main-Class due to multiple entry points:\n ${names.mkString("\n ")}")
}
}
else ctx.log(s"Main-Class was specified: ${settings.mainClass.value}")
else log(s"Main-Class was specified: ${settings.mainClass.value}")

new DirectToJarfileWriter(f.file)

case _ => factoryNonJarBytecodeWriter()
case _ => factoryNonJarBytecodeWriter(ctx)
}
}

Expand Down Expand Up @@ -295,17 +299,6 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {

} // end of method addInnerClassesASM()

/**
* All components (e.g. BCPickles, BCInnerClassGen) of the builder classes
* extend this trait to have access to the context.
*
* The context is provided by the three leaf classes (PlainClassBuilder,
* JMirrorBuilder and JBeanInfoBuilder) as class parameter.
*/
trait HasContext {
implicit protected val ctx: Context
}

/*
* Custom attribute (JVMS 4.7.1) "ScalaSig" used as marker only
* i.e., the pickle is contained in a custom annotation, see:
Expand Down Expand Up @@ -395,7 +388,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {

trait BCInnerClassGen extends HasContext {

def debugLevel = settings.debuginfo.indexOfChoice
def debugLevel = ctx.settings.g.indexOfChoice

val emitSource = debugLevel >= 1
val emitLines = debugLevel >= 2
Expand Down Expand Up @@ -797,7 +790,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
// without it. This is particularly bad because the availability of
// generic information could disappear as a consequence of a seemingly
// unrelated change.
settings.Ynogenericsig
ctx.settings.Ynogenericsig
|| sym.isArtifact
|| sym.isLiftedMethod
|| sym.isBridge
Expand Down Expand Up @@ -829,7 +822,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
catch { case _: Throwable => false }
}

if (settings.Xverify) {
if (ctx.settings.Xverify) {
// Run the signature parser to catch bogus signatures.
val isValidSignature = wrap {
// Alternative: scala.tools.reflect.SigParser (frontend to sun.reflect.generics.parser.SignatureParser)
Expand All @@ -849,7 +842,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
}
}

if ((settings.check containsName phaseName)) {
if ((ctx.settings.check containsName phaseName)) {
val normalizedTpe = enteringErasure(erasure.prepareSigMap(memberTpe))
val bytecodeTpe = owner.thisType.memberInfo(sym)
if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) {
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/backend/jvm/BCodeIdiomatic.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import core.Symbols.{Symbol, NoSymbol}
*/
abstract class BCodeIdiomatic extends BCodeGlue {

val classfileVersion: Int = settings.target.value match {
def classfileVersion(implicit ctx: Context): Int = ctx.settings.target.value match {
case "jvm-1.5" => asm.Opcodes.V1_5
case "jvm-1.6" => asm.Opcodes.V1_6
case "jvm-1.7" => asm.Opcodes.V1_7
Expand Down
4 changes: 2 additions & 2 deletions src/dotty/tools/dotc/backend/jvm/BCodeSkelBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {

} else {

val skipStaticForwarders = (claszSymbol.isInterface || settings.noForwarders)
val skipStaticForwarders = (claszSymbol.isInterface || ctx.settings.noForwarders)
if (!skipStaticForwarders) {
val lmoc = claszSymbol.companionModule
// add static forwarders if there are no name conflicts; see bugs #363 and #1735
Expand Down Expand Up @@ -605,7 +605,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
case Return(_) => ()
case EmptyTree =>
globalError("Concrete method has no definition: " + dd + (
if (settings.debug) "(found: " + methSymbol.owner.info.decls.toList.mkString(", ") + ")"
if (ctx.settings.debug) "(found: " + methSymbol.owner.info.decls.toList.mkString(", ") + ")"
else "")
)
case _ =>
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/backend/jvm/BCodeTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import StdNames.{nme, tpnme}
abstract class BCodeTypes extends BCodeIdiomatic {

// when compiling the Scala library, some assertions don't hold (e.g., scala.Boolean has null superClass although it's not an interface)
val isCompilingStdLib = !(settings.sourcepath.isDefault)
def isCompilingStdLib(implicit ctx: Context) = !(ctx.settings.sourcepath.isDefault)

val srBoxedUnit = brefType("scala/runtime/BoxedUnit")

Expand Down
32 changes: 17 additions & 15 deletions src/dotty/tools/dotc/backend/jvm/BytecodeWriters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import java.io.{ DataOutputStream, FileOutputStream, IOException, OutputStream,
import java.util.jar.Attributes.Name

import dotty.tools.io._
import core.Contexts.Context

/** Can't output a file due to the state of the file system. */
class FileConflictException(msg: String, val file: AbstractFile) extends IOException(msg)
Expand All @@ -22,8 +23,8 @@ class FileConflictException(msg: String, val file: AbstractFile) extends IOExcep
*/
trait BytecodeWriters {

def outputDirectory(sym: Symbol): AbstractFile =
settings.outputDirs outputDirFor enteringFlatten(sym.sourceFile)
def outputDirectory(sym: Symbol)(implicit ctx: Context): AbstractFile =
ctx.settings.outputDirs outputDirFor enteringFlatten(sym.sourceFile)

/**
* @param clsName cls.getName
Expand All @@ -40,26 +41,27 @@ trait BytecodeWriters {
def getFile(sym: Symbol, clsName: String, suffix: String): AbstractFile =
getFile(outputDirectory(sym), clsName, suffix)

def factoryNonJarBytecodeWriter(): BytecodeWriter = {
val emitAsmp = settings.Ygenasmp.isSetByUser
val doDump = settings.Ydumpclasses.isSetByUser
def factoryNonJarBytecodeWriter(implicit ctx: Context): BytecodeWriter = {
val emitAsmp = ctx.settings.Ygenasmp.isSetByUser
val doDump = ctx.settings.Ydumpclasses.isSetByUser
(emitAsmp, doDump) match {
case (false, false) => new ClassBytecodeWriter { }
case (false, true ) => new ClassBytecodeWriter with DumpBytecodeWriter { }
case (false, false) => new ClassBytecodeWriter
case (false, true ) => new ClassBytecodeWriter with DumpBytecodeWriter
case (true, false) => new ClassBytecodeWriter with AsmpBytecodeWriter
case (true, true ) => new ClassBytecodeWriter with AsmpBytecodeWriter with DumpBytecodeWriter { }
case (true, true ) => new ClassBytecodeWriter with AsmpBytecodeWriter with DumpBytecodeWriter
}
}

trait BytecodeWriter {
trait BytecodeWriter extends HasContext {
def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], outfile: AbstractFile): Unit
def close(): Unit = ()
}

class DirectToJarfileWriter(jfile: JFile) extends BytecodeWriter {
class DirectToJarfileWriter(jfile: JFile)(implicit protected val ctx: Context)
extends BytecodeWriter {
val jarMainAttrs = (
if (settings.mainClass.isDefault) Nil
else List(Name.MAIN_CLASS -> settings.mainClass.value)
if (ctx.settings.mainClass.isDefault) Nil
else List(Name.MAIN_CLASS -> ctx.settings.mainClass.value)
)
val writer = new Jar(jfile).jarWriter(jarMainAttrs: _*)

Expand Down Expand Up @@ -88,7 +90,7 @@ trait BytecodeWriters {
trait AsmpBytecodeWriter extends BytecodeWriter {
import dotty.tools.asm

private val baseDir = Directory(settings.Ygenasmp.value).createDirectory()
private val baseDir = Directory(ctx.settings.Ygenasmp.value).createDirectory()

private def emitAsmp(jclassBytes: Array[Byte], asmpFile: io.File): Unit = {
val pw = asmpFile.printWriter()
Expand All @@ -114,7 +116,7 @@ trait BytecodeWriters {
}
}

trait ClassBytecodeWriter extends BytecodeWriter {
class ClassBytecodeWriter(implicit protected val ctx: Context) extends BytecodeWriter {
def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], outfile: AbstractFile): Unit = {
assert(outfile != null,
"Precisely this override requires its invoker to hand out a non-null AbstractFile.")
Expand All @@ -127,7 +129,7 @@ trait BytecodeWriters {
}

trait DumpBytecodeWriter extends BytecodeWriter {
val baseDir = Directory(settings.Ydumpclasses.value).createDirectory()
val baseDir = Directory(ctx.settings.Ydumpclasses.value).createDirectory()

abstract override def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], outfile: AbstractFile): Unit = {
super.writeClass(label, jclassName, jclassBytes, outfile)
Expand Down
3 changes: 3 additions & 0 deletions src/dotty/tools/dotc/backend/jvm/GenBCode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,9 @@ object GenBCode extends BCodeSyncAndTry {

// clearing maps
clearBCodeTypes()

// free the Context instance reachable from BytecodeWriter
bytecodeWriter = null
}

override def run(implicit ctx: Context): Unit = unsupported("run()")
Expand Down
24 changes: 24 additions & 0 deletions src/dotty/tools/dotc/backend/jvm/HasContext.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* NSC -- new Scala compiler
* Copyright 2005-2012 LAMP/EPFL
* @author Martin Odersky
*/

package dotty.tools.dotc
package backend.jvm

import core.Contexts.Context

/**
* All components (e.g. BCPickles, BCInnerClassGen) of the builder classes
* extend this trait to have access to the context.
*
* The context is provided by the three leaf classes (PlainClassBuilder,
* JMirrorBuilder and JBeanInfoBuilder) as class parameter.
*
* Same goes for BytecodeWriter
*/
trait HasContext {
implicit protected val ctx: Context
}


4 changes: 0 additions & 4 deletions src/dotty/tools/dotc/config/ScalaSettings.scala
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,6 @@ class ScalaSettings extends Settings.SettingGroup {
/** -X "Advanced" settings
*/
val Xhelp = BooleanSetting("-X", "Print a synopsis of advanced options.")
val assemname = StringSetting("-Xassem-name", "file", "(Requires -target:msil) Name of the output assembly.", "").dependsOn(target, "msil")
val assemrefs = StringSetting("-Xassem-path", "path", "(Requires -target:msil) List of assemblies referenced by the program.", ".").dependsOn(target, "msil")
val assemextdirs = StringSetting("-Xassem-extdirs", "dirs", "(Requires -target:msil) List of directories containing assemblies. default:lib", Defaults.scalaLibDir.path).dependsOn(target, "msil")
val sourcedir = StringSetting("-Xsourcedir", "directory", "(Requires -target:msil) Mirror source folder structure in output directory.", ".").dependsOn(target, "msil")
val checkInit = BooleanSetting("-Xcheckinit", "Wrap field accessors to throw an exception on uninitialized access.")
val noassertions = BooleanSetting("-Xdisable-assertions", "Generate no assertions or assumptions.")
// val elidebelow = IntSetting("-Xelide-below", "Calls to @elidable methods are omitted if method priority is lower than argument",
Expand Down