| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 if (!maybe_result->ToObject(&result)) return maybe_result; | 645 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 646 } | 646 } |
| 647 } | 647 } |
| 648 return code; | 648 return code; |
| 649 } | 649 } |
| 650 | 650 |
| 651 #define CALL_LOGGER_TAG(kind, type) \ | 651 #define CALL_LOGGER_TAG(kind, type) \ |
| 652 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) | 652 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) |
| 653 | 653 |
| 654 MaybeObject* StubCache::ComputeCallConstant(int argc, | 654 MaybeObject* StubCache::ComputeCallConstant(int argc, |
| 655 InLoopFlag in_loop, | |
| 656 Code::Kind kind, | 655 Code::Kind kind, |
| 657 Code::ExtraICState extra_ic_state, | 656 Code::ExtraICState extra_ic_state, |
| 658 String* name, | 657 String* name, |
| 659 Object* object, | 658 Object* object, |
| 660 JSObject* holder, | 659 JSObject* holder, |
| 661 JSFunction* function) { | 660 JSFunction* function) { |
| 662 // Compute the check type and the map. | 661 // Compute the check type and the map. |
| 663 InlineCacheHolderFlag cache_holder = | 662 InlineCacheHolderFlag cache_holder = |
| 664 IC::GetCodeCacheForObject(object, holder); | 663 IC::GetCodeCacheForObject(object, holder); |
| 665 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder); | 664 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder); |
| 666 | 665 |
| 667 // Compute check type based on receiver/holder. | 666 // Compute check type based on receiver/holder. |
| 668 CheckType check = RECEIVER_MAP_CHECK; | 667 CheckType check = RECEIVER_MAP_CHECK; |
| 669 if (object->IsString()) { | 668 if (object->IsString()) { |
| 670 check = STRING_CHECK; | 669 check = STRING_CHECK; |
| 671 } else if (object->IsNumber()) { | 670 } else if (object->IsNumber()) { |
| 672 check = NUMBER_CHECK; | 671 check = NUMBER_CHECK; |
| 673 } else if (object->IsBoolean()) { | 672 } else if (object->IsBoolean()) { |
| 674 check = BOOLEAN_CHECK; | 673 check = BOOLEAN_CHECK; |
| 675 } | 674 } |
| 676 | 675 |
| 677 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, | 676 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, |
| 678 CONSTANT_FUNCTION, | 677 CONSTANT_FUNCTION, |
| 679 extra_ic_state, | 678 extra_ic_state, |
| 680 cache_holder, | 679 cache_holder, |
| 681 in_loop, | |
| 682 argc); | 680 argc); |
| 683 Object* code = map_holder->map()->FindInCodeCache(name, flags); | 681 Object* code = map_holder->map()->FindInCodeCache(name, flags); |
| 684 if (code->IsUndefined()) { | 682 if (code->IsUndefined()) { |
| 685 // If the function hasn't been compiled yet, we cannot do it now | 683 // If the function hasn't been compiled yet, we cannot do it now |
| 686 // because it may cause GC. To avoid this issue, we return an | 684 // because it may cause GC. To avoid this issue, we return an |
| 687 // internal error which will make sure we do not update any | 685 // internal error which will make sure we do not update any |
| 688 // caches. | 686 // caches. |
| 689 if (!function->is_compiled()) return Failure::InternalError(); | 687 if (!function->is_compiled()) return Failure::InternalError(); |
| 690 // Compile the stub - only create stubs for fully compiled functions. | 688 // Compile the stub - only create stubs for fully compiled functions. |
| 691 CallStubCompiler compiler( | 689 CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder); |
| 692 argc, in_loop, kind, extra_ic_state, cache_holder); | |
| 693 { MaybeObject* maybe_code = | 690 { MaybeObject* maybe_code = |
| 694 compiler.CompileCallConstant(object, holder, function, name, check); | 691 compiler.CompileCallConstant(object, holder, function, name, check); |
| 695 if (!maybe_code->ToObject(&code)) return maybe_code; | 692 if (!maybe_code->ToObject(&code)) return maybe_code; |
| 696 } | 693 } |
| 697 Code::cast(code)->set_check_type(check); | 694 Code::cast(code)->set_check_type(check); |
| 698 ASSERT_EQ(flags, Code::cast(code)->flags()); | 695 ASSERT_EQ(flags, Code::cast(code)->flags()); |
| 699 PROFILE(isolate_, | 696 PROFILE(isolate_, |
| 700 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | 697 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
| 701 Code::cast(code), name)); | 698 Code::cast(code), name)); |
| 702 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code))); | 699 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code))); |
| 703 Object* result; | 700 Object* result; |
| 704 { MaybeObject* maybe_result = | 701 { MaybeObject* maybe_result = |
| 705 map_holder->UpdateMapCodeCache(name, Code::cast(code)); | 702 map_holder->UpdateMapCodeCache(name, Code::cast(code)); |
| 706 if (!maybe_result->ToObject(&result)) return maybe_result; | 703 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 707 } | 704 } |
| 708 } | 705 } |
| 709 return code; | 706 return code; |
| 710 } | 707 } |
| 711 | 708 |
| 712 | 709 |
| 713 MaybeObject* StubCache::ComputeCallField(int argc, | 710 MaybeObject* StubCache::ComputeCallField(int argc, |
| 714 InLoopFlag in_loop, | |
| 715 Code::Kind kind, | 711 Code::Kind kind, |
| 716 Code::ExtraICState extra_ic_state, | 712 Code::ExtraICState extra_ic_state, |
| 717 String* name, | 713 String* name, |
| 718 Object* object, | 714 Object* object, |
| 719 JSObject* holder, | 715 JSObject* holder, |
| 720 int index) { | 716 int index) { |
| 721 // Compute the check type and the map. | 717 // Compute the check type and the map. |
| 722 InlineCacheHolderFlag cache_holder = | 718 InlineCacheHolderFlag cache_holder = |
| 723 IC::GetCodeCacheForObject(object, holder); | 719 IC::GetCodeCacheForObject(object, holder); |
| 724 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder); | 720 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder); |
| 725 | 721 |
| 726 // TODO(1233596): We cannot do receiver map check for non-JS objects | 722 // TODO(1233596): We cannot do receiver map check for non-JS objects |
| 727 // because they may be represented as immediates without a | 723 // because they may be represented as immediates without a |
| 728 // map. Instead, we check against the map in the holder. | 724 // map. Instead, we check against the map in the holder. |
| 729 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { | 725 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { |
| 730 object = holder; | 726 object = holder; |
| 731 } | 727 } |
| 732 | 728 |
| 733 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, | 729 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, |
| 734 FIELD, | 730 FIELD, |
| 735 extra_ic_state, | 731 extra_ic_state, |
| 736 cache_holder, | 732 cache_holder, |
| 737 in_loop, | |
| 738 argc); | 733 argc); |
| 739 Object* code = map_holder->map()->FindInCodeCache(name, flags); | 734 Object* code = map_holder->map()->FindInCodeCache(name, flags); |
| 740 if (code->IsUndefined()) { | 735 if (code->IsUndefined()) { |
| 741 CallStubCompiler compiler( | 736 CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder); |
| 742 argc, in_loop, kind, extra_ic_state, cache_holder); | |
| 743 { MaybeObject* maybe_code = | 737 { MaybeObject* maybe_code = |
| 744 compiler.CompileCallField(JSObject::cast(object), | 738 compiler.CompileCallField(JSObject::cast(object), |
| 745 holder, | 739 holder, |
| 746 index, | 740 index, |
| 747 name); | 741 name); |
| 748 if (!maybe_code->ToObject(&code)) return maybe_code; | 742 if (!maybe_code->ToObject(&code)) return maybe_code; |
| 749 } | 743 } |
| 750 ASSERT_EQ(flags, Code::cast(code)->flags()); | 744 ASSERT_EQ(flags, Code::cast(code)->flags()); |
| 751 PROFILE(isolate_, | 745 PROFILE(isolate_, |
| 752 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | 746 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
| (...skipping 25 matching lines...) Expand all Loading... |
| 778 // because they may be represented as immediates without a | 772 // because they may be represented as immediates without a |
| 779 // map. Instead, we check against the map in the holder. | 773 // map. Instead, we check against the map in the holder. |
| 780 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { | 774 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { |
| 781 object = holder; | 775 object = holder; |
| 782 } | 776 } |
| 783 | 777 |
| 784 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, | 778 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, |
| 785 INTERCEPTOR, | 779 INTERCEPTOR, |
| 786 extra_ic_state, | 780 extra_ic_state, |
| 787 cache_holder, | 781 cache_holder, |
| 788 NOT_IN_LOOP, | |
| 789 argc); | 782 argc); |
| 790 Object* code = map_holder->map()->FindInCodeCache(name, flags); | 783 Object* code = map_holder->map()->FindInCodeCache(name, flags); |
| 791 if (code->IsUndefined()) { | 784 if (code->IsUndefined()) { |
| 792 CallStubCompiler compiler( | 785 CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder); |
| 793 argc, NOT_IN_LOOP, kind, extra_ic_state, cache_holder); | |
| 794 { MaybeObject* maybe_code = | 786 { MaybeObject* maybe_code = |
| 795 compiler.CompileCallInterceptor(JSObject::cast(object), holder, name); | 787 compiler.CompileCallInterceptor(JSObject::cast(object), holder, name); |
| 796 if (!maybe_code->ToObject(&code)) return maybe_code; | 788 if (!maybe_code->ToObject(&code)) return maybe_code; |
| 797 } | 789 } |
| 798 ASSERT_EQ(flags, Code::cast(code)->flags()); | 790 ASSERT_EQ(flags, Code::cast(code)->flags()); |
| 799 PROFILE(isolate(), | 791 PROFILE(isolate(), |
| 800 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | 792 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
| 801 Code::cast(code), name)); | 793 Code::cast(code), name)); |
| 802 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code))); | 794 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code))); |
| 803 Object* result; | 795 Object* result; |
| 804 { MaybeObject* maybe_result = | 796 { MaybeObject* maybe_result = |
| 805 map_holder->UpdateMapCodeCache(name, Code::cast(code)); | 797 map_holder->UpdateMapCodeCache(name, Code::cast(code)); |
| 806 if (!maybe_result->ToObject(&result)) return maybe_result; | 798 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 807 } | 799 } |
| 808 } | 800 } |
| 809 return code; | 801 return code; |
| 810 } | 802 } |
| 811 | 803 |
| 812 | 804 |
| 813 MaybeObject* StubCache::ComputeCallNormal(int argc, | 805 MaybeObject* StubCache::ComputeCallNormal(int argc, |
| 814 InLoopFlag in_loop, | |
| 815 Code::Kind kind, | 806 Code::Kind kind, |
| 816 Code::ExtraICState extra_ic_state, | 807 Code::ExtraICState extra_ic_state, |
| 817 String* name, | 808 String* name, |
| 818 JSObject* receiver) { | 809 JSObject* receiver) { |
| 819 Object* code; | 810 Object* code; |
| 820 { MaybeObject* maybe_code = | 811 { MaybeObject* maybe_code = ComputeCallNormal(argc, kind, extra_ic_state); |
| 821 ComputeCallNormal(argc, in_loop, kind, extra_ic_state); | |
| 822 if (!maybe_code->ToObject(&code)) return maybe_code; | 812 if (!maybe_code->ToObject(&code)) return maybe_code; |
| 823 } | 813 } |
| 824 return code; | 814 return code; |
| 825 } | 815 } |
| 826 | 816 |
| 827 | 817 |
| 828 MaybeObject* StubCache::ComputeCallGlobal(int argc, | 818 MaybeObject* StubCache::ComputeCallGlobal(int argc, |
| 829 InLoopFlag in_loop, | |
| 830 Code::Kind kind, | 819 Code::Kind kind, |
| 831 Code::ExtraICState extra_ic_state, | 820 Code::ExtraICState extra_ic_state, |
| 832 String* name, | 821 String* name, |
| 833 JSObject* receiver, | 822 JSObject* receiver, |
| 834 GlobalObject* holder, | 823 GlobalObject* holder, |
| 835 JSGlobalPropertyCell* cell, | 824 JSGlobalPropertyCell* cell, |
| 836 JSFunction* function) { | 825 JSFunction* function) { |
| 837 InlineCacheHolderFlag cache_holder = | 826 InlineCacheHolderFlag cache_holder = |
| 838 IC::GetCodeCacheForObject(receiver, holder); | 827 IC::GetCodeCacheForObject(receiver, holder); |
| 839 JSObject* map_holder = IC::GetCodeCacheHolder(receiver, cache_holder); | 828 JSObject* map_holder = IC::GetCodeCacheHolder(receiver, cache_holder); |
| 840 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, | 829 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, |
| 841 NORMAL, | 830 NORMAL, |
| 842 extra_ic_state, | 831 extra_ic_state, |
| 843 cache_holder, | 832 cache_holder, |
| 844 in_loop, | |
| 845 argc); | 833 argc); |
| 846 Object* code = map_holder->map()->FindInCodeCache(name, flags); | 834 Object* code = map_holder->map()->FindInCodeCache(name, flags); |
| 847 if (code->IsUndefined()) { | 835 if (code->IsUndefined()) { |
| 848 // If the function hasn't been compiled yet, we cannot do it now | 836 // If the function hasn't been compiled yet, we cannot do it now |
| 849 // because it may cause GC. To avoid this issue, we return an | 837 // because it may cause GC. To avoid this issue, we return an |
| 850 // internal error which will make sure we do not update any | 838 // internal error which will make sure we do not update any |
| 851 // caches. | 839 // caches. |
| 852 if (!function->is_compiled()) return Failure::InternalError(); | 840 if (!function->is_compiled()) return Failure::InternalError(); |
| 853 CallStubCompiler compiler( | 841 CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder); |
| 854 argc, in_loop, kind, extra_ic_state, cache_holder); | |
| 855 { MaybeObject* maybe_code = | 842 { MaybeObject* maybe_code = |
| 856 compiler.CompileCallGlobal(receiver, holder, cell, function, name); | 843 compiler.CompileCallGlobal(receiver, holder, cell, function, name); |
| 857 if (!maybe_code->ToObject(&code)) return maybe_code; | 844 if (!maybe_code->ToObject(&code)) return maybe_code; |
| 858 } | 845 } |
| 859 ASSERT_EQ(flags, Code::cast(code)->flags()); | 846 ASSERT_EQ(flags, Code::cast(code)->flags()); |
| 860 PROFILE(isolate(), | 847 PROFILE(isolate(), |
| 861 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | 848 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
| 862 Code::cast(code), name)); | 849 Code::cast(code), name)); |
| 863 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code))); | 850 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code))); |
| 864 Object* result; | 851 Object* result; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 913 heap->undefined_value()); | 900 heap->undefined_value()); |
| 914 heap->non_monomorphic_cache()->ValueAtPut(entry, code); | 901 heap->non_monomorphic_cache()->ValueAtPut(entry, code); |
| 915 CHECK(GetProbeValue(isolate, Code::cast(code)->flags()) == code); | 902 CHECK(GetProbeValue(isolate, Code::cast(code)->flags()) == code); |
| 916 } | 903 } |
| 917 } | 904 } |
| 918 return maybe_code; | 905 return maybe_code; |
| 919 } | 906 } |
| 920 | 907 |
| 921 | 908 |
| 922 Code* StubCache::FindCallInitialize(int argc, | 909 Code* StubCache::FindCallInitialize(int argc, |
| 923 InLoopFlag in_loop, | |
| 924 RelocInfo::Mode mode, | 910 RelocInfo::Mode mode, |
| 925 Code::Kind kind) { | 911 Code::Kind kind) { |
| 926 Code::ExtraICState extra_state = | 912 Code::ExtraICState extra_state = |
| 927 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) | | 913 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) | |
| 928 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT); | 914 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT); |
| 929 Code::Flags flags = Code::ComputeFlags(kind, | 915 Code::Flags flags = Code::ComputeFlags(kind, |
| 930 in_loop, | |
| 931 UNINITIALIZED, | 916 UNINITIALIZED, |
| 932 extra_state, | 917 extra_state, |
| 933 NORMAL, | 918 NORMAL, |
| 934 argc); | 919 argc); |
| 935 Object* result = ProbeCache(isolate(), flags)->ToObjectUnchecked(); | 920 Object* result = ProbeCache(isolate(), flags)->ToObjectUnchecked(); |
| 936 ASSERT(result != heap()->undefined_value()); | 921 ASSERT(result != heap()->undefined_value()); |
| 937 // This might be called during the marking phase of the collector | 922 // This might be called during the marking phase of the collector |
| 938 // hence the unchecked cast. | 923 // hence the unchecked cast. |
| 939 return reinterpret_cast<Code*>(result); | 924 return reinterpret_cast<Code*>(result); |
| 940 } | 925 } |
| 941 | 926 |
| 942 | 927 |
| 943 MaybeObject* StubCache::ComputeCallInitialize(int argc, | 928 MaybeObject* StubCache::ComputeCallInitialize(int argc, |
| 944 InLoopFlag in_loop, | |
| 945 RelocInfo::Mode mode, | 929 RelocInfo::Mode mode, |
| 946 Code::Kind kind) { | 930 Code::Kind kind) { |
| 947 Code::ExtraICState extra_state = | 931 Code::ExtraICState extra_state = |
| 948 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) | | 932 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) | |
| 949 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT); | 933 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT); |
| 950 Code::Flags flags = Code::ComputeFlags(kind, | 934 Code::Flags flags = Code::ComputeFlags(kind, |
| 951 in_loop, | |
| 952 UNINITIALIZED, | 935 UNINITIALIZED, |
| 953 extra_state, | 936 extra_state, |
| 954 NORMAL, | 937 NORMAL, |
| 955 argc); | 938 argc); |
| 956 Object* probe; | 939 Object* probe; |
| 957 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 940 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); |
| 958 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 941 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
| 959 } | 942 } |
| 960 if (!probe->IsUndefined()) return probe; | 943 if (!probe->IsUndefined()) return probe; |
| 961 StubCompiler compiler; | 944 StubCompiler compiler; |
| 962 return FillCache(isolate_, compiler.CompileCallInitialize(flags)); | 945 return FillCache(isolate_, compiler.CompileCallInitialize(flags)); |
| 963 } | 946 } |
| 964 | 947 |
| 965 | 948 |
| 966 Handle<Code> StubCache::ComputeCallInitialize(int argc, | 949 Handle<Code> StubCache::ComputeCallInitialize(int argc, |
| 967 InLoopFlag in_loop, | |
| 968 RelocInfo::Mode mode) { | 950 RelocInfo::Mode mode) { |
| 969 if (in_loop == IN_LOOP) { | |
| 970 // Force the creation of the corresponding stub outside loops, | |
| 971 // because it may be used when clearing the ICs later - it is | |
| 972 // possible for a series of IC transitions to lose the in-loop | |
| 973 // information, and the IC clearing code can't generate a stub | |
| 974 // that it needs so we need to ensure it is generated already. | |
| 975 ComputeCallInitialize(argc, NOT_IN_LOOP, mode); | |
| 976 } | |
| 977 CALL_HEAP_FUNCTION(isolate_, | 951 CALL_HEAP_FUNCTION(isolate_, |
| 978 ComputeCallInitialize(argc, in_loop, mode, Code::CALL_IC), | 952 ComputeCallInitialize(argc, mode, Code::CALL_IC), |
| 979 Code); | 953 Code); |
| 980 } | 954 } |
| 981 | 955 |
| 982 | 956 |
| 983 Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc, | 957 Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) { |
| 984 InLoopFlag in_loop) { | |
| 985 if (in_loop == IN_LOOP) { | |
| 986 // Force the creation of the corresponding stub outside loops, | |
| 987 // because it may be used when clearing the ICs later - it is | |
| 988 // possible for a series of IC transitions to lose the in-loop | |
| 989 // information, and the IC clearing code can't generate a stub | |
| 990 // that it needs so we need to ensure it is generated already. | |
| 991 ComputeKeyedCallInitialize(argc, NOT_IN_LOOP); | |
| 992 } | |
| 993 CALL_HEAP_FUNCTION( | 958 CALL_HEAP_FUNCTION( |
| 994 isolate_, | 959 isolate_, |
| 995 ComputeCallInitialize(argc, | 960 ComputeCallInitialize(argc, RelocInfo::CODE_TARGET, Code::KEYED_CALL_IC), |
| 996 in_loop, | |
| 997 RelocInfo::CODE_TARGET, | |
| 998 Code::KEYED_CALL_IC), | |
| 999 Code); | 961 Code); |
| 1000 } | 962 } |
| 1001 | 963 |
| 1002 | 964 |
| 1003 MaybeObject* StubCache::ComputeCallPreMonomorphic( | 965 MaybeObject* StubCache::ComputeCallPreMonomorphic( |
| 1004 int argc, | 966 int argc, |
| 1005 InLoopFlag in_loop, | |
| 1006 Code::Kind kind, | 967 Code::Kind kind, |
| 1007 Code::ExtraICState extra_ic_state) { | 968 Code::ExtraICState extra_ic_state) { |
| 1008 Code::Flags flags = Code::ComputeFlags(kind, | 969 Code::Flags flags = Code::ComputeFlags(kind, |
| 1009 in_loop, | |
| 1010 PREMONOMORPHIC, | 970 PREMONOMORPHIC, |
| 1011 extra_ic_state, | 971 extra_ic_state, |
| 1012 NORMAL, | 972 NORMAL, |
| 1013 argc); | 973 argc); |
| 1014 Object* probe; | 974 Object* probe; |
| 1015 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 975 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); |
| 1016 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 976 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
| 1017 } | 977 } |
| 1018 if (!probe->IsUndefined()) return probe; | 978 if (!probe->IsUndefined()) return probe; |
| 1019 StubCompiler compiler; | 979 StubCompiler compiler; |
| 1020 return FillCache(isolate_, compiler.CompileCallPreMonomorphic(flags)); | 980 return FillCache(isolate_, compiler.CompileCallPreMonomorphic(flags)); |
| 1021 } | 981 } |
| 1022 | 982 |
| 1023 | 983 |
| 1024 MaybeObject* StubCache::ComputeCallNormal(int argc, | 984 MaybeObject* StubCache::ComputeCallNormal(int argc, |
| 1025 InLoopFlag in_loop, | |
| 1026 Code::Kind kind, | 985 Code::Kind kind, |
| 1027 Code::ExtraICState extra_ic_state) { | 986 Code::ExtraICState extra_ic_state) { |
| 1028 Code::Flags flags = Code::ComputeFlags(kind, | 987 Code::Flags flags = Code::ComputeFlags(kind, |
| 1029 in_loop, | |
| 1030 MONOMORPHIC, | 988 MONOMORPHIC, |
| 1031 extra_ic_state, | 989 extra_ic_state, |
| 1032 NORMAL, | 990 NORMAL, |
| 1033 argc); | 991 argc); |
| 1034 Object* probe; | 992 Object* probe; |
| 1035 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 993 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); |
| 1036 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 994 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
| 1037 } | 995 } |
| 1038 if (!probe->IsUndefined()) return probe; | 996 if (!probe->IsUndefined()) return probe; |
| 1039 StubCompiler compiler; | 997 StubCompiler compiler; |
| 1040 return FillCache(isolate_, compiler.CompileCallNormal(flags)); | 998 return FillCache(isolate_, compiler.CompileCallNormal(flags)); |
| 1041 } | 999 } |
| 1042 | 1000 |
| 1043 | 1001 |
| 1044 MaybeObject* StubCache::ComputeCallArguments(int argc, | 1002 MaybeObject* StubCache::ComputeCallArguments(int argc, Code::Kind kind) { |
| 1045 InLoopFlag in_loop, | |
| 1046 Code::Kind kind) { | |
| 1047 ASSERT(kind == Code::KEYED_CALL_IC); | 1003 ASSERT(kind == Code::KEYED_CALL_IC); |
| 1048 Code::Flags flags = Code::ComputeFlags(kind, | 1004 Code::Flags flags = Code::ComputeFlags(kind, |
| 1049 in_loop, | |
| 1050 MEGAMORPHIC, | 1005 MEGAMORPHIC, |
| 1051 Code::kNoExtraICState, | 1006 Code::kNoExtraICState, |
| 1052 NORMAL, | 1007 NORMAL, |
| 1053 argc); | 1008 argc); |
| 1054 Object* probe; | 1009 Object* probe; |
| 1055 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 1010 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); |
| 1056 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 1011 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
| 1057 } | 1012 } |
| 1058 if (!probe->IsUndefined()) return probe; | 1013 if (!probe->IsUndefined()) return probe; |
| 1059 StubCompiler compiler; | 1014 StubCompiler compiler; |
| 1060 return FillCache(isolate_, compiler.CompileCallArguments(flags)); | 1015 return FillCache(isolate_, compiler.CompileCallArguments(flags)); |
| 1061 } | 1016 } |
| 1062 | 1017 |
| 1063 | 1018 |
| 1064 MaybeObject* StubCache::ComputeCallMegamorphic( | 1019 MaybeObject* StubCache::ComputeCallMegamorphic( |
| 1065 int argc, | 1020 int argc, |
| 1066 InLoopFlag in_loop, | |
| 1067 Code::Kind kind, | 1021 Code::Kind kind, |
| 1068 Code::ExtraICState extra_ic_state) { | 1022 Code::ExtraICState extra_ic_state) { |
| 1069 Code::Flags flags = Code::ComputeFlags(kind, | 1023 Code::Flags flags = Code::ComputeFlags(kind, |
| 1070 in_loop, | |
| 1071 MEGAMORPHIC, | 1024 MEGAMORPHIC, |
| 1072 extra_ic_state, | 1025 extra_ic_state, |
| 1073 NORMAL, | 1026 NORMAL, |
| 1074 argc); | 1027 argc); |
| 1075 Object* probe; | 1028 Object* probe; |
| 1076 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 1029 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); |
| 1077 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 1030 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
| 1078 } | 1031 } |
| 1079 if (!probe->IsUndefined()) return probe; | 1032 if (!probe->IsUndefined()) return probe; |
| 1080 StubCompiler compiler; | 1033 StubCompiler compiler; |
| 1081 return FillCache(isolate_, compiler.CompileCallMegamorphic(flags)); | 1034 return FillCache(isolate_, compiler.CompileCallMegamorphic(flags)); |
| 1082 } | 1035 } |
| 1083 | 1036 |
| 1084 | 1037 |
| 1085 MaybeObject* StubCache::ComputeCallMiss(int argc, | 1038 MaybeObject* StubCache::ComputeCallMiss(int argc, |
| 1086 Code::Kind kind, | 1039 Code::Kind kind, |
| 1087 Code::ExtraICState extra_ic_state) { | 1040 Code::ExtraICState extra_ic_state) { |
| 1088 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs | 1041 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs |
| 1089 // and monomorphic stubs are not mixed up together in the stub cache. | 1042 // and monomorphic stubs are not mixed up together in the stub cache. |
| 1090 Code::Flags flags = Code::ComputeFlags(kind, | 1043 Code::Flags flags = Code::ComputeFlags(kind, |
| 1091 NOT_IN_LOOP, | |
| 1092 MONOMORPHIC_PROTOTYPE_FAILURE, | 1044 MONOMORPHIC_PROTOTYPE_FAILURE, |
| 1093 extra_ic_state, | 1045 extra_ic_state, |
| 1094 NORMAL, | 1046 NORMAL, |
| 1095 argc, | 1047 argc, |
| 1096 OWN_MAP); | 1048 OWN_MAP); |
| 1097 Object* probe; | 1049 Object* probe; |
| 1098 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 1050 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); |
| 1099 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 1051 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
| 1100 } | 1052 } |
| 1101 if (!probe->IsUndefined()) return probe; | 1053 if (!probe->IsUndefined()) return probe; |
| 1102 StubCompiler compiler; | 1054 StubCompiler compiler; |
| 1103 return FillCache(isolate_, compiler.CompileCallMiss(flags)); | 1055 return FillCache(isolate_, compiler.CompileCallMiss(flags)); |
| 1104 } | 1056 } |
| 1105 | 1057 |
| 1106 | 1058 |
| 1107 #ifdef ENABLE_DEBUGGER_SUPPORT | 1059 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 1108 MaybeObject* StubCache::ComputeCallDebugBreak( | 1060 MaybeObject* StubCache::ComputeCallDebugBreak( |
| 1109 int argc, | 1061 int argc, |
| 1110 Code::Kind kind) { | 1062 Code::Kind kind) { |
| 1111 // Extra IC state is irrelevant for debug break ICs. They jump to | 1063 // Extra IC state is irrelevant for debug break ICs. They jump to |
| 1112 // the actual call ic to carry out the work. | 1064 // the actual call ic to carry out the work. |
| 1113 Code::Flags flags = Code::ComputeFlags(kind, | 1065 Code::Flags flags = Code::ComputeFlags(kind, |
| 1114 NOT_IN_LOOP, | |
| 1115 DEBUG_BREAK, | 1066 DEBUG_BREAK, |
| 1116 Code::kNoExtraICState, | 1067 Code::kNoExtraICState, |
| 1117 NORMAL, | 1068 NORMAL, |
| 1118 argc); | 1069 argc); |
| 1119 Object* probe; | 1070 Object* probe; |
| 1120 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 1071 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); |
| 1121 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 1072 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
| 1122 } | 1073 } |
| 1123 if (!probe->IsUndefined()) return probe; | 1074 if (!probe->IsUndefined()) return probe; |
| 1124 StubCompiler compiler; | 1075 StubCompiler compiler; |
| 1125 return FillCache(isolate_, compiler.CompileCallDebugBreak(flags)); | 1076 return FillCache(isolate_, compiler.CompileCallDebugBreak(flags)); |
| 1126 } | 1077 } |
| 1127 | 1078 |
| 1128 | 1079 |
| 1129 MaybeObject* StubCache::ComputeCallDebugPrepareStepIn( | 1080 MaybeObject* StubCache::ComputeCallDebugPrepareStepIn( |
| 1130 int argc, | 1081 int argc, |
| 1131 Code::Kind kind) { | 1082 Code::Kind kind) { |
| 1132 // Extra IC state is irrelevant for debug break ICs. They jump to | 1083 // Extra IC state is irrelevant for debug break ICs. They jump to |
| 1133 // the actual call ic to carry out the work. | 1084 // the actual call ic to carry out the work. |
| 1134 Code::Flags flags = Code::ComputeFlags(kind, | 1085 Code::Flags flags = Code::ComputeFlags(kind, |
| 1135 NOT_IN_LOOP, | |
| 1136 DEBUG_PREPARE_STEP_IN, | 1086 DEBUG_PREPARE_STEP_IN, |
| 1137 Code::kNoExtraICState, | 1087 Code::kNoExtraICState, |
| 1138 NORMAL, | 1088 NORMAL, |
| 1139 argc); | 1089 argc); |
| 1140 Object* probe; | 1090 Object* probe; |
| 1141 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 1091 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); |
| 1142 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 1092 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
| 1143 } | 1093 } |
| 1144 if (!probe->IsUndefined()) return probe; | 1094 if (!probe->IsUndefined()) return probe; |
| 1145 StubCompiler compiler; | 1095 StubCompiler compiler; |
| (...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1665 Code::cast(result->ToObjectUnchecked()))); | 1615 Code::cast(result->ToObjectUnchecked()))); |
| 1666 } | 1616 } |
| 1667 return result; | 1617 return result; |
| 1668 } | 1618 } |
| 1669 | 1619 |
| 1670 | 1620 |
| 1671 MaybeObject* KeyedLoadStubCompiler::GetCode(PropertyType type, | 1621 MaybeObject* KeyedLoadStubCompiler::GetCode(PropertyType type, |
| 1672 String* name, | 1622 String* name, |
| 1673 InlineCacheState state) { | 1623 InlineCacheState state) { |
| 1674 Code::Flags flags = Code::ComputeFlags( | 1624 Code::Flags flags = Code::ComputeFlags( |
| 1675 Code::KEYED_LOAD_IC, NOT_IN_LOOP, state, Code::kNoExtraICState, type); | 1625 Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type); |
| 1676 MaybeObject* result = GetCodeWithFlags(flags, name); | 1626 MaybeObject* result = GetCodeWithFlags(flags, name); |
| 1677 if (!result->IsFailure()) { | 1627 if (!result->IsFailure()) { |
| 1678 PROFILE(isolate(), | 1628 PROFILE(isolate(), |
| 1679 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, | 1629 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, |
| 1680 Code::cast(result->ToObjectUnchecked()), | 1630 Code::cast(result->ToObjectUnchecked()), |
| 1681 name)); | 1631 name)); |
| 1682 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, | 1632 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, |
| 1683 name, | 1633 name, |
| 1684 Code::cast(result->ToObjectUnchecked()))); | 1634 Code::cast(result->ToObjectUnchecked()))); |
| 1685 } | 1635 } |
| 1686 return result; | 1636 return result; |
| 1687 } | 1637 } |
| 1688 | 1638 |
| 1689 | 1639 |
| 1690 MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) { | 1640 MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) { |
| 1691 Code::Flags flags = Code::ComputeMonomorphicFlags( | 1641 Code::Flags flags = |
| 1692 Code::STORE_IC, type, strict_mode_); | 1642 Code::ComputeMonomorphicFlags(Code::STORE_IC, type, strict_mode_); |
| 1693 MaybeObject* result = GetCodeWithFlags(flags, name); | 1643 MaybeObject* result = GetCodeWithFlags(flags, name); |
| 1694 if (!result->IsFailure()) { | 1644 if (!result->IsFailure()) { |
| 1695 PROFILE(isolate(), | 1645 PROFILE(isolate(), |
| 1696 CodeCreateEvent(Logger::STORE_IC_TAG, | 1646 CodeCreateEvent(Logger::STORE_IC_TAG, |
| 1697 Code::cast(result->ToObjectUnchecked()), | 1647 Code::cast(result->ToObjectUnchecked()), |
| 1698 name)); | 1648 name)); |
| 1699 GDBJIT(AddCode(GDBJITInterface::STORE_IC, | 1649 GDBJIT(AddCode(GDBJITInterface::STORE_IC, |
| 1700 name, | 1650 name, |
| 1701 Code::cast(result->ToObjectUnchecked()))); | 1651 Code::cast(result->ToObjectUnchecked()))); |
| 1702 } | 1652 } |
| 1703 return result; | 1653 return result; |
| 1704 } | 1654 } |
| 1705 | 1655 |
| 1706 | 1656 |
| 1707 MaybeObject* KeyedStoreStubCompiler::GetCode(PropertyType type, | 1657 MaybeObject* KeyedStoreStubCompiler::GetCode(PropertyType type, |
| 1708 String* name, | 1658 String* name, |
| 1709 InlineCacheState state) { | 1659 InlineCacheState state) { |
| 1710 Code::Flags flags = Code::ComputeFlags( | 1660 Code::Flags flags = |
| 1711 Code::KEYED_STORE_IC, NOT_IN_LOOP, state, strict_mode_, type); | 1661 Code::ComputeFlags(Code::KEYED_STORE_IC, state, strict_mode_, type); |
| 1712 MaybeObject* result = GetCodeWithFlags(flags, name); | 1662 MaybeObject* result = GetCodeWithFlags(flags, name); |
| 1713 if (!result->IsFailure()) { | 1663 if (!result->IsFailure()) { |
| 1714 PROFILE(isolate(), | 1664 PROFILE(isolate(), |
| 1715 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, | 1665 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, |
| 1716 Code::cast(result->ToObjectUnchecked()), | 1666 Code::cast(result->ToObjectUnchecked()), |
| 1717 name)); | 1667 name)); |
| 1718 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, | 1668 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, |
| 1719 name, | 1669 name, |
| 1720 Code::cast(result->ToObjectUnchecked()))); | 1670 Code::cast(result->ToObjectUnchecked()))); |
| 1721 } | 1671 } |
| 1722 return result; | 1672 return result; |
| 1723 } | 1673 } |
| 1724 | 1674 |
| 1725 | 1675 |
| 1726 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( | 1676 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( |
| 1727 MacroAssembler* masm) { | 1677 MacroAssembler* masm) { |
| 1728 KeyedStoreIC::GenerateSlow(masm); | 1678 KeyedStoreIC::GenerateSlow(masm); |
| 1729 } | 1679 } |
| 1730 | 1680 |
| 1731 | 1681 |
| 1732 CallStubCompiler::CallStubCompiler(int argc, | 1682 CallStubCompiler::CallStubCompiler(int argc, |
| 1733 InLoopFlag in_loop, | |
| 1734 Code::Kind kind, | 1683 Code::Kind kind, |
| 1735 Code::ExtraICState extra_ic_state, | 1684 Code::ExtraICState extra_ic_state, |
| 1736 InlineCacheHolderFlag cache_holder) | 1685 InlineCacheHolderFlag cache_holder) |
| 1737 : arguments_(argc), | 1686 : arguments_(argc), |
| 1738 in_loop_(in_loop), | |
| 1739 kind_(kind), | 1687 kind_(kind), |
| 1740 extra_ic_state_(extra_ic_state), | 1688 extra_ic_state_(extra_ic_state), |
| 1741 cache_holder_(cache_holder) { | 1689 cache_holder_(cache_holder) { |
| 1742 } | 1690 } |
| 1743 | 1691 |
| 1744 | 1692 |
| 1745 bool CallStubCompiler::HasCustomCallGenerator(JSFunction* function) { | 1693 bool CallStubCompiler::HasCustomCallGenerator(JSFunction* function) { |
| 1746 SharedFunctionInfo* info = function->shared(); | 1694 SharedFunctionInfo* info = function->shared(); |
| 1747 if (info->HasBuiltinFunctionId()) { | 1695 if (info->HasBuiltinFunctionId()) { |
| 1748 BuiltinFunctionId id = info->builtin_function_id(); | 1696 BuiltinFunctionId id = info->builtin_function_id(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1789 fname); | 1737 fname); |
| 1790 } | 1738 } |
| 1791 | 1739 |
| 1792 | 1740 |
| 1793 MaybeObject* CallStubCompiler::GetCode(PropertyType type, String* name) { | 1741 MaybeObject* CallStubCompiler::GetCode(PropertyType type, String* name) { |
| 1794 int argc = arguments_.immediate(); | 1742 int argc = arguments_.immediate(); |
| 1795 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, | 1743 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, |
| 1796 type, | 1744 type, |
| 1797 extra_ic_state_, | 1745 extra_ic_state_, |
| 1798 cache_holder_, | 1746 cache_holder_, |
| 1799 in_loop_, | |
| 1800 argc); | 1747 argc); |
| 1801 return GetCodeWithFlags(flags, name); | 1748 return GetCodeWithFlags(flags, name); |
| 1802 } | 1749 } |
| 1803 | 1750 |
| 1804 | 1751 |
| 1805 MaybeObject* CallStubCompiler::GetCode(JSFunction* function) { | 1752 MaybeObject* CallStubCompiler::GetCode(JSFunction* function) { |
| 1806 String* function_name = NULL; | 1753 String* function_name = NULL; |
| 1807 if (function->shared()->name()->IsString()) { | 1754 if (function->shared()->name()->IsString()) { |
| 1808 function_name = String::cast(function->shared()->name()); | 1755 function_name = String::cast(function->shared()->name()); |
| 1809 } | 1756 } |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1886 expected_receiver_type_ = | 1833 expected_receiver_type_ = |
| 1887 FunctionTemplateInfo::cast(signature->receiver()); | 1834 FunctionTemplateInfo::cast(signature->receiver()); |
| 1888 } | 1835 } |
| 1889 } | 1836 } |
| 1890 | 1837 |
| 1891 is_simple_api_call_ = true; | 1838 is_simple_api_call_ = true; |
| 1892 } | 1839 } |
| 1893 | 1840 |
| 1894 | 1841 |
| 1895 } } // namespace v8::internal | 1842 } } // namespace v8::internal |
| OLD | NEW |