OLD | NEW |
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 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 ClearInlinedVersion(address); | 292 ClearInlinedVersion(address); |
293 SetTargetAtAddress(address, initialize_stub()); | 293 SetTargetAtAddress(address, initialize_stub()); |
294 } | 294 } |
295 | 295 |
296 | 296 |
297 void LoadIC::ClearInlinedVersion(Address address) { | 297 void LoadIC::ClearInlinedVersion(Address address) { |
298 // Reset the map check of the inlined inobject property load (if | 298 // Reset the map check of the inlined inobject property load (if |
299 // present) to guarantee failure by holding an invalid map (the null | 299 // present) to guarantee failure by holding an invalid map (the null |
300 // value). The offset can be patched to anything. | 300 // value). The offset can be patched to anything. |
301 PatchInlinedLoad(address, Heap::null_value(), 0); | 301 PatchInlinedLoad(address, Heap::null_value(), 0); |
| 302 PatchInlinedContextualLoad(address, Heap::null_value(), Heap::null_value()); |
302 } | 303 } |
303 | 304 |
304 | 305 |
305 void LoadIC::Clear(Address address, Code* target) { | 306 void LoadIC::Clear(Address address, Code* target) { |
306 if (target->ic_state() == UNINITIALIZED) return; | 307 if (target->ic_state() == UNINITIALIZED) return; |
307 ClearInlinedVersion(address); | 308 ClearInlinedVersion(address); |
308 SetTargetAtAddress(address, initialize_stub()); | 309 SetTargetAtAddress(address, initialize_stub()); |
309 } | 310 } |
310 | 311 |
311 | 312 |
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
713 } | 714 } |
714 } | 715 } |
715 Object* result = Runtime::GetObjectProperty(object, key); | 716 Object* result = Runtime::GetObjectProperty(object, key); |
716 if (result->IsJSFunction()) return result; | 717 if (result->IsJSFunction()) return result; |
717 result = TryCallAsFunction(result); | 718 result = TryCallAsFunction(result); |
718 return result->IsJSFunction() ? | 719 return result->IsJSFunction() ? |
719 result : TypeError("property_not_function", object, key); | 720 result : TypeError("property_not_function", object, key); |
720 } | 721 } |
721 | 722 |
722 | 723 |
| 724 #ifdef DEBUG |
| 725 #define TRACE_IC_NAMED(msg, name) \ |
| 726 if (FLAG_trace_ic) PrintF(msg, *(name)->ToCString()) |
| 727 #else |
| 728 #define TRACE_IC_NAMED(msg, name) |
| 729 #endif |
| 730 |
| 731 |
723 Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) { | 732 Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) { |
724 // If the object is undefined or null it's illegal to try to get any | 733 // If the object is undefined or null it's illegal to try to get any |
725 // of its properties; throw a TypeError in that case. | 734 // of its properties; throw a TypeError in that case. |
726 if (object->IsUndefined() || object->IsNull()) { | 735 if (object->IsUndefined() || object->IsNull()) { |
727 return TypeError("non_object_property_load", object, name); | 736 return TypeError("non_object_property_load", object, name); |
728 } | 737 } |
729 | 738 |
730 if (FLAG_use_ic) { | 739 if (FLAG_use_ic) { |
731 // Use specialized code for getting the length of strings and | 740 // Use specialized code for getting the length of strings and |
732 // string wrapper objects. The length property of string wrapper | 741 // string wrapper objects. The length property of string wrapper |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
790 LookupForRead(*object, *name, &lookup); | 799 LookupForRead(*object, *name, &lookup); |
791 | 800 |
792 // If we did not find a property, check if we need to throw an exception. | 801 // If we did not find a property, check if we need to throw an exception. |
793 if (!lookup.IsProperty()) { | 802 if (!lookup.IsProperty()) { |
794 if (FLAG_strict || IsContextual(object)) { | 803 if (FLAG_strict || IsContextual(object)) { |
795 return ReferenceError("not_defined", name); | 804 return ReferenceError("not_defined", name); |
796 } | 805 } |
797 LOG(SuspectReadEvent(*name, *object)); | 806 LOG(SuspectReadEvent(*name, *object)); |
798 } | 807 } |
799 | 808 |
800 bool can_be_inlined = | 809 bool can_be_inlined_precheck = |
801 FLAG_use_ic && | 810 FLAG_use_ic && |
802 state == PREMONOMORPHIC && | |
803 lookup.IsProperty() && | 811 lookup.IsProperty() && |
804 lookup.IsCacheable() && | 812 lookup.IsCacheable() && |
805 lookup.holder() == *object && | 813 lookup.holder() == *object && |
806 lookup.type() == FIELD && | |
807 !object->IsAccessCheckNeeded(); | 814 !object->IsAccessCheckNeeded(); |
808 | 815 |
| 816 bool can_be_inlined = |
| 817 can_be_inlined_precheck && |
| 818 state == PREMONOMORPHIC && |
| 819 lookup.type() == FIELD; |
| 820 |
| 821 bool can_be_inlined_contextual = |
| 822 can_be_inlined_precheck && |
| 823 state == UNINITIALIZED && |
| 824 lookup.holder()->IsGlobalObject() && |
| 825 lookup.type() == NORMAL; |
| 826 |
809 if (can_be_inlined) { | 827 if (can_be_inlined) { |
810 Map* map = lookup.holder()->map(); | 828 Map* map = lookup.holder()->map(); |
811 // Property's index in the properties array. If negative we have | 829 // Property's index in the properties array. If negative we have |
812 // an inobject property. | 830 // an inobject property. |
813 int index = lookup.GetFieldIndex() - map->inobject_properties(); | 831 int index = lookup.GetFieldIndex() - map->inobject_properties(); |
814 if (index < 0) { | 832 if (index < 0) { |
815 // Index is an offset from the end of the object. | 833 // Index is an offset from the end of the object. |
816 int offset = map->instance_size() + (index * kPointerSize); | 834 int offset = map->instance_size() + (index * kPointerSize); |
817 if (PatchInlinedLoad(address(), map, offset)) { | 835 if (PatchInlinedLoad(address(), map, offset)) { |
818 set_target(megamorphic_stub()); | 836 set_target(megamorphic_stub()); |
819 #ifdef DEBUG | 837 TRACE_IC_NAMED("[LoadIC : inline patch %s]\n", name); |
820 if (FLAG_trace_ic) { | |
821 PrintF("[LoadIC : inline patch %s]\n", *name->ToCString()); | |
822 } | |
823 #endif | |
824 return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); | 838 return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); |
825 #ifdef DEBUG | |
826 } else { | 839 } else { |
827 if (FLAG_trace_ic) { | 840 TRACE_IC_NAMED("[LoadIC : no inline patch %s (patching failed)]\n", |
828 PrintF("[LoadIC : no inline patch %s (patching failed)]\n", | 841 name); |
829 *name->ToCString()); | |
830 } | |
831 } | 842 } |
832 } else { | 843 } else { |
833 if (FLAG_trace_ic) { | 844 TRACE_IC_NAMED("[LoadIC : no inline patch %s (not inobject)]\n", name); |
834 PrintF("[LoadIC : no inline patch %s (not inobject)]\n", | 845 } |
835 *name->ToCString()); | 846 } else if (can_be_inlined_contextual) { |
836 } | 847 Map* map = lookup.holder()->map(); |
| 848 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast( |
| 849 lookup.holder()->property_dictionary()->ValueAt( |
| 850 lookup.GetDictionaryEntry())); |
| 851 if (PatchInlinedContextualLoad(address(), map, cell)) { |
| 852 set_target(megamorphic_stub()); |
| 853 TRACE_IC_NAMED("[LoadIC : inline contextual patch %s]\n", name); |
| 854 ASSERT(cell->value() != Heap::the_hole_value()); |
| 855 return cell->value(); |
837 } | 856 } |
838 } else { | 857 } else { |
839 if (FLAG_use_ic && state == PREMONOMORPHIC) { | 858 if (FLAG_use_ic && state == PREMONOMORPHIC) { |
840 if (FLAG_trace_ic) { | 859 TRACE_IC_NAMED("[LoadIC : no inline patch %s (not inlinable)]\n", name); |
841 PrintF("[LoadIC : no inline patch %s (not inlinable)]\n", | |
842 *name->ToCString()); | |
843 #endif | |
844 } | |
845 } | 860 } |
846 } | 861 } |
847 | 862 |
848 // Update inline cache and stub cache. | 863 // Update inline cache and stub cache. |
849 if (FLAG_use_ic) { | 864 if (FLAG_use_ic) { |
850 UpdateCaches(&lookup, state, object, name); | 865 UpdateCaches(&lookup, state, object, name); |
851 } | 866 } |
852 | 867 |
853 PropertyAttributes attr; | 868 PropertyAttributes attr; |
854 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { | 869 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { |
(...skipping 963 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1818 #undef ADDR | 1833 #undef ADDR |
1819 }; | 1834 }; |
1820 | 1835 |
1821 | 1836 |
1822 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 1837 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
1823 return IC_utilities[id]; | 1838 return IC_utilities[id]; |
1824 } | 1839 } |
1825 | 1840 |
1826 | 1841 |
1827 } } // namespace v8::internal | 1842 } } // namespace v8::internal |
OLD | NEW |