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:
Jan Oravec
2013-06-05 22:02:50 -07:00
commit de sgolemon
commit c839f3c3d0
5 arquivos alterados com 21 adições e 15 exclusões
-7
Ver Arquivo
@@ -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");
-3
Ver Arquivo
@@ -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));
+7 -5
Ver Arquivo
@@ -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();
}
+6
Ver Arquivo
@@ -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