Keep track of whether we're jitting or not

Rather than test RuntimeOption::EvalJit and 5 thread locals to determine
whether or not to run the jit on each re-entry, maintain one thread local.
Make various RequestInjectionData fields private to ensure that the jit
flag is kept in sync.
Esse commit está contido em:
Mark Williams
2013-05-08 06:33:29 -07:00
commit de Sara Golemon
commit 1e75626704
13 arquivos alterados com 94 adições e 49 exclusões
+2 -1
Ver Arquivo
@@ -509,7 +509,8 @@ ssize_t check_request_surprise(ThreadInfo *info) {
bool do_timedout, do_memExceeded, do_signaled;
ssize_t flags = p.fetchAndClearFlags();
do_timedout = (flags & RequestInjectionData::TimedOutFlag) && !p.debugger;
do_timedout = (flags & RequestInjectionData::TimedOutFlag) &&
!p.getDebugger();
do_memExceeded = (flags & RequestInjectionData::MemExceededFlag);
do_signaled = (flags & RequestInjectionData::SignaledFlag);
+1 -1
Ver Arquivo
@@ -503,7 +503,7 @@ void execute_command_line_end(int xhprof, bool coverage, const char *program) {
}
hphp_context_exit(g_context.getNoCheck(), true, true, program);
hphp_session_exit();
if (coverage && ti->m_reqInjectionData.coverage &&
if (coverage && ti->m_reqInjectionData.getCoverage() &&
!RuntimeOption::CodeCoverageOutputFile.empty()) {
ti->m_coverage->Report(RuntimeOption::CodeCoverageOutputFile);
}
+12 -3
Ver Arquivo
@@ -128,12 +128,21 @@ void RequestInjectionData::onSessionInit() {
void RequestInjectionData::reset() {
__sync_fetch_and_and(getConditionFlags(), 0);
coverage = RuntimeOption::RecordCodeCoverage;
debugger = false;
debuggerIntr = false;
m_coverage = RuntimeOption::RecordCodeCoverage;
m_debugger = false;
m_debuggerIntr = false;
updateJit();
while (!interrupts.empty()) interrupts.pop();
}
void RequestInjectionData::updateJit() {
m_jit = RuntimeOption::EvalJit &&
!(RuntimeOption::EvalJitDisabledByHphpd && m_debugger) &&
!m_debuggerIntr &&
!m_coverage &&
!VM::shouldProfile();
}
void RequestInjectionData::setMemExceededFlag() {
__sync_fetch_and_or(getConditionFlags(),
RequestInjectionData::MemExceededFlag);
+32 -6
Ver Arquivo
@@ -394,8 +394,9 @@ public:
RequestInjectionData()
: cflagsPtr(nullptr), surprisePage(nullptr), started(0), timeoutSeconds(-1),
debugger(false), dummySandbox(false),
debuggerIntr(false), coverage(false) {
m_debugger(false), m_dummySandbox(false),
m_debuggerIntr(false), m_coverage(false),
m_jit(false) {
}
inline volatile ssize_t* getConditionFlags() {
@@ -411,12 +412,37 @@ public:
time_t started; // when a request was started
int timeoutSeconds; // how many seconds to timeout
private:
bool m_debugger; // whether there is a DebuggerProxy attached to me
bool m_dummySandbox; // indicating it is from a dummy sandbox thread
bool m_debuggerIntr; // indicating we should force interrupt for debugger
bool m_coverage; // is coverage being collected
bool m_jit; // is the jit enabled
public:
bool getJit() const { return m_jit; }
bool getDebugger() const { return m_debugger; }
void setDebugger(bool d) {
m_debugger = d;
updateJit();
}
static uint32_t debuggerReadOnlyOffset() {
return offsetof(RequestInjectionData, m_debugger);
}
bool getDebuggerIntr() const { return m_debuggerIntr; }
void setDebuggerIntr(bool d) {
m_debuggerIntr = d;
updateJit();
}
bool getCoverage() const { return m_coverage; }
void setCoverage(bool flag) {
m_coverage = flag;
updateJit();
}
bool getDummySandbox() const { return m_dummySandbox; }
void setDummySandbox(bool ds) { m_dummySandbox = ds; }
void updateJit();
bool debugger; // whether there is a DebuggerProxy attached to me
bool dummySandbox; // indicating it is from a dummy sandbox thread
bool debuggerIntr; // indicating we should force interrupt for debugger
std::stack<void *> interrupts; // CmdInterrupts this thread's handling
bool coverage; // is coverage being collected
void reset();
+12 -12
Ver Arquivo
@@ -137,7 +137,7 @@ void Debugger::DebuggerSession(const DebuggerClientOptions& options,
hphp_invoke_simple(options.extension);
}
ThreadInfo *ti = ThreadInfo::s_threadInfo.getNoCheck();
ti->m_reqInjectionData.debugger = true;
ti->m_reqInjectionData.setDebugger(true);
if (!restart) {
DebuggerDummyEnv dde;
Debugger::InterruptSessionStarted(file.c_str());
@@ -154,7 +154,7 @@ void Debugger::DebuggerSession(const DebuggerClientOptions& options,
void Debugger::InterruptSessionStarted(const char *file,
const char *error /* = NULL */) {
TRACE(2, "Debugger::InterruptSessionStarted\n");
ThreadInfo::s_threadInfo->m_reqInjectionData.debugger = true;
ThreadInfo::s_threadInfo->m_reqInjectionData.setDebugger(true);
Interrupt(SessionStarted, file, nullptr, error);
}
@@ -165,14 +165,14 @@ void Debugger::InterruptSessionEnded(const char *file) {
void Debugger::InterruptRequestStarted(const char *url) {
TRACE(2, "Debugger::InterruptRequestStarted\n");
if (ThreadInfo::s_threadInfo->m_reqInjectionData.debugger) {
if (ThreadInfo::s_threadInfo->m_reqInjectionData.getDebugger()) {
Interrupt(RequestStarted, url);
}
}
void Debugger::InterruptRequestEnded(const char *url) {
TRACE(2, "Debugger::InterruptRequestEnded: url=%s\n", url);
if (ThreadInfo::s_threadInfo->m_reqInjectionData.debugger) {
if (ThreadInfo::s_threadInfo->m_reqInjectionData.getDebugger()) {
Interrupt(RequestEnded, url);
}
CStrRef sandboxId = g_context->getSandboxId();
@@ -181,7 +181,7 @@ void Debugger::InterruptRequestEnded(const char *url) {
void Debugger::InterruptPSPEnded(const char *url) {
TRACE(2, "Debugger::InterruptPSPEnded\n");
if (ThreadInfo::s_threadInfo->m_reqInjectionData.debugger) {
if (ThreadInfo::s_threadInfo->m_reqInjectionData.getDebugger()) {
Interrupt(PSPEnded, url);
}
}
@@ -193,7 +193,7 @@ bool Debugger::InterruptException(CVarRef e) {
TRACE(2, "Debugger::InterruptException\n");
if (RuntimeOption::EnableDebugger) {
ThreadInfo *ti = ThreadInfo::s_threadInfo.getNoCheck();
if (ti->m_reqInjectionData.debugger) {
if (ti->m_reqInjectionData.getDebugger()) {
HPHP::VM::Transl::VMRegAnchor _;
InterruptVMHook(ExceptionThrown, e);
}
@@ -232,7 +232,7 @@ void Debugger::Interrupt(int type, const char *program,
// Some cmds require us to interpret all instructions until the cmd
// completes. Setting this will ensure we stay out of JIT code and in the
// interpreter so phpDebuggerOpcodeHook has a chance to work.
rjdata.debuggerIntr = proxy->needVMInterrupts();
rjdata.setDebuggerIntr(proxy->needVMInterrupts());
} else {
TRACE(3, "proxy == null\n");
// Debugger clients are disconnected abnormally, or this sandbox is not
@@ -300,7 +300,7 @@ bool Debugger::isThreadDebugging(int64_t tid) {
ThreadInfoMap::const_accessor acc;
if (m_threadInfos.find(acc, tid)) {
ThreadInfo* ti = acc->second;
return (ti->m_reqInjectionData.debugger);
return (ti->m_reqInjectionData.getDebugger());
}
return false;
}
@@ -358,7 +358,7 @@ void Debugger::registerSandbox(const DSandboxInfo &sandbox) {
// find out whether this sandbox is being debugged
DebuggerProxyPtr proxy = findProxy(sid);
if (proxy) {
ti->m_reqInjectionData.debugger = true;
ti->m_reqInjectionData.setDebugger(true);
proxy->writeInjTablesToThread();
}
}
@@ -392,19 +392,19 @@ void Debugger::requestInterrupt(DebuggerProxyPtr proxy) {
TRACE(2, "Debugger::requestInterrupt\n");
const StringData* sid = StringData::GetStaticString(proxy->getSandboxId());
FOREACH_SANDBOX_THREAD_BEGIN(sid, ti)
ti->m_reqInjectionData.debuggerIntr = true;
ti->m_reqInjectionData.setDebuggerIntr(true);
FOREACH_SANDBOX_THREAD_END()
sid = StringData::GetStaticString(proxy->getDummyInfo().id());
FOREACH_SANDBOX_THREAD_BEGIN(sid, ti)
ti->m_reqInjectionData.debuggerIntr = true;
ti->m_reqInjectionData.setDebuggerIntr(true);
FOREACH_SANDBOX_THREAD_END()
}
void Debugger::setDebuggerFlag(const StringData* sandboxId, bool flag) {
TRACE(2, "Debugger::setDebuggerFlag\n");
FOREACH_SANDBOX_THREAD_BEGIN(sandboxId, ti)
ti->m_reqInjectionData.debugger = flag;
ti->m_reqInjectionData.setDebugger(flag);
FOREACH_SANDBOX_THREAD_END()
}
+1 -1
Ver Arquivo
@@ -662,7 +662,7 @@ BreakPointInfoPtr DebuggerProxy::getBreakPointAtCmd(CmdInterrupt& cmd) {
void DebuggerProxy::readInjTablesFromThread() {
TRACE(2, "DebuggerProxy::readInjTablesFromThread\n");
ThreadInfo* ti = ThreadInfo::s_threadInfo.getNoCheck();
if (ti->m_reqInjectionData.dummySandbox) {
if (ti->m_reqInjectionData.getDummySandbox()) {
return;
}
if (m_injTables) {
+4 -4
Ver Arquivo
@@ -58,7 +58,7 @@ void DummySandbox::stop() {
TRACE(2, "DummySandbox::stop\n");
m_stopped = true;
ThreadInfo *ti = ThreadInfo::s_threadInfo.getNoCheck();
if (ti->m_reqInjectionData.dummySandbox) {
if (ti->m_reqInjectionData.getDummySandbox()) {
// called from dummy sandbox thread itself, schedule retirement
Debugger::RetireDummySandboxThread(this);
} else {
@@ -82,7 +82,7 @@ struct CLISession : boost::noncopyable {
TRACE(2, "CLISession::~CLISession\n");
Debugger::UnregisterSandbox(g_context->getSandboxId());
ThreadInfo::s_threadInfo.getNoCheck()->
m_reqInjectionData.debugger = false;
m_reqInjectionData.setDebugger(false);
execute_command_line_end(0, false, nullptr);
Eval::DebuggerClient::Shutdown();
}
@@ -94,7 +94,7 @@ void DummySandbox::run() {
TRACE(2, "DummySandbox::run\n");
ThreadInfo *ti = ThreadInfo::s_threadInfo.getNoCheck();
Debugger::RegisterThread();
ti->m_reqInjectionData.dummySandbox = true;
ti->m_reqInjectionData.setDummySandbox(true);
while (!m_stopped) {
try {
CLISession hphpSession;
@@ -136,7 +136,7 @@ void DummySandbox::run() {
g_context->setSandboxId(m_proxy->getDummyInfo().id());
}
ti->m_reqInjectionData.debugger = true;
ti->m_reqInjectionData.setDebugger(true);
{
DebuggerDummyEnv dde;
Debugger::InterruptSessionStarted(nullptr, msg.c_str());
+3 -3
Ver Arquivo
@@ -1528,7 +1528,7 @@ Array f_fb_call_user_func_array_safe(CVarRef function, CArrRef params) {
Variant f_fb_get_code_coverage(bool flush) {
ThreadInfo *ti = ThreadInfo::s_threadInfo.getNoCheck();
if (ti->m_reqInjectionData.coverage) {
if (ti->m_reqInjectionData.getCoverage()) {
Array ret = ti->m_coverage->Report();
if (flush) {
ti->m_coverage->Reset();
@@ -1541,7 +1541,7 @@ Variant f_fb_get_code_coverage(bool flush) {
void f_fb_enable_code_coverage() {
ThreadInfo *ti = ThreadInfo::s_threadInfo.getNoCheck();
ti->m_coverage->Reset();
ti->m_reqInjectionData.coverage = true;
ti->m_reqInjectionData.setCoverage(true);;
if (g_vmContext->isNested()) {
raise_notice("Calling fb_enable_code_coverage from a nested "
"VM instance may cause unpredicable results");
@@ -1551,7 +1551,7 @@ void f_fb_enable_code_coverage() {
Variant f_fb_disable_code_coverage() {
ThreadInfo *ti = ThreadInfo::s_threadInfo.getNoCheck();
ti->m_reqInjectionData.coverage = false;
ti->m_reqInjectionData.setCoverage(false);
Array ret = ti->m_coverage->Report();
ti->m_coverage->Reset();
return ret;
+4 -7
Ver Arquivo
@@ -174,7 +174,7 @@ const StaticString s_include("include");
DECODE_JMP(type, var); \
pc += sizeof(type)
#define DECODE_IVA(var) \
int32_t var UNUSED = decodeVariableSizeImm(&pc); \
int32_t var UNUSED = decodeVariableSizeImm(&pc); \
ONTRACE(2, \
Trace::trace("decode: Immediate int32 %" PRIi64"\n", \
(int64_t)var));
@@ -1854,11 +1854,7 @@ void VMExecutionContext::enterVMWork(ActRec* enterFnAr) {
start = enterFnAr->m_func->getFuncBody();
}
Stats::inc(Stats::VMEnter);
if (RuntimeOption::EvalJit &&
!shouldProfile() &&
!ThreadInfo::s_threadInfo->m_reqInjectionData.coverage &&
!(RuntimeOption::EvalJitDisabledByHphpd && isDebuggerAttached()) &&
LIKELY(!DEBUGGER_FORCE_INTR)) {
if (LIKELY(ThreadInfo::s_threadInfo->m_reqInjectionData.getJit())) {
Transl::SrcKey sk(curFunc(), m_pc);
(void) curUnit()->offsetOf(m_pc); /* assert */
tx64->enterTC(sk, start);
@@ -7228,7 +7224,8 @@ inline void VMExecutionContext::dispatchImpl(int numInstrs) {
const void **optab = optabDirect;
InjectionTableInt64* injTable = g_vmContext->m_injTables ?
g_vmContext->m_injTables->getInt64Table(InstHookTypeBCPC) : nullptr;
bool collectCoverage = ThreadInfo::s_threadInfo->m_reqInjectionData.coverage;
bool collectCoverage = ThreadInfo::s_threadInfo->
m_reqInjectionData.getCoverage();
if (injTable) {
optab = optabInst;
} else if (collectCoverage) {
+3 -2
Ver Arquivo
@@ -55,7 +55,8 @@ void phpRemoveBreakPoint(const Unit* unit, Offset offset);
// Is this thread being debugged?
static inline bool isDebuggerAttached() {
return ThreadInfo::s_threadInfo.getNoCheck()->m_reqInjectionData.debugger;
return ThreadInfo::s_threadInfo.getNoCheck()->
m_reqInjectionData.getDebugger();
}
#define DEBUGGER_ATTACHED_ONLY(code) do { \
@@ -71,7 +72,7 @@ bool isDebuggerAttachedProcess();
// out of JIT code. Second, that phpDebuggerOpcodeHook will continue to allow
// debugger interrupts for every opcode executed (modulo filters.)
#define DEBUGGER_FORCE_INTR \
(ThreadInfo::s_threadInfo.getNoCheck()->m_reqInjectionData.debuggerIntr)
(ThreadInfo::s_threadInfo.getNoCheck()->m_reqInjectionData.getDebuggerIntr())
// Map which holds a set of PCs and supports reasonably fast addition and
// lookup. Used by the debugger to decide if a given PC falls within an
+1 -1
Ver Arquivo
@@ -12009,7 +12009,7 @@ void TranslatorX64::addDbgGuardImpl(SrcKey sk, SrcRec& srcRec) {
// Emit the checks for debugger attach
emitTLSLoad<ThreadInfo>(a, ThreadInfo::s_threadInfo, rScratch);
static COff dbgOff = offsetof(ThreadInfo, m_reqInjectionData) +
offsetof(RequestInjectionData, debugger);
RequestInjectionData::debuggerReadOnlyOffset();
a. load_reg64_disp_reg32(rScratch, dbgOff, rScratch);
a. testb((int8_t)0xff, rbyte(rScratch));
// Branch to a special REQ_INTERPRET if attached
+13 -8
Ver Arquivo
@@ -13,6 +13,12 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "runtime/vm/type_profile.h"
#include "runtime/base/runtime_option.h"
#include "runtime/base/stats.h"
#include "runtime/vm/translator/translator.h"
#include "util/trace.h"
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -20,13 +26,6 @@
#include <unistd.h>
#include <fcntl.h>
#include "util/trace.h"
#include "runtime/base/types.h"
#include "runtime/base/runtime_option.h"
#include "runtime/base/stats.h"
#include "runtime/vm/translator/translator.h"
#include "runtime/vm/type_profile.h"
namespace HPHP {
namespace VM {
@@ -173,7 +172,13 @@ static inline bool profileThisRequest() {
void
profileRequestStart() {
profileOn = profileThisRequest();
bool p = profileThisRequest();
if (p != profileOn) {
profileOn = p;
if (!ThreadInfo::s_threadInfo.isNull()) {
ThreadInfo::s_threadInfo->m_reqInjectionData.updateJit();
}
}
}
void profileRequestEnd() {
+6
Ver Arquivo
@@ -16,7 +16,13 @@
#ifndef TYPE_PROFILE_H_
#define TYPE_PROFILE_H_
#include "runtime/base/types.h"
#include "runtime/vm/hhbc.h"
namespace HPHP {
class StringData;
namespace VM {
struct TypeProfileKey {