Skip to content
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

Try some more optimizations #9409

Closed
wants to merge 21 commits into from
Closed
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
14 changes: 10 additions & 4 deletions compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
import coreBTypes._
import BCodeBodyBuilder._

private val primitives = new DottyPrimitives(ctx)
protected val primitives: DottyPrimitives

/*
* Functionality to build the body of ASM MethodNode, except for `synchronized` and `try` expressions.
Expand Down Expand Up @@ -1021,9 +1021,15 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
}
}

def genLoadArguments(args: List[Tree], btpes: List[BType]): Unit = {
(args zip btpes) foreach { case (arg, btpe) => genLoad(arg, btpe) }
}
def genLoadArguments(args: List[Tree], btpes: List[BType]): Unit =
args match
case arg :: args1 =>
btpes match
case btpe :: btpes1 =>
genLoad(arg, btpe)
genLoadArguments(args1, btpes1)
case _ =>
case _ =>

def genLoadModule(tree: Tree): BType = {
val module = (
Expand Down
19 changes: 9 additions & 10 deletions compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -339,16 +339,15 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
* must-single-thread
*/
def emitParamAnnotations(jmethod: asm.MethodVisitor, pannotss: List[List[Annotation]]): Unit =
val annotationss = pannotss map (_ filter shouldEmitAnnotation)
if (annotationss forall (_.isEmpty)) return
for ((annots, idx) <- annotationss.zipWithIndex;
annot <- annots) {
val typ = annot.tree.tpe
val assocs = assocsFromApply(annot.tree)
val pannVisitor: asm.AnnotationVisitor = jmethod.visitParameterAnnotation(idx, typeDescriptor(typ.asInstanceOf[Type]), isRuntimeVisible(annot))
emitAssocs(pannVisitor, assocs, BCodeHelpers.this)(this)
}

if pannotss.nestedExists(shouldEmitAnnotation) then
for (annots, idx) <- pannotss.zipWithIndex
annot <- annots
if shouldEmitAnnotation(annot)
do
val typ = annot.tree.tpe
val assocs = assocsFromApply(annot.tree)
val pannVisitor: asm.AnnotationVisitor = jmethod.visitParameterAnnotation(idx, typeDescriptor(typ.asInstanceOf[Type]), isRuntimeVisible(annot))
emitAssocs(pannVisitor, assocs, BCodeHelpers.this)(this)

