Skip to content

Commit 7230580

Browse files
committed
Add -opt:l:inline and -opt-inline-from, deprecate -opt:l:classpath
Introduce the optimizer level `-opt:l:inline` and a new setting `-opt-inline-from` to control what classes we inline from. `-opt:l:classpath` and `-opt:l:project` continue to work in the same way, with a deprecation warning.
1 parent 1cebf8f commit 7230580

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+128
-86
lines changed

project/ScriptCommands.scala

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ object ScriptCommands {
2020
) ++ (args match {
2121
case Seq(url) => publishTarget(url)
2222
case Nil => Nil
23-
}) ++ noDocs ++ enableOptimizer
23+
}) ++ noDocs ++ enableOptimizerOldFlag
2424
}
2525

2626
/** Set up the environment for `validate/test`.
@@ -31,7 +31,7 @@ object ScriptCommands {
3131
) ++ (args match {
3232
case Seq(url) => Seq(resolvers in Global += "scala-pr" at url)
3333
case Nil => Nil
34-
}) ++ enableOptimizer
34+
}) ++ enableOptimizerNewFlags
3535
}
3636

3737
/** Set up the environment for building STARR in `validate/bootstrap`. The arguments are:
@@ -41,7 +41,7 @@ object ScriptCommands {
4141
Seq(
4242
baseVersion in Global := ver,
4343
baseVersionSuffix in Global := "SPLIT"
44-
) ++ publishTarget(url) ++ noDocs ++ enableOptimizer
44+
) ++ publishTarget(url) ++ noDocs ++ enableOptimizerOldFlag
4545
}
4646

4747
/** Set up the environment for building locker in `validate/bootstrap`. The arguments are:
@@ -52,7 +52,7 @@ object ScriptCommands {
5252
baseVersion in Global := ver,
5353
baseVersionSuffix in Global := "SPLIT",
5454
resolvers in Global += "scala-pr" at url
55-
) ++ publishTarget(url) ++ noDocs ++ enableOptimizer
55+
) ++ publishTarget(url) ++ noDocs ++ enableOptimizerOldFlag
5656
}
5757

5858
/** Set up the environment for building quick in `validate/bootstrap`. The arguments are:
@@ -64,7 +64,7 @@ object ScriptCommands {
6464
baseVersionSuffix in Global := "SPLIT",
6565
resolvers in Global += "scala-pr" at url,
6666
testOptions in IntegrationTest in LocalProject("test") ++= Seq(Tests.Argument("--show-log"), Tests.Argument("--show-diff"))
67-
) ++ publishTarget(url) ++ enableOptimizer
67+
) ++ publishTarget(url) ++ enableOptimizerNewFlags
6868
}
6969

7070
/** Set up the environment for publishing in `validate/bootstrap`. The arguments are:
@@ -81,7 +81,7 @@ object ScriptCommands {
8181
publishTo in Global := Some("sonatype-releases" at "https://oss.sonatype.org/service/local/staging/deploy/maven2"),
8282
credentials in Global += Credentials(Path.userHome / ".credentials-sonatype"),
8383
pgpPassphrase in Global := Some(Array.empty)
84-
) ++ enableOptimizer
84+
) ++ enableOptimizerNewFlags
8585
}
8686

8787
private[this] def setup(name: String)(f: Seq[String] => Seq[Setting[_]]) =
@@ -92,8 +92,13 @@ object ScriptCommands {
9292
logLevel in update in ThisBuild := Level.Warn
9393
)
9494

95-
private[this] val enableOptimizer = Seq(
96-
scalacOptions in Compile in ThisBuild += "-opt:l:classpath"
95+
// TODO: remove this once the STARR accepts the new flags
96+
private[this] val enableOptimizerOldFlag = Seq(
97+
scalacOptions in Compile in ThisBuild ++= Seq("-opt:l:classpath")
98+
)
99+
100+
private[this] val enableOptimizerNewFlags = Seq(
101+
scalacOptions in Compile in ThisBuild ++= Seq("-opt:l:inline", "-opt-inline-from", "scala/**")
97102
)
98103

99104
private[this] val noDocs = Seq(

src/compiler/scala/tools/nsc/Global.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,7 +1295,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
12951295
unitbuf += unit
12961296
compiledFiles += unit.source.file.path
12971297
}
1298-
private def warnDeprecatedAndConflictingSettings(unit: CompilationUnit) {
1298+
private def warnDeprecatedAndConflictingSettings() {
12991299
// issue warnings for any usage of deprecated settings
13001300
settings.userSetSettings filter (_.isDeprecated) foreach { s =>
13011301
currentRun.reporting.deprecationWarning(NoPosition, s.name + " is deprecated: " + s.deprecationMessage.get, "")
@@ -1396,7 +1396,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
13961396
def compileSources(sources: List[SourceFile]) = if (!reporter.hasErrors) {
13971397

13981398
def checkDeprecations() = {
1399-
warnDeprecatedAndConflictingSettings(newCompilationUnit(""))
1399+
warnDeprecatedAndConflictingSettings()
14001400
reporting.summarizeErrors()
14011401
}
14021402

@@ -1418,7 +1418,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
14181418
val startTime = currentTime
14191419

14201420
reporter.reset()
1421-
warnDeprecatedAndConflictingSettings(unitbuf.head)
1421+
warnDeprecatedAndConflictingSettings()
14221422
globalPhase = fromPhase
14231423

14241424
while (globalPhase.hasNext && !reporter.hasErrors) {

src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) {
387387
calleeInfoWarning: Option[CalleeInfoWarning]) {
388388
override def toString = s"Callee($calleeDeclarationClass.${callee.name})"
389389

390-
def canInlineFromSource = inlinerHeuristics.canInlineFromSource(sourceFilePath)
390+
def canInlineFromSource = inlinerHeuristics.canInlineFromSource(sourceFilePath, calleeDeclarationClass.internalName)
391391
def isAbstract = isAbstractMethod(callee)
392392
def isSpecialMethod = isConstructor(callee) || isNativeMethod(callee) || hasCallerSensitiveAnnotation(callee)
393393

src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,23 @@ import scala.tools.asm.Opcodes
1515
import scala.tools.asm.tree.{AbstractInsnNode, MethodInsnNode, MethodNode}
1616
import scala.tools.nsc.backend.jvm.BTypes.InternalName
1717
import scala.tools.nsc.backend.jvm.BackendReporting.{CalleeNotFinal, OptimizerWarning}
18-
import scala.collection.mutable
18+
import scala.tools.nsc.backend.jvm.opt.InlinerHeuristics.InlineSourceMatcher
1919

2020
class InlinerHeuristics[BT <: BTypes](val bTypes: BT) {
2121
import bTypes._
2222
import callGraph._
2323

24+
val inlineSourceMatcher = new InlineSourceMatcher(compilerSettings.optInlineFrom.value)
25+
2426
final case class InlineRequest(callsite: Callsite, post: List[InlineRequest], reason: String) {
2527
// invariant: all post inline requests denote callsites in the callee of the main callsite
2628
for (pr <- post) assert(pr.callsite.callsiteMethod == callsite.callee.get.callee, s"Callsite method mismatch: main $callsite - post ${pr.callsite}")
2729
}
2830

29-
def canInlineFromSource(sourceFilePath: Option[String]) = compilerSettings.optInlineGlobal || sourceFilePath.isDefined
31+
def canInlineFromSource(sourceFilePath: Option[String], calleeDeclarationClass: InternalName) = {
32+
compilerSettings.optLClasspath || (compilerSettings.optLProject && sourceFilePath.isDefined) ||
33+
inlineSourceMatcher.allow(calleeDeclarationClass)
34+
}
3035

3136
/**
3237
* Select callsites from the call graph that should be inlined, grouped by the containing method.

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

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -234,23 +234,36 @@ trait ScalaSettings extends AbsScalaSettings
234234
val boxUnbox = Choice("box-unbox", "Eliminate box-unbox pairs within the same method (also tuples, xRefs, value class instances). Enables unreachable-code.")
235235
val nullnessTracking = Choice("nullness-tracking", "Track nullness / non-nullness of local variables and apply optimizations.")
236236
val closureInvocations = Choice("closure-invocations" , "Rewrite closure invocations to the implementation method.")
237-
val inlineProject = Choice("inline-project", "Inline only methods defined in the files being compiled. Enables unreachable-code.")
238-
val inlineGlobal = Choice("inline-global", "Inline methods from any source, including classfiles on the compile classpath. Enables unreachable-code.")
237+
val inline = Choice("inline", "Inline method invocations according to -Yopt-inline-heuristics and -opt-inlnie-from.")
239238

240239
// note: unlike the other optimizer levels, "l:none" appears up in the `opt.value` set because it's not an expanding option (expandsTo is empty)
241-
val lNone = Choice("l:none", "Disable optimizations. Takes precedence: `-opt:l:none,+box-unbox` / `-opt:l:none -opt:box-unbox` don't enable box-unbox.")
240+
val lNone = Choice("l:none",
241+
"Disable optimizations. Takes precedence: `-opt:l:none,+box-unbox` / `-opt:l:none -opt:box-unbox` don't enable box-unbox.")
242242

243243
private val defaultChoices = List(unreachableCode)
244-
val lDefault = Choice("l:default", "Enable default optimizations: "+ defaultChoices.mkString("", ",", "."), expandsTo = defaultChoices)
244+
val lDefault = Choice(
245+
"l:default",
246+
"Enable default optimizations: " + defaultChoices.mkString("", ",", "."),
247+
expandsTo = defaultChoices)
245248

246249
private val methodChoices = List(unreachableCode, simplifyJumps, compactLocals, copyPropagation, redundantCasts, boxUnbox, nullnessTracking, closureInvocations)
247-
val lMethod = Choice("l:method", "Enable intra-method optimizations: "+ methodChoices.mkString("", ",", "."), expandsTo = methodChoices)
248-
249-
private val projectChoices = List(lMethod, inlineProject)
250-
val lProject = Choice("l:project", "Enable cross-method optimizations within the current project: "+ projectChoices.mkString("", ",", "."), expandsTo = projectChoices)
251-
252-
private val classpathChoices = List(lProject, inlineGlobal)
253-
val lClasspath = Choice("l:classpath", "Enable cross-method optimizations across the entire classpath: "+ classpathChoices.mkString("", ",", "."), expandsTo = classpathChoices)
250+
val lMethod = Choice(
251+
"l:method",
252+
"Enable intra-method optimizations: " + methodChoices.mkString("", ",", "."),
253+
expandsTo = methodChoices)
254+
255+
private val inlineChoices = List(lMethod, inline)
256+
val lInline = Choice("l:inline",
257+
"Enable cross-method optimizations: " + inlineChoices.mkString("", ",", "."),
258+
expandsTo = inlineChoices)
259+
260+
val lProject = Choice(
261+
"l:project",
262+
"[deprecated, use -opt:l:inline, -opt-inlnie-from] Enable cross-method optimizations within the current project.")
263+
264+
val lClasspath = Choice(
265+
"l:classpath",
266+
"[deprecated, use -opt:l:inline, -opt-inlnie-from] Enable cross-method optimizations across the entire classpath.")
254267
}
255268

256269
// We don't use the `default` parameter of `MultiChoiceSetting`: it specifies the default values
@@ -260,7 +273,11 @@ trait ScalaSettings extends AbsScalaSettings
260273
name = "-opt",
261274
helpArg = "optimization",
262275
descr = "Enable optimizations",
263-
domain = optChoices)
276+
domain = optChoices).withPostSetHook(s => {
277+
import optChoices._
278+
if (!s.value.contains(inline) && (s.value.contains(lProject) || s.value.contains(lClasspath)))
279+
s.enable(lInline)
280+
})
264281

265282
private def optEnabled(choice: optChoices.Choice) = {
266283
!opt.contains(optChoices.lNone) && {
@@ -278,14 +295,21 @@ trait ScalaSettings extends AbsScalaSettings
278295
def optBoxUnbox = optEnabled(optChoices.boxUnbox)
279296
def optNullnessTracking = optEnabled(optChoices.nullnessTracking)
280297
def optClosureInvocations = optEnabled(optChoices.closureInvocations)
298+
def optInlinerEnabled = optEnabled(optChoices.inline)
281299

282-
def optInlineProject = optEnabled(optChoices.inlineProject)
283-
def optInlineGlobal = optEnabled(optChoices.inlineGlobal)
284-
def optInlinerEnabled = optInlineProject || optInlineGlobal
300+
// deprecated inliner levels
301+
def optLProject = optEnabled(optChoices.lProject)
302+
def optLClasspath = optEnabled(optChoices.lClasspath)
285303

286304
def optBuildCallGraph = optInlinerEnabled || optClosureInvocations
287305
def optAddToBytecodeRepository = optBuildCallGraph || optInlinerEnabled || optClosureInvocations
288306

307+
val optInlineFrom = StringSetting(
308+
"-opt-inline-from",
309+
"patterns",
310+
"Classfile name patterns from which to allow inlining. ** = anything, * = package or class name, ! to exclude. Example: scala.**:!scala.Predef$:corp.*.util.*:corp.**.*Util*",
311+
"")
312+
289313
val YoptInlineHeuristics = ChoiceSetting(
290314
name = "-Yopt-inline-heuristics",
291315
helpArg = "strategy",
@@ -360,8 +384,11 @@ trait ScalaSettings extends AbsScalaSettings
360384
val future = BooleanSetting("-Xfuture", "Turn on future language features.") enablingIfNotSetByUser futureSettings
361385
val optimise = BooleanSetting("-optimise", "Compiler flag for the optimizer in Scala 2.11")
362386
.withAbbreviation("-optimize")
363-
.withDeprecationMessage("In 2.12, -optimise enables -opt:l:classpath. Check -opt:help for using the Scala 2.12 optimizer.")
364-
.withPostSetHook(_ => opt.tryToSet(List(optChoices.lClasspath.name)))
387+
.withDeprecationMessage("In 2.12, -optimise enables -opt:l:inline -opt-inline-from **. Check -opt:help for using the Scala 2.12 optimizer.")
388+
.withPostSetHook(_ => {
389+
opt.enable(optChoices.lInline)
390+
optInlineFrom.value = "**"
391+
})
365392
val Xexperimental = BooleanSetting("-Xexperimental", "Enable experimental extensions.") enablingIfNotSetByUser experimentalSettings
366393

367394
// Feature extensions
@@ -405,6 +432,11 @@ trait ScalaSettings extends AbsScalaSettings
405432
}
406433
*/
407434

