Line data Source code
1 : // Copyright 2015 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_INTERPRETER_CONTROL_FLOW_BUILDERS_H_
6 : #define V8_INTERPRETER_CONTROL_FLOW_BUILDERS_H_
7 :
8 : #include "src/interpreter/bytecode-array-builder.h"
9 :
10 : #include "src/interpreter/bytecode-label.h"
11 : #include "src/zone/zone-containers.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 : namespace interpreter {
16 :
17 : class V8_EXPORT_PRIVATE ControlFlowBuilder BASE_EMBEDDED {
18 : public:
19 : explicit ControlFlowBuilder(BytecodeArrayBuilder* builder)
20 5619873 : : builder_(builder) {}
21 5443346 : virtual ~ControlFlowBuilder() {}
22 :
23 : protected:
24 : BytecodeArrayBuilder* builder() const { return builder_; }
25 :
26 : private:
27 : BytecodeArrayBuilder* builder_;
28 :
29 : DISALLOW_COPY_AND_ASSIGN(ControlFlowBuilder);
30 : };
31 :
32 : class V8_EXPORT_PRIVATE BreakableControlFlowBuilder
33 : : public ControlFlowBuilder {
34 : public:
35 5443341 : explicit BreakableControlFlowBuilder(BytecodeArrayBuilder* builder)
36 5443341 : : ControlFlowBuilder(builder), break_labels_(builder->zone()) {}
37 : virtual ~BreakableControlFlowBuilder();
38 :
39 : // This method should be called by the control flow owner before
40 : // destruction to update sites that emit jumps for break.
41 : void BindBreakTarget();
42 :
43 : // This method is called when visiting break statements in the AST.
44 : // Inserts a jump to an unbound label that is patched when the corresponding
45 : // BindBreakTarget is called.
46 88395 : void Break() { EmitJump(&break_labels_); }
47 : void BreakIfTrue(BytecodeArrayBuilder::ToBooleanMode mode) {
48 31823 : EmitJumpIfTrue(mode, &break_labels_);
49 : }
50 : void BreakIfFalse(BytecodeArrayBuilder::ToBooleanMode mode) {
51 5764 : EmitJumpIfFalse(mode, &break_labels_);
52 : }
53 : void BreakIfUndefined() { EmitJumpIfUndefined(&break_labels_); }
54 : void BreakIfNull() { EmitJumpIfNull(&break_labels_); }
55 :
56 : BytecodeLabels* break_labels() { return &break_labels_; }
57 :
58 : protected:
59 : void EmitJump(BytecodeLabels* labels);
60 : void EmitJumpIfTrue(BytecodeArrayBuilder::ToBooleanMode mode,
61 : BytecodeLabels* labels);
62 : void EmitJumpIfFalse(BytecodeArrayBuilder::ToBooleanMode mode,
63 : BytecodeLabels* labels);
64 : void EmitJumpIfUndefined(BytecodeLabels* labels);
65 : void EmitJumpIfNull(BytecodeLabels* labels);
66 :
67 : // Unbound labels that identify jumps for break statements in the code.
68 : BytecodeLabels break_labels_;
69 : };
70 :
71 :
72 : // Class to track control flow for block statements (which can break in JS).
73 5183159 : class V8_EXPORT_PRIVATE BlockBuilder final
74 : : public BreakableControlFlowBuilder {
75 : public:
76 : explicit BlockBuilder(BytecodeArrayBuilder* builder)
77 5183158 : : BreakableControlFlowBuilder(builder) {}
78 :
79 : void EndBlock();
80 :
81 : private:
82 : BytecodeLabel block_end_;
83 : };
84 :
85 :
86 : // A class to help with co-ordinating break and continue statements with
87 : // their loop.
88 : class V8_EXPORT_PRIVATE LoopBuilder final : public BreakableControlFlowBuilder {
89 : public:
90 : explicit LoopBuilder(BytecodeArrayBuilder* builder)
91 : : BreakableControlFlowBuilder(builder),
92 : continue_labels_(builder->zone()),
93 193044 : header_labels_(builder->zone()) {}
94 : ~LoopBuilder();
95 :
96 : void LoopHeader(ZoneVector<BytecodeLabel>* additional_labels = nullptr);
97 : void JumpToHeader(int loop_depth);
98 : void BindContinueTarget();
99 : void EndLoop();
100 :
101 : // This method is called when visiting continue statements in the AST.
102 : // Inserts a jump to an unbound label that is patched when BindContinueTarget
103 : // is called.
104 11886 : void Continue() { EmitJump(&continue_labels_); }
105 5764 : void ContinueIfUndefined() { EmitJumpIfUndefined(&continue_labels_); }
106 : void ContinueIfNull() { EmitJumpIfNull(&continue_labels_); }
107 :
108 : private:
109 : BytecodeLabel loop_header_;
110 :
111 : // Unbound labels that identify jumps for continue statements in the code and
112 : // jumps from checking the loop condition to the header for do-while loops.
113 : BytecodeLabels continue_labels_;
114 : BytecodeLabels header_labels_;
115 : };
116 :
117 :
118 : // A class to help with co-ordinating break statements with their switch.
119 : class V8_EXPORT_PRIVATE SwitchBuilder final
120 : : public BreakableControlFlowBuilder {
121 : public:
122 67139 : explicit SwitchBuilder(BytecodeArrayBuilder* builder, int number_of_cases)
123 : : BreakableControlFlowBuilder(builder),
124 67139 : case_sites_(builder->zone()) {
125 67139 : case_sites_.resize(number_of_cases);
126 67139 : }
127 : ~SwitchBuilder();
128 :
129 : // This method should be called by the SwitchBuilder owner when the case
130 : // statement with |index| is emitted to update the case jump site.
131 : void SetCaseTarget(int index);
132 :
133 : // This method is called when visiting case comparison operation for |index|.
134 : // Inserts a JumpIfTrue with ToBooleanMode |mode| to a unbound label that is
135 : // patched when the corresponding SetCaseTarget is called.
136 195686 : void Case(BytecodeArrayBuilder::ToBooleanMode mode, int index) {
137 391372 : builder()->JumpIfTrue(mode, &case_sites_.at(index));
138 195685 : }
139 :
140 : // This method is called when all cases comparisons have been emitted if there
141 : // is a default case statement. Inserts a Jump to a unbound label that is
142 : // patched when the corresponding SetCaseTarget is called.
143 110166 : void DefaultAt(int index) { builder()->Jump(&case_sites_.at(index)); }
144 :
145 : private:
146 : // Unbound labels that identify jumps for case statements in the code.
147 : ZoneVector<BytecodeLabel> case_sites_;
148 : };
149 :
150 :
151 : // A class to help with co-ordinating control flow in try-catch statements.
152 0 : class V8_EXPORT_PRIVATE TryCatchBuilder final : public ControlFlowBuilder {
153 : public:
154 : explicit TryCatchBuilder(BytecodeArrayBuilder* builder,
155 : HandlerTable::CatchPrediction catch_prediction)
156 : : ControlFlowBuilder(builder),
157 : handler_id_(builder->NewHandlerEntry()),
158 256532 : catch_prediction_(catch_prediction) {}
159 :
160 : void BeginTry(Register context);
161 : void EndTry();
162 : void EndCatch();
163 :
164 : private:
165 : int handler_id_;
166 : HandlerTable::CatchPrediction catch_prediction_;
167 : BytecodeLabel handler_;
168 : BytecodeLabel exit_;
169 : };
170 :
171 :
172 : // A class to help with co-ordinating control flow in try-finally statements.
173 0 : class V8_EXPORT_PRIVATE TryFinallyBuilder final : public ControlFlowBuilder {
174 : public:
175 48266 : explicit TryFinallyBuilder(BytecodeArrayBuilder* builder,
176 : HandlerTable::CatchPrediction catch_prediction)
177 : : ControlFlowBuilder(builder),
178 : handler_id_(builder->NewHandlerEntry()),
179 : catch_prediction_(catch_prediction),
180 96532 : finalization_sites_(builder->zone()) {}
181 :
182 : void BeginTry(Register context);
183 : void LeaveTry();
184 : void EndTry();
185 : void BeginHandler();
186 : void BeginFinally();
187 : void EndFinally();
188 :
189 : private:
190 : int handler_id_;
191 : HandlerTable::CatchPrediction catch_prediction_;
192 : BytecodeLabel handler_;
193 :
194 : // Unbound labels that identify jumps to the finally block in the code.
195 : BytecodeLabels finalization_sites_;
196 : };
197 :
198 : } // namespace interpreter
199 : } // namespace internal
200 : } // namespace v8
201 :
202 : #endif // V8_INTERPRETER_CONTROL_FLOW_BUILDERS_H_
|