JVM: move more old backend code out of InlineCodegen
This commit is contained in:
@@ -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>()
|
||||
|
||||
|
||||
+1
-1
@@ -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,
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user