162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Copyright 2016 the V8 project authors. All rights reserved.
262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// found in the LICENSE file.
462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#ifndef V8_COMPILER_GRAPH_ASSEMBLER_H_
662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define V8_COMPILER_GRAPH_ASSEMBLER_H_
762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/compiler/js-graph.h"
962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/compiler/node.h"
1062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/compiler/simplified-operator.h"
1162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochnamespace v8 {
1362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochnamespace internal {
1462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochclass JSGraph;
1662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochclass Graph;
1762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochnamespace compiler {
1962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
2062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define PURE_ASSEMBLER_MACH_UNOP_LIST(V) \
2162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(ChangeInt32ToInt64)                  \
2262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(ChangeInt32ToFloat64)                \
2362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(ChangeUint32ToFloat64)               \
2462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(ChangeUint32ToUint64)                \
2562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(ChangeFloat64ToInt32)                \
2662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(ChangeFloat64ToUint32)               \
2762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(TruncateInt64ToInt32)                \
2862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(RoundFloat64ToInt32)                 \
2962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(TruncateFloat64ToWord32)             \
3062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Float64ExtractHighWord32)            \
3162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Float64Abs)                          \
3262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(BitcastWordToTagged)
3362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
3462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define PURE_ASSEMBLER_MACH_BINOP_LIST(V) \
3562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(WordShl)                              \
3662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(WordSar)                              \
3762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(WordAnd)                              \
3862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Word32Or)                             \
3962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Word32And)                            \
4062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Word32Shr)                            \
4162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Word32Shl)                            \
4262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(IntAdd)                               \
4362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(IntSub)                               \
4462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(UintLessThan)                         \
4562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Int32Add)                             \
4662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Int32Sub)                             \
4762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Int32Mul)                             \
4862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Int32LessThanOrEqual)                 \
4962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Uint32LessThanOrEqual)                \
5062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Uint32LessThan)                       \
5162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Int32LessThan)                        \
5262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Float64Add)                           \
5362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Float64Sub)                           \
5462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Float64Mod)                           \
5562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Float64Equal)                         \
5662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Float64LessThan)                      \
5762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Float64LessThanOrEqual)               \
5862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Word32Equal)                          \
5962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(WordEqual)
6062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
6162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define CHECKED_ASSEMBLER_MACH_BINOP_LIST(V) \
6262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Int32AddWithOverflow)                    \
6362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Int32SubWithOverflow)                    \
6462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Int32MulWithOverflow)                    \
6562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Int32Mod)                                \
6662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Int32Div)                                \
6762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Uint32Mod)                               \
6862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(Uint32Div)
6962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
7062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define JSGRAPH_SINGLETON_CONSTANT_LIST(V) \
7162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(TrueConstant)                          \
7262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(FalseConstant)                         \
7362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(HeapNumberMapConstant)                 \
7462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(NoContextConstant)                     \
7562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(EmptyStringConstant)                   \
7662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(UndefinedConstant)                     \
7762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(TheHoleConstant)                       \
7862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(FixedArrayMapConstant)                 \
7962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(ToNumberBuiltinConstant)               \
8062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(AllocateInNewSpaceStubConstant)        \
8162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V(AllocateInOldSpaceStubConstant)
8262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
8362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochclass GraphAssembler;
8462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
8562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochenum class GraphAssemblerLabelType { kDeferred, kNonDeferred };
8662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
8762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Label with statically known count of incoming branches and phis.
8862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <size_t MergeCount, size_t VarCount = 0u>
8962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochclass GraphAssemblerStaticLabel {
9062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch public:
9162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* PhiAt(size_t index);
9262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
9362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  template <typename... Reps>
9462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  explicit GraphAssemblerStaticLabel(GraphAssemblerLabelType is_deferred,
9562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                     Reps... reps)
9662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      : is_deferred_(is_deferred == GraphAssemblerLabelType::kDeferred) {
9762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    STATIC_ASSERT(VarCount == sizeof...(reps));
9862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    MachineRepresentation reps_array[] = {MachineRepresentation::kNone,
9962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                          reps...};
10062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    for (size_t i = 0; i < VarCount; i++) {
10162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      representations_[i] = reps_array[i + 1];
10262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
10362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
10462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
10562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ~GraphAssemblerStaticLabel() { DCHECK(IsBound() || MergedCount() == 0); }
10662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
10762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch private:
10862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  friend class GraphAssembler;
10962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
11062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void SetBound() {
11162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(!IsBound());
11262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_EQ(merged_count_, MergeCount);
11362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    is_bound_ = true;
11462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
11562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bool IsBound() const { return is_bound_; }
11662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
11762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  size_t PhiCount() const { return VarCount; }
11862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  size_t MaxMergeCount() const { return MergeCount; }
11962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  size_t MergedCount() const { return merged_count_; }
12062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bool IsDeferred() const { return is_deferred_; }
12162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
12262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // For each phi, the buffer must have at least MaxMergeCount() + 1
12362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // node entries.
12462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node** GetBindingsPtrFor(size_t phi_index) {
12562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_LT(phi_index, PhiCount());
12662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return &bindings_[phi_index * (MergeCount + 1)];
12762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
12862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void SetBinding(size_t phi_index, size_t merge_index, Node* binding) {
12962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_LT(phi_index, PhiCount());
13062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_LT(merge_index, MergeCount);
13162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bindings_[phi_index * (MergeCount + 1) + merge_index] = binding;
13262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
13362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  MachineRepresentation GetRepresentationFor(size_t phi_index) {
13462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_LT(phi_index, PhiCount());
13562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return representations_[phi_index];
13662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
13762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // The controls buffer must have at least MaxMergeCount() entries.
13862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node** GetControlsPtr() { return controls_; }
13962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // The effects buffer must have at least MaxMergeCount() + 1 entries.
14062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node** GetEffectsPtr() { return effects_; }
14162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void IncrementMergedCount() { merged_count_++; }
14262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
14362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bool is_bound_ = false;
14462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bool is_deferred_;
14562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  size_t merged_count_ = 0;
14662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* effects_[MergeCount + 1];  // Extra element for control edge,
14762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                   // so that we can use the array to
14862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                   // construct EffectPhi.
14962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* controls_[MergeCount];
15062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* bindings_[(MergeCount + 1) * VarCount + 1];
15162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  MachineRepresentation representations_[VarCount + 1];
15262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch};
15362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
15462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// General label (with zone allocated buffers for incoming branches and phi
15562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// inputs).
15662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochclass GraphAssemblerLabel {
15762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch public:
15862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* PhiAt(size_t index);
15962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
16062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GraphAssemblerLabel(GraphAssemblerLabelType is_deferred, size_t merge_count,
16162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      size_t var_count, MachineRepresentation* representations,
16262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      Zone* zone);
16362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
16462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ~GraphAssemblerLabel();
16562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
16662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch private:
16762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  friend class GraphAssembler;
16862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
16962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void SetBound() {
17062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(!is_bound_);
17162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    is_bound_ = true;
17262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
17362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bool IsBound() const { return is_bound_; }
17462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  size_t PhiCount() const { return var_count_; }
17562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  size_t MaxMergeCount() const { return max_merge_count_; }
17662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  size_t MergedCount() const { return merged_count_; }
17762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bool IsDeferred() const { return is_deferred_; }
17862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
17962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // For each phi, the buffer must have at least MaxMergeCount() + 1
18062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // node entries.
18162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node** GetBindingsPtrFor(size_t phi_index);
18262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void SetBinding(size_t phi_index, size_t merge_index, Node* binding);
18362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  MachineRepresentation GetRepresentationFor(size_t phi_index);
18462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // The controls buffer must have at least MaxMergeCount() entries.
18562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node** GetControlsPtr();
18662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // The effects buffer must have at least MaxMergeCount() + 1 entries.
18762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node** GetEffectsPtr();
18862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void IncrementMergedCount() { merged_count_++; }
18962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
19062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bool is_bound_ = false;
19162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bool is_deferred_;
19262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  size_t merged_count_ = 0;
19362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  size_t max_merge_count_;
19462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  size_t var_count_;
19562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node** effects_ = nullptr;
19662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node** controls_ = nullptr;
19762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node** bindings_ = nullptr;
19862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  MachineRepresentation* representations_ = nullptr;
19962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch};
20062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
20162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochclass GraphAssembler {
20262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch public:
20362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GraphAssembler(JSGraph* jsgraph, Node* effect, Node* control, Zone* zone);
20462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
20562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void Reset(Node* effect, Node* control);
20662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
20762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Create non-deferred label with statically known number of incoming
20862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // gotos/branches.
20962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  template <size_t MergeCount, typename... Reps>
21062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static GraphAssemblerStaticLabel<MergeCount, sizeof...(Reps)> MakeLabel(
21162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Reps... reps) {
21262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return GraphAssemblerStaticLabel<MergeCount, sizeof...(Reps)>(
21362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        GraphAssemblerLabelType::kNonDeferred, reps...);
21462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
21562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
21662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Create deferred label with statically known number of incoming
21762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // gotos/branches.
21862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  template <size_t MergeCount, typename... Reps>
21962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static GraphAssemblerStaticLabel<MergeCount, sizeof...(Reps)>
22062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  MakeDeferredLabel(Reps... reps) {
22162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return GraphAssemblerStaticLabel<MergeCount, sizeof...(Reps)>(
22262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        GraphAssemblerLabelType::kDeferred, reps...);
22362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
22462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
22562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Create label with number of incoming branches supplied at runtime.
22662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  template <typename... Reps>
22762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GraphAssemblerLabel MakeLabelFor(GraphAssemblerLabelType is_deferred,
22862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                   size_t merge_count, Reps... reps) {
22962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    MachineRepresentation reps_array[] = {MachineRepresentation::kNone,
23062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                          reps...};
23162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return GraphAssemblerLabel(is_deferred, merge_count, sizeof...(reps),
23262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               &(reps_array[1]), temp_zone());
23362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
23462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
23562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Value creation.
23662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* IntPtrConstant(intptr_t value);
23762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* Uint32Constant(int32_t value);
23862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* Int32Constant(int32_t value);
23962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* UniqueInt32Constant(int32_t value);
24062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* SmiConstant(int32_t value);
24162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* Float64Constant(double value);
24262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* Projection(int index, Node* value);
24362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* HeapConstant(Handle<HeapObject> object);
24462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* CEntryStubConstant(int result_size);
24562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* ExternalConstant(ExternalReference ref);
24662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
24762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define SINGLETON_CONST_DECL(Name) Node* Name();
24862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_DECL)
24962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#undef SINGLETON_CONST_DECL
25062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
25162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define PURE_UNOP_DECL(Name) Node* Name(Node* input);
25262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  PURE_ASSEMBLER_MACH_UNOP_LIST(PURE_UNOP_DECL)
25362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#undef PURE_UNOP_DECL
25462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
25562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define BINOP_DECL(Name) Node* Name(Node* left, Node* right);
25662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  PURE_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL)
25762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CHECKED_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL)
25862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#undef BINOP_DECL
25962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
26062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* Float64RoundDown(Node* value);
26162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
26262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* ToNumber(Node* value);
26362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* Allocate(PretenureFlag pretenure, Node* size);
26462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* LoadField(FieldAccess const&, Node* object);
26562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* LoadElement(ElementAccess const&, Node* object, Node* index);
26662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* StoreField(FieldAccess const&, Node* object, Node* value);
26762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* StoreElement(ElementAccess const&, Node* object, Node* index,
26862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     Node* value);
26962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
27062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* Store(StoreRepresentation rep, Node* object, Node* offset, Node* value);
27162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* Load(MachineType rep, Node* object, Node* offset);
27262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
27362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* Retain(Node* buffer);
27462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* UnsafePointerAdd(Node* base, Node* external);
27562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
27662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* DeoptimizeIf(DeoptimizeReason reason, Node* condition,
27762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     Node* frame_state);
27862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* DeoptimizeUnless(DeoptimizeKind kind, DeoptimizeReason reason,
27962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                         Node* condition, Node* frame_state);
28062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* DeoptimizeUnless(DeoptimizeReason reason, Node* condition,
28162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                         Node* frame_state);
28262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  template <typename... Args>
28362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* Call(const CallDescriptor* desc, Args... args);
28462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  template <typename... Args>
28562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* Call(const Operator* op, Args... args);
28662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
28762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Basic control operations.
28862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  template <class LabelType>
28962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void Bind(LabelType* label);
29062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
29162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  template <class LabelType, typename... vars>
29262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void Goto(LabelType* label, vars...);
29362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
29462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void Branch(Node* condition, GraphAssemblerStaticLabel<1>* if_true,
29562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              GraphAssemblerStaticLabel<1>* if_false);
29662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
29762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Control helpers.
29862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // {GotoIf(c, l)} is equivalent to {Branch(c, l, templ);Bind(templ)}.
29962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  template <class LabelType, typename... vars>
30062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void GotoIf(Node* condition, LabelType* label, vars...);
30162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
30262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // {GotoUnless(c, l)} is equivalent to {Branch(c, templ, l);Bind(templ)}.
30362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  template <class LabelType, typename... vars>
30462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void GotoUnless(Node* condition, LabelType* label, vars...);
30562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
30662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Extractors (should be only used when destructing/resetting the assembler).
30762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* ExtractCurrentControl();
30862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* ExtractCurrentEffect();
30962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
31062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch private:
31162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  template <class LabelType, typename... Vars>
31262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void MergeState(LabelType label, Vars... vars);
31362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
31462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Operator const* ToNumberOperator();
31562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
31662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSGraph* jsgraph() const { return jsgraph_; }
31762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Graph* graph() const { return jsgraph_->graph(); }
31862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Zone* temp_zone() const { return temp_zone_; }
31962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CommonOperatorBuilder* common() const { return jsgraph()->common(); }
32062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  MachineOperatorBuilder* machine() const { return jsgraph()->machine(); }
32162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  SimplifiedOperatorBuilder* simplified() const {
32262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return jsgraph()->simplified();
32362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
32462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
32562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  SetOncePointer<Operator const> to_number_operator_;
32662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Zone* temp_zone_;
32762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  JSGraph* jsgraph_;
32862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* current_effect_;
32962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* current_control_;
33062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch};
33162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
33262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <size_t MergeCount, size_t VarCount>
33362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* GraphAssemblerStaticLabel<MergeCount, VarCount>::PhiAt(size_t index) {
33462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IsBound());
33562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return GetBindingsPtrFor(index)[0];
33662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
33762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
33862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <class LabelType, typename... Vars>
33962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid GraphAssembler::MergeState(LabelType label, Vars... vars) {
34062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(!label->IsBound());
34162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  size_t merged_count = label->MergedCount();
34262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_LT(merged_count, label->MaxMergeCount());
34362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(label->PhiCount(), sizeof...(vars));
34462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  label->GetEffectsPtr()[merged_count] = current_effect_;
34562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  label->GetControlsPtr()[merged_count] = current_control_;
34662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // We need to start with nullptr to avoid 0-length arrays.
34762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* var_array[] = {nullptr, vars...};
34862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  for (size_t i = 0; i < sizeof...(vars); i++) {
34962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    label->SetBinding(i, merged_count, var_array[i + 1]);
35062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
35162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  label->IncrementMergedCount();
35262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
35362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
35462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <class LabelType>
35562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid GraphAssembler::Bind(LabelType* label) {
35662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(current_control_ == nullptr);
35762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(current_effect_ == nullptr);
35862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(label->MaxMergeCount() > 0);
35962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(label->MaxMergeCount(), label->MergedCount());
36062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
36162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int merge_count = static_cast<int>(label->MaxMergeCount());
36262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (merge_count == 1) {
36362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    current_control_ = label->GetControlsPtr()[0];
36462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    current_effect_ = label->GetEffectsPtr()[0];
36562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    label->SetBound();
36662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return;
36762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
36862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
36962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  current_control_ = graph()->NewNode(common()->Merge(merge_count), merge_count,
37062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                      label->GetControlsPtr());
37162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
37262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node** effects = label->GetEffectsPtr();
37362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  current_effect_ = effects[0];
37462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  for (size_t i = 1; i < label->MaxMergeCount(); i++) {
37562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (current_effect_ != effects[i]) {
37662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      effects[label->MaxMergeCount()] = current_control_;
37762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      current_effect_ = graph()->NewNode(common()->EffectPhi(merge_count),
37862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                         merge_count + 1, effects);
37962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
38062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
38162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
38262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
38362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  for (size_t var = 0; var < label->PhiCount(); var++) {
38462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node** bindings = label->GetBindingsPtrFor(var);
38562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bindings[label->MaxMergeCount()] = current_control_;
38662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    bindings[0] = graph()->NewNode(
38762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        common()->Phi(label->GetRepresentationFor(var), merge_count),
38862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        merge_count + 1, bindings);
38962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
39062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
39162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  label->SetBound();
39262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
39362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
39462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <class LabelType, typename... Vars>
39562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid GraphAssembler::Goto(LabelType* label, Vars... vars) {
39662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_NOT_NULL(current_control_);
39762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_NOT_NULL(current_effect_);
39862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  MergeState(label, vars...);
39962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  current_control_ = nullptr;
40062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  current_effect_ = nullptr;
40162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
40262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
40362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <class LabelType, typename... Vars>
40462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid GraphAssembler::GotoIf(Node* condition, LabelType* label, Vars... vars) {
40562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  BranchHint hint =
40662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      label->IsDeferred() ? BranchHint::kFalse : BranchHint::kNone;
40762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* branch =
40862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      graph()->NewNode(common()->Branch(hint), condition, current_control_);
40962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
41062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  current_control_ = graph()->NewNode(common()->IfTrue(), branch);
41162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  MergeState(label, vars...);
41262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
41362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  current_control_ = graph()->NewNode(common()->IfFalse(), branch);
41462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
41562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
41662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <class LabelType, typename... Vars>
41762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid GraphAssembler::GotoUnless(Node* condition, LabelType* label,
41862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                Vars... vars) {
41962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  BranchHint hint = label->IsDeferred() ? BranchHint::kTrue : BranchHint::kNone;
42062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* branch =
42162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      graph()->NewNode(common()->Branch(hint), condition, current_control_);
42262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
42362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  current_control_ = graph()->NewNode(common()->IfFalse(), branch);
42462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  MergeState(label, vars...);
42562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
42662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  current_control_ = graph()->NewNode(common()->IfTrue(), branch);
42762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
42862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
42962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <typename... Args>
43062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* GraphAssembler::Call(const CallDescriptor* desc, Args... args) {
43162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const Operator* op = common()->Call(desc);
43262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return Call(op, args...);
43362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
43462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
43562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <typename... Args>
43662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* GraphAssembler::Call(const Operator* op, Args... args) {
43762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(IrOpcode::kCall, op->opcode());
43862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* args_array[] = {args..., current_effect_, current_control_};
43962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int size = static_cast<int>(sizeof...(args)) + op->EffectInputCount() +
44062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch             op->ControlInputCount();
44162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* call = graph()->NewNode(op, size, args_array);
44262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(0, op->ControlOutputCount());
44362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  current_effect_ = call;
44462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return call;
44562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
44662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
44762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}  // namespace compiler
44862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}  // namespace internal
44962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}  // namespace v8
45062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
45162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#endif  // V8_COMPILER_GRAPH_ASSEMBLER_H_
452