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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand 10 before | Expand all | Expand 10 after 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 DCHECK(!receiver_map->IsJSGlobalObjectMap()); |
| 959 |
| 960 Handle<Object> smi_handler = LoadHandler::LoadNonExistent( |
| 961 isolate(), receiver_map->is_dictionary_map()); |
| 962 |
| 963 Handle<Object> validity_cell = |
| 964 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); |
| 965 if (validity_cell.is_null()) { |
| 966 // This must be a case when receiver's prototype is null. |
| 967 DCHECK_EQ(*isolate()->factory()->null_value(), |
| 968 receiver_map->GetPrototypeChainRootMap(isolate())->prototype()); |
| 969 DCHECK_EQ(0, checks_count); |
| 970 validity_cell = handle(Smi::FromInt(0), isolate()); |
| 971 } |
| 972 |
| 973 Factory* factory = isolate()->factory(); |
| 974 if (checks_count == 0) { |
| 975 return factory->NewTuple3(factory->null_value(), smi_handler, |
| 976 validity_cell); |
| 977 } |
| 978 Handle<FixedArray> handler_array(factory->NewFixedArray( |
| 979 LoadHandler::kFirstPrototypeIndex + checks_count, TENURED)); |
| 980 handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler); |
| 981 handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell); |
| 982 handler_array->set(LoadHandler::kHolderCellIndex, *factory->null_value()); |
| 983 InitPrototypeChecks<true>(isolate(), receiver_map, holder, handler_array, |
| 984 name); |
| 985 return handler_array; |
| 986 } |
| 987 |
953 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) { | 988 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) { |
954 DCHECK(lookup->state() == LookupIterator::ACCESSOR); | 989 DCHECK(lookup->state() == LookupIterator::ACCESSOR); |
955 Isolate* isolate = lookup->isolate(); | 990 Isolate* isolate = lookup->isolate(); |
956 Handle<Object> accessors = lookup->GetAccessors(); | 991 Handle<Object> accessors = lookup->GetAccessors(); |
957 if (accessors->IsAccessorInfo()) { | 992 if (accessors->IsAccessorInfo()) { |
958 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); | 993 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); |
959 if (info->getter() != NULL && | 994 if (info->getter() != NULL && |
960 !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) { | 995 !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) { |
961 return false; | 996 return false; |
962 } | 997 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
997 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); | 1032 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); |
998 TRACE_IC("LoadIC", lookup->name()); | 1033 TRACE_IC("LoadIC", lookup->name()); |
999 return; | 1034 return; |
1000 } | 1035 } |
1001 | 1036 |
1002 Handle<Object> code; | 1037 Handle<Object> code; |
1003 if (lookup->state() == LookupIterator::JSPROXY || | 1038 if (lookup->state() == LookupIterator::JSPROXY || |
1004 lookup->state() == LookupIterator::ACCESS_CHECK) { | 1039 lookup->state() == LookupIterator::ACCESS_CHECK) { |
1005 code = slow_stub(); | 1040 code = slow_stub(); |
1006 } else if (!lookup->IsFound()) { | 1041 } else if (!lookup->IsFound()) { |
1007 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC) { | 1042 if (kind() == Code::LOAD_IC) { |
| 1043 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH); |
| 1044 code = SimpleLoadNonExistent(receiver_map(), lookup->name()); |
| 1045 } else if (kind() == Code::LOAD_GLOBAL_IC) { |
1008 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), | 1046 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), |
1009 receiver_map()); | 1047 receiver_map()); |
1010 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. | 1048 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. |
1011 if (code.is_null()) code = slow_stub(); | 1049 if (code.is_null()) code = slow_stub(); |
1012 } else { | 1050 } else { |
1013 code = slow_stub(); | 1051 code = slow_stub(); |
1014 } | 1052 } |
1015 } else { | 1053 } else { |
1016 if (kind() == Code::LOAD_GLOBAL_IC && | 1054 if (kind() == Code::LOAD_GLOBAL_IC && |
1017 lookup->state() == LookupIterator::DATA && | 1055 lookup->state() == LookupIterator::DATA && |
(...skipping 2116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3134 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); | 3172 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); |
3135 it.Next(); | 3173 it.Next(); |
3136 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 3174 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
3137 Object::GetProperty(&it)); | 3175 Object::GetProperty(&it)); |
3138 } | 3176 } |
3139 | 3177 |
3140 return *result; | 3178 return *result; |
3141 } | 3179 } |
3142 } // namespace internal | 3180 } // namespace internal |
3143 } // namespace v8 | 3181 } // namespace v8 |
OLD | NEW |