Make climit and jslimit stack limits atomic.
This fixes TSAN failure caused by race between: - optimizing compiler thread setting climit - and json parser reading climit in the main thread. BUG= Review URL: https://codereview.chromium.org/1031223004 Cr-Commit-Position: refs/heads/master@{#27840}
This commit is contained in:
parent
dd06f905cb
commit
3a814e4c1a
@ -20,16 +20,16 @@ StackGuard::StackGuard()
|
||||
|
||||
void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) {
|
||||
DCHECK(isolate_ != NULL);
|
||||
thread_local_.jslimit_ = kInterruptLimit;
|
||||
thread_local_.climit_ = kInterruptLimit;
|
||||
thread_local_.set_jslimit(kInterruptLimit);
|
||||
thread_local_.set_climit(kInterruptLimit);
|
||||
isolate_->heap()->SetStackLimits();
|
||||
}
|
||||
|
||||
|
||||
void StackGuard::reset_limits(const ExecutionAccess& lock) {
|
||||
DCHECK(isolate_ != NULL);
|
||||
thread_local_.jslimit_ = thread_local_.real_jslimit_;
|
||||
thread_local_.climit_ = thread_local_.real_climit_;
|
||||
thread_local_.set_jslimit(thread_local_.real_jslimit_);
|
||||
thread_local_.set_climit(thread_local_.real_climit_);
|
||||
isolate_->heap()->SetStackLimits();
|
||||
}
|
||||
|
||||
@ -354,11 +354,11 @@ void StackGuard::SetStackLimit(uintptr_t limit) {
|
||||
// If the current limits are special (e.g. due to a pending interrupt) then
|
||||
// leave them alone.
|
||||
uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
|
||||
if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
|
||||
thread_local_.jslimit_ = jslimit;
|
||||
if (thread_local_.jslimit() == thread_local_.real_jslimit_) {
|
||||
thread_local_.set_jslimit(jslimit);
|
||||
}
|
||||
if (thread_local_.climit_ == thread_local_.real_climit_) {
|
||||
thread_local_.climit_ = limit;
|
||||
if (thread_local_.climit() == thread_local_.real_climit_) {
|
||||
thread_local_.set_climit(limit);
|
||||
}
|
||||
thread_local_.real_climit_ = limit;
|
||||
thread_local_.real_jslimit_ = jslimit;
|
||||
@ -474,9 +474,9 @@ void StackGuard::FreeThreadResources() {
|
||||
|
||||
void StackGuard::ThreadLocal::Clear() {
|
||||
real_jslimit_ = kIllegalLimit;
|
||||
jslimit_ = kIllegalLimit;
|
||||
set_jslimit(kIllegalLimit);
|
||||
real_climit_ = kIllegalLimit;
|
||||
climit_ = kIllegalLimit;
|
||||
set_climit(kIllegalLimit);
|
||||
postpone_interrupts_ = NULL;
|
||||
interrupt_flags_ = 0;
|
||||
}
|
||||
@ -489,9 +489,9 @@ bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
|
||||
DCHECK(GetCurrentStackPosition() > kLimitSize);
|
||||
uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
|
||||
real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
|
||||
jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
|
||||
set_jslimit(SimulatorStack::JsLimitFromCLimit(isolate, limit));
|
||||
real_climit_ = limit;
|
||||
climit_ = limit;
|
||||
set_climit(limit);
|
||||
should_set_stack_limits = true;
|
||||
}
|
||||
postpone_interrupts_ = NULL;
|
||||
|
@ -171,18 +171,14 @@ class StackGuard FINAL {
|
||||
#undef V
|
||||
};
|
||||
|
||||
uintptr_t climit() { return thread_local_.climit(); }
|
||||
uintptr_t jslimit() { return thread_local_.jslimit(); }
|
||||
// This provides an asynchronous read of the stack limits for the current
|
||||
// thread. There are no locks protecting this, but it is assumed that you
|
||||
// have the global V8 lock if you are using multiple V8 threads.
|
||||
uintptr_t climit() {
|
||||
return thread_local_.climit_;
|
||||
}
|
||||
uintptr_t real_climit() {
|
||||
return thread_local_.real_climit_;
|
||||
}
|
||||
uintptr_t jslimit() {
|
||||
return thread_local_.jslimit_;
|
||||
}
|
||||
uintptr_t real_jslimit() {
|
||||
return thread_local_.real_jslimit_;
|
||||
}
|
||||
@ -256,9 +252,27 @@ class StackGuard FINAL {
|
||||
// fail. Both the generated code and the runtime system check against the
|
||||
// one without the real_ prefix.
|
||||
uintptr_t real_jslimit_; // Actual JavaScript stack limit set for the VM.
|
||||
uintptr_t jslimit_;
|
||||
uintptr_t real_climit_; // Actual C++ stack limit set for the VM.
|
||||
uintptr_t climit_;
|
||||
|
||||
// jslimit_ and climit_ can be read without any lock.
|
||||
// Writing requires the ExecutionAccess lock.
|
||||
base::AtomicWord jslimit_;
|
||||
base::AtomicWord climit_;
|
||||
|
||||
uintptr_t jslimit() {
|
||||
return bit_cast<uintptr_t>(base::NoBarrier_Load(&jslimit_));
|
||||
}
|
||||
void set_jslimit(uintptr_t limit) {
|
||||
return base::NoBarrier_Store(&jslimit_,
|
||||
static_cast<base::AtomicWord>(limit));
|
||||
}
|
||||
uintptr_t climit() {
|
||||
return bit_cast<uintptr_t>(base::NoBarrier_Load(&climit_));
|
||||
}
|
||||
void set_climit(uintptr_t limit) {
|
||||
return base::NoBarrier_Store(&climit_,
|
||||
static_cast<base::AtomicWord>(limit));
|
||||
}
|
||||
|
||||
PostponeInterruptsScope* postpone_interrupts_;
|
||||
int interrupt_flags_;
|
||||
|
Loading…
Reference in New Issue
Block a user