OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/code_generator.h" | 5 #include "vm/code_generator.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 #include "vm/ast.h" | 8 #include "vm/ast.h" |
9 #include "vm/code_patcher.h" | 9 #include "vm/code_patcher.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 DEFINE_FLAG(bool, trace_osr, false, "Trace attempts at on-stack replacement."); | 62 DEFINE_FLAG(bool, trace_osr, false, "Trace attempts at on-stack replacement."); |
63 | 63 |
64 DEFINE_FLAG(int, stacktrace_every, 0, | 64 DEFINE_FLAG(int, stacktrace_every, 0, |
65 "Compute debugger stacktrace on every N stack overflow checks"); | 65 "Compute debugger stacktrace on every N stack overflow checks"); |
66 DEFINE_FLAG(charp, stacktrace_filter, NULL, | 66 DEFINE_FLAG(charp, stacktrace_filter, NULL, |
67 "Compute stacktrace in named function on stack overflow checks"); | 67 "Compute stacktrace in named function on stack overflow checks"); |
68 DEFINE_FLAG(int, deoptimize_every, 0, | 68 DEFINE_FLAG(int, deoptimize_every, 0, |
69 "Deoptimize on every N stack overflow checks"); | 69 "Deoptimize on every N stack overflow checks"); |
70 DEFINE_FLAG(charp, deoptimize_filter, NULL, | 70 DEFINE_FLAG(charp, deoptimize_filter, NULL, |
71 "Deoptimize in named function on stack overflow checks"); | 71 "Deoptimize in named function on stack overflow checks"); |
| 72 DEFINE_FLAG(bool, lazy_dispatchers, true, "Lazily generate dispatchers"); |
72 | 73 |
73 #ifdef DEBUG | 74 #ifdef DEBUG |
74 DEFINE_FLAG(charp, gc_at_instance_allocation, NULL, | 75 DEFINE_FLAG(charp, gc_at_instance_allocation, NULL, |
75 "Perform a GC before allocation of instances of " | 76 "Perform a GC before allocation of instances of " |
76 "the specified class"); | 77 "the specified class"); |
77 #endif | 78 #endif |
78 | 79 |
79 DEFINE_RUNTIME_ENTRY(TraceFunctionEntry, 1) { | 80 DEFINE_RUNTIME_ENTRY(TraceFunctionEntry, 1) { |
80 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); | 81 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); |
81 const String& function_name = String::Handle(function.name()); | 82 const String& function_name = String::Handle(function.name()); |
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
769 | 770 |
770 const Class& receiver_class = Class::Handle(receiver.clazz()); | 771 const Class& receiver_class = Class::Handle(receiver.clazz()); |
771 const String& target_name = String::Handle(ic_data.target_name()); | 772 const String& target_name = String::Handle(ic_data.target_name()); |
772 | 773 |
773 Function& result = Function::Handle(); | 774 Function& result = Function::Handle(); |
774 if (!ResolveCallThroughGetter(receiver, | 775 if (!ResolveCallThroughGetter(receiver, |
775 receiver_class, | 776 receiver_class, |
776 target_name, | 777 target_name, |
777 args_descriptor, | 778 args_descriptor, |
778 &result)) { | 779 &result)) { |
| 780 if (!FLAG_lazy_dispatchers) { |
| 781 return result.raw(); // Return null. |
| 782 } |
779 ArgumentsDescriptor desc(args_descriptor); | 783 ArgumentsDescriptor desc(args_descriptor); |
780 const Function& target_function = | 784 const Function& target_function = |
781 Function::Handle(receiver_class.GetInvocationDispatcher( | 785 Function::Handle(receiver_class.GetInvocationDispatcher( |
782 target_name, | 786 target_name, |
783 args_descriptor, | 787 args_descriptor, |
784 RawFunction::kNoSuchMethodDispatcher)); | 788 RawFunction::kNoSuchMethodDispatcher)); |
785 if (FLAG_trace_ic) { | 789 if (FLAG_trace_ic) { |
786 OS::PrintErr("NoSuchMethod IC miss: adding <%s> id:%" Pd " -> <%s>\n", | 790 OS::PrintErr("NoSuchMethod IC miss: adding <%s> id:%" Pd " -> <%s>\n", |
787 Class::Handle(receiver.clazz()).ToCString(), | 791 Class::Handle(receiver.clazz()).ToCString(), |
788 receiver.GetClassId(), | 792 receiver.GetClassId(), |
(...skipping 15 matching lines...) Expand all Loading... |
804 Function& target_function = Function::Handle( | 808 Function& target_function = Function::Handle( |
805 Resolver::ResolveDynamic(receiver, function_name, arguments_descriptor)); | 809 Resolver::ResolveDynamic(receiver, function_name, arguments_descriptor)); |
806 if (target_function.IsNull()) { | 810 if (target_function.IsNull()) { |
807 if (FLAG_trace_ic) { | 811 if (FLAG_trace_ic) { |
808 OS::PrintErr("InlineCacheMissHandler NULL function for %s receiver: %s\n", | 812 OS::PrintErr("InlineCacheMissHandler NULL function for %s receiver: %s\n", |
809 String::Handle(ic_data.target_name()).ToCString(), | 813 String::Handle(ic_data.target_name()).ToCString(), |
810 receiver.ToCString()); | 814 receiver.ToCString()); |
811 } | 815 } |
812 target_function = InlineCacheMissHelper(receiver, ic_data); | 816 target_function = InlineCacheMissHelper(receiver, ic_data); |
813 } | 817 } |
814 ASSERT(!target_function.IsNull()); | 818 if (target_function.IsNull()) { |
| 819 ASSERT(!FLAG_lazy_dispatchers); |
| 820 return target_function.raw(); |
| 821 } |
815 if (args.length() == 1) { | 822 if (args.length() == 1) { |
816 ic_data.AddReceiverCheck(args[0]->GetClassId(), target_function); | 823 ic_data.AddReceiverCheck(args[0]->GetClassId(), target_function); |
817 } else { | 824 } else { |
818 GrowableArray<intptr_t> class_ids(args.length()); | 825 GrowableArray<intptr_t> class_ids(args.length()); |
819 ASSERT(ic_data.NumArgsTested() == args.length()); | 826 ASSERT(ic_data.NumArgsTested() == args.length()); |
820 for (intptr_t i = 0; i < args.length(); i++) { | 827 for (intptr_t i = 0; i < args.length(); i++) { |
821 class_ids.Add(args[i]->GetClassId()); | 828 class_ids.Add(args[i]->GetClassId()); |
822 } | 829 } |
823 ic_data.AddCheck(class_ids, target_function); | 830 ic_data.AddCheck(class_ids, target_function); |
824 } | 831 } |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1005 } | 1012 } |
1006 | 1013 |
1007 ArgumentsDescriptor args_desc(descriptor); | 1014 ArgumentsDescriptor args_desc(descriptor); |
1008 Function& target_function = Function::Handle( | 1015 Function& target_function = Function::Handle( |
1009 Resolver::ResolveDynamicForReceiverClass(cls, | 1016 Resolver::ResolveDynamicForReceiverClass(cls, |
1010 name, | 1017 name, |
1011 args_desc)); | 1018 args_desc)); |
1012 if (target_function.IsNull()) { | 1019 if (target_function.IsNull()) { |
1013 target_function = InlineCacheMissHelper(receiver, ic_data); | 1020 target_function = InlineCacheMissHelper(receiver, ic_data); |
1014 } | 1021 } |
1015 | 1022 if (target_function.IsNull()) { |
1016 ASSERT(!target_function.IsNull()); | 1023 ASSERT(!FLAG_lazy_dispatchers); |
| 1024 arguments.SetReturn(target_function); |
| 1025 return; |
| 1026 } |
1017 // Insert function found into cache and return it. | 1027 // Insert function found into cache and return it. |
1018 cache.EnsureCapacity(); | 1028 cache.EnsureCapacity(); |
1019 const Smi& class_id = Smi::Handle(Smi::New(cls.id())); | 1029 const Smi& class_id = Smi::Handle(Smi::New(cls.id())); |
1020 cache.Insert(class_id, target_function); | 1030 cache.Insert(class_id, target_function); |
1021 arguments.SetReturn(target_function); | 1031 arguments.SetReturn(target_function); |
1022 } | 1032 } |
1023 | 1033 |
1024 | 1034 |
| 1035 // Invoke appropriate noSuchMethod or closure from getter. |
| 1036 // Arg0: receiver |
| 1037 // Arg1: IC data |
| 1038 // Arg2: arguments descriptor array |
| 1039 // Arg3: arguments array |
| 1040 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) { |
| 1041 ASSERT(!FLAG_lazy_dispatchers); |
| 1042 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); |
| 1043 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); |
| 1044 const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(2)); |
| 1045 const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3)); |
| 1046 const String& target_name = String::Handle(ic_data.target_name()); |
| 1047 // Handle noSuchMethod invocation. |
| 1048 const Object& result = Object::Handle( |
| 1049 DartEntry::InvokeNoSuchMethod(receiver, |
| 1050 target_name, |
| 1051 orig_arguments, |
| 1052 orig_arguments_desc)); |
| 1053 CheckResultError(result); |
| 1054 arguments.SetReturn(result); |
| 1055 } |
| 1056 |
| 1057 |
| 1058 |
1025 // Invoke appropriate noSuchMethod function. | 1059 // Invoke appropriate noSuchMethod function. |
1026 // Arg0: receiver (closure object) | 1060 // Arg0: receiver (closure object) |
1027 // Arg1: arguments descriptor array. | 1061 // Arg1: arguments descriptor array. |
1028 // Arg2: arguments array. | 1062 // Arg2: arguments array. |
1029 DEFINE_RUNTIME_ENTRY(InvokeClosureNoSuchMethod, 3) { | 1063 DEFINE_RUNTIME_ENTRY(InvokeClosureNoSuchMethod, 3) { |
1030 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); | 1064 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); |
1031 const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(1)); | 1065 const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(1)); |
1032 const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(2)); | 1066 const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(2)); |
1033 | 1067 |
1034 // For closure the function name is always 'call'. Replace it with the | 1068 // For closure the function name is always 'call'. Replace it with the |
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1684 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 1718 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
1685 const TypedData& new_data = | 1719 const TypedData& new_data = |
1686 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 1720 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
1687 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 1721 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
1688 typed_data_cell.SetAt(0, new_data); | 1722 typed_data_cell.SetAt(0, new_data); |
1689 arguments.SetReturn(new_data); | 1723 arguments.SetReturn(new_data); |
1690 } | 1724 } |
1691 | 1725 |
1692 | 1726 |
1693 } // namespace dart | 1727 } // namespace dart |
OLD | NEW |