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

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

Issue 2511603002: [ic] Support data handlers in LoadGlobalIC. (Closed)
Patch Set: fix 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 <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 546 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 } 557 }
558 558
559 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, 559 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
560 Handle<Object> handler) { 560 Handle<Object> handler) {
561 DCHECK(UseVector()); 561 DCHECK(UseVector());
562 if (kind() == Code::LOAD_IC) { 562 if (kind() == Code::LOAD_IC) {
563 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); 563 LoadICNexus* nexus = casted_nexus<LoadICNexus>();
564 nexus->ConfigureMonomorphic(map, handler); 564 nexus->ConfigureMonomorphic(map, handler);
565 } else if (kind() == Code::LOAD_GLOBAL_IC) { 565 } else if (kind() == Code::LOAD_GLOBAL_IC) {
566 LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>(); 566 LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
567 nexus->ConfigureHandlerMode(Handle<Code>::cast(handler)); 567 nexus->ConfigureHandlerMode(handler);
568 } else if (kind() == Code::KEYED_LOAD_IC) { 568 } else if (kind() == Code::KEYED_LOAD_IC) {
569 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); 569 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
570 nexus->ConfigureMonomorphic(name, map, handler); 570 nexus->ConfigureMonomorphic(name, map, handler);
571 } else if (kind() == Code::STORE_IC) { 571 } else if (kind() == Code::STORE_IC) {
572 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); 572 StoreICNexus* nexus = casted_nexus<StoreICNexus>();
573 nexus->ConfigureMonomorphic(map, handler); 573 nexus->ConfigureMonomorphic(map, handler);
574 } else { 574 } else {
575 DCHECK(kind() == Code::KEYED_STORE_IC); 575 DCHECK(kind() == Code::KEYED_STORE_IC);
576 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); 576 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
577 nexus->ConfigureMonomorphic(name, map, handler); 577 nexus->ConfigureMonomorphic(name, map, handler);
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
787 map_list.Add(handle(target_map)); 787 map_list.Add(handle(target_map));
788 transitioned_map = source_map->FindElementsKindTransitionedMap(&map_list); 788 transitioned_map = source_map->FindElementsKindTransitionedMap(&map_list);
789 } 789 }
790 return transitioned_map == target_map; 790 return transitioned_map == target_map;
791 } 791 }
792 792
793 void IC::PatchCache(Handle<Name> name, Handle<Object> handler) { 793 void IC::PatchCache(Handle<Name> name, Handle<Object> handler) {
794 DCHECK(IsHandler(*handler)); 794 DCHECK(IsHandler(*handler));
795 // Currently only LoadIC and KeyedLoadIC support non-code handlers. 795 // Currently only LoadIC and KeyedLoadIC support non-code handlers.
796 DCHECK_IMPLIES(!handler->IsCode(), kind() == Code::LOAD_IC || 796 DCHECK_IMPLIES(!handler->IsCode(), kind() == Code::LOAD_IC ||
797 kind() == Code::LOAD_GLOBAL_IC ||
797 kind() == Code::KEYED_LOAD_IC || 798 kind() == Code::KEYED_LOAD_IC ||
798 kind() == Code::STORE_IC || 799 kind() == Code::STORE_IC ||
799 kind() == Code::KEYED_STORE_IC); 800 kind() == Code::KEYED_STORE_IC);
800 switch (state()) { 801 switch (state()) {
801 case UNINITIALIZED: 802 case UNINITIALIZED:
802 case PREMONOMORPHIC: 803 case PREMONOMORPHIC:
803 UpdateMonomorphicIC(handler, name); 804 UpdateMonomorphicIC(handler, name);
804 break; 805 break;
805 case RECOMPUTE_HANDLER: 806 case RECOMPUTE_HANDLER:
806 case MONOMORPHIC: 807 case MONOMORPHIC:
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 } 852 }
852 853
853 namespace { 854 namespace {
854 855
855 template <bool fill_array = true> 856 template <bool fill_array = true>
856 int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map, 857 int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
857 Handle<JSObject> holder, Handle<FixedArray> array, 858 Handle<JSObject> holder, Handle<FixedArray> array,
858 Handle<Name> name, int first_index) { 859 Handle<Name> name, int first_index) {
859 DCHECK(holder.is_null() || holder->HasFastProperties()); 860 DCHECK(holder.is_null() || holder->HasFastProperties());
860 861
861 // The following kinds of receiver maps require custom handler compilation.
862 if (receiver_map->IsJSGlobalObjectMap()) {
863 return -1;
864 }
865 // 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
866 // passed the access check for current native context and the access 863 // passed the access check for current native context and the access
867 // can't be revoked. 864 // can't be revoked.
868 865
869 HandleScope scope(isolate); 866 HandleScope scope(isolate);
870 int checks_count = 0; 867 int checks_count = 0;
871 868
872 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) { 869 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) {
873 // The validity cell check for primitive and global proxy receivers does 870 // The validity cell check for primitive and global proxy receivers does
874 // not guarantee that certain native context ever had access to other 871 // not guarantee that certain native context ever had access to other
875 // native context. However, a handler created for one native context could 872 // native context. However, a handler created for one native context could
876 // be used in other native context through the megamorphic stub cache. 873 // be used in other native context through the megamorphic stub cache.
877 // So we record the original native context to which this handler 874 // So we record the original native context to which this handler
878 // corresponds. 875 // corresponds.
879 if (fill_array) { 876 if (fill_array) {
880 Handle<Context> native_context = isolate->native_context(); 877 Handle<Context> native_context = isolate->native_context();
881 array->set(LoadHandler::kFirstPrototypeIndex + checks_count, 878 array->set(LoadHandler::kFirstPrototypeIndex + checks_count,
882 native_context->self_weak_cell()); 879 native_context->self_weak_cell());
883 } 880 }
884 checks_count++; 881 checks_count++;
882
883 } else if (receiver_map->IsJSGlobalObjectMap()) {
884 if (fill_array) {
885 Handle<JSGlobalObject> global = isolate->global_object();
886 Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
887 global, name, PropertyCellType::kInvalidated);
888 DCHECK(cell->value()->IsTheHole(isolate));
889 Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
890 array->set(LoadHandler::kFirstPrototypeIndex + checks_count, *weak_cell);
891 }
892 checks_count++;
885 } 893 }
886 894
887 // Create/count entries for each global or dictionary prototype appeared in 895 // Create/count entries for each global or dictionary prototype appeared in
888 // the prototype chain contains from receiver till holder. 896 // the prototype chain contains from receiver till holder.
889 for (PrototypeIterator iter(receiver_map); !iter.IsAtEnd(); iter.Advance()) { 897 for (PrototypeIterator iter(receiver_map); !iter.IsAtEnd(); iter.Advance()) {
890 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); 898 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
891 if (holder.is_identical_to(current)) break; 899 if (holder.is_identical_to(current)) break;
892 Handle<Map> current_map(current->map(), isolate); 900 Handle<Map> current_map(current->map(), isolate);
893 901
894 if (current_map->IsJSGlobalObjectMap()) { 902 if (current_map->IsJSGlobalObjectMap()) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
930 } 938 }
931 939
932 } // namespace 940 } // namespace
933 941
934 Handle<Object> LoadIC::LoadFromPrototype(Handle<Map> receiver_map, 942 Handle<Object> LoadIC::LoadFromPrototype(Handle<Map> receiver_map,
935 Handle<JSObject> holder, 943 Handle<JSObject> holder,
936 Handle<Name> name, 944 Handle<Name> name,
937 Handle<Object> smi_handler) { 945 Handle<Object> smi_handler) {
938 int checks_count = GetPrototypeCheckCount(isolate(), receiver_map, holder); 946 int checks_count = GetPrototypeCheckCount(isolate(), receiver_map, holder);
939 DCHECK_LE(0, checks_count); 947 DCHECK_LE(0, checks_count);
940 DCHECK(!receiver_map->IsJSGlobalObjectMap());
941 948
942 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) { 949 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) {
943 DCHECK(!receiver_map->is_dictionary_map()); 950 DCHECK(!receiver_map->is_dictionary_map());
944 DCHECK_LE(1, checks_count); // For native context. 951 DCHECK_LE(1, checks_count); // For native context.
945 smi_handler = 952 smi_handler =
946 LoadHandler::EnableAccessCheckOnReceiver(isolate(), smi_handler); 953 LoadHandler::EnableAccessCheckOnReceiver(isolate(), smi_handler);
947 } else if (receiver_map->is_dictionary_map()) { 954 } else if (receiver_map->is_dictionary_map() &&
955 !receiver_map->IsJSGlobalObjectMap()) {
948 smi_handler = 956 smi_handler =
949 LoadHandler::EnableNegativeLookupOnReceiver(isolate(), smi_handler); 957 LoadHandler::EnableNegativeLookupOnReceiver(isolate(), smi_handler);
950 } 958 }
951 959
952 Handle<Cell> validity_cell = 960 Handle<Cell> validity_cell =
953 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); 961 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
954 DCHECK(!validity_cell.is_null()); 962 DCHECK(!validity_cell.is_null());
955 963
956 Handle<WeakCell> holder_cell = 964 Handle<WeakCell> holder_cell =
957 Map::GetOrCreatePrototypeWeakCell(holder, isolate()); 965 Map::GetOrCreatePrototypeWeakCell(holder, isolate());
(...skipping 10 matching lines...) Expand all
968 InitPrototypeChecks(isolate(), receiver_map, holder, handler_array, name, 976 InitPrototypeChecks(isolate(), receiver_map, holder, handler_array, name,
969 LoadHandler::kFirstPrototypeIndex); 977 LoadHandler::kFirstPrototypeIndex);
970 return handler_array; 978 return handler_array;
971 } 979 }
972 980
973 Handle<Object> LoadIC::LoadNonExistent(Handle<Map> receiver_map, 981 Handle<Object> LoadIC::LoadNonExistent(Handle<Map> receiver_map,
974 Handle<Name> name) { 982 Handle<Name> name) {
975 Handle<JSObject> holder; // null handle 983 Handle<JSObject> holder; // null handle
976 int checks_count = GetPrototypeCheckCount(isolate(), receiver_map, holder); 984 int checks_count = GetPrototypeCheckCount(isolate(), receiver_map, holder);
977 DCHECK_LE(0, checks_count); 985 DCHECK_LE(0, checks_count);
978 DCHECK(!receiver_map->IsJSGlobalObjectMap());
979 986
980 Handle<Object> smi_handler = LoadHandler::LoadNonExistent( 987 Handle<Object> smi_handler = LoadHandler::LoadNonExistent(
981 isolate(), receiver_map->is_dictionary_map()); 988 isolate(), receiver_map->is_dictionary_map());
982 989
983 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) { 990 if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) {
984 DCHECK(!receiver_map->is_dictionary_map()); 991 DCHECK(!receiver_map->is_dictionary_map());
985 DCHECK_LE(1, checks_count); // For native context. 992 DCHECK_LE(1, checks_count); // For native context.
986 smi_handler = 993 smi_handler =
987 LoadHandler::EnableAccessCheckOnReceiver(isolate(), smi_handler); 994 LoadHandler::EnableAccessCheckOnReceiver(isolate(), smi_handler);
988 } 995 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1059 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); 1066 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>());
1060 TRACE_IC("LoadIC", lookup->name()); 1067 TRACE_IC("LoadIC", lookup->name());
1061 return; 1068 return;
1062 } 1069 }
1063 1070
1064 Handle<Object> code; 1071 Handle<Object> code;
1065 if (lookup->state() == LookupIterator::JSPROXY || 1072 if (lookup->state() == LookupIterator::JSPROXY ||
1066 lookup->state() == LookupIterator::ACCESS_CHECK) { 1073 lookup->state() == LookupIterator::ACCESS_CHECK) {
1067 code = slow_stub(); 1074 code = slow_stub();
1068 } else if (!lookup->IsFound()) { 1075 } else if (!lookup->IsFound()) {
1069 if (kind() == Code::LOAD_IC) { 1076 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC) {
1070 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH); 1077 if (FLAG_tf_load_ic_stub) {
1071 code = LoadNonExistent(receiver_map(), lookup->name()); 1078 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH);
1072 } else if (kind() == Code::LOAD_GLOBAL_IC) { 1079 code = LoadNonExistent(receiver_map(), lookup->name());
1073 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), 1080 } else {
1074 receiver_map()); 1081 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(),
1075 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. 1082 receiver_map());
1076 if (code.is_null()) code = slow_stub(); 1083 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case.
1084 if (code.is_null()) code = slow_stub();
1085 }
1077 } else { 1086 } else {
1078 code = slow_stub(); 1087 code = slow_stub();
1079 } 1088 }
1080 } else { 1089 } else {
1081 if (kind() == Code::LOAD_GLOBAL_IC && 1090 if (kind() == Code::LOAD_GLOBAL_IC &&
1082 lookup->state() == LookupIterator::DATA && 1091 lookup->state() == LookupIterator::DATA &&
1083 lookup->GetHolder<Object>()->IsJSGlobalObject()) { 1092 lookup->GetHolder<Object>()->IsJSGlobalObject()) {
1084 #if DEBUG 1093 #if DEBUG
1085 Handle<Object> holder = lookup->GetHolder<Object>(); 1094 Handle<Object> holder = lookup->GetHolder<Object>();
1086 Handle<Object> receiver = lookup->GetReceiver(); 1095 Handle<Object> receiver = lookup->GetReceiver();
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
1394 return isolate()->builtins()->LoadIC_Normal(); 1403 return isolate()->builtins()->LoadIC_Normal();
1395 } 1404 }
1396 1405
1397 // -------------- Fields -------------- 1406 // -------------- Fields --------------
1398 if (lookup->property_details().type() == DATA) { 1407 if (lookup->property_details().type() == DATA) {
1399 FieldIndex field = lookup->GetFieldIndex(); 1408 FieldIndex field = lookup->GetFieldIndex();
1400 Handle<Object> smi_handler = SimpleFieldLoad(field); 1409 Handle<Object> smi_handler = SimpleFieldLoad(field);
1401 if (receiver_is_holder) { 1410 if (receiver_is_holder) {
1402 return smi_handler; 1411 return smi_handler;
1403 } 1412 }
1404 if (FLAG_tf_load_ic_stub && kind() != Code::LOAD_GLOBAL_IC) { 1413 if (FLAG_tf_load_ic_stub) {
1405 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH); 1414 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH);
1406 return LoadFromPrototype(map, holder, lookup->name(), smi_handler); 1415 return LoadFromPrototype(map, holder, lookup->name(), smi_handler);
1407 } 1416 }
1408 break; // Custom-compiled handler. 1417 break; // Custom-compiled handler.
1409 } 1418 }
1410 1419
1411 // -------------- Constant properties -------------- 1420 // -------------- Constant properties --------------
1412 DCHECK(lookup->property_details().type() == DATA_CONSTANT); 1421 DCHECK(lookup->property_details().type() == DATA_CONSTANT);
1413 if (FLAG_tf_load_ic_stub) { 1422 if (FLAG_tf_load_ic_stub) {
1414 Handle<Object> smi_handler = 1423 Handle<Object> smi_handler =
1415 LoadHandler::LoadConstant(isolate(), lookup->GetConstantIndex()); 1424 LoadHandler::LoadConstant(isolate(), lookup->GetConstantIndex());
1416 if (receiver_is_holder) { 1425 if (receiver_is_holder) {
1417 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH); 1426 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH);
1418 return smi_handler; 1427 return smi_handler;
1419 } 1428 }
1420 if (kind() != Code::LOAD_GLOBAL_IC) { 1429 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH);
1421 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH); 1430 return LoadFromPrototype(map, holder, lookup->name(), smi_handler);
1422 return LoadFromPrototype(map, holder, lookup->name(), smi_handler);
1423 }
1424 } else { 1431 } else {
1425 if (receiver_is_holder) { 1432 if (receiver_is_holder) {
1426 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub); 1433 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub);
1427 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); 1434 LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
1428 return stub.GetCode(); 1435 return stub.GetCode();
1429 } 1436 }
1430 } 1437 }
1431 break; // Custom-compiled handler. 1438 break; // Custom-compiled handler.
1432 } 1439 }
1433 1440
(...skipping 1806 matching lines...) Expand 10 before | Expand all | Expand 10 after
3240 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); 3247 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
3241 it.Next(); 3248 it.Next();
3242 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, 3249 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3243 Object::GetProperty(&it)); 3250 Object::GetProperty(&it));
3244 } 3251 }
3245 3252
3246 return *result; 3253 return *result;
3247 } 3254 }
3248 } // namespace internal 3255 } // namespace internal
3249 } // namespace v8 3256 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698