From eefc49a617ea25836b0418df6ea0ccb998176cb7 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Thu, 3 May 2018 11:03:06 +0200 Subject: [PATCH] Use symbols to find local declarations in codegen --- .../backend/jvm/codegen/ExpressionCodegen.kt | 42 ++++++++++++------- .../backend/jvm/codegen/FunctionCodegen.kt | 39 +++++++---------- .../backend/jvm/codegen/irCodegenUtils.kt | 16 ++++++- 3 files changed, 57 insertions(+), 40 deletions(-) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 8c6a258a7eb..6aa5cef5b32 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -27,6 +27,8 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrTypeAlias import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -86,12 +88,12 @@ class BlockInfo private constructor(val parent: BlockInfo?) { } } -class VariableInfo(val descriptor: VariableDescriptor, val index: Int, val type: Type, val startLabel: Label) +class VariableInfo(val declaration: IrVariable, val index: Int, val type: Type, val startLabel: Label) @Suppress("IMPLICIT_CAST_TO_ANY") class ExpressionCodegen( val irFunction: IrFunction, - val frame: FrameMap, + val frame: IrFrameMap, val mv: InstructionAdapter, val classCodegen: ClassCodegen ) : IrElementVisitor, BaseExpressionCodegen { @@ -148,11 +150,11 @@ class ExpressionCodegen( private fun writeLocalVariablesInTable(info: BlockInfo) { val endLabel = markNewLabel() info.variables.forEach { - mv.visitLocalVariable(it.descriptor.name.asString(), it.type.descriptor, null, it.startLabel, endLabel, it.index) + mv.visitLocalVariable(it.declaration.name.asString(), it.type.descriptor, null, it.startLabel, endLabel, it.index) } info.variables.reversed().forEach { - frame.leave(it.descriptor) + frame.leave(it.declaration.symbol) } } @@ -293,14 +295,14 @@ class ExpressionCodegen( override fun visitVariable(declaration: IrVariable, data: BlockInfo): StackValue { val varType = typeMapper.mapType(declaration.descriptor) - val index = frame.enter(declaration.descriptor, varType) + val index = frame.enter(declaration.symbol, varType) declaration.initializer?.apply { StackValue.local(index, varType).store(gen(this, varType, data), mv) } val info = VariableInfo( - declaration.descriptor, + declaration, index, varType, markNewLabel() @@ -320,7 +322,7 @@ class ExpressionCodegen( } override fun visitGetValue(expression: IrGetValue, data: BlockInfo): StackValue { - return generateLocal(expression.descriptor, expression.asmType) + return generateLocal(expression.symbol, expression.asmType) } private fun generateFieldValue(expression: IrFieldAccessExpression, data: BlockInfo): StackValue { @@ -349,15 +351,23 @@ class ExpressionCodegen( return none() } - private fun generateLocal(descriptor: CallableDescriptor, type: Type): StackValue { - val index = findLocalIndex(descriptor) + private fun generateLocal(symbol: IrSymbol, type: Type): StackValue { + val index = findLocalIndex(symbol) StackValue.local(index, type).put(type, mv) return onStack(type) } - private fun findLocalIndex(descriptor: CallableDescriptor): Int { - return frame.getIndex(descriptor).apply { - if (this < 0) throw AssertionError("Non-mapped local variable descriptor: $descriptor") + private fun findLocalIndex(irSymbol: IrSymbol): Int { + return frame.getIndex(irSymbol).apply { + if (this < 0) { + if (irFunction.dispatchReceiverParameter != null) { + (irFunction.parent as? IrClass)?.takeIf { it.thisReceiver?.symbol == irSymbol }?.let { return 0 } + } + throw AssertionError( + "Non-mapped local declaration: " + + "${if (irSymbol.isBound) irSymbol.owner.dump() else irSymbol.descriptor} \n in ${irFunction.dump()}" + ) + } } } @@ -371,7 +381,7 @@ class ExpressionCodegen( override fun visitSetVariable(expression: IrSetVariable, data: BlockInfo): StackValue { val value = expression.value.accept(this, data) - StackValue.local(findLocalIndex(expression.descriptor), expression.descriptor.asmType).store(value, mv) + StackValue.local(findLocalIndex(expression.symbol), expression.descriptor.asmType).store(value, mv) return none() } @@ -729,13 +739,13 @@ class ExpressionCodegen( val clauseStart = markNewLabel() val descriptor = clause.parameter val descriptorType = descriptor.asmType - val index = frame.enter(descriptor, descriptorType) + val index = frame.enter(clause.catchParameter, descriptorType) mv.store(index, descriptorType) val catchBody = clause.result gen(catchBody, catchBody.asmType, data) - frame.leave(descriptor) + frame.leave(clause.catchParameter) val clauseEnd = markNewLabel() @@ -1014,7 +1024,7 @@ class ExpressionCodegen( return getOrCreateCallGenerator(descriptor, memberAccessExpression, mappings, false) } - override val frameMap: FrameMap + override val frameMap: IrFrameMap get() = frame override val visitor: InstructionAdapter get() = mv diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt index adc9de5565b..cf8818ad131 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt @@ -22,8 +22,7 @@ import org.jetbrains.kotlin.backend.common.lower.InitializersLowering import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.FunctionCodegen import org.jetbrains.kotlin.codegen.state.GenerationState -import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.util.dump @@ -55,8 +54,7 @@ open class FunctionCodegen(private val irFunction: IrFunction, private val class private fun doGenerate() { val signature = classCodegen.typeMapper.mapSignatureWithGeneric(descriptor, OwnerKind.IMPLEMENTATION) val isStatic = irFunction.isStatic - val frameMap = createFrameMapWithReceivers(classCodegen.state, descriptor, signature, isStatic) - + val frameMap = createFrameMapWithReceivers(classCodegen.state, irFunction, signature) val flags = calculateMethodFlags(isStatic) val methodVisitor = createMethod(flags, signature) @@ -90,7 +88,7 @@ open class FunctionCodegen(private val irFunction: IrFunction, private val class return flags } - open protected fun createMethod(flags: Int, signature: JvmMethodGenericSignature): MethodVisitor { + protected open fun createMethod(flags: Int, signature: JvmMethodGenericSignature): MethodVisitor { return classCodegen.visitor.newMethod( irFunction.OtherOrigin, flags, @@ -120,26 +118,21 @@ open class FunctionCodegen(private val irFunction: IrFunction, private val class fun createFrameMapWithReceivers( state: GenerationState, - function: FunctionDescriptor, - signature: JvmMethodSignature, - isStatic: Boolean -): FrameMap { - val frameMap = FrameMap() - if (!isStatic) { - val descriptorForThis = - if (function is ClassConstructorDescriptor) - function.containingDeclaration.thisAsReceiverParameter - else - function.dispatchReceiverParameter - - frameMap.enter(descriptorForThis, AsmTypes.OBJECT_TYPE) + irFunction: IrFunction, + signature: JvmMethodSignature +): IrFrameMap { + val frameMap = IrFrameMap() + if (irFunction is IrConstructor) { + frameMap.enter((irFunction.parent as IrClass).thisReceiver!!, AsmTypes.OBJECT_TYPE) + } else if (irFunction.dispatchReceiverParameter != null) { + frameMap.enter(irFunction.dispatchReceiverParameter!!, AsmTypes.OBJECT_TYPE) } for (parameter in signature.valueParameters) { if (parameter.kind == JvmMethodParameterKind.RECEIVER) { - val receiverParameter = function.extensionReceiverParameter - if (receiverParameter != null) { - frameMap.enter(receiverParameter, state.typeMapper.mapType(receiverParameter)) + val receiverParameter = irFunction.extensionReceiverParameter + if (receiverParameter?.descriptor != null) { + frameMap.enter(receiverParameter, state.typeMapper.mapType(receiverParameter.descriptor)) } else { frameMap.enterTemp(parameter.asmType) } @@ -148,8 +141,8 @@ fun createFrameMapWithReceivers( } } - for (parameter in function.valueParameters) { - frameMap.enter(parameter, state.typeMapper.mapType(parameter)) + for (parameter in irFunction.valueParameters) { + frameMap.enter(parameter, state.typeMapper.mapType(parameter.type)) } return frameMap diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt index 77af54a1118..2b62d19883f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt @@ -5,8 +5,22 @@ package org.jetbrains.kotlin.backend.jvm.codegen +import org.jetbrains.kotlin.codegen.FrameMapBase import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.org.objectweb.asm.Type + +class IrFrameMap : FrameMapBase() internal val IrFunction.isStatic - get() = this.dispatchReceiverParameter == null && this !is IrConstructor \ No newline at end of file + get() = this.dispatchReceiverParameter == null && this !is IrConstructor + +fun IrFrameMap.enter(irDeclaration: IrSymbolOwner, type: Type): Int { + return enter(irDeclaration.symbol, type) +} + +fun IrFrameMap.leave(irDeclaration: IrSymbolOwner): Int { + return leave(irDeclaration.symbol) +} \ No newline at end of file