Chromium Code Reviews

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

Issue 2471613006: [ic] Data handlers for loads of non-existent properties. (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
« no previous file with comments | « src/ic/ic.h ('k') | no next file » | 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 841 matching lines...)
852 LoadFieldStub stub(isolate(), index); 852 LoadFieldStub stub(isolate(), index);
853 return stub.GetCode(); 853 return stub.GetCode();
854 } 854 }
855 855
856 namespace { 856 namespace {
857 857
858 template <bool fill_array> 858 template <bool fill_array>
859 int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map, 859 int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
860 Handle<JSObject> holder, Handle<FixedArray> array, 860 Handle<JSObject> holder, Handle<FixedArray> array,
861 Handle<Name> name) { 861 Handle<Name> name) {
862 DCHECK(holder->HasFastProperties()); 862 DCHECK(holder.is_null() || holder->HasFastProperties());
863 863
864 // The following kinds of receiver maps require custom handler compilation. 864 // The following kinds of receiver maps require custom handler compilation.
865 if (receiver_map->IsJSGlobalObjectMap()) { 865 if (receiver_map->IsJSGlobalObjectMap()) {
866 return -1; 866 return -1;
867 } 867 }
868 // We don't encode the requirement to check access rights because we already 868 // We don't encode the requirement to check access rights because we already
869 // passed the access check for current native context and the access 869 // passed the access check for current native context and the access
870 // can't be revoked. 870 // can't be revoked.
871 871
872 HandleScope scope(isolate); 872 HandleScope scope(isolate);
873 int checks_count = 0; 873 int checks_count = 0;
874 874
875 // Switch to custom compiled handler if the prototype chain contains global 875 // Create/count entries for each global or dictionary prototype appeared in
876 // or dictionary objects. 876 // the prototype chain contains from receiver till holder.
877 for (PrototypeIterator iter(receiver_map); !iter.IsAtEnd(); iter.Advance()) { 877 for (PrototypeIterator iter(receiver_map); !iter.IsAtEnd(); iter.Advance()) {
878 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); 878 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
879 if (*current == *holder) break; 879 if (holder.is_identical_to(current)) break;
880 Handle<Map> current_map(current->map(), isolate); 880 Handle<Map> current_map(current->map(), isolate);
881 881
882 if (current_map->IsJSGlobalObjectMap()) { 882 if (current_map->IsJSGlobalObjectMap()) {
883 if (fill_array) { 883 if (fill_array) {
884 Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(current); 884 Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(current);
885 Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell( 885 Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
886 global, name, PropertyCellType::kInvalidated); 886 global, name, PropertyCellType::kInvalidated);
887 DCHECK(cell->value()->IsTheHole(isolate)); 887 DCHECK(cell->value()->IsTheHole(isolate));
888 Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell); 888 Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
889 array->set(LoadHandler::kFirstPrototypeIndex + checks_count, 889 array->set(LoadHandler::kFirstPrototypeIndex + checks_count,
(...skipping 53 matching lines...)
943 Handle<FixedArray> handler_array(isolate()->factory()->NewFixedArray( 943 Handle<FixedArray> handler_array(isolate()->factory()->NewFixedArray(
944 LoadHandler::kFirstPrototypeIndex + checks_count, TENURED)); 944 LoadHandler::kFirstPrototypeIndex + checks_count, TENURED));
945 handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler); 945 handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler);
946 handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell); 946 handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell);
947 handler_array->set(LoadHandler::kHolderCellIndex, *holder_cell); 947 handler_array->set(LoadHandler::kHolderCellIndex, *holder_cell);
948 InitPrototypeChecks<true>(isolate(), receiver_map, holder, handler_array, 948 InitPrototypeChecks<true>(isolate(), receiver_map, holder, handler_array,
949 name); 949 name);
950 return handler_array; 950 return handler_array;
951 } 951 }
952 952
953 Handle<Object> LoadIC::SimpleLoadNonExistent(Handle<Map> receiver_map,
954 Handle<Name> name) {
955 Handle<JSObject> holder; // null handle
956 int checks_count = GetPrototypeCheckCount(receiver_map, holder);
957 DCHECK_LE(0, checks_count);
958
959 if (receiver_map->IsJSGlobalObjectMap()) {
Jakob Kummerow 2016/11/03 13:03:40 You mean DCHECK(!receiver_map->IsJSGlobalObjectMap
Igor Sheludko 2016/11/03 16:14:38 Indeed.
960 UNREACHABLE();
961 }
962 Handle<Object> smi_handler = LoadHandler::LoadNonExistent(
963 isolate(), receiver_map->is_dictionary_map());
964
965 Handle<Object> validity_cell =
966 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
967 if (validity_cell.is_null()) {
968 // This must be a case when receiver's prototype is null.
969 DCHECK_EQ(*isolate()->factory()->null_value(),
970 receiver_map->GetPrototypeChainRootMap(isolate())->prototype());
971 DCHECK_EQ(0, checks_count);
972 validity_cell = handle(Smi::FromInt(0), isolate());
973 }
974
975 Factory* factory = isolate()->factory();
976 if (checks_count == 0) {
977 return factory->NewTuple3(factory->null_value(), smi_handler,
978 validity_cell);
979 }
980 Handle<FixedArray> handler_array(factory->NewFixedArray(
981 LoadHandler::kFirstPrototypeIndex + checks_count, TENURED));
982 handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler);
983 handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell);
984 handler_array->set(LoadHandler::kHolderCellIndex, *factory->null_value());
985 InitPrototypeChecks<true>(isolate(), receiver_map, holder, handler_array,
986 name);
987 return handler_array;
988 }
989
953 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) { 990 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) {
954 DCHECK(lookup->state() == LookupIterator::ACCESSOR); 991 DCHECK(lookup->state() == LookupIterator::ACCESSOR);
955 Isolate* isolate = lookup->isolate(); 992 Isolate* isolate = lookup->isolate();
956 Handle<Object> accessors = lookup->GetAccessors(); 993 Handle<Object> accessors = lookup->GetAccessors();
957 if (accessors->IsAccessorInfo()) { 994 if (accessors->IsAccessorInfo()) {
958 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); 995 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
959 if (info->getter() != NULL && 996 if (info->getter() != NULL &&
960 !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) { 997 !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) {
961 return false; 998 return false;
962 } 999 }
(...skipping 34 matching lines...)
997 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); 1034 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>());
998 TRACE_IC("LoadIC", lookup->name()); 1035 TRACE_IC("LoadIC", lookup->name());
999 return; 1036 return;
1000 } 1037 }
1001 1038
1002 Handle<Object> code; 1039 Handle<Object> code;
1003 if (lookup->state() == LookupIterator::JSPROXY || 1040 if (lookup->state() == LookupIterator::JSPROXY ||
1004 lookup->state() == LookupIterator::ACCESS_CHECK) { 1041 lookup->state() == LookupIterator::ACCESS_CHECK) {
1005 code = slow_stub(); 1042 code = slow_stub();
1006 } else if (!lookup->IsFound()) { 1043 } else if (!lookup->IsFound()) {
1007 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC) { 1044 if (kind() == Code::LOAD_IC) {
1045 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH);
1046 code = SimpleLoadNonExistent(receiver_map(), lookup->name());
1047 } else if (kind() == Code::LOAD_GLOBAL_IC) {
1008 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), 1048 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(),
1009 receiver_map()); 1049 receiver_map());
1010 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. 1050 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case.
1011 if (code.is_null()) code = slow_stub(); 1051 if (code.is_null()) code = slow_stub();
1012 } else { 1052 } else {
1013 code = slow_stub(); 1053 code = slow_stub();
1014 } 1054 }
1015 } else { 1055 } else {
1016 if (kind() == Code::LOAD_GLOBAL_IC && 1056 if (kind() == Code::LOAD_GLOBAL_IC &&
1017 lookup->state() == LookupIterator::DATA && 1057 lookup->state() == LookupIterator::DATA &&
(...skipping 2116 matching lines...)
3134 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); 3174 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
3135 it.Next(); 3175 it.Next();
3136 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, 3176 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3137 Object::GetProperty(&it)); 3177 Object::GetProperty(&it));
3138 } 3178 }
3139 3179
3140 return *result; 3180 return *result;
3141 } 3181 }
3142 } // namespace internal 3182 } // namespace internal
3143 } // namespace v8 3183 } // namespace v8
OLDNEW
« no previous file with comments | « src/ic/ic.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine