v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
node.h
Go to the documentation of this file.
1// Copyright 2013 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_COMPILER_NODE_H_
6#define V8_COMPILER_NODE_H_
7
14
15namespace v8 {
16namespace internal {
17namespace compiler {
18
19// Forward declarations.
20class Edge;
21class TFGraph;
22
23// Marks are used during traversal of the graph to distinguish states of nodes.
24// Each node has a mark which is a monotonically increasing integer, and a
25// {NodeMarker} has a range of values that indicate states of a node.
26using Mark = uint32_t;
27
28// NodeIds are identifying numbers for nodes that can be used to index auxiliary
29// out-of-line data associated with each node.
30using NodeId = uint32_t;
31
32// A Node is the basic primitive of graphs. Nodes are chained together by
33// input/use chains but by default otherwise contain only an identifying number
34// which specific applications of graphs and nodes can use to index auxiliary
35// out-of-line data, especially transient data.
36//
37// In addition Nodes only contain a mutable Operator that may change during
38// compilation, e.g. during lowering passes. Other information that needs to be
39// associated with Nodes during compilation must be stored out-of-line indexed
40// by the Node's id.
42 public:
43 static Node* New(Zone* zone, NodeId id, const Operator* op, int input_count,
44 Node* const* inputs, bool has_extensible_inputs);
45 static Node* Clone(Zone* zone, NodeId id, const Node* node);
46
47 inline bool IsDead() const;
48 void Kill();
49
50 const Operator* op() const { return op_; }
51
52 constexpr IrOpcode::Value opcode() const {
53 DCHECK_GE(IrOpcode::kLast, op_->opcode());
54 return static_cast<IrOpcode::Value>(op_->opcode());
55 }
56
57 NodeId id() const { return IdField::decode(bit_field_); }
58
59 int InputCount() const {
60 return has_inline_inputs() ? InlineCountField::decode(bit_field_)
61 : outline_inputs()->count_;
62 }
63
64#ifdef DEBUG
65 void Verify();
66#else
67 inline void Verify() {}
68#endif
69
70 Node* InputAt(int index) const {
71 DCHECK_LE(0, index);
72 DCHECK_LT(index, InputCount());
73 return *GetInputPtrConst(index);
74 }
75
76 void ReplaceInput(int index, Node* new_to) {
77 DCHECK_LE(0, index);
78 DCHECK_LT(index, InputCount());
79 ZoneNodePtr* input_ptr = GetInputPtr(index);
80 Node* old_to = *input_ptr;
81 if (old_to != new_to) {
82 Use* use = GetUsePtr(index);
83 if (old_to) old_to->RemoveUse(use);
84 *input_ptr = new_to;
85 if (new_to) new_to->AppendUse(use);
86 }
87 }
88
89 void AppendInput(Zone* zone, Node* new_to);
90 void InsertInput(Zone* zone, int index, Node* new_to);
91 void InsertInputs(Zone* zone, int index, int count);
92 // Returns the removed input.
93 Node* RemoveInput(int index);
94 void NullAllInputs();
95 void TrimInputCount(int new_input_count);
96 // Can trim, extend by appending new inputs, or do nothing.
97 void EnsureInputCount(Zone* zone, int new_input_count);
98
99 int UseCount() const;
100 int BranchUseCount() const;
101 void ReplaceUses(Node* replace_to);
102
103 class InputEdges;
104 inline InputEdges input_edges();
105
106 class Inputs;
107 inline Inputs inputs() const;
108 inline base::Vector<Node*> inputs_vector() const;
109
110 class UseEdges final {
111 public:
113
114 class iterator;
115 inline iterator begin() const;
116 inline iterator end() const;
117
118 bool empty() const;
119
120 explicit UseEdges(Node* node) : node_(node) {}
121
122 private:
124 };
125
126 UseEdges use_edges() { return UseEdges(this); }
127
129 public:
130 using value_type = Node*;
131
132 class const_iterator;
133 inline const_iterator begin() const;
134 inline const_iterator end() const;
135
136 bool empty() const;
137
138 explicit Uses(Node* node) : node_(node) {}
139
140 private:
142 };
143
144 Uses uses() { return Uses(this); }
145
146 // Returns true if {owner} is the only user of {this} node.
147 bool OwnedBy(Node const* owner) const;
148
149 // Returns true if {owner1} and {owner2} are the only users of {this} node.
150 bool OwnedBy(Node const* owner1, Node const* owner2) const;
151
152 void Print() const { Print(1); }
153 void Print(int depth) const;
154 void Print(std::ostream&, int depth = 1) const;
155
156 private:
157 template <typename NodePtrT>
158 inline static Node* NewImpl(Zone* zone, NodeId id, const Operator* op,
159 int input_count, NodePtrT const* inputs,
160 bool has_extensible_inputs);
161
162 struct Use;
163 using ZoneUsePtr = GraphZoneTraits::Ptr<Use>;
164
165 // Out of line storage for inputs when the number of inputs overflowed the
166 // capacity of the inline-allocated space.
171
172 // Inputs are allocated right behind the OutOfLineInputs instance.
173 inline ZoneNodePtr* inputs();
174
175 static OutOfLineInputs* New(Zone* zone, int capacity);
176 void ExtractFrom(Use* use_ptr, ZoneNodePtr* input_ptr, int count);
177 };
178 using ZoneOutOfLineInputsPtr = GraphZoneTraits::Ptr<OutOfLineInputs>;
179
180 // A link in the use chain for a node. Every input {i} to a node {n} has an
181 // associated {Use} which is linked into the use chain of the {i} node.
182 struct Use {
185 uint32_t bit_field_;
186
187 int input_index() const { return InputIndexField::decode(bit_field_); }
188 bool is_inline_use() const { return InlineField::decode(bit_field_); }
190 int index = input_index();
191 Use* start = this + 1 + index;
192 ZoneNodePtr* inputs =
193 is_inline_use() ? reinterpret_cast<Node*>(start)->inline_inputs()
194 : reinterpret_cast<OutOfLineInputs*>(start)->inputs();
195 return &inputs[index];
196 }
197
199 Use* start = this + 1 + input_index();
200 return is_inline_use() ? reinterpret_cast<Node*>(start)
201 : reinterpret_cast<OutOfLineInputs*>(start)->node_;
202 }
203
206 };
207
208 //============================================================================
209 //== Memory layout ===========================================================
210 //============================================================================
211 // Saving space for big graphs is important. We use a memory layout trick to
212 // be able to map {Node} objects to {Use} objects and vice-versa in a
213 // space-efficient manner.
214 //
215 // {Use} links are laid out in memory directly before a {Node}, followed by
216 // direct pointers to input {Nodes}.
217 //
218 // inline case:
219 // |Use #N |Use #N-1|...|Use #1 |Use #0 |Node xxxx |I#0|I#1|...|I#N-1|I#N|
220 // ^ ^ ^
221 // + Use + Node + Input
222 //
223 // Since every {Use} instance records its {input_index}, pointer arithmetic
224 // can compute the {Node}.
225 //
226 // out-of-line case:
227 // |Node xxxx |
228 // ^ + outline ------------------+
229 // +----------------------------------------+
230 // | |
231 // v | node
232 // |Use #N |Use #N-1|...|Use #1 |Use #0 |OOL xxxxx |I#0|I#1|...|I#N-1|I#N|
233 // ^ ^
234 // + Use + Input
235 //
236 // Out-of-line storage of input lists is needed if appending an input to
237 // a node exceeds the maximum inline capacity.
238
239 Node(NodeId id, const Operator* op, int inline_count, int inline_capacity);
240 Node(const Node&) = delete;
241 Node& operator=(const Node&) = delete;
242
243 inline Address inputs_location() const;
244
246 return reinterpret_cast<ZoneNodePtr*>(inputs_location());
247 }
249 return *reinterpret_cast<ZoneOutOfLineInputsPtr*>(inputs_location());
250 }
252 *reinterpret_cast<ZoneOutOfLineInputsPtr*>(inputs_location()) = outline;
253 }
254
255 ZoneNodePtr const* GetInputPtrConst(int input_index) const {
256 return has_inline_inputs() ? &(inline_inputs()[input_index])
257 : &(outline_inputs()->inputs()[input_index]);
258 }
259 ZoneNodePtr* GetInputPtr(int input_index) {
260 return has_inline_inputs() ? &(inline_inputs()[input_index])
261 : &(outline_inputs()->inputs()[input_index]);
262 }
263 Use* GetUsePtr(int input_index) {
264 Use* ptr = has_inline_inputs() ? reinterpret_cast<Use*>(this)
265 : reinterpret_cast<Use*>(outline_inputs());
266 return &ptr[-1 - input_index];
267 }
268
269 void AppendUse(Use* use);
270 void RemoveUse(Use* use);
271
272 void* operator new(size_t, void* location) { return location; }
273
274 // Only NodeProperties should manipulate the op.
275 void set_op(const Operator* op) { op_ = op; }
276
277 // Only NodeProperties should manipulate the type.
278 Type type() const { return type_; }
279 void set_type(Type type) { type_ = type; }
280
281 // Only NodeMarkers should manipulate the marks on nodes.
282 Mark mark() const { return mark_; }
283 void set_mark(Mark mark) { mark_ = mark; }
284
285 inline bool has_inline_inputs() const {
286 return InlineCountField::decode(bit_field_) != kOutlineMarker;
287 }
288
289 void ClearInputs(int start, int count);
290
294 static const int kOutlineMarker = InlineCountField::kMax;
295 static const int kMaxInlineCapacity = InlineCapacityField::kMax - 1;
296
297 const Operator* op_;
300 uint32_t bit_field_;
302
303 friend class Edge;
304 friend class NodeMarkerBase;
305 friend class NodeProperties;
306};
307
309 return reinterpret_cast<Address>(this) + sizeof(Node);
310}
311
313 return reinterpret_cast<ZoneNodePtr*>(reinterpret_cast<Address>(this) +
314 sizeof(Node::OutOfLineInputs));
315}
316
317std::ostream& operator<<(std::ostream& os, const Node& n);
318
319// Base class for node wrappers.
321 public:
322 explicit constexpr NodeWrapper(Node* node) : node_(node) {}
323 operator Node*() const { return node_; }
324 Node* operator->() const { return node_; }
325
326 protected:
327 Node* node() const { return node_; }
328 void set_node(Node* node) {
329 DCHECK_NOT_NULL(node);
330 node_ = node;
331 }
332
333 private:
335};
336
337// Wrapper classes for special node/edge types (effect, control, frame states).
338
339class Effect : public NodeWrapper {
340 public:
341 explicit constexpr Effect(Node* node) : NodeWrapper(node) {
342 // TODO(jgruber): Remove the End special case.
343 SLOW_DCHECK(node == nullptr || node->op()->opcode() == IrOpcode::kEnd ||
344 node->op()->EffectOutputCount() > 0);
345 }
346
347 // Support the common `Node* x = effect = ...` pattern.
348 Node* operator=(Node* value) {
349 DCHECK_GT(value->op()->EffectOutputCount(), 0);
350 set_node(value);
351 return value;
352 }
353};
354
355class Control : public NodeWrapper {
356 public:
357 explicit constexpr Control(Node* node) : NodeWrapper(node) {
358 // TODO(jgruber): Remove the End special case.
359 SLOW_DCHECK(node == nullptr || node->opcode() == IrOpcode::kEnd ||
360 node->op()->ControlOutputCount() > 0);
361 }
362
363 // Support the common `Node* x = control = ...` pattern.
364 Node* operator=(Node* value) {
365 DCHECK_GT(value->op()->ControlOutputCount(), 0);
366 set_node(value);
367 return value;
368 }
369};
370
371// Typedefs to shorten commonly used Node containers.
376
377class Node::InputEdges final {
378 public:
380
381 class iterator;
382 inline iterator begin() const;
383 inline iterator end() const;
384
385 bool empty() const { return count_ == 0; }
386 int count() const { return count_; }
387
388 inline value_type operator[](int index) const;
389
390 InputEdges(ZoneNodePtr* input_root, Use* use_root, int count)
391 : input_root_(input_root), use_root_(use_root), count_(count) {}
392
393 private:
397};
398
400 public:
401 using value_type = Node*;
402
403 class const_iterator;
404 inline const_iterator begin() const;
405 inline const_iterator end() const;
406
407 bool empty() const { return count_ == 0; }
408 int count() const { return count_; }
409
410 inline value_type operator[](int index) const;
411
412 explicit Inputs(ZoneNodePtr const* input_root, int count)
413 : input_root_(input_root), count_(count) {}
414
415 private:
418};
419
420// An encapsulation for information associated with a single use of a node as an
421// input from another node, allowing access to both the defining node and
422// the node having the input.
423class Edge final {
424 public:
425 Node* from() const { return use_->from(); }
426 Node* to() const { return *input_ptr_; }
427 int index() const {
428 int const index = use_->input_index();
429 DCHECK_LT(index, use_->from()->InputCount());
430 return index;
431 }
432
433 bool operator==(const Edge& other) { return input_ptr_ == other.input_ptr_; }
434 bool operator!=(const Edge& other) { return !(*this == other); }
435
436 void UpdateTo(Node* new_to) {
437 Node* old_to = *input_ptr_;
438 if (old_to != new_to) {
439 if (old_to) old_to->RemoveUse(use_);
440 *input_ptr_ = new_to;
441 if (new_to) new_to->AppendUse(use_);
442 }
443 }
444
445 private:
447 friend class Node::InputEdges;
449
450 Edge(Node::Use* use, ZoneNodePtr* input_ptr)
451 : use_(use), input_ptr_(input_ptr) {
452 DCHECK_NOT_NULL(use);
453 DCHECK_NOT_NULL(input_ptr);
454 DCHECK_EQ(input_ptr, use->input_ptr());
455 }
456
459};
460
461bool Node::IsDead() const {
462 Node::Inputs inputs = this->inputs();
463 return inputs.count() > 0 && inputs[0] == nullptr;
464}
465
467 int inline_count = InlineCountField::decode(bit_field_);
468 if (inline_count != kOutlineMarker) {
469 return InputEdges(inline_inputs(), reinterpret_cast<Use*>(this) - 1,
470 inline_count);
471 } else {
472 return InputEdges(outline_inputs()->inputs(),
473 reinterpret_cast<Use*>(outline_inputs()) - 1,
475 }
476}
477
479 int inline_count = InlineCountField::decode(bit_field_);
480 if (inline_count != kOutlineMarker) {
481 return Inputs(inline_inputs(), inline_count);
482 } else {
484 }
485}
486
488 int inline_count = InlineCountField::decode(bit_field_);
489 if (inline_count != kOutlineMarker) {
490 return base::VectorOf<Node*>(inline_inputs(), inline_count);
491 } else {
494 }
495}
496
497// A forward iterator to visit the edges for the input dependencies of a node.
499 public:
500 using iterator_category = std::forward_iterator_tag;
501 using difference_type = std::ptrdiff_t;
503 using pointer = Edge*;
504 using reference = Edge&;
505
506 iterator() : use_(nullptr), input_ptr_(nullptr) {}
507 iterator(const iterator& other) = default;
508
509 Edge operator*() const { return Edge(use_, input_ptr_); }
510 bool operator==(const iterator& other) const {
511 return input_ptr_ == other.input_ptr_;
512 }
513 bool operator!=(const iterator& other) const { return !(*this == other); }
515 input_ptr_++;
516 use_--;
517 return *this;
518 }
519 iterator operator++(int);
521 input_ptr_ += offset;
522 use_ -= offset;
523 return *this;
524 }
526 return iterator(use_ - offset, input_ptr_ + offset);
527 }
528 difference_type operator-(const iterator& other) const {
529 return input_ptr_ - other.input_ptr_;
530 }
531
532 private:
533 friend class Node;
534
535 explicit iterator(Use* use, ZoneNodePtr* input_ptr)
536 : use_(use), input_ptr_(input_ptr) {}
537
540};
541
542
544 return Node::InputEdges::iterator(use_root_, input_root_);
545}
546
547
549 return Node::InputEdges::iterator(use_root_ - count_, input_root_ + count_);
550}
551
553 return Edge(use_root_ + index, input_root_ + index);
554}
555
556// A forward iterator to visit the inputs of a node.
558 public:
559 using iterator_category = std::forward_iterator_tag;
560 using difference_type = std::ptrdiff_t;
561 using value_type = Node*;
562 using pointer = const value_type*;
564
565 const_iterator(const const_iterator& other) = default;
566
567 Node* operator*() const { return *input_ptr_; }
568 bool operator==(const const_iterator& other) const {
569 return input_ptr_ == other.input_ptr_;
570 }
571 bool operator!=(const const_iterator& other) const {
572 return !(*this == other);
573 }
575 ++input_ptr_;
576 return *this;
577 }
580 input_ptr_ += offset;
581 return *this;
582 }
584 return const_iterator(input_ptr_ + offset);
585 }
587 return input_ptr_ - other.input_ptr_;
588 }
589
590 private:
591 friend class Node::Inputs;
592
593 explicit const_iterator(ZoneNodePtr const* input_ptr)
594 : input_ptr_(input_ptr) {}
595
597};
598
599
603
604
606 return const_iterator(input_root_ + count_);
607}
608
609Node* Node::Inputs::operator[](int index) const { return input_root_[index]; }
610
611// A forward iterator to visit the uses edges of a node.
613 public:
614 iterator(const iterator& other) = default;
615
616 Edge operator*() const { return Edge(current_, current_->input_ptr()); }
617 bool operator==(const iterator& other) const {
618 return current_ == other.current_;
619 }
620 bool operator!=(const iterator& other) const { return !(*this == other); }
623 current_ = next_;
624 next_ = current_ ? static_cast<Node::Use*>(current_->next) : nullptr;
625 return *this;
626 }
627 iterator operator++(int);
628
629 private:
630 friend class Node::UseEdges;
631
632 iterator() : current_(nullptr), next_(nullptr) {}
633 explicit iterator(Node* node)
634 : current_(node->first_use_),
635 next_(current_ ? static_cast<Node::Use*>(current_->next) : nullptr) {}
636
639};
640
641
645
646
650
651
652// A forward iterator to visit the uses of a node.
654 public:
655 using iterator_category = std::forward_iterator_tag;
656 using difference_type = int;
657 using value_type = Node*;
658 using pointer = Node**;
659 using reference = Node*&;
660
661 Node* operator*() const { return current_->from(); }
662 bool operator==(const const_iterator& other) const {
663 return other.current_ == current_;
664 }
665 bool operator!=(const const_iterator& other) const {
666 return other.current_ != current_;
667 }
670 // Checking no use gets mutated while iterating through them, a potential
671 // very tricky cause of bug.
672 current_ = current_->next;
673#ifdef DEBUG
674 DCHECK_EQ(current_, next_);
675 next_ = current_ ? current_->next : nullptr;
676#endif
677 return *this;
678 }
680
681 private:
682 friend class Node::Uses;
683
684 const_iterator() : current_(nullptr) {}
685 explicit const_iterator(Node* node)
686 : current_(node->first_use_)
687#ifdef DEBUG
688 ,
689 next_(current_ ? current_->next : nullptr)
690#endif
691 {
692 }
693
695#ifdef DEBUG
696 Node::Use* next_;
697#endif
698};
699
700
704
705
707
709 return uses.begin();
710}
712 return uses.end();
713}
714
715} // namespace compiler
716} // namespace internal
717} // namespace v8
718
719#endif // V8_COMPILER_NODE_H_
uint32_t bit_field_
#define SLOW_DCHECK(condition)
Definition checks.h:21
static constexpr T decode(U value)
Definition bit-field.h:66
Node * operator=(Node *value)
Definition node.h:364
constexpr Control(Node *node)
Definition node.h:357
bool operator==(const Edge &other)
Definition node.h:433
Node * from() const
Definition node.h:425
Node * to() const
Definition node.h:426
bool operator!=(const Edge &other)
Definition node.h:434
ZoneNodePtr * input_ptr_
Definition node.h:458
Edge(Node::Use *use, ZoneNodePtr *input_ptr)
Definition node.h:450
void UpdateTo(Node *new_to)
Definition node.h:436
Node * operator=(Node *value)
Definition node.h:348
constexpr Effect(Node *node)
Definition node.h:341
constexpr NodeWrapper(Node *node)
Definition node.h:322
iterator(Use *use, ZoneNodePtr *input_ptr)
Definition node.h:535
bool operator==(const iterator &other) const
Definition node.h:510
iterator & operator+=(difference_type offset)
Definition node.h:520
iterator operator+(difference_type offset) const
Definition node.h:525
std::forward_iterator_tag iterator_category
Definition node.h:500
bool operator!=(const iterator &other) const
Definition node.h:513
difference_type operator-(const iterator &other) const
Definition node.h:528
InputEdges(ZoneNodePtr *input_root, Use *use_root, int count)
Definition node.h:390
value_type operator[](int index) const
Definition node.h:552
std::forward_iterator_tag iterator_category
Definition node.h:559
const_iterator & operator+=(difference_type offset)
Definition node.h:579
bool operator==(const const_iterator &other) const
Definition node.h:568
const_iterator operator+(difference_type offset) const
Definition node.h:583
difference_type operator-(const const_iterator &other) const
Definition node.h:586
const_iterator(ZoneNodePtr const *input_ptr)
Definition node.h:593
bool operator!=(const const_iterator &other) const
Definition node.h:571
const_iterator(const const_iterator &other)=default
ZoneNodePtr const * input_root_
Definition node.h:416
const_iterator begin() const
Definition node.h:600
Inputs(ZoneNodePtr const *input_root, int count)
Definition node.h:412
value_type operator[](int index) const
Definition node.h:609
const_iterator end() const
Definition node.h:605
bool operator==(const iterator &other) const
Definition node.h:617
iterator(const iterator &other)=default
bool operator!=(const iterator &other) const
Definition node.h:620
bool operator==(const const_iterator &other) const
Definition node.h:662
std::forward_iterator_tag iterator_category
Definition node.h:655
bool operator!=(const const_iterator &other) const
Definition node.h:665
const_iterator begin() const
Definition node.h:701
const_iterator end() const
Definition node.h:706
base::Vector< Node * > inputs_vector() const
Definition node.h:487
ZoneNodePtr * GetInputPtr(int input_index)
Definition node.h:259
const Operator * op_
Definition node.h:297
InputEdges input_edges()
Definition node.h:466
GraphZoneTraits::Ptr< OutOfLineInputs > ZoneOutOfLineInputsPtr
Definition node.h:178
GraphZoneTraits::Ptr< Use > ZoneUsePtr
Definition node.h:163
bool has_inline_inputs() const
Definition node.h:285
constexpr IrOpcode::Value opcode() const
Definition node.h:52
ZoneNodePtr * inline_inputs() const
Definition node.h:245
void AppendUse(Use *use)
Definition node.cc:409
Address inputs_location() const
Definition node.h:308
Use * GetUsePtr(int input_index)
Definition node.h:263
ZoneNodePtr const * GetInputPtrConst(int input_index) const
Definition node.h:255
Inputs inputs() const
Definition node.h:478
OutOfLineInputs * outline_inputs() const
Definition node.h:248
Node & operator=(const Node &)=delete
void set_op(const Operator *op)
Definition node.h:275
void set_type(Type type)
Definition node.h:279
void RemoveUse(Use *use)
Definition node.cc:419
const Operator * op() const
Definition node.h:50
void set_outline_inputs(OutOfLineInputs *outline)
Definition node.h:251
int InputCount() const
Definition node.h:59
void set_mark(Mark mark)
Definition node.h:283
void ReplaceInput(int index, Node *new_to)
Definition node.h:76
Node * InputAt(int index) const
Definition node.h:70
Node(const Node &)=delete
static const int kOutlineMarker
Definition node.h:294
NodeId id() const
Definition node.h:57
const ObjectRef type_
size_t count_
Definition sweeper.cc:55
int start
int end
OptionalOpIndex index
int32_t offset
Node * node
constexpr Vector< T > VectorOf(T *start, size_t size)
Definition vector.h:360
GraphZoneTraits::Ptr< Node > ZoneNodePtr
std::ostream & operator<<(std::ostream &os, AccessMode access_mode)
Node::Uses::const_iterator begin(const Node::Uses &uses)
Definition node.h:708
V8_INLINE Builtin operator++(Builtin &builtin)
Definition builtins.h:80
base::uc32 current_
Node * node_
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define V8_EXPORT_PRIVATE
Definition macros.h:460
ZoneNodePtr * input_ptr()
Definition node.h:189
std::unique_ptr< ValueMirror > value
wasm::ValueType type