blob: ff66c3df712d3cb05ae60d6adb33a6f300f5a93e [file] [log] [blame]
// Copyright 2015 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_COMPILER_STATE_VALUES_UTILS_H_
#define V8_COMPILER_STATE_VALUES_UTILS_H_
#include <array>
#include "src/common/globals.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/js-graph.h"
#include "src/zone/zone-hashmap.h"
namespace v8 {
namespace internal {
class BitVector;
namespace compiler {
class Graph;
class V8_EXPORT_PRIVATE StateValuesCache {
public:
explicit StateValuesCache(JSGraph* js_graph);
Node* GetNodeForValues(Node** values, size_t count,
const BitVector* liveness = nullptr,
int liveness_offset = 0);
private:
static const size_t kMaxInputCount = 8;
using WorkingBuffer = std::array<Node*, kMaxInputCount>;
struct NodeKey {
Node* node;
explicit NodeKey(Node* node) : node(node) {}
};
struct StateValuesKey : public NodeKey {
// ValueArray - array of nodes ({node} has to be nullptr).
size_t count;
SparseInputMask mask;
Node** values;
StateValuesKey(size_t count, SparseInputMask mask, Node** values)
: NodeKey(nullptr), count(count), mask(mask), values(values) {}
};
static bool AreKeysEqual(void* key1, void* key2);
static bool IsKeysEqualToNode(StateValuesKey* key, Node* node);
static bool AreValueKeysEqual(StateValuesKey* key1, StateValuesKey* key2);
// Fills {node_buffer}, starting from {node_count}, with {values}, starting
// at {values_idx}, sparsely encoding according to {liveness}. {node_count} is
// updated with the new number of inputs in {node_buffer}, and a bitmask of
// the sparse encoding is returned.
SparseInputMask::BitMaskType FillBufferWithValues(WorkingBuffer* node_buffer,
size_t* node_count,
size_t* values_idx,
Node** values, size_t count,
const BitVector* liveness,
int liveness_offset);
Node* BuildTree(size_t* values_idx, Node** values, size_t count,
const BitVector* liveness, int liveness_offset, size_t level);
WorkingBuffer* GetWorkingSpace(size_t level);
Node* GetEmptyStateValues();
Node* GetValuesNodeFromCache(Node** nodes, size_t count,
SparseInputMask mask);
Graph* graph() { return js_graph_->graph(); }
CommonOperatorBuilder* common() { return js_graph_->common(); }
Zone* zone() { return graph()->zone(); }
JSGraph* js_graph_;
CustomMatcherZoneHashMap hash_map_;
ZoneVector<WorkingBuffer> working_space_; // One working space per level.
Node* empty_state_values_;
};
class V8_EXPORT_PRIVATE StateValuesAccess {
public:
struct TypedNode {
Node* node;
MachineType type;
TypedNode(Node* node, MachineType type) : node(node), type(type) {}
};
class V8_EXPORT_PRIVATE iterator {
public:
bool operator!=(iterator const& other) const;
iterator& operator++();
TypedNode operator*();
Node* node();
bool done() const { return current_depth_ < 0; }
// Returns the number of empty nodes that were skipped over.
size_t AdvanceTillNotEmpty();
private:
friend class StateValuesAccess;
iterator() : current_depth_(-1) {}
explicit iterator(Node* node);
MachineType type();
void Advance();
void EnsureValid();
SparseInputMask::InputIterator* Top();
void Push(Node* node);
void Pop();
static const int kMaxInlineDepth = 8;
SparseInputMask::InputIterator stack_[kMaxInlineDepth];
int current_depth_;
};
explicit StateValuesAccess(Node* node) : node_(node) {}
size_t size() const;
iterator begin() const { return iterator(node_); }
iterator end() const { return iterator(); }
private:
Node* node_;
};
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_STATE_VALUES_UTILS_H_