Skip to content

Commit ebf8017

Browse files
authored
Merge pull request scala#7135 from hrhino/faster/misc
a small handful of optimizations for 2.12
2 parents 2b48ca6 + fb2b676 commit ebf8017

34 files changed

+148
-135
lines changed

src/compiler/scala/tools/nsc/ast/TreeGen.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
352352
})
353353
val selfParam = ValDef(selfParamSym)
354354
val rhs = orig.rhs.substituteThis(newSym.owner, gen.mkAttributedIdent(selfParamSym)) // scala/scala-dev#186 intentionally leaving Ident($this) is unpositioned
355-
.substituteSymbols(origParams, newSym.info.params.drop(1)).changeOwner(origSym -> newSym)
355+
.substituteSymbols(origParams, newSym.info.params.drop(1)).changeOwner(origSym, newSym)
356356
treeCopy.DefDef(orig, orig.mods, orig.name, orig.tparams, (selfParam :: orig.vparamss.head) :: Nil, orig.tpt, rhs).setSymbol(newSym)
357357
}
358358

src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
932932
}
933933

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

938938
def genLoadModule(tree: Tree): BType = {

src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ abstract class BCodeHelpers extends BCodeIdiomatic {
789789
if (needsAnnotation) {
790790
val c = Constant(definitions.RemoteExceptionClass.tpe)
791791
val arg = Literal(c) setType c.tpe
792-
meth.addAnnotation(appliedType(definitions.ThrowsClass, c.tpe), arg)
792+
meth.addAnnotation(appliedType(definitions.ThrowsClass, c.tpe :: Nil), arg)
793793
}
794794
}
795795

src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
package scala.tools.nsc
77
package backend.jvm
88

9-
import scala.collection.{concurrent, mutable}
9+
import java.{util => ju}
10+
import scala.collection.concurrent
1011
import scala.tools.asm
1112
import scala.tools.asm.Opcodes
1213
import scala.tools.nsc.backend.jvm.BTypes.{InlineInfo, InternalName}
@@ -23,7 +24,7 @@ import scala.tools.nsc.backend.jvm.opt._
2324
*/
2425
abstract class BTypes {
2526
val frontendAccess: PostProcessorFrontendAccess
26-
import frontendAccess.{frontendSynch, recordPerRunCache}
27+
import frontendAccess.{frontendSynch, recordPerRunJavaMapCache}
2728

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

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

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

811814
def apply(internalName: InternalName, fromSymbol: Boolean)(init: (ClassBType) => Either[NoClassBTypeInfo, ClassInfo]) = {
812-
val newRes = if (fromSymbol) new ClassBTypeFromSymbol(internalName) else new ClassBTypeFromClassfile(internalName)
813-
// synchronized s required to ensure proper initialisation if info.
814-
// see comment on def info
815-
newRes.synchronized {
816-
classBTypeCache.putIfAbsent(internalName, newRes) match {
817-
case None =>
818-
newRes._info = init(newRes)
819-
newRes.checkInfoConsistency()
820-
newRes
821-
case Some(old) =>
822-
old
815+
val cached = classBTypeCache.get(internalName)
816+
if (cached ne null) cached
817+
else {
818+
val newRes =
819+
if (fromSymbol) new ClassBTypeFromSymbol(internalName)
820+
else new ClassBTypeFromClassfile(internalName)
821+
// synchronized is required to ensure proper initialisation of info.
822+
// see comment on def info
823+
newRes.synchronized {
824+
classBTypeCache.putIfAbsent(internalName, newRes) match {
825+
case null =>
826+
newRes._info = init(newRes)
827+
newRes.checkInfoConsistency()
828+
newRes
829+
case old =>
830+
old
831+
}
823832
}
824833
}
825834
}

src/compiler/scala/tools/nsc/backend/jvm/BTypesFromClassfile.scala

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,10 @@ abstract class BTypesFromClassfile {
4646
* be found in the `byteCodeRepository`, the `info` of the resulting ClassBType is undefined.
4747
*/
4848
def classBTypeFromParsedClassfile(internalName: InternalName): ClassBType = {
49-
cachedClassBType(internalName).getOrElse{
50-
ClassBType(internalName, false){ res:ClassBType =>
51-
byteCodeRepository.classNode(internalName) match {
52-
case Left(msg) => Left(NoClassBTypeInfoMissingBytecode(msg))
53-
case Right(c) => computeClassInfoFromClassNode(c, res)
54-
}
49+
ClassBType(internalName, fromSymbol = false) { res: ClassBType =>
50+
byteCodeRepository.classNode(internalName) match {
51+
case Left(msg) => Left(NoClassBTypeInfoMissingBytecode(msg))
52+
case Right(c) => computeClassInfoFromClassNode(c, res)
5553
}
5654
}
5755
}
@@ -60,10 +58,8 @@ abstract class BTypesFromClassfile {
6058
* Construct the [[ClassBType]] for a parsed classfile.
6159
*/
6260
def classBTypeFromClassNode(classNode: ClassNode): ClassBType = {
63-
cachedClassBType(classNode.name).getOrElse {
64-
ClassBType(classNode.name, false) { res: ClassBType =>
65-
computeClassInfoFromClassNode(classNode, res)
66-
}
61+
ClassBType(classNode.name, fromSymbol = false) { res: ClassBType =>
62+
computeClassInfoFromClassNode(classNode, res)
6763
}
6864
}
6965

src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -93,19 +93,12 @@ abstract class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
9393
else if (classSym == NullClass) srNullRef
9494
else {
9595
val internalName = classSym.javaBinaryNameString
96-
cachedClassBType(internalName) match {
97-
case Some(bType) =>
98-
if (currentRun.compiles(classSym))
99-
assert(bType fromSymbol, s"ClassBType for class being compiled was already created from a classfile: ${classSym.fullName}")
100-
bType
101-
case None =>
102-
// The new ClassBType is added to the map via its apply, before we set its info. This
103-
// allows initializing cyclic dependencies, see the comment on variable ClassBType._info.
104-
ClassBType(internalName, true) { res:ClassBType =>
105-
if (completeSilentlyAndCheckErroneous(classSym))
106-
Left(NoClassBTypeInfoClassSymbolInfoFailedSI9111(classSym.fullName))
107-
else computeClassInfo(classSym, res)
108-
}
96+
// The new ClassBType is added to the map via its apply, before we set its info. This
97+
// allows initializing cyclic dependencies, see the comment on variable ClassBType._info.
98+
ClassBType(internalName, fromSymbol = true) { res:ClassBType =>
99+
if (completeSilentlyAndCheckErroneous(classSym))
100+
Left(NoClassBTypeInfoClassSymbolInfoFailedSI9111(classSym.fullName))
101+
else computeClassInfo(classSym, res)
109102
}
110103
}
111104
}
@@ -623,33 +616,29 @@ abstract class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
623616
def mirrorClassClassBType(moduleClassSym: Symbol): ClassBType = {
624617
assert(isTopLevelModuleClass(moduleClassSym), s"not a top-level module class: $moduleClassSym")
625618
val internalName = moduleClassSym.javaBinaryNameString.stripSuffix(nme.MODULE_SUFFIX_STRING)
626-
cachedClassBType(internalName).getOrElse {
627-
ClassBType(internalName, true) { c: ClassBType =>
628-
val shouldBeLazy = moduleClassSym.isJavaDefined || !currentRun.compiles(moduleClassSym)
629-
val nested = Lazy.withLockOrEager(shouldBeLazy, exitingPickler(memberClassesForInnerClassTable(moduleClassSym)) map classBTypeFromSymbol)
630-
Right(ClassInfo(
631-
superClass = Some(ObjectRef),
632-
interfaces = Nil,
633-
flags = asm.Opcodes.ACC_SUPER | asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_FINAL,
634-
nestedClasses = nested,
635-
nestedInfo = Lazy.eagerNone,
636-
inlineInfo = EmptyInlineInfo.copy(isEffectivelyFinal = true))) // no method inline infos needed, scala never invokes methods on the mirror class
637-
}
619+
ClassBType(internalName, fromSymbol = true) { c: ClassBType =>
620+
val shouldBeLazy = moduleClassSym.isJavaDefined || !currentRun.compiles(moduleClassSym)
621+
val nested = Lazy.withLockOrEager(shouldBeLazy, exitingPickler(memberClassesForInnerClassTable(moduleClassSym)) map classBTypeFromSymbol)
622+
Right(ClassInfo(
623+
superClass = Some(ObjectRef),
624+
interfaces = Nil,
625+
flags = asm.Opcodes.ACC_SUPER | asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_FINAL,
626+
nestedClasses = nested,
627+
nestedInfo = Lazy.eagerNone,
628+
inlineInfo = EmptyInlineInfo.copy(isEffectivelyFinal = true))) // no method inline infos needed, scala never invokes methods on the mirror class
638629
}
639630
}
640631

641632
def beanInfoClassClassBType(mainClass: Symbol): ClassBType = {
642633
val internalName = mainClass.javaBinaryNameString + "BeanInfo"
643-
cachedClassBType(internalName).getOrElse {
644-
ClassBType(internalName, true) { c: ClassBType =>
645-
Right(ClassInfo(
646-
superClass = Some(sbScalaBeanInfoRef),
647-
interfaces = Nil,
648-
flags = javaFlags(mainClass),
649-
nestedClasses = Lazy.eagerNil,
650-
nestedInfo = Lazy.eagerNone,
651-
inlineInfo = EmptyInlineInfo))
652-
}
634+
ClassBType(internalName, fromSymbol = true) { c: ClassBType =>
635+
Right(ClassInfo(
636+
superClass = Some(sbScalaBeanInfoRef),
637+
interfaces = Nil,
638+
flags = javaFlags(mainClass),
639+
nestedClasses = Lazy.eagerNil,
640+
nestedInfo = Lazy.eagerNone,
641+
inlineInfo = EmptyInlineInfo))
653642
}
654643
}
655644

src/compiler/scala/tools/nsc/backend/jvm/PostProcessor.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,8 @@ abstract class PostProcessor extends PerRunInit {
148148
*/
149149
override def getCommonSuperClass(inameA: String, inameB: String): String = {
150150
// All types that appear in a class node need to have their ClassBType cached, see [[cachedClassBType]].
151-
val a = cachedClassBType(inameA).get
152-
val b = cachedClassBType(inameB).get
151+
val a = cachedClassBType(inameA)
152+
val b = cachedClassBType(inameB)
153153
val lub = a.jvmWiseLUB(b).get
154154
val lubName = lub.internalName
155155
assert(lubName != "scala/Any")

src/compiler/scala/tools/nsc/settings/MutableSettings.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ package settings
1111
import io.{ AbstractFile, Jar, Path, PlainFile, VirtualDirectory }
1212
import scala.collection.generic.Clearable
1313
import scala.io.Source
14-
import scala.reflect.internal.util.StringOps
14+
import scala.reflect.internal.util.{ SomeOfNil, StringOps }
1515
import scala.reflect.{ ClassTag, classTag }
1616

1717
/** A mutable Settings object.
@@ -127,7 +127,7 @@ class MutableSettings(val errorFn: String => Unit)
127127

128128
// -Xfoo: clears Clearables
129129
def clearIfExists(cmd: String): Option[List[String]] = lookupSetting(cmd) match {
130-
case Some(c: Clearable) => c.clear() ; Some(Nil)
130+
case Some(c: Clearable) => c.clear() ; SomeOfNil
131131
case Some(s) => s.errorAndValue(s"Missing argument to $cmd", None)
132132
case None => None
133133
}
@@ -463,10 +463,10 @@ class MutableSettings(val errorFn: String => Unit)
463463
case List(x) =>
464464
if (x.equalsIgnoreCase("true")) {
465465
value = true
466-
Some(Nil)
466+
SomeOfNil
467467
} else if (x.equalsIgnoreCase("false")) {
468468
value = false
469-
Some(Nil)
469+
SomeOfNil
470470
} else errorAndValue(s"'$x' is not a valid choice for '$name'", None)
471471
case _ => errorAndValue(s"'$name' accepts only one boolean value", None)
472472
}
@@ -867,8 +867,8 @@ class MutableSettings(val errorFn: String => Unit)
867867

868868
override def tryToSetColon(args: List[String]) = args match {
869869
case Nil => errorAndValue(usageErrorMessage, None)
870-
case List("help") => sawHelp = true; Some(Nil)
871-
case List(x) if choices contains x => value = x ; Some(Nil)
870+
case List("help") => sawHelp = true; SomeOfNil
871+
case List(x) if choices contains x => value = x ; SomeOfNil
872872
case List(x) => errorAndValue("'" + x + "' is not a valid choice for '" + name + "'", None)
873873
case xs => errorAndValue("'" + name + "' does not accept multiple arguments.", None)
874874
}
@@ -933,7 +933,7 @@ class MutableSettings(val errorFn: String => Unit)
933933
args match {
934934
case Nil => if (default == "") errorAndValue("missing phase", None)
935935
else tryToSetColon(splitDefault)
936-
case xs => value = (value ++ xs).distinct.sorted ; Some(Nil)
936+
case xs => value = (value ++ xs).distinct.sorted ; SomeOfNil
937937
}
938938
} catch { case _: NumberFormatException => None }
939939

src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,7 @@ abstract class ClassfileParser {
10941094
def addParamNames(): Unit =
10951095
if ((paramNames ne null) && sym.hasRawInfo && sym.isMethod) {
10961096
val params = sym.rawInfo.params
1097-
(paramNames zip params).foreach {
1097+
foreach2(paramNames.toList, params) {
10981098
case (nme.NO_NAME, _) => // param was ACC_SYNTHETIC; ignore
10991099
case (name, param) =>
11001100
param.resetFlag(SYNTHETIC)

src/compiler/scala/tools/nsc/transform/AccessorSynthesis.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ trait AccessorSynthesis extends Transform with ast.TreeDSL {
278278
*/
279279
def expandLazyClassMember(lazyVar: global.Symbol, lazyAccessor: global.Symbol, transformedRhs: global.Tree): Tree = {
280280
val slowPathSym = slowPathFor(lazyAccessor)
281-
val rhsAtSlowDef = transformedRhs.changeOwner(lazyAccessor -> slowPathSym)
281+
val rhsAtSlowDef = transformedRhs.changeOwner(lazyAccessor, slowPathSym)
282282

283283
val isUnit = isUnitGetter(lazyAccessor)
284284
val selectVar = if (isUnit) UNIT else Select(thisRef, lazyVar)

0 commit comments

Comments
 (0)