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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
183 Code* IC::GetOriginalCode() const { | 183 Code* IC::GetOriginalCode() const { |
184 HandleScope scope(isolate()); | 184 HandleScope scope(isolate()); |
185 Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate()); | 185 Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate()); |
186 ASSERT(Debug::HasDebugInfo(shared)); | 186 ASSERT(Debug::HasDebugInfo(shared)); |
187 Code* original_code = Debug::GetDebugInfo(shared)->original_code(); | 187 Code* original_code = Debug::GetDebugInfo(shared)->original_code(); |
188 ASSERT(original_code->IsCode()); | 188 ASSERT(original_code->IsCode()); |
189 return original_code; | 189 return original_code; |
190 } | 190 } |
191 | 191 |
192 | 192 |
193 static bool HasInterceptorGetter(JSObject* object) { | |
194 return !object->GetNamedInterceptor()->getter()->IsUndefined(); | |
195 } | |
196 | |
197 | |
198 static bool HasInterceptorSetter(JSObject* object) { | 193 static bool HasInterceptorSetter(JSObject* object) { |
199 return !object->GetNamedInterceptor()->setter()->IsUndefined(); | 194 return !object->GetNamedInterceptor()->setter()->IsUndefined(); |
200 } | 195 } |
201 | 196 |
202 | 197 |
203 static void LookupForRead(Handle<Object> object, | 198 static void LookupForRead(LookupIterator* it) { |
204 Handle<String> name, | 199 for (; it->IsFound(); it->Next()) { |
205 LookupResult* lookup) { | 200 switch (it->state()) { |
206 // Skip all the objects with named interceptors, but | 201 case LookupIterator::NOT_FOUND: |
207 // without actual getter. | 202 UNREACHABLE(); |
208 while (true) { | 203 case LookupIterator::JSPROXY: |
209 object->Lookup(name, lookup); | 204 return; |
210 // Besides normal conditions (property not found or it's not | 205 case LookupIterator::INTERCEPTOR: { |
211 // an interceptor), bail out if lookup is not cacheable: we won't | 206 // If there is a getter, return; otherwise loop to perform the lookup. |
212 // be able to IC it anyway and regular lookup should work fine. | 207 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
213 if (!lookup->IsInterceptor() || !lookup->IsCacheable()) { | 208 if (!holder->GetNamedInterceptor()->getter()->IsUndefined()) { |
Toon Verwaest
2014/07/30 16:54:52
In the future we should probably get the property
Jakob Kummerow
2014/07/31 13:55:51
But that assumes that the interceptor never change
| |
214 return; | 209 return; |
210 } | |
211 break; | |
212 } | |
213 case LookupIterator::ACCESS_CHECK: | |
214 return; | |
215 case LookupIterator::PROPERTY: | |
216 if (it->HasProperty()) return; // Yay! | |
217 break; | |
215 } | 218 } |
216 | |
217 Handle<JSObject> holder(lookup->holder(), lookup->isolate()); | |
218 if (HasInterceptorGetter(*holder)) { | |
219 return; | |
220 } | |
221 | |
222 holder->LookupOwnRealNamedProperty(name, lookup); | |
223 if (lookup->IsFound()) { | |
224 ASSERT(!lookup->IsInterceptor()); | |
225 return; | |
226 } | |
227 | |
228 PrototypeIterator iter(lookup->isolate(), holder); | |
229 if (iter.IsAtEnd()) { | |
230 ASSERT(!lookup->IsFound()); | |
231 return; | |
232 } | |
233 | |
234 object = PrototypeIterator::GetCurrent(iter); | |
235 } | 219 } |
236 } | 220 } |
237 | 221 |
238 | 222 |
239 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, | 223 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, |
240 Handle<String> name) { | 224 Handle<String> name) { |
241 if (!IsNameCompatibleWithPrototypeFailure(name)) return false; | 225 if (!IsNameCompatibleWithPrototypeFailure(name)) return false; |
242 Handle<Map> receiver_map = TypeToMap(*receiver_type(), isolate()); | 226 Handle<Map> receiver_map = TypeToMap(*receiver_type(), isolate()); |
243 maybe_handler_ = target()->FindHandlerForMap(*receiver_map); | 227 maybe_handler_ = target()->FindHandlerForMap(*receiver_map); |
244 | 228 |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
567 isolate(), | 551 isolate(), |
568 result, | 552 result, |
569 Runtime::GetElementOrCharAt(isolate(), object, index), | 553 Runtime::GetElementOrCharAt(isolate(), object, index), |
570 Object); | 554 Object); |
571 return result; | 555 return result; |
572 } | 556 } |
573 | 557 |
574 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; | 558 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; |
575 | 559 |
576 // Named lookup in the object. | 560 // Named lookup in the object. |
577 LookupResult lookup(isolate()); | 561 LookupIterator it(object, name); |
578 LookupForRead(object, name, &lookup); | 562 LookupForRead(&it); |
579 | 563 |
580 // If we did not find a property, check if we need to throw an exception. | 564 // If we did not find a property, check if we need to throw an exception. |
581 if (!lookup.IsFound()) { | 565 if (!it.IsFound()) { |
582 if (IsUndeclaredGlobal(object)) { | 566 if (IsUndeclaredGlobal(object)) { |
583 return ReferenceError("not_defined", name); | 567 return ReferenceError("not_defined", name); |
584 } | 568 } |
585 LOG(isolate(), SuspectReadEvent(*name, *object)); | 569 LOG(isolate(), SuspectReadEvent(*name, *object)); |
586 } | 570 } |
587 | 571 |
588 // Update inline cache and stub cache. | 572 // Update inline cache and stub cache. |
589 if (use_ic) UpdateCaches(&lookup, object, name); | 573 if (use_ic) UpdateCaches(&it, object, name); |
590 | 574 |
591 // Get the property. | 575 // Get the property. |
592 LookupIterator it(object, name); | |
593 Handle<Object> result; | 576 Handle<Object> result; |
594 ASSIGN_RETURN_ON_EXCEPTION( | 577 ASSIGN_RETURN_ON_EXCEPTION( |
595 isolate(), result, Object::GetProperty(&it), Object); | 578 isolate(), result, Object::GetProperty(&it), Object); |
596 // If the property is not present, check if we need to throw an exception. | 579 // If the property is not present, check if we need to throw an exception. |
597 if ((lookup.IsInterceptor() || lookup.IsHandler()) && | 580 if (!it.IsFound() && IsUndeclaredGlobal(object)) { |
598 !it.IsFound() && IsUndeclaredGlobal(object)) { | |
599 return ReferenceError("not_defined", name); | 581 return ReferenceError("not_defined", name); |
600 } | 582 } |
601 | 583 |
602 return result; | 584 return result; |
603 } | 585 } |
604 | 586 |
605 | 587 |
606 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, | 588 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, |
607 Handle<Map> new_receiver_map) { | 589 Handle<Map> new_receiver_map) { |
608 ASSERT(!new_receiver_map.is_null()); | 590 ASSERT(!new_receiver_map.is_null()); |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
821 } | 803 } |
822 } | 804 } |
823 | 805 |
824 | 806 |
825 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { | 807 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { |
826 LoadFieldStub stub(isolate(), index); | 808 LoadFieldStub stub(isolate(), index); |
827 return stub.GetCode(); | 809 return stub.GetCode(); |
828 } | 810 } |
829 | 811 |
830 | 812 |
831 void LoadIC::UpdateCaches(LookupResult* lookup, | 813 void LoadIC::UpdateCaches(LookupIterator* lookup, Handle<Object> object, |
832 Handle<Object> object, | |
833 Handle<String> name) { | 814 Handle<String> name) { |
834 if (state() == UNINITIALIZED) { | 815 if (state() == UNINITIALIZED) { |
835 // This is the first time we execute this inline cache. | 816 // This is the first time we execute this inline cache. |
836 // Set the target to the pre monomorphic stub to delay | 817 // Set the target to the pre monomorphic stub to delay |
837 // setting the monomorphic state. | 818 // setting the monomorphic state. |
838 set_target(*pre_monomorphic_stub()); | 819 set_target(*pre_monomorphic_stub()); |
839 TRACE_IC("LoadIC", name); | 820 TRACE_IC("LoadIC", name); |
840 return; | 821 return; |
841 } | 822 } |
842 | 823 |
843 Handle<Code> code; | 824 Handle<Code> code; |
844 if (!lookup->IsCacheable()) { | 825 if (lookup->state() == LookupIterator::JSPROXY || |
845 // Bail out if the result is not cacheable. | 826 lookup->state() == LookupIterator::ACCESS_CHECK) { |
846 code = slow_stub(); | 827 code = slow_stub(); |
847 } else if (!lookup->IsProperty()) { | 828 } else if (!lookup->IsFound()) { |
848 if (kind() == Code::LOAD_IC) { | 829 if (kind() == Code::LOAD_IC) { |
849 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(name, | 830 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(name, |
850 receiver_type()); | 831 receiver_type()); |
851 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. | 832 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. |
852 if (code.is_null()) code = slow_stub(); | 833 if (code.is_null()) code = slow_stub(); |
853 } else { | 834 } else { |
854 code = slow_stub(); | 835 code = slow_stub(); |
855 } | 836 } |
856 } else { | 837 } else { |
857 code = ComputeHandler(lookup, object, name); | 838 code = ComputeHandler(lookup, object, name); |
858 } | 839 } |
859 | 840 |
860 PatchCache(name, code); | 841 PatchCache(name, code); |
861 TRACE_IC("LoadIC", name); | 842 TRACE_IC("LoadIC", name); |
862 } | 843 } |
863 | 844 |
864 | 845 |
865 void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) { | 846 void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) { |
866 if (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC) return; | 847 if (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC) return; |
867 Map* map = *TypeToMap(type, isolate()); | 848 Map* map = *TypeToMap(type, isolate()); |
868 isolate()->stub_cache()->Set(name, map, code); | 849 isolate()->stub_cache()->Set(name, map, code); |
869 } | 850 } |
870 | 851 |
871 | 852 |
872 Handle<Code> IC::ComputeHandler(LookupResult* lookup, | 853 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> object, |
873 Handle<Object> object, | 854 Handle<String> name, Handle<Object> value) { |
874 Handle<String> name, | 855 bool receiver_is_holder = lookup->HolderIsReceiver(); |
Toon Verwaest
2014/07/30 16:54:53
These 2 things are different.
Rename HolderIsRecei
Jakob Kummerow
2014/07/31 13:55:51
Done.
| |
875 Handle<Object> value) { | 856 CacheHolderFlag flag; |
857 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( | |
858 *receiver_type(), receiver_is_holder, isolate(), &flag); | |
859 | |
860 Handle<Code> code = PropertyHandlerCompiler::Find( | |
861 name, stub_holder_map, kind(), flag, | |
862 lookup->has_fast_properties() ? Code::FAST : Code::NORMAL); | |
Toon Verwaest
2014/07/30 16:54:53
What about just doing lookup->holder_map()->is_dic
Jakob Kummerow
2014/07/31 13:55:51
Done.
| |
863 // Use the cached value if it exists, and if it is different from the | |
864 // handler that just missed. | |
865 if (!code.is_null()) { | |
866 if (!maybe_handler_.is_null() && | |
867 !maybe_handler_.ToHandleChecked().is_identical_to(code)) { | |
868 return code; | |
869 } | |
870 if (maybe_handler_.is_null()) { | |
871 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs. | |
872 // In MEGAMORPHIC case, check if the handler in the megamorphic stub | |
873 // cache (which just missed) is different from the cached handler. | |
874 if (state() == MEGAMORPHIC && object->IsHeapObject()) { | |
875 Map* map = Handle<HeapObject>::cast(object)->map(); | |
876 Code* megamorphic_cached_code = | |
877 isolate()->stub_cache()->Get(*name, map, code->flags()); | |
878 if (megamorphic_cached_code != *code) return code; | |
879 } else { | |
880 return code; | |
881 } | |
882 } | |
883 } | |
884 | |
885 code = CompileHandler(lookup, object, name, value, flag); | |
886 ASSERT(code->is_handler()); | |
887 | |
888 if (code->type() != Code::NORMAL) { | |
889 Map::UpdateCodeCache(stub_holder_map, name, code); | |
890 } | |
891 | |
892 return code; | |
893 } | |
894 | |
895 | |
896 Handle<Code> IC::ComputeStoreHandler(LookupResult* lookup, | |
897 Handle<Object> object, Handle<String> name, | |
898 Handle<Object> value) { | |
876 bool receiver_is_holder = lookup->ReceiverIsHolder(object); | 899 bool receiver_is_holder = lookup->ReceiverIsHolder(object); |
877 CacheHolderFlag flag; | 900 CacheHolderFlag flag; |
878 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( | 901 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( |
879 *receiver_type(), receiver_is_holder, isolate(), &flag); | 902 *receiver_type(), receiver_is_holder, isolate(), &flag); |
880 | 903 |
881 Handle<Code> code = PropertyHandlerCompiler::Find( | 904 Handle<Code> code = PropertyHandlerCompiler::Find( |
882 name, stub_holder_map, handler_kind(), flag, | 905 name, stub_holder_map, handler_kind(), flag, |
883 lookup->holder()->HasFastProperties() ? Code::FAST : Code::NORMAL); | 906 lookup->holder()->HasFastProperties() ? Code::FAST : Code::NORMAL); |
884 // Use the cached value if it exists, and if it is different from the | 907 // Use the cached value if it exists, and if it is different from the |
885 // handler that just missed. | 908 // handler that just missed. |
(...skipping 10 matching lines...) Expand all Loading... | |
896 Map* map = Handle<HeapObject>::cast(object)->map(); | 919 Map* map = Handle<HeapObject>::cast(object)->map(); |
897 Code* megamorphic_cached_code = | 920 Code* megamorphic_cached_code = |
898 isolate()->stub_cache()->Get(*name, map, code->flags()); | 921 isolate()->stub_cache()->Get(*name, map, code->flags()); |
899 if (megamorphic_cached_code != *code) return code; | 922 if (megamorphic_cached_code != *code) return code; |
900 } else { | 923 } else { |
901 return code; | 924 return code; |
902 } | 925 } |
903 } | 926 } |
904 } | 927 } |
905 | 928 |
906 code = CompileHandler(lookup, object, name, value, flag); | 929 code = CompileStoreHandler(lookup, object, name, value, flag); |
907 ASSERT(code->is_handler()); | 930 ASSERT(code->is_handler()); |
908 | 931 |
909 if (code->type() != Code::NORMAL) { | 932 if (code->type() != Code::NORMAL) { |
910 Map::UpdateCodeCache(stub_holder_map, name, code); | 933 Map::UpdateCodeCache(stub_holder_map, name, code); |
911 } | 934 } |
912 | 935 |
913 return code; | 936 return code; |
914 } | 937 } |
915 | 938 |
916 | 939 |
917 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, Handle<Object> object, | 940 Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup, |
918 Handle<String> name, Handle<Object> unused, | 941 Handle<Object> object, Handle<String> name, |
942 Handle<Object> unused, | |
919 CacheHolderFlag cache_holder) { | 943 CacheHolderFlag cache_holder) { |
920 if (object->IsString() && | 944 if (object->IsString() && |
921 String::Equals(isolate()->factory()->length_string(), name)) { | 945 String::Equals(isolate()->factory()->length_string(), name)) { |
922 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); | 946 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); |
923 return SimpleFieldLoad(index); | 947 return SimpleFieldLoad(index); |
924 } | 948 } |
925 | 949 |
926 if (object->IsStringWrapper() && | 950 if (object->IsStringWrapper() && |
927 String::Equals(isolate()->factory()->length_string(), name)) { | 951 String::Equals(isolate()->factory()->length_string(), name)) { |
928 StringLengthStub string_length_stub(isolate()); | 952 StringLengthStub string_length_stub(isolate()); |
929 return string_length_stub.GetCode(); | 953 return string_length_stub.GetCode(); |
930 } | 954 } |
931 | 955 |
932 // Use specialized code for getting prototype of functions. | 956 // Use specialized code for getting prototype of functions. |
933 if (object->IsJSFunction() && | 957 if (object->IsJSFunction() && |
934 String::Equals(isolate()->factory()->prototype_string(), name) && | 958 String::Equals(isolate()->factory()->prototype_string(), name) && |
935 Handle<JSFunction>::cast(object)->should_have_prototype() && | 959 Handle<JSFunction>::cast(object)->should_have_prototype() && |
936 !Handle<JSFunction>::cast(object)->map()->has_non_instance_prototype()) { | 960 !Handle<JSFunction>::cast(object)->map()->has_non_instance_prototype()) { |
937 Handle<Code> stub; | 961 Handle<Code> stub; |
938 FunctionPrototypeStub function_prototype_stub(isolate()); | 962 FunctionPrototypeStub function_prototype_stub(isolate()); |
939 return function_prototype_stub.GetCode(); | 963 return function_prototype_stub.GetCode(); |
940 } | 964 } |
941 | 965 |
942 Handle<HeapType> type = receiver_type(); | 966 Handle<HeapType> type = receiver_type(); |
943 Handle<JSObject> holder(lookup->holder()); | 967 Handle<JSObject> holder(lookup->GetHolder<JSObject>()); |
Toon Verwaest
2014/07/30 16:54:52
Handle<JSObject> holder = lookup->GetHolder<JSObje
Jakob Kummerow
2014/07/31 13:55:50
Done.
| |
944 bool receiver_is_holder = object.is_identical_to(holder); | 968 bool receiver_is_holder = object.is_identical_to(holder); |
945 NamedLoadHandlerCompiler compiler(isolate(), cache_holder); | 969 NamedLoadHandlerCompiler compiler(isolate(), cache_holder); |
946 | 970 |
947 switch (lookup->type()) { | 971 if (lookup->state() == LookupIterator::INTERCEPTOR) { |
972 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | |
973 return compiler.CompileLoadInterceptor(type, holder, name); | |
974 } | |
975 ASSERT(lookup->state() == LookupIterator::PROPERTY); | |
976 | |
977 switch (lookup->property_details().type()) { | |
Toon Verwaest
2014/07/30 16:54:52
What about doing the same as GetProperty; using pr
Jakob Kummerow
2014/07/31 13:55:51
Done.
| |
948 case FIELD: { | 978 case FIELD: { |
949 FieldIndex field = lookup->GetFieldIndex(); | 979 FieldIndex field = lookup->GetFieldIndex(); |
950 if (receiver_is_holder) { | 980 if (receiver_is_holder) { |
951 return SimpleFieldLoad(field); | 981 return SimpleFieldLoad(field); |
952 } | 982 } |
953 return compiler.CompileLoadField( | 983 return compiler.CompileLoadField( |
954 type, holder, name, field, lookup->representation()); | 984 type, holder, name, field, lookup->representation()); |
955 } | 985 } |
956 case CONSTANT: { | 986 case CONSTANT: { |
957 Handle<Object> constant(lookup->GetConstant(), isolate()); | 987 Handle<Object> constant = lookup->GetDataValue(); |
958 return compiler.CompileLoadConstant(type, holder, name, constant); | 988 return compiler.CompileLoadConstant(type, holder, name, constant); |
959 } | 989 } |
960 case NORMAL: | 990 case NORMAL: |
961 if (kind() != Code::LOAD_IC) break; | 991 if (kind() != Code::LOAD_IC) break; |
962 if (holder->IsGlobalObject()) { | 992 if (holder->IsGlobalObject()) { |
963 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); | 993 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); |
964 Handle<PropertyCell> cell( | 994 Handle<PropertyCell> cell( |
965 global->GetPropertyCell(lookup), isolate()); | 995 global->GetPropertyCell(lookup), isolate()); |
966 Handle<Code> code = compiler.CompileLoadGlobal( | 996 Handle<Code> code = compiler.CompileLoadGlobal( |
967 type, global, cell, name, lookup->IsDontDelete()); | 997 type, global, cell, name, !lookup->IsConfigurable()); |
Toon Verwaest
2014/07/30 16:54:52
What about changing the interface of CompileLoadGl
Jakob Kummerow
2014/07/31 13:55:51
Done.
| |
968 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 998 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
969 CacheHolderFlag flag; | 999 CacheHolderFlag flag; |
970 Handle<Map> stub_holder_map = | 1000 Handle<Map> stub_holder_map = |
971 GetHandlerCacheHolder(*type, receiver_is_holder, isolate(), &flag); | 1001 GetHandlerCacheHolder(*type, receiver_is_holder, isolate(), &flag); |
972 Map::UpdateCodeCache(stub_holder_map, name, code); | 1002 Map::UpdateCodeCache(stub_holder_map, name, code); |
973 return code; | 1003 return code; |
974 } | 1004 } |
975 // There is only one shared stub for loading normalized | 1005 // There is only one shared stub for loading normalized |
976 // properties. It does not traverse the prototype chain, so the | 1006 // properties. It does not traverse the prototype chain, so the |
977 // property must be found in the object for the stub to be | 1007 // property must be found in the object for the stub to be |
978 // applicable. | 1008 // applicable. |
979 if (!receiver_is_holder) break; | 1009 if (!receiver_is_holder) break; |
980 return isolate()->builtins()->LoadIC_Normal(); | 1010 return isolate()->builtins()->LoadIC_Normal(); |
981 case CALLBACKS: { | 1011 case CALLBACKS: { |
982 // Use simple field loads for some well-known callback properties. | 1012 // Use simple field loads for some well-known callback properties. |
983 if (receiver_is_holder) { | 1013 if (receiver_is_holder) { |
984 ASSERT(object->IsJSObject()); | 1014 ASSERT(object->IsJSObject()); |
985 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1015 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
986 int object_offset; | 1016 int object_offset; |
987 if (Accessors::IsJSObjectFieldAccessor<HeapType>( | 1017 if (Accessors::IsJSObjectFieldAccessor<HeapType>( |
988 type, name, &object_offset)) { | 1018 type, name, &object_offset)) { |
989 FieldIndex index = FieldIndex::ForInObjectOffset( | 1019 FieldIndex index = FieldIndex::ForInObjectOffset( |
990 object_offset, receiver->map()); | 1020 object_offset, receiver->map()); |
991 return SimpleFieldLoad(index); | 1021 return SimpleFieldLoad(index); |
992 } | 1022 } |
993 } | 1023 } |
994 | 1024 |
995 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); | 1025 Handle<Object> accessors = lookup->GetAccessors(); |
996 if (callback->IsExecutableAccessorInfo()) { | 1026 if (accessors->IsExecutableAccessorInfo()) { |
997 Handle<ExecutableAccessorInfo> info = | 1027 Handle<ExecutableAccessorInfo> info = |
998 Handle<ExecutableAccessorInfo>::cast(callback); | 1028 Handle<ExecutableAccessorInfo>::cast(accessors); |
999 if (v8::ToCData<Address>(info->getter()) == 0) break; | 1029 if (v8::ToCData<Address>(info->getter()) == 0) break; |
1000 if (!info->IsCompatibleReceiver(*object)) break; | 1030 if (!info->IsCompatibleReceiver(*object)) break; |
1001 return compiler.CompileLoadCallback(type, holder, name, info); | 1031 return compiler.CompileLoadCallback(type, holder, name, info); |
1002 } else if (callback->IsAccessorPair()) { | 1032 } else if (accessors->IsAccessorPair()) { |
1003 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), | 1033 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), |
1004 isolate()); | 1034 isolate()); |
1005 if (!getter->IsJSFunction()) break; | 1035 if (!getter->IsJSFunction()) break; |
1006 if (holder->IsGlobalObject()) break; | 1036 if (holder->IsGlobalObject()) break; |
1007 if (!holder->HasFastProperties()) break; | 1037 if (!holder->HasFastProperties()) break; |
1008 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); | 1038 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); |
1009 if (!object->IsJSObject() && | 1039 if (!object->IsJSObject() && |
1010 !function->IsBuiltin() && | 1040 !function->IsBuiltin() && |
1011 function->shared()->strict_mode() == SLOPPY) { | 1041 function->shared()->strict_mode() == SLOPPY) { |
1012 // Calling sloppy non-builtins with a value as the receiver | 1042 // Calling sloppy non-builtins with a value as the receiver |
1013 // requires boxing. | 1043 // requires boxing. |
1014 break; | 1044 break; |
1015 } | 1045 } |
1016 CallOptimization call_optimization(function); | 1046 CallOptimization call_optimization(function); |
1017 if (call_optimization.is_simple_api_call() && | 1047 if (call_optimization.is_simple_api_call() && |
1018 call_optimization.IsCompatibleReceiver(object, holder)) { | 1048 call_optimization.IsCompatibleReceiver(object, holder)) { |
1019 return compiler.CompileLoadCallback( | 1049 return compiler.CompileLoadCallback( |
1020 type, holder, name, call_optimization); | 1050 type, holder, name, call_optimization); |
1021 } | 1051 } |
1022 return compiler.CompileLoadViaGetter(type, holder, name, function); | 1052 return compiler.CompileLoadViaGetter(type, holder, name, function); |
1023 } | 1053 } |
1024 // TODO(dcarney): Handle correctly. | 1054 // TODO(dcarney): Handle correctly. |
1025 ASSERT(callback->IsDeclaredAccessorInfo()); | 1055 ASSERT(accessors->IsDeclaredAccessorInfo()); |
1026 break; | 1056 break; |
1027 } | 1057 } |
1028 case INTERCEPTOR: | |
1029 ASSERT(HasInterceptorGetter(*holder)); | |
1030 return compiler.CompileLoadInterceptor(type, holder, name); | |
1031 default: | 1058 default: |
1032 break; | 1059 break; |
1033 } | 1060 } |
1034 | 1061 |
1035 return slow_stub(); | 1062 return slow_stub(); |
1036 } | 1063 } |
1037 | 1064 |
1038 | 1065 |
1039 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { | 1066 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { |
1040 // This helper implements a few common fast cases for converting | 1067 // This helper implements a few common fast cases for converting |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1367 | 1394 |
1368 void StoreIC::UpdateCaches(LookupResult* lookup, | 1395 void StoreIC::UpdateCaches(LookupResult* lookup, |
1369 Handle<JSObject> receiver, | 1396 Handle<JSObject> receiver, |
1370 Handle<String> name, | 1397 Handle<String> name, |
1371 Handle<Object> value) { | 1398 Handle<Object> value) { |
1372 ASSERT(lookup->IsFound()); | 1399 ASSERT(lookup->IsFound()); |
1373 | 1400 |
1374 // These are not cacheable, so we never see such LookupResults here. | 1401 // These are not cacheable, so we never see such LookupResults here. |
1375 ASSERT(!lookup->IsHandler()); | 1402 ASSERT(!lookup->IsHandler()); |
1376 | 1403 |
1377 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); | 1404 Handle<Code> code = ComputeStoreHandler(lookup, receiver, name, value); |
1378 | 1405 |
1379 PatchCache(name, code); | 1406 PatchCache(name, code); |
1380 TRACE_IC("StoreIC", name); | 1407 TRACE_IC("StoreIC", name); |
1381 } | 1408 } |
1382 | 1409 |
1383 | 1410 |
1384 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, | 1411 Handle<Code> StoreIC::CompileStoreHandler(LookupResult* lookup, |
1385 Handle<Object> object, Handle<String> name, | 1412 Handle<Object> object, |
1386 Handle<Object> value, | 1413 Handle<String> name, |
1387 CacheHolderFlag cache_holder) { | 1414 Handle<Object> value, |
1415 CacheHolderFlag cache_holder) { | |
1388 if (object->IsAccessCheckNeeded()) return slow_stub(); | 1416 if (object->IsAccessCheckNeeded()) return slow_stub(); |
1389 ASSERT(cache_holder == kCacheOnReceiver || lookup->type() == CALLBACKS || | 1417 ASSERT(cache_holder == kCacheOnReceiver || lookup->type() == CALLBACKS || |
1390 (object->IsJSGlobalProxy() && lookup->holder()->IsJSGlobalObject())); | 1418 (object->IsJSGlobalProxy() && lookup->holder()->IsJSGlobalObject())); |
1391 // This is currently guaranteed by checks in StoreIC::Store. | 1419 // This is currently guaranteed by checks in StoreIC::Store. |
1392 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1420 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1393 | 1421 |
1394 Handle<JSObject> holder(lookup->holder()); | 1422 Handle<JSObject> holder(lookup->holder()); |
1395 NamedStoreHandlerCompiler compiler(isolate()); | 1423 NamedStoreHandlerCompiler compiler(isolate()); |
1396 | 1424 |
1397 if (lookup->IsTransition()) { | 1425 if (lookup->IsTransition()) { |
(...skipping 1650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3048 #undef ADDR | 3076 #undef ADDR |
3049 }; | 3077 }; |
3050 | 3078 |
3051 | 3079 |
3052 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3080 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
3053 return IC_utilities[id]; | 3081 return IC_utilities[id]; |
3054 } | 3082 } |
3055 | 3083 |
3056 | 3084 |
3057 } } // namespace v8::internal | 3085 } } // namespace v8::internal |
OLD | NEW |