Use annotation to distinct inline constructor

This commit is contained in:
Konstantin Anisimov
2017-05-10 17:35:45 +07:00
committed by KonstantinAnisimov
parent 31a24d4607
commit ba1f3d502e
5 changed files with 36 additions and 24 deletions
@@ -312,25 +312,13 @@ internal fun DeclarationDescriptor.getMemberScope(): MemberScope {
// It is possible to declare "external inline fun",
// but it doesn't have much sense for native,
// since externals don't have IR bodies.
// Enforce inlining of some constructors
private val mustInlineFunctions = setOf(
"kotlin.DoubleArray.<init>",
"kotlin.FloatArray.<init>",
"kotlin.ByteArray.<init>",
"kotlin.ShortArray.<init>",
"kotlin.IntArray.<init>",
"kotlin.LongArray.<init>",
"kotlin.CharArray.<init>",
"kotlin.BooleanArray.<init>"
)
// Enforce inlining of some constructors.
internal val FunctionDescriptor.needsInlining: Boolean
get() {
val needs = this.isInline && !this.isExternal
if (valueParameters.size != 2) return needs // Constructor must have two parameters.
if (mustInlineFunctions.contains(fqNameSafe.toString())) return true
return needs
val inlineConstructor = annotations.hasAnnotation(FqName("konan.internal.InlineConstructor"))
if (inlineConstructor) return true
return (this.isInline && !this.isExternal)
}
internal val FunctionDescriptor.needsSerializedIr: Boolean
@@ -40,11 +40,14 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor
private val inlineConstructor = FqName("konan.internal.InlineConstructor")
//-----------------------------------------------------------------------------//
internal class FunctionInlining(val context: Context): IrElementTransformerVoidWithContext() {
@@ -99,12 +102,14 @@ private class Inliner(val currentScope: ScopeWithIr, val context: Context) {
val copyIrElement = DeepCopyIrTreeWithDescriptors(currentScope.scope.scopeOwner, context) // Create DeepCopy for current scope.
val substituteMap = mutableMapOf<ValueDescriptor, IrExpression>()
var isInlineConstructor = false
//-------------------------------------------------------------------------//
fun inline(irCall : IrCall, // Call to be substituted.
functionDeclaration: IrFunction): IrReturnableBlockImpl { // Function to substitute.
isInlineConstructor = irCall.descriptor.annotations.hasAnnotation(inlineConstructor)
val inlineFunctionBody = inlineFunction(irCall, functionDeclaration)
val descriptorSubstitutor = copyIrElement.descriptorSubstitutorForExternalScope
currentScope.irElement.transformChildrenVoid(descriptorSubstitutor) // Transform calls to object that might be returned from inline function call.
@@ -365,15 +370,15 @@ private class Inliner(val currentScope: ScopeWithIr, val context: Context) {
fun generateIrCall(expression: IrDelegatingConstructorCallImpl): IrStatement {
if (!expression.descriptor.fqNameSafe.toString().contains("kotlin.IntArray.<init>")) return expression
if (!isInlineConstructor) return expression
val newExpression = IrCallImpl(
startOffset = expression.startOffset,
endOffset = expression.endOffset,
type = expression.descriptor.returnType,
descriptor = expression.descriptor,
typeArguments = expression.typeArguments,
origin = expression.origin
expression.startOffset,
expression.endOffset,
expression.descriptor.returnType,
expression.descriptor,
expression.typeArguments,
expression.origin
).apply {
expression.descriptor.valueParameters.forEach {
val valueArgument = expression.getValueArgument(it)
@@ -41,3 +41,11 @@ annotation class Intrinsic
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
annotation class ExportForCompiler
/**
* Annotated constructor will be inlined.
*/
@Target(AnnotationTarget.CONSTRUCTOR)
@Retention(AnnotationRetention.BINARY)
annotation class InlineConstructor
+3 -1
View File
@@ -16,12 +16,14 @@
package kotlin
import konan.internal.ExportForCompiler
import konan.internal.InlineConstructor
// TODO: remove that, as RTTI shall be per instantiation.
@ExportTypeInfo("theArrayTypeInfo")
public final class Array<T> {
// Constructors are handled with compiler magic.
public constructor(size: Int, init: (Int) -> T) {
@InlineConstructor
public constructor(size: Int, init: (Int) -> T): this(size) {
var index = 0
while (index < size) {
this[index] = init(index)
+9
View File
@@ -25,6 +25,7 @@ import kotlin.internal.PureReifiable
import kotlin.util.sortArrayComparable
import kotlin.util.sortArrayWith
import kotlin.util.sortArray
import konan.internal.InlineConstructor
// TODO: make all iterator() methods inline.
/**
@@ -41,6 +42,7 @@ public final class ByteArray {
* [init] function. The [init] function returns an array element given its index.
*/
// TODO: What about inline constructors?
@InlineConstructor
public constructor(size: Int, init: (Int) -> Byte): this(size) {
for (i in 0..size - 1) {
this[i] = init(i)
@@ -92,6 +94,7 @@ public final class CharArray {
* Creates a new array of the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
*/
@InlineConstructor
public constructor(size: Int, init: (Int) -> Char): this(size) {
for (i in 0..size - 1) {
this[i] = init(i)
@@ -142,6 +145,7 @@ public final class ShortArray {
* Creates a new array of the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
*/
@InlineConstructor
public constructor(size: Int, init: (Int) -> Short): this(size) {
for (i in 0..size - 1) {
this[i] = init(i)
@@ -192,6 +196,7 @@ public final class IntArray {
* Creates a new array of the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
*/
@InlineConstructor
public constructor(size: Int, init: (Int) -> Int): this(size) {
for (i in 0..size - 1) {
this[i] = init(i)
@@ -242,6 +247,7 @@ public final class LongArray {
* Creates a new array of the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
*/
@InlineConstructor
public constructor(size: Int, init: (Int) -> Long): this(size) {
for (i in 0..size - 1) {
this[i] = init(i)
@@ -292,6 +298,7 @@ public final class FloatArray {
* Creates a new array of the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
*/
@InlineConstructor
public constructor(size: Int, init: (Int) -> Float): this(size) {
for (i in 0..size - 1) {
this[i] = init(i)
@@ -338,6 +345,7 @@ public final class DoubleArray {
* Creates a new array of the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
*/
@InlineConstructor
public constructor(size: Int, init: (Int) -> Double): this(size) {
for (i in 0..size - 1) {
this[i] = init(i)
@@ -384,6 +392,7 @@ public final class BooleanArray {
* Creates a new array of the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
*/
@InlineConstructor
public constructor(size: Int, init: (Int) -> Boolean): this(size) {
for (i in 0..size - 1) {
this[i] = init(i)