From bf52b61852bbb09042af3056b90841a9193aeaae Mon Sep 17 00:00:00 2001 From: Bert Maher Date: Wed, 5 Jun 2013 13:46:13 -0700 Subject: [PATCH] Allow early initialization of classes if they don't have any [sp]init methods We were being too conservative in determining whether to use the static property cache when accessing a property from outside the class. In fact we'd never use it in that case, because we required that the class not need initialization (and any class with static properties needs initialization!). We can relax this restriction to just enforce that the class not define sinit or pinit methods -- scalar properties are fine. --- hphp/runtime/vm/class.cpp | 1 + hphp/runtime/vm/class.h | 8 ++++++-- hphp/runtime/vm/jit/simplifier.cpp | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/hphp/runtime/vm/class.cpp b/hphp/runtime/vm/class.cpp index 69760882b..4d6a7b53b 100644 --- a/hphp/runtime/vm/class.cpp +++ b/hphp/runtime/vm/class.cpp @@ -2197,6 +2197,7 @@ void Class::setInitializers() { m_needInitialization = (m_pinitVec.size() > 0 || m_staticProperties.size() > 0); + m_hasInitMethods = (m_pinitVec.size() > 0 || m_sinitVec.size() > 0); // The __init__ method defined in the Exception class gets special treatment static StringData* sd__init__ = StringData::GetStaticString("__init__"); diff --git a/hphp/runtime/vm/class.h b/hphp/runtime/vm/class.h index 542740478..5827ce7ce 100644 --- a/hphp/runtime/vm/class.h +++ b/hphp/runtime/vm/class.h @@ -721,6 +721,7 @@ public: bool hasDeepInitProps() const { return m_hasDeepInitProps; } bool needInitialization() const { return m_needInitialization; } + bool hasInitMethods() const { return m_hasInitMethods; } bool callsCustomInstanceInit() const { return m_callsCustomInstanceInit; } const InterfaceMap& allInterfaces() const { return m_interfaces; } const std::vector& usedTraits() const { @@ -966,11 +967,14 @@ private: InitVec m_pinitVec; InitVec m_sinitVec; const ClassInfo* m_clsInfo; - unsigned m_needInitialization : 1; // any __[ps]init() methods? + unsigned m_needInitialization : 1; // requires initialization, + // due to [ps]init or simply + // having static members + unsigned m_hasInitMethods : 1; // any __[ps]init() methods? unsigned m_callsCustomInstanceInit : 1; // should we always call __init__ // on new instances? unsigned m_hasDeepInitProps : 1; - unsigned m_attrCopy : 29; // cache of m_preClass->attrs(). + unsigned m_attrCopy : 28; // cache of m_preClass->attrs(). int m_ODAttrs; int m_builtinPropSize; diff --git a/hphp/runtime/vm/jit/simplifier.cpp b/hphp/runtime/vm/jit/simplifier.cpp index f666bc047..54e8bf3f9 100644 --- a/hphp/runtime/vm/jit/simplifier.cpp +++ b/hphp/runtime/vm/jit/simplifier.cpp @@ -223,7 +223,7 @@ bool canUseSPropCache(SSATmp* clsTmp, // initialized yet. getSProp() below will trigger initialization, // but that's only valid to do earlier if it doesn't require any // property initializer ([sp]init methods). - if (cls->needInitialization()) return false; + if (cls->hasInitMethods()) return false; bool visible, accessible; cls->getSProp(const_cast(ctx), propName, visible, accessible);