Without this commit, JVM name mapping logic in BE does not work for FIR,
because FIR cannot use old BuiltInsPackageFragmentImpl descriptor.
In this commit we add our own implementation thus fixing
a pack of FIR black box tests.
This could happen:
* when a common source set had no sources
* when the compile task of a common source set was disabled
In those cases, there were two subsequent failures:
* the metadata JAR could not interpret the missing klib file as ZIP
* the consumer could not read the empty klib in its dependencies
Issue #KT-36674 Fixed
* Add `ResolvedMppVariantsProvider` that provides variant names,
platform artifacts, and metadata artifacts for MPP dependencies
* Rework SourceSetVisibilityProvider.kt so that it uses the
`ResolvedMppVariantsProvider` to determine which source sets should be
read from which metadata artifacts
* Rework `GranularMetadataTransformation` and its consumers so that:
* it uses the
visibility result and extracts the source set metadata from the
host-specific artifacts whenever `SourceSetsVisibilityProvider`
yields host-specific artifacts in the visibility results
* it uses the new Gradle API for resolutionResults / artifactView
* Rework module IDs in the code base, unify the logic of their
construction, also fix possible false-positive visibility in
`applyToConfiguration` that used a module ID that mismatched the
published module ID.
Create the compilations even when all of the targets that the
shared-Native source set is compiled for are disabled on the current
host. In that case, disable the compilation task
Also clear the inputs of the disabled tasks so that when Gradle builds
the task graph it doesn't resolve the dependencies.
Otherwise, a Gradle build that includes the compile tasks of the
disabled targets in the task graph would fail as follows, e.g. on a
macOS host with a project containing a mingw target):
```
Could not determine the dependencies of task ':compileKotlinMingwX86'
...
Could not resolve all task dependencies for configuration
':mingwX86CompileKlibraries'
...
Could not find com.example:my-dependency-mingwx86:1.0
...
Consider host-specific all source sets that participate in a compilation
of a target that cannot be built on some of the hosts.
Exclude those source sets from the `-metadata` artifact since the
`metadata` target must publish in the same way from any host.
Instead, add a metadata variant to those targets which use such a source
set and pack the source set's klib into a similar metadata JAR as the
artifact of those metadata variants.
The JVM IR backend code seems saner to me. The string concatenation
lowering for JVM IR calls the stringPlus intrinsic if there are
only two arguments. That leads to a lot less code:
```
load string
load argument
box argument
call Intrinsics.stringPlus
```
instead of
```
allocate StringBuilder
call StringBuilder.<init>
load string
call StringBuilder.append
load argument
call StringBuilder.append
call StringBuilder.toString
```
This will lead to more boxing, but a lot smaller code. We still
use StringBuilders in JVM IR if there are more than two strings
being concatenated.
There are several performance optimizations:
* ByteBuffer/CharBuffer/StringBuilder objects pre-allocated and are
reused on each call to readLine.
* The state for readLine is lazily allocated via JVM classloading
(using a singleton object).
* There is an auto-detection heuristic for "directEOL" encodings which
represent LF ('\n') directly as the corresponding byte
(UTF-8 and many single-byte encodings are like that).
When "directEOL" encoding is used, then bytes are batched into
ByteBuffer for a single call to CharsetDecoder.decode which
results in higher throughput. Otherwise (UTF-16, etc), slower
byte-by-byte approach is used.
* Bytes and chars are directly moved in/out of byte/char arrays and
ByteBuffer/CharBuffer wrappers are used only to interface with
JVM CharsetDecoder class (which is the slowest piece).
* StringBuilder is not used at all for short lines (<=32 chars).
There are also some function improvements to readLine functionality:
* Restriction on "max chars per byte" is lifted, so readLine works with
all encodings that JVM supports.
* It support on-the-fly changes to system default charset, because
it rechecks current charset on each call and updates it decoder
when needed.
All the other features of readLine function are retained:
* It does not read more bytes from System.in than needed, so it
is compatible with other ways to read System.in. On-the-fly
changes to System.in are supported.
* It is thread-safe. Its internal mutable state is protected by
synchronization.
* There is an internal method for tests that supports explicit
charset specification, but the name of this method has changed.
There are additional tests:
* Check all supported encodings on JVM to make sure that readLine
works correctly with them all.
* Check unicode code points of different bits length with all standard
unicode encodings (UTF-8, UTF-16, and UTF-32 in LE/HE byte orders).
Benchmarks that compare different implementations of readLine,
including this one (readLine6NoLV in the set) can be found here:
https://github.com/elizarov/ReadLineBenchmark
Taking BufferedReader as 100% baseline we see that:
* Current readLine is 7.5 times slower than BufferedReader baseline.
* New implementation in this commit is 2.5 timer slower than baseline.
It is ~3 times faster than existing implementation of readLine.
Altogether these optimizations are enough to enable reading of
~500K lines in sports programming setting under 2s time-limit with
plenty of headroom in time. Example that is using this version of
readLine can be found here:
https://codeforces.com/contest/1322/submission/73005366
#KT-37416 Fixed
Added way to retrieve coroutine information without an agent
in target JVM. 'kotlin.debugger.coroutines.switch' provides
two possibilities to test coroutines.
Agent way gets activated once kotlinx.coroutines.debug.DebugProbes
started with javaagent.
Library-less ways use DispatchedContinuation or ChildContinuationImpl
classes to retrieve coroutine information and stack traces.