Index: runtime/vm/code_generator_x64.h |
=================================================================== |
--- runtime/vm/code_generator_x64.h (revision 2556) |
+++ runtime/vm/code_generator_x64.h (working copy) |
@@ -6,35 +6,108 @@ |
#define VM_CODE_GENERATOR_X64_H_ |
#ifndef VM_CODE_GENERATOR_H_ |
-#error Do not include code_generator_x64.h directly; use assembler.h instead. |
+#error Do not include code_generator_x64.h directly; use code_generator.h. |
#endif |
-#include "vm/allocation.h" |
+#include "vm/assembler.h" |
#include "vm/ast.h" |
#include "vm/growable_array.h" |
+#include "vm/parser.h" |
namespace dart { |
// Forward declarations. |
class Assembler; |
class AstNode; |
-class ParsedFunction; |
+class CodeGenerator; |
+class SourceLabel; |
+ |
+class CodeGeneratorState : public StackResource { |
+ public: |
+ explicit CodeGeneratorState(CodeGenerator* codegen); |
+ virtual ~CodeGeneratorState(); |
+ |
+ CodeGeneratorState* parent() const { return parent_; } |
+ |
+ AstNode* root_node() const { return root_node_; } |
+ void set_root_node(AstNode* value) { root_node_ = value; } |
+ bool IsRootNode(AstNode* node) const { |
+ return root_node_ == node; |
+ } |
+ |
+ int loop_level() const { return loop_level_; } |
+ void set_loop_level(int loop_level) { |
+ loop_level_ = loop_level; |
+ } |
+ |
+ int context_level() const { return context_level_; } |
+ void set_context_level(int context_level) { |
+ context_level_ = context_level; |
+ } |
+ |
+ int try_index() const { return current_try_index_; } |
+ void set_try_index(int value) { |
+ current_try_index_ = value; |
+ } |
+ |
+ private: |
+ CodeGenerator* codegen_; |
+ CodeGeneratorState* parent_; |
+ AstNode* root_node_; |
+ |
+ // The loop level reflects the lexical nesting of loop statements, regardless |
+ // of the presence of captured variables. |
+ int loop_level_; |
+ |
+ // The runtime context level is only incremented when a new context is |
+ // allocated and chained to the list of contexts. This occurs when the scopes |
+ // at the current loop level contain captured variables. |
+ int context_level_; |
+ |
+ // We identify each try block in this function with an unique 'try index' |
+ // value. |
+ // The 'try index' is used to match the try blocks with the corresponding |
+ // catch block (if one exists). The PC descriptors generated for |
+ // statements in the try block use this index so that it can be matched |
+ // to the appropriate catch block. |
+ // The 'try index' value is generated by incrementing the try_index_ |
+ // variable in the CodeGenerator object. |
+ // We store the 'try index' of the block of code that we are |
+ // currently generating code for in the current_try_index_ variable. |
+ int current_try_index_; |
+ |
+ DISALLOW_IMPLICIT_CONSTRUCTORS(CodeGeneratorState); |
+}; |
+ |
+ |
class CodeGenerator : public AstNodeVisitor { |
public: |
- CodeGenerator(Assembler* assembler, const ParsedFunction& parsed_function) { } |
+ CodeGenerator(Assembler* assembler, const ParsedFunction& parsed_function); |
virtual ~CodeGenerator() { } |
- bool GenerateCode() { |
- return false; |
- } |
+ // Accessors. |
+ Assembler* assembler() const { return assembler_; } |
- // Add an exception handler table to code. |
- void FinalizeExceptionHandlers(const Code& code) { UNIMPLEMENTED(); } |
+ const ParsedFunction& parsed_function() const { return parsed_function_; } |
- // Add Pcdescriptors to code. |
- void FinalizePcDescriptors(const Code& code) { UNIMPLEMENTED(); } |
+ void GenerateCode(); |
+ virtual void GenerateDeferredCode(); |
+#define DEFINE_VISITOR_FUNCTION(type, name) \ |
+ virtual void Visit##type(type* node); |
+NODE_LIST(DEFINE_VISITOR_FUNCTION) |
+#undef DEFINE_VISITOR_FUNCTION |
+ |
+ CodeGeneratorState* state() const { return state_; } |
+ void set_state(CodeGeneratorState* state) { state_ = state; } |
+ |
+ // Add exception handler table to code. |
+ void FinalizeExceptionHandlers(const Code& code); |
+ |
+ // Add pc descriptors to code. |
+ void FinalizePcDescriptors(const Code& code); |
+ |
// Allocate and return an arguments descriptor. |
// Let 'num_names' be the length of 'optional_arguments_names'. |
// Treat the first 'num_arguments - num_names' arguments as positional and |
@@ -43,7 +116,111 @@ |
int num_arguments, |
const Array& optional_arguments_names); |
+ virtual bool IsOptimizing() const { |
+ return false; |
+ } |
+ |
+ virtual void CountBackwardLoop(); |
+ |
+ void GenerateReturnEpilog(); |
+ |
private: |
+ // TODO(srdjan): Remove the friendship once the two compilers are properly |
+ // structured. |
+ friend class OptimizingCodeGenerator; |
+ |
+ // Forward declarations. |
+ class DescriptorList; |
+ class HandlerList; |
+ |
+ // Return true if intrinsification was completed and no other code |
+ // needs to be generated. |
+ virtual bool TryIntrinsify() { return false; } |
+ virtual void GeneratePreEntryCode(); |
+ void GenerateLegacyEntryCode(); |
+ void GenerateEntryCode(); |
+ void GenerateLoadVariable(Register dst, const LocalVariable& local); |
+ void GeneratePushVariable(const LocalVariable& variable, Register scratch); |
+ void GenerateStoreVariable(const LocalVariable& local, |
+ Register src, |
+ Register scratch); |
+ void GenerateLogicalNotOp(UnaryOpNode* node); |
+ void GenerateLogicalAndOrOp(BinaryOpNode* node); |
+ void GenerateInstanceGetterCall(intptr_t node_id, |
+ intptr_t token_index, |
+ const String& field_name); |
+ void GenerateInstanceSetterCall(intptr_t node_id, |
+ intptr_t token_index, |
+ const String& field_name); |
+ void GenerateBinaryOperatorCall(intptr_t node_id, |
+ intptr_t token_index, |
+ const char* operator_name); |
+ void GenerateStaticGetterCall(intptr_t token_index, |
+ const Class& field_class, |
+ const String& field_name); |
+ void GenerateStaticSetterCall(intptr_t token_index, |
+ const Class& field_class, |
+ const String& field_name); |
+ void GenerateLoadIndexed(intptr_t node_id, intptr_t token_index); |
+ void GenerateStoreIndexed(intptr_t node_id, |
+ intptr_t token_index, |
+ bool preserve_value); |
+ |
+ // Invokes funtion via an inline cache stub. 'num_args_checked' specifies |
+ // the number of call arguments that are being checked in the inline cache. |
+ void GenerateInstanceCall(intptr_t node_id, |
+ intptr_t token_index, |
+ const String& function_name, |
+ int num_arguments, |
+ const Array& optional_arguments_names, |
+ intptr_t num_args_checked); |
+ |
+ void GenerateInstanceOf(intptr_t node_id, |
+ intptr_t token_index, |
+ const AbstractType& type, |
+ bool negate_result); |
+ void GenerateAssertAssignable(intptr_t node_id, |
+ intptr_t token_index, |
+ const AbstractType& dst_type, |
+ const String& dst_name); |
+ void GenerateArgumentTypeChecks(); |
+ void GenerateConditionTypeCheck(intptr_t node_id, intptr_t token_index); |
+ |
+ void GenerateInstantiatorTypeArguments(intptr_t token_index); |
+ void GenerateTypeArguments(ConstructorCallNode* node, |
+ bool is_cls_parameterized); |
+ |
+ void TestClassAndJump(const Class& cls, Label *label); |
+ |
+ intptr_t locals_space_size() const { return locals_space_size_; } |
+ void set_locals_space_size(intptr_t value) { locals_space_size_ = value; } |
+ |
+ bool IsResultNeeded(AstNode* node) const; |
+ |
+ void GenerateCall(intptr_t token_index, const ExternalLabel* ext_label); |
+ void GenerateCallRuntime(intptr_t node_id, |
+ intptr_t token_index, |
+ const RuntimeEntry& entry); |
+ |
+ void GenerateInlinedFinallyBlocks(SourceLabel* label); |
+ |
+ void ErrorMsg(intptr_t token_index, const char* format, ...); |
+ |
+ int generate_next_try_index() { return try_index_ += 1; } |
+ |
+ void MarkDeoptPoint(intptr_t node_id, intptr_t token_index); |
+ void AddCurrentDescriptor(PcDescriptors::Kind kind, |
+ intptr_t node_id, |
+ intptr_t token_index); |
+ |
+ Assembler* assembler_; |
+ const ParsedFunction& parsed_function_; |
+ intptr_t locals_space_size_; |
+ CodeGeneratorState* state_; |
+ DescriptorList* pc_descriptors_list_; |
+ HandlerList* exception_handlers_list_; |
+ int try_index_; |
+ |
DISALLOW_IMPLICIT_CONSTRUCTORS(CodeGenerator); |
}; |