Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1168)

Side by Side Diff: src/ic/ic.cc

Issue 2513893003: [ic] Don't check full prototype chain if name is a private symbol. (Closed)
Patch Set: and JSProxy case Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/prototype.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/ic/ic.h" 5 #include "src/ic/ic.h"
6 6
7 #include <iostream> 7 #include <iostream>
8 8
9 #include "src/accessors.h" 9 #include "src/accessors.h"
10 #include "src/api-arguments-inl.h" 10 #include "src/api-arguments-inl.h"
(...skipping 837 matching lines...) Expand 10 before | Expand all | Expand 10 after
848 } 848 }
849 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub); 849 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub);
850 LoadFieldStub stub(isolate(), index); 850 LoadFieldStub stub(isolate(), index);
851 return stub.GetCode(); 851 return stub.GetCode();
852 } 852 }
853 853
854 namespace { 854 namespace {
855 855
856 template <bool fill_array = true> 856 template <bool fill_array = true>
857 int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map, 857 int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
858 Handle<JSObject> holder, Handle<FixedArray> array, 858 Handle<JSObject> holder, Handle<Name> name,
859 Handle<Name> name, int first_index) { 859 Handle<FixedArray> array, int first_index) {
860 DCHECK(holder.is_null() || holder->HasFastProperties()); 860 DCHECK(holder.is_null() || holder->HasFastProperties());
861 861
862 // We don't encode the requirement to check access rights because we already 862 // We don't encode the requirement to check access rights because we already
863 // passed the access check for current native context and the access 863 // passed the access check for current native context and the access
864 // can't be revoked. 864 // can't be revoked.
865 865
866 HandleScope scope(isolate); 866 HandleScope scope(isolate);
867 int checks_count = 0; 867 int checks_count = 0;
868 868
869 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) { 869 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) {
(...skipping 17 matching lines...) Expand all
887 global, name, PropertyCellType::kInvalidated); 887 global, name, PropertyCellType::kInvalidated);
888 DCHECK(cell->value()->IsTheHole(isolate)); 888 DCHECK(cell->value()->IsTheHole(isolate));
889 Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell); 889 Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
890 array->set(LoadHandler::kFirstPrototypeIndex + checks_count, *weak_cell); 890 array->set(LoadHandler::kFirstPrototypeIndex + checks_count, *weak_cell);
891 } 891 }
892 checks_count++; 892 checks_count++;
893 } 893 }
894 894
895 // Create/count entries for each global or dictionary prototype appeared in 895 // Create/count entries for each global or dictionary prototype appeared in
896 // the prototype chain contains from receiver till holder. 896 // the prototype chain contains from receiver till holder.
897 for (PrototypeIterator iter(receiver_map); !iter.IsAtEnd(); iter.Advance()) { 897 PrototypeIterator::WhereToEnd end = name->IsPrivate()
898 ? PrototypeIterator::END_AT_NON_HIDDEN
899 : PrototypeIterator::END_AT_NULL;
900 for (PrototypeIterator iter(receiver_map, end); !iter.IsAtEnd();
901 iter.Advance()) {
898 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); 902 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
899 if (holder.is_identical_to(current)) break; 903 if (holder.is_identical_to(current)) break;
900 Handle<Map> current_map(current->map(), isolate); 904 Handle<Map> current_map(current->map(), isolate);
901 905
902 if (current_map->IsJSGlobalObjectMap()) { 906 if (current_map->IsJSGlobalObjectMap()) {
903 if (fill_array) { 907 if (fill_array) {
904 Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(current); 908 Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(current);
905 Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell( 909 Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
906 global, name, PropertyCellType::kInvalidated); 910 global, name, PropertyCellType::kInvalidated);
907 DCHECK(cell->value()->IsTheHole(isolate)); 911 DCHECK(cell->value()->IsTheHole(isolate));
(...skipping 17 matching lines...) Expand all
925 return checks_count; 929 return checks_count;
926 } 930 }
927 931
928 // Returns 0 if the validity cell check is enough to ensure that the 932 // Returns 0 if the validity cell check is enough to ensure that the
929 // prototype chain from |receiver_map| till |holder| did not change. 933 // prototype chain from |receiver_map| till |holder| did not change.
930 // If the |holder| is an empty handle then the full prototype chain is 934 // If the |holder| is an empty handle then the full prototype chain is
931 // checked. 935 // checked.
932 // Returns -1 if the handler has to be compiled or the number of prototype 936 // Returns -1 if the handler has to be compiled or the number of prototype
933 // checks otherwise. 937 // checks otherwise.
934 int GetPrototypeCheckCount(Isolate* isolate, Handle<Map> receiver_map, 938 int GetPrototypeCheckCount(Isolate* isolate, Handle<Map> receiver_map,
935 Handle<JSObject> holder) { 939 Handle<JSObject> holder, Handle<Name> name) {
936 return InitPrototypeChecks<false>(isolate, receiver_map, holder, 940 return InitPrototypeChecks<false>(isolate, receiver_map, holder, name,
937 Handle<FixedArray>(), Handle<Name>(), 0); 941 Handle<FixedArray>(), 0);
938 } 942 }
939 943
940 } // namespace 944 } // namespace
941 945
942 Handle<Object> LoadIC::LoadFromPrototype(Handle<Map> receiver_map, 946 Handle<Object> LoadIC::LoadFromPrototype(Handle<Map> receiver_map,
943 Handle<JSObject> holder, 947 Handle<JSObject> holder,
944 Handle<Name> name, 948 Handle<Name> name,
945 Handle<Object> smi_handler) { 949 Handle<Object> smi_handler) {
946 int checks_count = GetPrototypeCheckCount(isolate(), receiver_map, holder); 950 int checks_count =
951 GetPrototypeCheckCount(isolate(), receiver_map, holder, name);
947 DCHECK_LE(0, checks_count); 952 DCHECK_LE(0, checks_count);
948 953
949 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) { 954 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) {
950 DCHECK(!receiver_map->is_dictionary_map()); 955 DCHECK(!receiver_map->is_dictionary_map());
951 DCHECK_LE(1, checks_count); // For native context. 956 DCHECK_LE(1, checks_count); // For native context.
952 smi_handler = 957 smi_handler =
953 LoadHandler::EnableAccessCheckOnReceiver(isolate(), smi_handler); 958 LoadHandler::EnableAccessCheckOnReceiver(isolate(), smi_handler);
954 } else if (receiver_map->is_dictionary_map() && 959 } else if (receiver_map->is_dictionary_map() &&
955 !receiver_map->IsJSGlobalObjectMap()) { 960 !receiver_map->IsJSGlobalObjectMap()) {
956 smi_handler = 961 smi_handler =
957 LoadHandler::EnableNegativeLookupOnReceiver(isolate(), smi_handler); 962 LoadHandler::EnableNegativeLookupOnReceiver(isolate(), smi_handler);
958 } 963 }
959 964
960 Handle<Cell> validity_cell = 965 Handle<Cell> validity_cell =
961 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); 966 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
962 DCHECK(!validity_cell.is_null()); 967 DCHECK(!validity_cell.is_null());
963 968
964 Handle<WeakCell> holder_cell = 969 Handle<WeakCell> holder_cell =
965 Map::GetOrCreatePrototypeWeakCell(holder, isolate()); 970 Map::GetOrCreatePrototypeWeakCell(holder, isolate());
966 971
967 if (checks_count == 0) { 972 if (checks_count == 0) {
968 return isolate()->factory()->NewTuple3(holder_cell, smi_handler, 973 return isolate()->factory()->NewTuple3(holder_cell, smi_handler,
969 validity_cell); 974 validity_cell);
970 } 975 }
971 Handle<FixedArray> handler_array(isolate()->factory()->NewFixedArray( 976 Handle<FixedArray> handler_array(isolate()->factory()->NewFixedArray(
972 LoadHandler::kFirstPrototypeIndex + checks_count, TENURED)); 977 LoadHandler::kFirstPrototypeIndex + checks_count, TENURED));
973 handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler); 978 handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler);
974 handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell); 979 handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell);
975 handler_array->set(LoadHandler::kHolderCellIndex, *holder_cell); 980 handler_array->set(LoadHandler::kHolderCellIndex, *holder_cell);
976 InitPrototypeChecks(isolate(), receiver_map, holder, handler_array, name, 981 InitPrototypeChecks(isolate(), receiver_map, holder, name, handler_array,
977 LoadHandler::kFirstPrototypeIndex); 982 LoadHandler::kFirstPrototypeIndex);
978 return handler_array; 983 return handler_array;
979 } 984 }
980 985
981 Handle<Object> LoadIC::LoadNonExistent(Handle<Map> receiver_map, 986 Handle<Object> LoadIC::LoadNonExistent(Handle<Map> receiver_map,
982 Handle<Name> name) { 987 Handle<Name> name) {
983 Handle<JSObject> holder; // null handle 988 Handle<JSObject> holder; // null handle
984 int checks_count = GetPrototypeCheckCount(isolate(), receiver_map, holder); 989 int checks_count =
990 GetPrototypeCheckCount(isolate(), receiver_map, holder, name);
985 DCHECK_LE(0, checks_count); 991 DCHECK_LE(0, checks_count);
986 992
987 bool do_negative_lookup_on_receiver = 993 bool do_negative_lookup_on_receiver =
988 receiver_map->is_dictionary_map() && !receiver_map->IsJSGlobalObjectMap(); 994 receiver_map->is_dictionary_map() && !receiver_map->IsJSGlobalObjectMap();
989 Handle<Object> smi_handler = 995 Handle<Object> smi_handler =
990 LoadHandler::LoadNonExistent(isolate(), do_negative_lookup_on_receiver); 996 LoadHandler::LoadNonExistent(isolate(), do_negative_lookup_on_receiver);
991 997
992 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) { 998 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) {
993 DCHECK(!receiver_map->is_dictionary_map()); 999 DCHECK(!receiver_map->is_dictionary_map());
994 DCHECK_LE(1, checks_count); // For native context. 1000 DCHECK_LE(1, checks_count); // For native context.
995 smi_handler = 1001 smi_handler =
996 LoadHandler::EnableAccessCheckOnReceiver(isolate(), smi_handler); 1002 LoadHandler::EnableAccessCheckOnReceiver(isolate(), smi_handler);
997 } 1003 }
998 1004
999 Handle<Object> validity_cell = 1005 Handle<Object> validity_cell =
1000 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); 1006 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
1001 if (validity_cell.is_null()) { 1007 if (validity_cell.is_null()) {
1002 // This must be a case when receiver's prototype is null.
1003 DCHECK_EQ(*isolate()->factory()->null_value(),
1004 receiver_map->GetPrototypeChainRootMap(isolate())->prototype());
1005 DCHECK_EQ(0, checks_count); 1008 DCHECK_EQ(0, checks_count);
1006 validity_cell = handle(Smi::FromInt(0), isolate()); 1009 validity_cell = handle(Smi::FromInt(0), isolate());
1007 } 1010 }
1008 1011
1009 Factory* factory = isolate()->factory(); 1012 Factory* factory = isolate()->factory();
1010 if (checks_count == 0) { 1013 if (checks_count == 0) {
1011 return factory->NewTuple3(factory->null_value(), smi_handler, 1014 return factory->NewTuple3(factory->null_value(), smi_handler,
1012 validity_cell); 1015 validity_cell);
1013 } 1016 }
1014 Handle<FixedArray> handler_array(factory->NewFixedArray( 1017 Handle<FixedArray> handler_array(factory->NewFixedArray(
1015 LoadHandler::kFirstPrototypeIndex + checks_count, TENURED)); 1018 LoadHandler::kFirstPrototypeIndex + checks_count, TENURED));
1016 handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler); 1019 handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler);
1017 handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell); 1020 handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell);
1018 handler_array->set(LoadHandler::kHolderCellIndex, *factory->null_value()); 1021 handler_array->set(LoadHandler::kHolderCellIndex, *factory->null_value());
1019 InitPrototypeChecks(isolate(), receiver_map, holder, handler_array, name, 1022 InitPrototypeChecks(isolate(), receiver_map, holder, name, handler_array,
1020 LoadHandler::kFirstPrototypeIndex); 1023 LoadHandler::kFirstPrototypeIndex);
1021 return handler_array; 1024 return handler_array;
1022 } 1025 }
1023 1026
1024 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) { 1027 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) {
1025 DCHECK(lookup->state() == LookupIterator::ACCESSOR); 1028 DCHECK(lookup->state() == LookupIterator::ACCESSOR);
1026 Isolate* isolate = lookup->isolate(); 1029 Isolate* isolate = lookup->isolate();
1027 Handle<Object> accessors = lookup->GetAccessors(); 1030 Handle<Object> accessors = lookup->GetAccessors();
1028 if (accessors->IsAccessorInfo()) { 1031 if (accessors->IsAccessorInfo()) {
1029 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); 1032 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
(...skipping 856 matching lines...) Expand 10 before | Expand all | Expand 10 after
1886 1889
1887 } else { 1890 } else {
1888 DCHECK_EQ(DATA, details.type()); 1891 DCHECK_EQ(DATA, details.type());
1889 bool extend_storage = 1892 bool extend_storage =
1890 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0; 1893 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0;
1891 1894
1892 FieldIndex index = FieldIndex::ForDescriptor(*transition, descriptor); 1895 FieldIndex index = FieldIndex::ForDescriptor(*transition, descriptor);
1893 smi_handler = StoreHandler::TransitionToField( 1896 smi_handler = StoreHandler::TransitionToField(
1894 isolate(), descriptor, index, representation, extend_storage); 1897 isolate(), descriptor, index, representation, extend_storage);
1895 } 1898 }
1899 // |holder| is either a receiver if the property is non-existent or
1900 // one of the prototypes.
1901 DCHECK(!holder.is_null());
1902 bool is_nonexistent = holder->map() == transition->GetBackPointer();
1903 if (is_nonexistent) holder = Handle<JSObject>::null();
1896 1904
1897 int checks_count = GetPrototypeCheckCount(isolate(), receiver_map, holder); 1905 int checks_count =
1906 GetPrototypeCheckCount(isolate(), receiver_map, holder, name);
1898 DCHECK_LE(0, checks_count); 1907 DCHECK_LE(0, checks_count);
1899 DCHECK(!receiver_map->IsJSGlobalObjectMap()); 1908 DCHECK(!receiver_map->IsJSGlobalObjectMap());
1900 1909
1901 Handle<Object> validity_cell = 1910 Handle<Object> validity_cell =
1902 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); 1911 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
1903 if (validity_cell.is_null()) { 1912 if (validity_cell.is_null()) {
1904 // This must be a case when receiver's prototype is null.
1905 DCHECK_EQ(*isolate()->factory()->null_value(),
1906 receiver_map->GetPrototypeChainRootMap(isolate())->prototype());
1907 DCHECK_EQ(0, checks_count); 1913 DCHECK_EQ(0, checks_count);
1908 validity_cell = handle(Smi::FromInt(0), isolate()); 1914 validity_cell = handle(Smi::FromInt(0), isolate());
1909 } 1915 }
1910 1916
1911 Handle<WeakCell> transition_cell = Map::WeakCellForMap(transition); 1917 Handle<WeakCell> transition_cell = Map::WeakCellForMap(transition);
1912 1918
1913 Factory* factory = isolate()->factory(); 1919 Factory* factory = isolate()->factory();
1914 if (checks_count == 0) { 1920 if (checks_count == 0) {
1915 return factory->NewTuple3(transition_cell, smi_handler, validity_cell); 1921 return factory->NewTuple3(transition_cell, smi_handler, validity_cell);
1916 } 1922 }
1917 Handle<FixedArray> handler_array(factory->NewFixedArray( 1923 Handle<FixedArray> handler_array(factory->NewFixedArray(
1918 StoreHandler::kFirstPrototypeIndex + checks_count, TENURED)); 1924 StoreHandler::kFirstPrototypeIndex + checks_count, TENURED));
1919 handler_array->set(StoreHandler::kSmiHandlerIndex, *smi_handler); 1925 handler_array->set(StoreHandler::kSmiHandlerIndex, *smi_handler);
1920 handler_array->set(StoreHandler::kValidityCellIndex, *validity_cell); 1926 handler_array->set(StoreHandler::kValidityCellIndex, *validity_cell);
1921 handler_array->set(StoreHandler::kTransitionCellIndex, *transition_cell); 1927 handler_array->set(StoreHandler::kTransitionCellIndex, *transition_cell);
1922 InitPrototypeChecks(isolate(), receiver_map, holder, handler_array, name, 1928 InitPrototypeChecks(isolate(), receiver_map, holder, name, handler_array,
1923 StoreHandler::kFirstPrototypeIndex); 1929 StoreHandler::kFirstPrototypeIndex);
1924 return handler_array; 1930 return handler_array;
1925 } 1931 }
1926 1932
1927 static Handle<Code> PropertyCellStoreHandler( 1933 static Handle<Code> PropertyCellStoreHandler(
1928 Isolate* isolate, Handle<JSObject> receiver, Handle<JSGlobalObject> holder, 1934 Isolate* isolate, Handle<JSObject> receiver, Handle<JSGlobalObject> holder,
1929 Handle<Name> name, Handle<PropertyCell> cell, PropertyCellType type) { 1935 Handle<Name> name, Handle<PropertyCell> cell, PropertyCellType type) {
1930 auto constant_type = Nothing<PropertyCellConstantType>(); 1936 auto constant_type = Nothing<PropertyCellConstantType>();
1931 if (type == PropertyCellType::kConstantType) { 1937 if (type == PropertyCellType::kConstantType) {
1932 constant_type = Just(cell->GetConstantType()); 1938 constant_type = Just(cell->GetConstantType());
(...skipping 1311 matching lines...) Expand 10 before | Expand all | Expand 10 after
3244 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); 3250 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
3245 it.Next(); 3251 it.Next();
3246 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, 3252 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3247 Object::GetProperty(&it)); 3253 Object::GetProperty(&it));
3248 } 3254 }
3249 3255
3250 return *result; 3256 return *result;
3251 } 3257 }
3252 } // namespace internal 3258 } // namespace internal
3253 } // namespace v8 3259 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/prototype.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698