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

Side by Side Diff: src/ic.cc

Issue 150164: Ignore interceptors with no getters when doing any kind of read. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 5 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 | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 SetTargetAtAddress(address, initialize_stub()); 258 SetTargetAtAddress(address, initialize_stub());
259 } 259 }
260 260
261 261
262 void KeyedStoreIC::Clear(Address address, Code* target) { 262 void KeyedStoreIC::Clear(Address address, Code* target) {
263 if (target->ic_state() == UNINITIALIZED) return; 263 if (target->ic_state() == UNINITIALIZED) return;
264 SetTargetAtAddress(address, initialize_stub()); 264 SetTargetAtAddress(address, initialize_stub());
265 } 265 }
266 266
267 267
268 static bool HasInterceptorGetter(JSObject* object) {
269 return !object->GetNamedInterceptor()->getter()->IsUndefined();
270 }
271
272
273 static void LookupForRead(Object* object,
274 String* name,
275 LookupResult* lookup) {
276 object->Lookup(name, lookup);
277 if (lookup->IsNotFound() || lookup->type() != INTERCEPTOR) {
278 return;
279 }
280
281 JSObject* holder = lookup->holder();
282 if (HasInterceptorGetter(holder)) {
283 return;
284 }
285
286 // There is no getter, just skip it and lookup down the proto chain
287 holder->LocalLookupRealNamedProperty(name, lookup);
288 if (lookup->IsValid()) {
289 return;
290 }
291
292 Object* proto = holder->GetPrototype();
293 if (proto == Heap::null_value()) {
294 return;
295 }
296
297 LookupForRead(proto, name, lookup);
298 }
299
300
268 Object* CallIC::TryCallAsFunction(Object* object) { 301 Object* CallIC::TryCallAsFunction(Object* object) {
269 HandleScope scope; 302 HandleScope scope;
270 Handle<Object> target(object); 303 Handle<Object> target(object);
271 Handle<Object> delegate = Execution::GetFunctionDelegate(target); 304 Handle<Object> delegate = Execution::GetFunctionDelegate(target);
272 305
273 if (delegate->IsJSFunction()) { 306 if (delegate->IsJSFunction()) {
274 // Patch the receiver and use the delegate as the function to 307 // Patch the receiver and use the delegate as the function to
275 // invoke. This is used for invoking objects as if they were 308 // invoke. This is used for invoking objects as if they were
276 // functions. 309 // functions.
277 const int argc = this->target()->arguments_count(); 310 const int argc = this->target()->arguments_count();
(...skipping 27 matching lines...) Expand all
305 338
306 // Try to find a suitable function delegate for the object at hand. 339 // Try to find a suitable function delegate for the object at hand.
307 result = TryCallAsFunction(result); 340 result = TryCallAsFunction(result);
308 if (result->IsJSFunction()) return result; 341 if (result->IsJSFunction()) return result;
309 342
310 // Otherwise, it will fail in the lookup step. 343 // Otherwise, it will fail in the lookup step.
311 } 344 }
312 345
313 // Lookup the property in the object. 346 // Lookup the property in the object.
314 LookupResult lookup; 347 LookupResult lookup;
315 object->Lookup(*name, &lookup); 348 LookupForRead(*object, *name, &lookup);
316 349
317 if (!lookup.IsValid()) { 350 if (!lookup.IsValid()) {
318 // If the object does not have the requested property, check which 351 // If the object does not have the requested property, check which
319 // exception we need to throw. 352 // exception we need to throw.
320 if (is_contextual()) { 353 if (is_contextual()) {
321 return ReferenceError("not_defined", name); 354 return ReferenceError("not_defined", name);
322 } 355 }
323 return TypeError("undefined_method", object, name); 356 return TypeError("undefined_method", object, name);
324 } 357 }
325 358
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 // properties. It does not traverse the prototype chain, so the 470 // properties. It does not traverse the prototype chain, so the
438 // property must be found in the receiver for the stub to be 471 // property must be found in the receiver for the stub to be
439 // applicable. 472 // applicable.
440 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 473 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
441 if (lookup->holder() != *receiver) return; 474 if (lookup->holder() != *receiver) return;
442 code = StubCache::ComputeCallNormal(argc, in_loop, *name, *receiver); 475 code = StubCache::ComputeCallNormal(argc, in_loop, *name, *receiver);
443 } 476 }
444 break; 477 break;
445 } 478 }
446 case INTERCEPTOR: { 479 case INTERCEPTOR: {
480 ASSERT(HasInterceptorGetter(lookup->holder()));
447 code = StubCache::ComputeCallInterceptor(argc, *name, *object, 481 code = StubCache::ComputeCallInterceptor(argc, *name, *object,
448 lookup->holder()); 482 lookup->holder());
449 break; 483 break;
450 } 484 }
451 default: 485 default:
452 return; 486 return;
453 } 487 }
454 } 488 }
455 489
456 // If we're unable to compute the stub (not enough memory left), we 490 // If we're unable to compute the stub (not enough memory left), we
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 } 557 }
524 } 558 }
525 559
526 // Check if the name is trivially convertible to an index and get 560 // Check if the name is trivially convertible to an index and get
527 // the element if so. 561 // the element if so.
528 uint32_t index; 562 uint32_t index;
529 if (name->AsArrayIndex(&index)) return object->GetElement(index); 563 if (name->AsArrayIndex(&index)) return object->GetElement(index);
530 564
531 // Named lookup in the object. 565 // Named lookup in the object.
532 LookupResult lookup; 566 LookupResult lookup;
533 object->Lookup(*name, &lookup); 567 LookupForRead(*object, *name, &lookup);
534 568
535 // If lookup is invalid, check if we need to throw an exception. 569 // If lookup is invalid, check if we need to throw an exception.
536 if (!lookup.IsValid()) { 570 if (!lookup.IsValid()) {
537 if (FLAG_strict || is_contextual()) { 571 if (FLAG_strict || is_contextual()) {
538 return ReferenceError("not_defined", name); 572 return ReferenceError("not_defined", name);
539 } 573 }
540 LOG(SuspectReadEvent(*name, *object)); 574 LOG(SuspectReadEvent(*name, *object));
541 } 575 }
542 576
543 bool can_be_inlined = 577 bool can_be_inlined =
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 case CALLBACKS: { 680 case CALLBACKS: {
647 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; 681 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
648 AccessorInfo* callback = 682 AccessorInfo* callback =
649 AccessorInfo::cast(lookup->GetCallbackObject()); 683 AccessorInfo::cast(lookup->GetCallbackObject());
650 if (v8::ToCData<Address>(callback->getter()) == 0) return; 684 if (v8::ToCData<Address>(callback->getter()) == 0) return;
651 code = StubCache::ComputeLoadCallback(*name, *receiver, 685 code = StubCache::ComputeLoadCallback(*name, *receiver,
652 lookup->holder(), callback); 686 lookup->holder(), callback);
653 break; 687 break;
654 } 688 }
655 case INTERCEPTOR: { 689 case INTERCEPTOR: {
690 ASSERT(HasInterceptorGetter(lookup->holder()));
656 code = StubCache::ComputeLoadInterceptor(*name, *receiver, 691 code = StubCache::ComputeLoadInterceptor(*name, *receiver,
657 lookup->holder()); 692 lookup->holder());
658 break; 693 break;
659 } 694 }
660 default: 695 default:
661 return; 696 return;
662 } 697 }
663 } 698 }
664 699
665 // If we're unable to compute the stub (not enough memory left), we 700 // If we're unable to compute the stub (not enough memory left), we
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
737 uint32_t index = 0; 772 uint32_t index = 0;
738 if (name->AsArrayIndex(&index)) { 773 if (name->AsArrayIndex(&index)) {
739 HandleScope scope; 774 HandleScope scope;
740 // Rewrite to the generic keyed load stub. 775 // Rewrite to the generic keyed load stub.
741 if (FLAG_use_ic) set_target(generic_stub()); 776 if (FLAG_use_ic) set_target(generic_stub());
742 return Runtime::GetElementOrCharAt(object, index); 777 return Runtime::GetElementOrCharAt(object, index);
743 } 778 }
744 779
745 // Named lookup. 780 // Named lookup.
746 LookupResult lookup; 781 LookupResult lookup;
747 object->Lookup(*name, &lookup); 782 LookupForRead(*object, *name, &lookup);
748 783
749 // If lookup is invalid, check if we need to throw an exception. 784 // If lookup is invalid, check if we need to throw an exception.
750 if (!lookup.IsValid()) { 785 if (!lookup.IsValid()) {
751 if (FLAG_strict || is_contextual()) { 786 if (FLAG_strict || is_contextual()) {
752 return ReferenceError("not_defined", name); 787 return ReferenceError("not_defined", name);
753 } 788 }
754 } 789 }
755 790
756 // Update the inline cache. 791 // Update the inline cache.
757 if (FLAG_use_ic && lookup.IsLoaded()) { 792 if (FLAG_use_ic && lookup.IsLoaded()) {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
831 case CALLBACKS: { 866 case CALLBACKS: {
832 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; 867 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
833 AccessorInfo* callback = 868 AccessorInfo* callback =
834 AccessorInfo::cast(lookup->GetCallbackObject()); 869 AccessorInfo::cast(lookup->GetCallbackObject());
835 if (v8::ToCData<Address>(callback->getter()) == 0) return; 870 if (v8::ToCData<Address>(callback->getter()) == 0) return;
836 code = StubCache::ComputeKeyedLoadCallback(*name, *receiver, 871 code = StubCache::ComputeKeyedLoadCallback(*name, *receiver,
837 lookup->holder(), callback); 872 lookup->holder(), callback);
838 break; 873 break;
839 } 874 }
840 case INTERCEPTOR: { 875 case INTERCEPTOR: {
876 ASSERT(HasInterceptorGetter(lookup->holder()));
841 code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver, 877 code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver,
842 lookup->holder()); 878 lookup->holder());
843 break; 879 break;
844 } 880 }
845 default: { 881 default: {
846 // Always rewrite to the generic case so that we do not 882 // Always rewrite to the generic case so that we do not
847 // repeatedly try to rewrite. 883 // repeatedly try to rewrite.
848 code = generic_stub(); 884 code = generic_stub();
849 break; 885 break;
850 } 886 }
(...skipping 26 matching lines...) Expand all
877 // If the property is read-only, we leave the IC in its current 913 // If the property is read-only, we leave the IC in its current
878 // state. 914 // state.
879 if (lookup->IsReadOnly()) return false; 915 if (lookup->IsReadOnly()) return false;
880 916
881 if (!lookup->IsLoaded()) return false; 917 if (!lookup->IsLoaded()) return false;
882 918
883 return true; 919 return true;
884 } 920 }
885 921
886 922
887 static bool LookupForStoreIC(JSObject* object, 923 static bool LookupForWrite(JSObject* object,
888 String* name, 924 String* name,
889 LookupResult* lookup) { 925 LookupResult* lookup) {
890 object->LocalLookup(name, lookup); 926 object->LocalLookup(name, lookup);
891 if (!StoreICableLookup(lookup)) { 927 if (!StoreICableLookup(lookup)) {
892 return false; 928 return false;
893 } 929 }
894 930
895 if (lookup->type() == INTERCEPTOR) { 931 if (lookup->type() == INTERCEPTOR) {
896 if (object->GetNamedInterceptor()->setter()->IsUndefined()) { 932 if (object->GetNamedInterceptor()->setter()->IsUndefined()) {
897 object->LocalLookupRealNamedProperty(name, lookup); 933 object->LocalLookupRealNamedProperty(name, lookup);
898 return StoreICableLookup(lookup); 934 return StoreICableLookup(lookup);
899 } 935 }
(...skipping 22 matching lines...) Expand all
922 if (name->AsArrayIndex(&index)) { 958 if (name->AsArrayIndex(&index)) {
923 HandleScope scope; 959 HandleScope scope;
924 Handle<Object> result = SetElement(receiver, index, value); 960 Handle<Object> result = SetElement(receiver, index, value);
925 if (result.is_null()) return Failure::Exception(); 961 if (result.is_null()) return Failure::Exception();
926 return *value; 962 return *value;
927 } 963 }
928 964
929 // Lookup the property locally in the receiver. 965 // Lookup the property locally in the receiver.
930 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { 966 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
931 LookupResult lookup; 967 LookupResult lookup;
932 if (LookupForStoreIC(*receiver, *name, &lookup)) { 968 if (LookupForWrite(*receiver, *name, &lookup)) {
933 UpdateCaches(&lookup, state, receiver, name, value); 969 UpdateCaches(&lookup, state, receiver, name, value);
934 } 970 }
935 } 971 }
936 972
937 // Set the property. 973 // Set the property.
938 return receiver->SetProperty(*name, *value, NONE); 974 return receiver->SetProperty(*name, *value, NONE);
939 } 975 }
940 976
941 977
942 void StoreIC::UpdateCaches(LookupResult* lookup, 978 void StoreIC::UpdateCaches(LookupResult* lookup,
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
988 break; 1024 break;
989 } 1025 }
990 case CALLBACKS: { 1026 case CALLBACKS: {
991 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; 1027 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
992 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); 1028 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
993 if (v8::ToCData<Address>(callback->setter()) == 0) return; 1029 if (v8::ToCData<Address>(callback->setter()) == 0) return;
994 code = StubCache::ComputeStoreCallback(*name, *receiver, callback); 1030 code = StubCache::ComputeStoreCallback(*name, *receiver, callback);
995 break; 1031 break;
996 } 1032 }
997 case INTERCEPTOR: { 1033 case INTERCEPTOR: {
1034 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
998 code = StubCache::ComputeStoreInterceptor(*name, *receiver); 1035 code = StubCache::ComputeStoreInterceptor(*name, *receiver);
999 break; 1036 break;
1000 } 1037 }
1001 default: 1038 default:
1002 return; 1039 return;
1003 } 1040 }
1004 1041
1005 // If we're unable to compute the stub (not enough memory left), we 1042 // If we're unable to compute the stub (not enough memory left), we
1006 // simply avoid updating the caches. 1043 // simply avoid updating the caches.
1007 if (code->IsFailure()) return; 1044 if (code->IsFailure()) return;
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
1318 #undef ADDR 1355 #undef ADDR
1319 }; 1356 };
1320 1357
1321 1358
1322 Address IC::AddressFromUtilityId(IC::UtilityId id) { 1359 Address IC::AddressFromUtilityId(IC::UtilityId id) {
1323 return IC_utilities[id]; 1360 return IC_utilities[id];
1324 } 1361 }
1325 1362
1326 1363
1327 } } // namespace v8::internal 1364 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698