зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1125837 - smush SimulatorRuntime into Simulator. r=jandem
This commit is contained in:
Родитель
1e523dd28b
Коммит
2e7f093f9d
|
@ -352,98 +352,20 @@ class CachePage
|
|||
char validity_map_[kValidityMapSize]; // One byte per line.
|
||||
};
|
||||
|
||||
class Redirection;
|
||||
|
||||
class SimulatorRuntime
|
||||
{
|
||||
friend class AutoLockSimulatorRuntime;
|
||||
|
||||
Redirection *redirection_;
|
||||
|
||||
// ICache checking.
|
||||
struct ICacheHasher {
|
||||
typedef void *Key;
|
||||
typedef void *Lookup;
|
||||
static HashNumber hash(const Lookup &l);
|
||||
static bool match(const Key &k, const Lookup &l);
|
||||
};
|
||||
|
||||
public:
|
||||
typedef HashMap<void *, CachePage *, ICacheHasher, SystemAllocPolicy> ICacheMap;
|
||||
|
||||
protected:
|
||||
ICacheMap icache_;
|
||||
|
||||
// Synchronize access between main thread and compilation threads.
|
||||
PRLock *lock_;
|
||||
mozilla::DebugOnly<PRThread *> lockOwner_;
|
||||
|
||||
public:
|
||||
SimulatorRuntime()
|
||||
: redirection_(nullptr),
|
||||
lock_(nullptr),
|
||||
lockOwner_(nullptr)
|
||||
{}
|
||||
~SimulatorRuntime();
|
||||
bool init() {
|
||||
lock_ = PR_NewLock();
|
||||
if (!lock_)
|
||||
return false;
|
||||
if (!icache_.init())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
ICacheMap &icache() {
|
||||
MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
|
||||
return icache_;
|
||||
}
|
||||
Redirection *redirection() const {
|
||||
MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
|
||||
return redirection_;
|
||||
}
|
||||
void setRedirection(js::jit::Redirection *redirection) {
|
||||
MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
|
||||
redirection_ = redirection;
|
||||
}
|
||||
};
|
||||
|
||||
class AutoLockSimulatorRuntime
|
||||
{
|
||||
protected:
|
||||
SimulatorRuntime *srt_;
|
||||
|
||||
public:
|
||||
AutoLockSimulatorRuntime(SimulatorRuntime *srt)
|
||||
: srt_(srt)
|
||||
{
|
||||
PR_Lock(srt_->lock_);
|
||||
MOZ_ASSERT(!srt_->lockOwner_);
|
||||
#ifdef DEBUG
|
||||
srt_->lockOwner_ = PR_GetCurrentThread();
|
||||
#endif
|
||||
}
|
||||
|
||||
~AutoLockSimulatorRuntime() {
|
||||
MOZ_ASSERT(srt_->lockOwner_ == PR_GetCurrentThread());
|
||||
srt_->lockOwner_ = nullptr;
|
||||
PR_Unlock(srt_->lock_);
|
||||
}
|
||||
};
|
||||
|
||||
bool Simulator::ICacheCheckingEnabled = false;
|
||||
|
||||
int64_t Simulator::StopSimAt = -1L;
|
||||
|
||||
SimulatorRuntime *
|
||||
CreateSimulatorRuntime()
|
||||
Simulator *
|
||||
Simulator::Create()
|
||||
{
|
||||
SimulatorRuntime *srt = js_new<SimulatorRuntime>();
|
||||
if (!srt)
|
||||
Simulator *sim = js_new<Simulator>();
|
||||
if (!sim)
|
||||
return nullptr;
|
||||
|
||||
if (!srt->init()) {
|
||||
js_delete(srt);
|
||||
return nullptr;
|
||||
if (!sim->icache_.init()) {
|
||||
js_delete(sim);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getenv("ARM_SIM_ICACHE_CHECKS"))
|
||||
|
@ -456,13 +378,13 @@ CreateSimulatorRuntime()
|
|||
Simulator::StopSimAt = stopAt;
|
||||
}
|
||||
|
||||
return srt;
|
||||
return sim;
|
||||
}
|
||||
|
||||
void
|
||||
DestroySimulatorRuntime(SimulatorRuntime *srt)
|
||||
Simulator::Destroy(Simulator *sim)
|
||||
{
|
||||
js_delete(srt);
|
||||
js_delete(sim);
|
||||
}
|
||||
|
||||
// The ArmDebugger class is used by the simulator while debugging simulated ARM
|
||||
|
@ -1000,11 +922,11 @@ AllOnOnePage(uintptr_t start, int size)
|
|||
}
|
||||
|
||||
static CachePage *
|
||||
GetCachePage(SimulatorRuntime::ICacheMap &i_cache, void *page)
|
||||
GetCachePage(Simulator::ICacheMap &i_cache, void *page)
|
||||
{
|
||||
MOZ_ASSERT(Simulator::ICacheCheckingEnabled);
|
||||
|
||||
SimulatorRuntime::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
|
||||
Simulator::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
|
||||
if (p)
|
||||
return p->value();
|
||||
|
||||
|
@ -1016,7 +938,7 @@ GetCachePage(SimulatorRuntime::ICacheMap &i_cache, void *page)
|
|||
|
||||
// Flush from start up to and not including start + size.
|
||||
static void
|
||||
FlushOnePage(SimulatorRuntime::ICacheMap &i_cache, intptr_t start, int size)
|
||||
FlushOnePage(Simulator::ICacheMap &i_cache, intptr_t start, int size)
|
||||
{
|
||||
MOZ_ASSERT(size <= CachePage::kPageSize);
|
||||
MOZ_ASSERT(AllOnOnePage(start, size - 1));
|
||||
|
@ -1031,7 +953,7 @@ FlushOnePage(SimulatorRuntime::ICacheMap &i_cache, intptr_t start, int size)
|
|||
}
|
||||
|
||||
static void
|
||||
FlushICache(SimulatorRuntime::ICacheMap &i_cache, void *start_addr, size_t size)
|
||||
FlushICache(Simulator::ICacheMap &i_cache, void *start_addr, size_t size)
|
||||
{
|
||||
intptr_t start = reinterpret_cast<intptr_t>(start_addr);
|
||||
int intra_line = (start & CachePage::kLineMask);
|
||||
|
@ -1052,7 +974,7 @@ FlushICache(SimulatorRuntime::ICacheMap &i_cache, void *start_addr, size_t size)
|
|||
}
|
||||
|
||||
static void
|
||||
CheckICache(SimulatorRuntime::ICacheMap &i_cache, SimInstruction *instr)
|
||||
CheckICache(Simulator::ICacheMap &i_cache, SimInstruction *instr)
|
||||
{
|
||||
intptr_t address = reinterpret_cast<intptr_t>(instr);
|
||||
void *page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
|
||||
|
@ -1075,13 +997,13 @@ CheckICache(SimulatorRuntime::ICacheMap &i_cache, SimInstruction *instr)
|
|||
}
|
||||
|
||||
HashNumber
|
||||
SimulatorRuntime::ICacheHasher::hash(const Lookup &l)
|
||||
Simulator::ICacheHasher::hash(const Lookup &l)
|
||||
{
|
||||
return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(l)) >> 2;
|
||||
}
|
||||
|
||||
bool
|
||||
SimulatorRuntime::ICacheHasher::match(const Key &k, const Lookup &l)
|
||||
Simulator::ICacheHasher::match(const Key &k, const Lookup &l)
|
||||
{
|
||||
MOZ_ASSERT((reinterpret_cast<intptr_t>(k) & CachePage::kPageMask) == 0);
|
||||
MOZ_ASSERT((reinterpret_cast<intptr_t>(l) & CachePage::kPageMask) == 0);
|
||||
|
@ -1101,30 +1023,24 @@ Simulator::FlushICache(void *start_addr, size_t size)
|
|||
JitSpewCont(JitSpew_CacheFlush, "[%p %zx]", start_addr, size);
|
||||
if (!Simulator::ICacheCheckingEnabled)
|
||||
return;
|
||||
SimulatorRuntime *srt = TlsPerThreadData.get()->simulatorRuntime();
|
||||
AutoLockSimulatorRuntime alsr(srt);
|
||||
js::jit::FlushICache(srt->icache(), start_addr, size);
|
||||
js::jit::FlushICache(Simulator::Current()->icache(), start_addr, size);
|
||||
}
|
||||
|
||||
Simulator::~Simulator()
|
||||
{
|
||||
js_free(stack_);
|
||||
}
|
||||
|
||||
Simulator::Simulator(SimulatorRuntime *srt)
|
||||
: srt_(srt)
|
||||
Simulator::Simulator()
|
||||
{
|
||||
// Set up simulator support first. Some of this information is needed to
|
||||
// setup the architecture state.
|
||||
|
||||
// Allocate 2MB for the stack. Note that we will only use 1MB, see also
|
||||
// Simulator::stackLimit().
|
||||
// Allocate 2MB for the stack. Note that we will only use 1MB, see below.
|
||||
static const size_t stackSize = 2 * 1024*1024;
|
||||
stack_ = reinterpret_cast<char*>(js_malloc(stackSize));
|
||||
if (!stack_) {
|
||||
MOZ_ReportAssertionFailure("[unhandlable oom] Simulator stack", __FILE__, __LINE__);
|
||||
MOZ_CRASH();
|
||||
}
|
||||
// Leave a safety margin of 1MB to prevent overrunning the stack when
|
||||
// pushing values (total stack size is 2MB).
|
||||
stackLimit_ = reinterpret_cast<uintptr_t>(stack_) + 1024 * 1024;
|
||||
pc_modified_ = false;
|
||||
icount_ = 0L;
|
||||
resume_pc_ = 0;
|
||||
|
@ -1172,6 +1088,8 @@ Simulator::Simulator(SimulatorRuntime *srt)
|
|||
registers_[lr] = bad_lr;
|
||||
|
||||
lastDebuggerInput_ = nullptr;
|
||||
|
||||
redirection_ = nullptr;
|
||||
}
|
||||
|
||||
// When the generated code calls a VM function (masm.callWithABI) we need to
|
||||
|
@ -1182,18 +1100,18 @@ Simulator::Simulator(SimulatorRuntime *srt)
|
|||
// offset from the svc instruction so the simulator knows what to call.
|
||||
class Redirection
|
||||
{
|
||||
friend class SimulatorRuntime;
|
||||
friend class Simulator;
|
||||
|
||||
Redirection(void *nativeFunction, ABIFunctionType type, SimulatorRuntime *srt)
|
||||
Redirection(void *nativeFunction, ABIFunctionType type, Simulator *sim)
|
||||
: nativeFunction_(nativeFunction),
|
||||
swiInstruction_(Assembler::AL | (0xf * (1 << 24)) | kCallRtRedirected),
|
||||
type_(type),
|
||||
next_(nullptr)
|
||||
{
|
||||
next_ = srt->redirection();
|
||||
next_ = sim->redirection();
|
||||
if (Simulator::ICacheCheckingEnabled)
|
||||
FlushICache(srt->icache(), addressOfSwiInstruction(), SimInstruction::kInstrSize);
|
||||
srt->setRedirection(this);
|
||||
FlushICache(sim->icache(), addressOfSwiInstruction(), SimInstruction::kInstrSize);
|
||||
sim->setRedirection(this);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -1202,13 +1120,8 @@ class Redirection
|
|||
ABIFunctionType type() const { return type_; }
|
||||
|
||||
static Redirection *Get(void *nativeFunction, ABIFunctionType type) {
|
||||
PerThreadData *pt = TlsPerThreadData.get();
|
||||
SimulatorRuntime *srt = pt->simulatorRuntime();
|
||||
AutoLockSimulatorRuntime alsr(srt);
|
||||
|
||||
MOZ_ASSERT_IF(pt->simulator(), pt->simulator()->srt_ == srt);
|
||||
|
||||
Redirection *current = srt->redirection();
|
||||
Simulator *sim = Simulator::Current();
|
||||
Redirection *current = sim->redirection();
|
||||
for (; current != nullptr; current = current->next_) {
|
||||
if (current->nativeFunction_ == nativeFunction) {
|
||||
MOZ_ASSERT(current->type() == type);
|
||||
|
@ -1222,7 +1135,7 @@ class Redirection
|
|||
__FILE__, __LINE__);
|
||||
MOZ_CRASH();
|
||||
}
|
||||
new(redir) Redirection(nativeFunction, type, srt);
|
||||
new(redir) Redirection(nativeFunction, type, sim);
|
||||
return redir;
|
||||
}
|
||||
|
||||
|
@ -1239,23 +1152,22 @@ class Redirection
|
|||
Redirection *next_;
|
||||
};
|
||||
|
||||
/* static */ void *
|
||||
Simulator::RedirectNativeFunction(void *nativeFunction, ABIFunctionType type)
|
||||
{
|
||||
Redirection *redirection = Redirection::Get(nativeFunction, type);
|
||||
return redirection->addressOfSwiInstruction();
|
||||
}
|
||||
|
||||
SimulatorRuntime::~SimulatorRuntime()
|
||||
Simulator::~Simulator()
|
||||
{
|
||||
js_free(stack_);
|
||||
Redirection *r = redirection_;
|
||||
while (r) {
|
||||
Redirection *next = r->next_;
|
||||
js_delete(r);
|
||||
r = next;
|
||||
}
|
||||
if (lock_)
|
||||
PR_DestroyLock(lock_);
|
||||
}
|
||||
|
||||
/* static */ void *
|
||||
Simulator::RedirectNativeFunction(void *nativeFunction, ABIFunctionType type)
|
||||
{
|
||||
Redirection *redirection = Redirection::Get(nativeFunction, type);
|
||||
return redirection->addressOfSwiInstruction();
|
||||
}
|
||||
|
||||
// Sets the register in the architecture state. It will also deal with updating
|
||||
|
@ -1630,9 +1542,13 @@ Simulator::writeDW(int32_t addr, int32_t value1, int32_t value2)
|
|||
uintptr_t
|
||||
Simulator::stackLimit() const
|
||||
{
|
||||
// Leave a safety margin of 1MB to prevent overrunning the stack when
|
||||
// pushing values (total stack size is 2MB).
|
||||
return reinterpret_cast<uintptr_t>(stack_) + 1024 * 1024;
|
||||
return stackLimit_;
|
||||
}
|
||||
|
||||
uintptr_t *
|
||||
Simulator::addressOfStackLimit()
|
||||
{
|
||||
return &stackLimit_;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -4170,10 +4086,8 @@ Simulator::decodeSpecialCondition(SimInstruction *instr)
|
|||
void
|
||||
Simulator::instructionDecode(SimInstruction *instr)
|
||||
{
|
||||
if (Simulator::ICacheCheckingEnabled) {
|
||||
AutoLockSimulatorRuntime alsr(srt_);
|
||||
CheckICache(srt_->icache(), instr);
|
||||
}
|
||||
if (Simulator::ICacheCheckingEnabled)
|
||||
CheckICache(icache(), instr);
|
||||
|
||||
pc_modified_ = false;
|
||||
|
||||
|
@ -4441,14 +4355,7 @@ Simulator::call(uint8_t* entry, int argument_count, ...)
|
|||
Simulator *
|
||||
Simulator::Current()
|
||||
{
|
||||
PerThreadData *pt = TlsPerThreadData.get();
|
||||
Simulator *sim = pt->simulator();
|
||||
if (!sim) {
|
||||
sim = js_new<Simulator>(pt->simulatorRuntime());
|
||||
pt->setSimulator(sim);
|
||||
}
|
||||
|
||||
return sim;
|
||||
return TlsPerThreadData.get()->simulator();
|
||||
}
|
||||
|
||||
} // namespace jit
|
||||
|
@ -4460,46 +4367,14 @@ JSRuntime::simulator() const
|
|||
return simulator_;
|
||||
}
|
||||
|
||||
uintptr_t *
|
||||
JSRuntime::addressOfSimulatorStackLimit()
|
||||
{
|
||||
return simulator_->addressOfStackLimit();
|
||||
}
|
||||
|
||||
js::jit::Simulator *
|
||||
js::PerThreadData::simulator() const
|
||||
{
|
||||
return runtime_->simulator();
|
||||
}
|
||||
|
||||
void
|
||||
JSRuntime::setSimulator(js::jit::Simulator *sim)
|
||||
{
|
||||
simulator_ = sim;
|
||||
simulatorStackLimit_ = sim->stackLimit();
|
||||
}
|
||||
|
||||
void
|
||||
js::PerThreadData::setSimulator(js::jit::Simulator *sim)
|
||||
{
|
||||
runtime_->setSimulator(sim);
|
||||
}
|
||||
|
||||
uintptr_t *
|
||||
JSRuntime::addressOfSimulatorStackLimit()
|
||||
{
|
||||
return &simulatorStackLimit_;
|
||||
}
|
||||
|
||||
js::jit::SimulatorRuntime *
|
||||
js::PerThreadData::simulatorRuntime() const
|
||||
{
|
||||
return runtime_->simulatorRuntime();
|
||||
}
|
||||
|
||||
js::jit::SimulatorRuntime *
|
||||
JSRuntime::simulatorRuntime() const
|
||||
{
|
||||
return simulatorRuntime_;
|
||||
}
|
||||
|
||||
void
|
||||
JSRuntime::setSimulatorRuntime(js::jit::SimulatorRuntime *srt)
|
||||
{
|
||||
MOZ_ASSERT(!simulatorRuntime_);
|
||||
simulatorRuntime_ = srt;
|
||||
}
|
||||
|
|
|
@ -38,9 +38,8 @@ namespace js {
|
|||
namespace jit {
|
||||
|
||||
class Simulator;
|
||||
class SimulatorRuntime;
|
||||
SimulatorRuntime *CreateSimulatorRuntime();
|
||||
void DestroySimulatorRuntime(SimulatorRuntime *srt);
|
||||
class Redirection;
|
||||
class CachePage;
|
||||
|
||||
// When the SingleStepCallback is called, the simulator is about to execute
|
||||
// sim->get_pc() and the current machine state represents the completed
|
||||
|
@ -95,7 +94,11 @@ class Simulator
|
|||
num_q_registers = 16
|
||||
};
|
||||
|
||||
explicit Simulator(SimulatorRuntime *srt);
|
||||
static Simulator *Create();
|
||||
static void Destroy(Simulator *simulator);
|
||||
|
||||
// Constructor/destructor are for internal use only; use the static methods above.
|
||||
Simulator();
|
||||
~Simulator();
|
||||
|
||||
// The currently executing Simulator instance. Potentially there can be one
|
||||
|
@ -106,6 +109,8 @@ class Simulator
|
|||
return Simulator::Current()->stackLimit();
|
||||
}
|
||||
|
||||
uintptr_t *addressOfStackLimit();
|
||||
|
||||
// Accessors for register state. Reading the pc value adheres to the ARM
|
||||
// architecture specification and is off by a 8 from the currently executing
|
||||
// instruction.
|
||||
|
@ -333,6 +338,7 @@ class Simulator
|
|||
|
||||
// Simulator support.
|
||||
char *stack_;
|
||||
uintptr_t stackLimit_;
|
||||
bool pc_modified_;
|
||||
int64_t icount_;
|
||||
|
||||
|
@ -350,8 +356,6 @@ class Simulator
|
|||
SingleStepCallback single_step_callback_;
|
||||
void *single_step_callback_arg_;
|
||||
|
||||
SimulatorRuntime *srt_;
|
||||
|
||||
// A stop is watched if its code is less than kNumOfWatchedStops.
|
||||
// Only watched stops support enabling/disabling and the counter feature.
|
||||
static const uint32_t kNumOfWatchedStops = 256;
|
||||
|
@ -374,6 +378,35 @@ class Simulator
|
|||
return icount_;
|
||||
}
|
||||
|
||||
private:
|
||||
Redirection *redirection_;
|
||||
|
||||
// ICache checking.
|
||||
struct ICacheHasher {
|
||||
typedef void *Key;
|
||||
typedef void *Lookup;
|
||||
static HashNumber hash(const Lookup &l);
|
||||
static bool match(const Key &k, const Lookup &l);
|
||||
};
|
||||
|
||||
public:
|
||||
typedef HashMap<void *, CachePage *, ICacheHasher, SystemAllocPolicy> ICacheMap;
|
||||
|
||||
protected:
|
||||
ICacheMap icache_;
|
||||
|
||||
public:
|
||||
ICacheMap &icache() {
|
||||
return icache_;
|
||||
}
|
||||
|
||||
Redirection *redirection() const {
|
||||
return redirection_;
|
||||
}
|
||||
|
||||
void setRedirection(js::jit::Redirection *redirection) {
|
||||
redirection_ = redirection;
|
||||
}
|
||||
};
|
||||
|
||||
#define JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, onerror) \
|
||||
|
|
|
@ -486,96 +486,20 @@ class CachePage {
|
|||
char validity_map_[kValidityMapSize]; // One byte per line.
|
||||
};
|
||||
|
||||
class Redirection;
|
||||
|
||||
class SimulatorRuntime
|
||||
{
|
||||
friend class AutoLockSimulatorRuntime;
|
||||
|
||||
Redirection *redirection_;
|
||||
|
||||
// ICache checking.
|
||||
struct ICacheHasher {
|
||||
typedef void *Key;
|
||||
typedef void *Lookup;
|
||||
static HashNumber hash(const Lookup &l);
|
||||
static bool match(const Key &k, const Lookup &l);
|
||||
};
|
||||
|
||||
public:
|
||||
typedef HashMap<void *, CachePage *, ICacheHasher, SystemAllocPolicy> ICacheMap;
|
||||
|
||||
protected:
|
||||
ICacheMap icache_;
|
||||
|
||||
// Synchronize access between main thread and compilation threads.
|
||||
PRLock *lock_;
|
||||
mozilla::DebugOnly<PRThread *> lockOwner_;
|
||||
|
||||
public:
|
||||
SimulatorRuntime()
|
||||
: redirection_(nullptr),
|
||||
lock_(nullptr),
|
||||
lockOwner_(nullptr) {}
|
||||
~SimulatorRuntime();
|
||||
bool init() {
|
||||
lock_ = PR_NewLock();
|
||||
if (!lock_)
|
||||
return false;
|
||||
if (!icache_.init())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
ICacheMap &icache() {
|
||||
MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
|
||||
return icache_;
|
||||
}
|
||||
Redirection *redirection() const {
|
||||
MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
|
||||
return redirection_;
|
||||
}
|
||||
void setRedirection(js::jit::Redirection *redirection) {
|
||||
MOZ_ASSERT(lockOwner_ == PR_GetCurrentThread());
|
||||
redirection_ = redirection;
|
||||
}
|
||||
};
|
||||
|
||||
class AutoLockSimulatorRuntime
|
||||
{
|
||||
protected:
|
||||
SimulatorRuntime *srt_;
|
||||
|
||||
public:
|
||||
AutoLockSimulatorRuntime(SimulatorRuntime *srt)
|
||||
: srt_(srt) {
|
||||
PR_Lock(srt_->lock_);
|
||||
MOZ_ASSERT(!srt_->lockOwner_);
|
||||
#ifdef DEBUG
|
||||
srt_->lockOwner_ = PR_GetCurrentThread();
|
||||
#endif
|
||||
}
|
||||
|
||||
~AutoLockSimulatorRuntime() {
|
||||
MOZ_ASSERT(srt_->lockOwner_ == PR_GetCurrentThread());
|
||||
srt_->lockOwner_ = nullptr;
|
||||
PR_Unlock(srt_->lock_);
|
||||
}
|
||||
};
|
||||
|
||||
bool Simulator::ICacheCheckingEnabled = false;
|
||||
|
||||
int Simulator::StopSimAt = -1;
|
||||
|
||||
SimulatorRuntime *
|
||||
CreateSimulatorRuntime()
|
||||
Simulator *
|
||||
Simulator::Create()
|
||||
{
|
||||
SimulatorRuntime *srt = js_new<SimulatorRuntime>();
|
||||
if (!srt)
|
||||
Simulator *sim = js_new<Simulator>();
|
||||
if (!sim)
|
||||
return nullptr;
|
||||
|
||||
if (!srt->init()) {
|
||||
js_delete(srt);
|
||||
return nullptr;
|
||||
if (!sim->icache_.init()) {
|
||||
js_delete(sim);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getenv("MIPS_SIM_ICACHE_CHECKS"))
|
||||
|
@ -588,13 +512,13 @@ CreateSimulatorRuntime()
|
|||
Simulator::StopSimAt = stopAt;
|
||||
}
|
||||
|
||||
return srt;
|
||||
return sim;
|
||||
}
|
||||
|
||||
void
|
||||
DestroySimulatorRuntime(SimulatorRuntime *srt)
|
||||
Simulator::Destroy(Simulator *sim)
|
||||
{
|
||||
js_delete(srt);
|
||||
js_delete(sim);
|
||||
}
|
||||
|
||||
// The MipsDebugger class is used by the simulator while debugging simulated
|
||||
|
@ -1193,9 +1117,9 @@ Simulator::setLastDebuggerInput(char *input)
|
|||
}
|
||||
|
||||
static CachePage *
|
||||
GetCachePage(SimulatorRuntime::ICacheMap &i_cache, void *page)
|
||||
GetCachePage(Simulator::ICacheMap &i_cache, void *page)
|
||||
{
|
||||
SimulatorRuntime::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
|
||||
Simulator::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
|
||||
if (p)
|
||||
return p->value();
|
||||
|
||||
|
@ -1207,7 +1131,7 @@ GetCachePage(SimulatorRuntime::ICacheMap &i_cache, void *page)
|
|||
|
||||
// Flush from start up to and not including start + size.
|
||||
static void
|
||||
FlushOnePage(SimulatorRuntime::ICacheMap &i_cache, intptr_t start, int size)
|
||||
FlushOnePage(Simulator::ICacheMap &i_cache, intptr_t start, int size)
|
||||
{
|
||||
MOZ_ASSERT(size <= CachePage::kPageSize);
|
||||
MOZ_ASSERT(AllOnOnePage(start, size - 1));
|
||||
|
@ -1221,7 +1145,7 @@ FlushOnePage(SimulatorRuntime::ICacheMap &i_cache, intptr_t start, int size)
|
|||
}
|
||||
|
||||
static void
|
||||
FlushICache(SimulatorRuntime::ICacheMap &i_cache, void *start_addr, size_t size)
|
||||
FlushICache(Simulator::ICacheMap &i_cache, void *start_addr, size_t size)
|
||||
{
|
||||
intptr_t start = reinterpret_cast<intptr_t>(start_addr);
|
||||
int intra_line = (start & CachePage::kLineMask);
|
||||
|
@ -1243,7 +1167,7 @@ FlushICache(SimulatorRuntime::ICacheMap &i_cache, void *start_addr, size_t size)
|
|||
}
|
||||
|
||||
static void
|
||||
CheckICache(SimulatorRuntime::ICacheMap &i_cache, SimInstruction *instr)
|
||||
CheckICache(Simulator::ICacheMap &i_cache, SimInstruction *instr)
|
||||
{
|
||||
intptr_t address = reinterpret_cast<intptr_t>(instr);
|
||||
void *page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
|
||||
|
@ -1266,13 +1190,13 @@ CheckICache(SimulatorRuntime::ICacheMap &i_cache, SimInstruction *instr)
|
|||
}
|
||||
|
||||
HashNumber
|
||||
SimulatorRuntime::ICacheHasher::hash(const Lookup &l)
|
||||
Simulator::ICacheHasher::hash(const Lookup &l)
|
||||
{
|
||||
return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(l)) >> 2;
|
||||
}
|
||||
|
||||
bool
|
||||
SimulatorRuntime::ICacheHasher::match(const Key &k, const Lookup &l)
|
||||
Simulator::ICacheHasher::match(const Key &k, const Lookup &l)
|
||||
{
|
||||
MOZ_ASSERT((reinterpret_cast<intptr_t>(k) & CachePage::kPageMask) == 0);
|
||||
MOZ_ASSERT((reinterpret_cast<intptr_t>(l) & CachePage::kPageMask) == 0);
|
||||
|
@ -1282,30 +1206,24 @@ SimulatorRuntime::ICacheHasher::match(const Key &k, const Lookup &l)
|
|||
void
|
||||
Simulator::FlushICache(void *start_addr, size_t size)
|
||||
{
|
||||
SimulatorRuntime *srt = TlsPerThreadData.get()->simulatorRuntime();
|
||||
AutoLockSimulatorRuntime alsr(srt);
|
||||
js::jit::FlushICache(srt->icache(), start_addr, size);
|
||||
js::jit::FlushICache(Simulator::Current()->icache(), start_addr, size);
|
||||
}
|
||||
|
||||
Simulator::~Simulator()
|
||||
{
|
||||
js_free(stack_);
|
||||
}
|
||||
|
||||
Simulator::Simulator(SimulatorRuntime *srt)
|
||||
: srt_(srt)
|
||||
Simulator::Simulator()
|
||||
{
|
||||
// Set up simulator support first. Some of this information is needed to
|
||||
// setup the architecture state.
|
||||
|
||||
// Allocate 2MB for the stack. Note that we will only use 1MB, see also
|
||||
// Simulator::stackLimit().
|
||||
// Allocate 2MB for the stack. Note that we will only use 1MB, see below.
|
||||
static const size_t stackSize = 2 * 1024 * 1024;
|
||||
stack_ = static_cast<char*>(js_malloc(stackSize));
|
||||
if (!stack_) {
|
||||
MOZ_ReportAssertionFailure("[unhandlable oom] Simulator stack", __FILE__, __LINE__);
|
||||
MOZ_CRASH();
|
||||
}
|
||||
// Leave a safety margin of 1MB to prevent overrunning the stack when
|
||||
// pushing values (total stack size is 2MB).
|
||||
stackLimit_ = reinterpret_cast<uintptr_t>(stack_) + 1024 * 1024;
|
||||
pc_modified_ = false;
|
||||
icount_ = 0;
|
||||
break_count_ = 0;
|
||||
|
@ -1336,6 +1254,8 @@ Simulator::Simulator(SimulatorRuntime *srt)
|
|||
exceptions[i] = 0;
|
||||
|
||||
lastDebuggerInput_ = nullptr;
|
||||
|
||||
redirection_ = nullptr;
|
||||
}
|
||||
|
||||
// When the generated code calls an external reference we need to catch that in
|
||||
|
@ -1347,18 +1267,18 @@ Simulator::Simulator(SimulatorRuntime *srt)
|
|||
// offset from the swi instruction so the simulator knows what to call.
|
||||
class Redirection
|
||||
{
|
||||
friend class SimulatorRuntime;
|
||||
friend class Simulator;
|
||||
|
||||
Redirection(void* nativeFunction, ABIFunctionType type, SimulatorRuntime *srt)
|
||||
Redirection(void* nativeFunction, ABIFunctionType type, Simulator *sim)
|
||||
: nativeFunction_(nativeFunction),
|
||||
swiInstruction_(kCallRedirInstr),
|
||||
type_(type),
|
||||
next_(nullptr)
|
||||
{
|
||||
next_ = srt->redirection();
|
||||
next_ = sim->redirection();
|
||||
if (Simulator::ICacheCheckingEnabled)
|
||||
FlushICache(srt->icache(), addressOfSwiInstruction(), SimInstruction::kInstrSize);
|
||||
srt->setRedirection(this);
|
||||
FlushICache(sim->icache(), addressOfSwiInstruction(), SimInstruction::kInstrSize);
|
||||
sim->setRedirection(this);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -1367,13 +1287,8 @@ class Redirection
|
|||
ABIFunctionType type() const { return type_; }
|
||||
|
||||
static Redirection *Get(void *nativeFunction, ABIFunctionType type) {
|
||||
PerThreadData *pt = TlsPerThreadData.get();
|
||||
SimulatorRuntime *srt = pt->simulatorRuntime();
|
||||
AutoLockSimulatorRuntime alsr(srt);
|
||||
|
||||
MOZ_ASSERT_IF(pt->simulator(), pt->simulator()->srt_ == srt);
|
||||
|
||||
Redirection *current = srt->redirection();
|
||||
Simulator *sim = Simulator::Current();
|
||||
Redirection *current = sim->redirection();
|
||||
for (; current != nullptr; current = current->next_) {
|
||||
if (current->nativeFunction_ == nativeFunction) {
|
||||
MOZ_ASSERT(current->type() == type);
|
||||
|
@ -1387,7 +1302,7 @@ class Redirection
|
|||
__FILE__, __LINE__);
|
||||
MOZ_CRASH();
|
||||
}
|
||||
new(redir) Redirection(nativeFunction, type, srt);
|
||||
new(redir) Redirection(nativeFunction, type, sim);
|
||||
return redir;
|
||||
}
|
||||
|
||||
|
@ -1404,6 +1319,17 @@ class Redirection
|
|||
Redirection *next_;
|
||||
};
|
||||
|
||||
Simulator::~Simulator()
|
||||
{
|
||||
js_free(stack_);
|
||||
Redirection *r = redirection_;
|
||||
while (r) {
|
||||
Redirection *next = r->next_;
|
||||
js_delete(r);
|
||||
r = next;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void *
|
||||
Simulator::RedirectNativeFunction(void *nativeFunction, ABIFunctionType type)
|
||||
{
|
||||
|
@ -1411,30 +1337,11 @@ Simulator::RedirectNativeFunction(void *nativeFunction, ABIFunctionType type)
|
|||
return redirection->addressOfSwiInstruction();
|
||||
}
|
||||
|
||||
SimulatorRuntime::~SimulatorRuntime()
|
||||
{
|
||||
Redirection *r = redirection_;
|
||||
while (r) {
|
||||
Redirection *next = r->next_;
|
||||
js_delete(r);
|
||||
r = next;
|
||||
}
|
||||
if (lock_)
|
||||
PR_DestroyLock(lock_);
|
||||
}
|
||||
|
||||
// Get the active Simulator for the current thread.
|
||||
Simulator *
|
||||
Simulator::Current()
|
||||
{
|
||||
PerThreadData *pt = TlsPerThreadData.get();
|
||||
Simulator *sim = pt->simulator();
|
||||
if (!sim) {
|
||||
sim = js_new<Simulator>(pt->simulatorRuntime());
|
||||
pt->setSimulator(sim);
|
||||
}
|
||||
|
||||
return sim;
|
||||
return TlsPerThreadData.get()->simulator();
|
||||
}
|
||||
|
||||
// Sets the register in the architecture state. It will also deal with updating
|
||||
|
@ -1808,9 +1715,13 @@ Simulator::writeB(uint32_t addr, int8_t value)
|
|||
uintptr_t
|
||||
Simulator::stackLimit() const
|
||||
{
|
||||
// Leave a safety margin of 1MB to prevent overrunning the stack when
|
||||
// pushing values (total stack size is 2MB).
|
||||
return reinterpret_cast<uintptr_t>(stack_) + 1024 * 1024;
|
||||
return stackLimit_;
|
||||
}
|
||||
|
||||
uintptr_t *
|
||||
Simulator::addressOfStackLimit()
|
||||
{
|
||||
return &stackLimit_;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -3302,10 +3213,8 @@ Simulator::decodeTypeJump(SimInstruction *instr)
|
|||
void
|
||||
Simulator::instructionDecode(SimInstruction *instr)
|
||||
{
|
||||
if (Simulator::ICacheCheckingEnabled) {
|
||||
AutoLockSimulatorRuntime alsr(srt_);
|
||||
CheckICache(srt_->icache(), instr);
|
||||
}
|
||||
if (Simulator::ICacheCheckingEnabled)
|
||||
CheckICache(icache(), instr);
|
||||
pc_modified_ = false;
|
||||
|
||||
switch (instr->instructionType()) {
|
||||
|
@ -3516,40 +3425,9 @@ js::PerThreadData::simulator() const
|
|||
return runtime_->simulator();
|
||||
}
|
||||
|
||||
void
|
||||
JSRuntime::setSimulator(js::jit::Simulator *sim)
|
||||
{
|
||||
simulator_ = sim;
|
||||
simulatorStackLimit_ = sim->stackLimit();
|
||||
}
|
||||
|
||||
void
|
||||
js::PerThreadData::setSimulator(js::jit::Simulator *sim)
|
||||
{
|
||||
runtime_->setSimulator(sim);
|
||||
}
|
||||
|
||||
uintptr_t *
|
||||
JSRuntime::addressOfSimulatorStackLimit()
|
||||
{
|
||||
return &simulatorStackLimit_;
|
||||
return simulator_->addressOfStackLimit();
|
||||
}
|
||||
|
||||
js::jit::SimulatorRuntime *
|
||||
js::PerThreadData::simulatorRuntime() const
|
||||
{
|
||||
return runtime_->simulatorRuntime();
|
||||
}
|
||||
|
||||
js::jit::SimulatorRuntime *
|
||||
JSRuntime::simulatorRuntime() const
|
||||
{
|
||||
return simulatorRuntime_;
|
||||
}
|
||||
|
||||
void
|
||||
JSRuntime::setSimulatorRuntime(js::jit::SimulatorRuntime *srt)
|
||||
{
|
||||
MOZ_ASSERT(!simulatorRuntime_);
|
||||
simulatorRuntime_ = srt;
|
||||
}
|
||||
|
|
|
@ -36,9 +36,9 @@
|
|||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
class SimulatorRuntime;
|
||||
SimulatorRuntime *CreateSimulatorRuntime();
|
||||
void DestroySimulatorRuntime(SimulatorRuntime *srt);
|
||||
class Simulator;
|
||||
class Redirection;
|
||||
class CachePage;
|
||||
|
||||
const intptr_t kPointerAlignment = 4;
|
||||
const intptr_t kPointerAlignmentMask = kPointerAlignment - 1;
|
||||
|
@ -137,7 +137,11 @@ class Simulator {
|
|||
kNumFPURegisters
|
||||
};
|
||||
|
||||
explicit Simulator(SimulatorRuntime *srt);
|
||||
static Simulator *Create();
|
||||
static void Destroy(Simulator *simulator);
|
||||
|
||||
// Constructor/destructor are for internal use only; use the static methods above.
|
||||
Simulator();
|
||||
~Simulator();
|
||||
|
||||
// The currently executing Simulator instance. Potentially there can be one
|
||||
|
@ -148,6 +152,8 @@ class Simulator {
|
|||
return Simulator::Current()->stackLimit();
|
||||
}
|
||||
|
||||
uintptr_t *addressOfStackLimit();
|
||||
|
||||
// Accessors for register state. Reading the pc value adheres to the MIPS
|
||||
// architecture specification and is off by a 8 from the currently executing
|
||||
// instruction.
|
||||
|
@ -315,6 +321,7 @@ class Simulator {
|
|||
|
||||
// Simulator support.
|
||||
char *stack_;
|
||||
uintptr_t stackLimit_;
|
||||
bool pc_modified_;
|
||||
int icount_;
|
||||
int break_count_;
|
||||
|
@ -328,8 +335,6 @@ class Simulator {
|
|||
SimInstruction *break_pc_;
|
||||
Instr break_instr_;
|
||||
|
||||
SimulatorRuntime *srt_;
|
||||
|
||||
// A stop is watched if its code is less than kNumOfWatchedStops.
|
||||
// Only watched stops support enabling/disabling and the counter feature.
|
||||
static const uint32_t kNumOfWatchedStops = 256;
|
||||
|
@ -347,6 +352,36 @@ class Simulator {
|
|||
char *desc_;
|
||||
};
|
||||
StopCountAndDesc watchedStops_[kNumOfWatchedStops];
|
||||
|
||||
private:
|
||||
Redirection *redirection_;
|
||||
|
||||
// ICache checking.
|
||||
struct ICacheHasher {
|
||||
typedef void *Key;
|
||||
typedef void *Lookup;
|
||||
static HashNumber hash(const Lookup &l);
|
||||
static bool match(const Key &k, const Lookup &l);
|
||||
};
|
||||
|
||||
public:
|
||||
typedef HashMap<void *, CachePage *, ICacheHasher, SystemAllocPolicy> ICacheMap;
|
||||
|
||||
protected:
|
||||
ICacheMap icache_;
|
||||
|
||||
public:
|
||||
ICacheMap &icache() {
|
||||
return icache_;
|
||||
}
|
||||
|
||||
Redirection *redirection() const {
|
||||
return redirection_;
|
||||
}
|
||||
|
||||
void setRedirection(js::jit::Redirection *redirection) {
|
||||
redirection_ = redirection;
|
||||
}
|
||||
};
|
||||
|
||||
#define JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, onerror) \
|
||||
|
|
|
@ -1191,8 +1191,9 @@ ExclusiveContext::stackLimitAddressForJitCode(StackKind kind)
|
|||
{
|
||||
#if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
|
||||
return runtime_->addressOfSimulatorStackLimit();
|
||||
#endif
|
||||
#else
|
||||
return stackLimitAddress(kind);
|
||||
#endif
|
||||
}
|
||||
|
||||
JSVersion
|
||||
|
|
|
@ -158,8 +158,6 @@ JSRuntime::JSRuntime(JSRuntime *parentRuntime)
|
|||
gcInitialized(false),
|
||||
#if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
|
||||
simulator_(nullptr),
|
||||
simulatorStackLimit_(0),
|
||||
simulatorRuntime_(nullptr),
|
||||
#endif
|
||||
scriptAndCountsVector(nullptr),
|
||||
NaNValue(DoubleNaNValue()),
|
||||
|
@ -318,8 +316,8 @@ JSRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
|
|||
dateTimeInfo.updateTimeZoneAdjustment();
|
||||
|
||||
#if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
|
||||
simulatorRuntime_ = js::jit::CreateSimulatorRuntime();
|
||||
if (!simulatorRuntime_)
|
||||
simulator_ = js::jit::Simulator::Create();
|
||||
if (!simulator_)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
|
@ -435,8 +433,7 @@ JSRuntime::~JSRuntime()
|
|||
gc.nursery.disable();
|
||||
|
||||
#if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
|
||||
js::jit::DestroySimulatorRuntime(simulatorRuntime_);
|
||||
js_delete(simulator_);
|
||||
js::jit::Simulator::Destroy(simulator_);
|
||||
#endif
|
||||
|
||||
DebugOnly<size_t> oldCount = liveRuntimesCount--;
|
||||
|
|
|
@ -85,7 +85,6 @@ class JitRuntime;
|
|||
class JitActivation;
|
||||
struct PcScriptCache;
|
||||
class Simulator;
|
||||
class SimulatorRuntime;
|
||||
struct AutoFlushICache;
|
||||
class CompileRuntime;
|
||||
}
|
||||
|
@ -562,8 +561,6 @@ class PerThreadData : public PerThreadDataFriendFields
|
|||
|
||||
#if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
|
||||
js::jit::Simulator *simulator() const;
|
||||
void setSimulator(js::jit::Simulator *sim);
|
||||
js::jit::SimulatorRuntime *simulatorRuntime() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -959,8 +956,6 @@ struct JSRuntime : public JS::shadow::Runtime,
|
|||
|
||||
#if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
|
||||
js::jit::Simulator *simulator_;
|
||||
uintptr_t simulatorStackLimit_;
|
||||
js::jit::SimulatorRuntime *simulatorRuntime_;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
@ -970,10 +965,7 @@ struct JSRuntime : public JS::shadow::Runtime,
|
|||
|
||||
#if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
|
||||
js::jit::Simulator *simulator() const;
|
||||
void setSimulator(js::jit::Simulator *sim);
|
||||
uintptr_t *addressOfSimulatorStackLimit();
|
||||
js::jit::SimulatorRuntime *simulatorRuntime() const;
|
||||
void setSimulatorRuntime(js::jit::SimulatorRuntime *srt);
|
||||
#endif
|
||||
|
||||
/* Strong references on scripts held for PCCount profiling API. */
|
||||
|
|
Загрузка…
Ссылка в новой задаче