diff --git a/src/coreclr/interpreter/compiler.cpp b/src/coreclr/interpreter/compiler.cpp index 716068c876f7e0..5189fb28328184 100644 --- a/src/coreclr/interpreter/compiler.cpp +++ b/src/coreclr/interpreter/compiler.cpp @@ -1418,6 +1418,10 @@ void InterpCompiler::EmitBranch(InterpOpcode opcode, int32_t ilOffset) if (target < 0 || target >= m_ILCodeSize) assert(0); + // Backwards branch, emit safepoint + if (ilOffset < 0) + AddIns(INTOP_SAFEPOINT); + InterpBasicBlock *pTargetBB = m_ppOffsetToBB[target]; assert(pTargetBB != NULL); @@ -2113,6 +2117,10 @@ int InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo) codeEnd = m_ip + m_ILCodeSize; + // Safepoint at each method entry. This could be done as part of a call, rather than + // adding an opcode. + AddIns(INTOP_SAFEPOINT); + linkBBlocks = true; needsRetryEmit = false; retry_emit: diff --git a/src/coreclr/interpreter/intops.def b/src/coreclr/interpreter/intops.def index efdb1c4d4fe414..eae777005c7c0e 100644 --- a/src/coreclr/interpreter/intops.def +++ b/src/coreclr/interpreter/intops.def @@ -35,6 +35,7 @@ OPDEF(INTOP_LDLOCA, "ldloca", 3, 1, 0, InterpOpInt) OPDEF(INTOP_SWITCH, "switch", 0, 0, 1, InterpOpSwitch) +OPDEF(INTOP_SAFEPOINT, "safepoint", 1, 0, 0, InterpOpNoArgs) OPDEF(INTOP_BR, "br", 2, 0, 0, InterpOpBranch) OPDEF(INTOP_BRFALSE_I4, "brfalse.i4", 3, 0, 1, InterpOpBranch) diff --git a/src/coreclr/vm/interpexec.cpp b/src/coreclr/vm/interpexec.cpp index 883d12e336e22c..98314eda763d9c 100644 --- a/src/coreclr/vm/interpexec.cpp +++ b/src/coreclr/vm/interpexec.cpp @@ -35,6 +35,13 @@ static void InterpBreakpoint() void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFrame *pFrame, InterpThreadContext *pThreadContext) { + CONTRACTL + { + GC_TRIGGERS; + MODE_COOPERATIVE; + } + CONTRACTL_END; + #if defined(HOST_AMD64) && defined(HOST_WINDOWS) pInterpreterFrame->SetInterpExecMethodSSP((TADDR)_rdsspq()); #endif // HOST_AMD64 && HOST_WINDOWS @@ -292,6 +299,12 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr break; } + case INTOP_SAFEPOINT: + if (g_TrapReturningThreads) + JIT_PollGC(); + ip++; + break; + case INTOP_BR: ip += ip[1]; break;