diff --git a/hphp/runtime/vm/bytecode.cpp b/hphp/runtime/vm/bytecode.cpp index 046bacabd..288b65c76 100644 --- a/hphp/runtime/vm/bytecode.cpp +++ b/hphp/runtime/vm/bytecode.cpp @@ -6820,9 +6820,8 @@ inline void OPTBLD_INLINE VMExecutionContext::iopUnpackCont(PC& pc) { c_Continuation* cont = frame_continuation(m_fp); // Return the received value - TypedValue* recv_to = m_stack.allocTV(); TypedValue* recv_fr = cont->m_received.asTypedValue(); - memcpy(recv_to, recv_fr, sizeof(TypedValue)); + tvTeleport(recv_fr, m_stack.allocTV()); tvWriteNull(recv_fr); // Return the label in a stack cell @@ -6866,19 +6865,21 @@ inline void OPTBLD_INLINE VMExecutionContext::iopContCheck(PC& pc) { inline void OPTBLD_INLINE VMExecutionContext::iopContNext(PC& pc) { NEXT(); c_Continuation* cont = this_continuation(m_fp); - cont->m_received.setNull(); + tvWriteNull(cont->m_received.asTypedValue()); } inline void OPTBLD_INLINE VMExecutionContext::iopContSend(PC& pc) { NEXT(); c_Continuation* cont = this_continuation(m_fp); - cont->m_received.assignVal(tvAsVariant(frame_local(m_fp, 0))); + tvTeleport(frame_local(m_fp, 0), cont->m_received.asTypedValue()); + tvWriteUninit(frame_local(m_fp, 0)); } inline void OPTBLD_INLINE VMExecutionContext::iopContRaise(PC& pc) { NEXT(); c_Continuation* cont = this_continuation(m_fp); - cont->m_received.assignVal(tvAsVariant(frame_local(m_fp, 0))); + tvTeleport(frame_local(m_fp, 0), cont->m_received.asTypedValue()); + tvWriteUninit(frame_local(m_fp, 0)); assert(cont->m_label); --cont->m_label; } diff --git a/hphp/runtime/vm/jit/hhbctranslator.cpp b/hphp/runtime/vm/jit/hhbctranslator.cpp index ede55a3a4..a51a9f7cd 100644 --- a/hphp/runtime/vm/jit/hhbctranslator.cpp +++ b/hphp/runtime/vm/jit/hhbctranslator.cpp @@ -1177,14 +1177,14 @@ void HhbcTranslator::emitContNext() { void HhbcTranslator::emitContSendImpl(bool raise) { assert(curClass()); SSATmp* cont = gen(LdThis, m_tb->fp()); - gen(AssertLoc, Type::Cell, LocalId(0), m_tb->fp()); - auto const newVal = gen(IncRef, ldLoc(0)); if (RuntimeOption::EvalHHIRGenerateAsserts) { // We're guaranteed to have a Null in m_received at this point auto const oldVal = gen(LdProp, Type::Cell, cont, cns(CONTOFF(m_received))); gen(DbgAssertType, Type::InitNull, oldVal); } - gen(StProp, cont, cns(CONTOFF(m_received)), newVal); + gen(AssertLoc, Type::Cell, LocalId(0), m_tb->fp()); + gen(StProp, cont, cns(CONTOFF(m_received)), ldLoc(0)); + gen(StLoc, LocalId(0), m_tb->fp(), m_tb->genDefUninit()); if (raise) { SSATmp* label = gen(LdRaw, Type::Int, cont, cns(RawMemSlot::ContLabel)); label = gen(OpSub, label, cns(1)); diff --git a/hphp/test/slow/yield/2183.php.expect b/hphp/test/slow/yield/2183.php.expect index e7bc63ef5..fedb98f03 100644 --- a/hphp/test/slow/yield/2183.php.expect +++ b/hphp/test/slow/yield/2183.php.expect @@ -1,9 +1,10 @@ in __destruct() +object(Evil)#2 (0) { +} +in __destruct() NULL in __destruct() -NULL -in __destruct() -object(Evil)#4 (0) { +object(Evil)#3 (0) { } Caught: Continuation is already running in __destruct()