From 955b9260d1e18d4fe599d7f5db23b44ba8d65cc0 Mon Sep 17 00:00:00 2001 From: pyos Date: Tue, 25 May 2021 19:27:17 +0200 Subject: [PATCH] JVM: move more old backend code out of InlineCodegen --- .../jetbrains/kotlin/codegen/CallGenerator.kt | 11 +- .../kotlin/codegen/ExpressionCodegen.java | 3 +- .../jetbrains/kotlin/codegen/StackValue.java | 10 +- .../kotlin/codegen/inline/InlineCodegen.kt | 101 ++++-------------- .../inline/InlineCodegenForDefaultBody.kt | 2 +- .../kotlin/codegen/inline/PsiInlineCodegen.kt | 30 +++--- .../backend/jvm/codegen/IrInlineCodegen.kt | 2 +- 7 files changed, 49 insertions(+), 110 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt index 74ed48546e9..75a5726d630 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallGenerator.kt @@ -39,13 +39,9 @@ interface CallGenerator { } } - override fun processAndPutHiddenParameters(justProcess: Boolean) { + override fun processHiddenParameters() {} - } - - override fun putHiddenParamsIntoLocals() { - - } + override fun putHiddenParamsIntoLocals() {} override fun genValueAndPut( valueParameterDescriptor: ValueParameterDescriptor?, @@ -140,9 +136,8 @@ interface CallGenerator { paramIndex: Int ) - fun processAndPutHiddenParameters(justProcess: Boolean) + fun processHiddenParameters() - /*should be called if justProcess = true in processAndPutHiddenParameters*/ fun putHiddenParamsIntoLocals() fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List, valueParameterTypes: List) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 2063c5b2470..223bdb26be6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -2780,7 +2780,8 @@ public class ExpressionCodegen extends KtVisitor impleme putReceiverAndInlineMarkerIfNeeded(callableMethod, resolvedCall, receiver, maybeSuspensionPoint, isConstructor); } - callGenerator.processAndPutHiddenParameters(false); + callGenerator.processHiddenParameters(); + callGenerator.putHiddenParamsIntoLocals(); List valueArguments = resolvedCall.getValueArgumentsByIndex(); assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java index aa7b669fbcc..52c96a80739 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java @@ -45,7 +45,6 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.SimpleType; -import org.jetbrains.kotlin.types.TypeUtils; import org.jetbrains.kotlin.types.model.KotlinTypeMarker; import org.jetbrains.org.objectweb.asm.Label; import org.jetbrains.org.objectweb.asm.Opcodes; @@ -1329,8 +1328,8 @@ public abstract class StackValue { StackValue newReceiver = StackValue.receiver(call, receiver, codegen, callable); ArgumentGenerator generator = createArgumentGenerator(); newReceiver.put(newReceiver.type, newReceiver.kotlinType, v); - callGenerator.processAndPutHiddenParameters(false); - + callGenerator.processHiddenParameters(); + callGenerator.putHiddenParamsIntoLocals(); defaultArgs = generator.generate(valueArguments, valueArguments, call.getResultingDescriptor()); } @@ -1748,7 +1747,8 @@ public abstract class StackValue { assert getterDescriptor != null : "Getter descriptor should be not null for " + descriptor; if (resolvedCall != null && getterDescriptor.isInline()) { CallGenerator callGenerator = codegen.getOrCreateCallGenerator(resolvedCall, ((PropertyDescriptor)resolvedCall.getResultingDescriptor()).getGetter()); - callGenerator.processAndPutHiddenParameters(false); + callGenerator.processHiddenParameters(); + callGenerator.putHiddenParamsIntoLocals(); callGenerator.genCall(getter, resolvedCall, false, codegen); } else { @@ -1832,7 +1832,7 @@ public abstract class StackValue { if (!skipReceiver) { putReceiver(v, false); } - callGenerator.processAndPutHiddenParameters(true); + callGenerator.processHiddenParameters(); callGenerator.putValueIfNeeded(new JvmKotlinType( CollectionsKt.last(setter.getValueParameters()).getAsmType(), CollectionsKt.last(setterDescriptor.getValueParameters()).getType()), diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt index de08917e008..e7aa52773f9 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt @@ -61,7 +61,7 @@ abstract class InlineCodegen( private val initialFrameSize = codegen.frameMap.currentSize - private val isSameModule: Boolean + private val isSameModule: Boolean = sourceCompiler.isCallInsideSameModuleAsDeclared(functionDescriptor) protected val invocationParamBuilder = ParametersBuilder.newBuilder() @@ -69,15 +69,11 @@ abstract class InlineCodegen( private val sourceMapper = sourceCompiler.lazySourceMapper - protected var delayedHiddenWriting: Function0? = null - protected val maskValues = ArrayList() protected var maskStartIndex = -1 protected var methodHandleInDefaultMethodIndex = -1 init { - isSameModule = sourceCompiler.isCallInsideSameModuleAsDeclared(functionDescriptor) - if (functionDescriptor !is FictitiousArrayConstructor) { //track changes for property accessor and @JvmName inline functions/property accessors if (jvmSignature.asmMethod.name != functionDescriptor.name.asString()) { @@ -200,8 +196,6 @@ abstract class InlineCodegen( } private fun inlineCall(nodeAndSmap: SMAPAndMethodNode, inlineDefaultLambda: Boolean): InlineResult { - assert(delayedHiddenWriting == null) { "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'" } - val node = nodeAndSmap.node if (inlineDefaultLambda) { for (lambda in extractDefaultLambdas(node)) { @@ -352,15 +346,16 @@ abstract class InlineCodegen( val isDefaultParameter = kind === ValueKind.DEFAULT_PARAMETER val jvmType = jvmKotlinType.type val kotlinType = jvmKotlinType.kotlinType - if (!isDefaultParameter && shouldPutGeneralValue(jvmType, kotlinType, stackValue)) { + val canRemap = isPrimitive(jvmType) == isPrimitive(stackValue.type) && + !StackValue.requiresInlineClassBoxingOrUnboxing(stackValue.type, stackValue.kotlinType, jvmType, kotlinType) && + (stackValue is StackValue.Local || stackValue.isCapturedInlineParameter()) + if (!canRemap && !isDefaultParameter) { stackValue.put(jvmType, kotlinType, codegen.visitor) } if (!asFunctionInline && Type.VOID_TYPE !== jvmType) { //TODO remap only inlinable closure => otherwise we could get a lot of problem - val couldBeRemapped = !shouldPutGeneralValue(jvmType, kotlinType, stackValue) && !isDefaultParameter - val remappedValue = if (couldBeRemapped) stackValue else null - + val remappedValue = if (canRemap && !isDefaultParameter) stackValue else null val info: ParameterInfo if (capturedParam != null) { info = invocationParamBuilder.addCapturedParam(capturedParam, capturedParam.fieldName, false) @@ -370,49 +365,25 @@ abstract class InlineCodegen( info.functionalArgument = when (kind) { ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_PARAMETER_CALLED_IN_SUSPEND -> NonInlineableArgumentForInlineableParameterCalledInSuspend - ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER -> NonInlineableArgumentForInlineableSuspendParameter + ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER -> + NonInlineableArgumentForInlineableSuspendParameter else -> null } } - recordParameterValueInLocalVal(false, isDefaultParameter, info) - } - } - - protected fun recordParameterValueInLocalVal( - delayedWritingToLocals: Boolean, - skipStore: Boolean, - vararg infos: ParameterInfo - ): Function0? { - val index = IntArray(infos.size) { i -> - if (!infos[i].isSkippedOrRemapped) { - codegen.frameMap.enterTemp(infos[i].type) - } else -1 - } - - val possibleLazyTask = { - for (i in infos.indices.reversed()) { - val info = infos[i] - if (!info.isSkippedOrRemapped) { - val type = info.type - val local = StackValue.local(index[i], type) - if (!skipStore) { - local.store(StackValue.onStack(info.typeOnStack), codegen.visitor) - } - if (info is CapturedParamInfo) { - info.remapValue = local - info.isSynthetic = true - } + if (!info.isSkippedOrRemapped) { + val local = StackValue.local(codegen.frameMap.enterTemp(info.type), info.type) + if (!isDefaultParameter) { + local.store(StackValue.onStack(info.typeOnStack), codegen.visitor) + } + if (info is CapturedParamInfo) { + info.remapValue = local + info.isSynthetic = true } } } - - if (delayedWritingToLocals) return possibleLazyTask - possibleLazyTask() - return null } - private fun leaveTemps() { invocationParamBuilder.listAllParams().asReversed().forEach { param -> if (!param.isSkippedOrRemapped || CapturedParamInfo.isSynthetic(param)) { @@ -615,43 +586,13 @@ abstract class InlineCodegen( } } - /*descriptor is null for captured vars*/ - private fun shouldPutGeneralValue(type: Type, kotlinType: KotlinType?, stackValue: StackValue): Boolean { - //remap only inline functions (and maybe non primitives) - //TODO - clean assertion and remapping logic - - // don't remap boxing/unboxing primitives - if (isPrimitive(type) != isPrimitive(stackValue.type)) { - return true - } - - // don't remap boxing/unboxing inline classes - if (StackValue.requiresInlineClassBoxingOrUnboxing(stackValue.type, stackValue.kotlinType, type, kotlinType)) { - return true - } - - if (stackValue is StackValue.Local) { - return false - } - - var field = stackValue - if (stackValue is StackValue.FieldForSharedVar) { - field = stackValue.receiver - } - - //check that value corresponds to captured inlining parameter - if (field is StackValue.Field) { - val varDescriptor = field.descriptor - //check that variable is inline function parameter - return !(varDescriptor is ParameterDescriptor && - InlineUtil.isInlineParameter(varDescriptor) && - InlineUtil.isInline(varDescriptor.containingDeclaration)) - } - - return true + private fun StackValue.isCapturedInlineParameter(): Boolean { + val field = if (this is StackValue.FieldForSharedVar) receiver else this + return field is StackValue.Field && field.descriptor is ParameterDescriptor && + InlineUtil.isInlineParameter(field.descriptor) && + InlineUtil.isInline(field.descriptor.containingDeclaration) } - fun getDeclarationLabels(lambdaOrFun: PsiElement?, descriptor: DeclarationDescriptor): Set { val result = HashSet() diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt index d0b343c16e0..f5b9acba134 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt @@ -85,7 +85,7 @@ class InlineCodegenForDefaultBody( throw UnsupportedOperationException("Shouldn't be called") } - override fun processAndPutHiddenParameters(justProcess: Boolean) { + override fun processHiddenParameters() { throw UnsupportedOperationException("Shouldn't be called") } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt index b504cfe7156..fb00a0f220b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineCodegen.kt @@ -65,6 +65,7 @@ class PsiInlineCodegen( callDefault: Boolean, codegen: ExpressionCodegen ) { + assert(hiddenParameters.isEmpty()) { "putHiddenParamsIntoLocals() should be called after processHiddenParameters()" } if (!state.globalInlineContext.enterIntoInlining(functionDescriptor, resolvedCall?.call?.callElement)) { generateStub(resolvedCall?.call?.callElement?.text ?: "", codegen) return @@ -94,22 +95,29 @@ class PsiInlineCodegen( return parentIfCondition.isAncestor(callElement, false) } - override fun processAndPutHiddenParameters(justProcess: Boolean) { - if (getMethodAsmFlags(functionDescriptor, sourceCompiler.contextKind, state) and Opcodes.ACC_STATIC == 0) { - invocationParamBuilder.addNextParameter(methodOwner, false, actualDispatchReceiver) - } + private val hiddenParameters = mutableListOf>() + override fun processHiddenParameters() { + if (getMethodAsmFlags(functionDescriptor, sourceCompiler.contextKind, state) and Opcodes.ACC_STATIC == 0) { + hiddenParameters += invocationParamBuilder.addNextParameter(methodOwner, false, actualDispatchReceiver) to + codegen.frameMap.enterTemp(methodOwner) + } for (param in jvmSignature.valueParameters) { if (param.kind == JvmMethodParameterKind.VALUE) { break } - invocationParamBuilder.addNextParameter(param.asmType, false) + hiddenParameters += invocationParamBuilder.addNextParameter(param.asmType, false) to + codegen.frameMap.enterTemp(param.asmType) } - invocationParamBuilder.markValueParametersStart() - val hiddenParameters = invocationParamBuilder.buildParameters().parameters + } - delayedHiddenWriting = recordParameterValueInLocalVal(justProcess, false, *hiddenParameters.toTypedArray()) + override fun putHiddenParamsIntoLocals() { + for (i in hiddenParameters.indices.reversed()) { + val (param, offset) = hiddenParameters[i] + StackValue.local(offset, param.type).store(StackValue.onStack(param.typeOnStack), codegen.visitor) + } + hiddenParameters.clear() } /*lambda or callable reference*/ @@ -204,12 +212,6 @@ class PsiInlineCodegen( override fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List, valueParameterTypes: List) = Unit - override fun putHiddenParamsIntoLocals() { - assert(delayedHiddenWriting != null) { "processAndPutHiddenParameters(true) should be called before putHiddenParamsIntoLocals" } - delayedHiddenWriting!!.invoke() - delayedHiddenWriting = null - } - override fun extractDefaultLambdas(node: MethodNode): List { return expandMaskConditionsAndUpdateVariableNodes( node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex, diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt index 5d839db9234..25dffc09ff5 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt @@ -90,7 +90,7 @@ class IrInlineCodegen( val onStack = when { kind == ValueKind.METHOD_HANDLE_IN_DEFAULT -> StackValue.constant(null, AsmTypes.OBJECT_TYPE) kind == ValueKind.DEFAULT_MASK -> StackValue.constant((argumentExpression as IrConst<*>).value, Type.INT_TYPE) - kind == ValueKind.DEFAULT_PARAMETER -> StackValue.constant(null, AsmTypes.OBJECT_TYPE) + kind == ValueKind.DEFAULT_PARAMETER -> StackValue.createDefaultValue(parameterType) irValueParameter.index >= 0 // Reuse an existing local if possible. NOTE: when stopping at a breakpoint placed // in an inline function, arguments which reuse an existing local will not be visible