void Symbol::triggerUpdates(BlockScopeRawPtr scope) const { int useKind = BlockScope::GetNonStaticRefUseKind(getHash()); if (isConstant()) { useKind = BlockScope::UseKindConstRef; if (m_declaration) { BlockScopeRawPtr declScope(m_declaration->getScope()); /** * Constants can only belong to a file or class scope */ assert(scope->is(BlockScope::FileScope) || scope->is(BlockScope::ClassScope)); /** * Constants can only be declared in a function or * class scope */ assert(declScope->is(BlockScope::FunctionScope) || declScope->is(BlockScope::ClassScope)); /** * For class scopes, the declaration scope *must* * match the scope the symbol lives in */ assert(!scope->is(BlockScope::ClassScope) || scope == declScope); /** * For file scopes, the declaration scope *must* * live in a function scope */ assert(!scope->is(BlockScope::FileScope) || declScope->is(BlockScope::FunctionScope)); /** * This is really only for file scopes (constants created with * define('FOO', ...)). const FOO = 1 outside of a class is re-written * into a define('FOO', 1) by earlier phases of the compiler */ if (scope->is(BlockScope::FileScope)) { declScope->announceUpdates(BlockScope::UseKindConstRef); return; } } } else if (isStatic()) { useKind = BlockScope::UseKindStaticRef; } else if (isParameter()) { useKind = BlockScope::UseKindCallerParam; } if (isPassClosureVar()) { useKind |= BlockScope::UseKindClosure; } scope->addUpdates(useKind); }
int DepthFirstVisitor<Pre, OptVisitor>::visitScope(BlockScopeRawPtr scope) { int updates, all_updates = 0; StatementPtr stmt = scope->getStmt(); if (MethodStatementPtr m = dynamic_pointer_cast<MethodStatement>(stmt)) { WriteLock lock(m->getFunctionScope()->getInlineMutex()); do { scope->clearUpdated(); if (Option::LocalCopyProp || Option::EliminateDeadCode) { AliasManager am(-1); if (am.optimize(this->m_data.m_ar, m)) { scope->addUpdates(BlockScope::UseKindCaller); } } else { StatementPtr rep = this->visitStmtRecur(stmt); always_assert(!rep); } updates = scope->getUpdated(); all_updates |= updates; } while (updates); if (all_updates & BlockScope::UseKindCaller && !m->getFunctionScope()->getInlineAsExpr()) { all_updates &= ~BlockScope::UseKindCaller; } return all_updates; } do { scope->clearUpdated(); StatementPtr rep = this->visitStmtRecur(stmt); always_assert(!rep); updates = scope->getUpdated(); all_updates |= updates; } while (updates); return all_updates; }