408-
None
435+
if (opt.value.contains(optChoices.lProject))
436+
Some("-opt:l:project is deprecated, use -opt:l:inline and -opt-inlnie-from")
437+
else if (opt.value.contains(optChoices.lClasspath))
438+
Some("-opt:l:classpath is deprecated, use -opt:l:inline and -opt-inlnie-from")
439+
else
440+
None
409441
}
410442
}

test/benchmarks/build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
scalaHome := Some(file("../../build/pack"))
22
scalaVersion := "2.12.1-dev"
3-
scalacOptions ++= Seq("-feature", "-opt:l:classpath")
3+
scalacOptions ++= Seq("-feature", "-opt:l:inline", "-opt-inline-from", "**")
44

55
lazy val root = (project in file(".")).
66
enablePlugins(JmhPlugin).
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
-opt:l:classpath
1+
-opt:l:inline -opt-inline-from **
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
-opt:l:classpath -Yopt-inline-heuristics:everything -opt-warnings:_ -Xfatal-warnings
1+
-opt:l:inline -opt-inline-from ** -Yopt-inline-heuristics:everything -opt-warnings:_ -Xfatal-warnings

test/files/neg/inlineMaxSize.flags

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
-Ydelambdafy:method -opt:l:classpath -opt-warnings -Xfatal-warnings
1+
-Ydelambdafy:method -opt:l:inline -opt-inline-from ** -opt-warnings -Xfatal-warnings
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
warning: -optimise is deprecated: In 2.12, -optimise enables -opt:l:classpath. Check -opt:help for using the Scala 2.12 optimizer.
1+
warning: -optimise is deprecated: In 2.12, -optimise enables -opt:l:inline -opt-inline-from **. Check -opt:help for using the Scala 2.12 optimizer.
22
error: No warnings can be incurred under -Xfatal-warnings.
33
one warning found
44
one error found

0 commit comments

Comments
 (0)