From fb214b965505a458939450beee83541ecbff4d20 Mon Sep 17 00:00:00 2001 From: mwilliams Date: Thu, 18 Apr 2013 16:32:39 -0700 Subject: [PATCH] Better dynamic constant support in repo mode A constant defined in a function/method should be treated as dynamic. A class constant with a dynamic initializer should evaluate to the value of its initializer at the time the constant was first seen; so the optimization should be all or nothing - either turn the class constant into a scalar, or leave it in its original form. --- .../expression/class_constant_expression.cpp | 13 ++++++++++ .../expression/simple_function_call.cpp | 25 ++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/hphp/compiler/expression/class_constant_expression.cpp b/hphp/compiler/expression/class_constant_expression.cpp index dbabb2670..cebbb0597 100644 --- a/hphp/compiler/expression/class_constant_expression.cpp +++ b/hphp/compiler/expression/class_constant_expression.cpp @@ -144,6 +144,19 @@ ExpressionPtr ClassConstantExpression::preOptimize(AnalysisResultConstPtr ar) { ExpressionPtr value = dynamic_pointer_cast(decl); BlockScope::s_constMutex.unlock(); + if (!value->isScalar() && + (value->is(KindOfClassConstantExpression) || + value->is(KindOfConstantExpression))) { + std::set seen; + do { + if (!seen.insert(value).second) return ExpressionPtr(); + value = value->preOptimize(ar); + if (!value) return ExpressionPtr(); + } while (!value->isScalar() && + (value->is(KindOfClassConstantExpression) || + value->is(KindOfConstantExpression))); + } + ExpressionPtr rep = Clone(value, getScope()); bool annotate = Option::FlAnnotate; Option::FlAnnotate = false; // avoid nested comments on getText diff --git a/hphp/compiler/expression/simple_function_call.cpp b/hphp/compiler/expression/simple_function_call.cpp index cb69c7cb9..2b2605141 100644 --- a/hphp/compiler/expression/simple_function_call.cpp +++ b/hphp/compiler/expression/simple_function_call.cpp @@ -332,7 +332,8 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) { // check for dynamic constant and volatile function/class if (!m_class && m_className.empty() && - (m_type == DefinedFunction || + (m_type == DefineFunction || + m_type == DefinedFunction || m_type == FunctionExistsFunction || m_type == FBCallUserFuncSafeFunction || m_type == ClassExistsFunction || @@ -345,6 +346,28 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) { if (name && name->isLiteralString()) { string symbol = name->getLiteralString(); switch (m_type) { + case DefineFunction: { + ConstantTableConstPtr constants = ar->getConstants(); + // system constant + if (constants->isPresent(symbol)) { + break; + } + // user constant + BlockScopeConstPtr block = ar->findConstantDeclarer(symbol); + // not found (i.e., undefined) + if (!block) break; + constants = block->getConstants(); + const Symbol *sym = constants->getSymbol(symbol); + always_assert(sym); + if (!sym->isDynamic()) { + if (FunctionScopeRawPtr fsc = getFunctionScope()) { + if (!fsc->inPseudoMain()) { + const_cast(sym)->setDynamic(); + } + } + } + break; + } case DefinedFunction: { ConstantTablePtr constants = ar->getConstants(); if (!constants->isPresent(symbol)) {