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 2689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2700 } | 2700 } |
2701 | 2701 |
2702 | 2702 |
2703 // Looks up dynamic method noSuchMethod in target_class | 2703 // Looks up dynamic method noSuchMethod in target_class |
2704 // (including its super class chain) and builds a static call to it. | 2704 // (including its super class chain) and builds a static call to it. |
2705 StaticCallInstr* EffectGraphVisitor::BuildStaticNoSuchMethodCall( | 2705 StaticCallInstr* EffectGraphVisitor::BuildStaticNoSuchMethodCall( |
2706 const Class& target_class, | 2706 const Class& target_class, |
2707 AstNode* receiver, | 2707 AstNode* receiver, |
2708 const String& method_name, | 2708 const String& method_name, |
2709 ArgumentListNode* method_arguments) { | 2709 ArgumentListNode* method_arguments) { |
| 2710 // Build the graph to allocate an InvocationMirror object by calling |
| 2711 // the static allocation method. |
| 2712 const String& mirror_name = String::Handle(Symbols::InvocationMirror()); |
| 2713 const Library& corelib = Library::Handle(Library::CoreLibrary()); |
| 2714 const Class& mirror_class = Class::Handle( |
| 2715 corelib.LookupClassAllowPrivate(mirror_name)); |
| 2716 ASSERT(!mirror_class.IsNull()); |
| 2717 const String& function_name = String::Handle( |
| 2718 Symbols::AllocateInvocationMirror()); |
| 2719 const Function& allocation_function = Function::ZoneHandle( |
| 2720 Resolver::ResolveStaticByName(mirror_class, |
| 2721 function_name, |
| 2722 Resolver::kIsQualified)); |
| 2723 ASSERT(!allocation_function.IsNull()); |
| 2724 |
| 2725 // Evaluate the receiver before the arguments. This will be used |
| 2726 // as an argument to the noSuchMethod call. |
| 2727 ValueGraphVisitor for_receiver(owner(), temp_index()); |
| 2728 receiver->Visit(&for_receiver); |
| 2729 Append(for_receiver); |
| 2730 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); |
| 2731 |
| 2732 // Allocate the arguments and pass them into the construction |
| 2733 // of the InvocationMirror. |
| 2734 const intptr_t args_pos = method_arguments->token_pos(); |
| 2735 ArgumentListNode* arguments = new ArgumentListNode(args_pos); |
| 2736 // The first argument is the original method name. |
| 2737 arguments->Add(new LiteralNode(args_pos, method_name)); |
| 2738 // The second argument is an array containing the original method arguments. |
| 2739 ArrayNode* args_array = |
| 2740 new ArrayNode(args_pos, Type::ZoneHandle(Type::ListInterface())); |
| 2741 for (intptr_t i = 0; i < method_arguments->length(); i++) { |
| 2742 args_array->AddElement(method_arguments->NodeAt(i)); |
| 2743 } |
| 2744 arguments->Add(args_array); |
| 2745 ZoneGrowableArray<PushArgumentInstr*>* allocation_args = |
| 2746 new ZoneGrowableArray<PushArgumentInstr*>(arguments->length()); |
| 2747 BuildPushArguments(*arguments, allocation_args); |
| 2748 StaticCallInstr* allocation = new StaticCallInstr(args_pos, |
| 2749 allocation_function, |
| 2750 Array::ZoneHandle(), |
| 2751 allocation_args); |
| 2752 Value* invocation_mirror = Bind(allocation); |
| 2753 PushArgumentInstr* push_invocation_mirror = PushArgument(invocation_mirror); |
| 2754 // Lookup noSuchMethod and call it with the receiver and the InvocationMirror. |
2710 const String& no_such_method_name = | 2755 const String& no_such_method_name = |
2711 String::ZoneHandle(Symbols::NoSuchMethod()); | 2756 String::ZoneHandle(Symbols::NoSuchMethod()); |
2712 const Function& no_such_method_func = Function::ZoneHandle( | 2757 const Function& no_such_method_func = Function::ZoneHandle( |
2713 Resolver::ResolveDynamicAnyArgs(target_class, no_such_method_name)); | 2758 Resolver::ResolveDynamicAnyArgs(target_class, no_such_method_name)); |
2714 // We are guaranteed to find noSuchMethod of class Object. | 2759 // We are guaranteed to find noSuchMethod of class Object. |
2715 ASSERT(!no_such_method_func.IsNull()); | 2760 ASSERT(!no_such_method_func.IsNull()); |
2716 | |
2717 const intptr_t args_pos = method_arguments->token_pos(); | |
2718 ArgumentListNode* arguments = new ArgumentListNode(args_pos); | |
2719 // The first argument is the receiver. | |
2720 arguments->Add(receiver); | |
2721 // The second argument is the original method name. | |
2722 // TODO(regis): This will change once mirrors are supported. | |
2723 arguments->Add(new LiteralNode(args_pos, method_name)); | |
2724 // The third argument is an array containing the original method arguments. | |
2725 ArrayNode* args_array = | |
2726 new ArrayNode(args_pos, Type::ZoneHandle(Type::ListInterface())); | |
2727 for (intptr_t i = 0; i < method_arguments->length(); i++) { | |
2728 args_array->AddElement(method_arguments->NodeAt(i)); | |
2729 } | |
2730 arguments->Add(args_array); | |
2731 | |
2732 ZoneGrowableArray<PushArgumentInstr*>* args = | 2761 ZoneGrowableArray<PushArgumentInstr*>* args = |
2733 new ZoneGrowableArray<PushArgumentInstr*>(arguments->length()); | 2762 new ZoneGrowableArray<PushArgumentInstr*>(2); |
2734 BuildPushArguments(*arguments, args); | 2763 args->Add(push_receiver); |
| 2764 args->Add(push_invocation_mirror); |
2735 return new StaticCallInstr(args_pos, | 2765 return new StaticCallInstr(args_pos, |
2736 no_such_method_func, | 2766 no_such_method_func, |
2737 Array::ZoneHandle(), | 2767 Array::ZoneHandle(), |
2738 args); | 2768 args); |
2739 } | 2769 } |
2740 | 2770 |
2741 | 2771 |
2742 void EffectGraphVisitor::BuildThrowNode(ThrowNode* node) { | 2772 void EffectGraphVisitor::BuildThrowNode(ThrowNode* node) { |
2743 // TODO(kmillikin) non-local control flow is not handled correctly | 2773 // TODO(kmillikin) non-local control flow is not handled correctly |
2744 // by the inliner. | 2774 // by the inliner. |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2850 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 2880 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
2851 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 2881 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
2852 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2882 OS::SNPrint(chars, len, kFormat, function_name, reason); |
2853 const Error& error = Error::Handle( | 2883 const Error& error = Error::Handle( |
2854 LanguageError::New(String::Handle(String::New(chars)))); | 2884 LanguageError::New(String::Handle(String::New(chars)))); |
2855 Isolate::Current()->long_jump_base()->Jump(1, error); | 2885 Isolate::Current()->long_jump_base()->Jump(1, error); |
2856 } | 2886 } |
2857 | 2887 |
2858 | 2888 |
2859 } // namespace dart | 2889 } // namespace dart |
OLD | NEW |