Early release of m_received value
Continuation::send() uses m_received field to transfer the value inside the continuation. This field remains set until the continuation is iterated the next time. Unset this field early by ContReceive so that the memory can be reclaimed.
Esse commit está contido em:
@@ -3647,7 +3647,8 @@ ContReceive [] -> [C]
|
||||
|
||||
Receive continuation value. If the continuation in local 0 has a pending
|
||||
exception, this instruction will throw that exception. Otherwise, the value
|
||||
sent to the continuation will be pushed on the stack.
|
||||
sent to the continuation will be pushed on the stack. The value will be no
|
||||
longer referenced by the Continuation object.
|
||||
|
||||
ContDone [] -> []
|
||||
|
||||
|
||||
@@ -6887,8 +6887,10 @@ inline void OPTBLD_INLINE VMExecutionContext::iopContReceive(PC& pc) {
|
||||
NEXT();
|
||||
c_Continuation* cont = frame_continuation(m_fp);
|
||||
cont->t_raised();
|
||||
TypedValue* tv = m_stack.allocTV();
|
||||
tvDup(cont->m_received.asTypedValue(), tv);
|
||||
TypedValue* fr = cont->m_received.asTypedValue();
|
||||
TypedValue* to = m_stack.allocTV();
|
||||
memcpy(to, fr, sizeof(TypedValue));
|
||||
tvWriteUninit(fr);
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopContDone(PC& pc) {
|
||||
|
||||
@@ -752,9 +752,8 @@ void HhbcTranslator::emitContReceive() {
|
||||
SSATmp* cont = m_tb->genLdAssertedLoc(0, Type::Obj);
|
||||
m_tb->genContRaiseCheck(cont, getExitSlowTrace());
|
||||
SSATmp* valOffset = m_tb->genDefConst<int64_t>(CONTOFF(m_received));
|
||||
SSATmp* value = m_tb->genLdProp(cont, valOffset, Type::Cell, nullptr);
|
||||
value = m_tb->genIncRef(value);
|
||||
push(value);
|
||||
push(m_tb->genLdProp(cont, valOffset, Type::Cell, nullptr));
|
||||
m_tb->genStProp(cont, valOffset, m_tb->genDefUninit(), true);
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitContDone() {
|
||||
|
||||
@@ -7538,11 +7538,11 @@ void TranslatorX64::translateContReceive(const Tracelet& t,
|
||||
const NormalizedInstruction& i) {
|
||||
const int contIdx = 0;
|
||||
emitContRaiseCheck(a, i);
|
||||
PhysReg rCont = getReg(i.inputs[contIdx]->location);
|
||||
ScratchReg rScratch(m_regMap);
|
||||
emitLea(a, getReg(i.inputs[contIdx]->location), CONTOFF(m_received),
|
||||
r(rScratch));
|
||||
emitIncRefGeneric(r(rScratch), 0);
|
||||
emitLea(a, rCont, CONTOFF(m_received), r(rScratch));
|
||||
emitCopyToStack(a, i, r(rScratch), -1 * (int)sizeof(Cell));
|
||||
emitStoreUninitNull(a, CONTOFF(m_received), rCont);
|
||||
}
|
||||
|
||||
void TranslatorX64::translateContEnter(const Tracelet& t,
|
||||
|
||||
@@ -25827,8 +25827,8 @@ bool TestCodeRun::TestYield() {
|
||||
"function gen() {\n"
|
||||
" yield new Evil;\n"
|
||||
" yield null;\n"
|
||||
" yield null;\n"
|
||||
" yield null;\n"
|
||||
" yield new Evil;\n"
|
||||
" yield new Evil;\n"
|
||||
"}\n"
|
||||
"function main() {\n"
|
||||
" $GLOBALS['cont'] = $c = gen();\n"
|
||||
@@ -25837,7 +25837,7 @@ bool TestCodeRun::TestYield() {
|
||||
" $c->send(new Evil);\n"
|
||||
" $GLOBALS['gonext'] = true;\n"
|
||||
" $c->next();\n"
|
||||
" $c->send(new Evil);\n"
|
||||
" $c->send(null);\n"
|
||||
" $c->send(null);\n"
|
||||
" echo \"Finished!\\n\";\n"
|
||||
"}\n"
|
||||
@@ -25848,10 +25848,13 @@ bool TestCodeRun::TestYield() {
|
||||
"NULL\n"
|
||||
"in __destruct()\n"
|
||||
"NULL\n"
|
||||
"in __destruct()\n"
|
||||
"object(Evil)#4 (0) {\n"
|
||||
"}\n"
|
||||
"Caught: Continuation is already running\n"
|
||||
"in __destruct()\n"
|
||||
"NULL\n"
|
||||
"Caught: Continuation is already running\n"
|
||||
"Caught: Continuation is already finished\n"
|
||||
"Finished!\n"
|
||||
"Returned from main safely\n");
|
||||
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário