org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructors.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2016 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.codegen.intrinsics
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.inline.ReificationArgument
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.commons.Method
import org.jetbrains.org.objectweb.asm.tree.MethodNode
internal object IntrinsicArrayConstructors {
fun isArrayOf(descriptor: FunctionDescriptor): Boolean =
descriptor.name.asString() == "arrayOf" && descriptor.containingDeclaration.isBuiltInsPackage
fun isEmptyArray(descriptor: FunctionDescriptor): Boolean =
descriptor.name.asString() == "emptyArray" && descriptor.containingDeclaration.isBuiltInsPackage
private val DeclarationDescriptor.isBuiltInsPackage: Boolean
get() = this is PackageFragmentDescriptor && fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME
fun generateArrayConstructorBody(method: Method): MethodNode {
val node = MethodNode(
Opcodes.ASM6, Opcodes.ACC_PUBLIC or Opcodes.ACC_STATIC or Opcodes.ACC_FINAL, method.name, method.descriptor, null, null
)
val arrayType = method.returnType
val elementType = AsmUtil.correctElementType(arrayType)
val size = StackValue.local(0, Type.INT_TYPE)
val lambda = StackValue.local(1, AsmTypes.FUNCTION1)
val loopIndex = StackValue.local(2, Type.INT_TYPE)
val array = StackValue.local(3, arrayType)
/*
inline fun Array(size: Int, init: (Int) -> T): Array {
val result = arrayOfNulls(size)
for (i in 0 until size) {
result[i] = init(i)
}
return result as Array
}
*/
val iv = InstructionAdapter(node)
size.put(iv)
if (elementType.sort == Type.OBJECT) {
ReifiedTypeInliner.putReifiedOperationMarker(ReifiedTypeInliner.OperationKind.NEW_ARRAY, ReificationArgument("T", true, 0), iv)
}
iv.newarray(elementType)
array.store(StackValue.onStack(arrayType), iv)
loopIndex.store(StackValue.constant(0), iv)
val begin = Label()
iv.visitLabel(begin)
loopIndex.put(iv)
size.put(iv)
val end = Label()
iv.ificmpge(end)
array.put(iv)
loopIndex.put(iv)
lambda.put(iv)
loopIndex.put(AsmUtil.boxType(Type.INT_TYPE), iv)
iv.invokeinterface(
AsmTypes.FUNCTION1.internalName, OperatorNameConventions.INVOKE.asString(),
Type.getMethodDescriptor(AsmTypes.OBJECT_TYPE, AsmTypes.OBJECT_TYPE)
)
StackValue.coerce(AsmTypes.OBJECT_TYPE, elementType, iv)
iv.astore(elementType)
iv.iinc(loopIndex.index, 1)
iv.goTo(begin)
iv.visitLabel(end)
array.put(iv)
iv.areturn(arrayType)
iv.visitMaxs(5, 4)
return node
}
fun generateEmptyArrayBody(method: Method): MethodNode {
val node = MethodNode(
Opcodes.ASM6, Opcodes.ACC_PUBLIC or Opcodes.ACC_STATIC or Opcodes.ACC_FINAL, method.name, method.descriptor, null, null
)
/*
inline fun emptyArray(): Array = arrayOfNulls(0) as Array
*/
val iv = InstructionAdapter(node)
iv.iconst(0)
ReifiedTypeInliner.putReifiedOperationMarker(ReifiedTypeInliner.OperationKind.NEW_ARRAY, ReificationArgument("T", true, 0), iv)
iv.newarray(AsmTypes.OBJECT_TYPE)
iv.areturn(AsmTypes.OBJECT_TYPE)
iv.visitMaxs(3, 1)
return node
}
fun generateArrayOfBody(method: Method): MethodNode {
val node = MethodNode(
Opcodes.ASM6, Opcodes.ACC_PUBLIC or Opcodes.ACC_STATIC or Opcodes.ACC_FINAL, method.name, method.descriptor, null, null
)
/*
inline fun arrayOf(vararg elements: T): Array = elements as Array
*/
val iv = InstructionAdapter(node)
iv.load(0, AsmTypes.OBJECT_TYPE)
iv.areturn(AsmTypes.OBJECT_TYPE)
iv.visitMaxs(1, 1)
return node
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy