Fix static variables in closure generators
Each closure instance carries its own set of static variables. Multiple generators created using the same closure instance should share their static variables. This was not the case and static variables in closure generators behaved like normal local variables. Let's fix it by referencing closure and using its static locals. Pointer to the closure is located in the local following original input arguments. These are shifted by one, as Continuation occupies local 0. This also frees 8 bytes from c_Continuation (or 16 if you count 16-byte alignment).
Esse commit está contido em:
@@ -169,13 +169,6 @@ Variant c_Continuation::t___clone() {
|
||||
return uninit_null();
|
||||
}
|
||||
|
||||
HphpArray* c_Continuation::getStaticLocals() {
|
||||
if (m_VMStatics.get() == NULL) {
|
||||
m_VMStatics = ArrayData::Make(1);
|
||||
}
|
||||
return m_VMStatics.get();
|
||||
}
|
||||
|
||||
namespace {
|
||||
StaticString s_send("send");
|
||||
StaticString s_raise("raise");
|
||||
|
||||
@@ -131,11 +131,8 @@ public:
|
||||
|
||||
p_ContinuationWaitHandle m_waitHandle;
|
||||
|
||||
SmartPtr<HphpArray> m_VMStatics;
|
||||
|
||||
String& getCalledClass() { not_reached(); }
|
||||
|
||||
HphpArray* getStaticLocals();
|
||||
static size_t sizeForLocalsAndIters(int nLocals, int nIters) {
|
||||
return (sizeof(c_Continuation) + sizeof(TypedValue) * nLocals +
|
||||
sizeof(Iter) * nIters + sizeof(ActRec));
|
||||
|
||||
@@ -361,14 +361,16 @@ HphpArray* pack_args_into_array(ActRec* ar, int nargs) {
|
||||
HphpArray* get_static_locals(const ActRec* ar) {
|
||||
if (ar->m_func->isClosureBody()) {
|
||||
TypedValue* closureLoc = frame_local(ar, ar->m_func->numParams());
|
||||
c_Closure* closure = static_cast<c_Closure*>(closureLoc->m_data.pobj);
|
||||
assert(closure != nullptr);
|
||||
return closure->getStaticLocals();
|
||||
assert(dynamic_cast<c_Closure*>(closureLoc->m_data.pobj));
|
||||
return static_cast<c_Closure*>(closureLoc->m_data.pobj)->getStaticLocals();
|
||||
} else if (ar->m_func->isGeneratorFromClosure()) {
|
||||
TypedValue* contLoc = frame_local(ar, 0);
|
||||
assert(dynamic_cast<c_Continuation*>(contLoc->m_data.pobj));
|
||||
c_Continuation* cont = static_cast<c_Continuation*>(contLoc->m_data.pobj);
|
||||
assert(cont != nullptr);
|
||||
return cont->getStaticLocals();
|
||||
|
||||
TypedValue* closureLoc = frame_local(ar, cont->m_origFunc->numParams() + 1);
|
||||
assert(dynamic_cast<c_Closure*>(closureLoc->m_data.pobj));
|
||||
return static_cast<c_Closure*>(closureLoc->m_data.pobj)->getStaticLocals();
|
||||
} else {
|
||||
return ar->m_func->getStaticLocals();
|
||||
}
|
||||
|
||||
@@ -28,6 +28,12 @@ dumpEach($cgg);
|
||||
$cgg = null;
|
||||
$cgg = $cg();
|
||||
dumpEach($cgg);
|
||||
$cg = makeClosureGen();
|
||||
$cgg = $cg();
|
||||
dumpEach($cgg);
|
||||
$cgg = null;
|
||||
$cgg = $cg();
|
||||
dumpEach($cgg);
|
||||
|
||||
function makeClosure() {
|
||||
return function() {
|
||||
|
||||
@@ -4,10 +4,18 @@ int(0)
|
||||
int(0)
|
||||
int(1)
|
||||
int(1)
|
||||
int(2)
|
||||
int(2)
|
||||
int(3)
|
||||
int(3)
|
||||
int(0)
|
||||
int(0)
|
||||
int(1)
|
||||
int(1)
|
||||
int(2)
|
||||
int(2)
|
||||
int(3)
|
||||
int(3)
|
||||
|
||||
plain closure:
|
||||
012
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário