Revert: Forbid suspension points in critical sections

This commit is contained in:
Ilmir Usmanov
2018-09-28 17:03:20 +03:00
parent 37a88fda78
commit 1b04945625
5 changed files with 3 additions and 126 deletions
@@ -2438,11 +2438,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return;
}
if (resolvedCall.getResultingDescriptor() instanceof FunctionDescriptor &&
((FunctionDescriptor) resolvedCall.getResultingDescriptor()).isSuspend()) {
state.getGlobalCoroutinesContext().checkSuspendCall(resolvedCall);
}
boolean isSuspendNoInlineCall =
CoroutineCodegenUtilKt.isSuspendNoInlineCall(resolvedCall, this, state.getLanguageVersionSettings());
boolean isConstructor = resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor;
@@ -1,55 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.kotlin.backend.common.peek
import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.SUSPENSION_POINT_INSIDE_MONITOR
class GlobalCoroutinesContext(private val diagnostics: DiagnosticSink) {
private var monitorsDepth = 0
private val inlineLambdaInsideMonitorSourceArgumentIndexes = arrayListOf<Set<Int>>()
fun pushArgumentIndexes(indexes: Set<Int>) {
inlineLambdaInsideMonitorSourceArgumentIndexes.add(indexes)
}
fun popArgumentIndexes() {
inlineLambdaInsideMonitorSourceArgumentIndexes.pop()
}
private fun enterMonitor() {
monitorsDepth++
}
fun enterMonitorIfNeeded(index: Int?) {
if (index == null) return
if (inlineLambdaInsideMonitorSourceArgumentIndexes.peek()?.contains(index) != true) return
enterMonitor()
}
private fun exitMonitor() {
assert(monitorsDepth > 0) {
"exitMonitor without corresponding enterMonitor"
}
monitorsDepth--
}
fun exitMonitorIfNeeded(index: Int?) {
if (index == null) return
if (inlineLambdaInsideMonitorSourceArgumentIndexes.peek()?.contains(index) != true) return
exitMonitor()
}
fun checkSuspendCall(call: ResolvedCall<*>) {
if (monitorsDepth != 0) {
diagnostics.report(SUSPENSION_POINT_INSIDE_MONITOR.on(call.call.callElement, call.resultingDescriptor))
}
}
}
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.codegen.inline
import com.intellij.psi.PsiElement
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.backend.common.isBuiltInIntercepted
import org.jetbrains.kotlin.backend.common.isTopLevelInPackage
import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags
@@ -20,8 +19,6 @@ import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForSuspendCorouti
import org.jetbrains.kotlin.codegen.coroutines.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm
import org.jetbrains.kotlin.codegen.intrinsics.bytecode
import org.jetbrains.kotlin.codegen.intrinsics.classId
import org.jetbrains.kotlin.codegen.optimization.common.ControlFlowGraph
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.isReleaseCoroutines
@@ -247,18 +244,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
}
}
val reificationResult = reifiedTypeInliner.reifyInstructions(node)
val hasMonitor = node.instructions.asSequence().any { it.opcode == Opcodes.MONITORENTER }
if (hasMonitor) {
state.globalCoroutinesContext.pushArgumentIndexes(findInlineLambdasInsideMonitor(node))
}
try {
generateClosuresBodies()
} finally {
if (hasMonitor) {
state.globalCoroutinesContext.popArgumentIndexes()
}
}
generateClosuresBodies()
//through generation captured parameters will be added to invocationParamBuilder
putClosureParametersOnStack()
@@ -315,45 +301,6 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
return result
}
private fun findInlineLambdasInsideMonitor(node: MethodNode): Set<Int> {
val sources = MethodInliner.analyzeMethodNodeBeforeInline(node)
val cfg = ControlFlowGraph.build(node)
val monitorDepthMap = hashMapOf<AbstractInsnNode, Int>()
val result = hashSetOf<Int>()
fun addMonitorDepthToSuccs(index: Int, depth: Int) {
val insn = node.instructions[index]
monitorDepthMap[insn] = depth
val newDepth = when (insn.opcode) {
Opcodes.MONITORENTER -> depth + 1
Opcodes.MONITOREXIT -> depth - 1
else -> depth
}
for (succIndex in cfg.getSuccessorsIndices(index)) {
if (monitorDepthMap[node.instructions[succIndex]] == null) {
addMonitorDepthToSuccs(succIndex, newDepth)
}
}
}
addMonitorDepthToSuccs(0, 0)
for (insn in node.instructions.asSequence()) {
if (insn !is MethodInsnNode) continue
if (!isInvokeOnLambda(insn.owner, insn.name)) continue
if (monitorDepthMap[insn]?.let { it > 0 } != true) continue
val frame = sources[node.instructions.indexOf(insn)] ?: continue
for (source in frame.getStack(frame.stackSize - Type.getArgumentTypes(insn.desc).size - 1).insns) {
if (source.opcode == Opcodes.ALOAD) {
result.add((source as VarInsnNode).`var`)
}
}
}
return result
}
private fun isInlinedToInlineFunInKotlinRuntime(): Boolean {
val codegen = this.codegen as? ExpressionCodegen ?: return false
val caller = codegen.context.functionDescriptor
@@ -363,16 +310,8 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
}
private fun generateClosuresBodies() {
val parameters = invocationParamBuilder.buildParameters()
for (info in expressionMap.values) {
val index = parameters.find { it.lambda == info }?.index
state.globalCoroutinesContext.enterMonitorIfNeeded(index)
try {
info.generateLambdaBody(sourceCompiler, reifiedTypeInliner)
} finally {
state.globalCoroutinesContext.exitMonitorIfNeeded(index)
}
info.generateLambdaBody(sourceCompiler, reifiedTypeInliner)
}
}
@@ -998,7 +998,7 @@ class MethodInliner(
)
}
fun analyzeMethodNodeBeforeInline(node: MethodNode): Array<Frame<SourceValue>?> {
private fun analyzeMethodNodeBeforeInline(node: MethodNode): Array<Frame<SourceValue>?> {
val analyzer = object : Analyzer<SourceValue>(SourceInterpreter()) {
override fun newFrame(nLocals: Int, nStack: Int): Frame<SourceValue> {
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.codegen.`when`.MappingsClassesForWhenByEnum
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.context.CodegenContext
import org.jetbrains.kotlin.codegen.context.RootContext
import org.jetbrains.kotlin.codegen.coroutines.GlobalCoroutinesContext
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
import org.jetbrains.kotlin.codegen.inline.GlobalInlineContext
import org.jetbrains.kotlin.codegen.inline.InlineCache
@@ -203,7 +202,6 @@ class GenerationState private constructor(
}
val samWrapperClasses: SamWrapperClasses = SamWrapperClasses(this)
val globalInlineContext: GlobalInlineContext = GlobalInlineContext(diagnostics)
val globalCoroutinesContext: GlobalCoroutinesContext = GlobalCoroutinesContext(diagnostics)
val mappingsClassesForWhenByEnum: MappingsClassesForWhenByEnum = MappingsClassesForWhenByEnum(this)
val jvmRuntimeTypes: JvmRuntimeTypes = JvmRuntimeTypes(module, configuration.languageVersionSettings)
val factory: ClassFileFactory