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

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: 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
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()) {
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
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 = 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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698