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:
Mark Williams
2013-05-14 14:40:17 -07:00
commit de Sara Golemon
commit 5c491af2de
9 arquivos alterados com 66 adições e 62 exclusões
+32 -35
Ver Arquivo
@@ -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);
+2 -1
Ver Arquivo
@@ -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.
+13 -5
Ver Arquivo
@@ -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
+2 -1
Ver Arquivo
@@ -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());
}
+3 -3
Ver Arquivo
@@ -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));
}
}
+8 -5
Ver Arquivo
@@ -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) {
+1
Ver Arquivo
@@ -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;
+1 -7
Ver Arquivo
@@ -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);
+4 -5
Ver Arquivo
@@ -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();