JVM: move more old backend code out of InlineCodegen

This commit is contained in:
pyos
2021-05-25 19:27:17 +02:00
committed by max-kammerer
parent 043452fb62
commit 955b9260d1
7 changed files with 49 additions and 110 deletions
@@ -39,13 +39,9 @@ interface CallGenerator {
} }
} }
override fun processAndPutHiddenParameters(justProcess: Boolean) { override fun processHiddenParameters() {}
} override fun putHiddenParamsIntoLocals() {}
override fun putHiddenParamsIntoLocals() {
}
override fun genValueAndPut( override fun genValueAndPut(
valueParameterDescriptor: ValueParameterDescriptor?, valueParameterDescriptor: ValueParameterDescriptor?,
@@ -140,9 +136,8 @@ interface CallGenerator {
paramIndex: Int paramIndex: Int
) )
fun processAndPutHiddenParameters(justProcess: Boolean) fun processHiddenParameters()
/*should be called if justProcess = true in processAndPutHiddenParameters*/
fun putHiddenParamsIntoLocals() fun putHiddenParamsIntoLocals()
fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>) fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>)
@@ -2780,7 +2780,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
putReceiverAndInlineMarkerIfNeeded(callableMethod, resolvedCall, receiver, maybeSuspensionPoint, isConstructor); putReceiverAndInlineMarkerIfNeeded(callableMethod, resolvedCall, receiver, maybeSuspensionPoint, isConstructor);
} }
callGenerator.processAndPutHiddenParameters(false); callGenerator.processHiddenParameters();
callGenerator.putHiddenParamsIntoLocals();
List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex(); List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex();
assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor(); assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor();
@@ -45,7 +45,6 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.SimpleType; import org.jetbrains.kotlin.types.SimpleType;
import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.kotlin.types.model.KotlinTypeMarker; import org.jetbrains.kotlin.types.model.KotlinTypeMarker;
import org.jetbrains.org.objectweb.asm.Label; import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.Opcodes; import org.jetbrains.org.objectweb.asm.Opcodes;
@@ -1329,8 +1328,8 @@ public abstract class StackValue {
StackValue newReceiver = StackValue.receiver(call, receiver, codegen, callable); StackValue newReceiver = StackValue.receiver(call, receiver, codegen, callable);
ArgumentGenerator generator = createArgumentGenerator(); ArgumentGenerator generator = createArgumentGenerator();
newReceiver.put(newReceiver.type, newReceiver.kotlinType, v); newReceiver.put(newReceiver.type, newReceiver.kotlinType, v);
callGenerator.processAndPutHiddenParameters(false); callGenerator.processHiddenParameters();
callGenerator.putHiddenParamsIntoLocals();
defaultArgs = generator.generate(valueArguments, valueArguments, call.getResultingDescriptor()); 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; assert getterDescriptor != null : "Getter descriptor should be not null for " + descriptor;
if (resolvedCall != null && getterDescriptor.isInline()) { if (resolvedCall != null && getterDescriptor.isInline()) {
CallGenerator callGenerator = codegen.getOrCreateCallGenerator(resolvedCall, ((PropertyDescriptor)resolvedCall.getResultingDescriptor()).getGetter()); CallGenerator callGenerator = codegen.getOrCreateCallGenerator(resolvedCall, ((PropertyDescriptor)resolvedCall.getResultingDescriptor()).getGetter());
callGenerator.processAndPutHiddenParameters(false); callGenerator.processHiddenParameters();
callGenerator.putHiddenParamsIntoLocals();
callGenerator.genCall(getter, resolvedCall, false, codegen); callGenerator.genCall(getter, resolvedCall, false, codegen);
} }
else { else {
@@ -1832,7 +1832,7 @@ public abstract class StackValue {
if (!skipReceiver) { if (!skipReceiver) {
putReceiver(v, false); putReceiver(v, false);
} }
callGenerator.processAndPutHiddenParameters(true); callGenerator.processHiddenParameters();
callGenerator.putValueIfNeeded(new JvmKotlinType( callGenerator.putValueIfNeeded(new JvmKotlinType(
CollectionsKt.last(setter.getValueParameters()).getAsmType(), CollectionsKt.last(setter.getValueParameters()).getAsmType(),
CollectionsKt.last(setterDescriptor.getValueParameters()).getType()), CollectionsKt.last(setterDescriptor.getValueParameters()).getType()),
@@ -61,7 +61,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
private val initialFrameSize = codegen.frameMap.currentSize private val initialFrameSize = codegen.frameMap.currentSize
private val isSameModule: Boolean private val isSameModule: Boolean = sourceCompiler.isCallInsideSameModuleAsDeclared(functionDescriptor)
protected val invocationParamBuilder = ParametersBuilder.newBuilder() protected val invocationParamBuilder = ParametersBuilder.newBuilder()
@@ -69,15 +69,11 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
private val sourceMapper = sourceCompiler.lazySourceMapper private val sourceMapper = sourceCompiler.lazySourceMapper
protected var delayedHiddenWriting: Function0<Unit>? = null
protected val maskValues = ArrayList<Int>() protected val maskValues = ArrayList<Int>()
protected var maskStartIndex = -1 protected var maskStartIndex = -1
protected var methodHandleInDefaultMethodIndex = -1 protected var methodHandleInDefaultMethodIndex = -1
init { init {
isSameModule = sourceCompiler.isCallInsideSameModuleAsDeclared(functionDescriptor)
if (functionDescriptor !is FictitiousArrayConstructor) { if (functionDescriptor !is FictitiousArrayConstructor) {
//track changes for property accessor and @JvmName inline functions/property accessors //track changes for property accessor and @JvmName inline functions/property accessors
if (jvmSignature.asmMethod.name != functionDescriptor.name.asString()) { if (jvmSignature.asmMethod.name != functionDescriptor.name.asString()) {
@@ -200,8 +196,6 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
} }
private fun inlineCall(nodeAndSmap: SMAPAndMethodNode, inlineDefaultLambda: Boolean): InlineResult { private fun inlineCall(nodeAndSmap: SMAPAndMethodNode, inlineDefaultLambda: Boolean): InlineResult {
assert(delayedHiddenWriting == null) { "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'" }
val node = nodeAndSmap.node val node = nodeAndSmap.node
if (inlineDefaultLambda) { if (inlineDefaultLambda) {
for (lambda in extractDefaultLambdas(node)) { for (lambda in extractDefaultLambdas(node)) {
@@ -352,15 +346,16 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
val isDefaultParameter = kind === ValueKind.DEFAULT_PARAMETER val isDefaultParameter = kind === ValueKind.DEFAULT_PARAMETER
val jvmType = jvmKotlinType.type val jvmType = jvmKotlinType.type
val kotlinType = jvmKotlinType.kotlinType 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) stackValue.put(jvmType, kotlinType, codegen.visitor)
} }
if (!asFunctionInline && Type.VOID_TYPE !== jvmType) { if (!asFunctionInline && Type.VOID_TYPE !== jvmType) {
//TODO remap only inlinable closure => otherwise we could get a lot of problem //TODO remap only inlinable closure => otherwise we could get a lot of problem
val couldBeRemapped = !shouldPutGeneralValue(jvmType, kotlinType, stackValue) && !isDefaultParameter val remappedValue = if (canRemap && !isDefaultParameter) stackValue else null
val remappedValue = if (couldBeRemapped) stackValue else null
val info: ParameterInfo val info: ParameterInfo
if (capturedParam != null) { if (capturedParam != null) {
info = invocationParamBuilder.addCapturedParam(capturedParam, capturedParam.fieldName, false) info = invocationParamBuilder.addCapturedParam(capturedParam, capturedParam.fieldName, false)
@@ -370,49 +365,25 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
info.functionalArgument = when (kind) { info.functionalArgument = when (kind) {
ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_PARAMETER_CALLED_IN_SUSPEND -> ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_PARAMETER_CALLED_IN_SUSPEND ->
NonInlineableArgumentForInlineableParameterCalledInSuspend NonInlineableArgumentForInlineableParameterCalledInSuspend
ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER -> NonInlineableArgumentForInlineableSuspendParameter ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER ->
NonInlineableArgumentForInlineableSuspendParameter
else -> null else -> null
} }
} }
recordParameterValueInLocalVal(false, isDefaultParameter, info) if (!info.isSkippedOrRemapped) {
} val local = StackValue.local(codegen.frameMap.enterTemp(info.type), info.type)
} if (!isDefaultParameter) {
local.store(StackValue.onStack(info.typeOnStack), codegen.visitor)
protected fun recordParameterValueInLocalVal( }
delayedWritingToLocals: Boolean, if (info is CapturedParamInfo) {
skipStore: Boolean, info.remapValue = local
vararg infos: ParameterInfo info.isSynthetic = true
): Function0<Unit>? {
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 (delayedWritingToLocals) return possibleLazyTask
possibleLazyTask()
return null
} }
private fun leaveTemps() { private fun leaveTemps() {
invocationParamBuilder.listAllParams().asReversed().forEach { param -> invocationParamBuilder.listAllParams().asReversed().forEach { param ->
if (!param.isSkippedOrRemapped || CapturedParamInfo.isSynthetic(param)) { if (!param.isSkippedOrRemapped || CapturedParamInfo.isSynthetic(param)) {
@@ -615,43 +586,13 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
} }
} }
/*descriptor is null for captured vars*/ private fun StackValue.isCapturedInlineParameter(): Boolean {
private fun shouldPutGeneralValue(type: Type, kotlinType: KotlinType?, stackValue: StackValue): Boolean { val field = if (this is StackValue.FieldForSharedVar) receiver else this
//remap only inline functions (and maybe non primitives) return field is StackValue.Field && field.descriptor is ParameterDescriptor &&
//TODO - clean assertion and remapping logic InlineUtil.isInlineParameter(field.descriptor) &&
InlineUtil.isInline(field.descriptor.containingDeclaration)
// 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
} }
fun getDeclarationLabels(lambdaOrFun: PsiElement?, descriptor: DeclarationDescriptor): Set<String> { fun getDeclarationLabels(lambdaOrFun: PsiElement?, descriptor: DeclarationDescriptor): Set<String> {
val result = HashSet<String>() val result = HashSet<String>()
@@ -85,7 +85,7 @@ class InlineCodegenForDefaultBody(
throw UnsupportedOperationException("Shouldn't be called") throw UnsupportedOperationException("Shouldn't be called")
} }
override fun processAndPutHiddenParameters(justProcess: Boolean) { override fun processHiddenParameters() {
throw UnsupportedOperationException("Shouldn't be called") throw UnsupportedOperationException("Shouldn't be called")
} }
@@ -65,6 +65,7 @@ class PsiInlineCodegen(
callDefault: Boolean, callDefault: Boolean,
codegen: ExpressionCodegen codegen: ExpressionCodegen
) { ) {
assert(hiddenParameters.isEmpty()) { "putHiddenParamsIntoLocals() should be called after processHiddenParameters()" }
if (!state.globalInlineContext.enterIntoInlining(functionDescriptor, resolvedCall?.call?.callElement)) { if (!state.globalInlineContext.enterIntoInlining(functionDescriptor, resolvedCall?.call?.callElement)) {
generateStub(resolvedCall?.call?.callElement?.text ?: "<no source>", codegen) generateStub(resolvedCall?.call?.callElement?.text ?: "<no source>", codegen)
return return
@@ -94,22 +95,29 @@ class PsiInlineCodegen(
return parentIfCondition.isAncestor(callElement, false) return parentIfCondition.isAncestor(callElement, false)
} }
override fun processAndPutHiddenParameters(justProcess: Boolean) { private val hiddenParameters = mutableListOf<Pair<ParameterInfo, Int>>()
if (getMethodAsmFlags(functionDescriptor, sourceCompiler.contextKind, state) and Opcodes.ACC_STATIC == 0) {
invocationParamBuilder.addNextParameter(methodOwner, false, actualDispatchReceiver)
}
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) { for (param in jvmSignature.valueParameters) {
if (param.kind == JvmMethodParameterKind.VALUE) { if (param.kind == JvmMethodParameterKind.VALUE) {
break break
} }
invocationParamBuilder.addNextParameter(param.asmType, false) hiddenParameters += invocationParamBuilder.addNextParameter(param.asmType, false) to
codegen.frameMap.enterTemp(param.asmType)
} }
invocationParamBuilder.markValueParametersStart() 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*/ /*lambda or callable reference*/
@@ -204,12 +212,6 @@ class PsiInlineCodegen(
override fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>) = Unit override fun reorderArgumentsIfNeeded(actualArgsWithDeclIndex: List<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>) = Unit
override fun putHiddenParamsIntoLocals() {
assert(delayedHiddenWriting != null) { "processAndPutHiddenParameters(true) should be called before putHiddenParamsIntoLocals" }
delayedHiddenWriting!!.invoke()
delayedHiddenWriting = null
}
override fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda> { override fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda> {
return expandMaskConditionsAndUpdateVariableNodes( return expandMaskConditionsAndUpdateVariableNodes(
node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex, node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex,
@@ -90,7 +90,7 @@ class IrInlineCodegen(
val onStack = when { val onStack = when {
kind == ValueKind.METHOD_HANDLE_IN_DEFAULT -> StackValue.constant(null, AsmTypes.OBJECT_TYPE) 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_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 irValueParameter.index >= 0
// Reuse an existing local if possible. NOTE: when stopping at a breakpoint placed // 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 // in an inline function, arguments which reuse an existing local will not be visible