Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 867 // stub cache. | 867 // stub cache. |
| 868 Object* code = NULL; | 868 Object* code = NULL; |
| 869 switch (type) { | 869 switch (type) { |
| 870 case FIELD: { | 870 case FIELD: { |
| 871 code = StubCache::ComputeStoreField(*name, *receiver, | 871 code = StubCache::ComputeStoreField(*name, *receiver, |
| 872 lookup->GetFieldIndex()); | 872 lookup->GetFieldIndex()); |
| 873 break; | 873 break; |
| 874 } | 874 } |
| 875 case MAP_TRANSITION: { | 875 case MAP_TRANSITION: { |
| 876 if (lookup->GetAttributes() != NONE) return; | 876 if (lookup->GetAttributes() != NONE) return; |
| 877 if (receiver->map()->unused_property_fields() == 0) return; | |
| 878 HandleScope scope; | 877 HandleScope scope; |
| 879 ASSERT(type == MAP_TRANSITION && | 878 ASSERT(type == MAP_TRANSITION); |
| 880 (receiver->map()->unused_property_fields() > 0)); | |
| 881 Handle<Map> transition(lookup->GetTransitionMap()); | 879 Handle<Map> transition(lookup->GetTransitionMap()); |
| 882 int index = transition->PropertyIndexFor(*name); | 880 int index = transition->PropertyIndexFor(*name); |
| 883 code = StubCache::ComputeStoreField(*name, *receiver, index, *transition); | 881 code = StubCache::ComputeStoreField(*name, *receiver, index, *transition); |
| 884 break; | 882 break; |
| 885 } | 883 } |
| 886 case CALLBACKS: { | 884 case CALLBACKS: { |
| 887 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; | 885 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; |
| 888 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 886 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); |
| 889 if (v8::ToCData<Address>(callback->setter()) == 0) return; | 887 if (v8::ToCData<Address>(callback->setter()) == 0) return; |
| 890 code = StubCache::ComputeStoreCallback(*name, *receiver, callback); | 888 code = StubCache::ComputeStoreCallback(*name, *receiver, callback); |
| 891 break; | 889 break; |
| 892 } | 890 } |
| 893 case INTERCEPTOR: { | 891 case INTERCEPTOR: { |
| 894 code = StubCache::ComputeStoreInterceptor(*name, *receiver); | 892 code = StubCache::ComputeStoreInterceptor(*name, *receiver); |
| 895 break; | 893 break; |
| 896 } | 894 } |
| 897 default: | 895 default: |
| 898 return; | 896 return; |
| 899 } | 897 } |
| 900 | 898 |
| 901 // If we're unable to compute the stub (not enough memory left), we | 899 // If we're unable to compute the stub (not enough memory left), we |
| 902 // simply avoid updating the caches. | 900 // simply avoid updating the caches. |
| 903 if (code->IsFailure()) return; | 901 if (code->IsFailure()) return; |
| 904 | 902 |
| 905 // Patch the call site depending on the state of the cache. | 903 // Patch the call site depending on the state of the cache. |
| 906 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 904 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
| 907 set_target(Code::cast(code)); | 905 set_target(Code::cast(code)); |
| 908 } else if (state == MONOMORPHIC) { | 906 } else if (state == MONOMORPHIC) { |
| 909 set_target(megamorphic_stub()); | 907 // Only move to mega morphic if the target changes. |
| 908 if (target() != Code::cast(code)) set_target(megamorphic_stub()); | |
| 910 } | 909 } |
| 911 | 910 |
| 912 #ifdef DEBUG | 911 #ifdef DEBUG |
| 913 TraceIC("StoreIC", name, state, target()); | 912 TraceIC("StoreIC", name, state, target()); |
| 914 #endif | 913 #endif |
| 915 } | 914 } |
| 916 | 915 |
| 917 | 916 |
| 918 Object* KeyedStoreIC::Store(State state, | 917 Object* KeyedStoreIC::Store(State state, |
| 919 Handle<Object> object, | 918 Handle<Object> object, |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 989 Object* code = NULL; | 988 Object* code = NULL; |
| 990 | 989 |
| 991 switch (type) { | 990 switch (type) { |
| 992 case FIELD: { | 991 case FIELD: { |
| 993 code = StubCache::ComputeKeyedStoreField(*name, *receiver, | 992 code = StubCache::ComputeKeyedStoreField(*name, *receiver, |
| 994 lookup->GetFieldIndex()); | 993 lookup->GetFieldIndex()); |
| 995 break; | 994 break; |
| 996 } | 995 } |
| 997 case MAP_TRANSITION: { | 996 case MAP_TRANSITION: { |
| 998 if (lookup->GetAttributes() == NONE) { | 997 if (lookup->GetAttributes() == NONE) { |
| 999 if (receiver->map()->unused_property_fields() == 0) return; | |
| 1000 HandleScope scope; | 998 HandleScope scope; |
| 1001 ASSERT(type == MAP_TRANSITION && | 999 ASSERT(type == MAP_TRANSITION); |
| 1002 (receiver->map()->unused_property_fields() > 0)); | |
| 1003 Handle<Map> transition(lookup->GetTransitionMap()); | 1000 Handle<Map> transition(lookup->GetTransitionMap()); |
| 1004 int index = transition->PropertyIndexFor(*name); | 1001 int index = transition->PropertyIndexFor(*name); |
| 1005 code = StubCache::ComputeKeyedStoreField(*name, *receiver, | 1002 code = StubCache::ComputeKeyedStoreField(*name, *receiver, |
| 1006 index, *transition); | 1003 index, *transition); |
| 1007 break; | 1004 break; |
| 1008 } | 1005 } |
| 1009 // fall through. | 1006 // fall through. |
| 1010 } | 1007 } |
| 1011 default: { | 1008 default: { |
| 1012 // Always rewrite to the generic case so that we do not | 1009 // Always rewrite to the generic case so that we do not |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1108 Object* StoreIC_Miss(Arguments args) { | 1105 Object* StoreIC_Miss(Arguments args) { |
| 1109 NoHandleAllocation na; | 1106 NoHandleAllocation na; |
| 1110 ASSERT(args.length() == 3); | 1107 ASSERT(args.length() == 3); |
| 1111 StoreIC ic; | 1108 StoreIC ic; |
| 1112 IC::State state = IC::StateFrom(ic.target(), args[0]); | 1109 IC::State state = IC::StateFrom(ic.target(), args[0]); |
| 1113 return ic.Store(state, args.at<Object>(0), args.at<String>(1), | 1110 return ic.Store(state, args.at<Object>(0), args.at<String>(1), |
| 1114 args.at<Object>(2)); | 1111 args.at<Object>(2)); |
| 1115 } | 1112 } |
| 1116 | 1113 |
| 1117 | 1114 |
| 1115 // Extend storage is called in a store inline cache when | |
| 1116 // it is necessary to extend the properties array of a | |
| 1117 // JSObject. | |
| 1118 Object* StoreIC_ExtendStorage(Arguments args) { | |
| 1119 NoHandleAllocation na; | |
| 1120 ASSERT(args.length() == 3); | |
| 1121 | |
| 1122 // Convert the parameters | |
| 1123 JSObject* object = JSObject::cast(args[0]); | |
| 1124 Map* transition = Map::cast(args[1]); | |
| 1125 Object* value = args[2]; | |
| 1126 | |
| 1127 // Check the object has run out out property space. | |
| 1128 ASSERT(object->HasFastProperties()); | |
| 1129 ASSERT(object->map()->unused_property_fields() == 0); | |
| 1130 | |
| 1131 // Expand the properties array. | |
| 1132 FixedArray* old_storage = object->properties(); | |
| 1133 int new_unused = transition->unused_property_fields(); | |
| 1134 int new_size = old_storage->length() + new_unused + 1; | |
|
Mads Ager (chromium)
2008/10/03 09:12:45
Please remove extra space between type and name.
| |
| 1135 Object* result = old_storage->CopySize(new_size); | |
| 1136 if (result->IsFailure()) return result; | |
| 1137 FixedArray* new_storage = FixedArray::cast(result); | |
| 1138 new_storage->set(old_storage->length(), value); | |
| 1139 | |
| 1140 // Set the new property value and do the map tranistion. | |
| 1141 object->set_properties(new_storage); | |
| 1142 object->set_map(transition); | |
| 1143 | |
| 1144 // Return the stored value. | |
| 1145 return value; | |
| 1146 } | |
| 1147 | |
| 1148 | |
| 1118 void StoreIC::GenerateInitialize(MacroAssembler* masm) { | 1149 void StoreIC::GenerateInitialize(MacroAssembler* masm) { |
| 1119 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss))); | 1150 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss))); |
| 1120 } | 1151 } |
| 1121 | 1152 |
| 1122 | 1153 |
| 1123 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 1154 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1124 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss))); | 1155 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss))); |
| 1125 } | 1156 } |
| 1126 | 1157 |
| 1127 | 1158 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1153 #undef ADDR | 1184 #undef ADDR |
| 1154 }; | 1185 }; |
| 1155 | 1186 |
| 1156 | 1187 |
| 1157 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 1188 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 1158 return IC_utilities[id]; | 1189 return IC_utilities[id]; |
| 1159 } | 1190 } |
| 1160 | 1191 |
| 1161 | 1192 |
| 1162 } } // namespace v8::internal | 1193 } } // namespace v8::internal |
| OLD | NEW |