Permalink
Browse files

Use Eval.AllowObjectDestructors in hhbbc and add some RuntimeOptions …

…for testing

Summary: Thread Eval.AllowObjectDestructors through hhbbc and use it in `could_run_destructor` checks. Additionally add options to mark all destructors as optional and suppress error handling (these are just useful for testing).

Reviewed By: ottoni

Differential Revision: D6970251

fbshipit-source-id: 07680d02a1c72d90f653281c640c76dfc1826b00
  • Loading branch information...
paulbiss authored and hhvm-bot committed Feb 15, 2018
1 parent 72ab5dd commit 660cdcb7def2fdcccbb97d52ef8ee6ff66afd534
@@ -12478,6 +12478,7 @@ void commitGlobalData(std::unique_ptr<ArrayTypeTable::Builder> arrTable) {
gd.EnableIntrinsicsExtension = RuntimeOption::EnableIntrinsicsExtension;
gd.ReffinessInvariance = RuntimeOption::EvalReffinessInvariance;
gd.NoticeOnAllDynamicCalls = RuntimeOption::EvalNoticeOnAllDynamicCalls;
gd.AllowObjectDestructors = RuntimeOption::EvalAllowObjectDestructors;
gd.NoticeOnBuiltinDynamicCalls =
RuntimeOption::EvalNoticeOnBuiltinDynamicCalls;
gd.InitialNamedEntityTableSize =
@@ -280,6 +280,9 @@ void Option::Load(const IniSetting::Map& ini, Hdf &config) {
Config::Bind(RuntimeOption::EvalUseMSRVForInOut,
ini, config, "UseMSRVForInOut",
RuntimeOption::EvalUseMSRVForInOut);
Config::Bind(RuntimeOption::EvalAllowObjectDestructors,
ini, config, "AllowObjectDestructors",
RuntimeOption::EvalAllowObjectDestructors);
{
// Hack
@@ -1088,8 +1088,8 @@ void pushRemovable(Env& env) {
*/
void dce(Env& env, const bc::PopC&) { discardNonDtors(env); }
// For PopV and PopR currently we never know if can't run a
// destructor.
void dce(Env& env, const bc::PopV&) { discardNonDtors(env); }
void dce(Env& env, const bc::PopR&) { discardNonDtors(env); }
void dce(Env& env, const bc::PopU&) { discard(env); }
void dce(Env& env, const bc::Int&) { pushRemovable(env); }
void dce(Env& env, const bc::String&) { pushRemovable(env); }
@@ -4097,7 +4097,7 @@ void in(ISS& env, const bc::InitProp& op) {
break;
}
auto const v = tv(t);
if (v || !could_run_destructor(t)) {
if (v || !could_contain_objects(t)) {
for (auto& prop : env.ctx.func->cls->properties) {
if (prop.name == op.str1) {
ITRACE(1, "InitProp: {} = {}\n", op.str1, show(t));
@@ -250,6 +250,7 @@ std::pair<std::vector<std::unique_ptr<UnitEmitter>>,
RuntimeOption::EvalJitEnableRenameFunction = gd.EnableRenameFunction;
RuntimeOption::EvalHackArrCompatNotices = gd.HackArrCompatNotices;
RuntimeOption::EvalNoticeOnAllDynamicCalls = gd.NoticeOnAllDynamicCalls;
RuntimeOption::EvalAllowObjectDestructors = gd.AllowObjectDestructors;
RuntimeOption::EvalNoticeOnBuiltinDynamicCalls =
gd.NoticeOnBuiltinDynamicCalls;
RuntimeOption::EvalHackArrCompatIsArrayNotices =
@@ -321,6 +322,7 @@ void write_global_data(
gd.APCProfile = std::move(apcProfile);
gd.ReffinessInvariance = RuntimeOption::EvalReffinessInvariance;
gd.NoticeOnAllDynamicCalls = RuntimeOption::EvalNoticeOnAllDynamicCalls;
gd.AllowObjectDestructors = RuntimeOption::EvalAllowObjectDestructors;
gd.NoticeOnBuiltinDynamicCalls =
RuntimeOption::EvalNoticeOnBuiltinDynamicCalls;
gd.HackArrCompatIsArrayNotices =
@@ -4464,15 +4464,15 @@ IterTypes iter_types(const Type& iterable) {
not_reached();
}
bool could_run_destructor(const Type& t) {
bool could_contain_objects(const Type& t) {
if (t.couldBe(TObj)) return true;
auto const couldBeArrWithDestructors =
t.m_bits & (BCArrN | BCVecN | BCDictN);
if (t.couldBe(TRef)) {
if (!couldBeArrWithDestructors && is_ref_with_inner(t)) {
return could_run_destructor(*t.m_data.inner);
return could_contain_objects(*t.m_data.inner);
}
return true;
}
@@ -4491,23 +4491,28 @@ bool could_run_destructor(const Type& t) {
case DataTag::ArrLikeVal: return false;
case DataTag::ArrLikePacked:
for (auto const& e : t.m_data.packed->elems) {
if (could_run_destructor(e)) return true;
if (could_contain_objects(e)) return true;
}
return false;
case DataTag::ArrLikePackedN:
return could_run_destructor(t.m_data.packedn->type);
return could_contain_objects(t.m_data.packedn->type);
case DataTag::ArrLikeMap:
for (auto const& kv : t.m_data.map->map) {
if (could_run_destructor(kv.second)) return true;
if (could_contain_objects(kv.second)) return true;
}
return false;
case DataTag::ArrLikeMapN:
return could_run_destructor(t.m_data.mapn->val);
return could_contain_objects(t.m_data.mapn->val);
}
not_reached();
}
bool could_run_destructor(const Type& t) {
if (!RuntimeOption::EvalAllowObjectDestructors) return false;
return could_contain_objects(t);
}
bool could_copy_on_write(const Type& t) {
return t.m_bits & (BCStr | BCArrN | BCVecN | BCDictN | BCKeysetN);
}
@@ -629,7 +629,7 @@ struct Type {
friend Type vec_val(SArray);
friend Type dict_val(SArray);
friend Type keyset_val(SArray);
friend bool could_run_destructor(const Type&);
friend bool could_contain_objects(const Type&);
friend bool could_copy_on_write(const Type&);
friend Type loosen_staticness(Type);
friend Type loosen_unstaticness(Type);
@@ -1440,6 +1440,12 @@ IterTypes iter_types(const Type&);
*/
RepoAuthType make_repo_type(ArrayTypeTable::Builder&, const Type& t);
/*
* True iff t could be an object or a type which contains objects and
* Eval.AllowObjectDestructors is enbaled.
*/
bool could_run_destructor(const Type& t);
//////////////////////////////////////////////////////////////////////
}}
@@ -798,7 +798,9 @@ void ExecutionContext::handleError(const std::string& msg,
{
ErrorStateHelper esh(this, newErrorState);
if (callUserHandler) {
handled = callUserErrorHandler(ee, errnum, false);
handled =
RuntimeOption::EvalDisableErrorHandler ||
callUserErrorHandler(ee, errnum, false);
}
if (!handled) {
@@ -974,7 +976,9 @@ bool ExecutionContext::onFatalError(const Exception &e) {
}
bool handled = false;
if (RuntimeOption::CallUserHandlerOnFatals) {
handled = callUserErrorHandler(e, errnum, true);
handled =
RuntimeOption::EvalDisableErrorHandler ||
callUserErrorHandler(e, errnum, true);
}
if (!handled && !silenced && !RuntimeOption::AlwaysLogUnhandledExceptions) {
Logger::Log(Logger::LogError, prefix, e, fileAndLine.first.c_str(),
@@ -551,6 +551,7 @@ struct RuntimeOption {
F(bool, HardTypeHints, RepoAuthoritative) \
F(bool, PromoteEmptyObject, !EnableHipHopSyntax) \
F(bool, AllowObjectDestructors, !one_bit_refcount) \
F(bool, AllDestructorsOptional, false) \
F(bool, AllowScopeBinding, true) \
F(bool, JitNoGdb, true) \
F(bool, SpinOnCrash, false) \
@@ -673,6 +674,7 @@ struct RuntimeOption {
F(int32_t, DumpBytecode, 0) \
F(bool, DumpHhas, false) \
F(bool, DisableHphpcOpts, false) \
F(bool, DisableErrorHandler, false) \
F(bool, DumpTC, false) \
F(string, DumpTCPath, "/tmp") \
F(bool, DumpTCAnchors, false) \
@@ -667,6 +667,7 @@ std::string mangleUnitMd5(const std::string& fileMd5) {
+ (RuntimeOption::EvalHackArrDVArrs ? '1' : '0')
+ (RuntimeOption::EvalDisableHphpcOpts ? '1' : '0')
+ (RuntimeOption::EvalUseMSRVForInOut ? '1' : '0')
+ (RuntimeOption::EvalAllowObjectDestructors ? '1' : '0')
+ RuntimeOption::EvalHackCompilerCommand + '\0'
+ mangleUnitPHP7Options()
+ mangleAliasedNamespaces()
@@ -2964,7 +2964,8 @@ void Class::setNativeDataInfo() {
// has one, and the destructor doesn't have the __OptionalDestruct attribute,
// prevent instantiation of the class with an instanceCtor.
if (!RuntimeOption::AllowObjectDestructors() && getDtor()) {
if (getDtor()->userAttributes().count(s___OptionalDestruct.get()) == 0) {
if (getDtor()->userAttributes().count(s___OptionalDestruct.get()) == 0 &&
!RuntimeOption::EvalAllDestructorsOptional) {
allocExtraData();
m_extra.raw()->m_instanceCtor = destructorFatalInstanceCtor;
} else {
@@ -189,6 +189,11 @@ struct Repo::GlobalData {
*/
bool UseMSRVForInOut = false;
/*
* Are objects allowed to run destructors?
*/
bool AllowObjectDestructors = false;
std::vector<const StringData*> APCProfile;
std::vector<std::pair<std::string,Cell>> ConstantFunctions;
@@ -223,6 +228,7 @@ struct Repo::GlobalData {
(NoticeOnAllDynamicCalls)
(NoticeOnBuiltinDynamicCalls)
(UseMSRVForInOut)
(AllowObjectDestructors)
;
}
};

0 comments on commit 660cdcb

Please sign in to comment.