[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
@@ -97,9 +97,6 @@ message IrFile {
message IrModule {
required String name = 1;
repeated IrFile file = 2;
required IrSymbolTable symbol_table = 3;
required IrTypeTable type_table = 4;
required StringTable string_table = 5;
}
/* ------ String Table ------------------------------------------ */
@@ -1,108 +0,0 @@
/**
* Copyright 2010-2019 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.backend.common.library
import java.io.File
import java.io.RandomAccessFile
import java.nio.MappedByteBuffer
import java.nio.channels.FileChannel
import java.nio.file.Files
data class DeclarationId(val id: Long, val isLocal: Boolean)
fun File.map(mode: FileChannel.MapMode = FileChannel.MapMode.READ_ONLY,
start: Long = 0, size: Long = -1): MappedByteBuffer {
val file = RandomAccessFile(path,
if (mode == FileChannel.MapMode.READ_ONLY) "r" else "rw")
val fileSize = if (mode == FileChannel.MapMode.READ_ONLY)
file.length() else size.also { assert(size != -1L) }
val channel = file.channel
return channel.map(mode, start, fileSize)
.also { channel.close() } // Channel close closes the file also.
}
class CombinedIrFileReader(file: File) {
private val buffer = file.map(FileChannel.MapMode.READ_ONLY)
private val declarationToOffsetSize = mutableMapOf<DeclarationId, Pair<Int, Int>>()
init {
val declarationsCount = buffer.int
for (i in 0 until declarationsCount) {
val id = buffer.long
val isLocal = buffer.int != 0
val offset = buffer.int
val size = buffer.int
declarationToOffsetSize[DeclarationId(id, isLocal)] = offset to size
}
}
fun declarationBytes(id: DeclarationId): ByteArray {
val offsetSize = declarationToOffsetSize[id] ?: throw Error("No declaration with $id here")
val result = ByteArray(offsetSize.second)
buffer.position(offsetSize.first)
buffer.get(result, 0, offsetSize.second)
return result
}
}
private const val SINGLE_INDEX_RECORD_SIZE = 20 // sizeof(Long) + 3 * sizeof(Int).
private const val INDEX_HEADER_SIZE = 4 // sizeof(Int).
class CombinedIrFileWriter(val declarationCount: Int) {
private var currentDeclaration = 0
private var currentPosition = 0
private val file = Files.createTempFile("ir", "").toFile()
private val randomAccessFile = RandomAccessFile(file.path, "rw")
init {
randomAccessFile.writeInt(declarationCount)
assert(randomAccessFile.filePointer.toInt() == INDEX_HEADER_SIZE)
for (i in 0 until declarationCount) {
randomAccessFile.writeLong(-1) // id
randomAccessFile.writeInt(-1) // isLocal
randomAccessFile.writeInt(-1) // offset
randomAccessFile.writeInt(-1) // size
}
currentPosition = randomAccessFile.filePointer.toInt()
assert(currentPosition == INDEX_HEADER_SIZE + SINGLE_INDEX_RECORD_SIZE * declarationCount)
}
fun skipDeclaration() {
currentDeclaration++
}
fun addDeclaration(id: DeclarationId, bytes: ByteArray) {
randomAccessFile.seek((currentDeclaration * SINGLE_INDEX_RECORD_SIZE + INDEX_HEADER_SIZE).toLong())
randomAccessFile.writeLong(id.id)
randomAccessFile.writeInt(if (id.isLocal) 1 else 0)
randomAccessFile.writeInt(currentPosition)
randomAccessFile.writeInt(bytes.size)
randomAccessFile.seek(currentPosition.toLong())
randomAccessFile.write(bytes)
assert(randomAccessFile.filePointer < Int.MAX_VALUE.toLong())
currentPosition = randomAccessFile.filePointer.toInt()
currentDeclaration++
}
fun finishWriting(): File {
assert(currentDeclaration == declarationCount)
randomAccessFile.close()
return file
}
}
@@ -7,9 +7,10 @@ package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.backend.common.LoggingContext
import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.common.library.CombinedIrFileWriter
import org.jetbrains.kotlin.backend.common.library.DeclarationId
import org.jetbrains.kotlin.library.SerializedIr
import org.jetbrains.kotlin.library.impl.CombinedIrFileWriter
import org.jetbrains.kotlin.library.impl.DeclarationId
import org.jetbrains.kotlin.library.impl.SimpleIrTableFileWriter
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.ClassKind.*
import org.jetbrains.kotlin.descriptors.Modality
@@ -1205,6 +1206,9 @@ open class IrModuleSerializer(
}
lateinit var writer: CombinedIrFileWriter
lateinit var symbolTableWriter: SimpleIrTableFileWriter
lateinit var typeTableWriter: SimpleIrTableFileWriter
lateinit var stringTableWriter: SimpleIrTableFileWriter
fun serializeModule(module: IrModuleFragment): KotlinIr.IrModule {
val proto = KotlinIr.IrModule.newBuilder()
@@ -1217,23 +1221,27 @@ open class IrModuleSerializer(
module.files.forEach {
proto.addFile(serializeIrFile(it))
}
proto.symbolTable = KotlinIr.IrSymbolTable.newBuilder()
.addAllSymbols(protoSymbolArray)
.build()
proto.typeTable = KotlinIr.IrTypeTable.newBuilder()
.addAllTypes(protoTypeArray)
.build()
symbolTableWriter = SimpleIrTableFileWriter("symbols", protoSymbolArray.size)
for (protoSymbol in protoSymbolArray)
symbolTableWriter.addItem(protoSymbol.toByteArray())
proto.stringTable = KotlinIr.StringTable.newBuilder()
.addAllStrings(protoStringArray)
.build()
typeTableWriter = SimpleIrTableFileWriter("types", protoTypeArray.size)
for (protoSymbol in protoTypeArray)
typeTableWriter.addItem(protoSymbol.toByteArray())
stringTableWriter = SimpleIrTableFileWriter("strings", protoStringArray.size)
for (protoSymbol in protoStringArray)
stringTableWriter.addItem(protoSymbol.toByteArray())
return proto.build()
}
fun serializedIrModule(module: IrModuleFragment): SerializedIr {
val moduleHeader = serializeModule(module).toByteArray()
return SerializedIr(moduleHeader, writer.finishWriting().absolutePath)
return SerializedIr(moduleHeader, symbolTableWriter.finishWriting().absolutePath,
typeTableWriter.finishWriting().absolutePath,
stringTableWriter.finishWriting().absolutePath,
writer.finishWriting().absolutePath)
}
}
@@ -6719,44 +6719,35 @@ public final class KotlinIr {
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
java.util.List<org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFile>
getFileList();
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFile getFile(int index);
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
int getFileCount();
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrSymbolTable symbol_table = 3;</code>
*/
boolean hasSymbolTable();
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrSymbolTable symbol_table = 3;</code>
*/
org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable getSymbolTable();
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrTypeTable type_table = 4;</code>
*/
boolean hasTypeTable();
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrTypeTable type_table = 4;</code>
*/
org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable getTypeTable();
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.StringTable string_table = 5;</code>
*/
boolean hasStringTable();
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.StringTable string_table = 5;</code>
*/
org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable getStringTable();
}
/**
* Protobuf type {@code org.jetbrains.kotlin.backend.common.serialization.IrModule}
@@ -6829,45 +6820,6 @@ public final class KotlinIr {
file_.add(input.readMessage(org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFile.PARSER, extensionRegistry));
break;
}
case 26: {
org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable.Builder subBuilder = null;
if (((bitField0_ & 0x00000002) == 0x00000002)) {
subBuilder = symbolTable_.toBuilder();
}
symbolTable_ = input.readMessage(org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable.PARSER, extensionRegistry);
if (subBuilder != null) {
subBuilder.mergeFrom(symbolTable_);
symbolTable_ = subBuilder.buildPartial();
}
bitField0_ |= 0x00000002;
break;
}
case 34: {
org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable.Builder subBuilder = null;
if (((bitField0_ & 0x00000004) == 0x00000004)) {
subBuilder = typeTable_.toBuilder();
}
typeTable_ = input.readMessage(org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable.PARSER, extensionRegistry);
if (subBuilder != null) {
subBuilder.mergeFrom(typeTable_);
typeTable_ = subBuilder.buildPartial();
}
bitField0_ |= 0x00000004;
break;
}
case 42: {
org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable.Builder subBuilder = null;
if (((bitField0_ & 0x00000008) == 0x00000008)) {
subBuilder = stringTable_.toBuilder();
}
stringTable_ = input.readMessage(org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable.PARSER, extensionRegistry);
if (subBuilder != null) {
subBuilder.mergeFrom(stringTable_);
stringTable_ = subBuilder.buildPartial();
}
bitField0_ |= 0x00000008;
break;
}
}
}
} catch (org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException e) {
@@ -6924,12 +6876,24 @@ public final class KotlinIr {
private java.util.List<org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFile> file_;
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public java.util.List<org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFile> getFileList() {
return file_;
}
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public java.util.List<? extends org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFileOrBuilder>
getFileOrBuilderList() {
@@ -6937,75 +6901,45 @@ public final class KotlinIr {
}
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public int getFileCount() {
return file_.size();
}
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFile getFile(int index) {
return file_.get(index);
}
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFileOrBuilder getFileOrBuilder(
int index) {
return file_.get(index);
}
public static final int SYMBOL_TABLE_FIELD_NUMBER = 3;
private org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable symbolTable_;
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrSymbolTable symbol_table = 3;</code>
*/
public boolean hasSymbolTable() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrSymbolTable symbol_table = 3;</code>
*/
public org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable getSymbolTable() {
return symbolTable_;
}
public static final int TYPE_TABLE_FIELD_NUMBER = 4;
private org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable typeTable_;
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrTypeTable type_table = 4;</code>
*/
public boolean hasTypeTable() {
return ((bitField0_ & 0x00000004) == 0x00000004);
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrTypeTable type_table = 4;</code>
*/
public org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable getTypeTable() {
return typeTable_;
}
public static final int STRING_TABLE_FIELD_NUMBER = 5;
private org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable stringTable_;
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.StringTable string_table = 5;</code>
*/
public boolean hasStringTable() {
return ((bitField0_ & 0x00000008) == 0x00000008);
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.StringTable string_table = 5;</code>
*/
public org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable getStringTable() {
return stringTable_;
}
private void initFields() {
name_ = org.jetbrains.kotlin.backend.common.serialization.KotlinIr.String.getDefaultInstance();
file_ = java.util.Collections.emptyList();
symbolTable_ = org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable.getDefaultInstance();
typeTable_ = org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable.getDefaultInstance();
stringTable_ = org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable.getDefaultInstance();
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -7017,18 +6951,6 @@ public final class KotlinIr {
memoizedIsInitialized = 0;
return false;
}
if (!hasSymbolTable()) {
memoizedIsInitialized = 0;
return false;
}
if (!hasTypeTable()) {
memoizedIsInitialized = 0;
return false;
}
if (!hasStringTable()) {
memoizedIsInitialized = 0;
return false;
}
if (!getName().isInitialized()) {
memoizedIsInitialized = 0;
return false;
@@ -7039,14 +6961,6 @@ public final class KotlinIr {
return false;
}
}
if (!getSymbolTable().isInitialized()) {
memoizedIsInitialized = 0;
return false;
}
if (!getTypeTable().isInitialized()) {
memoizedIsInitialized = 0;
return false;
}
memoizedIsInitialized = 1;
return true;
}
@@ -7060,15 +6974,6 @@ public final class KotlinIr {
for (int i = 0; i < file_.size(); i++) {
output.writeMessage(2, file_.get(i));
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeMessage(3, symbolTable_);
}
if (((bitField0_ & 0x00000004) == 0x00000004)) {
output.writeMessage(4, typeTable_);
}
if (((bitField0_ & 0x00000008) == 0x00000008)) {
output.writeMessage(5, stringTable_);
}
output.writeRawBytes(unknownFields);
}
@@ -7086,18 +6991,6 @@ public final class KotlinIr {
size += org.jetbrains.kotlin.protobuf.CodedOutputStream
.computeMessageSize(2, file_.get(i));
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
size += org.jetbrains.kotlin.protobuf.CodedOutputStream
.computeMessageSize(3, symbolTable_);
}
if (((bitField0_ & 0x00000004) == 0x00000004)) {
size += org.jetbrains.kotlin.protobuf.CodedOutputStream
.computeMessageSize(4, typeTable_);
}
if (((bitField0_ & 0x00000008) == 0x00000008)) {
size += org.jetbrains.kotlin.protobuf.CodedOutputStream
.computeMessageSize(5, stringTable_);
}
size += unknownFields.size();
memoizedSerializedSize = size;
return size;
@@ -7196,12 +7089,6 @@ public final class KotlinIr {
bitField0_ = (bitField0_ & ~0x00000001);
file_ = java.util.Collections.emptyList();
bitField0_ = (bitField0_ & ~0x00000002);
symbolTable_ = org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable.getDefaultInstance();
bitField0_ = (bitField0_ & ~0x00000004);
typeTable_ = org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable.getDefaultInstance();
bitField0_ = (bitField0_ & ~0x00000008);
stringTable_ = org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable.getDefaultInstance();
bitField0_ = (bitField0_ & ~0x00000010);
return this;
}
@@ -7234,18 +7121,6 @@ public final class KotlinIr {
bitField0_ = (bitField0_ & ~0x00000002);
}
result.file_ = file_;
if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
to_bitField0_ |= 0x00000002;
}
result.symbolTable_ = symbolTable_;
if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
to_bitField0_ |= 0x00000004;
}
result.typeTable_ = typeTable_;
if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
to_bitField0_ |= 0x00000008;
}
result.stringTable_ = stringTable_;
result.bitField0_ = to_bitField0_;
return result;
}
@@ -7265,15 +7140,6 @@ public final class KotlinIr {
}
}
if (other.hasSymbolTable()) {
mergeSymbolTable(other.getSymbolTable());
}
if (other.hasTypeTable()) {
mergeTypeTable(other.getTypeTable());
}
if (other.hasStringTable()) {
mergeStringTable(other.getStringTable());
}
setUnknownFields(
getUnknownFields().concat(other.unknownFields));
return this;
@@ -7284,18 +7150,6 @@ public final class KotlinIr {
return false;
}
if (!hasSymbolTable()) {
return false;
}
if (!hasTypeTable()) {
return false;
}
if (!hasStringTable()) {
return false;
}
if (!getName().isInitialized()) {
return false;
@@ -7306,14 +7160,6 @@ public final class KotlinIr {
return false;
}
}
if (!getSymbolTable().isInitialized()) {
return false;
}
if (!getTypeTable().isInitialized()) {
return false;
}
return true;
}
@@ -7407,24 +7253,48 @@ public final class KotlinIr {
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public java.util.List<org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFile> getFileList() {
return java.util.Collections.unmodifiableList(file_);
}
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public int getFileCount() {
return file_.size();
}
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFile getFile(int index) {
return file_.get(index);
}
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public Builder setFile(
int index, org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFile value) {
@@ -7438,6 +7308,12 @@ public final class KotlinIr {
}
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public Builder setFile(
int index, org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFile.Builder builderForValue) {
@@ -7448,6 +7324,12 @@ public final class KotlinIr {
}
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public Builder addFile(org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFile value) {
if (value == null) {
@@ -7460,6 +7342,12 @@ public final class KotlinIr {
}
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public Builder addFile(
int index, org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFile value) {
@@ -7473,6 +7361,12 @@ public final class KotlinIr {
}
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public Builder addFile(
org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFile.Builder builderForValue) {
@@ -7483,6 +7377,12 @@ public final class KotlinIr {
}
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public Builder addFile(
int index, org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFile.Builder builderForValue) {
@@ -7493,6 +7393,12 @@ public final class KotlinIr {
}
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public Builder addAllFile(
java.lang.Iterable<? extends org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrFile> values) {
@@ -7504,6 +7410,12 @@ public final class KotlinIr {
}
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public Builder clearFile() {
file_ = java.util.Collections.emptyList();
@@ -7513,6 +7425,12 @@ public final class KotlinIr {
}
/**
* <code>repeated .org.jetbrains.kotlin.backend.common.serialization.IrFile file = 2;</code>
*
* <pre>
*required IrSymbolTable symbol_table = 3;
*required IrTypeTable type_table = 4;
*required StringTable string_table = 5;
* </pre>
*/
public Builder removeFile(int index) {
ensureFileIsMutable();
@@ -7521,186 +7439,6 @@ public final class KotlinIr {
return this;
}
private org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable symbolTable_ = org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable.getDefaultInstance();
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrSymbolTable symbol_table = 3;</code>
*/
public boolean hasSymbolTable() {
return ((bitField0_ & 0x00000004) == 0x00000004);
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrSymbolTable symbol_table = 3;</code>
*/
public org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable getSymbolTable() {
return symbolTable_;
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrSymbolTable symbol_table = 3;</code>
*/
public Builder setSymbolTable(org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable value) {
if (value == null) {
throw new NullPointerException();
}
symbolTable_ = value;
bitField0_ |= 0x00000004;
return this;
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrSymbolTable symbol_table = 3;</code>
*/
public Builder setSymbolTable(
org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable.Builder builderForValue) {
symbolTable_ = builderForValue.build();
bitField0_ |= 0x00000004;
return this;
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrSymbolTable symbol_table = 3;</code>
*/
public Builder mergeSymbolTable(org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable value) {
if (((bitField0_ & 0x00000004) == 0x00000004) &&
symbolTable_ != org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable.getDefaultInstance()) {
symbolTable_ =
org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable.newBuilder(symbolTable_).mergeFrom(value).buildPartial();
} else {
symbolTable_ = value;
}
bitField0_ |= 0x00000004;
return this;
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrSymbolTable symbol_table = 3;</code>
*/
public Builder clearSymbolTable() {
symbolTable_ = org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrSymbolTable.getDefaultInstance();
bitField0_ = (bitField0_ & ~0x00000004);
return this;
}
private org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable typeTable_ = org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable.getDefaultInstance();
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrTypeTable type_table = 4;</code>
*/
public boolean hasTypeTable() {
return ((bitField0_ & 0x00000008) == 0x00000008);
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrTypeTable type_table = 4;</code>
*/
public org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable getTypeTable() {
return typeTable_;
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrTypeTable type_table = 4;</code>
*/
public Builder setTypeTable(org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable value) {
if (value == null) {
throw new NullPointerException();
}
typeTable_ = value;
bitField0_ |= 0x00000008;
return this;
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrTypeTable type_table = 4;</code>
*/
public Builder setTypeTable(
org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable.Builder builderForValue) {
typeTable_ = builderForValue.build();
bitField0_ |= 0x00000008;
return this;
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrTypeTable type_table = 4;</code>
*/
public Builder mergeTypeTable(org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable value) {
if (((bitField0_ & 0x00000008) == 0x00000008) &&
typeTable_ != org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable.getDefaultInstance()) {
typeTable_ =
org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable.newBuilder(typeTable_).mergeFrom(value).buildPartial();
} else {
typeTable_ = value;
}
bitField0_ |= 0x00000008;
return this;
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.IrTypeTable type_table = 4;</code>
*/
public Builder clearTypeTable() {
typeTable_ = org.jetbrains.kotlin.backend.common.serialization.KotlinIr.IrTypeTable.getDefaultInstance();
bitField0_ = (bitField0_ & ~0x00000008);
return this;
}
private org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable stringTable_ = org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable.getDefaultInstance();
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.StringTable string_table = 5;</code>
*/
public boolean hasStringTable() {
return ((bitField0_ & 0x00000010) == 0x00000010);
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.StringTable string_table = 5;</code>
*/
public org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable getStringTable() {
return stringTable_;
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.StringTable string_table = 5;</code>
*/
public Builder setStringTable(org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable value) {
if (value == null) {
throw new NullPointerException();
}
stringTable_ = value;
bitField0_ |= 0x00000010;
return this;
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.StringTable string_table = 5;</code>
*/
public Builder setStringTable(
org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable.Builder builderForValue) {
stringTable_ = builderForValue.build();
bitField0_ |= 0x00000010;
return this;
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.StringTable string_table = 5;</code>
*/
public Builder mergeStringTable(org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable value) {
if (((bitField0_ & 0x00000010) == 0x00000010) &&
stringTable_ != org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable.getDefaultInstance()) {
stringTable_ =
org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable.newBuilder(stringTable_).mergeFrom(value).buildPartial();
} else {
stringTable_ = value;
}
bitField0_ |= 0x00000010;
return this;
}
/**
* <code>required .org.jetbrains.kotlin.backend.common.serialization.StringTable string_table = 5;</code>
*/
public Builder clearStringTable() {
stringTable_ = org.jetbrains.kotlin.backend.common.serialization.KotlinIr.StringTable.getDefaultInstance();
bitField0_ = (bitField0_ & ~0x00000010);
return this;
}
// @@protoc_insertion_point(builder_scope:org.jetbrains.kotlin.backend.common.serialization.IrModule)
}
@@ -66,6 +66,10 @@ abstract class KotlinIrLinker(
private var moduleLoops = mutableMapOf<Int, IrLoopBase>()
private val symbolProtosCache = mutableMapOf<Int, KotlinIr.IrSymbolData>()
private val typeProtosCache = mutableMapOf<Int, KotlinIr.IrType>()
private val stringsCache = mutableMapOf<Int, String>()
// This is a heavy initializer
val module = deserializeIrModuleHeader(moduleProto)
@@ -132,18 +136,36 @@ abstract class KotlinIrLinker(
else -> TODO("Unexpected classifier symbol kind: ${proto.kind}")
}
private fun loadSymbolProto(index: Int): KotlinIr.IrSymbolData {
return symbolProtosCache.getOrPut(index) {
loadSymbolProto(moduleDescriptor, index)
}
}
private fun loadTypeProto(index: Int): KotlinIr.IrType {
return typeProtosCache.getOrPut(index) {
loadTypeProto(moduleDescriptor, index)
}
}
private fun loadString(index: Int): String {
return stringsCache.getOrPut(index) {
loadString(moduleDescriptor, index)
}
}
override fun deserializeIrSymbol(proto: KotlinIr.IrSymbol): IrSymbol {
val symbolData = moduleProto.symbolTable.getSymbols(proto.index)
val symbolData = loadSymbolProto(proto.index)
return deserializeIrSymbolData(symbolData)
}
override fun deserializeIrType(proto: KotlinIr.IrTypeIndex): IrType {
val typeData = moduleProto.typeTable.getTypes(proto.index)
val typeData = loadTypeProto(proto.index)
return deserializeIrTypeData(typeData)
}
override fun deserializeString(proto: KotlinIr.String): String =
moduleProto.stringTable.getStrings(proto.index)
loadString(proto.index)
override fun deserializeLoopHeader(loopIndex: Int, loopBuilder: () -> IrLoopBase) =
moduleLoops.getOrPut(loopIndex, loopBuilder)
@@ -228,7 +250,7 @@ abstract class KotlinIrLinker(
when (deserializationStrategy) {
DeserializationStrategy.EXPLICITLY_EXPORTED -> {
fileProto.explicitlyExportedToCompilerList.forEach {
val symbolProto = moduleProto.symbolTable.getSymbols(it.index)
val symbolProto = loadSymbolProto(it.index)
reachableTopLevels.add(symbolProto.topLevelUniqId.uniqIdKey(moduleDescriptor))
}
}
@@ -293,12 +315,29 @@ abstract class KotlinIrLinker(
}
protected abstract fun reader(moduleDescriptor: ModuleDescriptor, uniqId: UniqId): ByteArray
protected abstract fun readSymbol(moduleDescriptor: ModuleDescriptor, symbolIndex: Int): ByteArray
protected abstract fun readType(moduleDescriptor: ModuleDescriptor, typeIndex: Int): ByteArray
protected abstract fun readString(moduleDescriptor: ModuleDescriptor, stringIndex: Int): ByteArray
private fun loadTopLevelDeclarationProto(uniqIdKey: UniqIdKey): KotlinIr.IrDeclaration {
val stream = reader(uniqIdKey.moduleOfOrigin!!, uniqIdKey.uniqId).codedInputStream
return KotlinIr.IrDeclaration.parseFrom(stream, newInstance())
}
private fun loadSymbolProto(moduleDescriptor: ModuleDescriptor, index: Int): KotlinIr.IrSymbolData {
val stream = readSymbol(moduleDescriptor, index).codedInputStream
return KotlinIr.IrSymbolData.parseFrom(stream, newInstance())
}
private fun loadTypeProto(moduleDescriptor: ModuleDescriptor, index: Int): KotlinIr.IrType {
val stream = readType(moduleDescriptor, index).codedInputStream
return KotlinIr.IrType.parseFrom(stream, newInstance())
}
private fun loadString(moduleDescriptor: ModuleDescriptor, index: Int): String {
return String(readString(moduleDescriptor, index))
}
private fun deserializeFileAnnotationsIfFirstUse(module: ModuleDescriptor, file: IrFile) {
val annotations = fileAnnotations[file] ?: return
file.annotations.addAll(deserializersForModules[module]!!.deserializeAnnotations(annotations))
@@ -36,6 +36,15 @@ class JsIrLinker(
override val ModuleDescriptor.irHeader: ByteArray?
get() = this.kotlinLibrary.irHeader
override fun readSymbol(moduleDescriptor: ModuleDescriptor, symbolIndex: Int) =
moduleDescriptor.kotlinLibrary.symbol(symbolIndex)
override fun readType(moduleDescriptor: ModuleDescriptor, typeIndex: Int) =
moduleDescriptor.kotlinLibrary.type(typeIndex)
override fun readString(moduleDescriptor: ModuleDescriptor, stringIndex: Int) =
moduleDescriptor.kotlinLibrary.string(stringIndex)
override fun declareForwardDeclarations() {
// since for `knownBuiltIns` such as FunctionN it is possible to have unbound symbols after deserialization
// reference them through out lazy symbol table
@@ -48,5 +57,4 @@ class JsIrLinker(
ArrayList(unboundTypeParameters).forEach { lazyWrapper.referenceTypeParameter(it.descriptor) }
}
}
}
}
@@ -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
}
}