OLD | NEW |
---|---|
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...) Loading... | |
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...) Loading... | |
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...) Loading... | |
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...) Loading... | |
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 |
OLD | NEW |