| 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 |