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:
Jan Oravec
2013-06-26 11:36:26 -07:00
commit de Sara Golemon
commit 5b9e01ff47
3 arquivos alterados com 13 adições e 11 exclusões
+6 -5
Ver Arquivo
@@ -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;
}
+3 -3
Ver Arquivo
@@ -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));
+4 -3
Ver Arquivo
@@ -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()