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_COMPILER_X64_H_ | 5 #ifndef VM_FLOW_GRAPH_COMPILER_X64_H_ |
6 #define VM_FLOW_GRAPH_COMPILER_X64_H_ | 6 #define VM_FLOW_GRAPH_COMPILER_X64_H_ |
7 | 7 |
8 #ifndef VM_FLOW_GRAPH_COMPILER_H_ | 8 #ifndef VM_FLOW_GRAPH_COMPILER_H_ |
9 #error Include flow_graph_compiler.h instead of flow_graph_compiler_x64.h. | 9 #error Include flow_graph_compiler.h instead of flow_graph_compiler_x64.h. |
10 #endif | 10 #endif |
11 | 11 |
12 #include "vm/assembler.h" | 12 #include "vm/assembler.h" |
13 #include "vm/assembler_macros.h" | 13 #include "vm/assembler_macros.h" |
14 #include "vm/code_descriptors.h" | 14 #include "vm/code_descriptors.h" |
15 #include "vm/code_generator.h" | 15 #include "vm/code_generator.h" |
16 #include "vm/flow_graph_compiler_shared.h" | |
17 #include "vm/intermediate_language.h" | 16 #include "vm/intermediate_language.h" |
18 | 17 |
19 namespace dart { | 18 namespace dart { |
20 | 19 |
21 class Code; | 20 class Code; |
22 class DeoptimizationStub; | 21 class DeoptimizationStub; |
23 class ExceptionHandlerList; | 22 class ExceptionHandlerList; |
24 template <typename T> class GrowableArray; | 23 template <typename T> class GrowableArray; |
25 class ParsedFunction; | 24 class ParsedFunction; |
26 | 25 |
27 class FlowGraphCompiler : public FlowGraphCompilerShared { | 26 class FlowGraphCompiler : public ValueObject { |
| 27 private: |
| 28 struct BlockInfo : public ZoneAllocated { |
| 29 public: |
| 30 BlockInfo() : label() { } |
| 31 Label label; |
| 32 }; |
| 33 |
28 public: | 34 public: |
29 FlowGraphCompiler(Assembler* assembler, | 35 FlowGraphCompiler(Assembler* assembler, |
30 const ParsedFunction& parsed_function, | 36 const ParsedFunction& parsed_function, |
31 const GrowableArray<BlockEntryInstr*>& block_order, | 37 const GrowableArray<BlockEntryInstr*>& block_order, |
32 bool is_optimizing); | 38 bool is_optimizing); |
33 | 39 |
| 40 virtual ~FlowGraphCompiler(); |
| 41 |
| 42 // Accessors. |
| 43 Assembler* assembler() const { return assembler_; } |
| 44 const ParsedFunction& parsed_function() const { return parsed_function_; } |
| 45 const GrowableArray<BlockEntryInstr*>& block_order() const { |
| 46 return block_order_; |
| 47 } |
| 48 DescriptorList* pc_descriptors_list() const { |
| 49 return pc_descriptors_list_; |
| 50 } |
| 51 BlockEntryInstr* current_block() const { return current_block_; } |
| 52 void set_current_block(BlockEntryInstr* value) { |
| 53 current_block_ = value; |
| 54 } |
| 55 bool is_optimizing() const { return is_optimizing_; } |
| 56 const GrowableArray<BlockInfo*>& block_info() const { return block_info_; } |
| 57 |
| 58 // Constructor is lighweight, major initialization work should occur here. |
| 59 // This makes it easier to measure time spent in the compiler. |
| 60 void InitCompiler(); |
| 61 |
34 void CompileGraph(); | 62 void CompileGraph(); |
35 | 63 |
36 void GenerateCallRuntime(intptr_t cid, | 64 void VisitBlocks(); |
37 intptr_t token_index, | |
38 intptr_t try_index, | |
39 const RuntimeEntry& entry); | |
40 | 65 |
41 private: | 66 // Bail out of the flow graph compiler. Does not return to the caller. |
42 friend class DeoptimizationStub; | 67 void Bailout(const char* reason); |
43 | 68 |
44 // TODO(fschneider): Clean up friend-class declarations once all code | |
45 // generator templates have been moved to intermediate_language_x64.cc. | |
46 #define DECLARE_FRIEND(ShortName, ClassName) friend class ClassName; | |
47 FOR_EACH_COMPUTATION(DECLARE_FRIEND) | |
48 #undef DECLARE_FRIEND | |
49 | 69 |
50 static const int kLocalsOffsetFromFP = (-1 * kWordSize); | 70 // Returns 'true' if code generation for this function is complete, i.e., |
| 71 // no fall-through to regular code is needed. |
| 72 bool TryIntrinsify(); |
51 | 73 |
52 virtual void VisitBlocks(); | 74 virtual void GenerateCallRuntime(intptr_t cid, |
| 75 intptr_t token_index, |
| 76 intptr_t try_index, |
| 77 const RuntimeEntry& entry); |
53 | 78 |
54 void EmitInstructionPrologue(Instruction* instr); | 79 // Infrastructure copied from class CodeGenerator. |
| 80 void GenerateCall(intptr_t token_index, |
| 81 intptr_t try_index, |
| 82 const ExternalLabel* label, |
| 83 PcDescriptors::Kind kind); |
55 | 84 |
56 // Emit code to load a Value into register 'dst'. | 85 void GenerateAssertAssignable(intptr_t cid, |
57 void LoadValue(Register dst, Value* value); | 86 intptr_t token_index, |
| 87 intptr_t try_index, |
| 88 const AbstractType& dst_type, |
| 89 const String& dst_name); |
| 90 |
| 91 void GenerateInstanceOf(intptr_t cid, |
| 92 intptr_t token_index, |
| 93 intptr_t try_index, |
| 94 const AbstractType& type, |
| 95 bool negate_result); |
| 96 |
| 97 void GenerateInstanceCall(intptr_t cid, |
| 98 intptr_t token_index, |
| 99 intptr_t try_index, |
| 100 const String& function_name, |
| 101 intptr_t argument_count, |
| 102 const Array& argument_names, |
| 103 intptr_t checked_argument_count); |
| 104 |
| 105 void GenerateStaticCall(intptr_t cid, |
| 106 intptr_t token_index, |
| 107 intptr_t try_index, |
| 108 const Function& function, |
| 109 intptr_t argument_count, |
| 110 const Array& argument_names); |
| 111 |
| 112 void GenerateNumberTypeCheck(Register kClassIdReg, |
| 113 const AbstractType& type, |
| 114 Label* is_instance_lbl, |
| 115 Label* is_not_instance_lbl); |
| 116 void GenerateStringTypeCheck(Register kClassIdReg, |
| 117 Label* is_instance_lbl, |
| 118 Label* is_not_instance_lbl); |
| 119 void GenerateListTypeCheck(Register kClassIdReg, |
| 120 Label* is_instance_lbl); |
58 | 121 |
59 void EmitComment(Instruction* instr); | 122 void EmitComment(Instruction* instr); |
60 | 123 |
61 // Returns pc-offset (in bytes) of the pc after the call, can be used to emit | 124 // Returns pc-offset (in bytes) of the pc after the call, can be used to emit |
62 // pc-descriptor information. | 125 // pc-descriptor information. |
63 virtual intptr_t EmitInstanceCall(ExternalLabel* target_label, | 126 intptr_t EmitInstanceCall(ExternalLabel* target_label, |
64 const ICData& ic_data, | 127 const ICData& ic_data, |
65 const Array& arguments_descriptor, | 128 const Array& arguments_descriptor, |
66 intptr_t argument_count); | 129 intptr_t argument_count); |
| 130 |
| 131 intptr_t StackSize() const; |
| 132 |
| 133 // Returns assembler label associated with the given block entry. |
| 134 Label* GetBlockLabel(BlockEntryInstr* block_entry) const; |
| 135 |
| 136 // Returns true if the next block after current in the current block order |
| 137 // is the given block. |
| 138 bool IsNextBlock(TargetEntryInstr* block_entry) const; |
| 139 |
| 140 void AddExceptionHandler(intptr_t try_index, intptr_t pc_offset); |
| 141 void AddCurrentDescriptor(PcDescriptors::Kind kind, |
| 142 intptr_t cid, |
| 143 intptr_t token_index, |
| 144 intptr_t try_index); |
| 145 Label* AddDeoptStub(intptr_t deopt_id, |
| 146 intptr_t deopt_token_index, |
| 147 intptr_t try_index_, |
| 148 DeoptReasonId reason, |
| 149 Register reg1, |
| 150 Register reg2); |
| 151 |
| 152 void FinalizeExceptionHandlers(const Code& code); |
| 153 void FinalizePcDescriptors(const Code& code); |
| 154 void FinalizeStackmaps(const Code& code); |
| 155 void FinalizeVarDescriptors(const Code& code); |
| 156 void FinalizeComments(const Code& code); |
| 157 |
| 158 static const int kLocalsOffsetFromFP = (-1 * kWordSize); |
| 159 |
| 160 private: |
| 161 friend class DeoptimizationStub; |
| 162 |
| 163 void GenerateDeferredCode(); |
| 164 |
| 165 virtual void EmitInstructionPrologue(Instruction* instr); |
| 166 |
| 167 // Emit code to load a Value into register 'dst'. |
| 168 void LoadValue(Register dst, Value* value); |
67 | 169 |
68 // Returns pc-offset (in bytes) of the pc after the call, can be used to emit | 170 // Returns pc-offset (in bytes) of the pc after the call, can be used to emit |
69 // pc-descriptor information. | 171 // pc-descriptor information. |
70 virtual intptr_t EmitStaticCall(const Function& function, | 172 virtual intptr_t EmitStaticCall(const Function& function, |
71 const Array& arguments_descriptor, | 173 const Array& arguments_descriptor, |
72 intptr_t argument_count); | 174 intptr_t argument_count); |
73 | 175 |
74 // Infrastructure copied from class CodeGenerator. | |
75 void GenerateCall(intptr_t token_index, | |
76 intptr_t try_index, | |
77 const ExternalLabel* label, | |
78 PcDescriptors::Kind kind); | |
79 | |
80 // Type checking helper methods. | 176 // Type checking helper methods. |
81 virtual void CheckClassIds(Register class_id_reg, | 177 virtual void CheckClassIds(Register class_id_reg, |
82 const GrowableArray<intptr_t>& class_ids, | 178 const GrowableArray<intptr_t>& class_ids, |
83 Label* is_instance_lbl, | 179 Label* is_instance_lbl, |
84 Label* is_not_instance_lbl); | 180 Label* is_not_instance_lbl); |
85 | 181 |
86 RawSubtypeTestCache* GenerateInlineInstanceof(intptr_t cid, | 182 RawSubtypeTestCache* GenerateInlineInstanceof(intptr_t cid, |
87 intptr_t token_index, | 183 intptr_t token_index, |
88 const AbstractType& type, | 184 const AbstractType& type, |
89 Label* is_instance_lbl, | 185 Label* is_instance_lbl, |
(...skipping 19 matching lines...) Expand all Loading... |
109 Label* is_instance_lbl, | 205 Label* is_instance_lbl, |
110 Label* is_not_instance_label); | 206 Label* is_not_instance_label); |
111 | 207 |
112 RawSubtypeTestCache* GenerateSubtype1TestCacheLookup( | 208 RawSubtypeTestCache* GenerateSubtype1TestCacheLookup( |
113 intptr_t cid, | 209 intptr_t cid, |
114 intptr_t token_index, | 210 intptr_t token_index, |
115 const Class& type_class, | 211 const Class& type_class, |
116 Label* is_instance_lbl, | 212 Label* is_instance_lbl, |
117 Label* is_not_instance_lbl); | 213 Label* is_not_instance_lbl); |
118 | 214 |
119 void GenerateAssertAssignable(intptr_t cid, | |
120 intptr_t token_index, | |
121 intptr_t try_index, | |
122 const AbstractType& dst_type, | |
123 const String& dst_name); | |
124 | |
125 void GenerateInstanceOf(intptr_t cid, | |
126 intptr_t token_index, | |
127 intptr_t try_index, | |
128 const AbstractType& type, | |
129 bool negate_result); | |
130 | |
131 enum TypeTestStubKind { | 215 enum TypeTestStubKind { |
132 kTestTypeOneArg, | 216 kTestTypeOneArg, |
133 kTestTypeTwoArgs, | 217 kTestTypeTwoArgs, |
134 kTestTypeThreeArgs, | 218 kTestTypeThreeArgs, |
135 }; | 219 }; |
136 | 220 |
137 RawSubtypeTestCache* GenerateCallSubtypeTestStub(TypeTestStubKind test_kind, | 221 RawSubtypeTestCache* GenerateCallSubtypeTestStub(TypeTestStubKind test_kind, |
138 Register instance_reg, | 222 Register instance_reg, |
139 Register type_arguments_reg, | 223 Register type_arguments_reg, |
140 Register temp_reg, | 224 Register temp_reg, |
141 Label* is_instance_lbl, | 225 Label* is_instance_lbl, |
142 Label* is_not_instance_lbl); | 226 Label* is_not_instance_lbl); |
143 | 227 |
144 void GenerateBoolToJump(Register bool_reg, Label* is_true, Label* is_false); | 228 void GenerateBoolToJump(Register bool_reg, Label* is_true, Label* is_false); |
145 | 229 |
146 void CopyParameters(); | 230 void CopyParameters(); |
147 | 231 |
148 virtual void GenerateInlinedGetter(intptr_t offset); | 232 virtual void GenerateInlinedGetter(intptr_t offset); |
149 virtual void GenerateInlinedSetter(intptr_t offset); | 233 virtual void GenerateInlinedSetter(intptr_t offset); |
150 | 234 |
| 235 // Map a block number in a forward iteration into the block number in the |
| 236 // corresponding reverse iteration. Used to obtain an index into |
| 237 // block_order for reverse iterations. |
| 238 intptr_t reverse_index(intptr_t index) const { |
| 239 return block_order_.length() - index - 1; |
| 240 } |
| 241 |
| 242 class Assembler* assembler_; |
| 243 const ParsedFunction& parsed_function_; |
| 244 const GrowableArray<BlockEntryInstr*>& block_order_; |
| 245 |
| 246 // Compiler specific per-block state. Indexed by postorder block number |
| 247 // for convenience. This is not the block's index in the block order, |
| 248 // which is reverse postorder. |
| 249 BlockEntryInstr* current_block_; |
| 250 ExceptionHandlerList* exception_handlers_list_; |
| 251 DescriptorList* pc_descriptors_list_; |
| 252 StackmapBuilder* stackmap_builder_; |
| 253 GrowableArray<BlockInfo*> block_info_; |
| 254 GrowableArray<DeoptimizationStub*> deopt_stubs_; |
| 255 const bool is_optimizing_; |
| 256 |
151 DISALLOW_COPY_AND_ASSIGN(FlowGraphCompiler); | 257 DISALLOW_COPY_AND_ASSIGN(FlowGraphCompiler); |
152 }; | 258 }; |
153 | 259 |
| 260 |
| 261 class DeoptimizationStub : public ZoneAllocated { |
| 262 public: |
| 263 DeoptimizationStub(intptr_t deopt_id, |
| 264 intptr_t deopt_token_index, |
| 265 intptr_t try_index, |
| 266 DeoptReasonId reason) |
| 267 : deopt_id_(deopt_id), |
| 268 deopt_token_index_(deopt_token_index), |
| 269 try_index_(try_index), |
| 270 reason_(reason), |
| 271 registers_(2), |
| 272 entry_label_() {} |
| 273 |
| 274 void Push(Register reg) { registers_.Add(reg); } |
| 275 Label* entry_label() { return &entry_label_; } |
| 276 |
| 277 // Implementation is in architecture specific file. |
| 278 void GenerateCode(FlowGraphCompiler* compiler); |
| 279 |
| 280 private: |
| 281 const intptr_t deopt_id_; |
| 282 const intptr_t deopt_token_index_; |
| 283 const intptr_t try_index_; |
| 284 const DeoptReasonId reason_; |
| 285 GrowableArray<Register> registers_; |
| 286 Label entry_label_; |
| 287 |
| 288 DISALLOW_COPY_AND_ASSIGN(DeoptimizationStub); |
| 289 }; |
| 290 |
154 } // namespace dart | 291 } // namespace dart |
155 | 292 |
156 #endif // VM_FLOW_GRAPH_COMPILER_X64_H_ | 293 #endif // VM_FLOW_GRAPH_COMPILER_X64_H_ |
OLD | NEW |