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