Commit 5e9db683 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

no longer need a guard in StackTraceStack

Summary:
The guard targets its former use in `__thread` variables, which must be trivial. But it is now used in `thread_local` variables, which can have default constructors.

The relevant switch from `__thread` to `thread_local` was in {D27559375 (https://github.com/facebook/folly/commit/eeec4600b857dd70ca6b30837d14bb79cf9a2ef7)}.

Reviewed By: luciang

Differential Revision: D28683625

fbshipit-source-id: af74801a13e479a262ea50e6d3f89053e67d7ac9
parent a73640d7
......@@ -47,7 +47,6 @@ void StackTraceStack::Node::deallocate() {
}
bool StackTraceStack::pushCurrent() {
checkGuard();
auto node = Node::allocate();
if (!node) {
// cannot allocate memory
......@@ -61,61 +60,54 @@ bool StackTraceStack::pushCurrent() {
}
node->frameCount = n;
node->next = state_[kTopIdx];
state_[kTopIdx] = node;
node->next = state_;
state_ = node;
return true;
}
bool StackTraceStack::pop() {
checkGuard();
if (!state_[kTopIdx]) {
if (!state_) {
return false;
}
auto node = state_[kTopIdx];
state_[kTopIdx] = node->next;
auto node = state_;
state_ = node->next;
node->deallocate();
return true;
}
bool StackTraceStack::moveTopFrom(StackTraceStack& other) {
checkGuard();
if (!other.state_[kTopIdx]) {
if (!other.state_) {
return false;
}
auto node = other.state_[kTopIdx];
other.state_[kTopIdx] = node->next;
node->next = state_[kTopIdx];
state_[kTopIdx] = node;
auto node = other.state_;
other.state_ = node->next;
node->next = state_;
state_ = node;
return true;
}
void StackTraceStack::clear() {
checkGuard();
while (state_[kTopIdx]) {
while (state_) {
pop();
}
}
StackTrace* StackTraceStack::top() {
checkGuard();
return state_[kTopIdx];
return state_;
}
const StackTrace* StackTraceStack::top() const {
checkGuard();
return state_[kTopIdx];
return state_;
}
StackTrace* StackTraceStack::next(StackTrace* p) {
checkGuard();
assert(p);
return static_cast<Node*>(p)->next;
}
const StackTrace* StackTraceStack::next(const StackTrace* p) const {
checkGuard();
assert(p);
return static_cast<const Node*>(p)->next;
}
......
......@@ -34,12 +34,15 @@ struct StackTrace {
uintptr_t addresses[kMaxFrames];
};
// note: no constructor so this can be __thread.
// A StackTraceStack MUST be placed in zero-initialized memory.
class StackTraceStack {
class Node;
public:
StackTraceStack() = default;
StackTraceStack(const StackTraceStack&) = delete;
void operator=(const StackTraceStack&) = delete;
/**
* Push the current stack trace onto the stack.
* Returns false on failure (not enough memory, getting stack trace failed),
......@@ -68,7 +71,7 @@ class StackTraceStack {
/**
* Is the stack empty?
*/
bool empty() const { return !state_[kTopIdx]; }
bool empty() const { return !state_; }
/**
* Return the top stack trace, or nullptr if the stack is empty.
......@@ -84,13 +87,7 @@ class StackTraceStack {
const StackTrace* next(const StackTrace* p) const;
private:
static constexpr size_t kTopIdx = kIsDebug ? 1 : 0;
// In debug mode, we assert that we're in zero-initialized memory by
// checking that the two guards around the Node* from top() are zero.
void checkGuard() const { assert(state_[0] == 0 && state_[2] == 0); }
Node* state_[kIsDebug ? 3 : 1];
Node* state_ = nullptr;
};
} // namespace exception_tracer
} // namespace folly
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment