| 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 "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.h" |
| 9 #include "vm/code_descriptors.h" | 9 #include "vm/code_descriptors.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 DECLARE_FLAG(bool, enable_type_checks); | 34 DECLARE_FLAG(bool, enable_type_checks); |
| 35 | 35 |
| 36 | 36 |
| 37 static const String& PrivateCoreLibName(const String& str) { | 37 static const String& PrivateCoreLibName(const String& str) { |
| 38 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | 38 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 39 const String& private_name = String::ZoneHandle(core_lib.PrivateName(str)); | 39 const String& private_name = String::ZoneHandle(core_lib.PrivateName(str)); |
| 40 return private_name; | 40 return private_name; |
| 41 } | 41 } |
| 42 | 42 |
| 43 | 43 |
| 44 FlowGraphBuilder::FlowGraphBuilder(const ParsedFunction& parsed_function, | 44 FlowGraphBuilder::FlowGraphBuilder(ParsedFunction* parsed_function, |
| 45 const Array& ic_data_array, | 45 const Array& ic_data_array, |
| 46 InlineExitCollector* exit_collector) | 46 InlineExitCollector* exit_collector) |
| 47 : parsed_function_(parsed_function), | 47 : parsed_function_(parsed_function), |
| 48 ic_data_array_(ic_data_array), | 48 ic_data_array_(ic_data_array), |
| 49 num_copied_params_(parsed_function.num_copied_params()), | 49 num_copied_params_(parsed_function->num_copied_params()), |
| 50 // All parameters are copied if any parameter is. | 50 // All parameters are copied if any parameter is. |
| 51 num_non_copied_params_((num_copied_params_ == 0) | 51 num_non_copied_params_((num_copied_params_ == 0) |
| 52 ? parsed_function.function().num_fixed_parameters() | 52 ? parsed_function->function().num_fixed_parameters() |
| 53 : 0), | 53 : 0), |
| 54 num_stack_locals_(parsed_function.num_stack_locals()), | 54 num_stack_locals_(parsed_function->num_stack_locals()), |
| 55 exit_collector_(exit_collector), | 55 exit_collector_(exit_collector), |
| 56 last_used_block_id_(0), // 0 is used for the graph entry. | 56 last_used_block_id_(0), // 0 is used for the graph entry. |
| 57 context_level_(0), | 57 context_level_(0), |
| 58 last_used_try_index_(CatchClauseNode::kInvalidTryIndex), | 58 last_used_try_index_(CatchClauseNode::kInvalidTryIndex), |
| 59 try_index_(CatchClauseNode::kInvalidTryIndex), | 59 try_index_(CatchClauseNode::kInvalidTryIndex), |
| 60 graph_entry_(NULL), | 60 graph_entry_(NULL), |
| 61 args_pushed_(0) { } | 61 args_pushed_(0) { } |
| 62 | 62 |
| 63 | 63 |
| 64 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) { | 64 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) { |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 | 515 |
| 516 | 516 |
| 517 Definition* EffectGraphVisitor::BuildStoreTemp(const LocalVariable& local, | 517 Definition* EffectGraphVisitor::BuildStoreTemp(const LocalVariable& local, |
| 518 Value* value) { | 518 Value* value) { |
| 519 ASSERT(!local.is_captured()); | 519 ASSERT(!local.is_captured()); |
| 520 return new StoreLocalInstr(local, value); | 520 return new StoreLocalInstr(local, value); |
| 521 } | 521 } |
| 522 | 522 |
| 523 | 523 |
| 524 Definition* EffectGraphVisitor::BuildStoreExprTemp(Value* value) { | 524 Definition* EffectGraphVisitor::BuildStoreExprTemp(Value* value) { |
| 525 return BuildStoreTemp(*owner()->parsed_function().expression_temp_var(), | 525 return BuildStoreTemp(*owner()->parsed_function()->expression_temp_var(), |
| 526 value); | 526 value); |
| 527 } | 527 } |
| 528 | 528 |
| 529 | 529 |
| 530 Definition* EffectGraphVisitor::BuildLoadExprTemp() { | 530 Definition* EffectGraphVisitor::BuildLoadExprTemp() { |
| 531 return BuildLoadLocal(*owner()->parsed_function().expression_temp_var()); | 531 return BuildLoadLocal(*owner()->parsed_function()->expression_temp_var()); |
| 532 } | 532 } |
| 533 | 533 |
| 534 | 534 |
| 535 Definition* EffectGraphVisitor::BuildStoreLocal( | 535 Definition* EffectGraphVisitor::BuildStoreLocal( |
| 536 const LocalVariable& local, Value* value, bool result_is_needed) { | 536 const LocalVariable& local, Value* value, bool result_is_needed) { |
| 537 if (local.is_captured()) { | 537 if (local.is_captured()) { |
| 538 InlineBailout("EffectGraphVisitor::BuildStoreLocal (context)"); | 538 InlineBailout("EffectGraphVisitor::BuildStoreLocal (context)"); |
| 539 if (result_is_needed) { | 539 if (result_is_needed) { |
| 540 value = Bind(BuildStoreExprTemp(value)); | 540 value = Bind(BuildStoreExprTemp(value)); |
| 541 } | 541 } |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 ValueGraphVisitor::VisitBinaryOpNode(node); | 762 ValueGraphVisitor::VisitBinaryOpNode(node); |
| 763 } | 763 } |
| 764 | 764 |
| 765 | 765 |
| 766 void EffectGraphVisitor::Bailout(const char* reason) { | 766 void EffectGraphVisitor::Bailout(const char* reason) { |
| 767 owner()->Bailout(reason); | 767 owner()->Bailout(reason); |
| 768 } | 768 } |
| 769 | 769 |
| 770 | 770 |
| 771 void EffectGraphVisitor::InlineBailout(const char* reason) { | 771 void EffectGraphVisitor::InlineBailout(const char* reason) { |
| 772 owner()->parsed_function().function().set_is_inlinable(false); | 772 owner()->parsed_function()->function().set_is_inlinable(false); |
| 773 if (owner()->IsInlining()) owner()->Bailout(reason); | 773 if (owner()->IsInlining()) owner()->Bailout(reason); |
| 774 } | 774 } |
| 775 | 775 |
| 776 | 776 |
| 777 // <Statement> ::= Return { value: <Expression> | 777 // <Statement> ::= Return { value: <Expression> |
| 778 // inlined_finally_list: <InlinedFinally>* } | 778 // inlined_finally_list: <InlinedFinally>* } |
| 779 void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) { | 779 void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) { |
| 780 ValueGraphVisitor for_value(owner(), temp_index()); | 780 ValueGraphVisitor for_value(owner(), temp_index()); |
| 781 node->value()->Visit(&for_value); | 781 node->value()->Visit(&for_value); |
| 782 Append(for_value); | 782 Append(for_value); |
| 783 | 783 |
| 784 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { | 784 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { |
| 785 InlineBailout("EffectGraphVisitor::VisitReturnNode (exception)"); | 785 InlineBailout("EffectGraphVisitor::VisitReturnNode (exception)"); |
| 786 EffectGraphVisitor for_effect(owner(), temp_index()); | 786 EffectGraphVisitor for_effect(owner(), temp_index()); |
| 787 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); | 787 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); |
| 788 Append(for_effect); | 788 Append(for_effect); |
| 789 if (!is_open()) return; | 789 if (!is_open()) return; |
| 790 } | 790 } |
| 791 | 791 |
| 792 Value* return_value = for_value.value(); | 792 Value* return_value = for_value.value(); |
| 793 if (FLAG_enable_type_checks) { | 793 if (FLAG_enable_type_checks) { |
| 794 const Function& function = owner()->parsed_function().function(); | 794 const Function& function = owner()->parsed_function()->function(); |
| 795 const bool is_implicit_dynamic_getter = | 795 const bool is_implicit_dynamic_getter = |
| 796 (!function.is_static() && | 796 (!function.is_static() && |
| 797 ((function.kind() == RawFunction::kImplicitGetter) || | 797 ((function.kind() == RawFunction::kImplicitGetter) || |
| 798 (function.kind() == RawFunction::kConstImplicitGetter))); | 798 (function.kind() == RawFunction::kConstImplicitGetter))); |
| 799 // Implicit getters do not need a type check at return, unless they compute | 799 // Implicit getters do not need a type check at return, unless they compute |
| 800 // the initial value of a static field. | 800 // the initial value of a static field. |
| 801 // The body of a constructor cannot modify the type of the | 801 // The body of a constructor cannot modify the type of the |
| 802 // constructed instance, which is passed in as an implicit parameter. | 802 // constructed instance, which is passed in as an implicit parameter. |
| 803 // However, factories may create an instance of the wrong type. | 803 // However, factories may create an instance of the wrong type. |
| 804 if (!is_implicit_dynamic_getter && !function.IsConstructor()) { | 804 if (!is_implicit_dynamic_getter && !function.IsConstructor()) { |
| 805 const AbstractType& dst_type = | 805 const AbstractType& dst_type = |
| 806 AbstractType::ZoneHandle( | 806 AbstractType::ZoneHandle( |
| 807 owner()->parsed_function().function().result_type()); | 807 owner()->parsed_function()->function().result_type()); |
| 808 return_value = BuildAssignableValue(node->value()->token_pos(), | 808 return_value = BuildAssignableValue(node->value()->token_pos(), |
| 809 return_value, | 809 return_value, |
| 810 dst_type, | 810 dst_type, |
| 811 Symbols::FunctionResult()); | 811 Symbols::FunctionResult()); |
| 812 } | 812 } |
| 813 } | 813 } |
| 814 | 814 |
| 815 intptr_t current_context_level = owner()->context_level(); | 815 intptr_t current_context_level = owner()->context_level(); |
| 816 ASSERT(current_context_level >= 0); | 816 ASSERT(current_context_level >= 0); |
| 817 if (owner()->parsed_function().saved_entry_context_var() != NULL) { | 817 if (owner()->parsed_function()->saved_entry_context_var() != NULL) { |
| 818 // CTX on entry was saved, but not linked as context parent. | 818 // CTX on entry was saved, but not linked as context parent. |
| 819 BuildLoadContext(*owner()->parsed_function().saved_entry_context_var()); | 819 BuildLoadContext(*owner()->parsed_function()->saved_entry_context_var()); |
| 820 } else { | 820 } else { |
| 821 while (current_context_level-- > 0) { | 821 while (current_context_level-- > 0) { |
| 822 UnchainContext(); | 822 UnchainContext(); |
| 823 } | 823 } |
| 824 } | 824 } |
| 825 | 825 |
| 826 AddReturnExit(node->token_pos(), return_value); | 826 AddReturnExit(node->token_pos(), return_value); |
| 827 } | 827 } |
| 828 | 828 |
| 829 | 829 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 | 879 |
| 880 // If nothing is known about the value, as is the case for passed-in | 880 // If nothing is known about the value, as is the case for passed-in |
| 881 // parameters, and since dst_type is not one of the tested cases above, then | 881 // parameters, and since dst_type is not one of the tested cases above, then |
| 882 // the type test cannot be eliminated. | 882 // the type test cannot be eliminated. |
| 883 if (value == NULL) { | 883 if (value == NULL) { |
| 884 return false; | 884 return false; |
| 885 } | 885 } |
| 886 | 886 |
| 887 const bool eliminated = value->Type()->IsAssignableTo(dst_type); | 887 const bool eliminated = value->Type()->IsAssignableTo(dst_type); |
| 888 if (FLAG_trace_type_check_elimination) { | 888 if (FLAG_trace_type_check_elimination) { |
| 889 FlowGraphPrinter::PrintTypeCheck(owner()->parsed_function(), | 889 FlowGraphPrinter::PrintTypeCheck(*owner()->parsed_function(), |
| 890 token_pos, | 890 token_pos, |
| 891 value, | 891 value, |
| 892 dst_type, | 892 dst_type, |
| 893 dst_name, | 893 dst_name, |
| 894 eliminated); | 894 eliminated); |
| 895 } | 895 } |
| 896 return eliminated; | 896 return eliminated; |
| 897 } | 897 } |
| 898 | 898 |
| 899 | 899 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1027 } | 1027 } |
| 1028 EffectGraphVisitor::VisitBinaryOpNode(node); | 1028 EffectGraphVisitor::VisitBinaryOpNode(node); |
| 1029 } | 1029 } |
| 1030 | 1030 |
| 1031 | 1031 |
| 1032 void EffectGraphVisitor::BuildTypecheckPushArguments( | 1032 void EffectGraphVisitor::BuildTypecheckPushArguments( |
| 1033 intptr_t token_pos, | 1033 intptr_t token_pos, |
| 1034 PushArgumentInstr** push_instantiator_result, | 1034 PushArgumentInstr** push_instantiator_result, |
| 1035 PushArgumentInstr** push_instantiator_type_arguments_result) { | 1035 PushArgumentInstr** push_instantiator_type_arguments_result) { |
| 1036 const Class& instantiator_class = Class::Handle( | 1036 const Class& instantiator_class = Class::Handle( |
| 1037 owner()->parsed_function().function().Owner()); | 1037 owner()->parsed_function()->function().Owner()); |
| 1038 // Since called only when type tested against is not instantiated. | 1038 // Since called only when type tested against is not instantiated. |
| 1039 ASSERT(instantiator_class.NumTypeParameters() > 0); | 1039 ASSERT(instantiator_class.NumTypeParameters() > 0); |
| 1040 Value* instantiator_type_arguments = NULL; | 1040 Value* instantiator_type_arguments = NULL; |
| 1041 Value* instantiator = BuildInstantiator(); | 1041 Value* instantiator = BuildInstantiator(); |
| 1042 if (instantiator == NULL) { | 1042 if (instantiator == NULL) { |
| 1043 // No instantiator when inside factory. | 1043 // No instantiator when inside factory. |
| 1044 *push_instantiator_result = PushArgument(BuildNullValue()); | 1044 *push_instantiator_result = PushArgument(BuildNullValue()); |
| 1045 instantiator_type_arguments = | 1045 instantiator_type_arguments = |
| 1046 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); | 1046 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); |
| 1047 } else { | 1047 } else { |
| 1048 instantiator = Bind(BuildStoreExprTemp(instantiator)); | 1048 instantiator = Bind(BuildStoreExprTemp(instantiator)); |
| 1049 *push_instantiator_result = PushArgument(instantiator); | 1049 *push_instantiator_result = PushArgument(instantiator); |
| 1050 Value* loaded = Bind(BuildLoadExprTemp()); | 1050 Value* loaded = Bind(BuildLoadExprTemp()); |
| 1051 instantiator_type_arguments = | 1051 instantiator_type_arguments = |
| 1052 BuildInstantiatorTypeArguments(token_pos, instantiator_class, loaded); | 1052 BuildInstantiatorTypeArguments(token_pos, instantiator_class, loaded); |
| 1053 } | 1053 } |
| 1054 *push_instantiator_type_arguments_result = | 1054 *push_instantiator_type_arguments_result = |
| 1055 PushArgument(instantiator_type_arguments); | 1055 PushArgument(instantiator_type_arguments); |
| 1056 } | 1056 } |
| 1057 | 1057 |
| 1058 | 1058 |
| 1059 | 1059 |
| 1060 void EffectGraphVisitor::BuildTypecheckArguments( | 1060 void EffectGraphVisitor::BuildTypecheckArguments( |
| 1061 intptr_t token_pos, | 1061 intptr_t token_pos, |
| 1062 Value** instantiator_result, | 1062 Value** instantiator_result, |
| 1063 Value** instantiator_type_arguments_result) { | 1063 Value** instantiator_type_arguments_result) { |
| 1064 Value* instantiator = NULL; | 1064 Value* instantiator = NULL; |
| 1065 Value* instantiator_type_arguments = NULL; | 1065 Value* instantiator_type_arguments = NULL; |
| 1066 const Class& instantiator_class = Class::Handle( | 1066 const Class& instantiator_class = Class::Handle( |
| 1067 owner()->parsed_function().function().Owner()); | 1067 owner()->parsed_function()->function().Owner()); |
| 1068 // Since called only when type tested against is not instantiated. | 1068 // Since called only when type tested against is not instantiated. |
| 1069 ASSERT(instantiator_class.NumTypeParameters() > 0); | 1069 ASSERT(instantiator_class.NumTypeParameters() > 0); |
| 1070 instantiator = BuildInstantiator(); | 1070 instantiator = BuildInstantiator(); |
| 1071 if (instantiator == NULL) { | 1071 if (instantiator == NULL) { |
| 1072 // No instantiator when inside factory. | 1072 // No instantiator when inside factory. |
| 1073 instantiator = BuildNullValue(); | 1073 instantiator = BuildNullValue(); |
| 1074 instantiator_type_arguments = | 1074 instantiator_type_arguments = |
| 1075 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); | 1075 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); |
| 1076 } else { | 1076 } else { |
| 1077 // Preserve instantiator. | 1077 // Preserve instantiator. |
| (...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1831 | 1831 |
| 1832 intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const { | 1832 intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const { |
| 1833 return kFirstLocalSlotFromFp | 1833 return kFirstLocalSlotFromFp |
| 1834 - owner()->num_stack_locals() | 1834 - owner()->num_stack_locals() |
| 1835 - owner()->num_copied_params() | 1835 - owner()->num_copied_params() |
| 1836 - owner()->args_pushed() | 1836 - owner()->args_pushed() |
| 1837 - temp_index() + 1; | 1837 - temp_index() + 1; |
| 1838 } | 1838 } |
| 1839 | 1839 |
| 1840 | 1840 |
| 1841 class TempLocalScope : public ValueObject { | 1841 LocalVariable* EffectGraphVisitor::EnterTempLocalScope(Value* value) { |
| 1842 public: | 1842 Do(new PushTempInstr(value)); |
| 1843 TempLocalScope(EffectGraphVisitor* visitor, Value* value) | 1843 AllocateTempIndex(); |
| 1844 : visitor_(visitor) { | |
| 1845 ASSERT(value->definition()->temp_index() == visitor->temp_index() - 1); | |
| 1846 intptr_t index = visitor->GetCurrentTempLocalIndex(); | |
| 1847 char name[64]; | |
| 1848 OS::SNPrint(name, 64, ":tmp_local%"Pd, index); | |
| 1849 var_ = new LocalVariable(0, String::ZoneHandle(Symbols::New(name)), | |
| 1850 Type::ZoneHandle(Type::DynamicType())); | |
| 1851 var_->set_index(index); | |
| 1852 visitor->Do(new PushTempInstr(value)); | |
| 1853 visitor->AllocateTempIndex(); | |
| 1854 } | |
| 1855 | 1844 |
| 1856 LocalVariable* var() const { return var_; } | 1845 ASSERT(value->definition()->temp_index() == temp_index() - 1); |
| 1846 intptr_t index = GetCurrentTempLocalIndex(); |
| 1847 char name[64]; |
| 1848 OS::SNPrint(name, 64, ":tmp_local%"Pd, index); |
| 1849 LocalVariable* var = |
| 1850 new LocalVariable(0, String::ZoneHandle(Symbols::New(name)), |
| 1851 Type::ZoneHandle(Type::DynamicType())); |
| 1852 var->set_index(index); |
| 1853 return var; |
| 1854 } |
| 1857 | 1855 |
| 1858 ~TempLocalScope() { | |
| 1859 Value* result = visitor_->Bind(new LoadLocalInstr(*var_)); | |
| 1860 visitor_->DeallocateTempIndex(1); | |
| 1861 visitor_->ReturnDefinition(new DropTempsInstr(1, result)); | |
| 1862 } | |
| 1863 | 1856 |
| 1864 private: | 1857 Definition* EffectGraphVisitor::ExitTempLocalScope(LocalVariable* var) { |
| 1865 EffectGraphVisitor* visitor_; | 1858 Value* tmp = Bind(new LoadLocalInstr(*var)); |
| 1866 LocalVariable* var_; | 1859 DeallocateTempIndex(1); |
| 1867 }; | 1860 ASSERT(GetCurrentTempLocalIndex() == var->index()); |
| 1861 return new DropTempsInstr(1, tmp); |
| 1862 } |
| 1868 | 1863 |
| 1869 | 1864 |
| 1870 void EffectGraphVisitor::BuildLetTempExpressions(LetNode* node) { | 1865 void EffectGraphVisitor::BuildLetTempExpressions(LetNode* node) { |
| 1871 intptr_t num_temps = node->num_temps(); | 1866 intptr_t num_temps = node->num_temps(); |
| 1872 for (intptr_t i = 0; i < num_temps; ++i) { | 1867 for (intptr_t i = 0; i < num_temps; ++i) { |
| 1873 ValueGraphVisitor for_value(owner(), temp_index()); | 1868 ValueGraphVisitor for_value(owner(), temp_index()); |
| 1874 node->InitializerAt(i)->Visit(&for_value); | 1869 node->InitializerAt(i)->Visit(&for_value); |
| 1875 Append(for_value); | 1870 Append(for_value); |
| 1876 Value* temp_val = for_value.value(); | 1871 Value* temp_val = for_value.value(); |
| 1877 node->TempAt(i)->set_index(GetCurrentTempLocalIndex()); | 1872 node->TempAt(i)->set_index(GetCurrentTempLocalIndex()); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1919 const AbstractTypeArguments& type_args = | 1914 const AbstractTypeArguments& type_args = |
| 1920 AbstractTypeArguments::ZoneHandle(node->type().arguments()); | 1915 AbstractTypeArguments::ZoneHandle(node->type().arguments()); |
| 1921 Value* element_type = BuildInstantiatedTypeArguments(node->token_pos(), | 1916 Value* element_type = BuildInstantiatedTypeArguments(node->token_pos(), |
| 1922 type_args); | 1917 type_args); |
| 1923 CreateArrayInstr* create = new CreateArrayInstr(node->token_pos(), | 1918 CreateArrayInstr* create = new CreateArrayInstr(node->token_pos(), |
| 1924 node->length(), | 1919 node->length(), |
| 1925 node->type(), | 1920 node->type(), |
| 1926 element_type); | 1921 element_type); |
| 1927 Value* array_val = Bind(create); | 1922 Value* array_val = Bind(create); |
| 1928 | 1923 |
| 1929 { TempLocalScope tmp(this, array_val); | 1924 { LocalVariable* tmp_var = EnterTempLocalScope(array_val); |
| 1930 const intptr_t class_id = create->Type()->ToCid(); | 1925 const intptr_t class_id = create->Type()->ToCid(); |
| 1931 const intptr_t deopt_id = Isolate::kNoDeoptId; | 1926 const intptr_t deopt_id = Isolate::kNoDeoptId; |
| 1932 for (int i = 0; i < node->length(); ++i) { | 1927 for (int i = 0; i < node->length(); ++i) { |
| 1933 Value* array = Bind(new LoadLocalInstr(*tmp.var())); | 1928 Value* array = Bind(new LoadLocalInstr(*tmp_var)); |
| 1934 Value* index = Bind(new ConstantInstr(Smi::ZoneHandle(Smi::New(i)))); | 1929 Value* index = Bind(new ConstantInstr(Smi::ZoneHandle(Smi::New(i)))); |
| 1935 ValueGraphVisitor for_value(owner(), temp_index()); | 1930 ValueGraphVisitor for_value(owner(), temp_index()); |
| 1936 node->ElementAt(i)->Visit(&for_value); | 1931 node->ElementAt(i)->Visit(&for_value); |
| 1937 Append(for_value); | 1932 Append(for_value); |
| 1938 // No store barrier needed for constants. | 1933 // No store barrier needed for constants. |
| 1939 const StoreBarrierType emit_store_barrier = | 1934 const StoreBarrierType emit_store_barrier = |
| 1940 for_value.value()->BindsToConstant() | 1935 for_value.value()->BindsToConstant() |
| 1941 ? kNoStoreBarrier | 1936 ? kNoStoreBarrier |
| 1942 : kEmitStoreBarrier; | 1937 : kEmitStoreBarrier; |
| 1943 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(class_id); | 1938 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(class_id); |
| 1944 StoreIndexedInstr* store = new StoreIndexedInstr( | 1939 StoreIndexedInstr* store = new StoreIndexedInstr( |
| 1945 array, index, for_value.value(), | 1940 array, index, for_value.value(), |
| 1946 emit_store_barrier, index_scale, class_id, deopt_id); | 1941 emit_store_barrier, index_scale, class_id, deopt_id); |
| 1947 Do(store); | 1942 Do(store); |
| 1948 } | 1943 } |
| 1944 ReturnDefinition(ExitTempLocalScope(tmp_var)); |
| 1949 } | 1945 } |
| 1950 } | 1946 } |
| 1951 | 1947 |
| 1952 | 1948 |
| 1953 void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) { | 1949 void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) { |
| 1954 const Function& function = node->function(); | 1950 const Function& function = node->function(); |
| 1955 | 1951 |
| 1956 if (function.IsImplicitStaticClosureFunction()) { | 1952 if (function.IsImplicitStaticClosureFunction()) { |
| 1957 Instance& closure = Instance::ZoneHandle(); | 1953 Instance& closure = Instance::ZoneHandle(); |
| 1958 closure ^= function.implicit_static_closure(); | 1954 closure ^= function.implicit_static_closure(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1993 | 1989 |
| 1994 // The function type of a closure may have type arguments. In that case, pass | 1990 // The function type of a closure may have type arguments. In that case, pass |
| 1995 // the type arguments of the instantiator. Otherwise, pass null object. | 1991 // the type arguments of the instantiator. Otherwise, pass null object. |
| 1996 const Class& cls = Class::Handle(function.signature_class()); | 1992 const Class& cls = Class::Handle(function.signature_class()); |
| 1997 ASSERT(!cls.IsNull()); | 1993 ASSERT(!cls.IsNull()); |
| 1998 const bool requires_type_arguments = cls.HasTypeArguments(); | 1994 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 1999 Value* type_arguments = NULL; | 1995 Value* type_arguments = NULL; |
| 2000 if (requires_type_arguments) { | 1996 if (requires_type_arguments) { |
| 2001 ASSERT(!function.IsImplicitStaticClosureFunction()); | 1997 ASSERT(!function.IsImplicitStaticClosureFunction()); |
| 2002 const Class& instantiator_class = Class::Handle( | 1998 const Class& instantiator_class = Class::Handle( |
| 2003 owner()->parsed_function().function().Owner()); | 1999 owner()->parsed_function()->function().Owner()); |
| 2004 type_arguments = BuildInstantiatorTypeArguments(node->token_pos(), | 2000 type_arguments = BuildInstantiatorTypeArguments(node->token_pos(), |
| 2005 instantiator_class, | 2001 instantiator_class, |
| 2006 NULL); | 2002 NULL); |
| 2007 } else { | 2003 } else { |
| 2008 type_arguments = BuildNullValue(); | 2004 type_arguments = BuildNullValue(); |
| 2009 } | 2005 } |
| 2010 PushArgumentInstr* push_type_arguments = PushArgument(type_arguments); | 2006 PushArgumentInstr* push_type_arguments = PushArgument(type_arguments); |
| 2011 arguments->Add(push_type_arguments); | 2007 arguments->Add(push_type_arguments); |
| 2012 ReturnDefinition( | 2008 ReturnDefinition( |
| 2013 new CreateClosureInstr(node->function(), arguments, node->token_pos())); | 2009 new CreateClosureInstr(node->function(), arguments, node->token_pos())); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2114 node->closure()->Visit(&for_closure); | 2110 node->closure()->Visit(&for_closure); |
| 2115 Append(for_closure); | 2111 Append(for_closure); |
| 2116 PushArgumentInstr* push_closure = PushArgument(for_closure.value()); | 2112 PushArgumentInstr* push_closure = PushArgument(for_closure.value()); |
| 2117 | 2113 |
| 2118 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2114 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 2119 new ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length()); | 2115 new ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length()); |
| 2120 arguments->Add(push_closure); | 2116 arguments->Add(push_closure); |
| 2121 BuildPushArguments(*node->arguments(), arguments); | 2117 BuildPushArguments(*node->arguments(), arguments); |
| 2122 | 2118 |
| 2123 // Save context around the call. | 2119 // Save context around the call. |
| 2124 ASSERT(owner()->parsed_function().saved_current_context_var() != NULL); | 2120 ASSERT(owner()->parsed_function()->saved_current_context_var() != NULL); |
| 2125 BuildStoreContext(*owner()->parsed_function().saved_current_context_var()); | 2121 BuildStoreContext(*owner()->parsed_function()->saved_current_context_var()); |
| 2126 return new ClosureCallInstr(node, arguments); | 2122 return new ClosureCallInstr(node, arguments); |
| 2127 } | 2123 } |
| 2128 | 2124 |
| 2129 | 2125 |
| 2130 void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { | 2126 void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { |
| 2131 Do(BuildClosureCall(node)); | 2127 Do(BuildClosureCall(node)); |
| 2132 // Restore context from saved location. | 2128 // Restore context from saved location. |
| 2133 ASSERT(owner()->parsed_function().saved_current_context_var() != NULL); | 2129 ASSERT(owner()->parsed_function()->saved_current_context_var() != NULL); |
| 2134 BuildLoadContext(*owner()->parsed_function().saved_current_context_var()); | 2130 BuildLoadContext(*owner()->parsed_function()->saved_current_context_var()); |
| 2135 } | 2131 } |
| 2136 | 2132 |
| 2137 | 2133 |
| 2138 void ValueGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { | 2134 void ValueGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { |
| 2139 Value* result = Bind(BuildClosureCall(node)); | 2135 Value* result = Bind(BuildClosureCall(node)); |
| 2140 // Restore context from temp. | 2136 // Restore context from temp. |
| 2141 ASSERT(owner()->parsed_function().saved_current_context_var() != NULL); | 2137 ASSERT(owner()->parsed_function()->saved_current_context_var() != NULL); |
| 2142 BuildLoadContext(*owner()->parsed_function().saved_current_context_var()); | 2138 BuildLoadContext(*owner()->parsed_function()->saved_current_context_var()); |
| 2143 ReturnValue(result); | 2139 ReturnValue(result); |
| 2144 } | 2140 } |
| 2145 | 2141 |
| 2146 | 2142 |
| 2147 void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) { | 2143 void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) { |
| 2148 InlineBailout("EffectGraphVisitor::VisitCloneContextNode (context)"); | 2144 InlineBailout("EffectGraphVisitor::VisitCloneContextNode (context)"); |
| 2149 Value* context = Bind(new CurrentContextInstr()); | 2145 Value* context = Bind(new CurrentContextInstr()); |
| 2150 Value* clone = Bind(new CloneContextInstr(node->token_pos(), context)); | 2146 Value* clone = Bind(new CloneContextInstr(node->token_pos(), context)); |
| 2151 AddInstruction(new StoreContextInstr(clone)); | 2147 AddInstruction(new StoreContextInstr(clone)); |
| 2152 } | 2148 } |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2297 // StaticCall(constructor, t_n+1, t_n+2, ...) | 2293 // StaticCall(constructor, t_n+1, t_n+2, ...) |
| 2298 // No need to preserve allocated value (simpler than in ValueGraphVisitor). | 2294 // No need to preserve allocated value (simpler than in ValueGraphVisitor). |
| 2299 Value* allocated_value = BuildObjectAllocation(node); | 2295 Value* allocated_value = BuildObjectAllocation(node); |
| 2300 PushArgumentInstr* push_allocated_value = PushArgument(allocated_value); | 2296 PushArgumentInstr* push_allocated_value = PushArgument(allocated_value); |
| 2301 BuildConstructorCall(node, push_allocated_value); | 2297 BuildConstructorCall(node, push_allocated_value); |
| 2302 } | 2298 } |
| 2303 | 2299 |
| 2304 | 2300 |
| 2305 Value* EffectGraphVisitor::BuildInstantiator() { | 2301 Value* EffectGraphVisitor::BuildInstantiator() { |
| 2306 const Class& instantiator_class = Class::Handle( | 2302 const Class& instantiator_class = Class::Handle( |
| 2307 owner()->parsed_function().function().Owner()); | 2303 owner()->parsed_function()->function().Owner()); |
| 2308 if (instantiator_class.NumTypeParameters() == 0) { | 2304 if (instantiator_class.NumTypeParameters() == 0) { |
| 2309 return NULL; | 2305 return NULL; |
| 2310 } | 2306 } |
| 2311 Function& outer_function = | 2307 Function& outer_function = |
| 2312 Function::Handle(owner()->parsed_function().function().raw()); | 2308 Function::Handle(owner()->parsed_function()->function().raw()); |
| 2313 while (outer_function.IsLocalFunction()) { | 2309 while (outer_function.IsLocalFunction()) { |
| 2314 outer_function = outer_function.parent_function(); | 2310 outer_function = outer_function.parent_function(); |
| 2315 } | 2311 } |
| 2316 if (outer_function.IsFactory()) { | 2312 if (outer_function.IsFactory()) { |
| 2317 return NULL; | 2313 return NULL; |
| 2318 } | 2314 } |
| 2319 | 2315 |
| 2320 ASSERT(owner()->parsed_function().instantiator() != NULL); | 2316 ASSERT(owner()->parsed_function()->instantiator() != NULL); |
| 2321 ValueGraphVisitor for_instantiator(owner(), temp_index()); | 2317 ValueGraphVisitor for_instantiator(owner(), temp_index()); |
| 2322 owner()->parsed_function().instantiator()->Visit(&for_instantiator); | 2318 owner()->parsed_function()->instantiator()->Visit(&for_instantiator); |
| 2323 Append(for_instantiator); | 2319 Append(for_instantiator); |
| 2324 return for_instantiator.value(); | 2320 return for_instantiator.value(); |
| 2325 } | 2321 } |
| 2326 | 2322 |
| 2327 | 2323 |
| 2328 // 'expression_temp_var' may not be used inside this method if 'instantiator' | 2324 // 'expression_temp_var' may not be used inside this method if 'instantiator' |
| 2329 // is not NULL. | 2325 // is not NULL. |
| 2330 Value* EffectGraphVisitor::BuildInstantiatorTypeArguments( | 2326 Value* EffectGraphVisitor::BuildInstantiatorTypeArguments( |
| 2331 intptr_t token_pos, | 2327 intptr_t token_pos, |
| 2332 const Class& instantiator_class, | 2328 const Class& instantiator_class, |
| 2333 Value* instantiator) { | 2329 Value* instantiator) { |
| 2334 if (instantiator_class.NumTypeParameters() == 0) { | 2330 if (instantiator_class.NumTypeParameters() == 0) { |
| 2335 // The type arguments are compile time constants. | 2331 // The type arguments are compile time constants. |
| 2336 AbstractTypeArguments& type_arguments = AbstractTypeArguments::ZoneHandle(); | 2332 AbstractTypeArguments& type_arguments = AbstractTypeArguments::ZoneHandle(); |
| 2337 // Type is temporary. Only its type arguments are preserved. | 2333 // Type is temporary. Only its type arguments are preserved. |
| 2338 Type& type = Type::Handle( | 2334 Type& type = Type::Handle( |
| 2339 Type::New(instantiator_class, type_arguments, token_pos, Heap::kNew)); | 2335 Type::New(instantiator_class, type_arguments, token_pos, Heap::kNew)); |
| 2340 type ^= ClassFinalizer::FinalizeType( | 2336 type ^= ClassFinalizer::FinalizeType( |
| 2341 instantiator_class, type, ClassFinalizer::kFinalize); | 2337 instantiator_class, type, ClassFinalizer::kFinalize); |
| 2342 ASSERT(!type.IsMalformed()); | 2338 ASSERT(!type.IsMalformed()); |
| 2343 type_arguments = type.arguments(); | 2339 type_arguments = type.arguments(); |
| 2344 type_arguments = type_arguments.Canonicalize(); | 2340 type_arguments = type_arguments.Canonicalize(); |
| 2345 return Bind(new ConstantInstr(type_arguments)); | 2341 return Bind(new ConstantInstr(type_arguments)); |
| 2346 } | 2342 } |
| 2347 Function& outer_function = | 2343 Function& outer_function = |
| 2348 Function::Handle(owner()->parsed_function().function().raw()); | 2344 Function::Handle(owner()->parsed_function()->function().raw()); |
| 2349 while (outer_function.IsLocalFunction()) { | 2345 while (outer_function.IsLocalFunction()) { |
| 2350 outer_function = outer_function.parent_function(); | 2346 outer_function = outer_function.parent_function(); |
| 2351 } | 2347 } |
| 2352 if (outer_function.IsFactory()) { | 2348 if (outer_function.IsFactory()) { |
| 2353 // No instantiator for factories. | 2349 // No instantiator for factories. |
| 2354 ASSERT(instantiator == NULL); | 2350 ASSERT(instantiator == NULL); |
| 2355 ASSERT(owner()->parsed_function().instantiator() != NULL); | 2351 ASSERT(owner()->parsed_function()->instantiator() != NULL); |
| 2356 ValueGraphVisitor for_instantiator(owner(), temp_index()); | 2352 ValueGraphVisitor for_instantiator(owner(), temp_index()); |
| 2357 owner()->parsed_function().instantiator()->Visit(&for_instantiator); | 2353 owner()->parsed_function()->instantiator()->Visit(&for_instantiator); |
| 2358 Append(for_instantiator); | 2354 Append(for_instantiator); |
| 2359 return for_instantiator.value(); | 2355 return for_instantiator.value(); |
| 2360 } | 2356 } |
| 2361 if (instantiator == NULL) { | 2357 if (instantiator == NULL) { |
| 2362 instantiator = BuildInstantiator(); | 2358 instantiator = BuildInstantiator(); |
| 2363 } | 2359 } |
| 2364 // The instantiator is the receiver of the caller, which is not a factory. | 2360 // The instantiator is the receiver of the caller, which is not a factory. |
| 2365 // The receiver cannot be null; extract its AbstractTypeArguments object. | 2361 // The receiver cannot be null; extract its AbstractTypeArguments object. |
| 2366 // Note that in the factory case, the instantiator is the first parameter | 2362 // Note that in the factory case, the instantiator is the first parameter |
| 2367 // of the factory, i.e. already an AbstractTypeArguments object. | 2363 // of the factory, i.e. already an AbstractTypeArguments object. |
| 2368 intptr_t type_arguments_field_offset = | 2364 intptr_t type_arguments_field_offset = |
| 2369 instantiator_class.type_arguments_field_offset(); | 2365 instantiator_class.type_arguments_field_offset(); |
| 2370 ASSERT(type_arguments_field_offset != Class::kNoTypeArguments); | 2366 ASSERT(type_arguments_field_offset != Class::kNoTypeArguments); |
| 2371 | 2367 |
| 2372 return Bind(new LoadFieldInstr( | 2368 return Bind(new LoadFieldInstr( |
| 2373 instantiator, | 2369 instantiator, |
| 2374 type_arguments_field_offset, | 2370 type_arguments_field_offset, |
| 2375 Type::ZoneHandle())); // Not an instance, no type. | 2371 Type::ZoneHandle())); // Not an instance, no type. |
| 2376 } | 2372 } |
| 2377 | 2373 |
| 2378 | 2374 |
| 2379 Value* EffectGraphVisitor::BuildInstantiatedTypeArguments( | 2375 Value* EffectGraphVisitor::BuildInstantiatedTypeArguments( |
| 2380 intptr_t token_pos, | 2376 intptr_t token_pos, |
| 2381 const AbstractTypeArguments& type_arguments) { | 2377 const AbstractTypeArguments& type_arguments) { |
| 2382 if (type_arguments.IsNull() || type_arguments.IsInstantiated()) { | 2378 if (type_arguments.IsNull() || type_arguments.IsInstantiated()) { |
| 2383 return Bind(new ConstantInstr(type_arguments)); | 2379 return Bind(new ConstantInstr(type_arguments)); |
| 2384 } | 2380 } |
| 2385 // The type arguments are uninstantiated. | 2381 // The type arguments are uninstantiated. |
| 2386 const Class& instantiator_class = Class::ZoneHandle( | 2382 const Class& instantiator_class = Class::ZoneHandle( |
| 2387 owner()->parsed_function().function().Owner()); | 2383 owner()->parsed_function()->function().Owner()); |
| 2388 Value* instantiator_value = | 2384 Value* instantiator_value = |
| 2389 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); | 2385 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); |
| 2390 const bool use_instantiator_type_args = | 2386 const bool use_instantiator_type_args = |
| 2391 type_arguments.IsUninstantiatedIdentity() || | 2387 type_arguments.IsUninstantiatedIdentity() || |
| 2392 type_arguments.CanShareInstantiatorTypeArguments( | 2388 type_arguments.CanShareInstantiatorTypeArguments( |
| 2393 instantiator_class); | 2389 instantiator_class); |
| 2394 return use_instantiator_type_args | 2390 return use_instantiator_type_args |
| 2395 ? instantiator_value | 2391 ? instantiator_value |
| 2396 : Bind(new InstantiateTypeArgumentsInstr(token_pos, | 2392 : Bind(new InstantiateTypeArgumentsInstr(token_pos, |
| 2397 type_arguments, | 2393 type_arguments, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2412 | 2408 |
| 2413 // No instantiator required. | 2409 // No instantiator required. |
| 2414 Value* instantiator_val = Bind(new ConstantInstr( | 2410 Value* instantiator_val = Bind(new ConstantInstr( |
| 2415 Smi::ZoneHandle(Smi::New(StubCode::kNoInstantiator)))); | 2411 Smi::ZoneHandle(Smi::New(StubCode::kNoInstantiator)))); |
| 2416 call_arguments->Add(PushArgument(instantiator_val)); | 2412 call_arguments->Add(PushArgument(instantiator_val)); |
| 2417 return; | 2413 return; |
| 2418 } | 2414 } |
| 2419 | 2415 |
| 2420 // The type arguments are uninstantiated. We use expression_temp_var to save | 2416 // The type arguments are uninstantiated. We use expression_temp_var to save |
| 2421 // the instantiator type arguments because they have two uses. | 2417 // the instantiator type arguments because they have two uses. |
| 2422 ASSERT(owner()->parsed_function().expression_temp_var() != NULL); | 2418 ASSERT(owner()->parsed_function()->expression_temp_var() != NULL); |
| 2423 const Class& instantiator_class = Class::Handle( | 2419 const Class& instantiator_class = Class::Handle( |
| 2424 owner()->parsed_function().function().Owner()); | 2420 owner()->parsed_function()->function().Owner()); |
| 2425 Value* type_arguments_val = BuildInstantiatorTypeArguments( | 2421 Value* type_arguments_val = BuildInstantiatorTypeArguments( |
| 2426 node->token_pos(), instantiator_class, NULL); | 2422 node->token_pos(), instantiator_class, NULL); |
| 2427 | 2423 |
| 2428 const bool use_instantiator_type_args = | 2424 const bool use_instantiator_type_args = |
| 2429 node->type_arguments().IsUninstantiatedIdentity() || | 2425 node->type_arguments().IsUninstantiatedIdentity() || |
| 2430 node->type_arguments().CanShareInstantiatorTypeArguments( | 2426 node->type_arguments().CanShareInstantiatorTypeArguments( |
| 2431 instantiator_class); | 2427 instantiator_class); |
| 2432 | 2428 |
| 2433 if (!use_instantiator_type_args) { | 2429 if (!use_instantiator_type_args) { |
| 2434 const intptr_t len = node->type_arguments().Length(); | 2430 const intptr_t len = node->type_arguments().Length(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2475 | 2471 |
| 2476 // t_n contains the allocated and initialized object. | 2472 // t_n contains the allocated and initialized object. |
| 2477 // t_n <- AllocateObject(class) | 2473 // t_n <- AllocateObject(class) |
| 2478 // t_n <- StoreLocal(temp, t_n); | 2474 // t_n <- StoreLocal(temp, t_n); |
| 2479 // t_n+1 <- ctor-arg | 2475 // t_n+1 <- ctor-arg |
| 2480 // t_n+2... <- constructor arguments start here | 2476 // t_n+2... <- constructor arguments start here |
| 2481 // StaticCall(constructor, t_n, t_n+1, ...) | 2477 // StaticCall(constructor, t_n, t_n+1, ...) |
| 2482 // tn <- LoadLocal(temp) | 2478 // tn <- LoadLocal(temp) |
| 2483 | 2479 |
| 2484 Value* allocate = BuildObjectAllocation(node); | 2480 Value* allocate = BuildObjectAllocation(node); |
| 2485 { TempLocalScope tmp(this, allocate); | 2481 { LocalVariable* tmp_var = EnterTempLocalScope(allocate); |
| 2486 Value* allocated_tmp = Bind(new LoadLocalInstr(*tmp.var())); | 2482 Value* allocated_tmp = Bind(new LoadLocalInstr(*tmp_var)); |
| 2487 PushArgumentInstr* push_allocated_value = PushArgument(allocated_tmp); | 2483 PushArgumentInstr* push_allocated_value = PushArgument(allocated_tmp); |
| 2488 BuildConstructorCall(node, push_allocated_value); | 2484 BuildConstructorCall(node, push_allocated_value); |
| 2485 ReturnDefinition(ExitTempLocalScope(tmp_var)); |
| 2489 } | 2486 } |
| 2490 } | 2487 } |
| 2491 | 2488 |
| 2492 | 2489 |
| 2493 void EffectGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) { | 2490 void EffectGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) { |
| 2494 ValueGraphVisitor for_receiver(owner(), temp_index()); | 2491 ValueGraphVisitor for_receiver(owner(), temp_index()); |
| 2495 node->receiver()->Visit(&for_receiver); | 2492 node->receiver()->Visit(&for_receiver); |
| 2496 Append(for_receiver); | 2493 Append(for_receiver); |
| 2497 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); | 2494 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); |
| 2498 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2495 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2575 new ZoneGrowableArray<PushArgumentInstr*>(); | 2572 new ZoneGrowableArray<PushArgumentInstr*>(); |
| 2576 Function& getter_function = Function::ZoneHandle(); | 2573 Function& getter_function = Function::ZoneHandle(); |
| 2577 if (node->is_super_getter()) { | 2574 if (node->is_super_getter()) { |
| 2578 // Statically resolved instance getter, i.e. "super getter". | 2575 // Statically resolved instance getter, i.e. "super getter". |
| 2579 ASSERT(node->receiver() != NULL); | 2576 ASSERT(node->receiver() != NULL); |
| 2580 getter_function = Resolver::ResolveDynamicAnyArgs(node->cls(), getter_name); | 2577 getter_function = Resolver::ResolveDynamicAnyArgs(node->cls(), getter_name); |
| 2581 if (getter_function.IsNull()) { | 2578 if (getter_function.IsNull()) { |
| 2582 // Resolve and call noSuchMethod. | 2579 // Resolve and call noSuchMethod. |
| 2583 ArgumentListNode* arguments = new ArgumentListNode(node->token_pos()); | 2580 ArgumentListNode* arguments = new ArgumentListNode(node->token_pos()); |
| 2584 arguments->Add(node->receiver()); | 2581 arguments->Add(node->receiver()); |
| 2585 StaticCallInstr* call = BuildStaticNoSuchMethodCall(node->cls(), | 2582 StaticCallInstr* call = |
| 2586 node->receiver(), | 2583 BuildStaticNoSuchMethodCall(node->cls(), |
| 2587 getter_name, | 2584 node->receiver(), |
| 2588 arguments); | 2585 getter_name, |
| 2586 arguments, |
| 2587 false); // Don't save last argument. |
| 2589 ReturnDefinition(call); | 2588 ReturnDefinition(call); |
| 2590 return; | 2589 return; |
| 2591 } else { | 2590 } else { |
| 2592 ValueGraphVisitor receiver_value(owner(), temp_index()); | 2591 ValueGraphVisitor receiver_value(owner(), temp_index()); |
| 2593 node->receiver()->Visit(&receiver_value); | 2592 node->receiver()->Visit(&receiver_value); |
| 2594 Append(receiver_value); | 2593 Append(receiver_value); |
| 2595 arguments->Add(PushArgument(receiver_value.value())); | 2594 arguments->Add(PushArgument(receiver_value.value())); |
| 2596 } | 2595 } |
| 2597 } else { | 2596 } else { |
| 2598 getter_function = node->cls().LookupStaticFunction(getter_name); | 2597 getter_function = node->cls().LookupStaticFunction(getter_name); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2649 ? Resolver::ResolveDynamicAnyArgs(node->cls(), setter_name) | 2648 ? Resolver::ResolveDynamicAnyArgs(node->cls(), setter_name) |
| 2650 : node->cls().LookupStaticFunction(setter_name)); | 2649 : node->cls().LookupStaticFunction(setter_name)); |
| 2651 StaticCallInstr* call; | 2650 StaticCallInstr* call; |
| 2652 if (setter_function.IsNull()) { | 2651 if (setter_function.IsNull()) { |
| 2653 if (is_super_setter) { | 2652 if (is_super_setter) { |
| 2654 ASSERT(node->receiver() != NULL); | 2653 ASSERT(node->receiver() != NULL); |
| 2655 // Resolve and call noSuchMethod. | 2654 // Resolve and call noSuchMethod. |
| 2656 ArgumentListNode* arguments = new ArgumentListNode(node->token_pos()); | 2655 ArgumentListNode* arguments = new ArgumentListNode(node->token_pos()); |
| 2657 arguments->Add(node->receiver()); | 2656 arguments->Add(node->receiver()); |
| 2658 arguments->Add(node->value()); | 2657 arguments->Add(node->value()); |
| 2659 call = BuildStaticNoSuchMethodCall(node->cls(), | 2658 call = BuildStaticNoSuchMethodCall( |
| 2660 node->receiver(), | 2659 node->cls(), |
| 2661 setter_name, | 2660 node->receiver(), |
| 2662 arguments); | 2661 setter_name, |
| 2662 arguments, |
| 2663 result_is_needed); // Save last arg if result is needed. |
| 2663 } else { | 2664 } else { |
| 2664 // Throw a NoSuchMethodError. | 2665 // Throw a NoSuchMethodError. |
| 2665 call = BuildThrowNoSuchMethodError( | 2666 call = BuildThrowNoSuchMethodError( |
| 2666 node->token_pos(), | 2667 node->token_pos(), |
| 2667 node->cls(), | 2668 node->cls(), |
| 2668 setter_name, | 2669 setter_name, |
| 2669 InvocationMirror::EncodeType( | 2670 InvocationMirror::EncodeType( |
| 2670 node->cls().IsTopLevel() ? | 2671 node->cls().IsTopLevel() ? |
| 2671 InvocationMirror::kTopLevel : | 2672 InvocationMirror::kTopLevel : |
| 2672 InvocationMirror::kStatic, | 2673 InvocationMirror::kStatic, |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2884 if (super_function->IsNull()) { | 2885 if (super_function->IsNull()) { |
| 2885 // Could not resolve super operator. Generate call noSuchMethod() of the | 2886 // Could not resolve super operator. Generate call noSuchMethod() of the |
| 2886 // super class instead. | 2887 // super class instead. |
| 2887 ArgumentListNode* arguments = new ArgumentListNode(node->token_pos()); | 2888 ArgumentListNode* arguments = new ArgumentListNode(node->token_pos()); |
| 2888 arguments->Add(node->array()); | 2889 arguments->Add(node->array()); |
| 2889 arguments->Add(node->index_expr()); | 2890 arguments->Add(node->index_expr()); |
| 2890 StaticCallInstr* call = | 2891 StaticCallInstr* call = |
| 2891 BuildStaticNoSuchMethodCall(node->super_class(), | 2892 BuildStaticNoSuchMethodCall(node->super_class(), |
| 2892 node->array(), | 2893 node->array(), |
| 2893 Symbols::IndexToken(), | 2894 Symbols::IndexToken(), |
| 2894 arguments); | 2895 arguments, |
| 2896 false); // Don't save last arg. |
| 2895 ReturnDefinition(call); | 2897 ReturnDefinition(call); |
| 2896 return; | 2898 return; |
| 2897 } | 2899 } |
| 2898 } | 2900 } |
| 2899 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2901 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 2900 new ZoneGrowableArray<PushArgumentInstr*>(2); | 2902 new ZoneGrowableArray<PushArgumentInstr*>(2); |
| 2901 ValueGraphVisitor for_array(owner(), temp_index()); | 2903 ValueGraphVisitor for_array(owner(), temp_index()); |
| 2902 node->array()->Visit(&for_array); | 2904 node->array()->Visit(&for_array); |
| 2903 Append(for_array); | 2905 Append(for_array); |
| 2904 arguments->Add(PushArgument(for_array.value())); | 2906 arguments->Add(PushArgument(for_array.value())); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2938 // Resolve the store indexed operator in the super class. | 2940 // Resolve the store indexed operator in the super class. |
| 2939 super_function = &Function::ZoneHandle( | 2941 super_function = &Function::ZoneHandle( |
| 2940 Resolver::ResolveDynamicAnyArgs(node->super_class(), | 2942 Resolver::ResolveDynamicAnyArgs(node->super_class(), |
| 2941 Symbols::AssignIndexToken())); | 2943 Symbols::AssignIndexToken())); |
| 2942 if (super_function->IsNull()) { | 2944 if (super_function->IsNull()) { |
| 2943 // Could not resolve super operator. Generate call noSuchMethod() of the | 2945 // Could not resolve super operator. Generate call noSuchMethod() of the |
| 2944 // super class instead. | 2946 // super class instead. |
| 2945 ArgumentListNode* arguments = new ArgumentListNode(node->token_pos()); | 2947 ArgumentListNode* arguments = new ArgumentListNode(node->token_pos()); |
| 2946 arguments->Add(node->array()); | 2948 arguments->Add(node->array()); |
| 2947 arguments->Add(node->index_expr()); | 2949 arguments->Add(node->index_expr()); |
| 2948 | 2950 arguments->Add(node->value()); |
| 2949 // Even though noSuchMethod most likely does not return, | 2951 StaticCallInstr* call = BuildStaticNoSuchMethodCall( |
| 2950 // we save the stored value if the result is needed. | 2952 node->super_class(), |
| 2951 if (result_is_needed) { | 2953 node->array(), |
| 2952 ValueGraphVisitor for_value(owner(), temp_index()); | 2954 Symbols::AssignIndexToken(), |
| 2953 node->value()->Visit(&for_value); | 2955 arguments, |
| 2954 Append(for_value); | 2956 result_is_needed); // Save last arg if result is needed. |
| 2955 Do(BuildStoreExprTemp(for_value.value())); | |
| 2956 | |
| 2957 const LocalVariable* temp = | |
| 2958 owner()->parsed_function().expression_temp_var(); | |
| 2959 AstNode* value = new LoadLocalNode(node->token_pos(), temp); | |
| 2960 arguments->Add(value); | |
| 2961 } else { | |
| 2962 arguments->Add(node->value()); | |
| 2963 } | |
| 2964 StaticCallInstr* call = | |
| 2965 BuildStaticNoSuchMethodCall(node->super_class(), | |
| 2966 node->array(), | |
| 2967 Symbols::AssignIndexToken(), | |
| 2968 arguments); | |
| 2969 if (result_is_needed) { | 2957 if (result_is_needed) { |
| 2970 Do(call); | 2958 Do(call); |
| 2959 // BuildStaticNoSuchMethodCall stores the value in expression_temp. |
| 2971 return BuildLoadExprTemp(); | 2960 return BuildLoadExprTemp(); |
| 2972 } else { | 2961 } else { |
| 2973 return call; | 2962 return call; |
| 2974 } | 2963 } |
| 2975 } | 2964 } |
| 2976 } | 2965 } |
| 2977 | 2966 |
| 2978 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2967 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 2979 new ZoneGrowableArray<PushArgumentInstr*>(3); | 2968 new ZoneGrowableArray<PushArgumentInstr*>(3); |
| 2980 ValueGraphVisitor for_array(owner(), temp_index()); | 2969 ValueGraphVisitor for_array(owner(), temp_index()); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3039 ReturnDefinition(BuildStoreIndexedValues(node, kResultNotNeeded)); | 3028 ReturnDefinition(BuildStoreIndexedValues(node, kResultNotNeeded)); |
| 3040 } | 3029 } |
| 3041 | 3030 |
| 3042 | 3031 |
| 3043 void ValueGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) { | 3032 void ValueGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) { |
| 3044 ReturnDefinition(BuildStoreIndexedValues(node, kResultNeeded)); | 3033 ReturnDefinition(BuildStoreIndexedValues(node, kResultNeeded)); |
| 3045 } | 3034 } |
| 3046 | 3035 |
| 3047 | 3036 |
| 3048 bool EffectGraphVisitor::MustSaveRestoreContext(SequenceNode* node) const { | 3037 bool EffectGraphVisitor::MustSaveRestoreContext(SequenceNode* node) const { |
| 3049 return (node == owner()->parsed_function().node_sequence()) && | 3038 return (node == owner()->parsed_function()->node_sequence()) && |
| 3050 (owner()->parsed_function().saved_entry_context_var() != NULL); | 3039 (owner()->parsed_function()->saved_entry_context_var() != NULL); |
| 3051 } | 3040 } |
| 3052 | 3041 |
| 3053 | 3042 |
| 3054 void EffectGraphVisitor::UnchainContext() { | 3043 void EffectGraphVisitor::UnchainContext() { |
| 3055 InlineBailout("EffectGraphVisitor::UnchainContext (context)"); | 3044 InlineBailout("EffectGraphVisitor::UnchainContext (context)"); |
| 3056 Value* context = Bind(new CurrentContextInstr()); | 3045 Value* context = Bind(new CurrentContextInstr()); |
| 3057 Value* parent = Bind( | 3046 Value* parent = Bind( |
| 3058 new LoadFieldInstr(context, | 3047 new LoadFieldInstr(context, |
| 3059 Context::parent_offset(), | 3048 Context::parent_offset(), |
| 3060 Type::ZoneHandle())); // Not an instance, no type. | 3049 Type::ZoneHandle())); // Not an instance, no type. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3080 num_context_variables)); | 3069 num_context_variables)); |
| 3081 | 3070 |
| 3082 // If this node_sequence is the body of the function being compiled, and if | 3071 // If this node_sequence is the body of the function being compiled, and if |
| 3083 // this function allocates context variables, but none of its enclosing | 3072 // this function allocates context variables, but none of its enclosing |
| 3084 // functions do, the context on entry is not linked as parent of the | 3073 // functions do, the context on entry is not linked as parent of the |
| 3085 // allocated context but saved on entry and restored on exit as to prevent | 3074 // allocated context but saved on entry and restored on exit as to prevent |
| 3086 // memory leaks. | 3075 // memory leaks. |
| 3087 // In this case, the parser pre-allocates a variable to save the context. | 3076 // In this case, the parser pre-allocates a variable to save the context. |
| 3088 if (MustSaveRestoreContext(node)) { | 3077 if (MustSaveRestoreContext(node)) { |
| 3089 Value* current_context = Bind(new CurrentContextInstr()); | 3078 Value* current_context = Bind(new CurrentContextInstr()); |
| 3090 Do(BuildStoreTemp(*owner()->parsed_function().saved_entry_context_var(), | 3079 Do(BuildStoreTemp(*owner()->parsed_function()->saved_entry_context_var(), |
| 3091 current_context)); | 3080 current_context)); |
| 3092 Value* null_context = Bind(new ConstantInstr(Object::ZoneHandle())); | 3081 Value* null_context = Bind(new ConstantInstr(Object::ZoneHandle())); |
| 3093 AddInstruction(new StoreContextInstr(null_context)); | 3082 AddInstruction(new StoreContextInstr(null_context)); |
| 3094 } | 3083 } |
| 3095 | 3084 |
| 3096 AddInstruction(new ChainContextInstr(allocated_context)); | 3085 AddInstruction(new ChainContextInstr(allocated_context)); |
| 3097 owner()->set_context_level(scope->context_level()); | 3086 owner()->set_context_level(scope->context_level()); |
| 3098 | 3087 |
| 3099 // If this node_sequence is the body of the function being compiled, copy | 3088 // If this node_sequence is the body of the function being compiled, copy |
| 3100 // the captured parameters from the frame into the context. | 3089 // the captured parameters from the frame into the context. |
| 3101 if (node == owner()->parsed_function().node_sequence()) { | 3090 if (node == owner()->parsed_function()->node_sequence()) { |
| 3102 ASSERT(scope->context_level() == 1); | 3091 ASSERT(scope->context_level() == 1); |
| 3103 const Function& function = owner()->parsed_function().function(); | 3092 const Function& function = owner()->parsed_function()->function(); |
| 3104 int num_params = function.NumParameters(); | 3093 int num_params = function.NumParameters(); |
| 3105 int param_frame_index = (num_params == function.num_fixed_parameters()) ? | 3094 int param_frame_index = (num_params == function.num_fixed_parameters()) ? |
| 3106 (kParamEndSlotFromFp + num_params) : kFirstLocalSlotFromFp; | 3095 (kParamEndSlotFromFp + num_params) : kFirstLocalSlotFromFp; |
| 3107 // Handle the saved arguments descriptor as an additional parameter. | 3096 // Handle the saved arguments descriptor as an additional parameter. |
| 3108 if (owner()->parsed_function().GetSavedArgumentsDescriptorVar() != NULL) { | 3097 if (owner()->parsed_function()->GetSavedArgumentsDescriptorVar() != |
| 3098 NULL) { |
| 3109 ASSERT(param_frame_index == kFirstLocalSlotFromFp); | 3099 ASSERT(param_frame_index == kFirstLocalSlotFromFp); |
| 3110 num_params++; | 3100 num_params++; |
| 3111 } | 3101 } |
| 3112 for (int pos = 0; pos < num_params; param_frame_index--, pos++) { | 3102 for (int pos = 0; pos < num_params; param_frame_index--, pos++) { |
| 3113 const LocalVariable& parameter = *scope->VariableAt(pos); | 3103 const LocalVariable& parameter = *scope->VariableAt(pos); |
| 3114 ASSERT(parameter.owner() == scope); | 3104 ASSERT(parameter.owner() == scope); |
| 3115 if (parameter.is_captured()) { | 3105 if (parameter.is_captured()) { |
| 3116 // Create a temporary local describing the original position. | 3106 // Create a temporary local describing the original position. |
| 3117 const String& temp_name = String::ZoneHandle(String::Concat( | 3107 const String& temp_name = String::ZoneHandle(String::Concat( |
| 3118 parameter.name(), String::Handle(Symbols::New("-orig")))); | 3108 parameter.name(), String::Handle(Symbols::New("-orig")))); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3130 // the function. | 3120 // the function. |
| 3131 Value* null_constant = | 3121 Value* null_constant = |
| 3132 Bind(new ConstantInstr(Object::ZoneHandle())); | 3122 Bind(new ConstantInstr(Object::ZoneHandle())); |
| 3133 Do(BuildStoreLocal(*temp_local, null_constant, kResultNotNeeded)); | 3123 Do(BuildStoreLocal(*temp_local, null_constant, kResultNotNeeded)); |
| 3134 } | 3124 } |
| 3135 } | 3125 } |
| 3136 } | 3126 } |
| 3137 } | 3127 } |
| 3138 | 3128 |
| 3139 if (FLAG_enable_type_checks && | 3129 if (FLAG_enable_type_checks && |
| 3140 (node == owner()->parsed_function().node_sequence())) { | 3130 (node == owner()->parsed_function()->node_sequence())) { |
| 3141 const Function& function = owner()->parsed_function().function(); | 3131 const Function& function = owner()->parsed_function()->function(); |
| 3142 const int num_params = function.NumParameters(); | 3132 const int num_params = function.NumParameters(); |
| 3143 int pos = 0; | 3133 int pos = 0; |
| 3144 if (function.IsConstructor()) { | 3134 if (function.IsConstructor()) { |
| 3145 // Skip type checking of receiver and phase for constructor functions. | 3135 // Skip type checking of receiver and phase for constructor functions. |
| 3146 pos = 2; | 3136 pos = 2; |
| 3147 } else if (function.IsFactory() || function.IsDynamicFunction()) { | 3137 } else if (function.IsFactory() || function.IsDynamicFunction()) { |
| 3148 // Skip type checking of type arguments for factory functions. | 3138 // Skip type checking of type arguments for factory functions. |
| 3149 // Skip type checking of receiver for instance functions. | 3139 // Skip type checking of receiver for instance functions. |
| 3150 pos = 1; | 3140 pos = 1; |
| 3151 } | 3141 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3179 Append(for_effect); | 3169 Append(for_effect); |
| 3180 if (!is_open()) { | 3170 if (!is_open()) { |
| 3181 // E.g., because of a JumpNode. | 3171 // E.g., because of a JumpNode. |
| 3182 break; | 3172 break; |
| 3183 } | 3173 } |
| 3184 } | 3174 } |
| 3185 | 3175 |
| 3186 if (is_open()) { | 3176 if (is_open()) { |
| 3187 if (MustSaveRestoreContext(node)) { | 3177 if (MustSaveRestoreContext(node)) { |
| 3188 ASSERT(num_context_variables > 0); | 3178 ASSERT(num_context_variables > 0); |
| 3189 BuildLoadContext(*owner()->parsed_function().saved_entry_context_var()); | 3179 BuildLoadContext(*owner()->parsed_function()->saved_entry_context_var()); |
| 3190 } else if (num_context_variables > 0) { | 3180 } else if (num_context_variables > 0) { |
| 3191 UnchainContext(); | 3181 UnchainContext(); |
| 3192 } | 3182 } |
| 3193 } | 3183 } |
| 3194 | 3184 |
| 3195 // No continue on sequence allowed. | 3185 // No continue on sequence allowed. |
| 3196 ASSERT((node->label() == NULL) || | 3186 ASSERT((node->label() == NULL) || |
| 3197 (node->label()->join_for_continue() == NULL)); | 3187 (node->label()->join_for_continue() == NULL)); |
| 3198 // If this node sequence is labeled, a break out of the sequence will have | 3188 // If this node sequence is labeled, a break out of the sequence will have |
| 3199 // taken care of unchaining the context. | 3189 // taken care of unchaining the context. |
| 3200 if ((node->label() != NULL) && | 3190 if ((node->label() != NULL) && |
| 3201 (node->label()->join_for_break() != NULL)) { | 3191 (node->label()->join_for_break() != NULL)) { |
| 3202 if (is_open()) Goto(node->label()->join_for_break()); | 3192 if (is_open()) Goto(node->label()->join_for_break()); |
| 3203 exit_ = node->label()->join_for_break(); | 3193 exit_ = node->label()->join_for_break(); |
| 3204 } | 3194 } |
| 3205 | 3195 |
| 3206 // The outermost function sequence cannot contain a label. | 3196 // The outermost function sequence cannot contain a label. |
| 3207 ASSERT((node->label() == NULL) || | 3197 ASSERT((node->label() == NULL) || |
| 3208 (node != owner()->parsed_function().node_sequence())); | 3198 (node != owner()->parsed_function()->node_sequence())); |
| 3209 owner()->set_context_level(previous_context_level); | 3199 owner()->set_context_level(previous_context_level); |
| 3210 } | 3200 } |
| 3211 | 3201 |
| 3212 | 3202 |
| 3213 void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) { | 3203 void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) { |
| 3214 InlineBailout("EffectGraphVisitor::VisitCatchClauseNode (exception)"); | 3204 InlineBailout("EffectGraphVisitor::VisitCatchClauseNode (exception)"); |
| 3215 // NOTE: The implicit variables ':saved_context', ':exception_var' | 3205 // NOTE: The implicit variables ':saved_context', ':exception_var' |
| 3216 // and ':stacktrace_var' can never be captured variables. | 3206 // and ':stacktrace_var' can never be captured variables. |
| 3217 // Restores CTX from local variable ':saved_context'. | 3207 // Restores CTX from local variable ':saved_context'. |
| 3218 AddInstruction( | 3208 AddInstruction( |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3310 } | 3300 } |
| 3311 } | 3301 } |
| 3312 | 3302 |
| 3313 | 3303 |
| 3314 // Looks up dynamic method noSuchMethod in target_class | 3304 // Looks up dynamic method noSuchMethod in target_class |
| 3315 // (including its super class chain) and builds a static call to it. | 3305 // (including its super class chain) and builds a static call to it. |
| 3316 StaticCallInstr* EffectGraphVisitor::BuildStaticNoSuchMethodCall( | 3306 StaticCallInstr* EffectGraphVisitor::BuildStaticNoSuchMethodCall( |
| 3317 const Class& target_class, | 3307 const Class& target_class, |
| 3318 AstNode* receiver, | 3308 AstNode* receiver, |
| 3319 const String& method_name, | 3309 const String& method_name, |
| 3320 ArgumentListNode* method_arguments) { | 3310 ArgumentListNode* method_arguments, |
| 3321 // Build the graph to allocate an InvocationMirror object by calling | 3311 bool save_last_arg) { |
| 3322 // the static allocation method. | 3312 intptr_t args_pos = method_arguments->token_pos(); |
| 3323 const Library& corelib = Library::Handle(Library::CoreLibrary()); | 3313 LocalVariable* temp = NULL; |
| 3324 const Class& mirror_class = Class::Handle( | 3314 if (save_last_arg) { |
| 3325 corelib.LookupClassAllowPrivate(Symbols::InvocationMirror())); | 3315 temp = owner()->parsed_function()->EnsureExpressionTemp(); |
| 3326 ASSERT(!mirror_class.IsNull()); | |
| 3327 const Function& allocation_function = Function::ZoneHandle( | |
| 3328 Resolver::ResolveStaticByName( | |
| 3329 mirror_class, | |
| 3330 PrivateCoreLibName(Symbols::AllocateInvocationMirror()), | |
| 3331 Resolver::kIsQualified)); | |
| 3332 ASSERT(!allocation_function.IsNull()); | |
| 3333 | |
| 3334 // Evaluate the receiver before the arguments. This will be used | |
| 3335 // as an argument to the noSuchMethod call. | |
| 3336 ValueGraphVisitor for_receiver(owner(), temp_index()); | |
| 3337 receiver->Visit(&for_receiver); | |
| 3338 Append(for_receiver); | |
| 3339 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); | |
| 3340 | |
| 3341 // Allocate the arguments and pass them into the construction | |
| 3342 // of the InvocationMirror. | |
| 3343 const intptr_t args_pos = method_arguments->token_pos(); | |
| 3344 ArgumentListNode* arguments = new ArgumentListNode(args_pos); | |
| 3345 // The first argument is the original method name. | |
| 3346 arguments->Add(new LiteralNode(args_pos, method_name)); | |
| 3347 // The second argument is the arguments descriptor of the original method. | |
| 3348 const Array& args_descriptor = | |
| 3349 Array::ZoneHandle(ArgumentsDescriptor::New(method_arguments->length(), | |
| 3350 method_arguments->names())); | |
| 3351 arguments->Add(new LiteralNode(args_pos, args_descriptor)); | |
| 3352 // The third argument is an array containing the original method arguments, | |
| 3353 // including the receiver. | |
| 3354 ArrayNode* args_array = new ArrayNode( | |
| 3355 args_pos, | |
| 3356 Type::ZoneHandle(Type::ArrayType())); | |
| 3357 for (intptr_t i = 0; i < method_arguments->length(); i++) { | |
| 3358 args_array->AddElement(method_arguments->NodeAt(i)); | |
| 3359 } | 3316 } |
| 3360 arguments->Add(args_array); | 3317 ArgumentListNode* args = |
| 3361 ZoneGrowableArray<PushArgumentInstr*>* allocation_args = | 3318 Parser::BuildNoSuchMethodArguments(args_pos, |
| 3362 new ZoneGrowableArray<PushArgumentInstr*>(arguments->length()); | 3319 method_name, |
| 3363 BuildPushArguments(*arguments, allocation_args); | 3320 *method_arguments, |
| 3364 StaticCallInstr* allocation = new StaticCallInstr(args_pos, | 3321 temp); |
| 3365 allocation_function, | |
| 3366 Array::ZoneHandle(), | |
| 3367 allocation_args); | |
| 3368 Value* invocation_mirror = Bind(allocation); | |
| 3369 PushArgumentInstr* push_invocation_mirror = PushArgument(invocation_mirror); | |
| 3370 // Lookup noSuchMethod and call it with the receiver and the InvocationMirror. | |
| 3371 const Function& no_such_method_func = Function::ZoneHandle( | 3322 const Function& no_such_method_func = Function::ZoneHandle( |
| 3372 Resolver::ResolveDynamicAnyArgs(target_class, Symbols::NoSuchMethod())); | 3323 Resolver::ResolveDynamicAnyArgs(target_class, Symbols::NoSuchMethod())); |
| 3373 // We are guaranteed to find noSuchMethod of class Object. | 3324 // We are guaranteed to find noSuchMethod of class Object. |
| 3374 ASSERT(!no_such_method_func.IsNull()); | 3325 ASSERT(!no_such_method_func.IsNull()); |
| 3375 ZoneGrowableArray<PushArgumentInstr*>* args = | 3326 ZoneGrowableArray<PushArgumentInstr*>* push_arguments = |
| 3376 new ZoneGrowableArray<PushArgumentInstr*>(2); | 3327 new ZoneGrowableArray<PushArgumentInstr*>(2); |
| 3377 args->Add(push_receiver); | 3328 BuildPushArguments(*args, push_arguments); |
| 3378 args->Add(push_invocation_mirror); | |
| 3379 return new StaticCallInstr(args_pos, | 3329 return new StaticCallInstr(args_pos, |
| 3380 no_such_method_func, | 3330 no_such_method_func, |
| 3381 Array::ZoneHandle(), | 3331 Array::ZoneHandle(), |
| 3382 args); | 3332 push_arguments); |
| 3383 } | 3333 } |
| 3384 | |
| 3385 | |
| 3386 StaticCallInstr* EffectGraphVisitor::BuildThrowNoSuchMethodError( | 3334 StaticCallInstr* EffectGraphVisitor::BuildThrowNoSuchMethodError( |
| 3387 intptr_t token_pos, | 3335 intptr_t token_pos, |
| 3388 const Class& function_class, | 3336 const Class& function_class, |
| 3389 const String& function_name, | 3337 const String& function_name, |
| 3390 int invocation_type) { | 3338 int invocation_type) { |
| 3391 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 3339 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| 3392 new ZoneGrowableArray<PushArgumentInstr*>(); | 3340 new ZoneGrowableArray<PushArgumentInstr*>(); |
| 3393 // Object receiver. | 3341 // Object receiver. |
| 3394 // TODO(regis): For now, we pass a class literal of the unresolved | 3342 // TODO(regis): For now, we pass a class literal of the unresolved |
| 3395 // method's owner, but this is not specified and will probably change. | 3343 // method's owner, but this is not specified and will probably change. |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3504 | 3452 |
| 3505 Goto(finally_entry); | 3453 Goto(finally_entry); |
| 3506 AppendFragment(finally_entry, for_finally_block); | 3454 AppendFragment(finally_entry, for_finally_block); |
| 3507 exit_ = for_finally_block.exit_; | 3455 exit_ = for_finally_block.exit_; |
| 3508 } | 3456 } |
| 3509 | 3457 |
| 3510 | 3458 |
| 3511 FlowGraph* FlowGraphBuilder::BuildGraph() { | 3459 FlowGraph* FlowGraphBuilder::BuildGraph() { |
| 3512 if (FLAG_print_ast) { | 3460 if (FLAG_print_ast) { |
| 3513 // Print the function ast before IL generation. | 3461 // Print the function ast before IL generation. |
| 3514 AstPrinter::PrintFunctionNodes(parsed_function()); | 3462 AstPrinter::PrintFunctionNodes(*parsed_function()); |
| 3515 } | 3463 } |
| 3516 // Compilation can be nested, preserve the computation-id. | 3464 // Compilation can be nested, preserve the computation-id. |
| 3517 const Function& function = parsed_function().function(); | 3465 const Function& function = parsed_function()->function(); |
| 3518 TargetEntryInstr* normal_entry = | 3466 TargetEntryInstr* normal_entry = |
| 3519 new TargetEntryInstr(AllocateBlockId(), | 3467 new TargetEntryInstr(AllocateBlockId(), |
| 3520 CatchClauseNode::kInvalidTryIndex); | 3468 CatchClauseNode::kInvalidTryIndex); |
| 3521 graph_entry_ = new GraphEntryInstr(parsed_function(), normal_entry); | 3469 graph_entry_ = new GraphEntryInstr(*parsed_function(), normal_entry); |
| 3522 EffectGraphVisitor for_effect(this, 0); | 3470 EffectGraphVisitor for_effect(this, 0); |
| 3523 // This check may be deleted if the generated code is leaf. | 3471 // This check may be deleted if the generated code is leaf. |
| 3524 CheckStackOverflowInstr* check = | 3472 CheckStackOverflowInstr* check = |
| 3525 new CheckStackOverflowInstr(function.token_pos()); | 3473 new CheckStackOverflowInstr(function.token_pos()); |
| 3526 // If we are inlining don't actually attach the stack check. We must still | 3474 // If we are inlining don't actually attach the stack check. We must still |
| 3527 // create the stack check in order to allocate a deopt id. | 3475 // create the stack check in order to allocate a deopt id. |
| 3528 if (!IsInlining()) for_effect.AddInstruction(check); | 3476 if (!IsInlining()) for_effect.AddInstruction(check); |
| 3529 parsed_function().node_sequence()->Visit(&for_effect); | 3477 parsed_function()->node_sequence()->Visit(&for_effect); |
| 3530 AppendFragment(normal_entry, for_effect); | 3478 AppendFragment(normal_entry, for_effect); |
| 3531 // Check that the graph is properly terminated. | 3479 // Check that the graph is properly terminated. |
| 3532 ASSERT(!for_effect.is_open()); | 3480 ASSERT(!for_effect.is_open()); |
| 3533 FlowGraph* graph = new FlowGraph(*this, graph_entry_, last_used_block_id_); | 3481 FlowGraph* graph = new FlowGraph(*this, graph_entry_, last_used_block_id_); |
| 3534 return graph; | 3482 return graph; |
| 3535 } | 3483 } |
| 3536 | 3484 |
| 3537 | 3485 |
| 3538 void FlowGraphBuilder::Bailout(const char* reason) { | 3486 void FlowGraphBuilder::Bailout(const char* reason) { |
| 3539 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; | 3487 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; |
| 3540 const char* function_name = parsed_function_.function().ToCString(); | 3488 const char* function_name = parsed_function_->function().ToCString(); |
| 3541 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 3489 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 3542 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 3490 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
| 3543 OS::SNPrint(chars, len, kFormat, function_name, reason); | 3491 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 3544 const Error& error = Error::Handle( | 3492 const Error& error = Error::Handle( |
| 3545 LanguageError::New(String::Handle(String::New(chars)))); | 3493 LanguageError::New(String::Handle(String::New(chars)))); |
| 3546 Isolate::Current()->long_jump_base()->Jump(1, error); | 3494 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 3547 } | 3495 } |
| 3548 | 3496 |
| 3549 | 3497 |
| 3550 } // namespace dart | 3498 } // namespace dart |
| OLD | NEW |