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 |