OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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/code_index_table.h" | 7 #include "vm/code_index_table.h" |
8 #include "vm/code_patcher.h" | 8 #include "vm/code_patcher.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/dart_api_impl.h" | 10 #include "vm/dart_api_impl.h" |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 | 424 |
425 Function& function = Function::Handle(); | 425 Function& function = Function::Handle(); |
426 function = Resolver::ResolveDynamic(receiver, | 426 function = Resolver::ResolveDynamic(receiver, |
427 function_name, | 427 function_name, |
428 num_arguments, | 428 num_arguments, |
429 num_named_arguments); | 429 num_named_arguments); |
430 if (function.IsNull()) { | 430 if (function.IsNull()) { |
431 return Code::null(); | 431 return Code::null(); |
432 } else { | 432 } else { |
433 if (!function.HasCode()) { | 433 if (!function.HasCode()) { |
434 Compiler::CompileFunction(function); | 434 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
| 435 if (!error.IsNull()) { |
| 436 Exceptions::PropagateError(error); |
| 437 } |
435 } | 438 } |
436 functions_cache.AddCompiledFunction(function, | 439 functions_cache.AddCompiledFunction(function, |
437 num_arguments, | 440 num_arguments, |
438 num_named_arguments); | 441 num_named_arguments); |
439 return function.code(); | 442 return function.code(); |
440 } | 443 } |
441 } | 444 } |
442 | 445 |
443 | 446 |
444 // Result of an invoke may be an unhandled exception, in which case we | 447 // Result of an invoke may be an unhandled exception, in which case we |
445 // rethrow it. | 448 // rethrow it. |
446 static void CheckResultException(const Instance& result) { | 449 static void CheckResultError(const Object& result) { |
447 if (result.IsUnhandledException()) { | 450 if (result.IsError()) { |
448 const UnhandledException& unhandled = UnhandledException::Handle( | 451 Error& error = Error::Handle(); |
449 reinterpret_cast<RawUnhandledException*>(result.raw())); | 452 error ^= result.raw(); |
450 const Instance& excp = Instance::Handle(unhandled.exception()); | 453 Exceptions::PropagateError(error); |
451 const Instance& stack = Instance::Handle(unhandled.stacktrace()); | |
452 Exceptions::ReThrow(excp, stack); | |
453 } | 454 } |
454 } | 455 } |
455 | 456 |
456 | 457 |
457 // Resolves an instance function and compiles it if necessary. | 458 // Resolves an instance function and compiles it if necessary. |
458 // Arg0: receiver object. | 459 // Arg0: receiver object. |
459 // Returns: RawCode object or NULL (method not found or not compileable). | 460 // Returns: RawCode object or NULL (method not found or not compileable). |
460 // This is called by the megamorphic stub when instance call does not need to be | 461 // This is called by the megamorphic stub when instance call does not need to be |
461 // patched. | 462 // patched. |
462 // Used by megamorphic lookup/no-such-method-handling. | 463 // Used by megamorphic lookup/no-such-method-handling. |
(...skipping 12 matching lines...) Expand all Loading... |
475 DEFINE_RUNTIME_ENTRY(BreakpointStaticHandler, 1) { | 476 DEFINE_RUNTIME_ENTRY(BreakpointStaticHandler, 1) { |
476 ASSERT(arguments.Count() == | 477 ASSERT(arguments.Count() == |
477 kBreakpointStaticHandlerRuntimeEntry.argument_count()); | 478 kBreakpointStaticHandlerRuntimeEntry.argument_count()); |
478 ASSERT(isolate->debugger() != NULL); | 479 ASSERT(isolate->debugger() != NULL); |
479 isolate->debugger()->BreakpointCallback(); | 480 isolate->debugger()->BreakpointCallback(); |
480 // Make sure the static function that is about to be called is | 481 // Make sure the static function that is about to be called is |
481 // compiled. The stub will jump to the entry point without any | 482 // compiled. The stub will jump to the entry point without any |
482 // further tests. | 483 // further tests. |
483 const Function& function = Function::CheckedHandle(arguments.At(0)); | 484 const Function& function = Function::CheckedHandle(arguments.At(0)); |
484 if (!function.HasCode()) { | 485 if (!function.HasCode()) { |
485 Compiler::CompileFunction(function); | 486 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
| 487 if (!error.IsNull()) { |
| 488 Exceptions::PropagateError(error); |
| 489 } |
486 } | 490 } |
487 } | 491 } |
488 | 492 |
489 | 493 |
490 // Gets called from debug stub when code reaches a breakpoint. | 494 // Gets called from debug stub when code reaches a breakpoint. |
491 DEFINE_RUNTIME_ENTRY(BreakpointDynamicHandler, 0) { | 495 DEFINE_RUNTIME_ENTRY(BreakpointDynamicHandler, 0) { |
492 ASSERT(arguments.Count() == | 496 ASSERT(arguments.Count() == |
493 kBreakpointDynamicHandlerRuntimeEntry.argument_count()); | 497 kBreakpointDynamicHandlerRuntimeEntry.argument_count()); |
494 ASSERT(isolate->debugger() != NULL); | 498 ASSERT(isolate->debugger() != NULL); |
495 isolate->debugger()->BreakpointCallback(); | 499 isolate->debugger()->BreakpointCallback(); |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 getter_function_name, | 704 getter_function_name, |
701 kNumArguments, | 705 kNumArguments, |
702 kNumNamedArguments)); | 706 kNumNamedArguments)); |
703 Code& code = Code::Handle(); | 707 Code& code = Code::Handle(); |
704 if (function.IsNull()) { | 708 if (function.IsNull()) { |
705 arguments.SetReturn(code); | 709 arguments.SetReturn(code); |
706 return; // No getter function found so can't be an implicit closure. | 710 return; // No getter function found so can't be an implicit closure. |
707 } | 711 } |
708 GrowableArray<const Object*> invoke_arguments(0); | 712 GrowableArray<const Object*> invoke_arguments(0); |
709 const Array& kNoArgumentNames = Array::Handle(); | 713 const Array& kNoArgumentNames = Array::Handle(); |
710 const Instance& result = | 714 const Object& result = |
711 Instance::Handle( | 715 Object::Handle(DartEntry::InvokeDynamic(receiver, |
712 DartEntry::InvokeDynamic(receiver, | 716 function, |
713 function, | 717 invoke_arguments, |
714 invoke_arguments, | 718 kNoArgumentNames)); |
715 kNoArgumentNames)); | 719 if (result.IsError()) { |
716 if (result.IsUnhandledException()) { | 720 if (result.IsUnhandledException()) { |
717 arguments.SetReturn(code); | 721 // If the getter throws an exception, treat as no such method. |
718 return; // Error accessing getter, treat as no such method. | 722 arguments.SetReturn(code); |
| 723 return; |
| 724 } else { |
| 725 Error& error = Error::Handle(); |
| 726 error ^= result.raw(); |
| 727 Exceptions::PropagateError(error); |
| 728 } |
719 } | 729 } |
720 if (!result.IsSmi()) { | 730 if (!result.IsSmi()) { |
721 const Class& cls = Class::Handle(result.clazz()); | 731 const Class& cls = Class::Handle(result.clazz()); |
722 ASSERT(!cls.IsNull()); | 732 ASSERT(!cls.IsNull()); |
723 function = cls.signature_function(); | 733 function = cls.signature_function(); |
724 if (!function.IsNull()) { | 734 if (!function.IsNull()) { |
725 arguments.SetReturn(result); | 735 arguments.SetReturn(result); |
726 return; // Return closure object. | 736 return; // Return closure object. |
727 } | 737 } |
728 } | 738 } |
729 Exceptions::ThrowByType(Exceptions::kObjectNotClosure, invoke_arguments); | 739 Exceptions::ThrowByType(Exceptions::kObjectNotClosure, invoke_arguments); |
730 } | 740 } |
731 | 741 |
732 | 742 |
733 // Invoke Implicit Closure function. | 743 // Invoke Implicit Closure function. |
734 // Arg0: closure object. | 744 // Arg0: closure object. |
735 // Arg1: arguments descriptor (originally passed as dart instance invocation). | 745 // Arg1: arguments descriptor (originally passed as dart instance invocation). |
736 // Arg2: arguments array (originally passed to dart instance invocation). | 746 // Arg2: arguments array (originally passed to dart instance invocation). |
737 DEFINE_RUNTIME_ENTRY(InvokeImplicitClosureFunction, 3) { | 747 DEFINE_RUNTIME_ENTRY(InvokeImplicitClosureFunction, 3) { |
738 ASSERT(arguments.Count() == | 748 ASSERT(arguments.Count() == |
739 kInvokeImplicitClosureFunctionRuntimeEntry.argument_count()); | 749 kInvokeImplicitClosureFunctionRuntimeEntry.argument_count()); |
740 const Closure& closure = Closure::CheckedHandle(arguments.At(0)); | 750 const Closure& closure = Closure::CheckedHandle(arguments.At(0)); |
741 const Array& arg_descriptor = Array::CheckedHandle(arguments.At(1)); | 751 const Array& arg_descriptor = Array::CheckedHandle(arguments.At(1)); |
742 const Array& func_arguments = Array::CheckedHandle(arguments.At(2)); | 752 const Array& func_arguments = Array::CheckedHandle(arguments.At(2)); |
743 const Function& function = Function::Handle(closure.function()); | 753 const Function& function = Function::Handle(closure.function()); |
744 ASSERT(!function.IsNull()); | 754 ASSERT(!function.IsNull()); |
745 if (!function.HasCode()) { | 755 if (!function.HasCode()) { |
746 Compiler::CompileFunction(function); | 756 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
| 757 if (!error.IsNull()) { |
| 758 Exceptions::PropagateError(error); |
| 759 } |
747 } | 760 } |
748 const Context& context = Context::Handle(closure.context()); | 761 const Context& context = Context::Handle(closure.context()); |
749 const Code& code = Code::Handle(function.code()); | 762 const Code& code = Code::Handle(function.code()); |
750 ASSERT(!code.IsNull()); | 763 ASSERT(!code.IsNull()); |
751 const Instructions& instrs = Instructions::Handle(code.instructions()); | 764 const Instructions& instrs = Instructions::Handle(code.instructions()); |
752 ASSERT(!instrs.IsNull()); | 765 ASSERT(!instrs.IsNull()); |
753 | 766 |
754 // Adjust arguments descriptor array to account for removal of the receiver | 767 // Adjust arguments descriptor array to account for removal of the receiver |
755 // parameter. Since the arguments descriptor array is canonicalized, create a | 768 // parameter. Since the arguments descriptor array is canonicalized, create a |
756 // new one instead of patching the original one. | 769 // new one instead of patching the original one. |
(...skipping 28 matching lines...) Expand all Loading... |
785 GrowableArray<const Object*> invoke_arguments(0); | 798 GrowableArray<const Object*> invoke_arguments(0); |
786 for (intptr_t i = 0; i < func_arguments.Length(); i++) { | 799 for (intptr_t i = 0; i < func_arguments.Length(); i++) { |
787 const Object& value = Object::Handle(func_arguments.At(i)); | 800 const Object& value = Object::Handle(func_arguments.At(i)); |
788 invoke_arguments.Add(&value); | 801 invoke_arguments.Add(&value); |
789 } | 802 } |
790 | 803 |
791 // Now Call the invoke stub which will invoke the closure. | 804 // Now Call the invoke stub which will invoke the closure. |
792 DartEntry::invokestub entrypoint = reinterpret_cast<DartEntry::invokestub>( | 805 DartEntry::invokestub entrypoint = reinterpret_cast<DartEntry::invokestub>( |
793 StubCode::InvokeDartCodeEntryPoint()); | 806 StubCode::InvokeDartCodeEntryPoint()); |
794 ASSERT(context.isolate() == Isolate::Current()); | 807 ASSERT(context.isolate() == Isolate::Current()); |
795 const Instance& result = Instance::Handle( | 808 const Object& result = Object::Handle( |
796 entrypoint(instrs.EntryPoint(), | 809 entrypoint(instrs.EntryPoint(), |
797 adjusted_arg_descriptor, | 810 adjusted_arg_descriptor, |
798 invoke_arguments.data(), | 811 invoke_arguments.data(), |
799 context)); | 812 context)); |
800 CheckResultException(result); | 813 CheckResultError(result); |
801 arguments.SetReturn(result); | 814 arguments.SetReturn(result); |
802 } | 815 } |
803 | 816 |
804 | 817 |
805 // Invoke appropriate noSuchMethod function. | 818 // Invoke appropriate noSuchMethod function. |
806 // Arg0: receiver. | 819 // Arg0: receiver. |
807 // Arg1: ic-data array. | 820 // Arg1: ic-data array. |
808 // Arg2: original arguments descriptor array. | 821 // Arg2: original arguments descriptor array. |
809 // Arg3: original arguments array. | 822 // Arg3: original arguments array. |
810 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodFunction, 4) { | 823 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodFunction, 4) { |
(...skipping 15 matching lines...) Expand all Loading... |
826 String::Handle(String::NewSymbol("noSuchMethod")); | 839 String::Handle(String::NewSymbol("noSuchMethod")); |
827 const Function& function = Function::ZoneHandle( | 840 const Function& function = Function::ZoneHandle( |
828 Resolver::ResolveDynamic(receiver, | 841 Resolver::ResolveDynamic(receiver, |
829 function_name, | 842 function_name, |
830 kNumArguments, | 843 kNumArguments, |
831 kNumNamedArguments)); | 844 kNumNamedArguments)); |
832 ASSERT(!function.IsNull()); | 845 ASSERT(!function.IsNull()); |
833 GrowableArray<const Object*> invoke_arguments(2); | 846 GrowableArray<const Object*> invoke_arguments(2); |
834 invoke_arguments.Add(&original_function_name); | 847 invoke_arguments.Add(&original_function_name); |
835 invoke_arguments.Add(&orig_arguments); | 848 invoke_arguments.Add(&orig_arguments); |
836 const Instance& result = Instance::Handle( | 849 const Object& result = Object::Handle( |
837 DartEntry::InvokeDynamic(receiver, | 850 DartEntry::InvokeDynamic(receiver, |
838 function, | 851 function, |
839 invoke_arguments, | 852 invoke_arguments, |
840 kNoArgumentNames)); | 853 kNoArgumentNames)); |
841 CheckResultException(result); | 854 CheckResultError(result); |
842 arguments.SetReturn(result); | 855 arguments.SetReturn(result); |
843 } | 856 } |
844 | 857 |
845 | 858 |
846 // Report that an object is not a closure. | 859 // Report that an object is not a closure. |
847 // Arg0: non-closure object. | 860 // Arg0: non-closure object. |
848 // Arg1: arguments array. | 861 // Arg1: arguments array. |
849 DEFINE_RUNTIME_ENTRY(ReportObjectNotClosure, 2) { | 862 DEFINE_RUNTIME_ENTRY(ReportObjectNotClosure, 2) { |
850 ASSERT(arguments.Count() == | 863 ASSERT(arguments.Count() == |
851 kReportObjectNotClosureRuntimeEntry.argument_count()); | 864 kReportObjectNotClosureRuntimeEntry.argument_count()); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 if (function.deoptimization_counter() >= | 921 if (function.deoptimization_counter() >= |
909 FLAG_deoptimization_counter_threshold) { | 922 FLAG_deoptimization_counter_threshold) { |
910 // TODO(srdjan): Investigate excessive deoptimization. | 923 // TODO(srdjan): Investigate excessive deoptimization. |
911 function.set_invocation_counter(0); | 924 function.set_invocation_counter(0); |
912 return; | 925 return; |
913 } | 926 } |
914 if (function.is_optimizable()) { | 927 if (function.is_optimizable()) { |
915 ASSERT(!Code::Handle(function.code()).is_optimized()); | 928 ASSERT(!Code::Handle(function.code()).is_optimized()); |
916 const Code& unoptimized_code = Code::Handle(function.code()); | 929 const Code& unoptimized_code = Code::Handle(function.code()); |
917 // Compilation patches the entry of unoptimized code. | 930 // Compilation patches the entry of unoptimized code. |
918 Compiler::CompileOptimizedFunction(function); | 931 const Error& error = |
| 932 Error::Handle(Compiler::CompileOptimizedFunction(function)); |
| 933 if (!error.IsNull()) { |
| 934 Exceptions::PropagateError(error); |
| 935 } |
919 const Code& optimized_code = Code::Handle(function.code()); | 936 const Code& optimized_code = Code::Handle(function.code()); |
920 ASSERT(!optimized_code.IsNull()); | 937 ASSERT(!optimized_code.IsNull()); |
921 ASSERT(!unoptimized_code.IsNull()); | 938 ASSERT(!unoptimized_code.IsNull()); |
922 } else { | 939 } else { |
923 // TODO(5442338): Abort as this should not happen. | 940 // TODO(5442338): Abort as this should not happen. |
924 function.set_invocation_counter(0); | 941 function.set_invocation_counter(0); |
925 } | 942 } |
926 } | 943 } |
927 | 944 |
928 | 945 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1015 // types/classes have been collected. | 1032 // types/classes have been collected. |
1016 function.set_invocation_counter(0); | 1033 function.set_invocation_counter(0); |
1017 function.set_deoptimization_counter(function.deoptimization_counter() + 1); | 1034 function.set_deoptimization_counter(function.deoptimization_counter() + 1); |
1018 | 1035 |
1019 // We have to skip the following otherwise the compiler will complain | 1036 // We have to skip the following otherwise the compiler will complain |
1020 // when it attempts to install unoptimized code into a function that | 1037 // when it attempts to install unoptimized code into a function that |
1021 // was already deoptimized. | 1038 // was already deoptimized. |
1022 if (Code::Handle(function.code()).is_optimized()) { | 1039 if (Code::Handle(function.code()).is_optimized()) { |
1023 // Get unoptimized code. Compilation restores (reenables) the entry of | 1040 // Get unoptimized code. Compilation restores (reenables) the entry of |
1024 // unoptimized code. | 1041 // unoptimized code. |
1025 Compiler::CompileFunction(function); | 1042 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
| 1043 if (!error.IsNull()) { |
| 1044 Exceptions::PropagateError(error); |
| 1045 } |
1026 } | 1046 } |
1027 // TODO(srdjan): Handle better complex cases, e.g. when an older optimized | 1047 // TODO(srdjan): Handle better complex cases, e.g. when an older optimized |
1028 // code is alive on frame and gets deoptimized after the function was | 1048 // code is alive on frame and gets deoptimized after the function was |
1029 // optimized a second time. | 1049 // optimized a second time. |
1030 if (FLAG_trace_deopt) { | 1050 if (FLAG_trace_deopt) { |
1031 OS::Print("After patching ->0x%x:\n", continue_at_pc); | 1051 OS::Print("After patching ->0x%x:\n", continue_at_pc); |
1032 } | 1052 } |
1033 } | 1053 } |
1034 | 1054 |
1035 | 1055 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1106 } | 1126 } |
1107 } | 1127 } |
1108 } | 1128 } |
1109 // The cache is null terminated, therefore the loop above should never | 1129 // The cache is null terminated, therefore the loop above should never |
1110 // terminate by itself. | 1130 // terminate by itself. |
1111 UNREACHABLE(); | 1131 UNREACHABLE(); |
1112 return Code::null(); | 1132 return Code::null(); |
1113 } | 1133 } |
1114 | 1134 |
1115 } // namespace dart | 1135 } // namespace dart |
OLD | NEW |