| 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);
|
| };
|
|
|
|
|