bool SetVariableCommand::setLocalVariable( DebuggerSession* session, const std::string& name, const std::string& value, ScopeObject* scope, folly::dynamic* result ) { VMRegAnchor regAnchor; const auto fp = g_context->getFrameAtDepth(scope->m_frameDepth); const auto func = fp->m_func; const auto localCount = func->numNamedLocals(); for (Id id = 0; id < localCount; id++) { TypedValue* frameValue = frame_local(fp, id); const std::string localName = func->localVarName(id)->toCppString(); if (localName == name) { setVariableValue( session, name, value, frameValue, scope->m_requestId, result ); return true; } } return false; }
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; } }
Id FuncEmitter::allocUnnamedLocal() { ++m_activeUnnamedLocals; if (m_activeUnnamedLocals > m_numUnnamedLocals) { ++m_numLocals; ++m_numUnnamedLocals; } return numNamedLocals() - 1 + m_activeUnnamedLocals; }
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; } }