5 #include "src/compiler/state-values-utils.h" 7 #include "src/bit-vector.h" 13 StateValuesCache::StateValuesCache(JSGraph* js_graph)
14 : js_graph_(js_graph),
15 hash_map_(AreKeysEqual, ZoneHashMap::kDefaultHashMapCapacity,
16 ZoneAllocationPolicy(zone())),
17 working_space_(zone()),
18 empty_state_values_(nullptr) {}
22 bool StateValuesCache::AreKeysEqual(
void* key1,
void* key2) {
23 NodeKey* node_key1 =
reinterpret_cast<NodeKey*
>(key1);
24 NodeKey* node_key2 =
reinterpret_cast<NodeKey*
>(key2);
26 if (node_key1->node ==
nullptr) {
27 if (node_key2->node ==
nullptr) {
28 return AreValueKeysEqual(reinterpret_cast<StateValuesKey*>(key1),
29 reinterpret_cast<StateValuesKey*>(key2));
31 return IsKeysEqualToNode(reinterpret_cast<StateValuesKey*>(key1),
35 if (node_key2->node ==
nullptr) {
37 return IsKeysEqualToNode(reinterpret_cast<StateValuesKey*>(key2),
40 return node_key1->node == node_key2->node;
48 bool StateValuesCache::IsKeysEqualToNode(StateValuesKey* key, Node* node) {
49 if (key->count != static_cast<size_t>(node->InputCount())) {
53 DCHECK_EQ(IrOpcode::kStateValues, node->opcode());
54 SparseInputMask node_mask = SparseInputMaskOf(node->op());
56 if (node_mask != key->mask) {
62 for (
size_t i = 0;
i < key->count;
i++) {
63 if (key->values[
i] != node->InputAt(static_cast<int>(
i))) {
72 bool StateValuesCache::AreValueKeysEqual(StateValuesKey* key1,
73 StateValuesKey* key2) {
74 if (key1->count != key2->count) {
77 if (key1->mask != key2->mask) {
80 for (
size_t i = 0;
i < key1->count;
i++) {
81 if (key1->values[
i] != key2->values[
i]) {
89 Node* StateValuesCache::GetEmptyStateValues() {
90 if (empty_state_values_ ==
nullptr) {
92 graph()->NewNode(common()->StateValues(0, SparseInputMask::Dense()));
94 return empty_state_values_;
97 StateValuesCache::WorkingBuffer* StateValuesCache::GetWorkingSpace(
99 if (working_space_.size() <= level) {
100 working_space_.resize(level + 1);
102 return &working_space_[level];
107 int StateValuesHashKey(Node** nodes,
size_t count) {
109 for (
size_t i = 0;
i < count;
i++) {
110 hash = hash * 23 + (nodes[
i] ==
nullptr ? 0 : nodes[
i]->id());
112 return static_cast<int>(hash & 0x7FFFFFFF);
117 Node* StateValuesCache::GetValuesNodeFromCache(Node** nodes,
size_t count,
118 SparseInputMask mask) {
119 StateValuesKey key(count, mask, nodes);
120 int hash = StateValuesHashKey(nodes, count);
121 ZoneHashMap::Entry* lookup =
122 hash_map_.LookupOrInsert(&key, hash, ZoneAllocationPolicy(zone()));
123 DCHECK_NOT_NULL(lookup);
125 if (lookup->value ==
nullptr) {
126 int node_count =
static_cast<int>(count);
127 node = graph()->NewNode(common()->StateValues(node_count, mask), node_count,
129 NodeKey* new_key =
new (zone()->New(
sizeof(NodeKey))) NodeKey(node);
130 lookup->key = new_key;
131 lookup->value = node;
133 node =
reinterpret_cast<Node*
>(lookup->value);
138 SparseInputMask::BitMaskType StateValuesCache::FillBufferWithValues(
139 WorkingBuffer* node_buffer,
size_t* node_count,
size_t* values_idx,
140 Node** values,
size_t count,
const BitVector* liveness,
141 int liveness_offset) {
142 SparseInputMask::BitMaskType input_mask = 0;
146 size_t virtual_node_count = *node_count;
148 while (*values_idx < count && *node_count < kMaxInputCount &&
149 virtual_node_count < SparseInputMask::kMaxSparseInputs) {
150 DCHECK_LE(*values_idx, static_cast<size_t>(INT_MAX));
152 if (liveness ==
nullptr ||
153 liveness->Contains(liveness_offset + static_cast<int>(*values_idx))) {
154 input_mask |= 1 << (virtual_node_count);
155 (*node_buffer)[(*node_count)++] = values[*values_idx];
157 virtual_node_count++;
162 DCHECK_GE(StateValuesCache::kMaxInputCount, *node_count);
163 DCHECK_GE(SparseInputMask::kMaxSparseInputs, virtual_node_count);
166 input_mask |= SparseInputMask::kEndMarker << virtual_node_count;
171 Node* StateValuesCache::BuildTree(
size_t* values_idx, Node** values,
172 size_t count,
const BitVector* liveness,
173 int liveness_offset,
size_t level) {
174 WorkingBuffer* node_buffer = GetWorkingSpace(level);
175 size_t node_count = 0;
176 SparseInputMask::BitMaskType input_mask = SparseInputMask::kDenseBitMask;
179 input_mask = FillBufferWithValues(node_buffer, &node_count, values_idx,
180 values, count, liveness, liveness_offset);
182 DCHECK_NE(input_mask, SparseInputMask::kDenseBitMask);
184 while (*values_idx < count && node_count < kMaxInputCount) {
185 if (count - *values_idx < kMaxInputCount - node_count) {
191 size_t previous_input_count = node_count;
193 FillBufferWithValues(node_buffer, &node_count, values_idx, values,
194 count, liveness, liveness_offset);
196 DCHECK_EQ(*values_idx, count);
198 DCHECK_NE(input_mask, SparseInputMask::kDenseBitMask);
202 DCHECK_EQ(input_mask & ((1 << previous_input_count) - 1), 0u);
204 input_mask |= ((1 << previous_input_count) - 1);
210 Node* subtree = BuildTree(values_idx, values, count, liveness,
211 liveness_offset, level - 1);
212 (*node_buffer)[node_count++] = subtree;
218 if (node_count == 1 && input_mask == SparseInputMask::kDenseBitMask) {
222 DCHECK_EQ((*node_buffer)[0]->opcode(), IrOpcode::kStateValues);
223 return (*node_buffer)[0];
225 return GetValuesNodeFromCache(node_buffer->data(), node_count,
226 SparseInputMask(input_mask));
233 void CheckTreeContainsValues(Node* tree, Node** values,
size_t count,
234 const BitVector* liveness,
int liveness_offset) {
235 DCHECK_EQ(count, StateValuesAccess(tree).size());
238 auto access = StateValuesAccess(tree);
239 auto it = access.begin();
240 auto itend = access.end();
241 for (
i = 0; it != itend; ++it, ++
i) {
242 if (liveness ==
nullptr || liveness->Contains(liveness_offset +
i)) {
243 DCHECK_EQ((*it).node, values[
i]);
245 DCHECK_NULL((*it).node);
248 DCHECK_EQ(static_cast<size_t>(
i), count);
254 Node* StateValuesCache::GetNodeForValues(Node** values,
size_t count,
255 const BitVector* liveness,
256 int liveness_offset) {
259 for (
size_t i = 0;
i < count;
i++) {
260 if (values[
i] !=
nullptr) {
261 DCHECK_NE(values[
i]->opcode(), IrOpcode::kStateValues);
262 DCHECK_NE(values[
i]->opcode(), IrOpcode::kTypedStateValues);
265 if (liveness !=
nullptr) {
266 DCHECK_LE(liveness_offset + count, static_cast<size_t>(liveness->length()));
268 for (
size_t i = 0;
i < count;
i++) {
269 if (liveness->Contains(liveness_offset + static_cast<int>(
i))) {
270 DCHECK_NOT_NULL(values[
i]);
277 return GetEmptyStateValues();
285 size_t max_inputs = kMaxInputCount;
286 while (count > max_inputs) {
288 max_inputs *= kMaxInputCount;
291 size_t values_idx = 0;
293 BuildTree(&values_idx, values, count, liveness, liveness_offset, height);
295 DCHECK_EQ(values_idx, count);
298 DCHECK_EQ(tree->opcode(), IrOpcode::kStateValues);
301 CheckTreeContainsValues(tree, values, count, liveness, liveness_offset);
307 StateValuesAccess::iterator::iterator(Node* node) : current_depth_(0) {
308 stack_[current_depth_] =
309 SparseInputMaskOf(node->op()).IterateOverInputs(node);
313 SparseInputMask::InputIterator* StateValuesAccess::iterator::Top() {
314 DCHECK_LE(0, current_depth_);
315 DCHECK_GT(kMaxInlineDepth, current_depth_);
316 return &(stack_[current_depth_]);
319 void StateValuesAccess::iterator::Push(Node* node) {
321 CHECK_GT(kMaxInlineDepth, current_depth_);
322 stack_[current_depth_] =
323 SparseInputMaskOf(node->op()).IterateOverInputs(node);
327 void StateValuesAccess::iterator::Pop() {
328 DCHECK_LE(0, current_depth_);
333 bool StateValuesAccess::iterator::done() {
return current_depth_ < 0; }
336 void StateValuesAccess::iterator::Advance() {
341 void StateValuesAccess::iterator::EnsureValid() {
343 SparseInputMask::InputIterator* top = Top();
345 if (top->IsEmpty()) {
363 Node* value_node = top->GetReal();
365 if (value_node->opcode() == IrOpcode::kStateValues ||
366 value_node->opcode() == IrOpcode::kTypedStateValues) {
377 Node* StateValuesAccess::iterator::node() {
return Top()->Get(
nullptr); }
379 MachineType StateValuesAccess::iterator::type() {
380 Node* parent = Top()->parent();
381 if (parent->opcode() == IrOpcode::kStateValues) {
382 return MachineType::AnyTagged();
384 DCHECK_EQ(IrOpcode::kTypedStateValues, parent->opcode());
386 if (Top()->IsEmpty()) {
387 return MachineType::None();
389 ZoneVector<MachineType>
const* types = MachineTypesOf(parent->op());
390 return (*types)[Top()->real_index()];
396 bool StateValuesAccess::iterator::operator!=(iterator& other) {
403 StateValuesAccess::iterator& StateValuesAccess::iterator::operator++() {
409 StateValuesAccess::TypedNode StateValuesAccess::iterator::operator*() {
410 return TypedNode(node(), type());
414 size_t StateValuesAccess::size() {
416 SparseInputMask mask = SparseInputMaskOf(node_->op());
418 SparseInputMask::InputIterator iterator = mask.IterateOverInputs(node_);
420 for (; !iterator.IsEnd(); iterator.Advance()) {
421 if (iterator.IsEmpty()) {
424 Node* value = iterator.GetReal();
425 if (value->opcode() == IrOpcode::kStateValues ||
426 value->opcode() == IrOpcode::kTypedStateValues) {
427 count += StateValuesAccess(value).size();