Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(419)

Side by Side Diff: runtime/vm/code_generator_ia32.cc

Issue 8678033: Move more nodes to the optimizing code generator. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/code_generator_ia32.h ('k') | runtime/vm/opt_code_generator_ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
7 7
8 #include "vm/code_generator.h" 8 #include "vm/code_generator.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 15 matching lines...) Expand all
26 DEFINE_FLAG(bool, trace_functions, false, "Trace entry of each function."); 26 DEFINE_FLAG(bool, trace_functions, false, "Trace entry of each function.");
27 DEFINE_FLAG(int, optimization_invocation_threshold, 1000, 27 DEFINE_FLAG(int, optimization_invocation_threshold, 1000,
28 "number of invocations before a function is optimized, -1 means never."); 28 "number of invocations before a function is optimized, -1 means never.");
29 DECLARE_FLAG(bool, enable_type_checks); 29 DECLARE_FLAG(bool, enable_type_checks);
30 DECLARE_FLAG(bool, report_invocation_count); 30 DECLARE_FLAG(bool, report_invocation_count);
31 DECLARE_FLAG(bool, trace_compiler); 31 DECLARE_FLAG(bool, trace_compiler);
32 32
33 #define __ assembler_-> 33 #define __ assembler_->
34 34
35 35
36 class CodeGeneratorState : public StackResource { 36 CodeGeneratorState::CodeGeneratorState(CodeGenerator* codegen)
37 public: 37 : StackResource(Isolate::Current()),
38 explicit CodeGeneratorState(CodeGenerator* codegen) 38 codegen_(codegen),
39 : StackResource(Isolate::Current()), 39 parent_(codegen->state()) {
40 codegen_(codegen), 40 if (parent_ != NULL) {
41 parent_(codegen->state()) { 41 root_node_ = parent_->root_node_;
42 if (parent_ != NULL) { 42 loop_level_ = parent_->loop_level_;
43 root_node_ = parent_->root_node_; 43 context_level_ = parent_->context_level_;
44 loop_level_ = parent_->loop_level_; 44 current_try_index_ = parent_->current_try_index_;
45 context_level_ = parent_->context_level_; 45 } else {
46 current_try_index_ = parent_->current_try_index_; 46 root_node_ = NULL;
47 } else { 47 loop_level_ = 0;
48 root_node_ = NULL; 48 context_level_ = 0;
49 loop_level_ = 0; 49 current_try_index_ = CatchClauseNode::kInvalidTryIndex;
50 context_level_ = 0;
51 current_try_index_ = CatchClauseNode::kInvalidTryIndex;
52 }
53 codegen_->set_state(this);
54 } 50 }
55 virtual ~CodeGeneratorState() { 51 codegen_->set_state(this);
56 codegen_->set_state(parent_); 52 }
57 }
58 53
59 CodeGeneratorState* parent() const { return parent_; }
60 54
61 AstNode* root_node() const { return root_node_; } 55 CodeGeneratorState::~CodeGeneratorState() {
62 void set_root_node(AstNode* value) { root_node_ = value; } 56 codegen_->set_state(parent_);
63 bool IsRootNode(AstNode* node) const { 57 }
64 return root_node_ == node;
65 }
66
67 int loop_level() const { return loop_level_; }
68 void set_loop_level(int loop_level) {
69 loop_level_ = loop_level;
70 }
71
72 int context_level() const { return context_level_; }
73 void set_context_level(int context_level) {
74 context_level_ = context_level;
75 }
76
77 int try_index() const { return current_try_index_; }
78 void set_try_index(int value) {
79 current_try_index_ = value;
80 }
81
82 private:
83 CodeGenerator* codegen_;
84 CodeGeneratorState* parent_;
85 AstNode* root_node_;
86
87 // The loop level reflects the lexical nesting of loop statements, regardless
88 // of the presence of captured variables.
89 int loop_level_;
90
91 // The runtime context level is only incremented when a new context is
92 // allocated and chained to the list of contexts. This occurs when the scopes
93 // at the current loop level contain captured variables.
94 int context_level_;
95
96 // We identify each try block in this function with an unique 'try index'
97 // value.
98 // The 'try index' is used to match the try blocks with the corresponding
99 // catch block (if one exists). The PC descriptors generated for
100 // statements in the try block use this index so that it can be matched
101 // to the appropriate catch block.
102 // The 'try index' value is generated by incrementing the try_index_
103 // variable in the CodeGenerator object.
104 // We store the 'try index' of the block of code that we are
105 // currently generating code for in the current_try_index_ variable.
106 int current_try_index_;
107
108 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeGeneratorState);
109 };
110 58
111 59
112 class CodeGenerator::DescriptorList : public ZoneAllocated { 60 class CodeGenerator::DescriptorList : public ZoneAllocated {
113 public: 61 public:
114 struct PcDesc { 62 struct PcDesc {
115 intptr_t pc_offset; // PC offset value of the descriptor. 63 intptr_t pc_offset; // PC offset value of the descriptor.
116 PcDescriptors::Kind kind; // Descriptor kind (kDeopt, kOther). 64 PcDescriptors::Kind kind; // Descriptor kind (kDeopt, kOther).
117 intptr_t node_id; // AST node id. 65 intptr_t node_id; // AST node id.
118 intptr_t token_index; // Token position in source of PC. 66 intptr_t token_index; // Token position in source of PC.
119 intptr_t try_index; // Try block index of PC. 67 intptr_t try_index; // Try block index of PC.
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 // Consider emitting pushes instead of moves. 708 // Consider emitting pushes instead of moves.
761 for (int index = first_local_index; index > first_free_frame_index; index--) { 709 for (int index = first_local_index; index > first_free_frame_index; index--) {
762 if (index == first_local_index) { 710 if (index == first_local_index) {
763 __ movl(EAX, raw_null); 711 __ movl(EAX, raw_null);
764 } 712 }
765 __ movl(Address(EBP, index * kWordSize), EAX); 713 __ movl(Address(EBP, index * kWordSize), EAX);
766 } 714 }
767 } 715 }
768 716
769 717
718 void CodeGenerator::GenerateReturnEpilog() {
719 // Unchain the context(s) up to context level 0.
720 int context_level = state()->context_level();
721 ASSERT(context_level >= 0);
722 while (context_level-- > 0) {
723 __ movl(CTX, FieldAddress(CTX, Context::parent_offset()));
724 }
725 #ifdef DEBUG
726 // Check that the entry stack size matches the exit stack size.
727 __ movl(EDX, EBP);
728 __ subl(EDX, ESP);
729 ASSERT(locals_space_size() >= 0);
730 __ cmpl(EDX, Immediate(locals_space_size()));
731 Label wrong_stack;
732 __ j(NOT_EQUAL, &wrong_stack, Assembler::kNearJump);
733 #endif // DEBUG.
734
735 if (FLAG_trace_functions) {
736 __ pushl(EAX); // Preserve result.
737 const Function& function =
738 Function::ZoneHandle(parsed_function_.function().raw());
739 __ LoadObject(EBX, function);
740 __ pushl(EBX);
741 GenerateCallRuntime(AstNode::kNoId,
742 0,
743 kTraceFunctionExitRuntimeEntry);
744 __ popl(EAX); // Remove argument.
745 __ popl(EAX); // Restore result.
746 }
747 __ LeaveFrame();
748 __ ret();
749
750 #ifdef DEBUG
751 __ Bind(&wrong_stack);
752 __ Stop("Exit stack size does not match the entry stack size.");
753 #endif // DEBUG.
754 }
755
756
770 void CodeGenerator::VisitReturnNode(ReturnNode* node) { 757 void CodeGenerator::VisitReturnNode(ReturnNode* node) {
771 ASSERT(!IsResultNeeded(node)); 758 ASSERT(!IsResultNeeded(node));
772 ASSERT(node->value() != NULL); 759 ASSERT(node->value() != NULL);
773 760
774 if (!node->value()->IsLiteralNode()) { 761 if (!node->value()->IsLiteralNode()) {
775 node->value()->Visit(this); 762 node->value()->Visit(this);
776 // The result of the return value is now on top of the stack. 763 // The result of the return value is now on top of the stack.
777 } 764 }
778 765
779 // Generate inlined code for all finally blocks as we are about to transfer 766 // Generate inlined code for all finally blocks as we are about to transfer
(...skipping 21 matching lines...) Expand all
801 // Implicit getters do not need a type check at return. 788 // Implicit getters do not need a type check at return.
802 if ((kind != RawFunction::kImplicitGetter) && 789 if ((kind != RawFunction::kImplicitGetter) &&
803 (kind != RawFunction::kConstImplicitGetter)) { 790 (kind != RawFunction::kConstImplicitGetter)) {
804 GenerateAssertAssignable( 791 GenerateAssertAssignable(
805 node->id(), 792 node->id(),
806 node->value()->token_index(), 793 node->value()->token_index(),
807 Type::ZoneHandle(parsed_function().function().result_type()), 794 Type::ZoneHandle(parsed_function().function().result_type()),
808 String::ZoneHandle(String::NewSymbol("function result"))); 795 String::ZoneHandle(String::NewSymbol("function result")));
809 } 796 }
810 } 797 }
811 // Unchain the context(s) up to context level 0. 798 GenerateReturnEpilog();
812 int context_level = state()->context_level();
813 ASSERT(context_level >= 0);
814 while (context_level-- > 0) {
815 __ movl(CTX, FieldAddress(CTX, Context::parent_offset()));
816 }
817 #ifdef DEBUG
818 // Check that the entry stack size matches the exit stack size.
819 __ movl(EDX, EBP);
820 __ subl(EDX, ESP);
821 ASSERT(locals_space_size() >= 0);
822 __ cmpl(EDX, Immediate(locals_space_size()));
823 Label wrong_stack;
824 __ j(NOT_EQUAL, &wrong_stack, Assembler::kNearJump);
825 #endif // DEBUG.
826
827 if (FLAG_trace_functions) {
828 __ pushl(EAX); // Preserve result.
829 const Function& function =
830 Function::ZoneHandle(parsed_function_.function().raw());
831 __ LoadObject(EBX, function);
832 __ pushl(EBX);
833 GenerateCallRuntime(AstNode::kNoId,
834 0,
835 kTraceFunctionExitRuntimeEntry);
836 __ popl(EAX); // Remove argument.
837 __ popl(EAX); // Restore result.
838 }
839 __ LeaveFrame();
840 __ ret();
841
842 #ifdef DEBUG
843 __ Bind(&wrong_stack);
844 __ Stop("Exit stack size does not match the entry stack size.");
845 #endif // DEBUG.
846 } 799 }
847 800
848 801
849 void CodeGenerator::VisitLiteralNode(LiteralNode* node) { 802 void CodeGenerator::VisitLiteralNode(LiteralNode* node) {
850 if (!IsResultNeeded(node)) return; 803 if (!IsResultNeeded(node)) return;
851 const Object& literal = node->literal(); 804 const Object& literal = node->literal();
852 if (literal.IsSmi()) { 805 if (literal.IsSmi()) {
853 __ pushl(Immediate(reinterpret_cast<int32_t>(literal.raw()))); 806 __ pushl(Immediate(reinterpret_cast<int32_t>(literal.raw())));
854 } else { 807 } else {
855 __ PushObject(literal); 808 __ PushObject(literal);
(...skipping 1908 matching lines...) Expand 10 before | Expand all | Expand 10 after
2764 message_buffer, kMessageBufferSize, 2717 message_buffer, kMessageBufferSize,
2765 format, args); 2718 format, args);
2766 va_end(args); 2719 va_end(args);
2767 Isolate::Current()->long_jump_base()->Jump(1, message_buffer); 2720 Isolate::Current()->long_jump_base()->Jump(1, message_buffer);
2768 UNREACHABLE(); 2721 UNREACHABLE();
2769 } 2722 }
2770 2723
2771 } // namespace dart 2724 } // namespace dart
2772 2725
2773 #endif // defined TARGET_ARCH_IA32 2726 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/code_generator_ia32.h ('k') | runtime/vm/opt_code_generator_ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698