| 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 |