11cb0ef41Sopenharmony_ci// Copyright 2018 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_COMPILER_FUNCTIONAL_LIST_H_ 61cb0ef41Sopenharmony_ci#define V8_COMPILER_FUNCTIONAL_LIST_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/base/iterator.h" 91cb0ef41Sopenharmony_ci#include "src/zone/zone.h" 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_cinamespace v8 { 121cb0ef41Sopenharmony_cinamespace internal { 131cb0ef41Sopenharmony_cinamespace compiler { 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ci// A generic stack implemented with a singly-linked list, which results in an 161cb0ef41Sopenharmony_ci// O(1) copy operation. It can be used to model immutable lists like those in 171cb0ef41Sopenharmony_ci// functional languages. Compared to typical functional lists, this also caches 181cb0ef41Sopenharmony_ci// the length of the list in each node. 191cb0ef41Sopenharmony_ci// Note: The underlying implementation is mutable, so if you want to use this as 201cb0ef41Sopenharmony_ci// an immutable list, make sure to create a copy by passing it by value and 211cb0ef41Sopenharmony_ci// operate on the copy. 221cb0ef41Sopenharmony_ci// TODO(turbofan): Use this implementation also for RedundancyElimination. 231cb0ef41Sopenharmony_citemplate <class A> 241cb0ef41Sopenharmony_ciclass FunctionalList { 251cb0ef41Sopenharmony_ci private: 261cb0ef41Sopenharmony_ci struct Cons : ZoneObject { 271cb0ef41Sopenharmony_ci Cons(A top, Cons* rest) 281cb0ef41Sopenharmony_ci : top(std::move(top)), rest(rest), size(1 + (rest ? rest->size : 0)) {} 291cb0ef41Sopenharmony_ci A const top; 301cb0ef41Sopenharmony_ci Cons* const rest; 311cb0ef41Sopenharmony_ci size_t const size; 321cb0ef41Sopenharmony_ci }; 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci public: 351cb0ef41Sopenharmony_ci FunctionalList() : elements_(nullptr) {} 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci bool operator==(const FunctionalList<A>& other) const { 381cb0ef41Sopenharmony_ci if (Size() != other.Size()) return false; 391cb0ef41Sopenharmony_ci iterator it = begin(); 401cb0ef41Sopenharmony_ci iterator other_it = other.begin(); 411cb0ef41Sopenharmony_ci while (true) { 421cb0ef41Sopenharmony_ci if (it == other_it) return true; 431cb0ef41Sopenharmony_ci if (*it != *other_it) return false; 441cb0ef41Sopenharmony_ci ++it; 451cb0ef41Sopenharmony_ci ++other_it; 461cb0ef41Sopenharmony_ci } 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci bool operator!=(const FunctionalList<A>& other) const { 491cb0ef41Sopenharmony_ci return !(*this == other); 501cb0ef41Sopenharmony_ci } 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci bool TriviallyEquals(const FunctionalList<A>& other) const { 531cb0ef41Sopenharmony_ci return elements_ == other.elements_; 541cb0ef41Sopenharmony_ci } 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci const A& Front() const { 571cb0ef41Sopenharmony_ci DCHECK_GT(Size(), 0); 581cb0ef41Sopenharmony_ci return elements_->top; 591cb0ef41Sopenharmony_ci } 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci FunctionalList Rest() const { 621cb0ef41Sopenharmony_ci FunctionalList result = *this; 631cb0ef41Sopenharmony_ci result.DropFront(); 641cb0ef41Sopenharmony_ci return result; 651cb0ef41Sopenharmony_ci } 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci void DropFront() { 681cb0ef41Sopenharmony_ci CHECK_GT(Size(), 0); 691cb0ef41Sopenharmony_ci elements_ = elements_->rest; 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci void PushFront(A a, Zone* zone) { 731cb0ef41Sopenharmony_ci elements_ = zone->New<Cons>(std::move(a), elements_); 741cb0ef41Sopenharmony_ci } 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci // If {hint} happens to be exactly what we want to allocate, avoid allocation 771cb0ef41Sopenharmony_ci // by reusing {hint}. 781cb0ef41Sopenharmony_ci void PushFront(A a, Zone* zone, FunctionalList hint) { 791cb0ef41Sopenharmony_ci if (hint.Size() == Size() + 1 && hint.Front() == a && 801cb0ef41Sopenharmony_ci hint.Rest() == *this) { 811cb0ef41Sopenharmony_ci *this = hint; 821cb0ef41Sopenharmony_ci } else { 831cb0ef41Sopenharmony_ci PushFront(a, zone); 841cb0ef41Sopenharmony_ci } 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci // Drop elements until the current stack is equal to the tail shared with 881cb0ef41Sopenharmony_ci // {other}. The shared tail must not only be equal, but also refer to the 891cb0ef41Sopenharmony_ci // same memory. 901cb0ef41Sopenharmony_ci void ResetToCommonAncestor(FunctionalList other) { 911cb0ef41Sopenharmony_ci while (other.Size() > Size()) other.DropFront(); 921cb0ef41Sopenharmony_ci while (other.Size() < Size()) DropFront(); 931cb0ef41Sopenharmony_ci while (elements_ != other.elements_) { 941cb0ef41Sopenharmony_ci DropFront(); 951cb0ef41Sopenharmony_ci other.DropFront(); 961cb0ef41Sopenharmony_ci } 971cb0ef41Sopenharmony_ci } 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci size_t Size() const { return elements_ ? elements_->size : 0; } 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci void Clear() { elements_ = nullptr; } 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci class iterator : public base::iterator<std::forward_iterator_tag, A> { 1041cb0ef41Sopenharmony_ci public: 1051cb0ef41Sopenharmony_ci explicit iterator(Cons* cur) : current_(cur) {} 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci const A& operator*() const { return current_->top; } 1081cb0ef41Sopenharmony_ci iterator& operator++() { 1091cb0ef41Sopenharmony_ci current_ = current_->rest; 1101cb0ef41Sopenharmony_ci return *this; 1111cb0ef41Sopenharmony_ci } 1121cb0ef41Sopenharmony_ci bool operator==(const iterator& other) const { 1131cb0ef41Sopenharmony_ci return this->current_ == other.current_; 1141cb0ef41Sopenharmony_ci } 1151cb0ef41Sopenharmony_ci bool operator!=(const iterator& other) const { return !(*this == other); } 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci private: 1181cb0ef41Sopenharmony_ci Cons* current_; 1191cb0ef41Sopenharmony_ci }; 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ci iterator begin() const { return iterator(elements_); } 1221cb0ef41Sopenharmony_ci iterator end() const { return iterator(nullptr); } 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci private: 1251cb0ef41Sopenharmony_ci Cons* elements_; 1261cb0ef41Sopenharmony_ci}; 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci} // namespace compiler 1291cb0ef41Sopenharmony_ci} // namespace internal 1301cb0ef41Sopenharmony_ci} // namespace v8 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci#endif // V8_COMPILER_FUNCTIONAL_LIST_H_ 133