Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_FLOW_GRAPH_BUILDER_H_ | 5 #ifndef VM_FLOW_GRAPH_BUILDER_H_ |
| 6 #define VM_FLOW_GRAPH_BUILDER_H_ | 6 #define VM_FLOW_GRAPH_BUILDER_H_ |
| 7 | 7 |
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
| 9 #include "vm/ast.h" | 9 #include "vm/ast.h" |
| 10 #include "vm/growable_array.h" | 10 #include "vm/growable_array.h" |
| 11 #include "vm/intermediate_language.h" | 11 #include "vm/intermediate_language.h" |
| 12 | 12 |
| 13 namespace dart { | 13 namespace dart { |
| 14 | 14 |
| 15 class FlowGraph; | 15 class FlowGraph; |
| 16 class Instruction; | 16 class Instruction; |
| 17 class ParsedFunction; | 17 class ParsedFunction; |
| 18 | 18 |
| 19 // An abstraction of the graph context in which an inlined call occurs. | |
| 20 class InliningContext: public ZoneAllocated { | |
| 21 public: | |
| 22 virtual void AddExit(ReturnInstr* exit) = 0; | |
| 23 }; | |
| 24 | |
| 25 | |
| 26 // The context of a call inlined for its value (including calls inlined for | |
| 27 // their effects, i.e., when the value is ignored). Collects normal exit | |
| 28 // blocks and return values. | |
| 29 class ValueInliningContext: public InliningContext { | |
| 30 public: | |
| 31 ValueInliningContext() : exits_(4) { } | |
| 32 | |
| 33 BlockEntryInstr* ExitBlockAt(intptr_t i) const { | |
| 34 ASSERT(exits_[i].exit_block != NULL); | |
| 35 return exits_[i].exit_block; | |
| 36 } | |
| 37 Instruction* LastInstructionAt(intptr_t i) const { | |
| 38 return exits_[i].exit_return->previous(); | |
| 39 } | |
| 40 Value* ValueAt(intptr_t i) const { | |
| 41 return exits_[i].exit_return->value(); | |
| 42 } | |
| 43 | |
| 44 intptr_t NumExits() { return exits_.length(); } | |
|
srdjan
2013/01/11 21:40:26
const
| |
| 45 virtual void AddExit(ReturnInstr* exit); | |
| 46 void SortExits(); | |
| 47 | |
| 48 private: | |
| 49 struct Data { | |
| 50 BlockEntryInstr* exit_block; | |
| 51 ReturnInstr* exit_return; | |
| 52 }; | |
| 53 | |
| 54 static int LowestBlockIdFirst(const Data* a, const Data* b); | |
| 55 | |
| 56 GrowableArray<Data> exits_; | |
| 57 }; | |
| 58 | |
| 59 | |
| 19 // Build a flow graph from a parsed function's AST. | 60 // Build a flow graph from a parsed function's AST. |
| 20 class FlowGraphBuilder: public ValueObject { | 61 class FlowGraphBuilder: public ValueObject { |
| 21 public: | 62 public: |
| 22 explicit FlowGraphBuilder(const ParsedFunction& parsed_function); | 63 // The inlining context is NULL if not inlining. |
| 64 FlowGraphBuilder(const ParsedFunction& parsed_function, | |
| 65 InliningContext* inlining_context); | |
|
srdjan
2013/01/11 21:40:26
An alternative could be to pass an instance of cla
| |
| 23 | 66 |
| 24 enum InliningContext { | 67 FlowGraph* BuildGraph(intptr_t initial_loop_depth); |
| 25 kNotInlining, | |
| 26 kValueContext, | |
| 27 kEffectContext, | |
| 28 kTestContext | |
| 29 }; | |
| 30 | |
| 31 FlowGraph* BuildGraph(InliningContext context, intptr_t initial_loop_depth); | |
| 32 | 68 |
| 33 const ParsedFunction& parsed_function() const { return parsed_function_; } | 69 const ParsedFunction& parsed_function() const { return parsed_function_; } |
| 34 | 70 |
| 35 void Bailout(const char* reason); | 71 void Bailout(const char* reason); |
| 36 | 72 |
| 37 intptr_t AllocateBlockId() { return ++last_used_block_id_; } | 73 intptr_t AllocateBlockId() { return ++last_used_block_id_; } |
| 38 void SetInitialBlockId(intptr_t id) { last_used_block_id_ = id; } | 74 void SetInitialBlockId(intptr_t id) { last_used_block_id_ = id; } |
| 39 | 75 |
| 40 void set_context_level(intptr_t value) { context_level_ = value; } | 76 void set_context_level(intptr_t value) { context_level_ = value; } |
| 41 intptr_t context_level() const { return context_level_; } | 77 intptr_t context_level() const { return context_level_; } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 52 intptr_t num_copied_params() const { | 88 intptr_t num_copied_params() const { |
| 53 return num_copied_params_; | 89 return num_copied_params_; |
| 54 } | 90 } |
| 55 intptr_t num_non_copied_params() const { | 91 intptr_t num_non_copied_params() const { |
| 56 return num_non_copied_params_; | 92 return num_non_copied_params_; |
| 57 } | 93 } |
| 58 intptr_t num_stack_locals() const { | 94 intptr_t num_stack_locals() const { |
| 59 return num_stack_locals_; | 95 return num_stack_locals_; |
| 60 } | 96 } |
| 61 | 97 |
| 62 bool InInliningContext() const { return inlining_context_ != kNotInlining; } | 98 bool InInliningContext() const { return (inlining_context_ != NULL); } |
| 63 void AddReturnExit(ReturnInstr* return_instr) { | 99 InliningContext* inlining_context() const { return inlining_context_; } |
| 64 if (InInliningContext()) { | |
| 65 ASSERT(exits_ != NULL); | |
| 66 exits_->Add(return_instr); | |
| 67 } | |
| 68 } | |
| 69 | 100 |
| 70 private: | 101 private: |
| 71 intptr_t parameter_count() const { | 102 intptr_t parameter_count() const { |
| 72 return num_copied_params_ + num_non_copied_params_; | 103 return num_copied_params_ + num_non_copied_params_; |
| 73 } | 104 } |
| 74 intptr_t variable_count() const { | 105 intptr_t variable_count() const { |
| 75 return parameter_count() + num_stack_locals_; | 106 return parameter_count() + num_stack_locals_; |
| 76 } | 107 } |
| 77 | 108 |
| 78 const ParsedFunction& parsed_function_; | 109 const ParsedFunction& parsed_function_; |
| 79 | 110 |
| 80 const intptr_t num_copied_params_; | 111 const intptr_t num_copied_params_; |
| 81 const intptr_t num_non_copied_params_; | 112 const intptr_t num_non_copied_params_; |
| 82 const intptr_t num_stack_locals_; // Does not include any parameters. | 113 const intptr_t num_stack_locals_; // Does not include any parameters. |
| 114 InliningContext* const inlining_context_; | |
| 83 | 115 |
| 84 intptr_t last_used_block_id_; | 116 intptr_t last_used_block_id_; |
| 85 intptr_t context_level_; | 117 intptr_t context_level_; |
| 86 intptr_t last_used_try_index_; | 118 intptr_t last_used_try_index_; |
| 87 intptr_t try_index_; | 119 intptr_t try_index_; |
| 88 GraphEntryInstr* graph_entry_; | 120 GraphEntryInstr* graph_entry_; |
| 89 InliningContext inlining_context_; | |
| 90 ZoneGrowableArray<ReturnInstr*>* exits_; | |
| 91 | 121 |
| 92 DISALLOW_IMPLICIT_CONSTRUCTORS(FlowGraphBuilder); | 122 DISALLOW_IMPLICIT_CONSTRUCTORS(FlowGraphBuilder); |
| 93 }; | 123 }; |
| 94 | 124 |
| 95 | 125 |
| 96 class TestGraphVisitor; | 126 class TestGraphVisitor; |
| 97 | 127 |
| 98 // Translate an AstNode to a control-flow graph fragment for its effects | 128 // Translate an AstNode to a control-flow graph fragment for its effects |
| 99 // (e.g., a statement or an expression in an effect context). Implements a | 129 // (e.g., a statement or an expression in an effect context). Implements a |
| 100 // function from an AstNode and next temporary index to a graph fragment | 130 // function from an AstNode and next temporary index to a graph fragment |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 156 void TieLoop(const TestGraphVisitor& test_fragment, | 186 void TieLoop(const TestGraphVisitor& test_fragment, |
| 157 const EffectGraphVisitor& body_fragment); | 187 const EffectGraphVisitor& body_fragment); |
| 158 | 188 |
| 159 // Wraps a value in a push-argument instruction and adds the result to the | 189 // Wraps a value in a push-argument instruction and adds the result to the |
| 160 // graph. | 190 // graph. |
| 161 PushArgumentInstr* PushArgument(Value* value); | 191 PushArgumentInstr* PushArgument(Value* value); |
| 162 | 192 |
| 163 // This implementation shares state among visitors by using the builder. | 193 // This implementation shares state among visitors by using the builder. |
| 164 // The implementation is incorrect if a visitor that hits a return is not | 194 // The implementation is incorrect if a visitor that hits a return is not |
| 165 // actually added to the graph. | 195 // actually added to the graph. |
| 166 void AddReturnExit(ReturnInstr* return_instr) { | 196 void AddReturnExit(intptr_t token_pos, Value* value); |
| 167 owner()->AddReturnExit(return_instr); | |
| 168 } | |
| 169 | 197 |
| 170 protected: | 198 protected: |
| 171 Definition* BuildStoreTemp(const LocalVariable& local, Value* value); | 199 Definition* BuildStoreTemp(const LocalVariable& local, Value* value); |
| 172 Definition* BuildStoreExprTemp(Value* value); | 200 Definition* BuildStoreExprTemp(Value* value); |
| 173 Definition* BuildLoadExprTemp(); | 201 Definition* BuildLoadExprTemp(); |
| 174 | 202 |
| 175 Definition* BuildStoreLocal(const LocalVariable& local, | 203 Definition* BuildStoreLocal(const LocalVariable& local, |
| 176 Value* value, | 204 Value* value, |
| 177 bool result_is_needed); | 205 bool result_is_needed); |
| 178 Definition* BuildLoadLocal(const LocalVariable& local); | 206 Definition* BuildLoadLocal(const LocalVariable& local); |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 417 // Output parameters. | 445 // Output parameters. |
| 418 GrowableArray<TargetEntryInstr**> true_successor_addresses_; | 446 GrowableArray<TargetEntryInstr**> true_successor_addresses_; |
| 419 GrowableArray<TargetEntryInstr**> false_successor_addresses_; | 447 GrowableArray<TargetEntryInstr**> false_successor_addresses_; |
| 420 | 448 |
| 421 intptr_t condition_token_pos_; | 449 intptr_t condition_token_pos_; |
| 422 }; | 450 }; |
| 423 | 451 |
| 424 } // namespace dart | 452 } // namespace dart |
| 425 | 453 |
| 426 #endif // VM_FLOW_GRAPH_BUILDER_H_ | 454 #endif // VM_FLOW_GRAPH_BUILDER_H_ |
| OLD | NEW |