diff --git a/hphp/compiler/analysis/emitter.cpp b/hphp/compiler/analysis/emitter.cpp index 5ea4a63f5..ba26abf2f 100644 --- a/hphp/compiler/analysis/emitter.cpp +++ b/hphp/compiler/analysis/emitter.cpp @@ -15,37 +15,11 @@ */ #include "hphp/compiler/analysis/emitter.h" - -#include "folly/ScopeGuard.h" - -#include -#include -#include -#include - -#include "hphp/util/logger.h" -#include "hphp/util/util.h" -#include "hphp/util/job_queue.h" -#include "hphp/util/parser/hphp.tab.hpp" -#include "hphp/runtime/vm/bytecode.h" -#include "hphp/runtime/vm/repo.h" -#include "hphp/runtime/vm/as.h" -#include "hphp/runtime/base/stats.h" -#include "hphp/runtime/base/runtime_option.h" -#include "hphp/runtime/base/zend/zend_string.h" -#include "hphp/runtime/base/type_conversions.h" -#include "hphp/runtime/base/builtin_functions.h" -#include "hphp/runtime/base/variable_serializer.h" -#include "hphp/runtime/base/program_functions.h" -#include "hphp/runtime/eval/runtime/file_repository.h" -#include "hphp/runtime/ext_hhvm/ext_hhvm.h" - #include "hphp/compiler/builtin_symbols.h" #include "hphp/compiler/analysis/class_scope.h" #include "hphp/compiler/analysis/file_scope.h" #include "hphp/compiler/analysis/function_scope.h" #include "hphp/compiler/analysis/peephole.h" - #include "hphp/compiler/expression/array_element_expression.h" #include "hphp/compiler/expression/array_pair_expression.h" #include "hphp/compiler/expression/assignment_expression.h" @@ -70,7 +44,6 @@ #include "hphp/compiler/expression/static_member_expression.h" #include "hphp/compiler/expression/unary_op_expression.h" #include "hphp/compiler/expression/yield_expression.h" - #include "hphp/compiler/statement/break_statement.h" #include "hphp/compiler/statement/case_statement.h" #include "hphp/compiler/statement/catch_statement.h" @@ -99,11 +72,34 @@ #include "hphp/compiler/statement/trait_prec_statement.h" #include "hphp/compiler/statement/trait_alias_statement.h" #include "hphp/compiler/statement/typedef_statement.h" - #include "hphp/compiler/parser/parser.h" +#include "hphp/util/logger.h" +#include "hphp/util/util.h" +#include "hphp/util/job_queue.h" +#include "hphp/util/parser/hphp.tab.hpp" +#include "hphp/runtime/vm/bytecode.h" +#include "hphp/runtime/vm/repo.h" +#include "hphp/runtime/vm/as.h" +#include "hphp/runtime/base/stats.h" +#include "hphp/runtime/base/runtime_option.h" +#include "hphp/runtime/base/zend/zend_string.h" +#include "hphp/runtime/base/type_conversions.h" +#include "hphp/runtime/base/builtin_functions.h" +#include "hphp/runtime/base/variable_serializer.h" +#include "hphp/runtime/base/program_functions.h" +#include "hphp/runtime/eval/runtime/file_repository.h" +#include "hphp/runtime/ext_hhvm/ext_hhvm.h" + #include "hphp/system/lib/systemlib.h" +#include "folly/ScopeGuard.h" + +#include +#include +#include +#include + namespace HPHP { namespace Compiler { /////////////////////////////////////////////////////////////////////////////// @@ -6957,18 +6953,19 @@ static Unit* emitHHBCNativeFuncUnit(const HhbcExtFuncInfo* builtinFuncs, mfe->finish(ue->bcPos(), false); ue->recordFunction(mfe); + TypedValue mainReturn; + mainReturn.m_data.num = 1; + mainReturn.m_type = KindOfInt64; + ue->setMainReturn(&mainReturn); + ue->setMergeOnly(true); + /* Special function used by FPushCuf* when its argument is not callable. */ StringData* name = StringData::GetStaticString("86null"); FuncEmitter* fe = ue->newFuncEmitter(name, /*top*/ true); - /* - Dont mark it AttrPersistent, because it would be - deleted, and we need to be able to find it in the - unit's m_mergeInfo - */ - fe->init(0, 0, ue->bcPos(), AttrUnique, + fe->init(0, 0, ue->bcPos(), AttrUnique | AttrPersistent, true, empty_string.get()); ue->emitOp(OpNull); ue->emitOp(OpRetC); @@ -7082,7 +7079,7 @@ static Unit* emitHHBCNativeClassUnit(const HhbcExtClassInfo* builtinClasses, TypedValue mainReturn; mainReturn.m_data.num = 1; - mainReturn.m_type = KindOfBoolean; + mainReturn.m_type = KindOfInt64; ue->setMainReturn(&mainReturn); ue->setMergeOnly(true); diff --git a/hphp/hhvm/process_init.cpp b/hphp/hhvm/process_init.cpp index 6e6528eb6..0bb349c64 100644 --- a/hphp/hhvm/process_init.cpp +++ b/hphp/hhvm/process_init.cpp @@ -114,7 +114,6 @@ void ProcessInit() { Unit* nativeFuncUnit = build_native_func_unit(hhbc_ext_funcs, hhbc_ext_funcs_count); SystemLib::s_nativeFuncUnit = nativeFuncUnit; - String currentDir = g_vmContext->getCwd(); if (RuntimeOption::RepoAuthoritative) { @@ -148,6 +147,8 @@ void ProcessInit() { // load builtins SystemLib::s_nativeFuncUnit->merge(); + SystemLib::s_nullFunc = + Unit::lookupFunc(StringData::GetStaticString("86null")); // We call a special bytecode emitter function to build the native // unit which will contain all of our cppext functions and classes. diff --git a/hphp/runtime/vm/bytecode.cpp b/hphp/runtime/vm/bytecode.cpp index c22e1220d..552e0a5ee 100644 --- a/hphp/runtime/vm/bytecode.cpp +++ b/hphp/runtime/vm/bytecode.cpp @@ -5843,7 +5843,7 @@ inline void OPTBLD_INLINE VMExecutionContext::doFPushCuf(PC& pc, if (safe) m_stack.topTV()[1] = m_stack.topTV()[0]; m_stack.ndiscard(1); if (f == nullptr) { - f = SystemLib::GetNullFunction(); + f = SystemLib::s_nullFunc; if (safe) { m_stack.pushFalse(); } @@ -7536,10 +7536,18 @@ void VMExecutionContext::requestInit() { tx64 = nextTx64; tx64->requestInit(); - // Merge the systemlib unit into the ExecutionContext - SystemLib::s_unit->merge(); - SystemLib::s_nativeFuncUnit->merge(); - SystemLib::s_nativeClassUnit->merge(); + if (UNLIKELY(RuntimeOption::EvalJitEnableRenameFunction)) { + SystemLib::s_unit->merge(); + SystemLib::s_nativeFuncUnit->merge(); + SystemLib::s_nativeClassUnit->merge(); + } else { + // System units are always merge only, and + // everything is persistent. + assert(SystemLib::s_unit->isEmpty()); + assert(SystemLib::s_nativeFuncUnit->isEmpty()); + assert(SystemLib::s_nativeClassUnit->isEmpty()); + } + profileRequestStart(); #ifdef DEBUG diff --git a/hphp/runtime/vm/translator/targetcache.cpp b/hphp/runtime/vm/translator/targetcache.cpp index 13a49f985..59a2e904c 100644 --- a/hphp/runtime/vm/translator/targetcache.cpp +++ b/hphp/runtime/vm/translator/targetcache.cpp @@ -690,7 +690,8 @@ CacheHandle allocKnownClass(const Class* cls) { if (ne->m_cachedClassOffset) return ne->m_cachedClassOffset; return allocKnownClass(ne, - RuntimeOption::RepoAuthoritative && + (!SystemLib::s_inited || + RuntimeOption::RepoAuthoritative) && cls->verifyPersistent()); } diff --git a/hphp/runtime/vm/translator/translator-x64.cpp b/hphp/runtime/vm/translator/translator-x64.cpp index a59b4ca7f..92b811599 100644 --- a/hphp/runtime/vm/translator/translator-x64.cpp +++ b/hphp/runtime/vm/translator/translator-x64.cpp @@ -9532,7 +9532,7 @@ int64_t checkClass(TargetCache::CacheHandle ch, StringData* clsName, VMRegAnchor _; AutoloadHandler::s_instance->invokeHandler(clsName->data()); if (*(Class**)TargetCache::handleToPtr(ch)) return true; - ar->m_func = SystemLib::GetNullFunction(); + ar->m_func = SystemLib::s_nullFunc; if (ar->hasThis()) { // cannot hit zero, we just inc'ed it ar->getThis()->decRefCount(); @@ -9556,7 +9556,7 @@ static const Func* autoloadMissingFunc(const StringData* funcName, throw_invalid_argument("function: method '%s' not found", funcName->data()); } - return SystemLib::GetNullFunction(); + return SystemLib::s_nullFunc; } void @@ -9626,7 +9626,7 @@ TranslatorX64::translateFPushCufOp(const Tracelet& t, emitVStackStore(astubs, ni, rax, funcOff); if (safe) { astubs.xorq(r(flag), r(flag)); - astubs.cmpq(SystemLib::GetNullFunction(), rax); + astubs.cmpq(SystemLib::s_nullFunc, rax); astubs.setne(rbyte(flag)); } } diff --git a/hphp/runtime/vm/unit.cpp b/hphp/runtime/vm/unit.cpp index 64c83edb5..14fb1c22c 100644 --- a/hphp/runtime/vm/unit.cpp +++ b/hphp/runtime/vm/unit.cpp @@ -796,9 +796,9 @@ void Unit::loadFunc(const Func *func) { assert(!func->isMethod()); const NamedEntity *ne = func->getNamedEntity(); if (UNLIKELY(!ne->m_cachedFuncOffset)) { - Transl::TargetCache::allocFixedFunction(ne, - func->attrs() & AttrPersistent && - RuntimeOption::RepoAuthoritative); + Transl::TargetCache::allocFixedFunction( + ne, func->attrs() & AttrPersistent && + (RuntimeOption::RepoAuthoritative || !SystemLib::s_inited)); } const_cast(func)->m_cachedOffset = ne->m_cachedFuncOffset; } @@ -819,6 +819,7 @@ void Unit::initialMerge() { unitInitLock.assertOwnedBySelf(); if (LIKELY(m_mergeState == UnitMergeStateUnmerged)) { int state = 0; + bool needsCompact = false; m_mergeState = UnitMergeStateMerging; bool allFuncsUnique = RuntimeOption::RepoAuthoritative; @@ -828,9 +829,12 @@ void Unit::initialMerge() { allFuncsUnique = (f->attrs() & AttrUnique); } loadFunc(f); + if (TargetCache::isPersistentHandle(f->m_cachedOffset)) { + needsCompact = true; + } } if (allFuncsUnique) state |= UnitMergeStateUniqueFuncs; - if (!RuntimeOption::RepoAuthoritative) { + if (!RuntimeOption::RepoAuthoritative && SystemLib::s_inited) { Transl::mergePreConsts(m_preConsts); } else { /* @@ -851,7 +855,6 @@ void Unit::initialMerge() { * the pointer will be followed by a TypedValue representing * the value being defined/assigned. */ - bool needsCompact = false; int ix = m_mergeInfo->m_firstHoistablePreClass; int end = m_mergeInfo->m_firstMergeablePreClass; while (ix < end) { diff --git a/hphp/runtime/vm/unit.h b/hphp/runtime/vm/unit.h index 99a396e17..6e15293f4 100644 --- a/hphp/runtime/vm/unit.h +++ b/hphp/runtime/vm/unit.h @@ -642,6 +642,7 @@ public: } bool isMergeOnly() const { return m_mergeOnly; } void clearMergeOnly() { m_mergeOnly = false; } + bool isEmpty() const { return m_mergeState & UnitMergeStateEmpty; } void* replaceUnit() const; public: static Mutex s_classesMutex; diff --git a/hphp/system/lib/systemlib.cpp b/hphp/system/lib/systemlib.cpp index 1a65528f2..9a24aff58 100644 --- a/hphp/system/lib/systemlib.cpp +++ b/hphp/system/lib/systemlib.cpp @@ -36,6 +36,7 @@ bool SystemLib::s_inited = false; HPHP::Unit* SystemLib::s_unit = nullptr; HPHP::Unit* SystemLib::s_nativeFuncUnit = nullptr; HPHP::Unit* SystemLib::s_nativeClassUnit = nullptr; +HPHP::Func* SystemLib::s_nullFunc = nullptr; #define DEFINE_SYSTEMLIB_CLASS(cls) \ HPHP::Class* SystemLib::s_ ## cls ## Class = nullptr; @@ -154,13 +155,6 @@ ObjectData* SystemLib::AllocKeyedIterableViewObject(CVarRef iterable) { #undef CREATE_AND_CONSTRUCT -Func* -SystemLib::GetNullFunction() { - Func* f = s_nativeFuncUnit->firstHoistable(); - assert(!strcmp(f->name()->data(), "86null")); - return f; -} - ALLOC_OBJECT_STUB(Directory); ALLOC_OBJECT_STUB(RecursiveDirectoryIterator); ALLOC_OBJECT_STUB(PDOException); diff --git a/hphp/system/lib/systemlib.h b/hphp/system/lib/systemlib.h index 91dcf5dcb..48f7b768f 100644 --- a/hphp/system/lib/systemlib.h +++ b/hphp/system/lib/systemlib.h @@ -23,9 +23,9 @@ namespace HPHP { /////////////////////////////////////////////////////////////////////////////// class ObjectData; - class Unit; - class Class; - class Func; +class Unit; +class Class; +class Func; namespace Eval { class PhpFile; } @@ -79,8 +79,7 @@ class SystemLib { SYSTEMLIB_CLASSES(DECLARE_SYSTEMLIB_CLASS) #undef DECLARE_SYSTEMLIB_CLASS - static HPHP::Func* GetNullFunction(); - + static HPHP::Func* s_nullFunc; static ObjectData* AllocStdClassObject(); static ObjectData* AllocPinitSentinel();