Skip to content

Some Optimizations in Backend #9866

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 4 commits into from
Sep 25, 2020
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
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
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
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 @@ -596,9 +596,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
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: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,7 @@ object SymDenotations {
else if is(NoDefaultParams) then false
else
val result =
rawParamss.exists(_.exists(_.is(HasDefault)))
rawParamss.nestedExists(_.is(HasDefault))
|| allOverriddenSymbols.exists(_.hasDefaultParams)
setFlag(if result then HasDefaultParams else NoDefaultParams)
result
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3856,7 +3856,7 @@ object Parsers {
val problem = tree match
case tree: MemberDef if !(tree.mods.flags & ModifierFlags).isEmpty =>
i"refinement cannot be ${(tree.mods.flags & ModifierFlags).flagStrings().mkString("`", "`, `", "`")}"
case tree: DefDef if tree.vparamss.exists(_.exists(!_.rhs.isEmpty)) =>
case tree: DefDef if tree.vparamss.nestedExists(!_.rhs.isEmpty) =>
i"refinement cannot have default arguments"
case tree: ValOrDefDef =>
if tree.rhs.isEmpty then ""
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>

/** Is there a repeated parameter in some parameter list? */
private def hasRepeatedParams(sym: Symbol)(using Context): Boolean =
sym.info.paramInfoss.flatten.exists(_.isRepeatedParam)
sym.info.paramInfoss.nestedExists(_.isRepeatedParam)

/** Is this the type of a method that has a repeated parameter type as
* its last parameter in the last parameter list?
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/util/SourcePosition.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ extends SrcPos, interfaces.SourcePosition, Showable {

def point: Int = span.point

def line: Int = if (source.content().length != 0) source.offsetToLine(point) else -1
def line: Int = if (source.length != 0) source.offsetToLine(point) else -1

/** Extracts the lines from the underlying source file as `Array[Char]`*/
def linesSlice: Array[Char] =
Expand Down