| OLD | NEW |
| 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/flags.h" | 8 #include "vm/flags.h" |
| 9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| (...skipping 789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 800 Append(for_value); | 800 Append(for_value); |
| 801 values->Add(for_value.value()); | 801 values->Add(for_value.value()); |
| 802 index = for_value.temp_index(); | 802 index = for_value.temp_index(); |
| 803 } | 803 } |
| 804 CreateArrayComp* create = new CreateArrayComp(node, values); | 804 CreateArrayComp* create = new CreateArrayComp(node, values); |
| 805 ReturnComputation(create); | 805 ReturnComputation(create); |
| 806 } | 806 } |
| 807 | 807 |
| 808 | 808 |
| 809 void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) { | 809 void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) { |
| 810 Bailout("EffectGraphVisitor::VisitClosureNode"); | 810 const Function& function = node->function(); |
| 811 |
| 812 int next_index = temp_index(); |
| 813 if (function.IsNonImplicitClosureFunction()) { |
| 814 const int context_level = 0; // Only because we don't handle nesting yet. |
| 815 const ContextScope& context_scope = ContextScope::ZoneHandle( |
| 816 node->scope()->PreserveOuterScope(context_level)); |
| 817 ASSERT(!function.HasCode()); |
| 818 ASSERT(function.context_scope() == ContextScope::null()); |
| 819 function.set_context_scope(context_scope); |
| 820 } else if (function.IsImplicitInstanceClosureFunction()) { |
| 821 ValueGraphVisitor for_receiver(owner(), temp_index()); |
| 822 node->receiver()->Visit(&for_receiver); |
| 823 Append(for_receiver); |
| 824 if (!for_receiver.value()->IsTemp()) { |
| 825 AddInstruction(new BindInstr(temp_index(), for_receiver.value())); |
| 826 } |
| 827 ++next_index; |
| 828 } |
| 829 ASSERT(function.context_scope() != ContextScope::null()); |
| 830 |
| 831 // The function type of a closure may have type arguments. In that case, pass |
| 832 // the type arguments of the instantiator. |
| 833 const Class& cls = Class::Handle(function.signature_class()); |
| 834 ASSERT(!cls.IsNull()); |
| 835 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 836 if (requires_type_arguments) { |
| 837 Bailout("Closure creation requiring type arguments"); |
| 838 } |
| 839 |
| 840 CreateClosureComp* create = new CreateClosureComp(node); |
| 841 ReturnComputation(create); |
| 811 } | 842 } |
| 812 | 843 |
| 813 | 844 |
| 814 void EffectGraphVisitor::TranslateArgumentList( | 845 void EffectGraphVisitor::TranslateArgumentList( |
| 815 const ArgumentListNode& node, | 846 const ArgumentListNode& node, |
| 816 intptr_t next_temp_index, | 847 intptr_t next_temp_index, |
| 817 ZoneGrowableArray<Value*>* values) { | 848 ZoneGrowableArray<Value*>* values) { |
| 818 for (intptr_t i = 0; i < node.length(); ++i) { | 849 for (intptr_t i = 0; i < node.length(); ++i) { |
| 819 ArgumentGraphVisitor for_argument(owner(), next_temp_index); | 850 ArgumentGraphVisitor for_argument(owner(), next_temp_index); |
| 820 node.NodeAt(i)->Visit(&for_argument); | 851 node.NodeAt(i)->Visit(&for_argument); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 StaticCallComp* call = | 883 StaticCallComp* call = |
| 853 new StaticCallComp(node->token_index(), | 884 new StaticCallComp(node->token_index(), |
| 854 node->function(), | 885 node->function(), |
| 855 node->arguments()->names(), | 886 node->arguments()->names(), |
| 856 values); | 887 values); |
| 857 ReturnComputation(call); | 888 ReturnComputation(call); |
| 858 } | 889 } |
| 859 | 890 |
| 860 | 891 |
| 861 void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { | 892 void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { |
| 862 Bailout("EffectGraphVisitor::VisitClosureCallNode"); | 893 // Context is saved around the call, it's treated as an extra operand |
| 894 // consumed by the call (but not an argument). |
| 895 AddInstruction(new BindInstr(temp_index(), new CurrentContextComp())); |
| 896 |
| 897 ArgumentGraphVisitor for_closure(owner(), temp_index() + 1); |
| 898 node->closure()->Visit(&for_closure); |
| 899 Append(for_closure); |
| 900 |
| 901 ZoneGrowableArray<Value*>* arguments = |
| 902 new ZoneGrowableArray<Value*>(node->arguments()->length()); |
| 903 arguments->Add(for_closure.value()); |
| 904 TranslateArgumentList(*node->arguments(), temp_index() + 2, arguments); |
| 905 // First operand is the saved context, consumed by the call. |
| 906 ClosureCallComp* call = |
| 907 new ClosureCallComp(node, new TempVal(temp_index()), arguments); |
| 908 ReturnComputation(call); |
| 863 } | 909 } |
| 864 | 910 |
| 865 | 911 |
| 866 void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) { | 912 void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) { |
| 867 Bailout("EffectGraphVisitor::VisitCloneContextNode"); | 913 Bailout("EffectGraphVisitor::VisitCloneContextNode"); |
| 868 } | 914 } |
| 869 | 915 |
| 870 | 916 |
| 871 void EffectGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) { | 917 void EffectGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) { |
| 872 if (node->constructor().IsFactory()) { | 918 if (node->constructor().IsFactory()) { |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1243 } | 1289 } |
| 1244 | 1290 |
| 1245 | 1291 |
| 1246 void FlowGraphPrinter::VisitAssertAssignable(AssertAssignableComp* comp) { | 1292 void FlowGraphPrinter::VisitAssertAssignable(AssertAssignableComp* comp) { |
| 1247 OS::Print("AssertAssignable("); | 1293 OS::Print("AssertAssignable("); |
| 1248 comp->value()->Accept(this); | 1294 comp->value()->Accept(this); |
| 1249 OS::Print(", %s)", comp->type().ToCString()); | 1295 OS::Print(", %s)", comp->type().ToCString()); |
| 1250 } | 1296 } |
| 1251 | 1297 |
| 1252 | 1298 |
| 1299 void FlowGraphPrinter::VisitCurrentContext(CurrentContextComp* comp) { |
| 1300 OS::Print("CurrentContext"); |
| 1301 } |
| 1302 |
| 1303 |
| 1304 void FlowGraphPrinter::VisitClosureCall(ClosureCallComp* comp) { |
| 1305 OS::Print("ClosureCall("); |
| 1306 comp->context()->Accept(this); |
| 1307 for (intptr_t i = 0; i < comp->ArgumentCount(); ++i) { |
| 1308 OS::Print(", "); |
| 1309 comp->ArgumentAt(i)->Accept(this); |
| 1310 } |
| 1311 OS::Print(")"); |
| 1312 } |
| 1313 |
| 1314 |
| 1253 void FlowGraphPrinter::VisitInstanceCall(InstanceCallComp* comp) { | 1315 void FlowGraphPrinter::VisitInstanceCall(InstanceCallComp* comp) { |
| 1254 OS::Print("InstanceCall(%s", comp->function_name().ToCString()); | 1316 OS::Print("InstanceCall(%s", comp->function_name().ToCString()); |
| 1255 for (int i = 0; i < comp->ArgumentCount(); ++i) { | 1317 for (intptr_t i = 0; i < comp->ArgumentCount(); ++i) { |
| 1256 OS::Print(", "); | 1318 OS::Print(", "); |
| 1257 comp->ArgumentAt(i)->Accept(this); | 1319 comp->ArgumentAt(i)->Accept(this); |
| 1258 } | 1320 } |
| 1259 OS::Print(")"); | 1321 OS::Print(")"); |
| 1260 } | 1322 } |
| 1261 | 1323 |
| 1262 | 1324 |
| 1263 void FlowGraphPrinter::VisitStrictCompare(StrictCompareComp* comp) { | 1325 void FlowGraphPrinter::VisitStrictCompare(StrictCompareComp* comp) { |
| 1264 OS::Print("StrictCompare(%s, ", Token::Str(comp->kind())); | 1326 OS::Print("StrictCompare(%s, ", Token::Str(comp->kind())); |
| 1265 comp->left()->Accept(this); | 1327 comp->left()->Accept(this); |
| 1266 OS::Print(", "); | 1328 OS::Print(", "); |
| 1267 comp->right()->Accept(this); | 1329 comp->right()->Accept(this); |
| 1268 OS::Print(")"); | 1330 OS::Print(")"); |
| 1269 } | 1331 } |
| 1270 | 1332 |
| 1271 | 1333 |
| 1272 | 1334 |
| 1273 void FlowGraphPrinter::VisitStaticCall(StaticCallComp* comp) { | 1335 void FlowGraphPrinter::VisitStaticCall(StaticCallComp* comp) { |
| 1274 OS::Print("StaticCall(%s", | 1336 OS::Print("StaticCall(%s", |
| 1275 String::Handle(comp->function().name()).ToCString()); | 1337 String::Handle(comp->function().name()).ToCString()); |
| 1276 for (int i = 0; i < comp->ArgumentCount(); ++i) { | 1338 for (intptr_t i = 0; i < comp->ArgumentCount(); ++i) { |
| 1277 OS::Print(", "); | 1339 OS::Print(", "); |
| 1278 comp->ArgumentAt(i)->Accept(this); | 1340 comp->ArgumentAt(i)->Accept(this); |
| 1279 } | 1341 } |
| 1280 OS::Print(")"); | 1342 OS::Print(")"); |
| 1281 } | 1343 } |
| 1282 | 1344 |
| 1283 | 1345 |
| 1284 void FlowGraphPrinter::VisitLoadLocal(LoadLocalComp* comp) { | 1346 void FlowGraphPrinter::VisitLoadLocal(LoadLocalComp* comp) { |
| 1285 OS::Print("LoadLocal(%s)", comp->local().name().ToCString()); | 1347 OS::Print("LoadLocal(%s)", comp->local().name().ToCString()); |
| 1286 } | 1348 } |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1378 void FlowGraphPrinter::VisitCreateArray(CreateArrayComp* comp) { | 1440 void FlowGraphPrinter::VisitCreateArray(CreateArrayComp* comp) { |
| 1379 OS::Print("CreateArray("); | 1441 OS::Print("CreateArray("); |
| 1380 for (int i = 0; i < comp->ElementCount(); ++i) { | 1442 for (int i = 0; i < comp->ElementCount(); ++i) { |
| 1381 if (i != 0) OS::Print(", "); | 1443 if (i != 0) OS::Print(", "); |
| 1382 comp->ElementAt(i)->Accept(this); | 1444 comp->ElementAt(i)->Accept(this); |
| 1383 } | 1445 } |
| 1384 OS::Print(")"); | 1446 OS::Print(")"); |
| 1385 } | 1447 } |
| 1386 | 1448 |
| 1387 | 1449 |
| 1450 void FlowGraphPrinter::VisitCreateClosure(CreateClosureComp* comp) { |
| 1451 OS::Print("CreateClosure(%s)", comp->function().ToCString()); |
| 1452 } |
| 1453 |
| 1454 |
| 1388 void FlowGraphPrinter::VisitJoinEntry(JoinEntryInstr* instr) { | 1455 void FlowGraphPrinter::VisitJoinEntry(JoinEntryInstr* instr) { |
| 1389 OS::Print("%2d: [join]", instr->block_number()); | 1456 OS::Print("%2d: [join]", instr->block_number()); |
| 1390 } | 1457 } |
| 1391 | 1458 |
| 1392 | 1459 |
| 1393 void FlowGraphPrinter::VisitTargetEntry(TargetEntryInstr* instr) { | 1460 void FlowGraphPrinter::VisitTargetEntry(TargetEntryInstr* instr) { |
| 1394 OS::Print("%2d: [target]", instr->block_number()); | 1461 OS::Print("%2d: [target]", instr->block_number()); |
| 1395 } | 1462 } |
| 1396 | 1463 |
| 1397 | 1464 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1427 OS::Print(" if "); | 1494 OS::Print(" if "); |
| 1428 instr->value()->Accept(this); | 1495 instr->value()->Accept(this); |
| 1429 OS::Print(" goto(%d, %d)", instr->true_successor()->block_number(), | 1496 OS::Print(" goto(%d, %d)", instr->true_successor()->block_number(), |
| 1430 instr->false_successor()->block_number()); | 1497 instr->false_successor()->block_number()); |
| 1431 } | 1498 } |
| 1432 | 1499 |
| 1433 | 1500 |
| 1434 void FlowGraphBuilder::BuildGraph() { | 1501 void FlowGraphBuilder::BuildGraph() { |
| 1435 if (FLAG_print_ast) { | 1502 if (FLAG_print_ast) { |
| 1436 // Print the function ast before IL generation. | 1503 // Print the function ast before IL generation. |
| 1437 AstPrinter::PrintFunctionNodes(parsed_function_); | 1504 AstPrinter::PrintFunctionNodes(parsed_function()); |
| 1505 } |
| 1506 const Function& function = parsed_function().function(); |
| 1507 if ((function.num_optional_parameters() != 0)) { |
| 1508 Bailout("function has optional parameters"); |
| 1438 } | 1509 } |
| 1439 EffectGraphVisitor for_effect(this, 0); | 1510 EffectGraphVisitor for_effect(this, 0); |
| 1440 for_effect.AddInstruction(new TargetEntryInstr()); | 1511 for_effect.AddInstruction(new TargetEntryInstr()); |
| 1441 parsed_function().node_sequence()->Visit(&for_effect); | 1512 parsed_function().node_sequence()->Visit(&for_effect); |
| 1442 // Check that the graph is properly terminated. | 1513 // Check that the graph is properly terminated. |
| 1443 ASSERT(!for_effect.is_open()); | 1514 ASSERT(!for_effect.is_open()); |
| 1444 if (for_effect.entry() != NULL) { | 1515 if (for_effect.entry() != NULL) { |
| 1445 // Accumulate basic block entries via postorder traversal. | 1516 // Accumulate basic block entries via postorder traversal. |
| 1446 for_effect.entry()->Postorder(&postorder_block_entries_); | 1517 for_effect.entry()->Postorder(&postorder_block_entries_); |
| 1447 // Number the blocks in reverse postorder starting with 0. | 1518 // Number the blocks in reverse postorder starting with 0. |
| 1448 intptr_t last_index = postorder_block_entries_.length() - 1; | 1519 intptr_t last_index = postorder_block_entries_.length() - 1; |
| 1449 for (intptr_t i = last_index; i >= 0; --i) { | 1520 for (intptr_t i = last_index; i >= 0; --i) { |
| 1450 postorder_block_entries_[i]->set_block_number(last_index - i); | 1521 postorder_block_entries_[i]->set_block_number(last_index - i); |
| 1451 } | 1522 } |
| 1452 } | 1523 } |
| 1453 if (FLAG_print_flow_graph) { | 1524 if (FLAG_print_flow_graph) { |
| 1454 FlowGraphPrinter printer(parsed_function().function()); | 1525 FlowGraphPrinter printer(function); |
| 1455 printer.VisitBlocks(postorder_block_entries_); | 1526 printer.VisitBlocks(postorder_block_entries_); |
| 1456 } | 1527 } |
| 1457 } | 1528 } |
| 1458 | 1529 |
| 1459 | 1530 |
| 1460 void FlowGraphBuilder::Bailout(const char* reason) { | 1531 void FlowGraphBuilder::Bailout(const char* reason) { |
| 1461 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; | 1532 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; |
| 1462 const char* function_name = parsed_function_.function().ToCString(); | 1533 const char* function_name = parsed_function_.function().ToCString(); |
| 1463 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 1534 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 1464 char* chars = reinterpret_cast<char*>( | 1535 char* chars = reinterpret_cast<char*>( |
| 1465 Isolate::Current()->current_zone()->Allocate(len)); | 1536 Isolate::Current()->current_zone()->Allocate(len)); |
| 1466 OS::SNPrint(chars, len, kFormat, function_name, reason); | 1537 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 1467 const Error& error = Error::Handle( | 1538 const Error& error = Error::Handle( |
| 1468 LanguageError::New(String::Handle(String::New(chars)))); | 1539 LanguageError::New(String::Handle(String::New(chars)))); |
| 1469 Isolate::Current()->long_jump_base()->Jump(1, error); | 1540 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 1470 } | 1541 } |
| 1471 | 1542 |
| 1472 | 1543 |
| 1473 } // namespace dart | 1544 } // namespace dart |
| OLD | NEW |