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

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

Issue 10949019: Turn definitions that do not produce results (e.g. Checks) into instructions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 3 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
« no previous file with comments | « no previous file | runtime/vm/flow_graph_optimizer.h » ('j') | runtime/vm/flow_graph_optimizer.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/flow_graph_builder.h" 5 #include "vm/flow_graph_builder.h"
6 6
7 #include "vm/ast_printer.h" 7 #include "vm/ast_printer.h"
8 #include "vm/code_descriptors.h" 8 #include "vm/code_descriptors.h"
9 #include "vm/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/flags.h" 10 #include "vm/flags.h"
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 // Stores current context into the 'variable' 283 // Stores current context into the 'variable'
284 void EffectGraphVisitor::BuildStoreContext(const LocalVariable& variable) { 284 void EffectGraphVisitor::BuildStoreContext(const LocalVariable& variable) {
285 Value* context = Bind(new CurrentContextInstr()); 285 Value* context = Bind(new CurrentContextInstr());
286 Do(BuildStoreLocal(variable, context, kResultNotNeeded)); 286 Do(BuildStoreLocal(variable, context, kResultNotNeeded));
287 } 287 }
288 288
289 289
290 // Loads context saved in 'context_variable' into the current context. 290 // Loads context saved in 'context_variable' into the current context.
291 void EffectGraphVisitor::BuildLoadContext(const LocalVariable& variable) { 291 void EffectGraphVisitor::BuildLoadContext(const LocalVariable& variable) {
292 Value* load_saved_context = Bind(BuildLoadLocal(variable)); 292 Value* load_saved_context = Bind(BuildLoadLocal(variable));
293 Do(new StoreContextInstr(load_saved_context)); 293 AddInstruction(new StoreContextInstr(load_saved_context));
294 } 294 }
295 295
296 296
297 void TestGraphVisitor::ConnectBranchesTo( 297 void TestGraphVisitor::ConnectBranchesTo(
298 const GrowableArray<TargetEntryInstr**>& branches, 298 const GrowableArray<TargetEntryInstr**>& branches,
299 JoinEntryInstr* join) const { 299 JoinEntryInstr* join) const {
300 ASSERT(!branches.is_empty()); 300 ASSERT(!branches.is_empty());
301 for (intptr_t i = 0; i < branches.length(); i++) { 301 for (intptr_t i = 0; i < branches.length(); i++) {
302 TargetEntryInstr* target = new TargetEntryInstr(owner()->try_index()); 302 TargetEntryInstr* target = new TargetEntryInstr(owner()->try_index());
303 *(branches[i]) = target; 303 *(branches[i]) = target;
(...skipping 876 matching lines...) Expand 10 before | Expand all | Expand 10 after
1180 // g) break-join (optional) 1180 // g) break-join (optional)
1181 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { 1181 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) {
1182 InlineBailout("EffectGraphVisitor::VisitWhileNode (control)"); 1182 InlineBailout("EffectGraphVisitor::VisitWhileNode (control)");
1183 TestGraphVisitor for_test(owner(), 1183 TestGraphVisitor for_test(owner(),
1184 temp_index(), 1184 temp_index(),
1185 node->condition()->token_pos()); 1185 node->condition()->token_pos());
1186 node->condition()->Visit(&for_test); 1186 node->condition()->Visit(&for_test);
1187 ASSERT(!for_test.is_empty()); // Language spec. 1187 ASSERT(!for_test.is_empty()); // Language spec.
1188 1188
1189 EffectGraphVisitor for_body(owner(), temp_index()); 1189 EffectGraphVisitor for_body(owner(), temp_index());
1190 for_body.Do( 1190 for_body.AddInstruction(
1191 new CheckStackOverflowInstr(node->token_pos())); 1191 new CheckStackOverflowInstr(node->token_pos()));
1192 node->body()->Visit(&for_body); 1192 node->body()->Visit(&for_body);
1193 1193
1194 // Labels are set after body traversal. 1194 // Labels are set after body traversal.
1195 SourceLabel* lbl = node->label(); 1195 SourceLabel* lbl = node->label();
1196 ASSERT(lbl != NULL); 1196 ASSERT(lbl != NULL);
1197 JoinEntryInstr* join = lbl->join_for_continue(); 1197 JoinEntryInstr* join = lbl->join_for_continue();
1198 if (join != NULL) { 1198 if (join != NULL) {
1199 if (for_body.is_open()) for_body.Goto(join); 1199 if (for_body.is_open()) for_body.Goto(join);
1200 for_body.exit_ = join; 1200 for_body.exit_ = join;
(...skipping 12 matching lines...) Expand all
1213 // b) [ body ] 1213 // b) [ body ]
1214 // c) test-entry (continue-join or body-exit-target) 1214 // c) test-entry (continue-join or body-exit-target)
1215 // d) [ test-entry ] -> (back-target, loop-exit-target) 1215 // d) [ test-entry ] -> (back-target, loop-exit-target)
1216 // e) back-target -> (body-entry-join) 1216 // e) back-target -> (body-entry-join)
1217 // f) loop-exit-target 1217 // f) loop-exit-target
1218 // g) break-join 1218 // g) break-join
1219 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { 1219 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) {
1220 InlineBailout("EffectGraphVisitor::VisitDoWhileNode (control)"); 1220 InlineBailout("EffectGraphVisitor::VisitDoWhileNode (control)");
1221 // Traverse body first in order to generate continue and break labels. 1221 // Traverse body first in order to generate continue and break labels.
1222 EffectGraphVisitor for_body(owner(), temp_index()); 1222 EffectGraphVisitor for_body(owner(), temp_index());
1223 for_body.Do( 1223 for_body.AddInstruction(
1224 new CheckStackOverflowInstr(node->token_pos())); 1224 new CheckStackOverflowInstr(node->token_pos()));
1225 node->body()->Visit(&for_body); 1225 node->body()->Visit(&for_body);
1226 1226
1227 TestGraphVisitor for_test(owner(), 1227 TestGraphVisitor for_test(owner(),
1228 temp_index(), 1228 temp_index(),
1229 node->condition()->token_pos()); 1229 node->condition()->token_pos());
1230 node->condition()->Visit(&for_test); 1230 node->condition()->Visit(&for_test);
1231 ASSERT(is_open()); 1231 ASSERT(is_open());
1232 1232
1233 // Tie do-while loop (test is after the body). 1233 // Tie do-while loop (test is after the body).
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1269 // i) break-join 1269 // i) break-join
1270 void EffectGraphVisitor::VisitForNode(ForNode* node) { 1270 void EffectGraphVisitor::VisitForNode(ForNode* node) {
1271 InlineBailout("EffectGraphVisitor::VisitForNode (control)"); 1271 InlineBailout("EffectGraphVisitor::VisitForNode (control)");
1272 EffectGraphVisitor for_initializer(owner(), temp_index()); 1272 EffectGraphVisitor for_initializer(owner(), temp_index());
1273 node->initializer()->Visit(&for_initializer); 1273 node->initializer()->Visit(&for_initializer);
1274 Append(for_initializer); 1274 Append(for_initializer);
1275 ASSERT(is_open()); 1275 ASSERT(is_open());
1276 1276
1277 // Compose body to set any jump labels. 1277 // Compose body to set any jump labels.
1278 EffectGraphVisitor for_body(owner(), temp_index()); 1278 EffectGraphVisitor for_body(owner(), temp_index());
1279 for_body.Do( 1279 for_body.AddInstruction(
1280 new CheckStackOverflowInstr(node->token_pos())); 1280 new CheckStackOverflowInstr(node->token_pos()));
1281 node->body()->Visit(&for_body); 1281 node->body()->Visit(&for_body);
1282 1282
1283 // Join loop body, increment and compute their end instruction. 1283 // Join loop body, increment and compute their end instruction.
1284 ASSERT(!for_body.is_empty()); 1284 ASSERT(!for_body.is_empty());
1285 Instruction* loop_increment_end = NULL; 1285 Instruction* loop_increment_end = NULL;
1286 EffectGraphVisitor for_increment(owner(), temp_index()); 1286 EffectGraphVisitor for_increment(owner(), temp_index());
1287 node->increment()->Visit(&for_increment); 1287 node->increment()->Visit(&for_increment);
1288 JoinEntryInstr* join = node->label()->join_for_continue(); 1288 JoinEntryInstr* join = node->label()->join_for_continue();
1289 if (join != NULL) { 1289 if (join != NULL) {
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
1568 // Restore context from temp. 1568 // Restore context from temp.
1569 BuildLoadContext(*owner()->parsed_function().expression_temp_var()); 1569 BuildLoadContext(*owner()->parsed_function().expression_temp_var());
1570 ReturnValue(result); 1570 ReturnValue(result);
1571 } 1571 }
1572 1572
1573 1573
1574 void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) { 1574 void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) {
1575 InlineBailout("EffectGraphVisitor::VisitCloneContextNode (context)"); 1575 InlineBailout("EffectGraphVisitor::VisitCloneContextNode (context)");
1576 Value* context = Bind(new CurrentContextInstr()); 1576 Value* context = Bind(new CurrentContextInstr());
1577 Value* clone = Bind(new CloneContextInstr(node->token_pos(), context)); 1577 Value* clone = Bind(new CloneContextInstr(node->token_pos(), context));
1578 ReturnDefinition(new StoreContextInstr(clone)); 1578 AddInstruction(new StoreContextInstr(clone));
1579 } 1579 }
1580 1580
1581 1581
1582 Value* EffectGraphVisitor::BuildObjectAllocation( 1582 Value* EffectGraphVisitor::BuildObjectAllocation(
1583 ConstructorCallNode* node) { 1583 ConstructorCallNode* node) {
1584 const Class& cls = Class::ZoneHandle(node->constructor().Owner()); 1584 const Class& cls = Class::ZoneHandle(node->constructor().Owner());
1585 const bool requires_type_arguments = cls.HasTypeArguments(); 1585 const bool requires_type_arguments = cls.HasTypeArguments();
1586 1586
1587 // In checked mode, if the type arguments are uninstantiated, they may need to 1587 // In checked mode, if the type arguments are uninstantiated, they may need to
1588 // be checked against declared bounds at run time. 1588 // be checked against declared bounds at run time.
(...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after
2288 } 2288 }
2289 2289
2290 2290
2291 void EffectGraphVisitor::UnchainContext() { 2291 void EffectGraphVisitor::UnchainContext() {
2292 InlineBailout("EffectGraphVisitor::UnchainContext (context)"); 2292 InlineBailout("EffectGraphVisitor::UnchainContext (context)");
2293 Value* context = Bind(new CurrentContextInstr()); 2293 Value* context = Bind(new CurrentContextInstr());
2294 Value* parent = Bind( 2294 Value* parent = Bind(
2295 new LoadFieldInstr(context, 2295 new LoadFieldInstr(context,
2296 Context::parent_offset(), 2296 Context::parent_offset(),
2297 Type::ZoneHandle())); // Not an instance, no type. 2297 Type::ZoneHandle())); // Not an instance, no type.
2298 Do(new StoreContextInstr(parent)); 2298 AddInstruction(new StoreContextInstr(parent));
2299 } 2299 }
2300 2300
2301 2301
2302 // <Statement> ::= Sequence { scope: LocalScope 2302 // <Statement> ::= Sequence { scope: LocalScope
2303 // nodes: <Statement>* 2303 // nodes: <Statement>*
2304 // label: SourceLabel } 2304 // label: SourceLabel }
2305 void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) { 2305 void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
2306 LocalScope* scope = node->scope(); 2306 LocalScope* scope = node->scope();
2307 const intptr_t num_context_variables = 2307 const intptr_t num_context_variables =
2308 (scope != NULL) ? scope->num_context_variables() : 0; 2308 (scope != NULL) ? scope->num_context_variables() : 0;
2309 int previous_context_level = owner()->context_level(); 2309 int previous_context_level = owner()->context_level();
2310 if (num_context_variables > 0) { 2310 if (num_context_variables > 0) {
2311 InlineBailout("EffectGraphVisitor::VisitSequenceNode (context)"); 2311 InlineBailout("EffectGraphVisitor::VisitSequenceNode (context)");
2312 // The loop local scope declares variables that are captured. 2312 // The loop local scope declares variables that are captured.
2313 // Allocate and chain a new context. 2313 // Allocate and chain a new context.
2314 // Allocate context computation (uses current CTX) 2314 // Allocate context computation (uses current CTX)
2315 Value* allocated_context = 2315 Value* allocated_context =
2316 Bind(new AllocateContextInstr(node->token_pos(), 2316 Bind(new AllocateContextInstr(node->token_pos(),
2317 num_context_variables)); 2317 num_context_variables));
2318 2318
2319 // If this node_sequence is the body of the function being compiled, and if 2319 // If this node_sequence is the body of the function being compiled, and if
2320 // this function is not a closure, do not link the current context as the 2320 // this function is not a closure, do not link the current context as the
2321 // parent of the newly allocated context, as it is not accessible. Instead, 2321 // parent of the newly allocated context, as it is not accessible. Instead,
2322 // save it in a pre-allocated variable and restore it on exit. 2322 // save it in a pre-allocated variable and restore it on exit.
2323 if (MustSaveRestoreContext(node)) { 2323 if (MustSaveRestoreContext(node)) {
2324 Value* current_context = Bind(new CurrentContextInstr()); 2324 Value* current_context = Bind(new CurrentContextInstr());
2325 Do(BuildStoreTemp(*owner()->parsed_function().saved_context_var(), 2325 Do(BuildStoreTemp(*owner()->parsed_function().saved_context_var(),
2326 current_context)); 2326 current_context));
2327 Value* null_context = Bind(new ConstantInstr(Object::ZoneHandle())); 2327 Value* null_context = Bind(new ConstantInstr(Object::ZoneHandle()));
2328 Do(new StoreContextInstr(null_context)); 2328 AddInstruction(new StoreContextInstr(null_context));
2329 } 2329 }
2330 2330
2331 Do(new ChainContextInstr(allocated_context)); 2331 AddInstruction(new ChainContextInstr(allocated_context));
2332 owner()->set_context_level(scope->context_level()); 2332 owner()->set_context_level(scope->context_level());
2333 2333
2334 // If this node_sequence is the body of the function being compiled, copy 2334 // If this node_sequence is the body of the function being compiled, copy
2335 // the captured parameters from the frame into the context. 2335 // the captured parameters from the frame into the context.
2336 if (node == owner()->parsed_function().node_sequence()) { 2336 if (node == owner()->parsed_function().node_sequence()) {
2337 ASSERT(scope->context_level() == 1); 2337 ASSERT(scope->context_level() == 1);
2338 const Function& function = owner()->parsed_function().function(); 2338 const Function& function = owner()->parsed_function().function();
2339 int num_params = function.NumParameters(); 2339 int num_params = function.NumParameters();
2340 int param_frame_index = (num_params == function.num_fixed_parameters()) ? 2340 int param_frame_index = (num_params == function.num_fixed_parameters()) ?
2341 (1 + num_params) : ParsedFunction::kFirstLocalSlotIndex; 2341 (1 + num_params) : ParsedFunction::kFirstLocalSlotIndex;
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
2443 (node != owner()->parsed_function().node_sequence())); 2443 (node != owner()->parsed_function().node_sequence()));
2444 owner()->set_context_level(previous_context_level); 2444 owner()->set_context_level(previous_context_level);
2445 } 2445 }
2446 2446
2447 2447
2448 void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) { 2448 void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) {
2449 InlineBailout("EffectGraphVisitor::VisitCatchClauseNode (exception)"); 2449 InlineBailout("EffectGraphVisitor::VisitCatchClauseNode (exception)");
2450 // NOTE: The implicit variables ':saved_context', ':exception_var' 2450 // NOTE: The implicit variables ':saved_context', ':exception_var'
2451 // and ':stacktrace_var' can never be captured variables. 2451 // and ':stacktrace_var' can never be captured variables.
2452 // Restores CTX from local variable ':saved_context'. 2452 // Restores CTX from local variable ':saved_context'.
2453 Do(new CatchEntryInstr(node->exception_var(), node->stacktrace_var())); 2453 AddInstruction(
2454 new CatchEntryInstr(node->exception_var(), node->stacktrace_var()));
2454 BuildLoadContext(node->context_var()); 2455 BuildLoadContext(node->context_var());
2455 2456
2456 EffectGraphVisitor for_catch(owner(), temp_index()); 2457 EffectGraphVisitor for_catch(owner(), temp_index());
2457 node->VisitChildren(&for_catch); 2458 node->VisitChildren(&for_catch);
2458 Append(for_catch); 2459 Append(for_catch);
2459 } 2460 }
2460 2461
2461 2462
2462 void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) { 2463 void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) {
2463 InlineBailout("EffectGraphVisitor::VisitTryCatchNode (exception)"); 2464 InlineBailout("EffectGraphVisitor::VisitTryCatchNode (exception)");
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
2598 const Function& function = parsed_function().function(); 2599 const Function& function = parsed_function().function();
2599 TargetEntryInstr* normal_entry = new TargetEntryInstr( 2600 TargetEntryInstr* normal_entry = new TargetEntryInstr(
2600 CatchClauseNode::kInvalidTryIndex); 2601 CatchClauseNode::kInvalidTryIndex);
2601 graph_entry_ = new GraphEntryInstr(normal_entry); 2602 graph_entry_ = new GraphEntryInstr(normal_entry);
2602 EffectGraphVisitor for_effect(this, 0); 2603 EffectGraphVisitor for_effect(this, 0);
2603 if (InInliningContext()) { 2604 if (InInliningContext()) {
2604 exits_ = new ZoneGrowableArray<ReturnInstr*>(); 2605 exits_ = new ZoneGrowableArray<ReturnInstr*>();
2605 } 2606 }
2606 // TODO(kmillikin): We can eliminate stack checks in some cases (e.g., the 2607 // TODO(kmillikin): We can eliminate stack checks in some cases (e.g., the
2607 // stack check on entry for leaf routines). 2608 // stack check on entry for leaf routines).
2608 for_effect.Do(new CheckStackOverflowInstr(function.token_pos())); 2609 for_effect.AddInstruction(new CheckStackOverflowInstr(function.token_pos()));
2609 parsed_function().node_sequence()->Visit(&for_effect); 2610 parsed_function().node_sequence()->Visit(&for_effect);
2610 AppendFragment(normal_entry, for_effect); 2611 AppendFragment(normal_entry, for_effect);
2611 // Check that the graph is properly terminated. 2612 // Check that the graph is properly terminated.
2612 ASSERT(!for_effect.is_open()); 2613 ASSERT(!for_effect.is_open());
2613 FlowGraph* graph = new FlowGraph(*this, graph_entry_); 2614 FlowGraph* graph = new FlowGraph(*this, graph_entry_);
2614 if (InInliningContext()) graph->set_exits(exits_); 2615 if (InInliningContext()) graph->set_exits(exits_);
2615 return graph; 2616 return graph;
2616 } 2617 }
2617 2618
2618 2619
2619 void FlowGraphBuilder::Bailout(const char* reason) { 2620 void FlowGraphBuilder::Bailout(const char* reason) {
2620 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; 2621 const char* kFormat = "FlowGraphBuilder Bailout: %s %s";
2621 const char* function_name = parsed_function_.function().ToCString(); 2622 const char* function_name = parsed_function_.function().ToCString();
2622 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 2623 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
2623 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 2624 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
2624 OS::SNPrint(chars, len, kFormat, function_name, reason); 2625 OS::SNPrint(chars, len, kFormat, function_name, reason);
2625 const Error& error = Error::Handle( 2626 const Error& error = Error::Handle(
2626 LanguageError::New(String::Handle(String::New(chars)))); 2627 LanguageError::New(String::Handle(String::New(chars))));
2627 Isolate::Current()->long_jump_base()->Jump(1, error); 2628 Isolate::Current()->long_jump_base()->Jump(1, error);
2628 } 2629 }
2629 2630
2630 2631
2631 } // namespace dart 2632 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/flow_graph_optimizer.h » ('j') | runtime/vm/flow_graph_optimizer.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698