[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:
Florian Sattler 2018-09-26 14:39:46 +02:00 committed by Commit Bot
parent 0714bd9fa0
commit 56c832a5a5
11 changed files with 293 additions and 290 deletions

View File

@ -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)

View File

@ -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 &&

View File

@ -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_;

View File

@ -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
View 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_

View File

@ -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) {

View File

@ -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_) {

View File

@ -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);

View File

@ -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).

View File

@ -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",

View File

@ -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