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

Side by Side Diff: src/ic.cc

Issue 2801018: This change allows generating call-stubs for objects with normal (non-fast) o... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 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 | « src/ic.h ('k') | src/ic-inl.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 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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 Address addr = pc() - Assembler::kCallTargetAddressOffset; 127 Address addr = pc() - Assembler::kCallTargetAddressOffset;
128 // Return the address in the original code. This is the place where 128 // Return the address in the original code. This is the place where
129 // the call which has been overwritten by the DebugBreakXXX resides 129 // the call which has been overwritten by the DebugBreakXXX resides
130 // and the place where the inline cache system should look. 130 // and the place where the inline cache system should look.
131 intptr_t delta = 131 intptr_t delta =
132 original_code->instruction_start() - code->instruction_start(); 132 original_code->instruction_start() - code->instruction_start();
133 return addr + delta; 133 return addr + delta;
134 } 134 }
135 #endif 135 #endif
136 136
137
138 static bool HasNormalObjectsInPrototypeChain(LookupResult* lookup,
139 Object* receiver) {
140 Object* end = lookup->IsProperty() ? lookup->holder() : Heap::null_value();
141 for (Object* current = receiver;
142 current != end;
143 current = current->GetPrototype()) {
144 if (current->IsJSObject() &&
145 !JSObject::cast(current)->HasFastProperties() &&
146 !current->IsJSGlobalProxy() &&
147 !current->IsJSGlobalObject()) {
148 return true;
149 }
150 }
151
152 return false;
153 }
154
155
137 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) { 156 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) {
138 IC::State state = target->ic_state(); 157 IC::State state = target->ic_state();
139 158
140 if (state != MONOMORPHIC) return state; 159 if (state != MONOMORPHIC) return state;
141 if (receiver->IsUndefined() || receiver->IsNull()) return state; 160 if (receiver->IsUndefined() || receiver->IsNull()) return state;
142 161
143 Map* map = GetCodeCacheMapForObject(receiver); 162 InlineCacheHolderFlag cache_holder =
163 Code::ExtractCacheHolderFromFlags(target->flags());
164
165
166 if (cache_holder == OWN_MAP && !receiver->IsJSObject()) {
167 // The stub was generated for JSObject but called for non-JSObject.
168 // IC::GetCodeCacheMap is not applicable.
169 return MONOMORPHIC;
170 } else if (cache_holder == PROTOTYPE_MAP &&
171 receiver->GetPrototype()->IsNull()) {
172 // IC::GetCodeCacheMap is not applicable.
173 return MONOMORPHIC;
174 }
175 Map* map = IC::GetCodeCacheMap(receiver, cache_holder);
144 176
145 // Decide whether the inline cache failed because of changes to the 177 // Decide whether the inline cache failed because of changes to the
146 // receiver itself or changes to one of its prototypes. 178 // receiver itself or changes to one of its prototypes.
147 // 179 //
148 // If there are changes to the receiver itself, the map of the 180 // If there are changes to the receiver itself, the map of the
149 // receiver will have changed and the current target will not be in 181 // receiver will have changed and the current target will not be in
150 // the receiver map's code cache. Therefore, if the current target 182 // the receiver map's code cache. Therefore, if the current target
151 // is in the receiver map's code cache, the inline cache failed due 183 // is in the receiver map's code cache, the inline cache failed due
152 // to prototype check failure. 184 // to prototype check failure.
153 int index = map->IndexInCodeCache(name, target); 185 int index = map->IndexInCodeCache(name, target);
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 } 512 }
481 513
482 // Try to find a suitable function delegate for the object at hand. 514 // Try to find a suitable function delegate for the object at hand.
483 result = TryCallAsFunction(result); 515 result = TryCallAsFunction(result);
484 return result->IsJSFunction() ? 516 return result->IsJSFunction() ?
485 result : TypeError("property_not_function", object, name); 517 result : TypeError("property_not_function", object, name);
486 } 518 }
487 519
488 520
489 void CallICBase::UpdateCaches(LookupResult* lookup, 521 void CallICBase::UpdateCaches(LookupResult* lookup,
490 State state, 522 State state,
491 Handle<Object> object, 523 Handle<Object> object,
492 Handle<String> name) { 524 Handle<String> name) {
493 // Bail out if we didn't find a result. 525 // Bail out if we didn't find a result.
494 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 526 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
495 527
528 #ifndef V8_TARGET_ARCH_IA32
529 // Normal objects only implemented for IA32 by now.
530 if (HasNormalObjectsInPrototypeChain(lookup, *object)) return;
531 #else
532 if (lookup->holder() != *object &&
533 HasNormalObjectsInPrototypeChain(lookup, object->GetPrototype())) {
534 // Suppress optimization for prototype chains with slow properties objects
535 // in the middle.
536 return;
537 }
538 #endif
539
496 // Compute the number of arguments. 540 // Compute the number of arguments.
497 int argc = target()->arguments_count(); 541 int argc = target()->arguments_count();
498 InLoopFlag in_loop = target()->ic_in_loop(); 542 InLoopFlag in_loop = target()->ic_in_loop();
499 Object* code = NULL; 543 Object* code = NULL;
500 544
501 if (state == UNINITIALIZED) { 545 if (state == UNINITIALIZED) {
502 // This is the first time we execute this inline cache. 546 // This is the first time we execute this inline cache.
503 // Set the target to the pre monomorphic stub to delay 547 // Set the target to the pre monomorphic stub to delay
504 // setting the monomorphic state. 548 // setting the monomorphic state.
505 code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_); 549 code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 // simply avoid updating the caches. 627 // simply avoid updating the caches.
584 if (code == NULL || code->IsFailure()) return; 628 if (code == NULL || code->IsFailure()) return;
585 629
586 // Patch the call site depending on the state of the cache. 630 // Patch the call site depending on the state of the cache.
587 if (state == UNINITIALIZED || 631 if (state == UNINITIALIZED ||
588 state == PREMONOMORPHIC || 632 state == PREMONOMORPHIC ||
589 state == MONOMORPHIC || 633 state == MONOMORPHIC ||
590 state == MONOMORPHIC_PROTOTYPE_FAILURE) { 634 state == MONOMORPHIC_PROTOTYPE_FAILURE) {
591 set_target(Code::cast(code)); 635 set_target(Code::cast(code));
592 } else if (state == MEGAMORPHIC) { 636 } else if (state == MEGAMORPHIC) {
637 // Cache code holding map should be consistent with
638 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
639 Map* map = JSObject::cast(object->IsJSObject() ? *object :
640 object->GetPrototype())->map();
641
593 // Update the stub cache. 642 // Update the stub cache.
594 StubCache::Set(*name, GetCodeCacheMapForObject(*object), Code::cast(code)); 643 StubCache::Set(*name, map, Code::cast(code));
595 } 644 }
596 645
597 #ifdef DEBUG 646 #ifdef DEBUG
598 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", 647 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
599 name, state, target(), in_loop ? " (in-loop)" : ""); 648 name, state, target(), in_loop ? " (in-loop)" : "");
600 #endif 649 #endif
601 } 650 }
602 651
603 652
604 Object* KeyedCallIC::LoadFunction(State state, 653 Object* KeyedCallIC::LoadFunction(State state,
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 Handle<Object> object, 837 Handle<Object> object,
789 Handle<String> name) { 838 Handle<String> name) {
790 // Bail out if the result is not cacheable. 839 // Bail out if the result is not cacheable.
791 if (!lookup->IsCacheable()) return; 840 if (!lookup->IsCacheable()) return;
792 841
793 // Loading properties from values is not common, so don't try to 842 // Loading properties from values is not common, so don't try to
794 // deal with non-JS objects here. 843 // deal with non-JS objects here.
795 if (!object->IsJSObject()) return; 844 if (!object->IsJSObject()) return;
796 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 845 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
797 846
847 if (HasNormalObjectsInPrototypeChain(lookup, *object)) return;
848
798 // Compute the code stub for this load. 849 // Compute the code stub for this load.
799 Object* code = NULL; 850 Object* code = NULL;
800 if (state == UNINITIALIZED) { 851 if (state == UNINITIALIZED) {
801 // This is the first time we execute this inline cache. 852 // This is the first time we execute this inline cache.
802 // Set the target to the pre monomorphic stub to delay 853 // Set the target to the pre monomorphic stub to delay
803 // setting the monomorphic state. 854 // setting the monomorphic state.
804 code = pre_monomorphic_stub(); 855 code = pre_monomorphic_stub();
805 } else if (!lookup->IsProperty()) { 856 } else if (!lookup->IsProperty()) {
806 // Nonexistent property. The result is undefined. 857 // Nonexistent property. The result is undefined.
807 code = StubCache::ComputeLoadNonexistent(*name, *receiver); 858 code = StubCache::ComputeLoadNonexistent(*name, *receiver);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
864 // simply avoid updating the caches. 915 // simply avoid updating the caches.
865 if (code == NULL || code->IsFailure()) return; 916 if (code == NULL || code->IsFailure()) return;
866 917
867 // Patch the call site depending on the state of the cache. 918 // Patch the call site depending on the state of the cache.
868 if (state == UNINITIALIZED || state == PREMONOMORPHIC || 919 if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
869 state == MONOMORPHIC_PROTOTYPE_FAILURE) { 920 state == MONOMORPHIC_PROTOTYPE_FAILURE) {
870 set_target(Code::cast(code)); 921 set_target(Code::cast(code));
871 } else if (state == MONOMORPHIC) { 922 } else if (state == MONOMORPHIC) {
872 set_target(megamorphic_stub()); 923 set_target(megamorphic_stub());
873 } else if (state == MEGAMORPHIC) { 924 } else if (state == MEGAMORPHIC) {
874 // Update the stub cache. 925 // Cache code holding map should be consistent with
875 StubCache::Set(*name, GetCodeCacheMapForObject(*object), Code::cast(code)); 926 // GenerateMonomorphicCacheProbe.
927 Map* map = JSObject::cast(object->IsJSObject() ? *object :
928 object->GetPrototype())->map();
929
930 StubCache::Set(*name, map, Code::cast(code));
876 } 931 }
877 932
878 #ifdef DEBUG 933 #ifdef DEBUG
879 TraceIC("LoadIC", name, state, target()); 934 TraceIC("LoadIC", name, state, target());
880 #endif 935 #endif
881 } 936 }
882 937
883 938
884 Object* KeyedLoadIC::Load(State state, 939 Object* KeyedLoadIC::Load(State state,
885 Handle<Object> object, 940 Handle<Object> object,
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1011 1066
1012 1067
1013 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, 1068 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
1014 Handle<Object> object, Handle<String> name) { 1069 Handle<Object> object, Handle<String> name) {
1015 // Bail out if we didn't find a result. 1070 // Bail out if we didn't find a result.
1016 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 1071 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
1017 1072
1018 if (!object->IsJSObject()) return; 1073 if (!object->IsJSObject()) return;
1019 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1074 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1020 1075
1076 if (HasNormalObjectsInPrototypeChain(lookup, *object)) return;
1077
1021 // Compute the code stub for this load. 1078 // Compute the code stub for this load.
1022 Object* code = NULL; 1079 Object* code = NULL;
1023 1080
1024 if (state == UNINITIALIZED) { 1081 if (state == UNINITIALIZED) {
1025 // This is the first time we execute this inline cache. 1082 // This is the first time we execute this inline cache.
1026 // Set the target to the pre monomorphic stub to delay 1083 // Set the target to the pre monomorphic stub to delay
1027 // setting the monomorphic state. 1084 // setting the monomorphic state.
1028 code = pre_monomorphic_stub(); 1085 code = pre_monomorphic_stub();
1029 } else { 1086 } else {
1030 // Compute a monomorphic stub. 1087 // Compute a monomorphic stub.
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after
1621 #undef ADDR 1678 #undef ADDR
1622 }; 1679 };
1623 1680
1624 1681
1625 Address IC::AddressFromUtilityId(IC::UtilityId id) { 1682 Address IC::AddressFromUtilityId(IC::UtilityId id) {
1626 return IC_utilities[id]; 1683 return IC_utilities[id];
1627 } 1684 }
1628 1685
1629 1686
1630 } } // namespace v8::internal 1687 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698