Skip to content
Closed
4 changes: 2 additions & 2 deletions project/ScriptCommands.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@ object ScriptCommands {
Project.setProject(session, newStructure, state)
}

private[this] val enableOptimizer = Seq(
val enableOptimizer = Seq(
scalacOptions in Compile in ThisBuild ++= Seq("-opt:l:inline", "-opt-inline-from:scala/**")
)

private[this] val noDocs = Seq(
val noDocs = Seq(
publishArtifact in (Compile, packageDoc) in ThisBuild := false
)

Expand Down
7 changes: 6 additions & 1 deletion src/compiler/scala/tools/nsc/Global.scala
Original file line number Diff line number Diff line change
Expand Up @@ -438,8 +438,10 @@ class Global(var currentSettings: Settings, reporter0: Reporter)
currentRun.informUnitStarting(this, unit)
val unit0 = currentUnit
currentRun.currentUnit = unit
currentRun.profiler.beforeUnit(phase, unit.source.file)
try apply(unit)
finally {
currentRun.profiler.afterUnit(phase, unit.source.file)
currentRun.currentUnit = unit0
currentRun.advanceUnit()
}
Expand Down Expand Up @@ -1100,6 +1102,9 @@ class Global(var currentSettings: Settings, reporter0: Reporter)

def newJavaUnitParser(unit: CompilationUnit): JavaUnitParser = new JavaUnitParser(unit)

override protected[scala] def currentRunProfilerBeforeCompletion(root: Symbol, associatedFile: AbstractFile): Unit = currentRun.profiler.beforeCompletion(root, associatedFile)
override protected[scala] def currentRunProfilerAfterCompletion(root: Symbol, associatedFile: AbstractFile): Unit = currentRun.profiler.afterCompletion(root, associatedFile)

/** A Run is a single execution of the compiler on a set of units.
*/
class Run extends RunContextApi with RunReporting with RunParsing {
Expand Down Expand Up @@ -1448,7 +1453,7 @@ class Global(var currentSettings: Settings, reporter0: Reporter)
private final val GlobalPhaseName = "global (synthetic)"
protected final val totalCompileTime = statistics.newTimer("#total compile time", GlobalPhaseName)

def compileUnits(units: List[CompilationUnit], fromPhase: Phase): Unit = compileUnitsInternal(units,fromPhase)
def compileUnits(units: List[CompilationUnit], fromPhase: Phase): Unit = compileUnitsInternal(units,fromPhase)
private def compileUnitsInternal(units: List[CompilationUnit], fromPhase: Phase) {
units foreach addUnit
reporter.reset()
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/ast/TreeGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
})
val selfParam = ValDef(selfParamSym)
val rhs = orig.rhs.substituteThis(newSym.owner, gen.mkAttributedIdent(selfParamSym)) // scala/scala-dev#186 intentionally leaving Ident($this) is unpositioned
.substituteSymbols(origParams, newSym.info.params.drop(1)).changeOwner(origSym -> newSym)
.substituteSymbols(origParams, newSym.info.params.drop(1)).changeOwner(origSym, newSym)
treeCopy.DefDef(orig, orig.mods, orig.name, orig.tparams, (selfParam :: orig.vparamss.head) :: Nil, orig.tpt, rhs).setSymbol(newSym)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
}

def genLoadArguments(args: List[Tree], btpes: List[BType]) {
(args zip btpes) foreach { case (arg, btpe) => genLoad(arg, btpe) }
foreach2(args, btpes) { case (arg, btpe) => genLoad(arg, btpe) }
}

def genLoadModule(tree: Tree): BType = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ abstract class BCodeHelpers extends BCodeIdiomatic {
if (needsAnnotation) {
val c = Constant(definitions.RemoteExceptionClass.tpe)
val arg = Literal(c) setType c.tpe
meth.addAnnotation(appliedType(definitions.ThrowsClass, c.tpe), arg)
meth.addAnnotation(appliedType(definitions.ThrowsClass, c.tpe :: Nil), arg)
}
}

Expand Down
39 changes: 24 additions & 15 deletions src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
package scala.tools.nsc
package backend.jvm

import scala.collection.{concurrent, mutable}
import java.{util => ju}
import scala.collection.concurrent
import scala.tools.asm
import scala.tools.asm.Opcodes
import scala.tools.nsc.backend.jvm.BTypes.{InlineInfo, InternalName}
Expand All @@ -23,7 +24,7 @@ import scala.tools.nsc.backend.jvm.opt._
*/
abstract class BTypes {
val frontendAccess: PostProcessorFrontendAccess
import frontendAccess.{frontendSynch, recordPerRunCache}
import frontendAccess.{frontendSynch, recordPerRunJavaMapCache}

val coreBTypes: CoreBTypes { val bTypes: BTypes.this.type }
import coreBTypes._
Expand All @@ -35,13 +36,15 @@ abstract class BTypes {
* `getCommonSuperClass`. In this method we need to obtain the ClassBType for a given internal
* name. The method assumes that every class type that appears in the bytecode exists in the map
*/
def cachedClassBType(internalName: InternalName): Option[ClassBType] =
// OPT: not returning Option[ClassBType] because the Some allocation shows up as a hotspot
def cachedClassBType(internalName: InternalName): ClassBType =
classBTypeCache.get(internalName)

// Concurrent maps because stack map frames are computed when in the class writer, which
// might run on multiple classes concurrently.
// Note usage should be private to this file, except for tests
val classBTypeCache: concurrent.Map[InternalName, ClassBType] = recordPerRunCache(FlatConcurrentHashMap.empty)
val classBTypeCache: ju.concurrent.ConcurrentHashMap[InternalName, ClassBType] =
recordPerRunJavaMapCache(new ju.concurrent.ConcurrentHashMap[InternalName, ClassBType])

/**
* A BType is either a primitive type, a ClassBType, an ArrayBType of one of these, or a MethodType
Expand Down Expand Up @@ -809,17 +812,23 @@ abstract class BTypes {
def unapply(cr:ClassBType) = Some(cr.internalName)

def apply(internalName: InternalName, fromSymbol: Boolean)(init: (ClassBType) => Either[NoClassBTypeInfo, ClassInfo]) = {
val newRes = if (fromSymbol) new ClassBTypeFromSymbol(internalName) else new ClassBTypeFromClassfile(internalName)
// synchronized s required to ensure proper initialisation if info.
// see comment on def info
newRes.synchronized {
classBTypeCache.putIfAbsent(internalName, newRes) match {
case None =>
newRes._info = init(newRes)
newRes.checkInfoConsistency()
newRes
case Some(old) =>
old
val cached = classBTypeCache.get(internalName)
if (cached ne null) cached
else {
val newRes =
if (fromSymbol) new ClassBTypeFromSymbol(internalName)
else new ClassBTypeFromClassfile(internalName)
// synchronized is required to ensure proper initialisation of info.
// see comment on def info
newRes.synchronized {
classBTypeCache.putIfAbsent(internalName, newRes) match {
case null =>
newRes._info = init(newRes)
newRes.checkInfoConsistency()
newRes
case old =>
old
}
}
}
}
Expand Down
16 changes: 6 additions & 10 deletions src/compiler/scala/tools/nsc/backend/jvm/BTypesFromClassfile.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,10 @@ abstract class BTypesFromClassfile {
* be found in the `byteCodeRepository`, the `info` of the resulting ClassBType is undefined.
*/
def classBTypeFromParsedClassfile(internalName: InternalName): ClassBType = {
cachedClassBType(internalName).getOrElse{
ClassBType(internalName, false){ res:ClassBType =>
byteCodeRepository.classNode(internalName) match {
case Left(msg) => Left(NoClassBTypeInfoMissingBytecode(msg))
case Right(c) => computeClassInfoFromClassNode(c, res)
}
ClassBType(internalName, fromSymbol = false) { res: ClassBType =>
byteCodeRepository.classNode(internalName) match {
case Left(msg) => Left(NoClassBTypeInfoMissingBytecode(msg))
case Right(c) => computeClassInfoFromClassNode(c, res)
}
}
}
Expand All @@ -60,10 +58,8 @@ abstract class BTypesFromClassfile {
* Construct the [[ClassBType]] for a parsed classfile.
*/
def classBTypeFromClassNode(classNode: ClassNode): ClassBType = {
cachedClassBType(classNode.name).getOrElse {
ClassBType(classNode.name, false) { res: ClassBType =>
computeClassInfoFromClassNode(classNode, res)
}
ClassBType(classNode.name, fromSymbol = false) { res: ClassBType =>
computeClassInfoFromClassNode(classNode, res)
}
}

Expand Down
59 changes: 24 additions & 35 deletions src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,12 @@ abstract class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
else if (classSym == NullClass) srNullRef
else {
val internalName = classSym.javaBinaryNameString
cachedClassBType(internalName) match {
case Some(bType) =>
if (currentRun.compiles(classSym))
assert(bType fromSymbol, s"ClassBType for class being compiled was already created from a classfile: ${classSym.fullName}")
bType
case None =>
// The new ClassBType is added to the map via its apply, before we set its info. This
// allows initializing cyclic dependencies, see the comment on variable ClassBType._info.
ClassBType(internalName, true) { res:ClassBType =>
if (completeSilentlyAndCheckErroneous(classSym))
Left(NoClassBTypeInfoClassSymbolInfoFailedSI9111(classSym.fullName))
else computeClassInfo(classSym, res)
}
// The new ClassBType is added to the map via its apply, before we set its info. This
// allows initializing cyclic dependencies, see the comment on variable ClassBType._info.
ClassBType(internalName, fromSymbol = true) { res:ClassBType =>
if (completeSilentlyAndCheckErroneous(classSym))
Left(NoClassBTypeInfoClassSymbolInfoFailedSI9111(classSym.fullName))
else computeClassInfo(classSym, res)
}
}
}
Expand Down Expand Up @@ -623,33 +616,29 @@ abstract class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
def mirrorClassClassBType(moduleClassSym: Symbol): ClassBType = {
assert(isTopLevelModuleClass(moduleClassSym), s"not a top-level module class: $moduleClassSym")
val internalName = moduleClassSym.javaBinaryNameString.stripSuffix(nme.MODULE_SUFFIX_STRING)
cachedClassBType(internalName).getOrElse {
ClassBType(internalName, true) { c: ClassBType =>
val shouldBeLazy = moduleClassSym.isJavaDefined || !currentRun.compiles(moduleClassSym)
val nested = Lazy.withLockOrEager(shouldBeLazy, exitingPickler(memberClassesForInnerClassTable(moduleClassSym)) map classBTypeFromSymbol)
Right(ClassInfo(
superClass = Some(ObjectRef),
interfaces = Nil,
flags = asm.Opcodes.ACC_SUPER | asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_FINAL,
nestedClasses = nested,
nestedInfo = Lazy.eagerNone,
inlineInfo = EmptyInlineInfo.copy(isEffectivelyFinal = true))) // no method inline infos needed, scala never invokes methods on the mirror class
}
ClassBType(internalName, fromSymbol = true) { c: ClassBType =>
val shouldBeLazy = moduleClassSym.isJavaDefined || !currentRun.compiles(moduleClassSym)
val nested = Lazy.withLockOrEager(shouldBeLazy, exitingPickler(memberClassesForInnerClassTable(moduleClassSym)) map classBTypeFromSymbol)
Right(ClassInfo(
superClass = Some(ObjectRef),
interfaces = Nil,
flags = asm.Opcodes.ACC_SUPER | asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_FINAL,
nestedClasses = nested,
nestedInfo = Lazy.eagerNone,
inlineInfo = EmptyInlineInfo.copy(isEffectivelyFinal = true))) // no method inline infos needed, scala never invokes methods on the mirror class
}
}

def beanInfoClassClassBType(mainClass: Symbol): ClassBType = {
val internalName = mainClass.javaBinaryNameString + "BeanInfo"
cachedClassBType(internalName).getOrElse {
ClassBType(internalName, true) { c: ClassBType =>
Right(ClassInfo(
superClass = Some(sbScalaBeanInfoRef),
interfaces = Nil,
flags = javaFlags(mainClass),
nestedClasses = Lazy.eagerNil,
nestedInfo = Lazy.eagerNone,
inlineInfo = EmptyInlineInfo))
}
ClassBType(internalName, fromSymbol = true) { c: ClassBType =>
Right(ClassInfo(
superClass = Some(sbScalaBeanInfoRef),
interfaces = Nil,
flags = javaFlags(mainClass),
nestedClasses = Lazy.eagerNil,
nestedInfo = Lazy.eagerNone,
inlineInfo = EmptyInlineInfo))
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/compiler/scala/tools/nsc/backend/jvm/PostProcessor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ abstract class PostProcessor extends PerRunInit {
*/
override def getCommonSuperClass(inameA: String, inameB: String): String = {
// All types that appear in a class node need to have their ClassBType cached, see [[cachedClassBType]].
val a = cachedClassBType(inameA).get
val b = cachedClassBType(inameB).get
val a = cachedClassBType(inameA)
val b = cachedClassBType(inameB)
val lub = a.jvmWiseLUB(b).get
val lubName = lub.internalName
assert(lubName != "scala/Any")
Expand Down
Loading