From 072af7304f02d6e3bb850d452418ed18a24ab152 Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Fri, 6 Apr 2018 17:51:24 +0300 Subject: [PATCH] 182: `jdk.internal.org.objectweb.asm.Opcodes` -> `org.jetbrains` --- .../inline/LegacyInlineSuspendUtil.kt.182 | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LegacyInlineSuspendUtil.kt.182 diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LegacyInlineSuspendUtil.kt.182 b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LegacyInlineSuspendUtil.kt.182 new file mode 100644 index 00000000000..2101f93164c --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LegacyInlineSuspendUtil.kt.182 @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.codegen.inline + +import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.load.kotlin.getContainingKotlinJvmBinaryClass +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter +import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode +import org.jetbrains.org.objectweb.asm.tree.MethodNode + +// KLUDGE: Inline suspend function built with compiler version less than 1.1.4/1.2-M1 did not contain proper +// before/after suspension point marks, so we detect those functions here and insert the corresponding marks + +fun insertLegacySuspendInlineMarks(node: MethodNode) { + with (node.instructions) { + // look for return instruction before the end and insert "afterSuspendMarker" there + insertBefore(findLastReturn(last) ?: return, produceSuspendMarker(false).instructions) + // insert "beforeSuspendMarker" at the beginning + insertBefore(first, produceSuspendMarker(true).instructions) + } + node.maxStack = node.maxStack.coerceAtLeast(2) // min stack need for suspend marker before return +} + +fun findLastReturn(node: AbstractInsnNode?): AbstractInsnNode? { + var cur = node + while (cur != null && cur.opcode != Opcodes.ARETURN) cur = cur.previous + return cur +} + +private fun produceSuspendMarker(isStartNotEnd: Boolean): MethodNode = + MethodNode().also { addSuspendMarker(InstructionAdapter(it), isStartNotEnd) } + +fun isLegacySuspendInlineFunction(descriptor: CallableMemberDescriptor): Boolean { + if (descriptor !is FunctionDescriptor) return false + if (!descriptor.isSuspend || !descriptor.isInline) return false + val jvmBytecodeVersion = descriptor.getContainingKotlinJvmBinaryClass()?.classHeader?.bytecodeVersion ?: return false + return !jvmBytecodeVersion.isAtLeast(1, 0, 2) +}