Drop @inline from tests and incremental compilation

This commit is contained in:
Alexey Tsvetkov
2015-10-19 19:16:23 +03:00
parent df8066b1e4
commit d87ce33458
3 changed files with 89 additions and 29 deletions
@@ -0,0 +1,69 @@
/*
* Copyright 2010-2015 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.inline
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.serialization.Flags
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
import org.jetbrains.kotlin.serialization.jvm.BitEncoding
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
public fun inlineFunctionsJvmNames(bytes: ByteArray): Set<String> {
val header = readKotlinHeader(bytes)
val annotationData = header.annotationData
val strings = header.strings
if (annotationData == null || strings == null) return emptySet()
return when (header.kind) {
KotlinClassHeader.Kind.CLASS -> {
val classData = JvmProtoBufUtil.readClassDataFrom(BitEncoding.decodeBytes(annotationData), strings)
inlineFunctionsJvmNames(classData.classProto.functionList, classData.nameResolver, classData.classProto.typeTable)
}
KotlinClassHeader.Kind.FILE_FACADE,
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
val packageData = JvmProtoBufUtil.readPackageDataFrom(BitEncoding.decodeBytes(annotationData), strings)
inlineFunctionsJvmNames(packageData.packageProto.functionList, packageData.nameResolver, packageData.packageProto.typeTable)
}
else -> emptySet<String>()
}
}
private fun inlineFunctionsJvmNames(functions: List<ProtoBuf.Function>, nameResolver: NameResolver, protoTypeTable: ProtoBuf.TypeTable): Set<String> {
val typeTable = TypeTable(protoTypeTable)
val inlineFunctions = functions.filter { Flags.IS_INLINE.get(it.flags) }
val jvmNames = inlineFunctions.map {
JvmProtoBufUtil.getJvmMethodSignature(it, nameResolver, typeTable)
}
return jvmNames.filterNotNull().toSet()
}
private fun readKotlinHeader(bytes: ByteArray): KotlinClassHeader {
var header: KotlinClassHeader? = null
FileBasedKotlinClass.create(bytes) { className, classHeader, innerClasses ->
header = classHeader
null
}
if (header == null) throw AssertionError("Could not read kotlin header from byte array")
return header!!
}
@@ -17,10 +17,10 @@
package org.jetbrains.kotlin.codegen;
import org.jetbrains.kotlin.backend.common.output.OutputFile
import org.jetbrains.kotlin.inline.inlineFunctionsJvmNames
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
@@ -32,7 +32,6 @@ import kotlin.properties.Delegates
public object InlineTestUtil {
public val INLINE_ANNOTATION_CLASS: String = "kotlin/inline"
private val KOTLIN_PACKAGE_DESC = "L" + AsmUtil.internalNameByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_PACKAGE) + ";"
private val KOTLIN_MULTIFILE_CLASS_DESC = "L" + AsmUtil.internalNameByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS) + ";"
@@ -62,27 +61,28 @@ public object InlineTestUtil {
val classHeaders = hashMapOf<String, KotlinClassHeader>()
for (file in files) {
val cr = ClassReader(file.asByteArray())
val bytes = file.asByteArray()
val cr = ClassReader(bytes)
val inlineFunctions = inlineFunctionsJvmNames(bytes)
if (inlineFunctions.isEmpty()) continue
val classVisitor = object : ClassVisitorWithName() {
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor {
return object : MethodNode(Opcodes.ASM5, access, name, desc, signature, exceptions) {
public override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor {
val type = Type.getType(desc)
val annotationClass = type.getInternalName()
if (INLINE_ANNOTATION_CLASS == annotationClass) {
override fun visitEnd() {
if (name + desc in inlineFunctions) {
inlineMethods.add(MethodInfo(className, name, this.desc))
}
return super.visitAnnotation(desc, visible)
}
}
}
}
cr.accept(classVisitor, 0)
cr.accept(classVisitor, 0)
classHeaders.put(classVisitor.className, getClassHeader(file))
}
return InlineInfo(inlineMethods, classHeaders)
}
@@ -27,17 +27,15 @@ import org.jetbrains.jps.incremental.ModuleBuildTarget
import org.jetbrains.jps.incremental.storage.BuildDataManager
import org.jetbrains.jps.incremental.storage.PathStringDescriptor
import org.jetbrains.jps.incremental.storage.StorageOwner
import org.jetbrains.kotlin.inline.inlineFunctionsJvmNames
import org.jetbrains.kotlin.jps.build.GeneratedJvmClass
import org.jetbrains.kotlin.jps.build.KotlinBuilder
import org.jetbrains.kotlin.jps.incremental.storage.BasicMap
import org.jetbrains.kotlin.jps.incremental.storage.BasicStringMap
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
import org.jetbrains.kotlin.load.kotlin.ModuleMapping
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
import org.jetbrains.kotlin.load.kotlin.header.*
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.resolve.jvm.JvmClassName.byInternalName
import org.jetbrains.kotlin.serialization.jvm.BitEncoding
@@ -49,8 +47,6 @@ import java.io.File
import java.security.MessageDigest
import java.util.*
val INLINE_ANNOTATION_DESC = "Lkotlin/inline;"
internal val CACHE_DIRECTORY_NAME = "kotlin"
@TestOnly
@@ -451,26 +447,21 @@ public class IncrementalCacheImpl(
private fun getInlineFunctionsMap(bytes: ByteArray): Map<String, Long> {
val result = HashMap<String, Long>()
val inlineFunctions = inlineFunctionsJvmNames(bytes)
if (inlineFunctions.isEmpty()) return emptyMap()
ClassReader(bytes).accept(object : ClassVisitor(Opcodes.ASM5) {
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
val dummyClassWriter = ClassWriter(Opcodes.ASM5)
return object : MethodVisitor(Opcodes.ASM5, dummyClassWriter.visitMethod(0, name, desc, null, exceptions)) {
var hasInlineAnnotation = false
override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? {
if (desc == INLINE_ANNOTATION_DESC) {
hasInlineAnnotation = true
}
return null
}
override fun visitEnd() {
if (hasInlineAnnotation) {
val dummyBytes = dummyClassWriter.toByteArray()!!
val hash = dummyBytes.md5()
val jvmName = name + desc
if (jvmName !in inlineFunctions) return
result[name + desc] = hash
}
val dummyBytes = dummyClassWriter.toByteArray()!!
val hash = dummyBytes.md5()
result[jvmName] = hash
}
}
}