Do not calculate maxStack size manually when generating typeOf

This commit is contained in:
Alexander Udalov
2020-05-06 13:05:35 +02:00
parent 82603f3853
commit 37cf7316bc
2 changed files with 14 additions and 18 deletions
@@ -258,13 +258,18 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
instructions: InsnList, instructions: InsnList,
type: KT type: KT
) = rewriteNextTypeInsn(insn, Opcodes.ACONST_NULL) { stubConstNull: AbstractInsnNode -> ) = rewriteNextTypeInsn(insn, Opcodes.ACONST_NULL) { stubConstNull: AbstractInsnNode ->
val newMethodNode = MethodNode(Opcodes.API_VERSION) val newMethodNode = MethodNode(Opcodes.API_VERSION, "fake", "()V", null, null)
val stackSize = typeSystem.generateTypeOf(InstructionAdapter(newMethodNode), type, intrinsicsSupport) val mv = wrapWithMaxLocalCalc(newMethodNode)
typeSystem.generateTypeOf(InstructionAdapter(mv), type, intrinsicsSupport)
instructions.insert(insn, newMethodNode.instructions) // Adding a fake return (and removing it below) to trigger maxStack calculation
mv.visitInsn(Opcodes.RETURN)
mv.visitMaxs(-1, -1)
instructions.insert(insn, newMethodNode.instructions.apply { remove(last) })
instructions.remove(stubConstNull) instructions.remove(stubConstNull)
maxStackSize = max(maxStackSize, stackSize) maxStackSize = max(maxStackSize, newMethodNode.maxStack)
return true return true
} }
@@ -36,10 +36,9 @@ private fun TypeSystemCommonBackendContext.putTypeOfReifiedTypeParameter(
v.aconst(null) v.aconst(null)
} }
// Returns some upper bound on maximum stack size
internal fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateTypeOf( internal fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateTypeOf(
v: InstructionAdapter, type: KT, intrinsicsSupport: ReifiedTypeInliner.IntrinsicsSupport<KT> v: InstructionAdapter, type: KT, intrinsicsSupport: ReifiedTypeInliner.IntrinsicsSupport<KT>
): Int { ) {
intrinsicsSupport.putClassInstance(v, type) intrinsicsSupport.putClassInstance(v, type)
val argumentsSize = type.argumentsCount() val argumentsSize = type.argumentsCount()
@@ -50,16 +49,13 @@ internal fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateType
v.newarray(K_TYPE_PROJECTION) v.newarray(K_TYPE_PROJECTION)
} }
var maxStackSize = 3
for (i in 0 until argumentsSize) { for (i in 0 until argumentsSize) {
if (useArray) { if (useArray) {
v.dup() v.dup()
v.iconst(i) v.iconst(i)
} }
val stackSize = doGenerateTypeProjection(v, type.getArgument(i), intrinsicsSupport) doGenerateTypeProjection(v, type.getArgument(i), intrinsicsSupport)
maxStackSize = maxOf(maxStackSize, stackSize + i + 5)
if (useArray) { if (useArray) {
v.astore(K_TYPE_PROJECTION) v.astore(K_TYPE_PROJECTION)
@@ -77,30 +73,27 @@ internal fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateType
val signature = Type.getMethodDescriptor(K_TYPE, JAVA_CLASS_TYPE, *projections) val signature = Type.getMethodDescriptor(K_TYPE, JAVA_CLASS_TYPE, *projections)
v.invokestatic(REFLECTION, methodName, signature, false) v.invokestatic(REFLECTION, methodName, signature, false)
return maxStackSize
} }
private fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.doGenerateTypeProjection( private fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.doGenerateTypeProjection(
v: InstructionAdapter, v: InstructionAdapter,
projection: TypeArgumentMarker, projection: TypeArgumentMarker,
intrinsicsSupport: ReifiedTypeInliner.IntrinsicsSupport<KT> intrinsicsSupport: ReifiedTypeInliner.IntrinsicsSupport<KT>
): Int { ) {
// KTypeProjection members could be static, see KT-30083 and KT-30084 // KTypeProjection members could be static, see KT-30083 and KT-30084
v.getstatic(K_TYPE_PROJECTION.internalName, "Companion", K_TYPE_PROJECTION_COMPANION.descriptor) v.getstatic(K_TYPE_PROJECTION.internalName, "Companion", K_TYPE_PROJECTION_COMPANION.descriptor)
if (projection.isStarProjection()) { if (projection.isStarProjection()) {
v.invokevirtual(K_TYPE_PROJECTION_COMPANION.internalName, "getSTAR", Type.getMethodDescriptor(K_TYPE_PROJECTION), false) v.invokevirtual(K_TYPE_PROJECTION_COMPANION.internalName, "getSTAR", Type.getMethodDescriptor(K_TYPE_PROJECTION), false)
return 1 return
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val type = projection.getType() as KT val type = projection.getType() as KT
val typeParameterClassifier = type.typeConstructor().getTypeParameterClassifier() val typeParameterClassifier = type.typeConstructor().getTypeParameterClassifier()
val stackSize = if (typeParameterClassifier != null) { if (typeParameterClassifier != null) {
if (typeParameterClassifier.isReified()) { if (typeParameterClassifier.isReified()) {
putTypeOfReifiedTypeParameter(v, typeParameterClassifier, type.isMarkedNullable()) putTypeOfReifiedTypeParameter(v, typeParameterClassifier, type.isMarkedNullable())
2
} else { } else {
// TODO: support non-reified type parameters in typeOf // TODO: support non-reified type parameters in typeOf
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@@ -116,6 +109,4 @@ private fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.doGenerateTyp
TypeVariance.OUT -> "covariant" TypeVariance.OUT -> "covariant"
} }
v.invokevirtual(K_TYPE_PROJECTION_COMPANION.internalName, methodName, Type.getMethodDescriptor(K_TYPE_PROJECTION, K_TYPE), false) v.invokevirtual(K_TYPE_PROJECTION_COMPANION.internalName, methodName, Type.getMethodDescriptor(K_TYPE_PROJECTION, K_TYPE), false)
return stackSize + 1
} }