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

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: 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
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 }
902 // We don't have to perform access checks for global proxy objects appeared
Jakob Kummerow 2016/10/27 11:30:54 nit: s/appeared/appearing/
Igor Sheludko 2016/10/27 14:55:30 Given I'm going to remove the access checks in the
903 // in the middle of prototype chain because the receiver's map check
904 // already guarantees that we receiver belongs to the same native context.
Jakob Kummerow 2016/10/27 11:30:54 nit: s/we/the/
Igor Sheludko 2016/10/27 14:55:31 Acknowledged.
871 } 905 }
872 return true; 906 return checks_count;
907 }
908
909 } // namespace
910
911 int LoadIC::GetPrototypeCheckCount(Handle<Map> receiver_map,
912 Handle<JSObject> holder) {
913 return InitPrototypeChecks<false>(isolate(), receiver_map, holder,
914 Handle<FixedArray>(), Handle<Name>());
873 } 915 }
874 916
875 Handle<Object> LoadIC::SimpleLoadFromPrototype(Handle<Map> receiver_map, 917 Handle<Object> LoadIC::SimpleLoadFromPrototype(Handle<Map> receiver_map,
876 Handle<JSObject> holder, 918 Handle<JSObject> holder,
919 Handle<Name> name,
877 Handle<Object> smi_handler) { 920 Handle<Object> smi_handler) {
878 DCHECK(IsPrototypeValidityCellCheckEnough(receiver_map, holder)); 921 int checks_count = GetPrototypeCheckCount(receiver_map, holder);
922 DCHECK_LE(0, checks_count);
879 923
880 if (receiver_map->IsJSGlobalProxyMap() || 924 if (receiver_map->IsJSGlobalProxyMap() ||
881 receiver_map->IsJSGlobalObjectMap()) { 925 receiver_map->IsJSGlobalObjectMap()) {
882 UNREACHABLE(); 926 UNREACHABLE();
883 } else if (receiver_map->is_dictionary_map()) { 927 } else if (receiver_map->is_dictionary_map()) {
884 smi_handler = 928 smi_handler =
885 LoadHandler::EnableNegativeLookupOnReceiver(isolate(), smi_handler); 929 LoadHandler::EnableNegativeLookupOnReceiver(isolate(), smi_handler);
886 } 930 }
887 931
888 Handle<Cell> validity_cell = 932 Handle<Cell> validity_cell =
889 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); 933 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
890 DCHECK(!validity_cell.is_null()); 934 DCHECK(!validity_cell.is_null());
891 935
892 Handle<WeakCell> holder_cell = 936 Handle<WeakCell> holder_cell =
893 Map::GetOrCreatePrototypeWeakCell(holder, isolate()); 937 Map::GetOrCreatePrototypeWeakCell(holder, isolate());
894 return isolate()->factory()->NewTuple3(validity_cell, holder_cell, 938
895 smi_handler); 939 if (checks_count == 0) {
940 return isolate()->factory()->NewTuple3(holder_cell, smi_handler,
941 validity_cell);
942 }
943 Handle<FixedArray> handler_array(isolate()->factory()->NewFixedArray(
944 LoadHandler::kFirstPrototypeIndex + checks_count));
945 handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler);
946 handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell);
947 handler_array->set(LoadHandler::kHolderCellIndex, *holder_cell);
948 InitPrototypeChecks<true>(isolate(), receiver_map, holder, handler_array,
949 name);
950 return handler_array;
896 } 951 }
897 952
898 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) { 953 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) {
899 DCHECK(lookup->state() == LookupIterator::ACCESSOR); 954 DCHECK(lookup->state() == LookupIterator::ACCESSOR);
900 Isolate* isolate = lookup->isolate(); 955 Isolate* isolate = lookup->isolate();
901 Handle<Object> accessors = lookup->GetAccessors(); 956 Handle<Object> accessors = lookup->GetAccessors();
902 if (accessors->IsAccessorInfo()) { 957 if (accessors->IsAccessorInfo()) {
903 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); 958 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
904 if (info->getter() != NULL && 959 if (info->getter() != NULL &&
905 !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) { 960 !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) {
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
1223 return isolate()->builtins()->LoadIC_Normal(); 1278 return isolate()->builtins()->LoadIC_Normal();
1224 } 1279 }
1225 1280
1226 // -------------- Fields -------------- 1281 // -------------- Fields --------------
1227 if (lookup->property_details().type() == DATA) { 1282 if (lookup->property_details().type() == DATA) {
1228 FieldIndex field = lookup->GetFieldIndex(); 1283 FieldIndex field = lookup->GetFieldIndex();
1229 Handle<Object> smi_handler = SimpleFieldLoad(field); 1284 Handle<Object> smi_handler = SimpleFieldLoad(field);
1230 if (receiver_is_holder) { 1285 if (receiver_is_holder) {
1231 return smi_handler; 1286 return smi_handler;
1232 } 1287 }
1233 if (FLAG_tf_load_ic_stub && 1288 if (FLAG_tf_load_ic_stub && GetPrototypeCheckCount(map, holder) >= 0) {
1234 IsPrototypeValidityCellCheckEnough(map, holder)) {
1235 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH); 1289 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH);
1236 return SimpleLoadFromPrototype(map, holder, smi_handler); 1290 return SimpleLoadFromPrototype(map, holder, lookup->name(),
1291 smi_handler);
1237 } 1292 }
1238 break; // Custom-compiled handler. 1293 break; // Custom-compiled handler.
1239 } 1294 }
1240 1295
1241 // -------------- Constant properties -------------- 1296 // -------------- Constant properties --------------
1242 DCHECK(lookup->property_details().type() == DATA_CONSTANT); 1297 DCHECK(lookup->property_details().type() == DATA_CONSTANT);
1243 if (FLAG_tf_load_ic_stub) { 1298 if (FLAG_tf_load_ic_stub) {
1244 Handle<Object> smi_handler = 1299 Handle<Object> smi_handler =
1245 LoadHandler::LoadConstant(isolate(), lookup->GetConstantIndex()); 1300 LoadHandler::LoadConstant(isolate(), lookup->GetConstantIndex());
1246 if (receiver_is_holder) { 1301 if (receiver_is_holder) {
1247 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH); 1302 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH);
1248 return smi_handler; 1303 return smi_handler;
1249 } 1304 }
1250 if (IsPrototypeValidityCellCheckEnough(map, holder)) { 1305 if (GetPrototypeCheckCount(map, holder) >= 0) {
1251 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH); 1306 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH);
1252 return SimpleLoadFromPrototype(map, holder, smi_handler); 1307 return SimpleLoadFromPrototype(map, holder, lookup->name(),
1308 smi_handler);
1253 } 1309 }
1254 } else { 1310 } else {
1255 if (receiver_is_holder) { 1311 if (receiver_is_holder) {
1256 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub); 1312 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub);
1257 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); 1313 LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
1258 return stub.GetCode(); 1314 return stub.GetCode();
1259 } 1315 }
1260 } 1316 }
1261 break; // Custom-compiled handler. 1317 break; // Custom-compiled handler.
1262 } 1318 }
(...skipping 1750 matching lines...) Expand 10 before | Expand all | Expand 10 after
3013 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); 3069 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
3014 it.Next(); 3070 it.Next();
3015 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, 3071 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3016 Object::GetProperty(&it)); 3072 Object::GetProperty(&it));
3017 } 3073 }
3018 3074
3019 return *result; 3075 return *result;
3020 } 3076 }
3021 } // namespace internal 3077 } // namespace internal
3022 } // namespace v8 3078 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698