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

Side by Side Diff: src/ic.cc

Issue 429053005: Avoid one repeated property lookup when computing load ICs. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebased Created 6 years, 4 months 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 | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/lookup.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/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
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()) {
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
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
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 =
875 Handle<Object> value) { 856 object.is_identical_to(lookup->GetHolder<JSObject>());
857 CacheHolderFlag flag;
858 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder(
859 *receiver_type(), receiver_is_holder, isolate(), &flag);
860
861 Handle<Code> code = PropertyHandlerCompiler::Find(
862 name, stub_holder_map, kind(), flag,
863 lookup->holder_map()->is_dictionary_map() ? Code::NORMAL : Code::FAST);
864 // Use the cached value if it exists, and if it is different from the
865 // handler that just missed.
866 if (!code.is_null()) {
867 if (!maybe_handler_.is_null() &&
868 !maybe_handler_.ToHandleChecked().is_identical_to(code)) {
869 return code;
870 }
871 if (maybe_handler_.is_null()) {
872 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs.
873 // In MEGAMORPHIC case, check if the handler in the megamorphic stub
874 // cache (which just missed) is different from the cached handler.
875 if (state() == MEGAMORPHIC && object->IsHeapObject()) {
876 Map* map = Handle<HeapObject>::cast(object)->map();
877 Code* megamorphic_cached_code =
878 isolate()->stub_cache()->Get(*name, map, code->flags());
879 if (megamorphic_cached_code != *code) return code;
880 } else {
881 return code;
882 }
883 }
884 }
885
886 code = CompileHandler(lookup, object, name, value, flag);
887 ASSERT(code->is_handler());
888
889 if (code->type() != Code::NORMAL) {
890 Map::UpdateCodeCache(stub_holder_map, name, code);
891 }
892
893 return code;
894 }
895
896
897 Handle<Code> IC::ComputeStoreHandler(LookupResult* lookup,
898 Handle<Object> object, Handle<String> name,
899 Handle<Object> value) {
876 bool receiver_is_holder = lookup->ReceiverIsHolder(object); 900 bool receiver_is_holder = lookup->ReceiverIsHolder(object);
877 CacheHolderFlag flag; 901 CacheHolderFlag flag;
878 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( 902 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder(
879 *receiver_type(), receiver_is_holder, isolate(), &flag); 903 *receiver_type(), receiver_is_holder, isolate(), &flag);
880 904
881 Handle<Code> code = PropertyHandlerCompiler::Find( 905 Handle<Code> code = PropertyHandlerCompiler::Find(
882 name, stub_holder_map, handler_kind(), flag, 906 name, stub_holder_map, handler_kind(), flag,
883 lookup->holder()->HasFastProperties() ? Code::FAST : Code::NORMAL); 907 lookup->holder()->HasFastProperties() ? Code::FAST : Code::NORMAL);
884 // Use the cached value if it exists, and if it is different from the 908 // Use the cached value if it exists, and if it is different from the
885 // handler that just missed. 909 // handler that just missed.
(...skipping 10 matching lines...) Expand all
896 Map* map = Handle<HeapObject>::cast(object)->map(); 920 Map* map = Handle<HeapObject>::cast(object)->map();
897 Code* megamorphic_cached_code = 921 Code* megamorphic_cached_code =
898 isolate()->stub_cache()->Get(*name, map, code->flags()); 922 isolate()->stub_cache()->Get(*name, map, code->flags());
899 if (megamorphic_cached_code != *code) return code; 923 if (megamorphic_cached_code != *code) return code;
900 } else { 924 } else {
901 return code; 925 return code;
902 } 926 }
903 } 927 }
904 } 928 }
905 929
906 code = CompileHandler(lookup, object, name, value, flag); 930 code = CompileStoreHandler(lookup, object, name, value, flag);
907 ASSERT(code->is_handler()); 931 ASSERT(code->is_handler());
908 932
909 if (code->type() != Code::NORMAL) { 933 if (code->type() != Code::NORMAL) {
910 Map::UpdateCodeCache(stub_holder_map, name, code); 934 Map::UpdateCodeCache(stub_holder_map, name, code);
911 } 935 }
912 936
913 return code; 937 return code;
914 } 938 }
915 939
916 940
917 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, Handle<Object> object, 941 Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
918 Handle<String> name, Handle<Object> unused, 942 Handle<Object> object, Handle<String> name,
943 Handle<Object> unused,
919 CacheHolderFlag cache_holder) { 944 CacheHolderFlag cache_holder) {
920 if (object->IsString() && 945 if (object->IsString() &&
921 String::Equals(isolate()->factory()->length_string(), name)) { 946 String::Equals(isolate()->factory()->length_string(), name)) {
922 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); 947 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset);
923 return SimpleFieldLoad(index); 948 return SimpleFieldLoad(index);
924 } 949 }
925 950
926 if (object->IsStringWrapper() && 951 if (object->IsStringWrapper() &&
927 String::Equals(isolate()->factory()->length_string(), name)) { 952 String::Equals(isolate()->factory()->length_string(), name)) {
928 StringLengthStub string_length_stub(isolate()); 953 StringLengthStub string_length_stub(isolate());
929 return string_length_stub.GetCode(); 954 return string_length_stub.GetCode();
930 } 955 }
931 956
932 // Use specialized code for getting prototype of functions. 957 // Use specialized code for getting prototype of functions.
933 if (object->IsJSFunction() && 958 if (object->IsJSFunction() &&
934 String::Equals(isolate()->factory()->prototype_string(), name) && 959 String::Equals(isolate()->factory()->prototype_string(), name) &&
935 Handle<JSFunction>::cast(object)->should_have_prototype() && 960 Handle<JSFunction>::cast(object)->should_have_prototype() &&
936 !Handle<JSFunction>::cast(object)->map()->has_non_instance_prototype()) { 961 !Handle<JSFunction>::cast(object)->map()->has_non_instance_prototype()) {
937 Handle<Code> stub; 962 Handle<Code> stub;
938 FunctionPrototypeStub function_prototype_stub(isolate()); 963 FunctionPrototypeStub function_prototype_stub(isolate());
939 return function_prototype_stub.GetCode(); 964 return function_prototype_stub.GetCode();
940 } 965 }
941 966
942 Handle<HeapType> type = receiver_type(); 967 Handle<HeapType> type = receiver_type();
943 Handle<JSObject> holder(lookup->holder()); 968 Handle<JSObject> holder = lookup->GetHolder<JSObject>();
944 bool receiver_is_holder = object.is_identical_to(holder); 969 bool receiver_is_holder = object.is_identical_to(holder);
945 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, 970 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
946 cache_holder); 971 cache_holder);
947 972
948 switch (lookup->type()) { 973 // -------------- Interceptors --------------
949 case FIELD: { 974 if (lookup->state() == LookupIterator::INTERCEPTOR) {
950 FieldIndex field = lookup->GetFieldIndex(); 975 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
951 if (receiver_is_holder) { 976 return compiler.CompileLoadInterceptor(name);
952 return SimpleFieldLoad(field); 977 }
978 ASSERT(lookup->state() == LookupIterator::PROPERTY);
979
980 // -------------- Accessors --------------
981 if (lookup->property_kind() == LookupIterator::ACCESSOR) {
982 // Use simple field loads for some well-known callback properties.
983 if (receiver_is_holder) {
984 ASSERT(object->IsJSObject());
985 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
986 int object_offset;
987 if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, name,
988 &object_offset)) {
989 FieldIndex index =
990 FieldIndex::ForInObjectOffset(object_offset, receiver->map());
991 return SimpleFieldLoad(index);
953 } 992 }
954 return compiler.CompileLoadField(name, field, lookup->representation());
955 } 993 }
956 case CONSTANT: { 994
957 Handle<Object> constant(lookup->GetConstant(), isolate()); 995 Handle<Object> accessors = lookup->GetAccessors();
958 return compiler.CompileLoadConstant(name, constant); 996 if (accessors->IsExecutableAccessorInfo()) {
997 Handle<ExecutableAccessorInfo> info =
998 Handle<ExecutableAccessorInfo>::cast(accessors);
999 if (v8::ToCData<Address>(info->getter()) == 0) return slow_stub();
1000 if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info,
1001 type)) {
1002 return slow_stub();
1003 }
1004 if (holder->IsGlobalObject()) return slow_stub();
1005 return compiler.CompileLoadCallback(name, info);
959 } 1006 }
960 case NORMAL: 1007 if (accessors->IsAccessorPair()) {
961 if (kind() != Code::LOAD_IC) break; 1008 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
962 if (holder->IsGlobalObject()) { 1009 isolate());
963 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); 1010 if (!getter->IsJSFunction()) return slow_stub();
964 Handle<PropertyCell> cell( 1011 if (holder->IsGlobalObject()) return slow_stub();
965 global->GetPropertyCell(lookup), isolate()); 1012 if (!holder->HasFastProperties()) return slow_stub();
966 Handle<Code> code = 1013 Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
967 compiler.CompileLoadGlobal(cell, name, lookup->IsDontDelete()); 1014 if (!object->IsJSObject() && !function->IsBuiltin() &&
968 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. 1015 function->shared()->strict_mode() == SLOPPY) {
969 CacheHolderFlag flag; 1016 // Calling sloppy non-builtins with a value as the receiver
970 Handle<Map> stub_holder_map = 1017 // requires boxing.
971 GetHandlerCacheHolder(*type, receiver_is_holder, isolate(), &flag); 1018 return slow_stub();
972 Map::UpdateCodeCache(stub_holder_map, name, code);
973 return code;
974 } 1019 }
975 // There is only one shared stub for loading normalized 1020 CallOptimization call_optimization(function);
976 // properties. It does not traverse the prototype chain, so the 1021 if (call_optimization.is_simple_api_call() &&
977 // property must be found in the object for the stub to be 1022 call_optimization.IsCompatibleReceiver(object, holder)) {
978 // applicable. 1023 return compiler.CompileLoadCallback(name, call_optimization);
979 if (!receiver_is_holder) break;
980 return isolate()->builtins()->LoadIC_Normal();
981 case CALLBACKS: {
982 // Use simple field loads for some well-known callback properties.
983 if (receiver_is_holder) {
984 ASSERT(object->IsJSObject());
985 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
986 int object_offset;
987 if (Accessors::IsJSObjectFieldAccessor<HeapType>(
988 type, name, &object_offset)) {
989 FieldIndex index = FieldIndex::ForInObjectOffset(
990 object_offset, receiver->map());
991 return SimpleFieldLoad(index);
992 }
993 } 1024 }
994 1025 return compiler.CompileLoadViaGetter(name, function);
995 Handle<Object> callback(lookup->GetCallbackObject(), isolate());
996 if (callback->IsExecutableAccessorInfo()) {
997 Handle<ExecutableAccessorInfo> info =
998 Handle<ExecutableAccessorInfo>::cast(callback);
999 if (v8::ToCData<Address>(info->getter()) == 0) break;
1000 if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info,
1001 type)) {
1002 break;
1003 }
1004 if (holder->IsGlobalObject()) break;
1005 return compiler.CompileLoadCallback(name, info);
1006 } else if (callback->IsAccessorPair()) {
1007 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
1008 isolate());
1009 if (!getter->IsJSFunction()) break;
1010 if (holder->IsGlobalObject()) break;
1011 if (!holder->HasFastProperties()) break;
1012 Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
1013 if (!object->IsJSObject() &&
1014 !function->IsBuiltin() &&
1015 function->shared()->strict_mode() == SLOPPY) {
1016 // Calling sloppy non-builtins with a value as the receiver
1017 // requires boxing.
1018 break;
1019 }
1020 CallOptimization call_optimization(function);
1021 if (call_optimization.is_simple_api_call() &&
1022 call_optimization.IsCompatibleReceiver(object, holder)) {
1023 return compiler.CompileLoadCallback(name, call_optimization);
1024 }
1025 return compiler.CompileLoadViaGetter(name, function);
1026 }
1027 // TODO(dcarney): Handle correctly.
1028 ASSERT(callback->IsDeclaredAccessorInfo());
1029 break;
1030 } 1026 }
1031 case INTERCEPTOR: 1027 // TODO(dcarney): Handle correctly.
1032 ASSERT(HasInterceptorGetter(*holder)); 1028 ASSERT(accessors->IsDeclaredAccessorInfo());
1033 return compiler.CompileLoadInterceptor(name); 1029 return slow_stub();
1034 default:
1035 break;
1036 } 1030 }
1037 1031
1038 return slow_stub(); 1032 // -------------- Dictionary properties --------------
1033 ASSERT(lookup->property_kind() == LookupIterator::DATA);
1034 if (lookup->property_encoding() == LookupIterator::DICTIONARY) {
1035 if (kind() != Code::LOAD_IC) return slow_stub();
1036 if (holder->IsGlobalObject()) {
1037 Handle<PropertyCell> cell = lookup->GetPropertyCell();
1038 Handle<Code> code =
1039 compiler.CompileLoadGlobal(cell, name, lookup->IsConfigurable());
1040 // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
1041 CacheHolderFlag flag;
1042 Handle<Map> stub_holder_map =
1043 GetHandlerCacheHolder(*type, receiver_is_holder, isolate(), &flag);
1044 Map::UpdateCodeCache(stub_holder_map, name, code);
1045 return code;
1046 }
1047 // There is only one shared stub for loading normalized
1048 // properties. It does not traverse the prototype chain, so the
1049 // property must be found in the object for the stub to be
1050 // applicable.
1051 if (!receiver_is_holder) return slow_stub();
1052 return isolate()->builtins()->LoadIC_Normal();
1053 }
1054
1055 // -------------- Fields --------------
1056 ASSERT(lookup->property_encoding() == LookupIterator::DESCRIPTOR);
1057 if (lookup->property_details().type() == FIELD) {
1058 FieldIndex field = lookup->GetFieldIndex();
1059 if (receiver_is_holder) {
1060 return SimpleFieldLoad(field);
1061 }
1062 return compiler.CompileLoadField(name, field, lookup->representation());
1063 }
1064
1065 // -------------- Constant properties --------------
1066 ASSERT(lookup->property_details().type() == CONSTANT);
1067 Handle<Object> constant = lookup->GetDataValue();
1068 return compiler.CompileLoadConstant(name, constant);
1039 } 1069 }
1040 1070
1041 1071
1042 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { 1072 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
1043 // This helper implements a few common fast cases for converting 1073 // This helper implements a few common fast cases for converting
1044 // non-smi keys of keyed loads/stores to a smi or a string. 1074 // non-smi keys of keyed loads/stores to a smi or a string.
1045 if (key->IsHeapNumber()) { 1075 if (key->IsHeapNumber()) {
1046 double value = Handle<HeapNumber>::cast(key)->value(); 1076 double value = Handle<HeapNumber>::cast(key)->value();
1047 if (std::isnan(value)) { 1077 if (std::isnan(value)) {
1048 key = isolate->factory()->nan_string(); 1078 key = isolate->factory()->nan_string();
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
1370 1400
1371 void StoreIC::UpdateCaches(LookupResult* lookup, 1401 void StoreIC::UpdateCaches(LookupResult* lookup,
1372 Handle<JSObject> receiver, 1402 Handle<JSObject> receiver,
1373 Handle<String> name, 1403 Handle<String> name,
1374 Handle<Object> value) { 1404 Handle<Object> value) {
1375 ASSERT(lookup->IsFound()); 1405 ASSERT(lookup->IsFound());
1376 1406
1377 // These are not cacheable, so we never see such LookupResults here. 1407 // These are not cacheable, so we never see such LookupResults here.
1378 ASSERT(!lookup->IsHandler()); 1408 ASSERT(!lookup->IsHandler());
1379 1409
1380 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); 1410 Handle<Code> code = ComputeStoreHandler(lookup, receiver, name, value);
1381 1411
1382 PatchCache(name, code); 1412 PatchCache(name, code);
1383 TRACE_IC("StoreIC", name); 1413 TRACE_IC("StoreIC", name);
1384 } 1414 }
1385 1415
1386 1416
1387 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, 1417 Handle<Code> StoreIC::CompileStoreHandler(LookupResult* lookup,
1388 Handle<Object> object, Handle<String> name, 1418 Handle<Object> object,
1389 Handle<Object> value, 1419 Handle<String> name,
1390 CacheHolderFlag cache_holder) { 1420 Handle<Object> value,
1421 CacheHolderFlag cache_holder) {
1391 if (object->IsAccessCheckNeeded()) return slow_stub(); 1422 if (object->IsAccessCheckNeeded()) return slow_stub();
1392 ASSERT(cache_holder == kCacheOnReceiver || lookup->type() == CALLBACKS || 1423 ASSERT(cache_holder == kCacheOnReceiver || lookup->type() == CALLBACKS ||
1393 (object->IsJSGlobalProxy() && lookup->holder()->IsJSGlobalObject())); 1424 (object->IsJSGlobalProxy() && lookup->holder()->IsJSGlobalObject()));
1394 // This is currently guaranteed by checks in StoreIC::Store. 1425 // This is currently guaranteed by checks in StoreIC::Store.
1395 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1426 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1396 1427
1397 Handle<JSObject> holder(lookup->holder()); 1428 Handle<JSObject> holder(lookup->holder());
1398 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); 1429 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
1399 1430
1400 if (lookup->IsTransition()) { 1431 if (lookup->IsTransition()) {
(...skipping 1652 matching lines...) Expand 10 before | Expand all | Expand 10 after
3053 #undef ADDR 3084 #undef ADDR
3054 }; 3085 };
3055 3086
3056 3087
3057 Address IC::AddressFromUtilityId(IC::UtilityId id) { 3088 Address IC::AddressFromUtilityId(IC::UtilityId id) {
3058 return IC_utilities[id]; 3089 return IC_utilities[id];
3059 } 3090 }
3060 3091
3061 3092
3062 } } // namespace v8::internal 3093 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/lookup.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698