static Array HHVM_FUNCTION(xdebug_get_declared_vars) { if (RuntimeOption::RepoAuthoritative) { raise_error("xdebug_get_declared_vars unsupported in RepoAuthoritative " "mode"); } // Grab the callee function VMRegAnchor _; // Ensure consistent state for vmfp auto func = g_context->getPrevFunc(vmfp()); if (!func) { return Array::Create(); } // Add each named local to the returned array. Note that since this function // is supposed to return all _declared_ variables in scope, which includes // variables that have been unset. auto const numNames = func->numNamedLocals(); PackedArrayInit vars(numNames); for (Id i = 0; i < numNames; ++i) { assert(func->lookupVarId(func->localVarName(i)) == i); String varname(const_cast<StringData*>(func->localVarName(i))); // Skip the internal closure "0Closure" variable if (!s_closure_varname.equal(varname)) { vars.append(varname); } } return vars.toArray(); }
NameValueTable::NameValueTable(ActRec* fp) : m_fp(fp) , m_table(nullptr) , m_tabMask(0) , m_elms(0) { assert(m_fp); const auto func = m_fp->m_func; const Id numNames = func->numNamedLocals(); /** * Reserve space for all named locals plus one additional variable * to avoid reallocations if one extra dynamic variable is used. */ reserve(numNames + 1); for (Id i = 0; i < numNames; ++i) { assert(func->lookupVarId(func->localVarName(i)) == i); auto elm = insert(func->localVarName(i)); assert(elm && elm->m_tv.m_type == KindOfInvalid); elm->m_tv.m_type = KindOfNamedLocal; elm->m_tv.m_data.num = i; } }
void NameValueTable::detach(ActRec* fp) { assert(m_fp == fp); m_fp = nullptr; const auto func = fp->m_func; const Id numNames = func->numNamedLocals(); TypedValue* loc = frame_local(fp, 0); for (Id i = 0; i < numNames; ++i, --loc) { assert(func->lookupVarId(func->localVarName(i)) == i); auto elm = findElm(func->localVarName(i)); assert(elm && elm->m_tv.m_type == KindOfNamedLocal); tvCopy(*loc, elm->m_tv); tvDebugTrash(loc); } }
void NameValueTable::attach(ActRec* fp) { assert(m_fp == nullptr); m_fp = fp; const auto func = fp->m_func; const Id numNames = func->numNamedLocals(); TypedValue* loc = frame_local(fp, 0); for (Id i = 0; i < numNames; ++i, --loc) { assert(func->lookupVarId(func->localVarName(i)) == i); auto elm = insert(func->localVarName(i)); assert(elm); if (elm->m_tv.m_type != KindOfInvalid) { assert(elm->m_tv.m_type != KindOfNamedLocal); tvCopy(elm->m_tv, *loc); } elm->m_tv.m_type = KindOfNamedLocal; elm->m_tv.m_data.num = i; } }