Do not hold unnecessary reference to sent value
Continuaton::send()/raise() are holding reference to the sent value while the next iteration is being executed. Do not hold this reference and teleport values instead.
Esse commit está contido em:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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()
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário