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

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

Issue 9447102: Implement x64 compilation for loading and storing local variables. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 10 months 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
OLDNEW
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 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "vm/ast_printer.h" 10 #include "vm/ast_printer.h"
11 #include "vm/code_generator.h" 11 #include "vm/code_generator.h"
12 #include "vm/disassembler.h" 12 #include "vm/disassembler.h"
13 #include "vm/longjump.h" 13 #include "vm/longjump.h"
14 #include "vm/parser.h" 14 #include "vm/parser.h"
15 #include "vm/stub_code.h" 15 #include "vm/stub_code.h"
16 16
17 namespace dart { 17 namespace dart {
18 18
19 DECLARE_FLAG(bool, print_ast); 19 DECLARE_FLAG(bool, print_ast);
20 DECLARE_FLAG(bool, print_scopes); 20 DECLARE_FLAG(bool, print_scopes);
21 DECLARE_FLAG(bool, trace_functions); 21 DECLARE_FLAG(bool, trace_functions);
22 DECLARE_FLAG(bool, disassemble); 22 DECLARE_FLAG(bool, disassemble);
23 23
24 void FlowGraphCompiler::Bailout(const char* reason) { 24 void FlowGraphCompiler::Bailout(const char* reason) {
25 const char* kFormat = "FlowGraphCompiler Bailout: %s."; 25 const char* kFormat = "FlowGraphCompiler Bailout: %s %s.";
26 intptr_t len = OS::SNPrint(NULL, 0, kFormat, reason) + 1; 26 const char* function_name = parsed_function_.function().ToCString();
27 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
27 char* chars = reinterpret_cast<char*>( 28 char* chars = reinterpret_cast<char*>(
28 Isolate::Current()->current_zone()->Allocate(len)); 29 Isolate::Current()->current_zone()->Allocate(len));
29 OS::SNPrint(chars, len, kFormat, reason); 30 OS::SNPrint(chars, len, kFormat, function_name, reason);
30 const Error& error = Error::Handle( 31 const Error& error = Error::Handle(
31 LanguageError::New(String::Handle(String::New(chars)))); 32 LanguageError::New(String::Handle(String::New(chars))));
32 Isolate::Current()->long_jump_base()->Jump(1, error); 33 Isolate::Current()->long_jump_base()->Jump(1, error);
33 } 34 }
34 35
35 36
36 #define __ assembler_-> 37 #define __ assembler_->
37 38
38 void FlowGraphCompiler::LoadValue(Value* value) { 39 void FlowGraphCompiler::LoadValue(Value* value) {
39 if (value->IsConstant()) { 40 if (value->IsConstant()) {
40 ConstantValue* constant = value->AsConstant(); 41 ConstantVal* constant = value->AsConstant();
41 if (constant->instance().IsSmi()) { 42 if (constant->instance().IsSmi()) {
42 int64_t imm = reinterpret_cast<int64_t>(constant->instance().raw()); 43 int64_t imm = reinterpret_cast<int64_t>(constant->instance().raw());
43 __ movq(RAX, Immediate(imm)); 44 __ movq(RAX, Immediate(imm));
44 } else { 45 } else {
45 __ LoadObject(RAX, value->AsConstant()->instance()); 46 __ LoadObject(RAX, value->AsConstant()->instance());
46 } 47 }
47 } else { 48 } else {
48 ASSERT(value->IsTemp()); 49 ASSERT(value->IsTemp());
49 Bailout("return of non-ConstantValue value"); 50 __ popq(RAX);
50 } 51 }
51 } 52 }
52 53
53 54
55 void FlowGraphCompiler::VisitTemp(TempVal* val) {
56 Bailout("TempVal");
57 }
58
59
60 void FlowGraphCompiler::VisitConstant(ConstantVal* val) {
61 Bailout("ConstantVal");
62 }
63
64
65 void FlowGraphCompiler::VisitAssertAssignable(AssertAssignableComp* comp) {
66 Bailout("AssertAssignableComp");
67 }
68
69
70 void FlowGraphCompiler::VisitInstanceCall(InstanceCallComp* comp) {
71 Bailout("InstanceCallComp");
72 }
73
74
75 void FlowGraphCompiler::VisitStrictCompare(StrictCompareComp* comp) {
76 Bailout("StrictCompareComp");
77 }
78
79
80
81 void FlowGraphCompiler::VisitStaticCall(StaticCallComp* comp) {
82 Bailout("StaticCallComp");
83 }
84
85
86 void FlowGraphCompiler::VisitLoadLocal(LoadLocalComp* comp) {
87 if (comp->local().is_captured()) {
88 Bailout("load of context variable");
89 }
90 __ movw(RAX, Address(RBP, comp->local().index() * kWordSize));
Kevin Millikin (Google) 2012/02/27 13:40:42 Oops, movq.
91 }
92
93
94 void FlowGraphCompiler::VisitStoreLocal(StoreLocalComp* comp) {
95 if (comp->local().is_captured()) {
96 Bailout("store to context variable");
97 }
98 LoadValue(comp->value());
99 __ movq(Address(RBP, comp->local().index() * kWordSize), RAX);
100 }
101
102
54 void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) { 103 void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) {
55 Bailout("JoinEntryInstr"); 104 Bailout("JoinEntryInstr");
56 } 105 }
57 106
58 107
59 void FlowGraphCompiler::VisitTargetEntry(TargetEntryInstr* instr) { 108 void FlowGraphCompiler::VisitTargetEntry(TargetEntryInstr* instr) {
60 // Since we don't handle branching control flow yet, there is nothing to do. 109 // Since we don't handle branching control flow yet, there is nothing to do.
61 } 110 }
62 111
63 112
64 void FlowGraphCompiler::VisitDo(DoInstr* instr) { 113 void FlowGraphCompiler::VisitDo(DoInstr* instr) {
65 Bailout("DoInstr"); 114 instr->computation()->Accept(this);
66 } 115 }
67 116
68 117
69 void FlowGraphCompiler::VisitBind(BindInstr* instr) { 118 void FlowGraphCompiler::VisitBind(BindInstr* instr) {
70 Bailout("DoInstr"); 119 instr->computation()->Accept(this);
120 __ pushq(RAX);
71 } 121 }
72 122
73 123
74 void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) { 124 void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) {
75 LoadValue(instr->value()); 125 LoadValue(instr->value());
76 126
77 #ifdef DEBUG 127 #ifdef DEBUG
78 // Check that the entry stack size matches the exit stack size. 128 // Check that the entry stack size matches the exit stack size.
79 const intptr_t locals_space_size = 0;
80 __ movq(R10, RBP); 129 __ movq(R10, RBP);
81 __ subq(R10, RSP); 130 __ subq(R10, RSP);
82 __ cmpq(R10, Immediate(locals_space_size)); 131 __ cmpq(R10, Immediate(stack_local_count() * kWordSize));
83 Label stack_ok; 132 Label stack_ok;
84 __ j(EQUAL, &stack_ok, Assembler::kNearJump); 133 __ j(EQUAL, &stack_ok, Assembler::kNearJump);
85 __ Stop("Exit stack size does not match the entry stack size."); 134 __ Stop("Exit stack size does not match the entry stack size.");
86 __ Bind(&stack_ok); 135 __ Bind(&stack_ok);
87 #endif // DEBUG. 136 #endif // DEBUG.
88 137
89 if (FLAG_trace_functions) { 138 if (FLAG_trace_functions) {
90 __ pushq(RAX); // Preserve result. 139 __ pushq(RAX); // Preserve result.
91 const Function& function = 140 const Function& function =
92 Function::ZoneHandle(parsed_function_.function().raw()); 141 Function::ZoneHandle(parsed_function_.function().raw());
93 __ LoadObject(RBX, function); 142 __ LoadObject(RBX, function);
94 __ pushq(RBX); 143 __ pushq(RBX);
95 GenerateCallRuntime(AstNode::kNoId, 144 GenerateCallRuntime(AstNode::kNoId,
96 0, 145 0,
97 kTraceFunctionExitRuntimeEntry); 146 kTraceFunctionExitRuntimeEntry);
98 __ popq(RAX); // Remove argument. 147 __ popq(RAX); // Remove argument.
99 __ popq(RAX); // Restore result. 148 __ popq(RAX); // Restore result.
100 } 149 }
101 __ LeaveFrame(); 150 __ LeaveFrame();
102 __ ret(); 151 __ ret();
103 } 152 }
104 153
105 154
106 void FlowGraphCompiler::VisitBranch(BranchInstr* instr) { 155 void FlowGraphCompiler::VisitBranch(BranchInstr* instr) {
107 Bailout("VisitBranch"); 156 Bailout("BranchInstr");
108 } 157 }
109 158
110 159
111 void FlowGraphCompiler::CompileGraph() { 160 void FlowGraphCompiler::CompileGraph() {
112 const Function& function = parsed_function_.function(); 161 const Function& function = parsed_function_.function();
113 if ((function.num_fixed_parameters() != 0) || 162 if ((function.num_optional_parameters() != 0)) {
114 (function.num_optional_parameters() != 0)) { 163 Bailout("function has optional parameters");
115 Bailout("function has parameters");
116 } 164 }
117 LocalScope* scope = parsed_function_.node_sequence()->scope(); 165 LocalScope* scope = parsed_function_.node_sequence()->scope();
118 if (scope->child() != NULL) {
119 Bailout("function has local scopes");
120 }
121 LocalScope* context_owner = NULL; 166 LocalScope* context_owner = NULL;
122 const int first_parameter_index = 1; 167 const int parameter_count = function.num_fixed_parameters();
123 const int parameter_count = 0; 168 const int first_parameter_index = 1 + parameter_count;
124 const int first_local_index = -1; 169 const int first_local_index = -1;
125 int first_free_frame_index = 170 int first_free_frame_index =
126 scope->AllocateVariables(first_parameter_index, 171 scope->AllocateVariables(first_parameter_index,
127 parameter_count, 172 parameter_count,
128 first_local_index, 173 first_local_index,
129 scope, 174 scope,
130 &context_owner); 175 &context_owner);
131 const int local_count = first_local_index - first_free_frame_index; 176 set_stack_local_count(first_local_index - first_free_frame_index);
132 if (local_count != 0) Bailout("function has locals");
133 177
134 if (blocks_->length() != 1) Bailout("more than 1 basic block"); 178 if (blocks_->length() != 1) Bailout("more than 1 basic block");
135 179
136 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. 180 // Specialized version of entry code from CodeGenerator::GenerateEntryCode.
137 __ EnterFrame(0); 181 __ EnterFrame(stack_local_count() * kWordSize);
138 #ifdef DEBUG 182 #ifdef DEBUG
139 const bool check_arguments = true; 183 const bool check_arguments = true;
140 #else 184 #else
141 const bool check_arguments = function.IsClosureFunction(); 185 const bool check_arguments = function.IsClosureFunction();
142 #endif 186 #endif
143 if (check_arguments) { 187 if (check_arguments) {
144 // Check that num_fixed <= argc <= num_params. 188 // Check that num_fixed <= argc <= num_params.
145 Label argc_in_range; 189 Label argc_in_range;
146 // Total number of args is the first Smi in args descriptor array (R10). 190 // Total number of args is the first Smi in args descriptor array (R10).
147 __ movq(RAX, FieldAddress(R10, Array::data_offset())); 191 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
148 __ cmpq(RAX, Immediate(Smi::RawValue(0))); 192 __ cmpq(RAX, Immediate(Smi::RawValue(0)));
149 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); 193 __ j(EQUAL, &argc_in_range, Assembler::kNearJump);
150 if (function.IsClosureFunction()) { 194 if (function.IsClosureFunction()) {
151 GenerateCallRuntime(AstNode::kNoId, 195 GenerateCallRuntime(AstNode::kNoId,
152 function.token_index(), 196 function.token_index(),
153 kClosureArgumentMismatchRuntimeEntry); 197 kClosureArgumentMismatchRuntimeEntry);
154 } else { 198 } else {
155 __ Stop("Wrong number of arguments"); 199 __ Stop("Wrong number of arguments");
156 } 200 }
157 __ Bind(&argc_in_range); 201 __ Bind(&argc_in_range);
158 } 202 }
203
204 // Initialize locals to null.
205 if (stack_local_count() > 0) {
206 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(Object::null())));
207 for (int i = 0; i < stack_local_count(); ++i) {
208 // Subtract index i (locals lie at lower addresses than RBP).
209 __ movq(Address(RBP, (first_local_index - i) * kWordSize), RAX);
210 }
211 }
212
159 // Generate stack overflow check. 213 // Generate stack overflow check.
160 __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address())); 214 __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address()));
161 __ cmpq(RSP, Address(TMP, 0)); 215 __ cmpq(RSP, Address(TMP, 0));
162 Label no_stack_overflow; 216 Label no_stack_overflow;
163 __ j(ABOVE, &no_stack_overflow); 217 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump);
Kevin Millikin (Google) 2012/02/27 13:40:42 I did not make this change (to shorten the encodin
164 GenerateCallRuntime(AstNode::kNoId, 218 GenerateCallRuntime(AstNode::kNoId,
165 function.token_index(), 219 function.token_index(),
166 kStackOverflowRuntimeEntry); 220 kStackOverflowRuntimeEntry);
167 __ Bind(&no_stack_overflow); 221 __ Bind(&no_stack_overflow);
168 222
169 if (FLAG_print_scopes) { 223 if (FLAG_print_scopes) {
170 // Print the function scope (again) after generating the prologue in order 224 // Print the function scope (again) after generating the prologue in order
171 // to see annotations such as allocation indices of locals. 225 // to see annotations such as allocation indices of locals.
172 if (FLAG_print_ast) { 226 if (FLAG_print_ast) {
173 // Second printing. 227 // Second printing.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 assembler_->CodeSize(), 272 assembler_->CodeSize(),
219 node_id, 273 node_id,
220 token_index, 274 token_index,
221 CatchClauseNode::kInvalidTryIndex); 275 CatchClauseNode::kInvalidTryIndex);
222 } 276 }
223 277
224 278
225 } // namespace dart 279 } // namespace dart
226 280
227 #endif // defined TARGET_ARCH_X64 281 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698