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

Side by Side Diff: src/ic.cc

Issue 3402014: Generate inline code for contextual loads. (Closed)
Patch Set: Created 10 years, 3 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
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 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
OLDNEW
« src/ia32/codegen-ia32.cc ('K') | « src/ic.h ('k') | src/v8-counters.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698