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(
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<ArgumentAndDeclIndex>, valueParameterTypes: List<Type>)
@@ -2780,7 +2780,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
putReceiverAndInlineMarkerIfNeeded(callableMethod, resolvedCall, receiver, maybeSuspensionPoint, isConstructor);
}
callGenerator.processAndPutHiddenParameters(false);
callGenerator.processHiddenParameters();
callGenerator.putHiddenParamsIntoLocals();
List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex();
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.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()),
@@ -61,7 +61,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
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<out T : BaseExpressionCodegen>(
private val sourceMapper = sourceCompiler.lazySourceMapper
protected var delayedHiddenWriting: Function0<Unit>? = null
protected val maskValues = ArrayList<Int>()
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<out T : BaseExpressionCodegen>(
}
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<out T : BaseExpressionCodegen>(
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<out T : BaseExpressionCodegen>(
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<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 (!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<out T : BaseExpressionCodegen>(
}
}
/*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<String> {
val result = HashSet<String>()
@@ -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")
}
@@ -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 ?: "<no source>", 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<Pair<ParameterInfo, Int>>()
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<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> {
return expandMaskConditionsAndUpdateVariableNodes(
node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex,
@@ -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