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