Bug 1337084 - Tolerate multiple threads running JS in JIT simulators, r=jandem.

--HG--
extra : rebase_source : 63625feccd12838cda50fc3650de12c7b147275a
This commit is contained in:
Brian Hackett 2017-02-09 13:50:22 -07:00
Родитель 8287a9c71c
Коммит 18bc843966
12 изменённых файлов: 413 добавлений и 334 удалений

Просмотреть файл

@ -226,7 +226,7 @@ class ExecutableAllocator
#elif defined(JS_SIMULATOR_ARM) || defined(JS_SIMULATOR_MIPS32) || defined(JS_SIMULATOR_MIPS64)
static void cacheFlush(void* code, size_t size)
{
js::jit::Simulator::FlushICache(code, size);
js::jit::SimulatorProcess::FlushICache(code, size);
}
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
static void cacheFlush(void* code, size_t size)

Просмотреть файл

@ -365,28 +365,16 @@ class AutoLockSimulatorCache : public LockGuard<Mutex>
using Base = LockGuard<Mutex>;
public:
explicit AutoLockSimulatorCache(Simulator* sim)
: Base(sim->cacheLock_)
, sim_(sim)
{
MOZ_ASSERT(sim_->cacheLockHolder_.isNothing());
#ifdef DEBUG
sim_->cacheLockHolder_ = mozilla::Some(ThisThread::GetId());
#endif
}
~AutoLockSimulatorCache() {
MOZ_ASSERT(sim_->cacheLockHolder_.isSome());
#ifdef DEBUG
sim_->cacheLockHolder_.reset();
#endif
}
private:
Simulator* const sim_;
explicit AutoLockSimulatorCache()
: Base(SimulatorProcess::singleton_->cacheLock_)
{}
};
bool Simulator::ICacheCheckingEnabled = false;
mozilla::Atomic<size_t, mozilla::ReleaseAcquire>
SimulatorProcess::ICacheCheckingDisableCount(1); // Checking is disabled by default.
mozilla::Atomic<bool, mozilla::ReleaseAcquire>
SimulatorProcess::cacheInvalidatedBySignalHandler_(false);
SimulatorProcess* SimulatorProcess::singleton_ = nullptr;
int64_t Simulator::StopSimAt = -1L;
@ -402,9 +390,6 @@ Simulator::Create(JSContext* cx)
return nullptr;
}
if (getenv("ARM_SIM_ICACHE_CHECKS"))
Simulator::ICacheCheckingEnabled = true;
char* stopAtStr = getenv("ARM_SIM_STOP_AT");
int64_t stopAt;
if (stopAtStr && sscanf(stopAtStr, "%lld", &stopAt) == 1) {
@ -998,9 +983,9 @@ AllOnOnePage(uintptr_t start, int size)
}
static CachePage*
GetCachePageLocked(Simulator::ICacheMap& i_cache, void* page)
GetCachePageLocked(SimulatorProcess::ICacheMap& i_cache, void* page)
{
Simulator::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
SimulatorProcess::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
if (p)
return p->value();
@ -1014,7 +999,7 @@ GetCachePageLocked(Simulator::ICacheMap& i_cache, void* page)
// Flush from start up to and not including start + size.
static void
FlushOnePageLocked(Simulator::ICacheMap& i_cache, intptr_t start, int size)
FlushOnePageLocked(SimulatorProcess::ICacheMap& i_cache, intptr_t start, int size)
{
MOZ_ASSERT(size <= CachePage::kPageSize);
MOZ_ASSERT(AllOnOnePage(start, size - 1));
@ -1029,7 +1014,7 @@ FlushOnePageLocked(Simulator::ICacheMap& i_cache, intptr_t start, int size)
}
static void
FlushICacheLocked(Simulator::ICacheMap& i_cache, void* start_addr, size_t size)
FlushICacheLocked(SimulatorProcess::ICacheMap& i_cache, void* start_addr, size_t size)
{
intptr_t start = reinterpret_cast<intptr_t>(start_addr);
int intra_line = (start & CachePage::kLineMask);
@ -1049,14 +1034,14 @@ FlushICacheLocked(Simulator::ICacheMap& i_cache, void* start_addr, size_t size)
FlushOnePageLocked(i_cache, start, size);
}
void
Simulator::checkICacheLocked(Simulator::ICacheMap& i_cache, SimInstruction* instr)
/* static */ void
SimulatorProcess::checkICacheLocked(SimInstruction* instr)
{
intptr_t address = reinterpret_cast<intptr_t>(instr);
void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
int offset = (address & CachePage::kPageMask);
CachePage* cache_page = GetCachePageLocked(i_cache, page);
CachePage* cache_page = GetCachePageLocked(icache(), page);
char* cache_valid_byte = cache_page->validityByte(offset);
bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
char* cached_line = cache_page->cachedData(offset & ~CachePage::kLineMask);
@ -1074,7 +1059,7 @@ Simulator::checkICacheLocked(Simulator::ICacheMap& i_cache, SimInstruction* inst
// It is safe for the signal to arrive during the !cache_hit path, since it
// will be cleared the next time this function is called.
if (cacheInvalidatedBySignalHandler_) {
i_cache.clear();
icache().clear();
cacheInvalidatedBySignalHandler_ = false;
return;
}
@ -1089,13 +1074,13 @@ Simulator::checkICacheLocked(Simulator::ICacheMap& i_cache, SimInstruction* inst
}
HashNumber
Simulator::ICacheHasher::hash(const Lookup& l)
SimulatorProcess::ICacheHasher::hash(const Lookup& l)
{
return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(l)) >> 2;
}
bool
Simulator::ICacheHasher::match(const Key& k, const Lookup& l)
SimulatorProcess::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);
@ -1109,22 +1094,18 @@ Simulator::setLastDebuggerInput(char* input)
lastDebuggerInput_ = input;
}
void
Simulator::FlushICache(void* start_addr, size_t size)
/* static */ void
SimulatorProcess::FlushICache(void* start_addr, size_t size)
{
JitSpewCont(JitSpew_CacheFlush, "[%p %" PRIxSIZE "]", start_addr, size);
if (Simulator::ICacheCheckingEnabled) {
Simulator* sim = Simulator::Current();
AutoLockSimulatorCache als(sim);
js::jit::FlushICacheLocked(sim->icache(), start_addr, size);
if (!ICacheCheckingDisableCount) {
AutoLockSimulatorCache als;
js::jit::FlushICacheLocked(icache(), start_addr, size);
}
}
Simulator::Simulator(JSContext* cx)
: cx_(cx),
cacheLock_(mutexid::SimulatorCacheLock)
: cx_(cx)
{
// Set up simulator support first. Some of this information is needed to
// setup the architecture state.
@ -1142,7 +1123,6 @@ Simulator::Simulator(JSContext* cx)
single_stepping_ = false;
single_step_callback_ = nullptr;
single_step_callback_arg_ = nullptr;
cacheInvalidatedBySignalHandler_ = false;
skipCalleeSavedRegsCheck = false;
// Set up architecture state.
@ -1178,7 +1158,6 @@ Simulator::Simulator(JSContext* cx)
lastDebuggerInput_ = nullptr;
redirection_ = nullptr;
exclusiveMonitorHeld_ = false;
exclusiveMonitor_ = 0;
}
@ -1186,9 +1165,6 @@ Simulator::Simulator(JSContext* cx)
bool
Simulator::init()
{
if (!icache_.init())
return false;
// 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));
@ -1215,19 +1191,21 @@ Simulator::init()
// offset from the svc instruction so the simulator knows what to call.
class Redirection
{
friend class Simulator;
friend class SimulatorProcess;
// sim's lock must already be held.
Redirection(void* nativeFunction, ABIFunctionType type, Simulator* sim)
Redirection(void* nativeFunction, ABIFunctionType type)
: nativeFunction_(nativeFunction),
swiInstruction_(Assembler::AL | (0xf * (1 << 24)) | kCallRtRedirected),
type_(type),
next_(nullptr)
{
next_ = sim->redirection();
if (Simulator::ICacheCheckingEnabled)
FlushICacheLocked(sim->icache(), addressOfSwiInstruction(), SimInstruction::kInstrSize);
sim->setRedirection(this);
next_ = SimulatorProcess::redirection();
if (!SimulatorProcess::ICacheCheckingDisableCount) {
FlushICacheLocked(SimulatorProcess::icache(), addressOfSwiInstruction(),
SimInstruction::kInstrSize);
}
SimulatorProcess::setRedirection(this);
}
public:
@ -1236,11 +1214,9 @@ class Redirection
ABIFunctionType type() const { return type_; }
static Redirection* Get(void* nativeFunction, ABIFunctionType type) {
Simulator* sim = Simulator::Current();
AutoLockSimulatorCache als;
AutoLockSimulatorCache als(sim);
Redirection* current = sim->redirection();
Redirection* current = SimulatorProcess::redirection();
for (; current != nullptr; current = current->next_) {
if (current->nativeFunction_ == nativeFunction) {
MOZ_ASSERT(current->type() == type);
@ -1252,7 +1228,7 @@ class Redirection
Redirection* redir = (Redirection*)js_malloc(sizeof(Redirection));
if (!redir)
oomUnsafe.crash("Simulator redirection");
new(redir) Redirection(nativeFunction, type, sim);
new(redir) Redirection(nativeFunction, type);
return redir;
}
@ -1272,6 +1248,15 @@ class Redirection
Simulator::~Simulator()
{
js_free(stack_);
}
SimulatorProcess::SimulatorProcess()
: cacheLock_(mutexid::SimulatorCacheLock)
, redirection_(nullptr)
{}
SimulatorProcess::~SimulatorProcess()
{
Redirection* r = redirection_;
while (r) {
Redirection* next = r->next_;
@ -1280,6 +1265,15 @@ Simulator::~Simulator()
}
}
bool
SimulatorProcess::init()
{
if (getenv("ARM_SIM_ICACHE_CHECKS"))
ICacheCheckingDisableCount = 0;
return icache_.init();
}
/* static */ void*
Simulator::RedirectNativeFunction(void* nativeFunction, ABIFunctionType type)
{
@ -4660,9 +4654,9 @@ Simulator::decodeSpecialCondition(SimInstruction* instr)
void
Simulator::instructionDecode(SimInstruction* instr)
{
if (Simulator::ICacheCheckingEnabled) {
AutoLockSimulatorCache als(this);
checkICacheLocked(icache(), instr);
if (!SimulatorProcess::ICacheCheckingDisableCount) {
AutoLockSimulatorCache als;
SimulatorProcess::checkICacheLocked(instr);
}
pc_modified_ = false;
@ -4931,7 +4925,9 @@ Simulator::call(uint8_t* entry, int argument_count, ...)
Simulator*
Simulator::Current()
{
return TlsContext.get()->runtime()->unsafeContextFromAnyThread()->simulator();
JSContext* cx = TlsContext.get();
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
return cx->simulator();
}
} // namespace jit

Просмотреть файл

@ -71,11 +71,9 @@ const uint32_t kVFPRoundingModeMask = 3 << 22;
typedef int32_t Instr;
class SimInstruction;
// Per thread simulator state.
class Simulator
{
friend class Redirection;
friend class AutoLockSimulatorCache;
public:
friend class ArmDebugger;
enum Register {
@ -347,30 +345,7 @@ class Simulator
// Executes one instruction.
void instructionDecode(SimInstruction* instr);
private:
// 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;
public:
static bool ICacheCheckingEnabled;
static void FlushICache(void* start, size_t size);
// Jitcode may be rewritten from a signal handler, but is prevented from
// calling FlushICache() because the signal may arrive within the critical
// area of an AutoLockSimulatorCache. This flag instructs the Simulator
// to remove all cache entries the next time it checks, avoiding false negatives.
mozilla::Atomic<bool, mozilla::ReleaseAcquire> cacheInvalidatedBySignalHandler_;
void checkICacheLocked(ICacheMap& i_cache, SimInstruction* instr);
static int64_t StopSimAt;
// For testing the MoveResolver code, a MoveResolver is set up, and
@ -472,37 +447,6 @@ class Simulator
return icount_;
}
private:
// This lock creates a critical section around 'redirection_' and
// 'icache_', which are referenced both by the execution engine
// and by the off-thread compiler (see Redirection::Get in the cpp file).
Mutex cacheLock_;
#ifdef DEBUG
mozilla::Maybe<Thread::Id> cacheLockHolder_;
#endif
Redirection* redirection_;
ICacheMap icache_;
public:
ICacheMap& icache() {
// Technically we need the lock to access the innards of the
// icache, not to take its address, but the latter condition
// serves as a useful complement to the former.
MOZ_ASSERT(cacheLockHolder_.isSome());
return icache_;
}
Redirection* redirection() const {
MOZ_ASSERT(cacheLockHolder_.isSome());
return redirection_;
}
void setRedirection(js::jit::Redirection* redirection) {
MOZ_ASSERT(cacheLockHolder_.isSome());
redirection_ = redirection;
}
private:
// Exclusive access monitor
void exclusiveMonitorSet(uint64_t value);
@ -513,7 +457,81 @@ class Simulator
uint64_t exclusiveMonitor_;
};
#define JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, onerror) \
// Process wide simulator state.
class SimulatorProcess
{
friend class Redirection;
friend class AutoLockSimulatorCache;
private:
// 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;
static mozilla::Atomic<size_t, mozilla::ReleaseAcquire> ICacheCheckingDisableCount;
static void FlushICache(void* start, size_t size);
// Jitcode may be rewritten from a signal handler, but is prevented from
// calling FlushICache() because the signal may arrive within the critical
// area of an AutoLockSimulatorCache. This flag instructs the Simulator
// to remove all cache entries the next time it checks, avoiding false negatives.
static mozilla::Atomic<bool, mozilla::ReleaseAcquire> cacheInvalidatedBySignalHandler_;
static void checkICacheLocked(SimInstruction* instr);
static bool initialize() {
singleton_ = js_new<SimulatorProcess>();
return singleton_ && singleton_->init();
}
static void destroy() {
js_delete(singleton_);
singleton_ = nullptr;
}
SimulatorProcess();
~SimulatorProcess();
private:
bool init();
static SimulatorProcess* singleton_;
// This lock creates a critical section around 'redirection_' and
// 'icache_', which are referenced both by the execution engine
// and by the off-thread compiler (see Redirection::Get in the cpp file).
Mutex cacheLock_;
Redirection* redirection_;
ICacheMap icache_;
public:
static ICacheMap& icache() {
// Technically we need the lock to access the innards of the
// icache, not to take its address, but the latter condition
// serves as a useful complement to the former.
MOZ_ASSERT(singleton_->cacheLock_.ownedByCurrentThread());
return singleton_->icache_;
}
static Redirection* redirection() {
MOZ_ASSERT(singleton_->cacheLock_.ownedByCurrentThread());
return singleton_->redirection_;
}
static void setRedirection(js::jit::Redirection* redirection) {
MOZ_ASSERT(singleton_->cacheLock_.ownedByCurrentThread());
singleton_->redirection_ = redirection;
}
};
#define JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, onerror) \
JS_BEGIN_MACRO \
if (cx->simulator()->overRecursedWithExtra(extra)) { \
js::ReportOverRecursed(cx); \

Просмотреть файл

@ -32,11 +32,14 @@
#include "threading/LockGuard.h"
#include "vm/Runtime.h"
js::jit::SimulatorProcess* js::jit::SimulatorProcess::singleton_ = nullptr;
namespace vixl {
using mozilla::DebugOnly;
using js::jit::ABIFunctionType;
using js::jit::SimulatorProcess;
Simulator::Simulator(Decoder* decoder, FILE* stream)
: stream_(nullptr)
@ -46,7 +49,6 @@ Simulator::Simulator(Decoder* decoder, FILE* stream)
, stack_limit_(nullptr)
, decoder_(nullptr)
, oom_(false)
, lock_(js::mutexid::Arm64SimulatorLock)
{
this->init(decoder, stream);
}
@ -144,13 +146,13 @@ void Simulator::init(Decoder* decoder, FILE* stream) {
// time they are encountered. This warning can be silenced using
// SilenceExclusiveAccessWarning().
print_exclusive_access_warning_ = true;
redirection_ = nullptr;
}
Simulator* Simulator::Current() {
return js::TlsContext.get()->simulator();
JSContext* cx = js::TlsContext.get();
MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(cx->runtime()));
return cx->simulator();
}
@ -294,8 +296,8 @@ class AutoLockSimulatorCache : public js::LockGuard<js::Mutex>
using Base = js::LockGuard<js::Mutex>;
public:
explicit AutoLockSimulatorCache(Simulator* sim)
: Base(sim->lock_)
explicit AutoLockSimulatorCache()
: Base(SimulatorProcess::singleton_->lock_)
{
}
};
@ -311,14 +313,14 @@ class Redirection
{
friend class Simulator;
Redirection(void* nativeFunction, ABIFunctionType type, Simulator* sim)
Redirection(void* nativeFunction, ABIFunctionType type)
: nativeFunction_(nativeFunction),
type_(type),
next_(nullptr)
{
next_ = sim->redirection();
next_ = SimulatorProcess::redirection();
// TODO: Flush ICache?
sim->setRedirection(this);
SimulatorProcess::setRedirection(this);
Instruction* instr = (Instruction*)(&svcInstruction_);
vixl::Assembler::svc(instr, kCallRtRedirected);
@ -330,13 +332,12 @@ class Redirection
ABIFunctionType type() const { return type_; }
static Redirection* Get(void* nativeFunction, ABIFunctionType type) {
Simulator* sim = Simulator::Current();
AutoLockSimulatorCache alsr(sim);
AutoLockSimulatorCache alsr;
// TODO: Store srt_ in the simulator for this assertion.
// VIXL_ASSERT_IF(pt->simulator(), pt->simulator()->srt_ == srt);
Redirection* current = sim->redirection();
Redirection* current = SimulatorProcess::redirection();
for (; current != nullptr; current = current->next_) {
if (current->nativeFunction_ == nativeFunction) {
VIXL_ASSERT(current->type() == type);
@ -348,7 +349,7 @@ class Redirection
Redirection* redir = (Redirection*)js_malloc(sizeof(Redirection));
if (!redir)
oomUnsafe.crash("Simulator redirection");
new(redir) Redirection(nativeFunction, type, sim);
new(redir) Redirection(nativeFunction, type);
return redir;
}
@ -366,14 +367,6 @@ class Redirection
};
void Simulator::setRedirection(Redirection* redirection) {
redirection_ = redirection;
}
Redirection* Simulator::redirection() const {
return redirection_;
}
void* Simulator::RedirectNativeFunction(void* nativeFunction, ABIFunctionType type) {

Просмотреть файл

@ -704,8 +704,6 @@ class SimExclusiveGlobalMonitor {
class Redirection;
class Simulator : public DecoderVisitor {
friend class AutoLockSimulatorCache;
public:
explicit Simulator(Decoder* decoder, FILE* stream = stdout);
~Simulator();
@ -720,8 +718,6 @@ class Simulator : public DecoderVisitor {
bool overRecursed(uintptr_t newsp = 0) const;
bool overRecursedWithExtra(uint32_t extra) const;
int64_t call(uint8_t* entry, int argument_count, ...);
void setRedirection(Redirection* redirection);
Redirection* redirection() const;
static void* RedirectNativeFunction(void* nativeFunction, js::jit::ABIFunctionType type);
void setGPR32Result(int32_t result);
void setGPR64Result(int64_t result);
@ -2666,12 +2662,50 @@ class Simulator : public DecoderVisitor {
bool oom() const { return oom_; }
protected:
// Moz: Synchronizes access between main thread and compilation threads.
js::Mutex lock_;
Redirection* redirection_;
mozilla::Vector<int64_t, 0, js::SystemAllocPolicy> spStack_;
};
} // namespace vixl
namespace js {
namespace jit {
class SimulatorProcess
{
public:
static SimulatorProcess* singleton_;
SimulatorProcess()
: lock_(mutexid::Arm64SimulatorLock)
, redirection_(nullptr)
{}
// Synchronizes access between main thread and compilation threads.
js::Mutex lock_;
vixl::Redirection* redirection_;
static void setRedirection(vixl::Redirection* redirection) {
MOZ_ASSERT(singleton_->lock_.ownedByCurrentThread());
singleton_->redirection_ = redirection;
}
static vixl::Redirection* redirection() {
MOZ_ASSERT(singleton_->lock_.ownedByCurrentThread());
return singleton_->redirection_;
}
static bool initialize() {
singleton_ = js_new<SimulatorProcess>();
return !!singleton_;
}
static void destroy() {
js_delete(singleton_);
singleton_ = nullptr;
}
};
} // namespace jit
} // namespace js
#endif // JS_SIMULATOR_ARM64
#endif // VIXL_A64_SIMULATOR_A64_H_

Просмотреть файл

@ -499,28 +499,16 @@ class AutoLockSimulatorCache : public LockGuard<Mutex>
using Base = LockGuard<Mutex>;
public:
explicit AutoLockSimulatorCache(Simulator* sim)
: Base(sim->cacheLock_)
, sim_(sim)
{
MOZ_ASSERT(sim_->cacheLockHolder_.isNothing());
#ifdef DEBUG
sim_->cacheLockHolder_ = mozilla::Some(ThisThread::GetId());
#endif
}
~AutoLockSimulatorCache() {
MOZ_ASSERT(sim_->cacheLockHolder_.isSome());
#ifdef DEBUG
sim_->cacheLockHolder_.reset();
#endif
}
private:
Simulator* const sim_;
AutoLockSimulatorCache()
: Base(SimulatorProcess::singleton_->cacheLock_)
{}
};
bool Simulator::ICacheCheckingEnabled = false;
mozilla::Atomic<size_t, mozilla::ReleaseAcquire>
SimulatorProcess::ICacheCheckingDisableCount(1); // Checking is disabled by default.
mozilla::Atomic<bool, mozilla::ReleaseAcquire>
SimulatorProcess::cacheInvalidatedBySignalHandler_(false);
SimulatorProcess* SimulatorProcess::singleton_ = nullptr;
int Simulator::StopSimAt = -1;
@ -536,9 +524,6 @@ Simulator::Create(JSContext* cx)
return nullptr;
}
if (getenv("MIPS_SIM_ICACHE_CHECKS"))
Simulator::ICacheCheckingEnabled = true;
char* stopAtStr = getenv("MIPS_SIM_STOP_AT");
int64_t stopAt;
if (stopAtStr && sscanf(stopAtStr, "%lld", &stopAt) == 1) {
@ -1151,9 +1136,9 @@ Simulator::setLastDebuggerInput(char* input)
}
static CachePage*
GetCachePageLocked(Simulator::ICacheMap& i_cache, void* page)
GetCachePageLocked(SimulatorProcess::ICacheMap& i_cache, void* page)
{
Simulator::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
SimulatorProcess::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
if (p)
return p->value();
@ -1165,7 +1150,7 @@ GetCachePageLocked(Simulator::ICacheMap& i_cache, void* page)
// Flush from start up to and not including start + size.
static void
FlushOnePageLocked(Simulator::ICacheMap& i_cache, intptr_t start, int size)
FlushOnePageLocked(SimulatorProcess::ICacheMap& i_cache, intptr_t start, int size)
{
MOZ_ASSERT(size <= CachePage::kPageSize);
MOZ_ASSERT(AllOnOnePage(start, size - 1));
@ -1179,7 +1164,7 @@ FlushOnePageLocked(Simulator::ICacheMap& i_cache, intptr_t start, int size)
}
static void
FlushICacheLocked(Simulator::ICacheMap& i_cache, void* start_addr, size_t size)
FlushICacheLocked(SimulatorProcess::ICacheMap& i_cache, void* start_addr, size_t size)
{
intptr_t start = reinterpret_cast<intptr_t>(start_addr);
int intra_line = (start & CachePage::kLineMask);
@ -1200,14 +1185,14 @@ FlushICacheLocked(Simulator::ICacheMap& i_cache, void* start_addr, size_t size)
}
}
void
Simulator::checkICacheLocked(Simulator::ICacheMap& i_cache, SimInstruction* instr)
/* static */ void
SimulatorProcess::checkICacheLocked(SimInstruction* instr)
{
intptr_t address = reinterpret_cast<intptr_t>(instr);
void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
int offset = (address & CachePage::kPageMask);
CachePage* cache_page = GetCachePageLocked(i_cache, page);
CachePage* cache_page = GetCachePageLocked(icache(), page);
char* cache_valid_byte = cache_page->validityByte(offset);
bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
char* cached_line = cache_page->cachedData(offset & ~CachePage::kLineMask);
@ -1225,7 +1210,7 @@ Simulator::checkICacheLocked(Simulator::ICacheMap& i_cache, SimInstruction* inst
// It is safe for the signal to arrive during the !cache_hit path, since it
// will be cleared the next time this function is called.
if (cacheInvalidatedBySignalHandler_) {
i_cache.clear();
icache().clear();
cacheInvalidatedBySignalHandler_ = false;
return;
}
@ -1240,32 +1225,29 @@ Simulator::checkICacheLocked(Simulator::ICacheMap& i_cache, SimInstruction* inst
}
HashNumber
Simulator::ICacheHasher::hash(const Lookup& l)
SimulatorProcess::ICacheHasher::hash(const Lookup& l)
{
return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(l)) >> 2;
}
bool
Simulator::ICacheHasher::match(const Key& k, const Lookup& l)
SimulatorProcess::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);
return k == l;
}
void
Simulator::FlushICache(void* start_addr, size_t size)
/* static */ void
SimulatorProcess::FlushICache(void* start_addr, size_t size)
{
if (Simulator::ICacheCheckingEnabled) {
Simulator* sim = Simulator::Current();
AutoLockSimulatorCache als(sim);
js::jit::FlushICacheLocked(sim->icache(), start_addr, size);
if (!ICacheCheckingDisableCount) {
AutoLockSimulatorCache als;
js::jit::FlushICacheLocked(icache(), start_addr, size);
}
}
Simulator::Simulator()
: cacheLock_(mutexid::SimulatorCacheLock),
cacheInvalidatedBySignalHandler_(false)
{
// Set up simulator support first. Some of this information is needed to
// setup the architecture state.
@ -1301,16 +1283,11 @@ Simulator::Simulator()
exceptions[i] = 0;
lastDebuggerInput_ = nullptr;
redirection_ = nullptr;
}
bool
Simulator::init()
{
if (!icache_.init())
return false;
// 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));
@ -1338,19 +1315,21 @@ Simulator::init()
// offset from the swi instruction so the simulator knows what to call.
class Redirection
{
friend class Simulator;
friend class SimulatorProcess;
// sim's lock must already be held.
Redirection(void* nativeFunction, ABIFunctionType type, Simulator* sim)
Redirection(void* nativeFunction, ABIFunctionType type)
: nativeFunction_(nativeFunction),
swiInstruction_(kCallRedirInstr),
type_(type),
next_(nullptr)
{
next_ = sim->redirection();
if (Simulator::ICacheCheckingEnabled)
FlushICacheLocked(sim->icache(), addressOfSwiInstruction(), SimInstruction::kInstrSize);
sim->setRedirection(this);
next_ = SimulatorProcess::redirection();
if (!SimulatorProcess::ICacheCheckingDisableCount) {
FlushICacheLocked(SimulatorProcess::icache(), addressOfSwiInstruction(),
SimInstruction::kInstrSize);
}
SimulatorProcess::setRedirection(this);
}
public:
@ -1359,11 +1338,9 @@ class Redirection
ABIFunctionType type() const { return type_; }
static Redirection* Get(void* nativeFunction, ABIFunctionType type) {
Simulator* sim = Simulator::Current();
AutoLockSimulatorCache als;
AutoLockSimulatorCache als(sim);
Redirection* current = sim->redirection();
Redirection* current = SimulatorProcess::redirection();
for (; current != nullptr; current = current->next_) {
if (current->nativeFunction_ == nativeFunction) {
MOZ_ASSERT(current->type() == type);
@ -1377,7 +1354,7 @@ class Redirection
__FILE__, __LINE__);
MOZ_CRASH();
}
new(redir) Redirection(nativeFunction, type, sim);
new(redir) Redirection(nativeFunction, type);
return redir;
}
@ -1397,6 +1374,15 @@ class Redirection
Simulator::~Simulator()
{
js_free(stack_);
}
SimulatorProcess::SimulatorProcess()
: cacheLock_(mutexid::SimulatorCacheLock)
, redirection_(nullptr)
{}
SimulatorProcess::~SimulatorProcess()
{
Redirection* r = redirection_;
while (r) {
Redirection* next = r->next_;
@ -1405,6 +1391,15 @@ Simulator::~Simulator()
}
}
bool
SimulatorProcess::init()
{
if (getenv("MIPS_SIM_ICACHE_CHECKS"))
ICacheCheckingDisableCount = 0;
return icache_.init();
}
/* static */ void*
Simulator::RedirectNativeFunction(void* nativeFunction, ABIFunctionType type)
{
@ -1416,7 +1411,9 @@ Simulator::RedirectNativeFunction(void* nativeFunction, ABIFunctionType type)
Simulator*
Simulator::Current()
{
return TlsContext.get()->runtime()->unsafeContextFromAnyThread()->simulator();
JSContext* cx = TlsContext.get();
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
return cx->simulator();
}
// Sets the register in the architecture state. It will also deal with updating
@ -3360,9 +3357,9 @@ Simulator::decodeTypeJump(SimInstruction* instr)
void
Simulator::instructionDecode(SimInstruction* instr)
{
if (Simulator::ICacheCheckingEnabled) {
AutoLockSimulatorCache als(this);
checkICacheLocked(icache(), instr);
if (!SimulatorProcess::ICacheCheckingDisableCount) {
AutoLockSimulatorCache als;
SimulatorProcess::checkICacheLocked(instr);
}
pc_modified_ = false;

Просмотреть файл

@ -104,10 +104,9 @@ const uint32_t kMaxStopCode = 127;
typedef uint32_t Instr;
class SimInstruction;
// Per thread simulator state.
class Simulator {
friend class Redirection;
friend class MipsDebugger;
friend class AutoLockSimulatorCache;
public:
// Registers are declared in order. See "See MIPS Run Linux" chapter 2.
@ -214,8 +213,6 @@ class Simulator {
// Debugger input.
void setLastDebuggerInput(char* input);
char* lastDebuggerInput() { return lastDebuggerInput_; }
// ICache checking.
static void FlushICache(void* start, size_t size);
// Returns true if pc register contains one of the 'SpecialValues' defined
// below (bad_ra, end_sim_pc).
@ -365,6 +362,13 @@ class Simulator {
char* desc_;
};
StopCountAndDesc watchedStops_[kNumOfWatchedStops];
};
// Process wide simulator state.
class SimulatorProcess
{
friend class Redirection;
friend class AutoLockSimulatorCache;
private:
// ICache checking.
@ -378,44 +382,59 @@ class Simulator {
public:
typedef HashMap<void*, CachePage*, ICacheHasher, SystemAllocPolicy> ICacheMap;
private:
// This lock creates a critical section around 'redirection_' and
// 'icache_', which are referenced both by the execution engine
// and by the off-thread compiler (see Redirection::Get in the cpp file).
Mutex cacheLock_;
#ifdef DEBUG
mozilla::Maybe<Thread::Id> cacheLockHolder_;
#endif
static mozilla::Atomic<size_t, mozilla::ReleaseAcquire> ICacheCheckingDisableCount;
static void FlushICache(void* start, size_t size);
Redirection* redirection_;
ICacheMap icache_;
private:
// Jitcode may be rewritten from a signal handler, but is prevented from
// calling FlushICache() because the signal may arrive within the critical
// area of an AutoLockSimulatorCache. This flag instructs the Simulator
// to remove all cache entries the next time it checks, avoiding false negatives.
mozilla::Atomic<bool, mozilla::ReleaseAcquire> cacheInvalidatedBySignalHandler_;
static mozilla::Atomic<bool, mozilla::ReleaseAcquire> cacheInvalidatedBySignalHandler_;
void checkICacheLocked(ICacheMap& i_cache, SimInstruction* instr);
static void checkICacheLocked(SimInstruction* instr);
static bool initialize() {
singleton_ = js_new<SimulatorProcess>();
return singleton_ && singleton_->init();
}
static void destroy() {
js_delete(singleton_);
singleton_ = nullptr;
}
SimulatorProcess();
~SimulatorProcess();
private:
bool init();
static SimulatorProcess* singleton_;
// This lock creates a critical section around 'redirection_' and
// 'icache_', which are referenced both by the execution engine
// and by the off-thread compiler (see Redirection::Get in the cpp file).
Mutex cacheLock_;
Redirection* redirection_;
ICacheMap icache_;
public:
ICacheMap& icache() {
static ICacheMap& icache() {
// Technically we need the lock to access the innards of the
// icache, not to take its address, but the latter condition
// serves as a useful complement to the former.
MOZ_ASSERT(cacheLockHolder_.isSome());
return icache_;
MOZ_ASSERT(singleton_->cacheLock_.ownedByCurrentThread());
return singleton_->icache_;
}
Redirection* redirection() const {
MOZ_ASSERT(cacheLockHolder_.isSome());
return redirection_;
static Redirection* redirection() {
MOZ_ASSERT(singleton_->cacheLock_.ownedByCurrentThread());
return singleton_->redirection_;
}
void setRedirection(js::jit::Redirection* redirection) {
MOZ_ASSERT(cacheLockHolder_.isSome());
redirection_ = redirection;
static void setRedirection(js::jit::Redirection* redirection) {
MOZ_ASSERT(singleton_->cacheLock_.ownedByCurrentThread());
singleton_->redirection_ = redirection;
}
};

Просмотреть файл

@ -531,28 +531,16 @@ class AutoLockSimulatorCache : public LockGuard<Mutex>
using Base = LockGuard<Mutex>;
public:
explicit AutoLockSimulatorCache(Simulator* sim)
: Base(sim->cacheLock_)
, sim_(sim)
{
MOZ_ASSERT(sim_->cacheLockHolder_.isNothing());
#ifdef DEBUG
sim_->cacheLockHolder_ = mozilla::Some(ThisThread::GetId());
#endif
}
~AutoLockSimulatorCache() {
MOZ_ASSERT(sim_->cacheLockHolder_.isSome());
#ifdef DEBUG
sim_->cacheLockHolder_.reset();
#endif
}
private:
Simulator* const sim_;
explicit AutoLockSimulatorCache()
: Base(SimulatorProcess::singleton_->cacheLock_)
{}
};
bool Simulator::ICacheCheckingEnabled = false;
mozilla::Atomic<size_t, mozilla::ReleaseAcquire>
SimulatorProcess::ICacheCheckingDisableCount(1); // Checking is disabled by default.
mozilla::Atomic<bool, mozilla::ReleaseAcquire>
SimulatorProcess::cacheInvalidatedBySignalHandler_(false);
SimulatorProcess* SimulatorProcess::singleton_ = nullptr;
int64_t Simulator::StopSimAt = -1;
@ -568,9 +556,6 @@ Simulator::Create(JSContext* cx)
return nullptr;
}
if (getenv("MIPS_SIM_ICACHE_CHECKS"))
Simulator::ICacheCheckingEnabled = true;
int64_t stopAt;
char* stopAtStr = getenv("MIPS_SIM_STOP_AT");
if (stopAtStr && sscanf(stopAtStr, "%" PRIi64, &stopAt) == 1) {
@ -1159,9 +1144,9 @@ Simulator::setLastDebuggerInput(char* input)
}
static CachePage*
GetCachePageLocked(Simulator::ICacheMap& i_cache, void* page)
GetCachePageLocked(SimulatorProcess::ICacheMap& i_cache, void* page)
{
Simulator::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
SimulatorProcess::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
if (p)
return p->value();
@ -1173,7 +1158,7 @@ GetCachePageLocked(Simulator::ICacheMap& i_cache, void* page)
// Flush from start up to and not including start + size.
static void
FlushOnePageLocked(Simulator::ICacheMap& i_cache, intptr_t start, int size)
FlushOnePageLocked(SimulatorProcess::ICacheMap& i_cache, intptr_t start, int size)
{
MOZ_ASSERT(size <= CachePage::kPageSize);
MOZ_ASSERT(AllOnOnePage(start, size - 1));
@ -1187,7 +1172,7 @@ FlushOnePageLocked(Simulator::ICacheMap& i_cache, intptr_t start, int size)
}
static void
FlushICacheLocked(Simulator::ICacheMap& i_cache, void* start_addr, size_t size)
FlushICacheLocked(SimulatorProcess::ICacheMap& i_cache, void* start_addr, size_t size)
{
intptr_t start = reinterpret_cast<intptr_t>(start_addr);
int intra_line = (start & CachePage::kLineMask);
@ -1207,14 +1192,14 @@ FlushICacheLocked(Simulator::ICacheMap& i_cache, void* start_addr, size_t size)
FlushOnePageLocked(i_cache, start, size);
}
void
Simulator::checkICacheLocked(Simulator::ICacheMap& i_cache, SimInstruction* instr)
/* static */ void
SimulatorProcess::checkICacheLocked(SimInstruction* instr)
{
intptr_t address = reinterpret_cast<intptr_t>(instr);
void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
int offset = (address & CachePage::kPageMask);
CachePage* cache_page = GetCachePageLocked(i_cache, page);
CachePage* cache_page = GetCachePageLocked(icache(), page);
char* cache_valid_byte = cache_page->validityByte(offset);
bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
char* cached_line = cache_page->cachedData(offset & ~CachePage::kLineMask);
@ -1232,7 +1217,7 @@ Simulator::checkICacheLocked(Simulator::ICacheMap& i_cache, SimInstruction* inst
// It is safe for the signal to arrive during the !cache_hit path, since it
// will be cleared the next time this function is called.
if (cacheInvalidatedBySignalHandler_) {
i_cache.clear();
icache().clear();
cacheInvalidatedBySignalHandler_ = false;
return;
}
@ -1247,32 +1232,29 @@ Simulator::checkICacheLocked(Simulator::ICacheMap& i_cache, SimInstruction* inst
}
HashNumber
Simulator::ICacheHasher::hash(const Lookup& l)
SimulatorProcess::ICacheHasher::hash(const Lookup& l)
{
return U32(reinterpret_cast<uintptr_t>(l)) >> 2;
}
bool
Simulator::ICacheHasher::match(const Key& k, const Lookup& l)
SimulatorProcess::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);
return k == l;
}
void
Simulator::FlushICache(void* start_addr, size_t size)
/* static */ void
SimulatorProcess::FlushICache(void* start_addr, size_t size)
{
if (Simulator::ICacheCheckingEnabled) {
Simulator* sim = Simulator::Current();
AutoLockSimulatorCache als(sim);
js::jit::FlushICacheLocked(sim->icache(), start_addr, size);
if (!ICacheCheckingDisableCount) {
AutoLockSimulatorCache als;
js::jit::FlushICacheLocked(icache(), start_addr, size);
}
}
Simulator::Simulator()
: cacheLock_(mutexid::SimulatorCacheLock),
cacheInvalidatedBySignalHandler_(false)
{
// Set up simulator support first. Some of this information is needed to
// setup the architecture state.
@ -1309,16 +1291,11 @@ Simulator::Simulator()
exceptions[i] = 0;
lastDebuggerInput_ = nullptr;
redirection_ = nullptr;
}
bool
Simulator::init()
{
if (!icache_.init())
return false;
// 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));
@ -1346,19 +1323,21 @@ Simulator::init()
// offset from the swi instruction so the simulator knows what to call.
class Redirection
{
friend class Simulator;
friend class SimulatorProcess;
// sim's lock must already be held.
Redirection(void* nativeFunction, ABIFunctionType type, Simulator* sim)
Redirection(void* nativeFunction, ABIFunctionType type)
: nativeFunction_(nativeFunction),
swiInstruction_(kCallRedirInstr),
type_(type),
next_(nullptr)
{
next_ = sim->redirection();
if (Simulator::ICacheCheckingEnabled)
FlushICacheLocked(sim->icache(), addressOfSwiInstruction(), SimInstruction::kInstrSize);
sim->setRedirection(this);
next_ = SimulatorProcess::redirection();
if (!SimulatorProcess::ICacheCheckingDisableCount) {
FlushICacheLocked(SimulatorProcess::icache(), addressOfSwiInstruction(),
SimInstruction::kInstrSize);
}
SimulatorProcess::setRedirection(this);
}
public:
@ -1367,11 +1346,9 @@ class Redirection
ABIFunctionType type() const { return type_; }
static Redirection* Get(void* nativeFunction, ABIFunctionType type) {
Simulator* sim = Simulator::Current();
AutoLockSimulatorCache als;
AutoLockSimulatorCache als(sim);
Redirection* current = sim->redirection();
Redirection* current = SimulatorProcess::redirection();
for (; current != nullptr; current = current->next_) {
if (current->nativeFunction_ == nativeFunction) {
MOZ_ASSERT(current->type() == type);
@ -1385,7 +1362,7 @@ class Redirection
__FILE__, __LINE__);
MOZ_CRASH();
}
new(redir) Redirection(nativeFunction, type, sim);
new(redir) Redirection(nativeFunction, type);
return redir;
}
@ -1405,6 +1382,15 @@ class Redirection
Simulator::~Simulator()
{
js_free(stack_);
}
SimulatorProcess::SimulatorProcess()
: cacheLock_(mutexid::SimulatorCacheLock)
, redirection_(nullptr)
{}
SimulatorProcess::~SimulatorProcess()
{
Redirection* r = redirection_;
while (r) {
Redirection* next = r->next_;
@ -1413,6 +1399,15 @@ Simulator::~Simulator()
}
}
bool
SimulatorProcess::init()
{
if (getenv("MIPS_SIM_ICACHE_CHECKS"))
ICacheCheckingDisableCount = 0;
return icache_.init();
}
/* static */ void*
Simulator::RedirectNativeFunction(void* nativeFunction, ABIFunctionType type)
{
@ -1424,7 +1419,9 @@ Simulator::RedirectNativeFunction(void* nativeFunction, ABIFunctionType type)
Simulator*
Simulator::Current()
{
return TlsContext.get()->runtime()->unsafeContextFromAnyThread()->simulator();
JSContext* cx = TlsContext.get();
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
return cx->simulator();
}
// Sets the register in the architecture state. It will also deal with updating
@ -3654,9 +3651,9 @@ Simulator::decodeTypeJump(SimInstruction* instr)
void
Simulator::instructionDecode(SimInstruction* instr)
{
if (Simulator::ICacheCheckingEnabled) {
AutoLockSimulatorCache als(this);
checkICacheLocked(icache(), instr);
if (!SimulatorProcess::ICacheCheckingDisableCount) {
AutoLockSimulatorCache als;
SimulatorProcess::checkICacheLocked(instr);
}
pc_modified_ = false;

Просмотреть файл

@ -110,10 +110,9 @@ const uint32_t kMaxStopCode = 127;
typedef uint32_t Instr;
class SimInstruction;
// Per thread simulator state.
class Simulator {
friend class Redirection;
friend class MipsDebugger;
friend class AutoLockSimulatorCache;
public:
// Registers are declared in order. See "See MIPS Run Linux" chapter 2.
@ -222,8 +221,6 @@ class Simulator {
// Debugger input.
void setLastDebuggerInput(char* input);
char* lastDebuggerInput() { return lastDebuggerInput_; }
// ICache checking.
static void FlushICache(void* start, size_t size);
// Returns true if pc register contains one of the 'SpecialValues' defined
// below (bad_ra, end_sim_pc).
@ -307,8 +304,6 @@ class Simulator {
void branchDelayInstructionDecode(SimInstruction* instr);
public:
static bool ICacheCheckingEnabled;
static int64_t StopSimAt;
// Runtime call support.
@ -381,6 +376,13 @@ class Simulator {
char* desc_;
};
StopCountAndDesc watchedStops_[kNumOfWatchedStops];
};
// Process wide simulator state.
class SimulatorProcess
{
friend class Redirection;
friend class AutoLockSimulatorCache;
private:
// ICache checking.
@ -394,48 +396,63 @@ class Simulator {
public:
typedef HashMap<void*, CachePage*, ICacheHasher, SystemAllocPolicy> ICacheMap;
private:
// This lock creates a critical section around 'redirection_' and
// 'icache_', which are referenced both by the execution engine
// and by the off-thread compiler (see Redirection::Get in the cpp file).
Mutex cacheLock_;
#ifdef DEBUG
mozilla::Maybe<Thread::Id> cacheLockHolder_;
#endif
static mozilla::Atomic<size_t, mozilla::ReleaseAcquire> ICacheCheckingDisableCount;
static void FlushICache(void* start, size_t size);
Redirection* redirection_;
ICacheMap icache_;
private:
// Jitcode may be rewritten from a signal handler, but is prevented from
// calling FlushICache() because the signal may arrive within the critical
// area of an AutoLockSimulatorCache. This flag instructs the Simulator
// to remove all cache entries the next time it checks, avoiding false negatives.
mozilla::Atomic<bool, mozilla::ReleaseAcquire> cacheInvalidatedBySignalHandler_;
static mozilla::Atomic<bool, mozilla::ReleaseAcquire> cacheInvalidatedBySignalHandler_;
void checkICacheLocked(ICacheMap& i_cache, SimInstruction* instr);
static void checkICacheLocked(SimInstruction* instr);
static bool initialize() {
singleton_ = js_new<SimulatorProcess>();
return singleton_ && singleton_->init();
}
static void destroy() {
js_delete(singleton_);
singleton_ = nullptr;
}
SimulatorProcess();
~SimulatorProcess();
private:
bool init();
static SimulatorProcess* singleton_;
// This lock creates a critical section around 'redirection_' and
// 'icache_', which are referenced both by the execution engine
// and by the off-thread compiler (see Redirection::Get in the cpp file).
Mutex cacheLock_;
Redirection* redirection_;
ICacheMap icache_;
public:
ICacheMap& icache() {
static ICacheMap& icache() {
// Technically we need the lock to access the innards of the
// icache, not to take its address, but the latter condition
// serves as a useful complement to the former.
MOZ_ASSERT(cacheLockHolder_.isSome());
return icache_;
MOZ_ASSERT(singleton_->cacheLock_.ownedByCurrentThread());
return singleton_->icache_;
}
Redirection* redirection() const {
MOZ_ASSERT(cacheLockHolder_.isSome());
return redirection_;
static Redirection* redirection() {
MOZ_ASSERT(singleton_->cacheLock_.ownedByCurrentThread());
return singleton_->redirection_;
}
void setRedirection(js::jit::Redirection* redirection) {
MOZ_ASSERT(cacheLockHolder_.isSome());
redirection_ = redirection;
static void setRedirection(js::jit::Redirection* redirection) {
MOZ_ASSERT(singleton_->cacheLock_.ownedByCurrentThread());
singleton_->redirection_ = redirection;
}
};
#define JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, onerror) \
#define JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, onerror) \
JS_BEGIN_MACRO \
if (cx->simulator()->overRecursedWithExtra(extra)) { \
js::ReportOverRecursed(cx); \

Просмотреть файл

@ -7661,7 +7661,7 @@ SetContextOptions(JSContext* cx, const OptionParser& op)
#if defined(JS_SIMULATOR_ARM)
if (op.getBoolOption("arm-sim-icache-checks"))
jit::Simulator::ICacheCheckingEnabled = true;
jit::SimulatorProcess::ICacheCheckingDisableCount = 0;
int32_t stopAt = op.getIntOption("arm-sim-stop-at");
if (stopAt >= 0)

Просмотреть файл

@ -19,6 +19,7 @@
#include "gc/Statistics.h"
#include "jit/ExecutableAllocator.h"
#include "jit/Ion.h"
#include "jit/JitCommon.h"
#include "js/Utility.h"
#if ENABLE_INTL_API
#include "unicode/uclean.h"
@ -123,6 +124,10 @@ JS::detail::InitWithFailureDiagnostic(bool isDebugBuild)
RETURN_IF_FAIL(FutexThread::initialize());
RETURN_IF_FAIL(js::gcstats::Statistics::initialize());
#ifdef JS_SIMULATOR
RETURN_IF_FAIL(js::jit::SimulatorProcess::initialize());
#endif
libraryInitState = InitState::Running;
return nullptr;
}
@ -148,6 +153,10 @@ JS_ShutDown(void)
js::DestroyHelperThreadsState();
#ifdef JS_SIMULATOR
js::jit::SimulatorProcess::destroy();
#endif
#ifdef JS_TRACE_LOGGING
js::DestroyTraceLoggerThreadState();
js::DestroyTraceLoggerGraphState();

Просмотреть файл

@ -1274,15 +1274,14 @@ JitInterruptHandler(int signum, siginfo_t* info, void* context)
if (JSContext* cx = TlsContext.get()) {
#if defined(JS_SIMULATOR_ARM) || defined(JS_SIMULATOR_MIPS32) || defined(JS_SIMULATOR_MIPS64)
bool prevICacheCheckingState = Simulator::ICacheCheckingEnabled;
Simulator::ICacheCheckingEnabled = false;
SimulatorProcess::ICacheCheckingDisableCount++;
#endif
RedirectJitCodeToInterruptCheck(cx, (CONTEXT*)context);
#if defined(JS_SIMULATOR_ARM) || defined(JS_SIMULATOR_MIPS32) || defined(JS_SIMULATOR_MIPS64)
Simulator::ICacheCheckingEnabled = prevICacheCheckingState;
cx->simulator()->cacheInvalidatedBySignalHandler_ = true;
SimulatorProcess::cacheInvalidatedBySignalHandler_ = true;
SimulatorProcess::ICacheCheckingDisableCount--;
#endif
cx->finishHandlingJitInterrupt();