summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/control-builders.h
blob: 6ff00be59614378dd8be96943bbe77ba5e35479d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// Copyright 2013 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_CONTROL_BUILDERS_H_
#define V8_COMPILER_CONTROL_BUILDERS_H_

#include "src/compiler/ast-graph-builder.h"
#include "src/compiler/node.h"

namespace v8 {
namespace internal {
namespace compiler {

// Base class for all control builders. Also provides a common interface for
// control builders to handle 'break' statements when they are used to model
// breakable statements.
class ControlBuilder {
 public:
  explicit ControlBuilder(AstGraphBuilder* builder) : builder_(builder) {}
  virtual ~ControlBuilder() {}

  // Interface for break.
  virtual void Break() { UNREACHABLE(); }

 protected:
  typedef AstGraphBuilder Builder;
  typedef AstGraphBuilder::Environment Environment;

  Zone* zone() const { return builder_->local_zone(); }
  Environment* environment() { return builder_->environment(); }
  void set_environment(Environment* env) { builder_->set_environment(env); }
  Node* the_hole() const { return builder_->jsgraph()->TheHoleConstant(); }

  Builder* builder_;
};


// Tracks control flow for a conditional statement.
class IfBuilder final : public ControlBuilder {
 public:
  explicit IfBuilder(AstGraphBuilder* builder)
      : ControlBuilder(builder),
        then_environment_(nullptr),
        else_environment_(nullptr) {}

  // Primitive control commands.
  void If(Node* condition, BranchHint hint = BranchHint::kNone);
  void Then();
  void Else();
  void End();

 private:
  Environment* then_environment_;  // Environment after the 'then' body.
  Environment* else_environment_;  // Environment for the 'else' body.
};


// Tracks control flow for an iteration statement.
class LoopBuilder final : public ControlBuilder {
 public:
  explicit LoopBuilder(AstGraphBuilder* builder)
      : ControlBuilder(builder),
        loop_environment_(nullptr),
        continue_environment_(nullptr),
        break_environment_(nullptr) {}

  // Primitive control commands.
  void BeginLoop(BitVector* assigned, bool is_osr = false);
  void Continue();
  void EndBody();
  void EndLoop();

  // Primitive support for break.
  void Break() final;

  // Compound control commands for conditional break.
  void BreakUnless(Node* condition);
  void BreakWhen(Node* condition);

 private:
  Environment* loop_environment_;      // Environment of the loop header.
  Environment* continue_environment_;  // Environment after the loop body.
  Environment* break_environment_;     // Environment after the loop exits.
};


// Tracks control flow for a switch statement.
class SwitchBuilder final : public ControlBuilder {
 public:
  explicit SwitchBuilder(AstGraphBuilder* builder, int case_count)
      : ControlBuilder(builder),
        body_environment_(nullptr),
        label_environment_(nullptr),
        break_environment_(nullptr),
        body_environments_(case_count, zone()) {}

  // Primitive control commands.
  void BeginSwitch();
  void BeginLabel(int index, Node* condition);
  void EndLabel();
  void DefaultAt(int index);
  void BeginCase(int index);
  void EndCase();
  void EndSwitch();

  // Primitive support for break.
  void Break() final;

  // The number of cases within a switch is statically known.
  size_t case_count() const { return body_environments_.size(); }

 private:
  Environment* body_environment_;   // Environment after last case body.
  Environment* label_environment_;  // Environment for next label condition.
  Environment* break_environment_;  // Environment after the switch exits.
  ZoneVector<Environment*> body_environments_;
};


// Tracks control flow for a block statement.
class BlockBuilder final : public ControlBuilder {
 public:
  explicit BlockBuilder(AstGraphBuilder* builder)
      : ControlBuilder(builder), break_environment_(nullptr) {}

  // Primitive control commands.
  void BeginBlock();
  void EndBlock();

  // Primitive support for break.
  void Break() final;

  // Compound control commands for conditional break.
  void BreakWhen(Node* condition, BranchHint = BranchHint::kNone);
  void BreakUnless(Node* condition, BranchHint hint = BranchHint::kNone);

 private:
  Environment* break_environment_;  // Environment after the block exits.
};


// Tracks control flow for a try-catch statement.
class TryCatchBuilder final : public ControlBuilder {
 public:
  explicit TryCatchBuilder(AstGraphBuilder* builder)
      : ControlBuilder(builder),
        catch_environment_(nullptr),
        exit_environment_(nullptr),
        exception_node_(nullptr) {}

  // Primitive control commands.
  void BeginTry();
  void Throw(Node* exception);
  void EndTry();
  void EndCatch();

  // Returns the exception value inside the 'catch' body.
  Node* GetExceptionNode() const { return exception_node_; }

 private:
  Environment* catch_environment_;  // Environment for the 'catch' body.
  Environment* exit_environment_;   // Environment after the statement.
  Node* exception_node_;            // Node for exception in 'catch' body.
};


// Tracks control flow for a try-finally statement.
class TryFinallyBuilder final : public ControlBuilder {
 public:
  explicit TryFinallyBuilder(AstGraphBuilder* builder)
      : ControlBuilder(builder),
        finally_environment_(nullptr),
        token_node_(nullptr),
        value_node_(nullptr) {}

  // Primitive control commands.
  void BeginTry();
  void LeaveTry(Node* token, Node* value);
  void EndTry(Node* token, Node* value);
  void EndFinally();

  // Returns the dispatch token value inside the 'finally' body.
  Node* GetDispatchTokenNode() const { return token_node_; }

  // Returns the saved result value inside the 'finally' body.
  Node* GetResultValueNode() const { return value_node_; }

 private:
  Environment* finally_environment_;  // Environment for the 'finally' body.
  Node* token_node_;                  // Node for token in 'finally' body.
  Node* value_node_;                  // Node for value in 'finally' body.
};

}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_COMPILER_CONTROL_BUILDERS_H_