[utils] Move ThreadedList into own header
Change-Id: I49a4e9740f6a3715ca5cdafd121b3b99fed8dc6b Reviewed-on: https://chromium-review.googlesource.com/1245428 Reviewed-by: Igor Sheludko <ishell@chromium.org> Reviewed-by: Marja Hölttä <marja@chromium.org> Commit-Queue: Florian Sattler <sattlerf@google.com> Cr-Commit-Position: refs/heads/master@{#56267}
This commit is contained in:
parent
0714bd9fa0
commit
56c832a5a5
@ -383,7 +383,7 @@ class DoExpression final : public Expression {
|
||||
|
||||
class Declaration : public AstNode {
|
||||
public:
|
||||
typedef ThreadedList<Declaration> List;
|
||||
typedef base::ThreadedList<Declaration> List;
|
||||
|
||||
VariableProxy* proxy() const { return proxy_; }
|
||||
|
||||
@ -397,7 +397,7 @@ class Declaration : public AstNode {
|
||||
Declaration** next() { return &next_; }
|
||||
Declaration* next_;
|
||||
friend List;
|
||||
friend ThreadedListTraits<Declaration>;
|
||||
friend base::ThreadedListTraits<Declaration>;
|
||||
};
|
||||
|
||||
class VariableDeclaration : public Declaration {
|
||||
@ -1627,7 +1627,7 @@ class VariableProxy final : public Expression {
|
||||
VariableProxy** pre_parser_expr_next() { return &pre_parser_expr_next_; }
|
||||
VariableProxy* pre_parser_expr_next_;
|
||||
|
||||
friend ThreadedListTraits<VariableProxy>;
|
||||
friend base::ThreadedListTraits<VariableProxy>;
|
||||
};
|
||||
|
||||
// Left-hand side can only be a property, a global or a (parameter or local)
|
||||
|
@ -1536,7 +1536,7 @@ void DeclarationScope::SavePreParsedScopeDataForDeclarationScope() {
|
||||
|
||||
void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) {
|
||||
DCHECK(!force_eager_compilation_);
|
||||
ThreadedList<VariableProxy> new_unresolved_list;
|
||||
base::ThreadedList<VariableProxy> new_unresolved_list;
|
||||
if (!IsArrowFunction(function_kind_) &&
|
||||
(!outer_scope_->is_script_scope() ||
|
||||
(FLAG_preparser_scope_analysis &&
|
||||
|
@ -123,8 +123,8 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
|
||||
Scope* outer_scope_;
|
||||
Scope* top_inner_scope_;
|
||||
VariableProxy* top_unresolved_;
|
||||
ThreadedList<Variable>::Iterator top_local_;
|
||||
ThreadedList<Declaration>::Iterator top_decl_;
|
||||
base::ThreadedList<Variable>::Iterator top_local_;
|
||||
base::ThreadedList<Declaration>::Iterator top_decl_;
|
||||
const bool outer_scope_calls_eval_;
|
||||
};
|
||||
|
||||
@ -201,9 +201,9 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
|
||||
void DeclareCatchVariableName(const AstRawString* name);
|
||||
|
||||
// Declarations list.
|
||||
ThreadedList<Declaration>* declarations() { return &decls_; }
|
||||
base::ThreadedList<Declaration>* declarations() { return &decls_; }
|
||||
|
||||
ThreadedList<Variable>* locals() { return &locals_; }
|
||||
base::ThreadedList<Variable>* locals() { return &locals_; }
|
||||
|
||||
// Create a new unresolved variable.
|
||||
VariableProxy* NewUnresolved(AstNodeFactory* factory,
|
||||
@ -522,12 +522,12 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
|
||||
VariableMap variables_;
|
||||
// In case of non-scopeinfo-backed scopes, this contains the variables of the
|
||||
// map above in order of addition.
|
||||
ThreadedList<Variable> locals_;
|
||||
base::ThreadedList<Variable> locals_;
|
||||
// Unresolved variables referred to from this scope. The proxies themselves
|
||||
// form a linked list of all unresolved proxies.
|
||||
ThreadedList<VariableProxy> unresolved_list_;
|
||||
base::ThreadedList<VariableProxy> unresolved_list_;
|
||||
// Declarations.
|
||||
ThreadedList<Declaration> decls_;
|
||||
base::ThreadedList<Declaration> decls_;
|
||||
|
||||
// Serialized scope info support.
|
||||
Handle<ScopeInfo> scope_info_;
|
||||
|
@ -181,7 +181,7 @@ class Variable final : public ZoneObject {
|
||||
: kNeedsInitialization;
|
||||
}
|
||||
|
||||
typedef ThreadedList<Variable> List;
|
||||
typedef base::ThreadedList<Variable> List;
|
||||
|
||||
private:
|
||||
Scope* scope_;
|
||||
@ -215,7 +215,7 @@ class Variable final : public ZoneObject {
|
||||
ForceHoleInitializationField::kNext, 1> {};
|
||||
Variable** next() { return &next_; }
|
||||
friend List;
|
||||
friend ThreadedListTraits<Variable>;
|
||||
friend base::ThreadedListTraits<Variable>;
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
267
src/base/threaded-list.h
Normal file
267
src/base/threaded-list.h
Normal file
@ -0,0 +1,267 @@
|
||||
// Copyright 2018 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_BASE_THREADED_LIST_H_
|
||||
#define V8_BASE_THREADED_LIST_H_
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include "src/base/compiler-specific.h"
|
||||
#include "src/base/macros.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace base {
|
||||
|
||||
template <typename T>
|
||||
struct ThreadedListTraits {
|
||||
static T** next(T* t) { return t->next(); }
|
||||
};
|
||||
|
||||
// Represents a linked list that threads through the nodes in the linked list.
|
||||
// Entries in the list are pointers to nodes. By default nodes need to have a
|
||||
// T** next() method that returns the location where the next value is stored.
|
||||
// The default can be overwritten by providing a ThreadedTraits class.
|
||||
template <typename T, typename BaseClass,
|
||||
typename TLTraits = ThreadedListTraits<T>>
|
||||
class ThreadedListBase final : public BaseClass {
|
||||
public:
|
||||
ThreadedListBase() : head_(nullptr), tail_(&head_) {}
|
||||
void Add(T* v) {
|
||||
DCHECK_NULL(*tail_);
|
||||
DCHECK_NULL(*TLTraits::next(v));
|
||||
*tail_ = v;
|
||||
tail_ = TLTraits::next(v);
|
||||
}
|
||||
|
||||
void AddFront(T* v) {
|
||||
DCHECK_NULL(*TLTraits::next(v));
|
||||
DCHECK_NOT_NULL(v);
|
||||
T** const next = TLTraits::next(v);
|
||||
|
||||
*next = head_;
|
||||
if (head_ == nullptr) tail_ = next;
|
||||
head_ = v;
|
||||
}
|
||||
|
||||
// Reinitializing the head to a new node, this costs O(n).
|
||||
void ReinitializeHead(T* v) {
|
||||
head_ = v;
|
||||
T* current = v;
|
||||
if (current != nullptr) { // Find tail
|
||||
T* tmp;
|
||||
while ((tmp = *TLTraits::next(current))) {
|
||||
current = tmp;
|
||||
}
|
||||
tail_ = TLTraits::next(current);
|
||||
} else {
|
||||
tail_ = &head_;
|
||||
}
|
||||
}
|
||||
|
||||
void DropHead() {
|
||||
DCHECK_NOT_NULL(head_);
|
||||
|
||||
T* old_head = head_;
|
||||
head_ = *TLTraits::next(head_);
|
||||
if (head_ == nullptr) tail_ = &head_;
|
||||
*TLTraits::next(old_head) = nullptr;
|
||||
}
|
||||
|
||||
void Append(ThreadedListBase&& list) {
|
||||
*tail_ = list.head_;
|
||||
tail_ = list.tail_;
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
void Prepend(ThreadedListBase&& list) {
|
||||
if (list.head_ == nullptr) return;
|
||||
|
||||
T* new_head = list.head_;
|
||||
*list.tail_ = head_;
|
||||
if (head_ == nullptr) {
|
||||
tail_ = list.tail_;
|
||||
}
|
||||
head_ = new_head;
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
head_ = nullptr;
|
||||
tail_ = &head_;
|
||||
}
|
||||
|
||||
ThreadedListBase& operator=(ThreadedListBase&& other) V8_NOEXCEPT {
|
||||
head_ = other.head_;
|
||||
tail_ = other.head_ ? other.tail_ : &head_;
|
||||
#ifdef DEBUG
|
||||
other.Clear();
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
ThreadedListBase(ThreadedListBase&& other) V8_NOEXCEPT
|
||||
: head_(other.head_),
|
||||
tail_(other.head_ ? other.tail_ : &head_) {
|
||||
#ifdef DEBUG
|
||||
other.Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Remove(T* v) {
|
||||
T* current = first();
|
||||
if (current == v) {
|
||||
DropHead();
|
||||
return true;
|
||||
}
|
||||
|
||||
while (current != nullptr) {
|
||||
T* next = *TLTraits::next(current);
|
||||
if (next == v) {
|
||||
*TLTraits::next(current) = *TLTraits::next(next);
|
||||
*TLTraits::next(next) = nullptr;
|
||||
|
||||
if (TLTraits::next(next) == tail_) {
|
||||
tail_ = TLTraits::next(current);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
current = next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class Iterator final {
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = T*;
|
||||
using reference = value_type;
|
||||
using pointer = value_type*;
|
||||
|
||||
public:
|
||||
Iterator& operator++() {
|
||||
entry_ = TLTraits::next(*entry_);
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const Iterator& other) const {
|
||||
return entry_ == other.entry_;
|
||||
}
|
||||
bool operator!=(const Iterator& other) const {
|
||||
return entry_ != other.entry_;
|
||||
}
|
||||
T* operator*() { return *entry_; }
|
||||
T* operator->() { return *entry_; }
|
||||
Iterator& operator=(T* entry) {
|
||||
T* next = *TLTraits::next(*entry_);
|
||||
*TLTraits::next(entry) = next;
|
||||
*entry_ = entry;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit Iterator(T** entry) : entry_(entry) {}
|
||||
|
||||
T** entry_;
|
||||
|
||||
friend class ThreadedListBase;
|
||||
};
|
||||
|
||||
class ConstIterator final {
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = T*;
|
||||
using reference = const value_type;
|
||||
using pointer = const value_type*;
|
||||
|
||||
public:
|
||||
ConstIterator& operator++() {
|
||||
entry_ = TLTraits::next(*entry_);
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const ConstIterator& other) const {
|
||||
return entry_ == other.entry_;
|
||||
}
|
||||
bool operator!=(const ConstIterator& other) const {
|
||||
return entry_ != other.entry_;
|
||||
}
|
||||
const T* operator*() const { return *entry_; }
|
||||
|
||||
private:
|
||||
explicit ConstIterator(T* const* entry) : entry_(entry) {}
|
||||
|
||||
T* const* entry_;
|
||||
|
||||
friend class ThreadedListBase;
|
||||
};
|
||||
|
||||
Iterator begin() { return Iterator(&head_); }
|
||||
Iterator end() { return Iterator(tail_); }
|
||||
|
||||
ConstIterator begin() const { return ConstIterator(&head_); }
|
||||
ConstIterator end() const { return ConstIterator(tail_); }
|
||||
|
||||
// Rewinds the list's tail to the reset point, i.e., cutting of the rest of
|
||||
// the list, including the reset_point.
|
||||
void Rewind(Iterator reset_point) {
|
||||
tail_ = reset_point.entry_;
|
||||
*tail_ = nullptr;
|
||||
}
|
||||
|
||||
// Moves the tail of the from_list, starting at the from_location, to the end
|
||||
// of this list.
|
||||
void MoveTail(ThreadedListBase* from_list, Iterator from_location) {
|
||||
if (from_list->end() != from_location) {
|
||||
DCHECK_NULL(*tail_);
|
||||
*tail_ = *from_location;
|
||||
tail_ = from_list->tail_;
|
||||
from_list->Rewind(from_location);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_empty() const { return head_ == nullptr; }
|
||||
|
||||
T* first() const { return head_; }
|
||||
|
||||
// Slow. For testing purposes.
|
||||
int LengthForTest() {
|
||||
int result = 0;
|
||||
for (Iterator t = begin(); t != end(); ++t) ++result;
|
||||
return result;
|
||||
}
|
||||
|
||||
T* AtForTest(int i) {
|
||||
Iterator t = begin();
|
||||
while (i-- > 0) ++t;
|
||||
return *t;
|
||||
}
|
||||
|
||||
bool Verify() {
|
||||
T* last = this->first();
|
||||
if (last == nullptr) {
|
||||
CHECK_EQ(&head_, tail_);
|
||||
} else {
|
||||
while (*TLTraits::next(last) != nullptr) {
|
||||
last = *TLTraits::next(last);
|
||||
}
|
||||
CHECK_EQ(TLTraits::next(last), tail_);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
T* head_;
|
||||
T** tail_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ThreadedListBase);
|
||||
};
|
||||
|
||||
struct EmptyBase {};
|
||||
|
||||
template <typename T, typename TLTraits = ThreadedListTraits<T>>
|
||||
using ThreadedList = ThreadedListBase<T, EmptyBase, TLTraits>;
|
||||
|
||||
} // namespace base
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_BASE_THREADED_LIST_H_
|
@ -11,11 +11,11 @@
|
||||
#include "src/ast/ast.h"
|
||||
#include "src/ast/scopes.h"
|
||||
#include "src/base/compiler-specific.h"
|
||||
#include "src/base/threaded-list.h"
|
||||
#include "src/globals.h"
|
||||
#include "src/parsing/parser-base.h"
|
||||
#include "src/parsing/parsing.h"
|
||||
#include "src/parsing/preparser.h"
|
||||
#include "src/utils.h"
|
||||
#include "src/zone/zone-chunk-list.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -109,7 +109,7 @@ struct ParserFormalParameters : FormalParametersBase {
|
||||
|
||||
explicit ParserFormalParameters(DeclarationScope* scope)
|
||||
: FormalParametersBase(scope) {}
|
||||
ThreadedList<Parameter> params;
|
||||
base::ThreadedList<Parameter> params;
|
||||
};
|
||||
|
||||
template <>
|
||||
@ -921,7 +921,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
|
||||
|
||||
V8_INLINE void DeclareFormalParameters(
|
||||
DeclarationScope* scope,
|
||||
const ThreadedList<ParserFormalParameters::Parameter>& parameters,
|
||||
const base::ThreadedList<ParserFormalParameters::Parameter>& parameters,
|
||||
bool is_simple, bool* has_duplicate = nullptr) {
|
||||
if (!is_simple) scope->SetHasNonSimpleParameters();
|
||||
for (auto parameter : parameters) {
|
||||
|
@ -865,7 +865,7 @@ struct PreParserFormalParameters : FormalParametersBase {
|
||||
explicit PreParserFormalParameters(DeclarationScope* scope)
|
||||
: FormalParametersBase(scope) {}
|
||||
|
||||
ThreadedList<Parameter> params;
|
||||
base::ThreadedList<Parameter> params;
|
||||
};
|
||||
|
||||
|
||||
@ -1723,7 +1723,8 @@ class PreParser : public ParserBase<PreParser> {
|
||||
|
||||
V8_INLINE void DeclareFormalParameters(
|
||||
DeclarationScope* scope,
|
||||
const ThreadedList<PreParserFormalParameters::Parameter>& parameters,
|
||||
const base::ThreadedList<PreParserFormalParameters::Parameter>&
|
||||
parameters,
|
||||
bool is_simple) {
|
||||
if (!is_simple) scope->SetHasNonSimpleParameters();
|
||||
if (track_unresolved_variables_) {
|
||||
|
266
src/utils.h
266
src/utils.h
@ -1621,272 +1621,6 @@ static inline V ByteReverse(V value) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct ThreadedListTraits {
|
||||
static T** next(T* t) { return t->next(); }
|
||||
};
|
||||
|
||||
// Represents a linked list that threads through the nodes in the linked list.
|
||||
// Entries in the list are pointers to nodes. By default nodes need to have a
|
||||
// T** next() method that returns the location where the next value is stored.
|
||||
// The default can be overwritten by providing a ThreadedTraits class.
|
||||
template <typename T, typename BaseClass,
|
||||
typename TLTraits = ThreadedListTraits<T>>
|
||||
class ThreadedListBase final : public BaseClass {
|
||||
public:
|
||||
ThreadedListBase() : head_(nullptr), tail_(&head_) {}
|
||||
void Add(T* v) {
|
||||
DCHECK_NULL(*tail_);
|
||||
DCHECK_NULL(*TLTraits::next(v));
|
||||
*tail_ = v;
|
||||
tail_ = TLTraits::next(v);
|
||||
}
|
||||
|
||||
void AddFront(T* v) {
|
||||
DCHECK_NULL(*TLTraits::next(v));
|
||||
DCHECK_NOT_NULL(v);
|
||||
T** const next = TLTraits::next(v);
|
||||
|
||||
*next = head_;
|
||||
if (head_ == nullptr) tail_ = next;
|
||||
head_ = v;
|
||||
}
|
||||
|
||||
// Reinitializing the head to a new node, this costs O(n).
|
||||
void ReinitializeHead(T* v) {
|
||||
head_ = v;
|
||||
T* current = v;
|
||||
if (current != nullptr) { // Find tail
|
||||
T* tmp;
|
||||
while ((tmp = *TLTraits::next(current))) {
|
||||
current = tmp;
|
||||
}
|
||||
tail_ = TLTraits::next(current);
|
||||
} else {
|
||||
tail_ = &head_;
|
||||
}
|
||||
|
||||
SLOW_DCHECK(Verify());
|
||||
}
|
||||
|
||||
void DropHead() {
|
||||
DCHECK_NOT_NULL(head_);
|
||||
SLOW_DCHECK(Verify());
|
||||
|
||||
T* old_head = head_;
|
||||
head_ = *TLTraits::next(head_);
|
||||
if (head_ == nullptr) tail_ = &head_;
|
||||
*TLTraits::next(old_head) = nullptr;
|
||||
}
|
||||
|
||||
void Append(ThreadedListBase&& list) {
|
||||
SLOW_DCHECK(Verify());
|
||||
SLOW_DCHECK(list.Verify());
|
||||
|
||||
*tail_ = list.head_;
|
||||
tail_ = list.tail_;
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
void Prepend(ThreadedListBase&& list) {
|
||||
SLOW_DCHECK(Verify());
|
||||
SLOW_DCHECK(list.Verify());
|
||||
|
||||
if (list.head_ == nullptr) return;
|
||||
|
||||
T* new_head = list.head_;
|
||||
*list.tail_ = head_;
|
||||
if (head_ == nullptr) {
|
||||
tail_ = list.tail_;
|
||||
}
|
||||
head_ = new_head;
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
head_ = nullptr;
|
||||
tail_ = &head_;
|
||||
}
|
||||
|
||||
ThreadedListBase& operator=(ThreadedListBase&& other) V8_NOEXCEPT {
|
||||
head_ = other.head_;
|
||||
tail_ = other.head_ ? other.tail_ : &head_;
|
||||
#ifdef DEBUG
|
||||
other.Clear();
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
ThreadedListBase(ThreadedListBase&& other) V8_NOEXCEPT
|
||||
: head_(other.head_),
|
||||
tail_(other.head_ ? other.tail_ : &head_) {
|
||||
#ifdef DEBUG
|
||||
other.Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Remove(T* v) {
|
||||
SLOW_DCHECK(Verify());
|
||||
|
||||
T* current = first();
|
||||
if (current == v) {
|
||||
DropHead();
|
||||
return true;
|
||||
}
|
||||
|
||||
while (current != nullptr) {
|
||||
T* next = *TLTraits::next(current);
|
||||
if (next == v) {
|
||||
*TLTraits::next(current) = *TLTraits::next(next);
|
||||
*TLTraits::next(next) = nullptr;
|
||||
|
||||
if (TLTraits::next(next) == tail_) {
|
||||
tail_ = TLTraits::next(current);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
current = next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class Iterator final {
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = T*;
|
||||
using reference = value_type;
|
||||
using pointer = value_type*;
|
||||
|
||||
public:
|
||||
Iterator& operator++() {
|
||||
entry_ = TLTraits::next(*entry_);
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const Iterator& other) const {
|
||||
return entry_ == other.entry_;
|
||||
}
|
||||
bool operator!=(const Iterator& other) const {
|
||||
return entry_ != other.entry_;
|
||||
}
|
||||
T* operator*() { return *entry_; }
|
||||
T* operator->() { return *entry_; }
|
||||
Iterator& operator=(T* entry) {
|
||||
T* next = *TLTraits::next(*entry_);
|
||||
*TLTraits::next(entry) = next;
|
||||
*entry_ = entry;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit Iterator(T** entry) : entry_(entry) {}
|
||||
|
||||
T** entry_;
|
||||
|
||||
friend class ThreadedListBase;
|
||||
};
|
||||
|
||||
class ConstIterator final {
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = T*;
|
||||
using reference = const value_type;
|
||||
using pointer = const value_type*;
|
||||
|
||||
public:
|
||||
ConstIterator& operator++() {
|
||||
entry_ = TLTraits::next(*entry_);
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const ConstIterator& other) const {
|
||||
return entry_ == other.entry_;
|
||||
}
|
||||
bool operator!=(const ConstIterator& other) const {
|
||||
return entry_ != other.entry_;
|
||||
}
|
||||
const T* operator*() const { return *entry_; }
|
||||
|
||||
private:
|
||||
explicit ConstIterator(T* const* entry) : entry_(entry) {}
|
||||
|
||||
T* const* entry_;
|
||||
|
||||
friend class ThreadedListBase;
|
||||
};
|
||||
|
||||
Iterator begin() { return Iterator(&head_); }
|
||||
Iterator end() { return Iterator(tail_); }
|
||||
|
||||
ConstIterator begin() const { return ConstIterator(&head_); }
|
||||
ConstIterator end() const { return ConstIterator(tail_); }
|
||||
|
||||
// Rewinds the list's tail to the reset point, i.e., cutting of the rest of
|
||||
// the list, including the reset_point.
|
||||
void Rewind(Iterator reset_point) {
|
||||
SLOW_DCHECK(Verify());
|
||||
|
||||
tail_ = reset_point.entry_;
|
||||
*tail_ = nullptr;
|
||||
}
|
||||
|
||||
// Moves the tail of the from_list, starting at the from_location, to the end
|
||||
// of this list.
|
||||
void MoveTail(ThreadedListBase* from_list, Iterator from_location) {
|
||||
SLOW_DCHECK(Verify());
|
||||
|
||||
if (from_list->end() != from_location) {
|
||||
DCHECK_NULL(*tail_);
|
||||
*tail_ = *from_location;
|
||||
tail_ = from_list->tail_;
|
||||
from_list->Rewind(from_location);
|
||||
|
||||
SLOW_DCHECK(Verify());
|
||||
SLOW_DCHECK(from_list->Verify());
|
||||
}
|
||||
}
|
||||
|
||||
bool is_empty() const { return head_ == nullptr; }
|
||||
|
||||
T* first() const { return head_; }
|
||||
|
||||
// Slow. For testing purposes.
|
||||
int LengthForTest() {
|
||||
int result = 0;
|
||||
for (Iterator t = begin(); t != end(); ++t) ++result;
|
||||
return result;
|
||||
}
|
||||
|
||||
T* AtForTest(int i) {
|
||||
Iterator t = begin();
|
||||
while (i-- > 0) ++t;
|
||||
return *t;
|
||||
}
|
||||
|
||||
bool Verify() {
|
||||
T* last = this->first();
|
||||
if (last == nullptr) {
|
||||
CHECK_EQ(&head_, tail_);
|
||||
} else {
|
||||
while (*TLTraits::next(last) != nullptr) {
|
||||
last = *TLTraits::next(last);
|
||||
}
|
||||
CHECK_EQ(TLTraits::next(last), tail_);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
T* head_;
|
||||
T** tail_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ThreadedListBase);
|
||||
};
|
||||
|
||||
struct EmptyBase {};
|
||||
|
||||
template <typename T, typename TLTraits = ThreadedListTraits<T>>
|
||||
using ThreadedList = ThreadedListBase<T, EmptyBase, TLTraits>;
|
||||
|
||||
V8_EXPORT_PRIVATE bool PassesFilter(Vector<const char> name,
|
||||
Vector<const char> filter);
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "src/base/hashmap.h"
|
||||
#include "src/base/logging.h"
|
||||
#include "src/base/threaded-list.h"
|
||||
#include "src/globals.h"
|
||||
#include "src/splay-tree.h"
|
||||
#include "src/utils.h"
|
||||
@ -302,8 +303,8 @@ using ZonePtrList = ZoneList<T*>;
|
||||
|
||||
// ZoneThreadedList is a special variant of the ThreadedList that can be put
|
||||
// into a Zone.
|
||||
template <typename T, typename TLTraits = ThreadedListTraits<T>>
|
||||
using ZoneThreadedList = ThreadedListBase<T, ZoneObject, TLTraits>;
|
||||
template <typename T, typename TLTraits = base::ThreadedListTraits<T>>
|
||||
using ZoneThreadedList = base::ThreadedListBase<T, ZoneObject, TLTraits>;
|
||||
|
||||
// A zone splay tree. The config type parameter encapsulates the
|
||||
// different configurations of a concrete splay tree (see splay-tree.h).
|
||||
|
@ -76,6 +76,7 @@ v8_source_set("unittests_sources") {
|
||||
"base/region-allocator-unittest.cc",
|
||||
"base/sys-info-unittest.cc",
|
||||
"base/template-utils-unittest.cc",
|
||||
"base/threaded-list-unittest.cc",
|
||||
"base/utils/random-number-generator-unittest.cc",
|
||||
"bigint-unittest.cc",
|
||||
"cancelable-tasks-unittest.cc",
|
||||
@ -200,7 +201,6 @@ v8_source_set("unittests_sources") {
|
||||
"torque/earley-parser-unittest.cc",
|
||||
"unicode-unittest.cc",
|
||||
"utils-unittest.cc",
|
||||
"utils/threaded-list.cc",
|
||||
"value-serializer-unittest.cc",
|
||||
"wasm/control-transfer-unittest.cc",
|
||||
"wasm/decoder-unittest.cc",
|
||||
|
@ -6,11 +6,11 @@
|
||||
|
||||
#include "src/v8.h"
|
||||
|
||||
#include "src/utils.h"
|
||||
#include "src/base/threaded-list.h"
|
||||
#include "testing/gtest-support.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace base {
|
||||
|
||||
struct ThreadedListTestNode {
|
||||
ThreadedListTestNode() : next_(nullptr), other_next_(nullptr) {}
|
||||
@ -305,5 +305,5 @@ TEST_F(ThreadedListTest, ConstIterComp) {
|
||||
CHECK(found_first);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace base
|
||||
} // namespace v8
|
Loading…
Reference in New Issue
Block a user