OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 #ifndef VM_FLOW_GRAPH_BUILDER_H_ | |
6 #define VM_FLOW_GRAPH_BUILDER_H_ | |
7 | |
8 #include "vm/allocation.h" | |
9 #include "vm/ast.h" | |
10 #include "vm/growable_array.h" | |
11 #include "vm/intermediate_language.h" | |
12 | |
13 namespace dart { | |
14 | |
15 class Instruction; | |
16 class ParsedFunction; | |
17 | |
18 class FlowGraphBuilder: public ValueObject { | |
srdjan
2012/02/22 00:41:34
Please add a comment description to this class.
Kevin Millikin (Google)
2012/02/22 13:15:42
Done.
| |
19 public: | |
20 explicit FlowGraphBuilder(const ParsedFunction& parsed_function) | |
21 : parsed_function_(parsed_function), bailout_reason_(NULL) { } | |
srdjan
2012/02/21 14:33:41
We like to list/initialize all instance fields in
Kevin Millikin (Google)
2012/02/22 13:15:42
Done.
| |
22 | |
23 void BuildGraph(); | |
24 | |
25 const ParsedFunction& parsed_function() const { return parsed_function_; } | |
26 | |
27 void Bailout(const char* reason) { bailout_reason_ = reason; } | |
srdjan
2012/02/22 00:41:34
ASSERT(bailout_reason_ == NULL), otherwise the bai
Kevin Millikin (Google)
2012/02/22 13:15:42
Done.
| |
28 void TraceBailout() const; | |
29 void PrintGraph() const; | |
30 | |
31 private: | |
32 const ParsedFunction& parsed_function_; | |
33 const char* bailout_reason_; | |
34 GrowableArray<Instruction*> postorder_; | |
35 }; | |
36 | |
37 | |
38 #define DEFINE_VISIT(type, name) virtual void Visit##type(type* node); | |
39 | |
40 class TestGraphVisitor; | |
srdjan
2012/02/22 00:41:34
Comment: Class name TestGraphVisitor sounds like a
Kevin Millikin (Google)
2012/02/22 13:15:42
I agree, but it's nice and short. Alternatives ar
srdjan
2012/02/22 14:08:16
?
TestGraphVisitor and ConditionVisitor are longe
| |
41 | |
42 // Translate an AstNode to a control-flow graph fragment for its effects | |
43 // (e.g., a statement or an expression in an effect context). Implements a | |
44 // function from an AstNode and next temporary index to a graph fragment | |
45 // with a single entry and at most one exit. The fragment is represented by | |
46 // an (entry, exit) pair of Instruction pointers: | |
47 // | |
48 // - (NULL, NULL): an empty graph fragment | |
srdjan
2012/02/21 14:33:41
an empty and open graph fragment.
Kevin Millikin (Google)
2012/02/22 13:15:42
Done.
| |
49 // - (i0, NULL): a closed graph fragment which has only non-local exits | |
50 // - (i0, i1): an open graph fragment | |
51 class EffectGraphVisitor : public AstNodeVisitor { | |
52 public: | |
53 EffectGraphVisitor(FlowGraphBuilder* owner, intptr_t temp_index) | |
54 : owner_(owner), | |
55 temp_index_(temp_index), | |
56 entry_(NULL), | |
57 exit_(NULL), | |
58 bailing_out_(false) { } | |
59 | |
60 NODE_LIST(DEFINE_VISIT) | |
61 | |
62 FlowGraphBuilder* owner() const { return owner_; } | |
63 intptr_t temp_index() const { return temp_index_; } | |
64 Instruction* entry() const { return entry_; } | |
65 Instruction* exit() const { return exit_; } | |
66 | |
67 bool is_empty() const { return entry_ == NULL; } | |
68 bool is_open() const { return is_empty() || exit_ != NULL; } | |
69 | |
70 void Bailout(const char* reason); | |
71 | |
72 // Append a graph fragment to this graph. Assumes this graph is open. | |
73 void Append(const EffectGraphVisitor& other_fragment); | |
74 // Append a single instruction. Assumes this graph is open. | |
75 void AddInstruction(Instruction* instruction); | |
76 | |
77 // Append a 'diamond' branch and join to this graph, depending on which | |
78 // parts are reachable. Assumes this graph is open. | |
79 void Join(const TestGraphVisitor& test_fragment, | |
80 const EffectGraphVisitor& true_fragment, | |
81 const EffectGraphVisitor& false_fragment); | |
82 | |
83 // Append a 'while loop' test and back edge to this graph, depending on | |
84 // which parts are reachable. Afterward, the graph exit is the false | |
85 // successor of the loop condition. | |
86 void TieLoop(const TestGraphVisitor& test_fragment, | |
87 const EffectGraphVisitor& body_fragment); | |
88 | |
89 protected: | |
90 bool bailing_out() const { return bailing_out_; } | |
91 | |
92 // Implement the core part of the translation of expression node types. | |
93 AssertAssignableComp* TranslateAssignable(AssignableNode* node); | |
srdjan
2012/02/21 14:33:41
The node parameter in TranslateXXX could it be a c
Kevin Millikin (Google)
2012/02/22 13:15:42
Yup. Done. I think it looks strange to dereferen
srdjan
2012/02/22 14:08:16
By passing a reference you guarantee that the valu
| |
94 InstanceCallComp* TranslateBinaryOp(BinaryOpNode* node); | |
95 InstanceCallComp* TranslateComparison(ComparisonNode* node); | |
96 StoreLocalComp* TranslateStoreLocal(StoreLocalNode* node); | |
97 StaticCallComp* TranslateStaticCall(StaticCallNode* node); | |
98 | |
99 void CloseFragment() { exit_ = NULL; } | |
100 intptr_t AllocateTempIndex() { return temp_index_++; } | |
101 | |
102 private: | |
103 // Helper to append a Do instruction to the graph. | |
104 void DoComputation(Computation* computation) { | |
105 AddInstruction(new DoInstr(computation)); | |
106 } | |
107 | |
108 // Shared global state. | |
109 FlowGraphBuilder* owner_; | |
110 | |
111 // Input parameters. | |
112 intptr_t temp_index_; | |
113 | |
114 // Output parameters. | |
115 Instruction* entry_; | |
116 Instruction* exit_; | |
117 | |
118 // Local state. | |
119 bool bailing_out_; | |
120 }; | |
121 | |
122 | |
123 // Translate an AstNode to a control-flow graph fragment for both its effects | |
124 // and value (e.g., for an expression in a value context). Implements a | |
125 // function from an AstNode and next temporary index to a graph fragment (as | |
126 // in the EffectGraphVisitor), a next temporary index, and a intermediate | |
srdjan
2012/02/21 14:33:41
"an intermediate"
Kevin Millikin (Google)
2012/02/22 13:15:42
Done.
| |
127 // language Value. | |
128 class ValueGraphVisitor : public EffectGraphVisitor { | |
129 public: | |
130 ValueGraphVisitor(FlowGraphBuilder* owner, intptr_t temp_index) | |
131 : EffectGraphVisitor(owner, temp_index), value_(NULL) { } | |
132 | |
133 NODE_LIST(DEFINE_VISIT) | |
134 | |
135 Value* value() const { return value_; } | |
136 | |
137 private: | |
138 // Helper to set the output state to return a Value. | |
139 void ReturnValue(Value* value) { value_ = value; } | |
140 | |
141 // Helper to append a Bind instruction to the graph and return its | |
142 // temporary value (i.e., set the output parameters). | |
143 void ReturnValueOf(Computation* computation) { | |
144 AddInstruction(new BindInstr(temp_index(), computation)); | |
145 value_ = new TempValue(AllocateTempIndex()); | |
146 } | |
147 | |
148 // Output parameters. | |
149 Value* value_; | |
150 }; | |
151 | |
152 | |
153 // Translate an AstNode to a control-flow graph fragment for both its | |
154 // effects and true/false control flow (e.g., for an expression in a test | |
155 // context). The resulting graph is always closed (even if it is empty) | |
156 // Successor control flow is explicitly set by a pair of pointers to | |
157 // TargetEntryInstr*. | |
158 // | |
159 // To distinguish between the graphs with only nonlocal exits, graphs that | |
160 // are unconditionally true or else unconditionally false, and graphs with | |
161 // both true and false exits, there are a pair of TargetEntryInstr**: | |
162 // | |
163 // - Both NULL: only non-local exits, truly closed | |
164 // - One NULL: unconditionally true or else unconditionally false | |
165 // - Neither NULL: true and false successors at the given addresses | |
166 class TestGraphVisitor : public EffectGraphVisitor { | |
167 public: | |
168 TestGraphVisitor(FlowGraphBuilder* owner, intptr_t temp_index) | |
169 : EffectGraphVisitor(owner, temp_index), | |
170 true_successor_address_(NULL), | |
171 false_successor_address_(NULL) { | |
srdjan
2012/02/21 14:33:41
You need to initialize is_true_. Actually, I do no
Kevin Millikin (Google)
2012/02/22 13:15:42
Yeah, that's a leftover. Thanks for spotting it.
| |
172 } | |
173 | |
174 NODE_LIST(DEFINE_VISIT) | |
175 | |
176 bool can_be_true() const { | |
177 return true_successor_address_ != NULL; | |
178 } | |
179 bool can_be_false() const { | |
180 return false_successor_address_ != NULL; | |
181 } | |
182 | |
srdjan
2012/02/21 14:33:41
As mentioned, please remove can_be_true and can_be
| |
183 TargetEntryInstr** true_successor_address() const { | |
184 return true_successor_address_; | |
185 } | |
186 TargetEntryInstr** false_successor_address() const { | |
187 return false_successor_address_; | |
188 } | |
189 | |
190 private: | |
191 // Construct and concatenate a Branch instruction to this graph fragment. | |
192 // Closes the fragment and sets the output parameters. | |
193 void BranchOnValue(Value* value); | |
194 | |
195 // Helper to bind a computation and branch on its value. | |
196 void BranchOnValueOf(Computation* computation) { | |
197 AddInstruction(new BindInstr(temp_index(), computation)); | |
198 BranchOnValue(new TempValue(temp_index())); | |
199 } | |
200 | |
201 // Output parameters. | |
202 bool is_true_; | |
203 TargetEntryInstr** true_successor_address_; | |
204 TargetEntryInstr** false_successor_address_; | |
205 }; | |
206 | |
207 #undef DEFINE_VISIT | |
208 | |
209 | |
210 } // namespace dart | |
211 | |
212 #endif // VM_FLOW_GRAPH_BUILDER_H_ | |
OLD | NEW |