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

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

Issue 2449463002: [ic] Load IC data handlers now support prototype chain checks with global and dictionary objects. (Closed)
Patch Set: Addressing comments and fixing the handlers in new space issue 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 | « src/ic/ic.h ('k') | src/ic/ic-inl.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 "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/api-arguments-inl.h" 8 #include "src/api-arguments-inl.h"
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/arguments.h" 10 #include "src/arguments.h"
(...skipping 828 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 Handle<Object> LoadIC::SimpleFieldLoad(FieldIndex index) { 839 Handle<Object> LoadIC::SimpleFieldLoad(FieldIndex index) {
840 if (FLAG_tf_load_ic_stub) { 840 if (FLAG_tf_load_ic_stub) {
841 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldDH); 841 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldDH);
842 return LoadHandler::LoadField(isolate(), index); 842 return LoadHandler::LoadField(isolate(), index);
843 } 843 }
844 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub); 844 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub);
845 LoadFieldStub stub(isolate(), index); 845 LoadFieldStub stub(isolate(), index);
846 return stub.GetCode(); 846 return stub.GetCode();
847 } 847 }
848 848
849 bool LoadIC::IsPrototypeValidityCellCheckEnough(Handle<Map> receiver_map, 849 namespace {
850 Handle<JSObject> holder) { 850
851 template <bool fill_array>
852 int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
853 Handle<JSObject> holder, Handle<FixedArray> array,
854 Handle<Name> name) {
851 DCHECK(holder->HasFastProperties()); 855 DCHECK(holder->HasFastProperties());
852 856
853 // The following kinds of receiver maps require custom handler compilation. 857 // The following kinds of receiver maps require custom handler compilation.
854 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap() || 858 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap() ||
855 receiver_map->IsJSGlobalObjectMap()) { 859 receiver_map->IsJSGlobalObjectMap()) {
856 return false; 860 return -1;
857 } 861 }
858 862
863 HandleScope scope(isolate);
864 int checks_count = 0;
865
859 // Switch to custom compiled handler if the prototype chain contains global 866 // Switch to custom compiled handler if the prototype chain contains global
860 // or dictionary objects. 867 // or dictionary objects.
861 for (PrototypeIterator iter(*receiver_map); !iter.IsAtEnd(); iter.Advance()) { 868 for (PrototypeIterator iter(receiver_map); !iter.IsAtEnd(); iter.Advance()) {
862 JSObject* current = iter.GetCurrent<JSObject>(); 869 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
863 if (current == *holder) break; 870 if (*current == *holder) break;
864 Map* current_map = current->map(); 871 Handle<Map> current_map(current->map(), isolate);
872
873 // Only global objects and objects that do not require access
874 // checks are allowed in stubs.
875 DCHECK(current_map->IsJSGlobalProxyMap() ||
876 !current_map->is_access_check_needed());
877
865 if (current_map->IsJSGlobalObjectMap()) { 878 if (current_map->IsJSGlobalObjectMap()) {
866 return false; 879 if (fill_array) {
880 Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(current);
881 Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
882 global, name, PropertyCellType::kInvalidated);
883 DCHECK(cell->value()->IsTheHole(isolate));
884 Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
885 array->set(LoadHandler::kFirstPrototypeIndex + checks_count,
886 *weak_cell);
887 }
888 checks_count++;
889
867 } else if (current_map->is_dictionary_map()) { 890 } else if (current_map->is_dictionary_map()) {
868 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. 891 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast.
869 return false; 892 if (fill_array) {
893 DCHECK_EQ(NameDictionary::kNotFound,
894 current->property_dictionary()->FindEntry(name));
895 Handle<WeakCell> weak_cell =
896 Map::GetOrCreatePrototypeWeakCell(current, isolate);
897 array->set(LoadHandler::kFirstPrototypeIndex + checks_count,
898 *weak_cell);
899 }
900 checks_count++;
870 } 901 }
871 } 902 }
872 return true; 903 return checks_count;
904 }
905
906 } // namespace
907
908 int LoadIC::GetPrototypeCheckCount(Handle<Map> receiver_map,
909 Handle<JSObject> holder) {
910 return InitPrototypeChecks<false>(isolate(), receiver_map, holder,
911 Handle<FixedArray>(), Handle<Name>());
873 } 912 }
874 913
875 Handle<Object> LoadIC::SimpleLoadFromPrototype(Handle<Map> receiver_map, 914 Handle<Object> LoadIC::SimpleLoadFromPrototype(Handle<Map> receiver_map,
876 Handle<JSObject> holder, 915 Handle<JSObject> holder,
916 Handle<Name> name,
877 Handle<Object> smi_handler) { 917 Handle<Object> smi_handler) {
878 DCHECK(IsPrototypeValidityCellCheckEnough(receiver_map, holder)); 918 int checks_count = GetPrototypeCheckCount(receiver_map, holder);
919 DCHECK_LE(0, checks_count);
879 920
880 if (receiver_map->IsJSGlobalProxyMap() || 921 if (receiver_map->IsJSGlobalProxyMap() ||
881 receiver_map->IsJSGlobalObjectMap()) { 922 receiver_map->IsJSGlobalObjectMap()) {
882 UNREACHABLE(); 923 UNREACHABLE();
883 } else if (receiver_map->is_dictionary_map()) { 924 } else if (receiver_map->is_dictionary_map()) {
884 smi_handler = 925 smi_handler =
885 LoadHandler::EnableNegativeLookupOnReceiver(isolate(), smi_handler); 926 LoadHandler::EnableNegativeLookupOnReceiver(isolate(), smi_handler);
886 } 927 }
887 928
888 Handle<Cell> validity_cell = 929 Handle<Cell> validity_cell =
889 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); 930 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
890 DCHECK(!validity_cell.is_null()); 931 DCHECK(!validity_cell.is_null());
891 932
892 Handle<WeakCell> holder_cell = 933 Handle<WeakCell> holder_cell =
893 Map::GetOrCreatePrototypeWeakCell(holder, isolate()); 934 Map::GetOrCreatePrototypeWeakCell(holder, isolate());
894 return isolate()->factory()->NewTuple3(validity_cell, holder_cell, 935
895 smi_handler); 936 if (checks_count == 0) {
937 return isolate()->factory()->NewTuple3(holder_cell, smi_handler,
938 validity_cell);
939 }
940 Handle<FixedArray> handler_array(isolate()->factory()->NewFixedArray(
941 LoadHandler::kFirstPrototypeIndex + checks_count, TENURED));
942 handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler);
943 handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell);
944 handler_array->set(LoadHandler::kHolderCellIndex, *holder_cell);
945 InitPrototypeChecks<true>(isolate(), receiver_map, holder, handler_array,
946 name);
947 return handler_array;
896 } 948 }
897 949
898 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) { 950 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) {
899 DCHECK(lookup->state() == LookupIterator::ACCESSOR); 951 DCHECK(lookup->state() == LookupIterator::ACCESSOR);
900 Isolate* isolate = lookup->isolate(); 952 Isolate* isolate = lookup->isolate();
901 Handle<Object> accessors = lookup->GetAccessors(); 953 Handle<Object> accessors = lookup->GetAccessors();
902 if (accessors->IsAccessorInfo()) { 954 if (accessors->IsAccessorInfo()) {
903 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); 955 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
904 if (info->getter() != NULL && 956 if (info->getter() != NULL &&
905 !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) { 957 !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) {
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
1223 return isolate()->builtins()->LoadIC_Normal(); 1275 return isolate()->builtins()->LoadIC_Normal();
1224 } 1276 }
1225 1277
1226 // -------------- Fields -------------- 1278 // -------------- Fields --------------
1227 if (lookup->property_details().type() == DATA) { 1279 if (lookup->property_details().type() == DATA) {
1228 FieldIndex field = lookup->GetFieldIndex(); 1280 FieldIndex field = lookup->GetFieldIndex();
1229 Handle<Object> smi_handler = SimpleFieldLoad(field); 1281 Handle<Object> smi_handler = SimpleFieldLoad(field);
1230 if (receiver_is_holder) { 1282 if (receiver_is_holder) {
1231 return smi_handler; 1283 return smi_handler;
1232 } 1284 }
1233 if (FLAG_tf_load_ic_stub && 1285 if (FLAG_tf_load_ic_stub && GetPrototypeCheckCount(map, holder) >= 0) {
1234 IsPrototypeValidityCellCheckEnough(map, holder)) {
1235 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH); 1286 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH);
1236 return SimpleLoadFromPrototype(map, holder, smi_handler); 1287 return SimpleLoadFromPrototype(map, holder, lookup->name(),
1288 smi_handler);
1237 } 1289 }
1238 break; // Custom-compiled handler. 1290 break; // Custom-compiled handler.
1239 } 1291 }
1240 1292
1241 // -------------- Constant properties -------------- 1293 // -------------- Constant properties --------------
1242 DCHECK(lookup->property_details().type() == DATA_CONSTANT); 1294 DCHECK(lookup->property_details().type() == DATA_CONSTANT);
1243 if (FLAG_tf_load_ic_stub) { 1295 if (FLAG_tf_load_ic_stub) {
1244 Handle<Object> smi_handler = 1296 Handle<Object> smi_handler =
1245 LoadHandler::LoadConstant(isolate(), lookup->GetConstantIndex()); 1297 LoadHandler::LoadConstant(isolate(), lookup->GetConstantIndex());
1246 if (receiver_is_holder) { 1298 if (receiver_is_holder) {
1247 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH); 1299 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH);
1248 return smi_handler; 1300 return smi_handler;
1249 } 1301 }
1250 if (IsPrototypeValidityCellCheckEnough(map, holder)) { 1302 if (GetPrototypeCheckCount(map, holder) >= 0) {
1251 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH); 1303 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH);
1252 return SimpleLoadFromPrototype(map, holder, smi_handler); 1304 return SimpleLoadFromPrototype(map, holder, lookup->name(),
1305 smi_handler);
1253 } 1306 }
1254 } else { 1307 } else {
1255 if (receiver_is_holder) { 1308 if (receiver_is_holder) {
1256 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub); 1309 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub);
1257 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); 1310 LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
1258 return stub.GetCode(); 1311 return stub.GetCode();
1259 } 1312 }
1260 } 1313 }
1261 break; // Custom-compiled handler. 1314 break; // Custom-compiled handler.
1262 } 1315 }
(...skipping 1750 matching lines...) Expand 10 before | Expand all | Expand 10 after
3013 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); 3066 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
3014 it.Next(); 3067 it.Next();
3015 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, 3068 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3016 Object::GetProperty(&it)); 3069 Object::GetProperty(&it));
3017 } 3070 }
3018 3071
3019 return *result; 3072 return *result;
3020 } 3073 }
3021 } // namespace internal 3074 } // namespace internal
3022 } // namespace v8 3075 } // namespace v8
OLDNEW
« no previous file with comments | « src/ic/ic.h ('k') | src/ic/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698