[Klib] Split up IR header tables onto three parts

There was one monolith protobuf at irHeader.knd, it was
split up onto 4 parts due to performance issues:
  - a small irHeader with some basic info about a module
  - symbols table
  - types table
  - strings table
These 3 tables are then mmapped and accessed by index.
This commit is contained in:
Igor Chevdar
2019-06-05 19:56:31 +03:00
parent 5faccaa49e
commit 3e8f3e6f00
14 changed files with 315 additions and 519 deletions
@@ -22,7 +22,7 @@ fun String.parseKonanAbiVersion(): KotlinAbiVersion {
data class KotlinAbiVersion(val version: Int) {
companion object {
val CURRENT = KotlinAbiVersion(11)
val CURRENT = KotlinAbiVersion(12)
}
override fun toString() = "$version"
}
@@ -34,6 +34,9 @@ interface IrLibrary {
val dataFlowGraph: ByteArray?
val irHeader: ByteArray?
fun irDeclaration(index: Long, isLocal: Boolean): ByteArray
fun symbol(index: Int): ByteArray
fun type(index: Int): ByteArray
fun string(index: Int): ByteArray
}
val BaseKotlinLibrary.uniqueName: String
@@ -48,10 +48,18 @@ interface MetadataKotlinLibraryLayout : KotlinLibraryLayout {
interface IrKotlinLibraryLayout : KotlinLibraryLayout {
val irDir
get() = File(libDir, "ir")
val irFile
get() = File(irDir, "irCombined.knd")
val irTablesDir
get() = File(irDir, "ir_tables")
val irHeader
get() = File(irDir, "irHeaders.kni")
val irDeclarations
get() = File(irTablesDir, "irCombined.knd")
val irSymbols
get() = File(irTablesDir, "symbols.knt")
val irTypes
get() = File(irTablesDir, "types.knt")
val irStrings
get() = File(irTablesDir, "strings.knt")
val dataFlowGraphFile
get() = File(irDir, "module_data_flow_graph")
}
@@ -35,5 +35,8 @@ class SerializedMetadata(
class SerializedIr (
val module: ByteArray,
val symbolTableFilePath: String,
val typeTableFilePath: String,
val stringTableFilePath: String,
val combinedDeclarationFilePath: String
)
@@ -11,12 +11,16 @@ import org.jetbrains.kotlin.library.*
class IrWriterImpl(val irLayout: IrKotlinLibraryLayout) : IrWriter {
init {
irLayout.irDir.mkdirs()
irLayout.irTablesDir.mkdirs()
}
override fun addIr(ir: SerializedIr) {
irLayout.irHeader.writeBytes(ir.module)
// TODO: use Files.move.
File(ir.combinedDeclarationFilePath).copyTo(irLayout.irFile)
File(ir.combinedDeclarationFilePath).copyTo(irLayout.irDeclarations)
File(ir.symbolTableFilePath).copyTo(irLayout.irSymbols)
File(ir.typeTableFilePath).copyTo(irLayout.irTypes)
File(ir.stringTableFilePath).copyTo(irLayout.irStrings)
}
override fun addDataFlowGraph(dataFlowGraph: ByteArray) {
@@ -18,10 +18,8 @@ package org.jetbrains.kotlin.library.impl
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.library.impl.*
import org.jetbrains.kotlin.konan.properties.Properties
import org.jetbrains.kotlin.konan.properties.loadProperties
import org.jetbrains.kotlin.konan.properties.propertyList
open class BaseKotlinLibraryImpl(
private val access: BaseLibraryAccess<KotlinLibraryLayout>,
@@ -87,9 +85,33 @@ open class IrLibraryImpl(
override fun irDeclaration(index: Long, isLocal: Boolean) = loadIrDeclaraton(index, isLocal)
override fun symbol(index: Int) = symbols.tableItemBytes(index)
override fun type(index: Int) = types.tableItemBytes(index)
override fun string(index: Int) = strings.tableItemBytes(index)
private val combinedDeclarations: CombinedIrFileReader by lazy {
CombinedIrFileReader(access.realFiles {
it.irFile
it.irDeclarations
})
}
private val symbols: SimpleIrTableFileReader by lazy {
SimpleIrTableFileReader(access.realFiles {
it.irSymbols
})
}
private val types: SimpleIrTableFileReader by lazy {
SimpleIrTableFileReader(access.realFiles {
it.irTypes
})
}
private val strings: SimpleIrTableFileReader by lazy {
SimpleIrTableFileReader(access.realFiles {
it.irStrings
})
}
@@ -132,7 +132,13 @@ class ExtractingIrLibraryImpl(val zipped: IrLibraryLayoutImpl) :
ExtractingKotlinLibraryLayout(zipped),
IrKotlinLibraryLayout {
override val irFile: File by lazy { zipped.extract(zipped.irFile) }
override val irDeclarations: File by lazy { zipped.extract(zipped.irDeclarations) }
override val irSymbols: File by lazy { zipped.extract(zipped.irSymbols) }
override val irTypes: File by lazy { zipped.extract(zipped.irTypes) }
override val irStrings: File by lazy { zipped.extract(zipped.irStrings) }
}
internal fun zippedKotlinLibraryChecks(klibFile: File) {
@@ -0,0 +1,68 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.library.impl
import org.jetbrains.kotlin.konan.file.File
import java.io.RandomAccessFile
import java.nio.channels.FileChannel
import java.nio.file.Files
class SimpleIrTableFileReader(file: File) {
private val buffer = file.map(FileChannel.MapMode.READ_ONLY)
private val indexToOffset: IntArray
init {
val count = buffer.int
indexToOffset = IntArray(count + 1)
indexToOffset[0] = 4 * (count + 1)
for (i in 0 until count) {
val size = buffer.int
indexToOffset[i + 1] = indexToOffset[i] + size
}
}
fun tableItemBytes(id: Int): ByteArray {
val offset = indexToOffset[id]
val size = indexToOffset[id + 1] - offset
val result = ByteArray(size)
buffer.position(offset)
buffer.get(result, 0, size)
return result
}
}
class SimpleIrTableFileWriter(val tableName: String, val itemsCount: Int) {
private var currentItemIndex = 0
private var currentPosition = 0
private val file = Files.createTempFile(tableName, "").toFile()
private val randomAccessFile = RandomAccessFile(file.path, "rw")
init {
randomAccessFile.writeInt(itemsCount)
assert(randomAccessFile.filePointer.toInt() == 4)
for (i in 0 until itemsCount) {
randomAccessFile.writeInt(-1) // size
}
currentPosition = randomAccessFile.filePointer.toInt()
assert(currentPosition == 4 + 4 * itemsCount)
}
fun addItem(bytes: ByteArray) {
randomAccessFile.seek((currentItemIndex * 4 + 4).toLong())
randomAccessFile.writeInt(bytes.size)
randomAccessFile.seek(currentPosition.toLong())
randomAccessFile.write(bytes)
assert(randomAccessFile.filePointer < Int.MAX_VALUE.toLong())
currentPosition = randomAccessFile.filePointer.toInt()
currentItemIndex++
}
fun finishWriting(): java.io.File {
assert(currentItemIndex == itemsCount) { "Expected: $itemsCount, but was: $currentItemIndex" }
randomAccessFile.close()
return file
}
}