private def shouldEmitAnnotation(annot: Annotation): Boolean = {
annot.symbol.is(JavaDefined) &&
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/backend/jvm/BCodeIdiomatic.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ trait BCodeIdiomatic {
lazy val majorVersion: Int = (classfileVersion & 0xFF)
lazy val emitStackMapFrame = (majorVersion >= 50)

val extraProc: Int = GenBCodeOps.mkFlags(
asm.ClassWriter.COMPUTE_MAXS,
if (emitStackMapFrame) asm.ClassWriter.COMPUTE_FRAMES else 0
)
val extraProc: Int =
import GenBCodeOps.addFlagIf
asm.ClassWriter.COMPUTE_MAXS
.addFlagIf(emitStackMapFrame, asm.ClassWriter.COMPUTE_FRAMES)

lazy val JavaStringBuilderClassName = jlStringBuilderRef.internalName

Expand Down
14 changes: 7 additions & 7 deletions compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
}
def lineNumber(tree: Tree): Unit = {
if (!emitLines || !tree.span.exists) return;
val nr = ctx.source.atSpan(tree.span).line + 1
val nr = ctx.source.offsetToLine(tree.span.point) + 1
if (nr != lastEmittedLineNr) {
lastEmittedLineNr = nr
lastInsn match {
Expand Down Expand Up @@ -690,12 +690,12 @@ trait BCodeSkelBuilder extends BCodeHelpers {

val isNative = methSymbol.hasAnnotation(NativeAttr)
val isAbstractMethod = (methSymbol.is(Deferred) || (methSymbol.owner.isInterface && ((methSymbol.is(Deferred)) || methSymbol.isClassConstructor)))
val flags = GenBCodeOps.mkFlags(
javaFlags(methSymbol),
if (isAbstractMethod) asm.Opcodes.ACC_ABSTRACT else 0,
if (false /*methSymbol.isStrictFP*/) asm.Opcodes.ACC_STRICT else 0,
if (isNative) asm.Opcodes.ACC_NATIVE else 0 // native methods of objects are generated in mirror classes
)
val flags =
import GenBCodeOps.addFlagIf
javaFlags(methSymbol)
.addFlagIf(isAbstractMethod, asm.Opcodes.ACC_ABSTRACT)
.addFlagIf(false /*methSymbol.isStrictFP*/, asm.Opcodes.ACC_STRICT)
.addFlagIf(isNative, asm.Opcodes.ACC_NATIVE) // native methods of objects are generated in mirror classes

// TODO needed? for(ann <- m.symbol.annotations) { ann.symbol.initialize }
initJMethod(flags, params.map(p => p.symbol.annotations))
Expand Down
7 changes: 3 additions & 4 deletions compiler/src/dotty/tools/backend/jvm/BTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -649,14 +649,13 @@ abstract class BTypes {

def innerClassAttributeEntry: Option[InnerClassEntry] = info.nestedInfo map {
case NestedInfo(_, outerName, innerName, isStaticNestedClass) =>
import GenBCodeOps.addFlagIf
InnerClassEntry(
internalName,
outerName.orNull,
innerName.orNull,
GenBCodeOps.mkFlags(
info.flags,
if (isStaticNestedClass) asm.Opcodes.ACC_STATIC else 0
) & ClassBType.INNER_CLASSES_FLAGS
info.flags.addFlagIf(isStaticNestedClass, asm.Opcodes.ACC_STATIC)
& ClassBType.INNER_CLASSES_FLAGS
)
}

Expand Down
47 changes: 22 additions & 25 deletions compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -304,39 +304,36 @@ class BTypesFromSymbols[I <: DottyBackendInterface](val int: I) extends BTypes {
val finalFlag = sym.is(Final) && !toDenot(sym).isClassConstructor && !sym.is(Mutable) && !sym.enclosingClass.is(Trait)

import asm.Opcodes._
GenBCodeOps.mkFlags(
if (privateFlag) ACC_PRIVATE else ACC_PUBLIC,
if (sym.is(Deferred) || sym.isOneOf(AbstractOrTrait)) ACC_ABSTRACT else 0,
if (sym.isInterface) ACC_INTERFACE else 0,

if (finalFlag &&
import GenBCodeOps.addFlagIf
0 .addFlagIf(privateFlag, ACC_PRIVATE)
.addFlagIf(!privateFlag, ACC_PUBLIC)
.addFlagIf(sym.is(Deferred) || sym.isOneOf(AbstractOrTrait), ACC_ABSTRACT)
.addFlagIf(sym.isInterface, ACC_INTERFACE)
.addFlagIf(finalFlag
// Primitives are "abstract final" to prohibit instantiation
// without having to provide any implementations, but that is an
// illegal combination of modifiers at the bytecode level so
// suppress final if abstract if present.
!sym.isOneOf(AbstractOrTrait) &&
&& !sym.isOneOf(AbstractOrTrait)
// Mixin forwarders are bridges and can be final, but final bridges confuse some frameworks
!sym.is(Bridge))
ACC_FINAL else 0,

if (sym.isStaticMember) ACC_STATIC else 0,
if (sym.is(Bridge)) ACC_BRIDGE | ACC_SYNTHETIC else 0,
if (sym.is(Artifact)) ACC_SYNTHETIC else 0,
if (sym.isClass && !sym.isInterface) ACC_SUPER else 0,
if (sym.isAllOf(JavaEnumTrait)) ACC_ENUM else 0,
if (sym.is(JavaVarargs)) ACC_VARARGS else 0,
if (sym.is(Synchronized)) ACC_SYNCHRONIZED else 0,
if (sym.isDeprecated) ACC_DEPRECATED else 0,
if (sym.is(Enum)) ACC_ENUM else 0
)
&& !sym.is(Bridge), ACC_FINAL)
.addFlagIf(sym.isStaticMember, ACC_STATIC)
.addFlagIf(sym.is(Bridge), ACC_BRIDGE | ACC_SYNTHETIC)
.addFlagIf(sym.is(Artifact), ACC_SYNTHETIC)
.addFlagIf(sym.isClass && !sym.isInterface, ACC_SUPER)
.addFlagIf(sym.isAllOf(JavaEnumTrait), ACC_ENUM)
.addFlagIf(sym.is(JavaVarargs), ACC_VARARGS)
.addFlagIf(sym.is(Synchronized), ACC_SYNCHRONIZED)
.addFlagIf(sym.isDeprecated, ACC_DEPRECATED)
.addFlagIf(sym.is(Enum), ACC_ENUM)
}

def javaFieldFlags(sym: Symbol) = {
import asm.Opcodes._
javaFlags(sym) | GenBCodeOps.mkFlags(
if (sym.hasAnnotation(TransientAttr)) ACC_TRANSIENT else 0,
if (sym.hasAnnotation(VolatileAttr)) ACC_VOLATILE else 0,
if (sym.is(Mutable)) 0 else ACC_FINAL
)
import GenBCodeOps.addFlagIf
javaFlags(sym)
.addFlagIf(sym.hasAnnotation(TransientAttr), ACC_TRANSIENT)
.addFlagIf(sym.hasAnnotation(VolatileAttr), ACC_VOLATILE)
.addFlagIf(!sym.is(Mutable), ACC_FINAL)
}
}
10 changes: 7 additions & 3 deletions compiler/src/dotty/tools/backend/jvm/GenBCode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,13 @@ class GenBCode extends Phase {
myOutput
}

private var myPrimitives: DottyPrimitives = null

def run(using Context): Unit =
GenBCodePipeline(
DottyBackendInterface(outputDir, superCallsMap)
if myPrimitives == null then myPrimitives = new DottyPrimitives(ctx)
new GenBCodePipeline(
DottyBackendInterface(outputDir, superCallsMap),
myPrimitives
).run(ctx.compilationUnit.tpdTree)


Expand All @@ -74,7 +78,7 @@ object GenBCode {
val name: String = "genBCode"
}

class GenBCodePipeline(val int: DottyBackendInterface)(using Context) extends BCodeSyncAndTry {
class GenBCodePipeline(val int: DottyBackendInterface, val primitives: DottyPrimitives)(using Context) extends BCodeSyncAndTry {
import DottyBackendInterface.symExtensions

private var tree: Tree = _
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/backend/jvm/GenBCodeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import scala.tools.asm
object GenBCodeOps extends GenBCodeOps

class GenBCodeOps {
def mkFlags(args: Int*) = args.foldLeft(0)(_ | _)
extension (flags: Int)
def addFlagIf(cond: Boolean, flag: Int): Int = if cond then flags | flag else flags

final val PublicStatic = asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_STATIC
final val PublicStaticFinal = asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_STATIC | asm.Opcodes.ACC_FINAL
Expand Down
15 changes: 7 additions & 8 deletions compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala
Original file line number Diff line number Diff line change
Expand Up @@ -133,16 +133,15 @@ class DottyPrimitives(ictx: Context) {
}

def addPrimitives(cls: Symbol, method: TermName, code: Int)(using Context): Unit = {
val alts = cls.info.member(method).alternatives.map(_.symbol)
if (alts.isEmpty)
val alts = cls.info.member(method).alternatives
if alts.isEmpty then
report.error(s"Unknown primitive method $cls.$method")
else alts foreach (s =>
else for d <- alts do
val s = d.symbol
addPrimitive(s,
s.info.paramInfoss match {
case List(tp :: _) if code == ADD && tp =:= ctx.definitions.StringType => CONCAT
case _ => code
}
)
s.info.paramInfoss match
case (tp :: _) :: Nil if code == ADD && tp =:= ctx.definitions.StringType => CONCAT
case _ => code
)
}

Expand Down
14 changes: 8 additions & 6 deletions compiler/src/dotty/tools/dotc/Bench.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ object Bench extends Driver:
override def doCompile(compiler: Compiler, fileNames: List[String])(using Context): Reporter =
times = new Array[Int](numRuns)
var reporter: Reporter = emptyReporter
val stats = ctx.settings.YdetailedStats.value
for i <- 0 until numRuns do
val start = System.nanoTime()
reporter = super.doCompile(compiler, fileNames)
reporter = inContext(ctx.fresh.setSetting(ctx.settings.YdetailedStats, stats && i == numRuns - 1)) {
super.doCompile(compiler, fileNames)
}
times(i) = ((System.nanoTime - start) / 1000000).toInt
println(s"time elapsed: ${times(i)}ms")
if ctx.settings.Xprompt.value then
Expand All @@ -33,11 +36,10 @@ object Bench extends Driver:
println()
reporter

def extractNumArg(args: Array[String], name: String, default: Int = 1): (Int, Array[String]) = {
val pos = args indexOf name
if (pos < 0) (default, args)
else (args(pos + 1).toInt, (args take pos) ++ (args drop (pos + 2)))
}
def extractNumArg(args: Array[String], name: String, default: Int = 1): (Int, Array[String]) =
val pos = args.indexOf(name)
if pos < 0 then (default, args)
else (args(pos + 1).toInt, args.take(pos) ++ args.drop(pos + 2))

def reportTimes() =
val best = times.sorted
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -594,9 +594,9 @@ object desugar {
(ordinalMethLit(ordinal) :: enumLabelLit(className.toString) :: Nil, scaffolding)
else (Nil, Nil)
def copyMeths = {
val hasRepeatedParam = constrVparamss.exists(_.exists {
val hasRepeatedParam = constrVparamss.nestedExists {
case ValDef(_, tpt, _) => isRepeated(tpt)
})
}
if (mods.is(Abstract) || hasRepeatedParam) Nil // cannot have default arguments for repeated parameters, hence copy method is not issued
else {
def copyDefault(vparam: ValDef) =
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ object DesugarEnums {
case parent => parent.isType && typeHasRef(parent)
}

vparamss.exists(_.exists(valDefHasRef)) || parents.exists(parentHasRef)
vparamss.nestedExists(valDefHasRef) || parents.exists(parentHasRef)
}

/** A pair consisting of
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ object Trees {
def toList: List[Tree[T]] = this :: Nil

/** if this tree is the empty tree, the alternative, else this tree */
def orElse[U >: Untyped <: T](that: => Tree[U]): Tree[U] =
inline def orElse[U >: Untyped <: T](inline that: Tree[U]): Tree[U] =
if (this eq genericEmptyTree) that else this

/** The number of nodes in this tree */
Expand Down
6 changes: 5 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ object Contexts {
final def retractMode(mode: Mode): c.type = c.setMode(c.mode &~ mode)
}

private def exploreCtx(using Context): Context =
private def exploreCtx(using Context): FreshContext =
util.Stats.record("explore")
val base = ctx.base
import base._
Expand All @@ -701,6 +701,10 @@ object Contexts {
val ectx = exploreCtx
try op(using ectx) finally wrapUpExplore(ectx)

inline def exploreInFreshCtx[T](inline op: FreshContext ?=> T)(using Context): T =
val ectx = exploreCtx
try op(using ectx) finally wrapUpExplore(ectx)

private def changeOwnerCtx(owner: Symbol)(using Context): Context =
val base = ctx.base
import base._
Expand Down
8 changes: 6 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Decorators.scala
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,16 @@ object Decorators {
}

extension [T, U](xss: List[List[T]])
def nestedMap(f: T => U): List[List[U]] =
xss.map(_.map(f))
def nestedMap(f: T => U): List[List[U]] = xss match
case xs :: xss1 => xs.map(f) :: xss1.nestedMap(f)
case nil => Nil
def nestedMapConserve(f: T => U): List[List[U]] =
xss.mapconserve(_.mapconserve(f))
def nestedZipWithConserve(yss: List[List[U]])(f: (T, U) => T): List[List[T]] =
xss.zipWithConserve(yss)((xs, ys) => xs.zipWithConserve(ys)(f))
def nestedExists(p: T => Boolean): Boolean = xss match
case xs :: xss1 => xs.exists(p) || xss1.nestedExists(p)
case nil => false
end extension

extension (text: Text)
Expand Down
2 changes: 0 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -844,8 +844,6 @@ class Definitions {
@tu lazy val Not_value: Symbol = NotClass.companionModule.requiredMethod(nme.value)

@tu lazy val ValueOfClass: ClassSymbol = requiredClass("scala.ValueOf")
@tu lazy val StatsModule: Symbol = requiredModule("dotty.tools.dotc.util.Stats")
@tu lazy val Stats_doRecord: Symbol = StatsModule.requiredMethod("doRecord")

@tu lazy val FromDigitsClass: ClassSymbol = requiredClass("scala.util.FromDigits")
@tu lazy val FromDigits_WithRadixClass: ClassSymbol = requiredClass("scala.util.FromDigits.WithRadix")
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Denotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ object Denotations {
def mapInfo(f: Type => Type)(using Context): Denotation

/** If this denotation does not exist, fallback to alternative */
final def orElse(that: => Denotation): Denotation = if (this.exists) this else that
inline def orElse(inline that: Denotation): Denotation = if (this.exists) this else that

/** The set of alternative single-denotations making up this denotation */
final def alternatives: List[SingleDenotation] = altsWith(alwaysTrue)
Expand Down Expand Up @@ -596,7 +596,7 @@ object Denotations {
def mapInfo(f: Type => Type)(using Context): SingleDenotation =
derivedSingleDenotation(symbol, f(info))

def orElse(that: => SingleDenotation): SingleDenotation = if (this.exists) this else that
inline def orElse(inline that: SingleDenotation): SingleDenotation = if (this.exists) this else that

def altsWith(p: Symbol => Boolean): List[SingleDenotation] =
if (exists && p(symbol)) this :: Nil else Nil
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/core/NameKinds.scala
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ object NameKinds {
case class QualInfo(name: SimpleName) extends Info with QualifiedInfo {
override def map(f: SimpleName => SimpleName): NameInfo = new QualInfo(f(name))
override def toString: String = s"$infoString $name"
override def hashCode = scala.runtime.ScalaRunTime._hashCode(this) * 31 + kind.hashCode
}

def apply(qual: TermName, name: SimpleName): TermName =
Expand Down Expand Up @@ -173,6 +174,7 @@ object NameKinds {
type ThisInfo = NumberedInfo
case class NumberedInfo(val num: Int) extends Info with NameKinds.NumberedInfo {
override def toString: String = s"$infoString $num"
override def hashCode = scala.runtime.ScalaRunTime._hashCode(this) * 31 + kind.hashCode
}
def apply(qual: TermName, num: Int): TermName =
qual.derived(new NumberedInfo(num))
Expand Down Expand Up @@ -371,6 +373,7 @@ object NameKinds {
case class SignedInfo(sig: Signature) extends Info {
assert(sig ne Signature.NotAMethod)
override def toString: String = s"$infoString $sig"
override def hashCode = scala.runtime.ScalaRunTime._hashCode(this) * 31 + kind.hashCode
}
type ThisInfo = SignedInfo

Expand Down
Loading