You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
scala-js#4997
This commit introduces linktime dispatching with a new `LinkTimeIf` IR node.
The condition of `LinkTimeIf` will be evaluated at link-time and the dead
branch be eliminated at link-time by Optimizer or linker backend.
For example,
```scala
import scala.scalajs.LikningInfo._
val env = linkTimeIf(productionMode) {
"prod"
} {
"dev"
}
```
The code above under `.withProductionMode(true)` links to the following
at runtime.
```scala
val env = "prod"
```
This feature was originally motivated to allow switching the library
implementation based on whether it targets browser Wasm or
standalone Wasm (see scala-js#4991).
However, it should prove useful for further optimization through link-time
information-based dispatching.
**`LinkTimeIf` IR Node**
This change introduces a new IR node
`LinkTimeIf(cond: LinkTimeTree, thenp: Tree, elsep: Tree)`,
that represents link-time dispatching.
`LinkTimeTree` is a small set of IR tree evaluated at link-time.
Currently, `LinkTimeTree` contains `BinaryOp`, `IntConst`, `BooleanConst`, and `Property`.
- `BinaryOp` representing a simple binary operation that evaluates to a boolean value.
- `IntConst` and `BooleanConst` holds a constant of the type.
- `Property` contains a key to resolve a value at link-time, where `LinkTimeProperties.scala` is responsible for managing and resolving the link-time value dictionary, which is accessible through `CoreSpec`.
For example, the following `LinkTimeIf` looks up the link-time value whose key is
"scala.scalajs.LinkingInfo.esVersion" and compares it with the integer constant 6.
```scala
LinkTimeIf(
BinaryOp(
BinaryOp.Int_>=,
Property("core/esVersion"),
IntConst(6),
),
thenp,
elsep
)
```
**`LinkingInfo.linkTimeIf` and `@linkTimeProperty` annotation**
This commit defines a new API to represent link-time dispatching:
`LinkingInfo.linkTimeIf(...) { } { }`, which compiles to the `LinkTimeIf` IR node.
For example, `linkTimeIf(esVersion >= ESVersion.ES2015)` compiles to the
IR above.
Note that only symbols annotated with `@linkTimeProperty` or int/boolean constants
can be used in the condition of `linkTimeIf`.
Currently, `@linkTimeProperty` is private to `scalajs` (users cannot define new link-time values),
and only a predefined set of link-time values are annotated
(`productionMode` and `esVersion` for now).
When `@linkTimeProperty(name)` annotated values are used in `linkTimeIf`,
they are translated to `LinkTimeValue.Property(name)`.
**LinkTimeProperties to resolve and evaluate LinkTimeCondition/Value**
This commit defines a `LinkTimeProperty` that belongs to the `CoreSpec`
(making it accessible from various linker stages).
It constructs a link-time value dictionary from `Semantics` and `ESFeatures`,
and is responsible for resolving `LinkTimeValue.Property` and evaluating `LinkTimeTree`.
**Analyzer doesn't follow the dead branch of linkTimeIf**
Now `Analyzer` evaluates the `LinkTimeIf` and follow only the live branch.
For example, under `productionMode = true`, `doSomethingDev` won't be
marked as reachable by `Analyzer`.
```scala
linkTimeIf(productionMode) {
doSomethingProd()
} {
doSomethingDev()
}
```
**Eliminate dead branch of LinkTimeIf**
Finally, the optimizer and linker-backends (in case the optimizer is
turned off) eliminate the dead branch of `LinkTimeIf`.
0 commit comments