| 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/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 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 String::ZoneHandle(String::NewSymbol((node->kind() == Token::kSUB) | 717 String::ZoneHandle(String::NewSymbol((node->kind() == Token::kSUB) |
| 718 ? Token::Str(Token::kNEGATE) | 718 ? Token::Str(Token::kNEGATE) |
| 719 : node->Name())); | 719 : node->Name())); |
| 720 InstanceCallComp* call = new InstanceCallComp( | 720 InstanceCallComp* call = new InstanceCallComp( |
| 721 node->token_index(), owner()->try_index(), name, | 721 node->token_index(), owner()->try_index(), name, |
| 722 arguments, Array::ZoneHandle(), 1); | 722 arguments, Array::ZoneHandle(), 1); |
| 723 ReturnComputation(call); | 723 ReturnComputation(call); |
| 724 } | 724 } |
| 725 | 725 |
| 726 | 726 |
| 727 Definition* EffectGraphVisitor::BuildIncrOpFieldLoad( | |
| 728 IncrOpInstanceFieldNode* node, | |
| 729 Value** receiver) { | |
| 730 // Evaluate the receiver and duplicate it (it has two uses). | |
| 731 // t_n <- ... receiver ... | |
| 732 // t_n+1 <- Pick(t_n) | |
| 733 ValueGraphVisitor for_receiver(owner(), temp_index()); | |
| 734 node->receiver()->Visit(&for_receiver); | |
| 735 Append(for_receiver); | |
| 736 ASSERT(temp_index() == for_receiver.temp_index()); | |
| 737 PickTempInstr* duplicate = new PickTempInstr(temp_index() - 1); | |
| 738 AddInstruction(duplicate); | |
| 739 | |
| 740 // Load the value. | |
| 741 // t_n+1 <- InstanceCall(get:name, t_n+1) | |
| 742 const String& getter_name = | |
| 743 String::ZoneHandle(Field::GetterSymbol(node->field_name())); | |
| 744 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(1); | |
| 745 arguments->Add(new UseVal(duplicate)); | |
| 746 BindInstr* load = | |
| 747 new BindInstr(new InstanceCallComp( | |
| 748 node->token_index(), | |
| 749 owner()->try_index(), getter_name, arguments, | |
| 750 Array::ZoneHandle(), 1)); | |
| 751 AddInstruction(load); | |
| 752 | |
| 753 *receiver = for_receiver.value(); | |
| 754 return load; | |
| 755 } | |
| 756 | |
| 757 | |
| 758 Definition* EffectGraphVisitor::BuildIncrOpIncrement(Token::Kind kind, | |
| 759 intptr_t token_index, | |
| 760 Value* original) { | |
| 761 ASSERT((kind == Token::kINCR) || (kind == Token::kDECR)); | |
| 762 // Assumed that t_n-1 (where n is start_index) is the field value. | |
| 763 // t_n <- #1 | |
| 764 // t_n-1 <- InstanceCall(op, t_n-1, t_n) | |
| 765 BindInstr* one = | |
| 766 new BindInstr(new ConstantVal(Smi::ZoneHandle(Smi::New(1)))); | |
| 767 AddInstruction(one); | |
| 768 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2); | |
| 769 arguments->Add(original); | |
| 770 arguments->Add(new UseVal(one)); | |
| 771 const String& op_name = | |
| 772 String::ZoneHandle(String::NewSymbol((kind == Token::kINCR) ? "+" : "-")); | |
| 773 BindInstr* add = | |
| 774 new BindInstr(new InstanceCallComp( | |
| 775 token_index, owner()->try_index(), op_name, | |
| 776 arguments, Array::ZoneHandle(), 2)); | |
| 777 AddInstruction(add); | |
| 778 return add; | |
| 779 } | |
| 780 | |
| 781 | |
| 782 void EffectGraphVisitor::VisitIncrOpInstanceFieldNode( | |
| 783 IncrOpInstanceFieldNode* node) { | |
| 784 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); | |
| 785 // In an effect context, treat postincrement as if it were preincrement | |
| 786 // because its value is not needed. | |
| 787 | |
| 788 // 1. Load the value. | |
| 789 Value* receiver = NULL; | |
| 790 Definition* load = BuildIncrOpFieldLoad(node, &receiver); | |
| 791 // 2. Increment. | |
| 792 Definition* incr = | |
| 793 BuildIncrOpIncrement(node->kind(), node->token_index(), new UseVal(load)); | |
| 794 // 3. Perform the store, returning the stored value. | |
| 795 InstanceSetterComp* store = | |
| 796 new InstanceSetterComp(node->token_index(), | |
| 797 owner()->try_index(), | |
| 798 node->field_name(), | |
| 799 receiver, | |
| 800 new UseVal(incr)); | |
| 801 ReturnComputation(store); | |
| 802 } | |
| 803 | |
| 804 | |
| 805 void ValueGraphVisitor::VisitIncrOpInstanceFieldNode( | |
| 806 IncrOpInstanceFieldNode* node) { | |
| 807 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); | |
| 808 if (node->prefix()) { | |
| 809 // Base class handles preincrement. | |
| 810 EffectGraphVisitor::VisitIncrOpInstanceFieldNode(node); | |
| 811 return; | |
| 812 } | |
| 813 // For postincrement, preallocate a temporary to preserve the original | |
| 814 // value. | |
| 815 // | |
| 816 // 1. Name a placeholder. | |
| 817 BindInstr* placeholder = | |
| 818 new BindInstr(new ConstantVal(Smi::ZoneHandle(Smi::New(0)))); | |
| 819 AddInstruction(placeholder); | |
| 820 // 2. Load the value. | |
| 821 Value* receiver = NULL; | |
| 822 Definition* load = BuildIncrOpFieldLoad(node, &receiver); | |
| 823 // 3. Preserve the original value. | |
| 824 AddInstruction(new TuckTempInstr(placeholder->temp_index(), | |
| 825 load->temp_index())); | |
| 826 // 4. Increment. | |
| 827 Definition* incr = | |
| 828 BuildIncrOpIncrement(node->kind(), node->token_index(), new UseVal(load)); | |
| 829 // 5. Perform the store and return the original value. | |
| 830 const String& setter_name = | |
| 831 String::ZoneHandle(Field::SetterSymbol(node->field_name())); | |
| 832 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2); | |
| 833 arguments->Add(receiver); | |
| 834 arguments->Add(new UseVal(incr)); | |
| 835 InstanceCallComp* store = new InstanceCallComp( | |
| 836 node->token_index(), owner()->try_index(), | |
| 837 setter_name, arguments, Array::ZoneHandle(), 1); | |
| 838 AddInstruction(new DoInstr(store)); | |
| 839 ReturnValue(new UseVal(placeholder)); | |
| 840 } | |
| 841 | |
| 842 | |
| 843 Definition* EffectGraphVisitor::BuildIncrOpIndexedLoad( | |
| 844 IncrOpIndexedNode* node, | |
| 845 Value** receiver, | |
| 846 Value** index) { | |
| 847 // Evaluate the receiver and index. | |
| 848 // t_n <- ... receiver ... | |
| 849 // t_n+1 <- ... index ... | |
| 850 ValueGraphVisitor for_receiver(owner(), temp_index()); | |
| 851 node->array()->Visit(&for_receiver); | |
| 852 Append(for_receiver); | |
| 853 ASSERT(temp_index() == for_receiver.temp_index()); | |
| 854 | |
| 855 ValueGraphVisitor for_index(owner(), temp_index()); | |
| 856 node->index()->Visit(&for_index); | |
| 857 Append(for_index); | |
| 858 ASSERT(temp_index() == for_index.temp_index()); | |
| 859 | |
| 860 // Duplicate the receiver and index values, load the value. | |
| 861 // t_n+2 <- Pick(t_n) | |
| 862 // t_n+3 <- Pick(t_n+1) | |
| 863 // t_n+2 <- InstanceCall([], t_n+2, t_n+3) | |
| 864 PickTempInstr* duplicate_receiver = new PickTempInstr(temp_index() - 2); | |
| 865 AddInstruction(duplicate_receiver); | |
| 866 PickTempInstr* duplicate_index = new PickTempInstr(temp_index() - 2); | |
| 867 AddInstruction(duplicate_index); | |
| 868 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2); | |
| 869 arguments->Add(new UseVal(duplicate_receiver)); | |
| 870 arguments->Add(new UseVal(duplicate_index)); | |
| 871 const String& load_name = | |
| 872 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kINDEX))); | |
| 873 BindInstr* load = | |
| 874 new BindInstr(new InstanceCallComp( | |
| 875 node->token_index(), | |
| 876 owner()->try_index(), load_name, arguments, | |
| 877 Array::ZoneHandle(), 1)); | |
| 878 AddInstruction(load); | |
| 879 | |
| 880 *receiver = for_receiver.value(); | |
| 881 *index = for_index.value(); | |
| 882 return load; | |
| 883 } | |
| 884 | |
| 885 | |
| 886 void EffectGraphVisitor::VisitIncrOpIndexedNode(IncrOpIndexedNode* node) { | |
| 887 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); | |
| 888 // In an effect context, treat postincrement as if it were preincrement | |
| 889 // because its value is not needed. | |
| 890 | |
| 891 // 1. Load the value. | |
| 892 Value* receiver = NULL; | |
| 893 Value* index = NULL; | |
| 894 Definition* load = BuildIncrOpIndexedLoad(node, &receiver, &index); | |
| 895 // 2. Increment. | |
| 896 Definition* incr = | |
| 897 BuildIncrOpIncrement(node->kind(), node->token_index(), new UseVal(load)); | |
| 898 // 3. Perform the store, returning the stored value. | |
| 899 StoreIndexedComp* store = new StoreIndexedComp(node->token_index(), | |
| 900 owner()->try_index(), | |
| 901 receiver, | |
| 902 index, | |
| 903 new UseVal(incr)); | |
| 904 ReturnComputation(store); | |
| 905 } | |
| 906 | |
| 907 | |
| 908 void ValueGraphVisitor::VisitIncrOpIndexedNode(IncrOpIndexedNode* node) { | |
| 909 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); | |
| 910 if (node->prefix()) { | |
| 911 // Base class handles preincrement. | |
| 912 EffectGraphVisitor::VisitIncrOpIndexedNode(node); | |
| 913 return; | |
| 914 } | |
| 915 // For postincrement, preallocate a temporary to preserve the original | |
| 916 // value. | |
| 917 // | |
| 918 // 1. Name a placeholder. | |
| 919 BindInstr* placeholder = | |
| 920 new BindInstr(new ConstantVal(Smi::ZoneHandle(Smi::New(0)))); | |
| 921 AddInstruction(placeholder); | |
| 922 // 2. Load the value. | |
| 923 Value* receiver = NULL; | |
| 924 Value* index = NULL; | |
| 925 Definition* load = BuildIncrOpIndexedLoad(node, &receiver, &index); | |
| 926 // 3. Preserve the original value. | |
| 927 AddInstruction(new TuckTempInstr(placeholder->temp_index(), | |
| 928 load->temp_index())); | |
| 929 // 4. Increment. | |
| 930 Definition* incr = | |
| 931 BuildIncrOpIncrement(node->kind(), node->token_index(), new UseVal(load)); | |
| 932 // 5. Perform the store and return the original value. | |
| 933 const String& store_name = | |
| 934 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); | |
| 935 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(3); | |
| 936 arguments->Add(receiver); | |
| 937 arguments->Add(index); | |
| 938 arguments->Add(new UseVal(incr)); | |
| 939 InstanceCallComp* store = new InstanceCallComp( | |
| 940 node->token_index(), owner()->try_index(), | |
| 941 store_name, arguments, Array::ZoneHandle(), 1); | |
| 942 AddInstruction(new DoInstr(store)); | |
| 943 ReturnValue(new UseVal(placeholder)); | |
| 944 } | |
| 945 | |
| 946 | |
| 947 void EffectGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { | 727 void EffectGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { |
| 948 TestGraphVisitor for_test(owner(), | 728 TestGraphVisitor for_test(owner(), |
| 949 temp_index(), | 729 temp_index(), |
| 950 node->condition()->token_index()); | 730 node->condition()->token_index()); |
| 951 node->condition()->Visit(&for_test); | 731 node->condition()->Visit(&for_test); |
| 952 | 732 |
| 953 // Translate the subexpressions for their effects. | 733 // Translate the subexpressions for their effects. |
| 954 EffectGraphVisitor for_true(owner(), temp_index()); | 734 EffectGraphVisitor for_true(owner(), temp_index()); |
| 955 node->true_expr()->Visit(&for_true); | 735 node->true_expr()->Visit(&for_true); |
| 956 EffectGraphVisitor for_false(owner(), temp_index()); | 736 EffectGraphVisitor for_false(owner(), temp_index()); |
| (...skipping 1697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2654 reverse_index(instr->false_successor()->postorder_number())); | 2434 reverse_index(instr->false_successor()->postorder_number())); |
| 2655 } | 2435 } |
| 2656 | 2436 |
| 2657 | 2437 |
| 2658 void FlowGraphBuilder::BuildGraph() { | 2438 void FlowGraphBuilder::BuildGraph() { |
| 2659 if (FLAG_print_ast) { | 2439 if (FLAG_print_ast) { |
| 2660 // Print the function ast before IL generation. | 2440 // Print the function ast before IL generation. |
| 2661 AstPrinter::PrintFunctionNodes(parsed_function()); | 2441 AstPrinter::PrintFunctionNodes(parsed_function()); |
| 2662 } | 2442 } |
| 2663 TimerScope timer(FLAG_compiler_stats, &CompilerStats::graphbuilder_timer); | 2443 TimerScope timer(FLAG_compiler_stats, &CompilerStats::graphbuilder_timer); |
| 2444 // Compilation can be nested, preserve the computation-id. |
| 2445 Isolate* isolate = Isolate::Current(); |
| 2446 const intptr_t prev_cid = isolate->computation_id(); |
| 2447 isolate->set_computation_id(0); |
| 2664 const Function& function = parsed_function().function(); | 2448 const Function& function = parsed_function().function(); |
| 2665 EffectGraphVisitor for_effect(this, 0); | 2449 EffectGraphVisitor for_effect(this, 0); |
| 2666 for_effect.AddInstruction(new TargetEntryInstr()); | 2450 for_effect.AddInstruction(new TargetEntryInstr()); |
| 2667 parsed_function().node_sequence()->Visit(&for_effect); | 2451 parsed_function().node_sequence()->Visit(&for_effect); |
| 2668 // Check that the graph is properly terminated. | 2452 // Check that the graph is properly terminated. |
| 2669 ASSERT(!for_effect.is_open()); | 2453 ASSERT(!for_effect.is_open()); |
| 2670 GrowableArray<intptr_t> parent; | 2454 GrowableArray<intptr_t> parent; |
| 2671 for (intptr_t i = 0; i < catch_entries_.length(); i++) { | 2455 for (intptr_t i = 0; i < catch_entries_.length(); i++) { |
| 2672 Instruction* entry = catch_entries_[i]; | 2456 Instruction* entry = catch_entries_[i]; |
| 2673 entry->DiscoverBlocks(NULL, // Entry block predecessor. | 2457 entry->DiscoverBlocks(NULL, // Entry block predecessor. |
| 2674 &preorder_block_entries_, | 2458 &preorder_block_entries_, |
| 2675 &postorder_block_entries_, | 2459 &postorder_block_entries_, |
| 2676 &parent); | 2460 &parent); |
| 2677 ComputeDominators(&preorder_block_entries_, &parent); | 2461 ComputeDominators(&preorder_block_entries_, &parent); |
| 2678 } | 2462 } |
| 2679 if (for_effect.entry() != NULL) { | 2463 if (for_effect.entry() != NULL) { |
| 2680 // Perform a depth-first traversal of the graph to build preorder and | 2464 // Perform a depth-first traversal of the graph to build preorder and |
| 2681 // postorder block orders. | 2465 // postorder block orders. |
| 2682 for_effect.entry()->DiscoverBlocks(NULL, // Entry block predecessor. | 2466 for_effect.entry()->DiscoverBlocks(NULL, // Entry block predecessor. |
| 2683 &preorder_block_entries_, | 2467 &preorder_block_entries_, |
| 2684 &postorder_block_entries_, | 2468 &postorder_block_entries_, |
| 2685 &parent); | 2469 &parent); |
| 2686 ComputeDominators(&preorder_block_entries_, &parent); | 2470 ComputeDominators(&preorder_block_entries_, &parent); |
| 2687 } | 2471 } |
| 2472 isolate->set_computation_id(prev_cid); |
| 2688 if (FLAG_print_flow_graph) { | 2473 if (FLAG_print_flow_graph) { |
| 2689 intptr_t length = postorder_block_entries_.length(); | 2474 intptr_t length = postorder_block_entries_.length(); |
| 2690 GrowableArray<BlockEntryInstr*> reverse_postorder(length); | 2475 GrowableArray<BlockEntryInstr*> reverse_postorder(length); |
| 2691 for (intptr_t i = length - 1; i >= 0; --i) { | 2476 for (intptr_t i = length - 1; i >= 0; --i) { |
| 2692 reverse_postorder.Add(postorder_block_entries_[i]); | 2477 reverse_postorder.Add(postorder_block_entries_[i]); |
| 2693 } | 2478 } |
| 2694 FlowGraphPrinter printer(function, reverse_postorder); | 2479 FlowGraphPrinter printer(function, reverse_postorder); |
| 2695 printer.VisitBlocks(); | 2480 printer.VisitBlocks(); |
| 2696 } | 2481 } |
| 2697 } | 2482 } |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2791 char* chars = reinterpret_cast<char*>( | 2576 char* chars = reinterpret_cast<char*>( |
| 2792 Isolate::Current()->current_zone()->Allocate(len)); | 2577 Isolate::Current()->current_zone()->Allocate(len)); |
| 2793 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2578 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 2794 const Error& error = Error::Handle( | 2579 const Error& error = Error::Handle( |
| 2795 LanguageError::New(String::Handle(String::New(chars)))); | 2580 LanguageError::New(String::Handle(String::New(chars)))); |
| 2796 Isolate::Current()->long_jump_base()->Jump(1, error); | 2581 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2797 } | 2582 } |
| 2798 | 2583 |
| 2799 | 2584 |
| 2800 } // namespace dart | 2585 } // namespace dart |
| OLD | NEW |