OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
9 #include "src/ast.h" | 9 #include "src/ast.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 if (current_map->prototype()->IsNull()) break; | 196 if (current_map->prototype()->IsNull()) break; |
197 last = handle(JSObject::cast(current_map->prototype())); | 197 last = handle(JSObject::cast(current_map->prototype())); |
198 current_map = handle(last->map()); | 198 current_map = handle(last->map()); |
199 } | 199 } |
200 // Compile the stub that is either shared for all names or | 200 // Compile the stub that is either shared for all names or |
201 // name specific if there are global objects involved. | 201 // name specific if there are global objects involved. |
202 Handle<Code> handler = PropertyHandlerCompiler::Find( | 202 Handle<Code> handler = PropertyHandlerCompiler::Find( |
203 cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST); | 203 cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST); |
204 if (!handler.is_null()) return handler; | 204 if (!handler.is_null()) return handler; |
205 | 205 |
206 NamedLoadHandlerCompiler compiler(isolate, type, flag); | 206 NamedLoadHandlerCompiler compiler(isolate, type, last, flag); |
207 handler = compiler.CompileLoadNonexistent(last, cache_name); | 207 handler = compiler.CompileLoadNonexistent(cache_name); |
208 Map::UpdateCodeCache(stub_holder_map, cache_name, handler); | 208 Map::UpdateCodeCache(stub_holder_map, cache_name, handler); |
209 return handler; | 209 return handler; |
210 } | 210 } |
211 | 211 |
212 | 212 |
213 Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphic( | 213 Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphic( |
214 Handle<Map> receiver_map) { | 214 Handle<Map> receiver_map) { |
215 Isolate* isolate = receiver_map->GetIsolate(); | 215 Isolate* isolate = receiver_map->GetIsolate(); |
216 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); | 216 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); |
217 Handle<Name> name = isolate->factory()->KeyedLoadMonomorphic_string(); | 217 Handle<Name> name = isolate->factory()->KeyedLoadMonomorphic_string(); |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 return (FLAG_print_code_stubs && !name.is_null() && name->IsString()) | 742 return (FLAG_print_code_stubs && !name.is_null() && name->IsString()) |
743 ? GetCodeWithFlags(flags, Handle<String>::cast(name)->ToCString().get()) | 743 ? GetCodeWithFlags(flags, Handle<String>::cast(name)->ToCString().get()) |
744 : GetCodeWithFlags(flags, NULL); | 744 : GetCodeWithFlags(flags, NULL); |
745 } | 745 } |
746 | 746 |
747 | 747 |
748 #define __ ACCESS_MASM(masm()) | 748 #define __ ACCESS_MASM(masm()) |
749 | 749 |
750 | 750 |
751 Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg, | 751 Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg, |
752 Handle<JSObject> holder, | |
753 Handle<Name> name, | 752 Handle<Name> name, |
754 Label* miss) { | 753 Label* miss) { |
755 PrototypeCheckType check_type = CHECK_ALL_MAPS; | 754 PrototypeCheckType check_type = CHECK_ALL_MAPS; |
756 int function_index = -1; | 755 int function_index = -1; |
757 if (type()->Is(HeapType::String())) { | 756 if (type()->Is(HeapType::String())) { |
758 function_index = Context::STRING_FUNCTION_INDEX; | 757 function_index = Context::STRING_FUNCTION_INDEX; |
759 } else if (type()->Is(HeapType::Symbol())) { | 758 } else if (type()->Is(HeapType::Symbol())) { |
760 function_index = Context::SYMBOL_FUNCTION_INDEX; | 759 function_index = Context::SYMBOL_FUNCTION_INDEX; |
761 } else if (type()->Is(HeapType::Number())) { | 760 } else if (type()->Is(HeapType::Number())) { |
762 function_index = Context::NUMBER_FUNCTION_INDEX; | 761 function_index = Context::NUMBER_FUNCTION_INDEX; |
763 } else if (type()->Is(HeapType::Boolean())) { | 762 } else if (type()->Is(HeapType::Boolean())) { |
764 function_index = Context::BOOLEAN_FUNCTION_INDEX; | 763 function_index = Context::BOOLEAN_FUNCTION_INDEX; |
765 } else { | 764 } else { |
766 check_type = SKIP_RECEIVER; | 765 check_type = SKIP_RECEIVER; |
767 } | 766 } |
768 | 767 |
769 if (check_type == CHECK_ALL_MAPS) { | 768 if (check_type == CHECK_ALL_MAPS) { |
770 GenerateDirectLoadGlobalFunctionPrototype( | 769 GenerateDirectLoadGlobalFunctionPrototype( |
771 masm(), function_index, scratch1(), miss); | 770 masm(), function_index, scratch1(), miss); |
772 Object* function = isolate()->native_context()->get(function_index); | 771 Object* function = isolate()->native_context()->get(function_index); |
773 Object* prototype = JSFunction::cast(function)->instance_prototype(); | 772 Object* prototype = JSFunction::cast(function)->instance_prototype(); |
774 set_type_for_object(handle(prototype, isolate())); | 773 set_type_for_object(handle(prototype, isolate())); |
775 object_reg = scratch1(); | 774 object_reg = scratch1(); |
776 } | 775 } |
777 | 776 |
778 // Check that the maps starting from the prototype haven't changed. | 777 // Check that the maps starting from the prototype haven't changed. |
779 return CheckPrototypes(object_reg, holder, scratch1(), scratch2(), scratch3(), | 778 return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name, |
780 name, miss, check_type); | 779 miss, check_type); |
781 } | 780 } |
782 | 781 |
783 | 782 |
784 // Frontend for store uses the name register. It has to be restored before a | 783 // Frontend for store uses the name register. It has to be restored before a |
785 // miss. | 784 // miss. |
786 Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg, | 785 Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg, |
787 Handle<JSObject> holder, | |
788 Handle<Name> name, | 786 Handle<Name> name, |
789 Label* miss) { | 787 Label* miss) { |
790 return CheckPrototypes(object_reg, holder, this->name(), scratch1(), | 788 return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name, |
791 scratch2(), name, miss, SKIP_RECEIVER); | 789 miss, SKIP_RECEIVER); |
792 } | 790 } |
793 | 791 |
794 | 792 |
795 bool PropertyICCompiler::IncludesNumberType(TypeHandleList* types) { | 793 bool PropertyICCompiler::IncludesNumberType(TypeHandleList* types) { |
796 for (int i = 0; i < types->length(); ++i) { | 794 for (int i = 0; i < types->length(); ++i) { |
797 if (types->at(i)->Is(HeapType::Number())) return true; | 795 if (types->at(i)->Is(HeapType::Number())) return true; |
798 } | 796 } |
799 return false; | 797 return false; |
800 } | 798 } |
801 | 799 |
802 | 800 |
803 Register PropertyHandlerCompiler::Frontend(Register object_reg, | 801 Register PropertyHandlerCompiler::Frontend(Register object_reg, |
804 Handle<JSObject> holder, | |
805 Handle<Name> name) { | 802 Handle<Name> name) { |
806 Label miss; | 803 Label miss; |
807 Register reg = FrontendHeader(object_reg, holder, name, &miss); | 804 Register reg = FrontendHeader(object_reg, name, &miss); |
808 FrontendFooter(name, &miss); | 805 FrontendFooter(name, &miss); |
809 return reg; | 806 return reg; |
810 } | 807 } |
811 | 808 |
812 | 809 |
813 void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<JSObject> last, | 810 void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<Name> name) { |
814 Handle<Name> name) { | |
815 Label miss; | 811 Label miss; |
816 | 812 |
817 Register holder; | 813 Register holder_reg; |
818 Handle<Map> last_map; | 814 Handle<Map> last_map; |
819 if (last.is_null()) { | 815 if (holder().is_null()) { |
820 holder = receiver(); | 816 holder_reg = receiver(); |
821 last_map = IC::TypeToMap(*type(), isolate()); | 817 last_map = IC::TypeToMap(*type(), isolate()); |
822 // If |type| has null as its prototype, |last| is Handle<JSObject>::null(). | 818 // If |type| has null as its prototype, |holder()| is |
| 819 // Handle<JSObject>::null(). |
823 ASSERT(last_map->prototype() == isolate()->heap()->null_value()); | 820 ASSERT(last_map->prototype() == isolate()->heap()->null_value()); |
824 } else { | 821 } else { |
825 holder = FrontendHeader(receiver(), last, name, &miss); | 822 holder_reg = FrontendHeader(receiver(), name, &miss); |
826 last_map = handle(last->map()); | 823 last_map = handle(holder()->map()); |
827 } | 824 } |
828 | 825 |
829 if (last_map->is_dictionary_map() && | 826 if (last_map->is_dictionary_map() && !last_map->IsJSGlobalObjectMap()) { |
830 !last_map->IsJSGlobalObjectMap() && | |
831 !last_map->IsJSGlobalProxyMap()) { | |
832 if (!name->IsUniqueName()) { | 827 if (!name->IsUniqueName()) { |
833 ASSERT(name->IsString()); | 828 ASSERT(name->IsString()); |
834 name = factory()->InternalizeString(Handle<String>::cast(name)); | 829 name = factory()->InternalizeString(Handle<String>::cast(name)); |
835 } | 830 } |
836 ASSERT(last.is_null() || | 831 ASSERT(holder().is_null() || |
837 last->property_dictionary()->FindEntry(name) == | 832 holder()->property_dictionary()->FindEntry(name) == |
838 NameDictionary::kNotFound); | 833 NameDictionary::kNotFound); |
839 GenerateDictionaryNegativeLookup(masm(), &miss, holder, name, | 834 GenerateDictionaryNegativeLookup(masm(), &miss, holder_reg, name, |
840 scratch2(), scratch3()); | 835 scratch2(), scratch3()); |
841 } | 836 } |
842 | 837 |
843 // If the last object in the prototype chain is a global object, | 838 // If the last object in the prototype chain is a global object, |
844 // check that the global property cell is empty. | 839 // check that the global property cell is empty. |
845 if (last_map->IsJSGlobalObjectMap()) { | 840 if (last_map->IsJSGlobalObjectMap()) { |
846 Handle<JSGlobalObject> global = | 841 Handle<JSGlobalObject> global = |
847 last.is_null() | 842 holder().is_null() |
848 ? Handle<JSGlobalObject>::cast(type()->AsConstant()->Value()) | 843 ? Handle<JSGlobalObject>::cast(type()->AsConstant()->Value()) |
849 : Handle<JSGlobalObject>::cast(last); | 844 : Handle<JSGlobalObject>::cast(holder()); |
850 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 845 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
851 } | 846 } |
852 | 847 |
853 FrontendFooter(name, &miss); | 848 FrontendFooter(name, &miss); |
854 } | 849 } |
855 | 850 |
856 | 851 |
857 Handle<Code> NamedLoadHandlerCompiler::CompileLoadField( | 852 Handle<Code> NamedLoadHandlerCompiler::CompileLoadField( |
858 Handle<JSObject> holder, Handle<Name> name, FieldIndex field, | 853 Handle<Name> name, FieldIndex field, Representation representation) { |
859 Representation representation) { | 854 Register reg = Frontend(receiver(), name); |
860 Register reg = Frontend(receiver(), holder, name); | 855 GenerateLoadField(reg, field, representation); |
861 GenerateLoadField(reg, holder, field, representation); | |
862 return GetCode(kind(), Code::FAST, name); | 856 return GetCode(kind(), Code::FAST, name); |
863 } | 857 } |
864 | 858 |
865 | 859 |
866 Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant( | 860 Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant( |
867 Handle<JSObject> holder, Handle<Name> name, Handle<Object> value) { | 861 Handle<Name> name, Handle<Object> value) { |
868 Frontend(receiver(), holder, name); | 862 Frontend(receiver(), name); |
869 GenerateLoadConstant(value); | 863 GenerateLoadConstant(value); |
870 return GetCode(kind(), Code::FAST, name); | 864 return GetCode(kind(), Code::FAST, name); |
871 } | 865 } |
872 | 866 |
873 | 867 |
874 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( | 868 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( |
875 Handle<JSObject> holder, Handle<Name> name, | 869 Handle<Name> name, Handle<ExecutableAccessorInfo> callback) { |
876 Handle<ExecutableAccessorInfo> callback) { | 870 Register reg = CallbackFrontend(receiver(), name, callback); |
877 Register reg = CallbackFrontend(receiver(), holder, name, callback); | |
878 GenerateLoadCallback(reg, callback); | 871 GenerateLoadCallback(reg, callback); |
879 return GetCode(kind(), Code::FAST, name); | 872 return GetCode(kind(), Code::FAST, name); |
880 } | 873 } |
881 | 874 |
882 | 875 |
883 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( | 876 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( |
884 Handle<JSObject> holder, Handle<Name> name, | 877 Handle<Name> name, const CallOptimization& call_optimization) { |
885 const CallOptimization& call_optimization) { | |
886 ASSERT(call_optimization.is_simple_api_call()); | 878 ASSERT(call_optimization.is_simple_api_call()); |
887 Handle<JSFunction> callback = call_optimization.constant_function(); | 879 Handle<JSFunction> callback = call_optimization.constant_function(); |
888 CallbackFrontend(receiver(), holder, name, callback); | 880 CallbackFrontend(receiver(), name, callback); |
889 Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate()); | 881 Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate()); |
890 GenerateFastApiCall( | 882 GenerateFastApiCall( |
891 masm(), call_optimization, receiver_map, | 883 masm(), call_optimization, receiver_map, |
892 receiver(), scratch1(), false, 0, NULL); | 884 receiver(), scratch1(), false, 0, NULL); |
893 return GetCode(kind(), Code::FAST, name); | 885 return GetCode(kind(), Code::FAST, name); |
894 } | 886 } |
895 | 887 |
896 | 888 |
897 Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor( | 889 Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor( |
898 Handle<JSObject> holder, Handle<Name> name) { | 890 Handle<Name> name) { |
899 // Perform a lookup after the interceptor. | 891 // Perform a lookup after the interceptor. |
900 LookupResult lookup(isolate()); | 892 LookupResult lookup(isolate()); |
901 holder->LookupOwnRealNamedProperty(name, &lookup); | 893 holder()->LookupOwnRealNamedProperty(name, &lookup); |
902 if (!lookup.IsFound()) { | 894 if (!lookup.IsFound()) { |
903 PrototypeIterator iter(holder->GetIsolate(), holder); | 895 PrototypeIterator iter(holder()->GetIsolate(), holder()); |
904 if (!iter.IsAtEnd()) { | 896 if (!iter.IsAtEnd()) { |
905 PrototypeIterator::GetCurrent(iter)->Lookup(name, &lookup); | 897 PrototypeIterator::GetCurrent(iter)->Lookup(name, &lookup); |
906 } | 898 } |
907 } | 899 } |
908 | 900 |
909 Register reg = Frontend(receiver(), holder, name); | 901 Register reg = Frontend(receiver(), name); |
910 // TODO(368): Compile in the whole chain: all the interceptors in | 902 // TODO(368): Compile in the whole chain: all the interceptors in |
911 // prototypes and ultimate answer. | 903 // prototypes and ultimate answer. |
912 GenerateLoadInterceptor(reg, holder, &lookup, name); | 904 GenerateLoadInterceptor(reg, &lookup, name); |
913 return GetCode(kind(), Code::FAST, name); | 905 return GetCode(kind(), Code::FAST, name); |
914 } | 906 } |
915 | 907 |
916 | 908 |
917 void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( | 909 void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( |
918 Register interceptor_reg, Handle<JSObject> interceptor_holder, | 910 Register interceptor_reg, Handle<Name> name, LookupResult* lookup) { |
919 Handle<Name> name, LookupResult* lookup) { | 911 Handle<JSObject> real_named_property_holder(lookup->holder()); |
920 Handle<JSObject> holder(lookup->holder()); | |
921 if (lookup->IsField()) { | 912 if (lookup->IsField()) { |
922 FieldIndex field = lookup->GetFieldIndex(); | 913 FieldIndex field = lookup->GetFieldIndex(); |
923 if (interceptor_holder.is_identical_to(holder)) { | 914 if (holder().is_identical_to(real_named_property_holder)) { |
924 GenerateLoadField( | 915 GenerateLoadField(interceptor_reg, field, lookup->representation()); |
925 interceptor_reg, holder, field, lookup->representation()); | |
926 } else { | 916 } else { |
927 // We found FIELD property in prototype chain of interceptor's holder. | 917 set_type_for_object(holder()); |
928 // Retrieve a field from field's holder. | 918 set_holder(real_named_property_holder); |
929 set_type_for_object(interceptor_holder); | 919 Register reg = Frontend(interceptor_reg, name); |
930 Register reg = Frontend(interceptor_reg, holder, name); | 920 GenerateLoadField(reg, field, lookup->representation()); |
931 GenerateLoadField( | |
932 reg, holder, field, lookup->representation()); | |
933 } | 921 } |
934 } else { | 922 } else { |
935 // We found CALLBACKS property in prototype chain of interceptor's | 923 // We found CALLBACKS property in prototype chain of interceptor's holder. |
936 // holder. | |
937 ASSERT(lookup->type() == CALLBACKS); | 924 ASSERT(lookup->type() == CALLBACKS); |
938 Handle<ExecutableAccessorInfo> callback( | 925 Handle<ExecutableAccessorInfo> callback( |
939 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 926 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
940 ASSERT(callback->getter() != NULL); | 927 ASSERT(callback->getter() != NULL); |
941 | 928 |
942 set_type_for_object(interceptor_holder); | 929 set_type_for_object(holder()); |
943 Register reg = CallbackFrontend(interceptor_reg, holder, name, callback); | 930 set_holder(real_named_property_holder); |
| 931 Register reg = CallbackFrontend(interceptor_reg, name, callback); |
944 GenerateLoadCallback(reg, callback); | 932 GenerateLoadCallback(reg, callback); |
945 } | 933 } |
946 } | 934 } |
947 | 935 |
948 | 936 |
949 Handle<Code> PropertyICCompiler::CompileMonomorphic(Handle<HeapType> type, | 937 Handle<Code> PropertyICCompiler::CompileMonomorphic(Handle<HeapType> type, |
950 Handle<Code> handler, | 938 Handle<Code> handler, |
951 Handle<Name> name, | 939 Handle<Name> name, |
952 IcCheckType check) { | 940 IcCheckType check) { |
953 TypeHandleList types(1); | 941 TypeHandleList types(1); |
954 CodeHandleList handlers(1); | 942 CodeHandleList handlers(1); |
955 types.Add(type); | 943 types.Add(type); |
956 handlers.Add(handler); | 944 handlers.Add(handler); |
957 Code::StubType stub_type = handler->type(); | 945 Code::StubType stub_type = handler->type(); |
958 return CompilePolymorphic(&types, &handlers, name, stub_type, check); | 946 return CompilePolymorphic(&types, &handlers, name, stub_type, check); |
959 } | 947 } |
960 | 948 |
961 | 949 |
962 Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter( | 950 Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter( |
963 Handle<JSObject> holder, Handle<Name> name, Handle<JSFunction> getter) { | 951 Handle<Name> name, Handle<JSFunction> getter) { |
964 Frontend(receiver(), holder, name); | 952 Frontend(receiver(), name); |
965 GenerateLoadViaGetter(masm(), type(), receiver(), getter); | 953 GenerateLoadViaGetter(masm(), type(), receiver(), getter); |
966 return GetCode(kind(), Code::FAST, name); | 954 return GetCode(kind(), Code::FAST, name); |
967 } | 955 } |
968 | 956 |
969 | 957 |
| 958 // TODO(verwaest): Cleanup. holder() is actually the receiver. |
970 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( | 959 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( |
971 Handle<JSObject> object, LookupResult* lookup, Handle<Map> transition, | 960 LookupResult* lookup, Handle<Map> transition, Handle<Name> name) { |
972 Handle<Name> name) { | |
973 Label miss, slow; | 961 Label miss, slow; |
974 | 962 |
975 // Ensure no transitions to deprecated maps are followed. | 963 // Ensure no transitions to deprecated maps are followed. |
976 __ CheckMapDeprecated(transition, scratch1(), &miss); | 964 __ CheckMapDeprecated(transition, scratch1(), &miss); |
977 | 965 |
978 // Check that we are allowed to write this. | 966 // Check that we are allowed to write this. |
979 PrototypeIterator iter(object->GetIsolate(), object); | 967 bool is_nonexistent = holder()->map() == transition->GetBackPointer(); |
980 if (!iter.IsAtEnd()) { | 968 if (is_nonexistent) { |
981 Handle<JSObject> holder; | 969 // Find the top object. |
982 // holder == object indicates that no property was found. | 970 Handle<JSObject> last; |
983 if (lookup->holder() != *object) { | 971 PrototypeIterator iter(isolate(), holder()); |
984 holder = Handle<JSObject>(lookup->holder()); | 972 do { |
985 } else { | 973 last = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
986 // Find the top object. | 974 iter.Advance(); |
987 do { | 975 } while (!iter.IsAtEnd()); |
988 holder = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 976 set_holder(last); |
989 iter.Advance(); | 977 } |
990 } while (!iter.IsAtEnd()); | |
991 } | |
992 | 978 |
993 Register holder_reg = FrontendHeader(receiver(), holder, name, &miss); | 979 Register holder_reg = FrontendHeader(receiver(), name, &miss); |
994 | 980 |
995 // If no property was found, and the holder (the last object in the | 981 // If no property was found, and the holder (the last object in the |
996 // prototype chain) is in slow mode, we need to do a negative lookup on the | 982 // prototype chain) is in slow mode, we need to do a negative lookup on the |
997 // holder. | 983 // holder. |
998 if (lookup->holder() == *object) { | 984 if (is_nonexistent) { |
999 GenerateNegativeHolderLookup(masm(), holder, holder_reg, name, &miss); | 985 GenerateNegativeHolderLookup(masm(), holder(), holder_reg, name, &miss); |
1000 } | |
1001 } | 986 } |
1002 | 987 |
1003 GenerateStoreTransition(masm(), | 988 GenerateStoreTransition(masm(), |
1004 object, | |
1005 lookup, | 989 lookup, |
1006 transition, | 990 transition, |
1007 name, | 991 name, |
1008 receiver(), this->name(), value(), | 992 receiver(), this->name(), value(), |
1009 scratch1(), scratch2(), scratch3(), | 993 scratch1(), scratch2(), scratch3(), |
1010 &miss, | 994 &miss, |
1011 &slow); | 995 &slow); |
1012 | 996 |
1013 // Handle store cache miss. | 997 // Handle store cache miss. |
1014 GenerateRestoreName(masm(), &miss, name); | 998 GenerateRestoreName(masm(), &miss, name); |
1015 TailCallBuiltin(masm(), MissBuiltin(kind())); | 999 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1016 | 1000 |
1017 GenerateRestoreName(masm(), &slow, name); | 1001 GenerateRestoreName(masm(), &slow, name); |
1018 TailCallBuiltin(masm(), SlowBuiltin(kind())); | 1002 TailCallBuiltin(masm(), SlowBuiltin(kind())); |
1019 return GetCode(kind(), Code::FAST, name); | 1003 return GetCode(kind(), Code::FAST, name); |
1020 } | 1004 } |
1021 | 1005 |
1022 | 1006 |
1023 Handle<Code> NamedStoreHandlerCompiler::CompileStoreField( | 1007 Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupResult* lookup, |
1024 Handle<JSObject> object, LookupResult* lookup, Handle<Name> name) { | 1008 Handle<Name> name) { |
1025 Label miss; | 1009 Label miss; |
1026 | 1010 |
1027 FrontendHeader(receiver(), object, name, &miss); | 1011 FrontendHeader(receiver(), name, &miss); |
1028 | 1012 |
1029 // Generate store field code. | 1013 // Generate store field code. |
1030 GenerateStoreField(masm(), | 1014 GenerateStoreField(masm(), holder(), lookup, receiver(), this->name(), |
1031 object, | 1015 value(), scratch1(), scratch2(), &miss); |
1032 lookup, | |
1033 receiver(), this->name(), value(), scratch1(), scratch2(), | |
1034 &miss); | |
1035 | 1016 |
1036 // Handle store cache miss. | 1017 // Handle store cache miss. |
1037 __ bind(&miss); | 1018 __ bind(&miss); |
1038 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1019 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1039 return GetCode(kind(), Code::FAST, name); | 1020 return GetCode(kind(), Code::FAST, name); |
1040 } | 1021 } |
1041 | 1022 |
1042 | 1023 |
1043 Handle<Code> NamedStoreHandlerCompiler::CompileStoreArrayLength( | 1024 Handle<Code> NamedStoreHandlerCompiler::CompileStoreArrayLength( |
1044 Handle<JSObject> object, LookupResult* lookup, Handle<Name> name) { | 1025 LookupResult* lookup, Handle<Name> name) { |
1045 // This accepts as a receiver anything JSArray::SetElementsLength accepts | 1026 // This accepts as a receiver anything JSArray::SetElementsLength accepts |
1046 // (currently anything except for external arrays which means anything with | 1027 // (currently anything except for external arrays which means anything with |
1047 // elements of FixedArray type). Value must be a number, but only smis are | 1028 // elements of FixedArray type). Value must be a number, but only smis are |
1048 // accepted as the most common case. | 1029 // accepted as the most common case. |
1049 Label miss; | 1030 Label miss; |
1050 | 1031 |
1051 // Check that value is a smi. | 1032 // Check that value is a smi. |
1052 __ JumpIfNotSmi(value(), &miss); | 1033 __ JumpIfNotSmi(value(), &miss); |
1053 | 1034 |
1054 // Generate tail call to StoreIC_ArrayLength. | 1035 // Generate tail call to StoreIC_ArrayLength. |
1055 GenerateStoreArrayLength(); | 1036 GenerateStoreArrayLength(); |
1056 | 1037 |
1057 // Handle miss case. | 1038 // Handle miss case. |
1058 __ bind(&miss); | 1039 __ bind(&miss); |
1059 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1040 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1060 return GetCode(kind(), Code::FAST, name); | 1041 return GetCode(kind(), Code::FAST, name); |
1061 } | 1042 } |
1062 | 1043 |
1063 | 1044 |
1064 Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( | 1045 Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( |
1065 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, | 1046 Handle<JSObject> object, Handle<Name> name, Handle<JSFunction> setter) { |
1066 Handle<JSFunction> setter) { | 1047 Frontend(receiver(), name); |
1067 Frontend(receiver(), holder, name); | |
1068 GenerateStoreViaSetter(masm(), type(), receiver(), setter); | 1048 GenerateStoreViaSetter(masm(), type(), receiver(), setter); |
1069 | 1049 |
1070 return GetCode(kind(), Code::FAST, name); | 1050 return GetCode(kind(), Code::FAST, name); |
1071 } | 1051 } |
1072 | 1052 |
1073 | 1053 |
1074 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 1054 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
1075 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, | 1055 Handle<JSObject> object, Handle<Name> name, |
1076 const CallOptimization& call_optimization) { | 1056 const CallOptimization& call_optimization) { |
1077 Frontend(receiver(), holder, name); | 1057 Frontend(receiver(), name); |
1078 Register values[] = { value() }; | 1058 Register values[] = { value() }; |
1079 GenerateFastApiCall( | 1059 GenerateFastApiCall( |
1080 masm(), call_optimization, handle(object->map()), | 1060 masm(), call_optimization, handle(object->map()), |
1081 receiver(), scratch1(), true, 1, values); | 1061 receiver(), scratch1(), true, 1, values); |
1082 return GetCode(kind(), Code::FAST, name); | 1062 return GetCode(kind(), Code::FAST, name); |
1083 } | 1063 } |
1084 | 1064 |
1085 | 1065 |
1086 Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic( | 1066 Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic( |
1087 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) { | 1067 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) { |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1347 Handle<FunctionTemplateInfo>( | 1327 Handle<FunctionTemplateInfo>( |
1348 FunctionTemplateInfo::cast(signature->receiver())); | 1328 FunctionTemplateInfo::cast(signature->receiver())); |
1349 } | 1329 } |
1350 } | 1330 } |
1351 | 1331 |
1352 is_simple_api_call_ = true; | 1332 is_simple_api_call_ = true; |
1353 } | 1333 } |
1354 | 1334 |
1355 | 1335 |
1356 } } // namespace v8::internal | 1336 } } // namespace v8::internal |
OLD | NEW |