Don't reinitialize native funcs
The Func*'s in the native func unit are all persistent, which means that we can strip them, and skip the Unit::merge call on every request. But we didnt set the flag to compact the unit if the only things that needed stripping were Func*'s. Fixed that, and also fixed it so all the builtins are marked persistent even in non-repo-auth mode (funcs are not if rename function is enabled, because we implement fb_rename_function by swapping target cache entries).
Esse commit está contido em:
@@ -15,37 +15,11 @@
|
||||
*/
|
||||
|
||||
#include "hphp/compiler/analysis/emitter.h"
|
||||
|
||||
#include "folly/ScopeGuard.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#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 <iostream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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*>(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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário