| 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_CODE_GENERATOR_IA32_H_ | |
| 6 #define VM_CODE_GENERATOR_IA32_H_ | |
| 7 | |
| 8 #ifndef VM_CODE_GENERATOR_H_ | |
| 9 #error Do not include code_generator_ia32.h directly; use code_generator.h. | |
| 10 #endif | |
| 11 | |
| 12 #include "vm/ast.h" | |
| 13 #include "vm/growable_array.h" | |
| 14 #include "vm/parser.h" | |
| 15 | |
| 16 namespace dart { | |
| 17 | |
| 18 // Forward declarations. | |
| 19 class Assembler; | |
| 20 class AstNode; | |
| 21 class CodeGenerator; | |
| 22 class DescriptorList; | |
| 23 class ExceptionHandlerList; | |
| 24 class SourceLabel; | |
| 25 class StackmapBuilder; | |
| 26 | |
| 27 | |
| 28 class CodeGeneratorState : public StackResource { | |
| 29 public: | |
| 30 explicit CodeGeneratorState(CodeGenerator* codegen); | |
| 31 virtual ~CodeGeneratorState(); | |
| 32 | |
| 33 CodeGeneratorState* parent() const { return parent_; } | |
| 34 | |
| 35 AstNode* root_node() const { return root_node_; } | |
| 36 void set_root_node(AstNode* value) { root_node_ = value; } | |
| 37 bool IsRootNode(AstNode* node) const { | |
| 38 return root_node_ == node; | |
| 39 } | |
| 40 | |
| 41 int try_index() const { return current_try_index_; } | |
| 42 void set_try_index(int value) { | |
| 43 current_try_index_ = value; | |
| 44 } | |
| 45 | |
| 46 private: | |
| 47 CodeGenerator* codegen_; | |
| 48 CodeGeneratorState* parent_; | |
| 49 AstNode* root_node_; | |
| 50 | |
| 51 // We identify each try block in this function with an unique 'try index' | |
| 52 // value. | |
| 53 // The 'try index' is used to match the try blocks with the corresponding | |
| 54 // catch block (if one exists). The PC descriptors generated for | |
| 55 // statements in the try block use this index so that it can be matched | |
| 56 // to the appropriate catch block. | |
| 57 // The 'try index' value is generated by incrementing the try_index_ | |
| 58 // variable in the CodeGenerator object. | |
| 59 // We store the 'try index' of the block of code that we are | |
| 60 // currently generating code for in the current_try_index_ variable. | |
| 61 int current_try_index_; | |
| 62 | |
| 63 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeGeneratorState); | |
| 64 }; | |
| 65 | |
| 66 | |
| 67 class CodeGenerator : public AstNodeVisitor { | |
| 68 public: | |
| 69 CodeGenerator(Assembler* assembler, const ParsedFunction& parsed_function); | |
| 70 virtual ~CodeGenerator() { } | |
| 71 | |
| 72 // Accessors. | |
| 73 Assembler* assembler() const { return assembler_; } | |
| 74 | |
| 75 const ParsedFunction& parsed_function() const { return parsed_function_; } | |
| 76 | |
| 77 void GenerateCode(); | |
| 78 virtual void GenerateDeferredCode(); | |
| 79 // Constructor is lighweight, major initialization work should occur here. | |
| 80 // This makes it easier to measure time spent in the code generator. | |
| 81 virtual void InitGenerator(); | |
| 82 | |
| 83 #define DEFINE_VISITOR_FUNCTION(type, name) \ | |
| 84 virtual void Visit##type(type* node); | |
| 85 NODE_LIST(DEFINE_VISITOR_FUNCTION) | |
| 86 #undef DEFINE_VISITOR_FUNCTION | |
| 87 | |
| 88 CodeGeneratorState* state() const { return state_; } | |
| 89 void set_state(CodeGeneratorState* state) { state_ = state; } | |
| 90 | |
| 91 // Add exception handler table to code. | |
| 92 void FinalizeExceptionHandlers(const Code& code); | |
| 93 | |
| 94 // Add pc descriptors to code. | |
| 95 void FinalizePcDescriptors(const Code& code); | |
| 96 | |
| 97 // Add stack maps to code. | |
| 98 void FinalizeStackmaps(const Code& code); | |
| 99 | |
| 100 // Add local variable descriptors to code. | |
| 101 void FinalizeVarDescriptors(const Code& code); | |
| 102 | |
| 103 void FinalizeComments(const Code& code); | |
| 104 | |
| 105 // Allocate and return an arguments descriptor. | |
| 106 // Let 'num_names' be the length of 'optional_arguments_names'. | |
| 107 // Treat the first 'num_arguments - num_names' arguments as positional and | |
| 108 // treat the following 'num_names' arguments as named optional arguments. | |
| 109 static const Array& ArgumentsDescriptor( | |
| 110 int num_arguments, | |
| 111 const Array& optional_arguments_names); | |
| 112 | |
| 113 virtual bool IsOptimizing() const { | |
| 114 return false; | |
| 115 } | |
| 116 | |
| 117 void GenerateReturnEpilog(ReturnNode* node); | |
| 118 | |
| 119 // Return true if the VM may optimize functions. | |
| 120 static bool CanOptimize(); | |
| 121 | |
| 122 private: | |
| 123 static const int kLocalsOffsetFromFP = (-1 * kWordSize); | |
| 124 | |
| 125 // TODO(srdjan): Remove the friendship once the two compilers are properly | |
| 126 // structured. | |
| 127 friend class OptimizingCodeGenerator; | |
| 128 | |
| 129 // Return true if intrinsification succeeded and no more code is needed. | |
| 130 // Returns false if either no intrinsification occured or if intrinsified | |
| 131 // code needs the rest for slow case execution. | |
| 132 bool TryIntrinsify(); | |
| 133 | |
| 134 void IntrinsifyGetter(); | |
| 135 void IntrinsifySetter(); | |
| 136 | |
| 137 void GenerateLegacyEntryCode(); | |
| 138 void GenerateEntryCode(); | |
| 139 void GenerateLoadVariable(Register dst, const LocalVariable& local); | |
| 140 void GeneratePushVariable(const LocalVariable& variable, Register scratch); | |
| 141 void GenerateStoreVariable(const LocalVariable& local, | |
| 142 Register src, | |
| 143 Register scratch); | |
| 144 void GenerateLogicalNotOp(UnaryOpNode* node); | |
| 145 void GenerateLogicalAndOrOp(BinaryOpNode* node); | |
| 146 void GenerateInstanceGetterCall(intptr_t node_id, | |
| 147 intptr_t token_index, | |
| 148 const String& field_name); | |
| 149 void GenerateInstanceSetterCall(intptr_t node_id, | |
| 150 intptr_t token_index, | |
| 151 const String& field_name); | |
| 152 void GenerateBinaryOperatorCall(intptr_t node_id, | |
| 153 intptr_t token_index, | |
| 154 const char* operator_name); | |
| 155 void GenerateStaticGetterCall(intptr_t token_index, | |
| 156 const Class& field_class, | |
| 157 const String& field_name); | |
| 158 void GenerateStaticSetterCall(intptr_t token_index, | |
| 159 const Class& field_class, | |
| 160 const String& field_name); | |
| 161 void GenerateLoadIndexed(intptr_t node_id, intptr_t token_index); | |
| 162 void GenerateStoreIndexed(intptr_t node_id, | |
| 163 intptr_t token_index, | |
| 164 bool preserve_value); | |
| 165 | |
| 166 // Invokes funtion via an inline cache stub. 'num_args_checked' specifies | |
| 167 // the number of call arguments that are being checked in the inline cache. | |
| 168 void GenerateInstanceCall(intptr_t node_id, | |
| 169 intptr_t token_index, | |
| 170 const String& function_name, | |
| 171 int num_arguments, | |
| 172 const Array& optional_arguments_names, | |
| 173 intptr_t num_args_checked); | |
| 174 | |
| 175 void GenerateInstanceOf(intptr_t node_id, | |
| 176 intptr_t token_index, | |
| 177 AstNode* value, | |
| 178 const AbstractType& type, | |
| 179 bool negate_result); | |
| 180 void GenerateAssertAssignable(intptr_t node_id, | |
| 181 intptr_t token_index, | |
| 182 AstNode* value, | |
| 183 const AbstractType& dst_type, | |
| 184 const String& dst_name); | |
| 185 void GenerateArgumentTypeChecks(); | |
| 186 void GenerateConditionTypeCheck(intptr_t node_id, intptr_t token_index); | |
| 187 | |
| 188 void GenerateInstantiatorTypeArguments(intptr_t token_index, | |
| 189 bool push_instantiator); | |
| 190 void GenerateTypeArguments(intptr_t node_id, | |
| 191 intptr_t token_index, | |
| 192 const AbstractTypeArguments& type_arguments, | |
| 193 bool instantiate_type_arguments); | |
| 194 | |
| 195 intptr_t locals_space_size() const { return locals_space_size_; } | |
| 196 void set_locals_space_size(intptr_t value) { locals_space_size_ = value; } | |
| 197 | |
| 198 bool IsResultNeeded(AstNode* node) const; | |
| 199 | |
| 200 void GenerateCall(intptr_t token_index, | |
| 201 const ExternalLabel* ext_label, | |
| 202 PcDescriptors::Kind desc_kind); | |
| 203 void GenerateCallRuntime(intptr_t node_id, | |
| 204 intptr_t token_index, | |
| 205 const RuntimeEntry& entry); | |
| 206 | |
| 207 void GenerateInlinedFinallyBlocks(SourceLabel* label); | |
| 208 | |
| 209 RawSubtypeTestCache* GenerateInlineInstanceof(intptr_t node_id, | |
| 210 intptr_t token_index, | |
| 211 const AbstractType& type, | |
| 212 Label* is_instance_lbl, | |
| 213 Label* is_not_instance_lbl); | |
| 214 | |
| 215 RawSubtypeTestCache* GenerateInstantiatedTypeWithArgumentsTest( | |
| 216 intptr_t node_id, | |
| 217 intptr_t token_index, | |
| 218 const AbstractType& dst_type, | |
| 219 Label* is_instance_lbl, | |
| 220 Label* is_not_instance_lbl); | |
| 221 void GenerateInstantiatedTypeNoArgumentsTest(intptr_t node_id, | |
| 222 intptr_t token_index, | |
| 223 const AbstractType& dst_type, | |
| 224 Label* is_instance_lbl, | |
| 225 Label* is_not_instance_lbl); | |
| 226 RawSubtypeTestCache* GenerateUninstantiatedTypeTest( | |
| 227 const AbstractType& dst_type, | |
| 228 intptr_t node_id, | |
| 229 intptr_t token_index, | |
| 230 Label* is_instance_lbl, | |
| 231 Label* is_not_instance_label); | |
| 232 RawSubtypeTestCache* GenerateSubtype1TestCacheLookup( | |
| 233 intptr_t node_id, | |
| 234 intptr_t token_index, | |
| 235 const Class& type_class, | |
| 236 Label* is_instance_lbl, | |
| 237 Label* is_not_instance_lbl); | |
| 238 | |
| 239 void HandleBackwardBranch(intptr_t loop_id, intptr_t token_index); | |
| 240 | |
| 241 void ErrorMsg(intptr_t token_index, const char* format, ...); | |
| 242 | |
| 243 int generate_next_try_index() { return try_index_ += 1; } | |
| 244 | |
| 245 void MarkDeoptPoint(intptr_t node_id, intptr_t token_index); | |
| 246 void AddCurrentDescriptor(PcDescriptors::Kind kind, | |
| 247 intptr_t node_id, | |
| 248 intptr_t token_index); | |
| 249 | |
| 250 void set_context_level(intptr_t value) { context_level_ = value; } | |
| 251 intptr_t context_level() const { return context_level_; } | |
| 252 | |
| 253 Assembler* assembler_; | |
| 254 const ParsedFunction& parsed_function_; | |
| 255 intptr_t locals_space_size_; | |
| 256 CodeGeneratorState* state_; | |
| 257 DescriptorList* pc_descriptors_list_; | |
| 258 StackmapBuilder* stackmap_builder_; | |
| 259 ExceptionHandlerList* exception_handlers_list_; | |
| 260 int try_index_; | |
| 261 // The runtime context level is only incremented when a new context is | |
| 262 // allocated and chained to the list of contexts. | |
| 263 intptr_t context_level_; | |
| 264 | |
| 265 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeGenerator); | |
| 266 }; | |
| 267 | |
| 268 } // namespace dart | |
| 269 | |
| 270 #endif // VM_CODE_GENERATOR_IA32_H_ | |
| OLD | NEW |