JS: serialize .kjsm package-wise, adapt decompiler & stub builder

Instead of multiple .kjsm files for different classes and .kotlin_string_table,
.kotlin_file_table, .kotlin_classes files for each package, serialize the
contents of each package to a single foo/bar/baz/baz.kjsm file. The short name
of the file is the last segment in the FQ name of the package, or
"root-package" if the package is root.

There are two main reasons for this change:
1) Such structure takes less space, is more IO-friendly and will not cause
   multiple exceptions as the old one, where we sometimes tried to read
   non-existing files
2) This is exactly the same format that is used to serialize built-in
   declarations (.kotlin_builtins) at the moment, which will allow us to reuse
   some code

Also write a separate Header protobuf message to the beginning of the .kjsm
file. This will be used as arguments of the kotlin.Metadata annotation are used
in the JVM-specific parts of the compiler: to be able to provide some general
information about the binary file without parsing the whole protobuf data.

This commit breaks decompiled text & stub builder consistency tests. This is OK
because they're removed in a future commit.

Fixes EA-79605, EA-81947, EA-84277 and maybe EA-86787

 #KT-10894 Fixed
 #KT-14124 Fixed
 #KT-15755 Fixed
This commit is contained in:
Alexander Udalov
2017-01-25 15:17:57 +03:00
parent 46bf057b47
commit 63c24c56ec
23 changed files with 1660 additions and 419 deletions
@@ -17,7 +17,9 @@
package org.jetbrains.kotlin.utils
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
import java.io.DataInputStream
import java.io.File
import java.io.InputStream
import javax.xml.bind.DatatypeConverter.parseBase64Binary
import javax.xml.bind.DatatypeConverter.printBase64Binary
@@ -31,10 +33,21 @@ class JsBinaryVersion(vararg numbers: Int) : BinaryVersion(*numbers) {
companion object {
@JvmField
val INSTANCE = JsBinaryVersion(0, 7, 0)
val INSTANCE = JsBinaryVersion(0, 8, 0)
@JvmField
val INVALID_VERSION = JsBinaryVersion()
fun readFrom(stream: InputStream): JsBinaryVersion {
val dataInput = DataInputStream(stream)
val size = dataInput.readInt()
// We assume here that the version will always have 3 components. This is needed to prevent reading an unpredictable amount
// of integers from old .kjsm files (pre-1.1) because they did not have the version in the beginning
if (size != INSTANCE.toArray().size) return INVALID_VERSION
return JsBinaryVersion(*(1..size).map { dataInput.readInt() }.toIntArray())
}
}
}