Move SrcKey out of translator.h and Transl:: @override-unit-failures
I was going to #include translator.h in a header I had for talking to the region selector thing and decided to just get this over with instead. (It shouldn't need to #include that.) Found a few other unused things to remove while at it.
Esse commit está contido em:
@@ -18,6 +18,7 @@
|
||||
#include "hphp/compiler/builtin_symbols.h"
|
||||
#include "hphp/runtime/vm/event_hook.h"
|
||||
#include "hphp/runtime/vm/jit/translator-x64.h"
|
||||
#include "hphp/runtime/vm/srckey.h"
|
||||
#include "hphp/runtime/vm/member_operations.h"
|
||||
#include "hphp/runtime/base/code_coverage.h"
|
||||
#include "hphp/runtime/eval/runtime/file_repository.h"
|
||||
@@ -1831,7 +1832,7 @@ void VMExecutionContext::enterVMWork(ActRec* enterFnAr) {
|
||||
assert(start);
|
||||
tx64->enterTCAfterProlog(start);
|
||||
} else {
|
||||
Transl::SrcKey sk(curFunc(), m_pc);
|
||||
SrcKey sk(curFunc(), m_pc);
|
||||
tx64->enterTCAtSrcKey(sk);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -82,16 +82,17 @@ void Func::parametersCompat(const PreClass* preClass, const Func* imeth) const {
|
||||
}
|
||||
}
|
||||
|
||||
static Func::FuncId s_nextFuncId = 0;
|
||||
static FuncId s_nextFuncId = 0;
|
||||
|
||||
void Func::setFuncId(FuncId id) {
|
||||
assert(m_funcId == InvalidId);
|
||||
assert(id != InvalidId);
|
||||
assert(m_funcId == InvalidFuncId);
|
||||
assert(id != InvalidFuncId);
|
||||
m_funcId = id;
|
||||
}
|
||||
|
||||
void Func::setNewFuncId() {
|
||||
assert(m_funcId == InvalidId);
|
||||
m_funcId = __sync_fetch_and_add(&s_nextFuncId, 1);
|
||||
assert(m_funcId == InvalidFuncId);
|
||||
m_funcId = static_cast<FuncId>(__sync_fetch_and_add(&s_nextFuncId, 1));
|
||||
}
|
||||
|
||||
void Func::setFullName() {
|
||||
@@ -188,7 +189,7 @@ Func::Func(Unit& unit, Id id, int line1, int line2,
|
||||
, m_maxStackCells(0)
|
||||
, m_numParams(0)
|
||||
, m_attrs(attrs)
|
||||
, m_funcId(InvalidId)
|
||||
, m_funcId(InvalidFuncId)
|
||||
, m_hasPrivateAncestor(false)
|
||||
{
|
||||
m_shared = new SharedData(nullptr, id, base, past, line1, line2,
|
||||
@@ -211,7 +212,7 @@ Func::Func(Unit& unit, PreClass* preClass, int line1, int line2, Offset base,
|
||||
, m_maxStackCells(0)
|
||||
, m_numParams(0)
|
||||
, m_attrs(attrs)
|
||||
, m_funcId(InvalidId)
|
||||
, m_funcId(InvalidFuncId)
|
||||
, m_hasPrivateAncestor(false)
|
||||
{
|
||||
Id id = -1;
|
||||
@@ -247,7 +248,7 @@ Func* Func::clone() const {
|
||||
isClosureBody() || isGeneratorFromClosure()
|
||||
)) Func(*this);
|
||||
f->initPrologues(m_numParams, isGenerator());
|
||||
f->m_funcId = InvalidId;
|
||||
f->m_funcId = InvalidFuncId;
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,12 @@ static const int kNumFixedPrologues = 6;
|
||||
|
||||
typedef TypedValue*(*BuiltinFunction)(ActRec* ar);
|
||||
|
||||
/*
|
||||
* Unique identifier for a Func*.
|
||||
*/
|
||||
typedef uint32_t FuncId;
|
||||
constexpr FuncId InvalidFuncId = FuncId(-1LL);
|
||||
|
||||
/*
|
||||
* Metadata about a php function or object method.
|
||||
*/
|
||||
@@ -130,9 +136,6 @@ struct Func {
|
||||
typedef FixedVector<EHEnt> EHEntVec;
|
||||
typedef FixedVector<FPIEnt> FPIEntVec;
|
||||
|
||||
typedef uint32_t FuncId;
|
||||
static const FuncId InvalidId = -1LL;
|
||||
|
||||
Func(Unit& unit, Id id, int line1, int line2, Offset base,
|
||||
Offset past, const StringData* name, Attr attrs, bool top,
|
||||
const StringData* docComment, int numParams, bool isGenerator);
|
||||
@@ -153,7 +156,7 @@ struct Func {
|
||||
}
|
||||
|
||||
FuncId getFuncId() const {
|
||||
assert(m_funcId != InvalidId);
|
||||
assert(m_funcId != InvalidFuncId);
|
||||
return m_funcId;
|
||||
}
|
||||
void setFuncId(FuncId id);
|
||||
|
||||
@@ -40,7 +40,7 @@ struct CallRecord {
|
||||
};
|
||||
};
|
||||
|
||||
typedef hphp_hash_map<SrcKey, CallRecord, SrcKey> CallDB;
|
||||
typedef hphp_hash_map<SrcKey,CallRecord,SrcKey::Hasher> CallDB;
|
||||
static CallDB s_callDB;
|
||||
/* record the max number of args to enable invalidation */
|
||||
static int s_maxNumArgs;
|
||||
@@ -110,8 +110,7 @@ static void recordActRecPush(NormalizedInstruction& i,
|
||||
assert(fpi);
|
||||
assert(name->isStatic());
|
||||
assert(sk.offset() == fpi->m_fpushOff);
|
||||
SrcKey fcall = sk;
|
||||
fcall.m_offset = fpi->m_fcallOff;
|
||||
auto const fcall = SrcKey { curFunc(), fpi->m_fcallOff };
|
||||
assert(isFCallStar(*unit->at(fcall.offset())));
|
||||
if (clsName) {
|
||||
const Class* cls = Unit::lookupUniqueClass(clsName);
|
||||
|
||||
@@ -2673,7 +2673,7 @@ static void emitExitNoIRStats(Asm& a,
|
||||
HPHP::Trace::moduleEnabled(HPHP::Trace::stats, 3)) {
|
||||
Stats::emitInc(a,
|
||||
Stats::opcodeToIRPreStatCounter(
|
||||
Op(*func->unit()->at(dest.m_offset))),
|
||||
Op(*func->unit()->at(dest.offset()))),
|
||||
-1,
|
||||
Transl::CC_None,
|
||||
true);
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
#include "hphp/runtime/vm/member_operations.h"
|
||||
#include "hphp/runtime/vm/jit/runtime-type.h"
|
||||
#include "hphp/runtime/vm/jit/tracebuilder.h"
|
||||
#include "hphp/runtime/vm/srckey.h"
|
||||
|
||||
using HPHP::Transl::SrcKey;
|
||||
using HPHP::Transl::NormalizedInstruction;
|
||||
|
||||
namespace HPHP {
|
||||
|
||||
@@ -339,7 +339,7 @@ TranslatorX64::emitRB(X64Assembler& a,
|
||||
int arg = 0;
|
||||
emitImmReg(a, t, argNumToRegName[arg++]);
|
||||
emitImmReg(a, sk.getFuncId(), argNumToRegName[arg++]);
|
||||
emitImmReg(a, sk.m_offset, argNumToRegName[arg++]);
|
||||
emitImmReg(a, sk.offset(), argNumToRegName[arg++]);
|
||||
a. call((TCA)ringbufferEntry);
|
||||
}
|
||||
|
||||
@@ -1654,7 +1654,7 @@ TranslatorX64::emitPrologue(Func* func, int nPassed) {
|
||||
emitLea(a, rVmFp, -cellsToBytes(frameCells), rVmSp);
|
||||
}
|
||||
|
||||
Fixup fixup(funcBody.m_offset - func->base(), frameCells);
|
||||
Fixup fixup(funcBody.offset() - func->base(), frameCells);
|
||||
|
||||
// Emit warnings for any missing arguments
|
||||
if (!func->info()) {
|
||||
@@ -2476,7 +2476,7 @@ bool TranslatorX64::handleServiceRequest(TReqInfo& info,
|
||||
* axiom.
|
||||
*/
|
||||
assert(numInstrs >= 0);
|
||||
ONTRACE(5, SrcKey(curFunc(), off).trace("interp: enter\n"));
|
||||
SKTRACE(5, SrcKey(curFunc(), off), "interp: enter\n");
|
||||
if (numInstrs) {
|
||||
s_perfCounters[tpc_interp_instr] += numInstrs;
|
||||
g_vmContext->dispatchN(numInstrs);
|
||||
@@ -3451,7 +3451,7 @@ TranslatorX64::translateTracelet(const TranslArgs& args) {
|
||||
// otherwise there's some chance of hitting in the reader threads whose
|
||||
// metadata is not yet visible.
|
||||
TRACE(1, "newTranslation: %p sk: (func %d, bcOff %d)\n",
|
||||
start, sk.getFuncId(), sk.m_offset);
|
||||
start, sk.getFuncId(), sk.offset());
|
||||
srcRec.newTranslation(start);
|
||||
TRACE(1, "tx64: %zd-byte tracelet\n", a.code.frontier - start);
|
||||
if (Trace::moduleEnabledRelease(Trace::tcspace, 1)) {
|
||||
|
||||
@@ -205,57 +205,25 @@ void Tracelet::print(std::ostream& out) const {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SrcKey::trace(const char *fmt, ...) const {
|
||||
void sktrace(SrcKey sk, const char *fmt, ...) {
|
||||
if (!Trace::enabled) {
|
||||
return;
|
||||
}
|
||||
// We don't want to print string literals, so don't pass the unit
|
||||
string s = instrToString(curUnit()->at(m_offset));
|
||||
string s = instrToString(curUnit()->at(sk.offset()));
|
||||
const char *filepath = "*anonFile*";
|
||||
if (curUnit()->filepath()->data() &&
|
||||
strlen(curUnit()->filepath()->data()) > 0)
|
||||
filepath = curUnit()->filepath()->data();
|
||||
Trace::trace("%s:%llx %6d: %20s ",
|
||||
filepath, (unsigned long long)getFuncId(),
|
||||
m_offset, s.c_str());
|
||||
filepath, (unsigned long long)sk.getFuncId(),
|
||||
sk.offset(), s.c_str());
|
||||
va_list a;
|
||||
va_start(a, fmt);
|
||||
Trace::vtrace(fmt, a);
|
||||
va_end(a);
|
||||
}
|
||||
|
||||
void
|
||||
SrcKey::print(int ninstrs) const {
|
||||
const Unit* u = curUnit();
|
||||
Opcode* op = (Opcode*)u->at(m_offset);
|
||||
std::cerr << u->filepath()->data() << ':' << u->getLineNumber(m_offset)
|
||||
<< std::endl;
|
||||
for (int i = 0;
|
||||
i < ninstrs && (uintptr_t)op < ((uintptr_t)u->entry() + u->bclen());
|
||||
op += instrLen(op), ++i) {
|
||||
std::cerr << " " << u->offsetOf(op) << ": " << instrToString(op, u)
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
SrcKey::pretty() const {
|
||||
std::ostringstream result;
|
||||
const char* filepath = tl_regState == REGSTATE_CLEAN ?
|
||||
curUnit()->filepath()->data() : "unknown";
|
||||
result << filepath << ':' << getFuncId() << ':' << m_offset;
|
||||
return result.str();
|
||||
}
|
||||
|
||||
// advance --
|
||||
//
|
||||
// Move over the current instruction pointer.
|
||||
void
|
||||
Translator::advance(const Opcode** instrs) {
|
||||
(*instrs) += instrLen(*instrs);
|
||||
}
|
||||
|
||||
/*
|
||||
* locPhysicalOffset --
|
||||
*
|
||||
@@ -2981,7 +2949,7 @@ static bool checkTaintFuncs(StringData* name) {
|
||||
static bool shouldAnalyzeCallee(const NormalizedInstruction* fcall) {
|
||||
auto const numArgs = fcall->imm[0].u_IVA;
|
||||
auto const target = fcall->funcd;
|
||||
auto const fpi = curFunc()->findFPI(fcall->source.m_offset);
|
||||
auto const fpi = curFunc()->findFPI(fcall->source.offset());
|
||||
auto const pushOp = curUnit()->getOpcode(fpi->m_fpushOff);
|
||||
|
||||
if (!RuntimeOption::RepoAuthoritative) return false;
|
||||
@@ -3387,7 +3355,7 @@ std::unique_ptr<Tracelet> Translator::analyze(SrcKey sk,
|
||||
|
||||
if (isFCallStar(ni->op())) {
|
||||
if (!doVarEnvTaint) {
|
||||
const FPIEnt *fpi = curFunc()->findFPI(ni->source.m_offset);
|
||||
const FPIEnt *fpi = curFunc()->findFPI(ni->source.offset());
|
||||
assert(fpi);
|
||||
Offset fpushOff = fpi->m_fpushOff;
|
||||
PC fpushPc = curUnit()->at(fpushOff);
|
||||
@@ -3480,7 +3448,7 @@ std::unique_ptr<Tracelet> Translator::analyze(SrcKey sk,
|
||||
SKTRACE(1, sk, "greedily continuing through %dth jmp + %d\n",
|
||||
tas.m_numJmps, ni->imm[0].u_IA);
|
||||
tas.recordJmp();
|
||||
sk = SrcKey(curFunc(), sk.m_offset + ni->imm[0].u_IA);
|
||||
sk = SrcKey(curFunc(), sk.offset() + ni->imm[0].u_IA);
|
||||
goto head; // don't advance sk
|
||||
} else if (opcodeBreaksBB(ni->op()) ||
|
||||
(dontGuardAnyInputs(ni->op()) && opcodeChangesPC(ni->op()))) {
|
||||
@@ -3571,7 +3539,7 @@ Translator::isSrcKeyInBL(const Unit* unit, const SrcKey& sk) {
|
||||
if (m_dbgBLSrcKey.find(sk) != m_dbgBLSrcKey.end()) {
|
||||
return true;
|
||||
}
|
||||
for (PC pc = unit->at(sk.m_offset); !opcodeBreaksBB(*pc);
|
||||
for (PC pc = unit->at(sk.offset()); !opcodeBreaksBB(*pc);
|
||||
pc += instrLen(pc)) {
|
||||
if (m_dbgBLPC.checkPC(pc)) {
|
||||
m_dbgBLSrcKey.insert(sk);
|
||||
@@ -3616,6 +3584,34 @@ uint64_t* Translator::getTransCounterAddr() {
|
||||
[id % transCountersPerChunk]);
|
||||
}
|
||||
|
||||
uint32_t Translator::addTranslation(const TransRec& transRec) {
|
||||
if (Trace::moduleEnabledRelease(Trace::trans, 1)) {
|
||||
// Log the translation's size, creation time, SrcKey, and size
|
||||
Trace::traceRelease("New translation: %lld %s %u %u %d\n",
|
||||
Timer::GetCurrentTimeMicros() - m_createdTime,
|
||||
folly::format("{}:{}:{}",
|
||||
curUnit()->filepath()->data(),
|
||||
transRec.src.getFuncId(),
|
||||
transRec.src.offset()).str().c_str(),
|
||||
transRec.aLen,
|
||||
transRec.astubsLen,
|
||||
transRec.kind);
|
||||
}
|
||||
|
||||
if (!isTransDBEnabled()) return -1u;
|
||||
uint32_t id = getCurrentTransID();
|
||||
m_translations.push_back(transRec);
|
||||
m_translations[id].setID(id);
|
||||
|
||||
if (transRec.aLen > 0) {
|
||||
m_transDB[transRec.aStart] = id;
|
||||
}
|
||||
if (transRec.astubsLen > 0) {
|
||||
m_transDB[transRec.astubsStart] = id;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
uint64_t Translator::getTransCounter(TransID transId) const {
|
||||
if (!isTransDBEnabled()) return -1ul;
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "hphp/runtime/vm/jit/writelease.h"
|
||||
#include "hphp/runtime/vm/jit/trans-data.h"
|
||||
#include "hphp/runtime/vm/debugger_hook.h"
|
||||
#include "hphp/runtime/vm/srckey.h"
|
||||
#include "hphp/runtime/base/md5.h"
|
||||
|
||||
/* Translator front-end. */
|
||||
@@ -63,98 +64,9 @@ enum VMRegState {
|
||||
};
|
||||
extern __thread VMRegState tl_regState;
|
||||
|
||||
/*
|
||||
* A SrcKey is a logical source instruction, currently a unit/instruction pair.
|
||||
* The units are identified by contents rather than Unit; Unit's are
|
||||
* ephemeral, and we want to reuse SrcKey's when we encounter Unit's with
|
||||
* the same contents.
|
||||
*/
|
||||
struct SrcKey {
|
||||
private:
|
||||
Func::FuncId m_funcId;
|
||||
|
||||
public:
|
||||
Offset m_offset;
|
||||
|
||||
SrcKey() : m_funcId(Func::InvalidId), m_offset(0) { }
|
||||
|
||||
SrcKey(const Func* f, Offset off) :
|
||||
m_funcId(f->getFuncId()), m_offset(off) { }
|
||||
|
||||
SrcKey(const Func* f, const Opcode* i) :
|
||||
m_funcId(f->getFuncId()), m_offset(f->unit()->offsetOf(i)) { }
|
||||
|
||||
int cmp(const SrcKey &r) const {
|
||||
// Can't use memcmp because of pad bytes. Frowny.
|
||||
#define CMP(field) \
|
||||
if (field < r.field) return -1; \
|
||||
if (field > r.field) return 1
|
||||
CMP(getFuncId());
|
||||
CMP(m_offset);
|
||||
#undef CMP
|
||||
return 0;
|
||||
}
|
||||
bool operator==(const SrcKey& r) const {
|
||||
return cmp(r) == 0;
|
||||
}
|
||||
bool operator!=(const SrcKey& r) const {
|
||||
return cmp(r) != 0;
|
||||
}
|
||||
bool operator<(const SrcKey& r) const {
|
||||
return cmp(r) < 0;
|
||||
}
|
||||
bool operator>(const SrcKey& r) const {
|
||||
return cmp(r) > 0;
|
||||
}
|
||||
// Hash function for both hash_map and tbb conventions.
|
||||
static size_t hash(const SrcKey &sk) {
|
||||
return HPHP::hash_int64_pair(sk.getFuncId(), uint64_t(sk.m_offset));
|
||||
}
|
||||
size_t operator()(const SrcKey& sk) const {
|
||||
return hash(sk);
|
||||
}
|
||||
static bool equal(const SrcKey& sk1, const SrcKey& sk2) {
|
||||
return sk1 == sk2;
|
||||
}
|
||||
|
||||
// Packed representation of SrcKeys for use in contexts where we
|
||||
// want atomicity. (SrcDB.)
|
||||
typedef uint64_t AtomicInt;
|
||||
|
||||
AtomicInt toAtomicInt() const {
|
||||
return uint64_t(getFuncId()) << 32 | uint64_t(m_offset);
|
||||
}
|
||||
|
||||
static SrcKey fromAtomicInt(AtomicInt in) {
|
||||
SrcKey k;
|
||||
k.setFuncId(in >> 32);
|
||||
k.m_offset = in & 0xffffffff;
|
||||
return k;
|
||||
}
|
||||
|
||||
void setFuncId(Func::FuncId id) {
|
||||
assert(id != Func::InvalidId);
|
||||
m_funcId = id;
|
||||
}
|
||||
Func::FuncId getFuncId() const {
|
||||
assert(m_funcId != Func::InvalidId);
|
||||
return m_funcId;
|
||||
}
|
||||
|
||||
void trace(const char *fmt, ...) const;
|
||||
void print(int ninstr) const;
|
||||
std::string pretty() const;
|
||||
int offset() const {
|
||||
return m_offset;
|
||||
}
|
||||
void advance(const Unit* u) {
|
||||
m_offset += instrLen(u->at(offset()));
|
||||
}
|
||||
};
|
||||
|
||||
typedef hphp_hash_set<SrcKey, SrcKey> SrcKeySet;
|
||||
void sktrace(SrcKey sk, const char *fmt, ...);
|
||||
#define SKTRACE(level, sk, ...) \
|
||||
ONTRACE(level, (sk).trace(__VA_ARGS__))
|
||||
ONTRACE(level, sktrace(sk, __VA_ARGS__))
|
||||
|
||||
struct NormalizedInstruction;
|
||||
|
||||
@@ -893,34 +805,10 @@ public:
|
||||
}
|
||||
|
||||
uint64_t* getTransCounterAddr();
|
||||
|
||||
uint64_t getTransCounter(TransID transId) const;
|
||||
|
||||
void setTransCounter(TransID transId, uint64_t value);
|
||||
|
||||
uint32_t addTranslation(const TransRec& transRec) {
|
||||
if (Trace::moduleEnabledRelease(Trace::trans, 1)) {
|
||||
// Log the translation's size, creation time, SrcKey, and size
|
||||
Trace::traceRelease("New translation: %lld %s %u %u %d\n",
|
||||
Timer::GetCurrentTimeMicros() - m_createdTime,
|
||||
transRec.src.pretty().c_str(), transRec.aLen,
|
||||
transRec.astubsLen, transRec.kind);
|
||||
}
|
||||
|
||||
if (!isTransDBEnabled()) return -1u;
|
||||
uint32_t id = getCurrentTransID();
|
||||
m_translations.push_back(transRec);
|
||||
m_translations[id].setID(id);
|
||||
|
||||
if (transRec.aLen > 0) {
|
||||
m_transDB[transRec.aStart] = id;
|
||||
}
|
||||
if (transRec.astubsLen > 0) {
|
||||
m_transDB[transRec.astubsStart] = id;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
uint32_t addTranslation(const TransRec& transRec);
|
||||
|
||||
/*
|
||||
* Create a Tracelet for the given SrcKey, which must actually be
|
||||
@@ -933,7 +821,6 @@ public:
|
||||
|
||||
void postAnalyze(NormalizedInstruction* ni, SrcKey& sk,
|
||||
Tracelet& t, TraceletContext& tas);
|
||||
void advance(Opcode const **instrs);
|
||||
static int locPhysicalOffset(Location l, const Func* f = nullptr);
|
||||
static Location tvToLocation(const TypedValue* tv, const TypedValue* frame);
|
||||
static bool typeIsString(DataType type) {
|
||||
@@ -963,7 +850,7 @@ public:
|
||||
|
||||
protected:
|
||||
PCFilter m_dbgBLPC;
|
||||
SrcKeySet m_dbgBLSrcKey;
|
||||
hphp_hash_set<SrcKey,SrcKey::Hasher> m_dbgBLSrcKey;
|
||||
Mutex m_dbgBlacklistLock;
|
||||
bool isSrcKeyInBL(const Unit* unit, const SrcKey& sk);
|
||||
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
#ifndef incl_HPHP_SRCKEY_H_
|
||||
#define incl_HPHP_SRCKEY_H_
|
||||
|
||||
#include <tuple>
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
#include "hphp/runtime/vm/func.h"
|
||||
#include "hphp/runtime/vm/core_types.h"
|
||||
|
||||
namespace HPHP {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* A SrcKey is a logical source instruction---it's enough to identify
|
||||
* these using a (Func id, hhbc instruction) pair.
|
||||
*/
|
||||
struct SrcKey : private boost::totally_ordered<SrcKey> {
|
||||
typedef uint64_t AtomicInt;
|
||||
struct Hasher;
|
||||
|
||||
SrcKey()
|
||||
: m_funcId(InvalidFuncId)
|
||||
, m_offset(0)
|
||||
{}
|
||||
|
||||
SrcKey(const Func* f, Offset off)
|
||||
: m_funcId(f->getFuncId())
|
||||
, m_offset(off)
|
||||
{}
|
||||
|
||||
SrcKey(const Func* f, const Opcode* i)
|
||||
: m_funcId(f->getFuncId())
|
||||
, m_offset(f->unit()->offsetOf(i))
|
||||
{}
|
||||
|
||||
SrcKey(FuncId funcId, Offset off)
|
||||
: m_funcId{funcId}
|
||||
, m_offset{off}
|
||||
{}
|
||||
|
||||
// Packed representation of SrcKeys for use in contexts where we
|
||||
// want atomicity. (SrcDB.)
|
||||
AtomicInt toAtomicInt() const {
|
||||
return uint64_t(getFuncId()) << 32 | uint64_t(offset());
|
||||
}
|
||||
static SrcKey fromAtomicInt(AtomicInt in) {
|
||||
return SrcKey { uint32_t(in >> 32), uint32_t(in & 0xffffffff) };
|
||||
}
|
||||
|
||||
void setFuncId(FuncId id) {
|
||||
assert(id != InvalidFuncId);
|
||||
m_funcId = id;
|
||||
}
|
||||
|
||||
FuncId getFuncId() const {
|
||||
assert(m_funcId != InvalidFuncId);
|
||||
return m_funcId;
|
||||
}
|
||||
|
||||
int offset() const {
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Advance the SrcKey to the next instruction.
|
||||
*
|
||||
* If the SrcKey points to the last instruction in a function, this
|
||||
* will advance past the end of the function, and potentially
|
||||
* contain an invalid bytecode offset.
|
||||
*/
|
||||
void advance(const Unit* u) {
|
||||
m_offset += instrLen(u->at(offset()));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a SrcKey representing the next instruction, without
|
||||
* mutating this SrcKey.
|
||||
*/
|
||||
SrcKey advanced(const Unit* u) const {
|
||||
auto tmp = *this;
|
||||
tmp.advance(u);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const SrcKey& r) const {
|
||||
return offset() == r.offset() &&
|
||||
getFuncId() == r.getFuncId();
|
||||
}
|
||||
|
||||
bool operator<(const SrcKey& r) const {
|
||||
return std::make_tuple(offset(), getFuncId()) <
|
||||
std::make_tuple(r.offset(), r.getFuncId());
|
||||
}
|
||||
|
||||
private:
|
||||
FuncId m_funcId;
|
||||
Offset m_offset;
|
||||
};
|
||||
|
||||
struct SrcKey::Hasher {
|
||||
size_t operator()(SrcKey sk) const {
|
||||
return hash_int64_pair(sk.getFuncId(), uint64_t(sk.offset()));
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1498,8 +1498,7 @@ bool Unit::getOffsetRange(Offset pc, OffsetRange& range) const {
|
||||
|
||||
const Func* Unit::getFunc(Offset pc) const {
|
||||
FuncEntry key = FuncEntry(pc, nullptr);
|
||||
FuncTable::const_iterator it =
|
||||
upper_bound(m_funcTable.begin(), m_funcTable.end(), key);
|
||||
auto it = std::upper_bound(m_funcTable.begin(), m_funcTable.end(), key);
|
||||
if (it != m_funcTable.end()) {
|
||||
assert(pc < it->pastOffset());
|
||||
return it->val();
|
||||
|
||||
@@ -609,7 +609,14 @@ public:
|
||||
return (Opcode)m_bc[instrOffset];
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the Func* for the code at offset off.
|
||||
*
|
||||
* Returns nullptr if the offset is not in a func body (but this
|
||||
* should be impossible).
|
||||
*/
|
||||
const Func* getFunc(Offset pc) const;
|
||||
|
||||
void setCacheId(unsigned id) {
|
||||
m_cacheOffset = id >> 3;
|
||||
m_cacheMask = 1 << (id & 7);
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário