OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
175 intptr_t delta = | 175 intptr_t delta = |
176 original_code->instruction_start() - code->instruction_start(); | 176 original_code->instruction_start() - code->instruction_start(); |
177 return addr + delta; | 177 return addr + delta; |
178 } | 178 } |
179 #endif | 179 #endif |
180 | 180 |
181 | 181 |
182 static bool TryRemoveInvalidPrototypeDependentStub(Code* target, | 182 static bool TryRemoveInvalidPrototypeDependentStub(Code* target, |
183 Object* receiver, | 183 Object* receiver, |
184 Object* name) { | 184 Object* name) { |
185 // If the code is NORMAL, it handles dictionary mode objects. Such stubs do | 185 if (target->is_keyed_load_stub() || |
danno
2013/05/02 11:36:06
// Determine whether the failure is due to a name
Toon Verwaest
2013/05/02 12:27:20
Done.
| |
186 // not check maps, but do positive/negative lookups. | 186 target->is_keyed_call_stub() || |
187 if (target->type() != Code::NORMAL) { | 187 target->is_keyed_store_stub()) { |
188 Map* map = target->FindFirstMap(); | 188 if (!name->IsName()) return false; |
189 if (map != NULL && map->is_deprecated()) { | 189 Name* stub_name = target->FindFirstName(); |
190 return true; | 190 if (Name::cast(name) != stub_name) return false; |
191 } | |
192 } | 191 } |
193 | 192 |
194 InlineCacheHolderFlag cache_holder = | 193 InlineCacheHolderFlag cache_holder = |
195 Code::ExtractCacheHolderFromFlags(target->flags()); | 194 Code::ExtractCacheHolderFromFlags(target->flags()); |
196 | 195 |
197 Isolate* isolate = target->GetIsolate(); | 196 Isolate* isolate = target->GetIsolate(); |
198 if (cache_holder == OWN_MAP && !receiver->IsJSObject()) { | 197 if (cache_holder == OWN_MAP && !receiver->IsJSObject()) { |
199 // The stub was generated for JSObject but called for non-JSObject. | 198 // The stub was generated for JSObject but called for non-JSObject. |
200 // IC::GetCodeCacheHolder is not applicable. | 199 // IC::GetCodeCacheHolder is not applicable. |
201 return false; | 200 return false; |
202 } else if (cache_holder == PROTOTYPE_MAP && | 201 } else if (cache_holder == PROTOTYPE_MAP && |
203 receiver->GetPrototype(isolate)->IsNull()) { | 202 receiver->GetPrototype(isolate)->IsNull()) { |
204 // IC::GetCodeCacheHolder is not applicable. | 203 // IC::GetCodeCacheHolder is not applicable. |
205 return false; | 204 return false; |
206 } | 205 } |
207 Map* map = IC::GetCodeCacheHolder(isolate, receiver, cache_holder)->map(); | 206 Map* map = IC::GetCodeCacheHolder(isolate, receiver, cache_holder)->map(); |
208 | 207 |
209 // Decide whether the inline cache failed because of changes to the | 208 // Decide whether the inline cache failed because of changes to the |
210 // receiver itself or changes to one of its prototypes. | 209 // receiver itself or changes to one of its prototypes. |
211 // | 210 // |
212 // If there are changes to the receiver itself, the map of the | 211 // If there are changes to the receiver itself, the map of the |
213 // receiver will have changed and the current target will not be in | 212 // receiver will have changed and the current target will not be in |
214 // the receiver map's code cache. Therefore, if the current target | 213 // the receiver map's code cache. Therefore, if the current target |
215 // is in the receiver map's code cache, the inline cache failed due | 214 // is in the receiver map's code cache, the inline cache failed due |
216 // to prototype check failure. | 215 // to prototype check failure. |
217 int index = map->IndexInCodeCache(name, target); | 216 int index = map->IndexInCodeCache(name, target); |
218 if (index >= 0) { | 217 if (index >= 0) { |
219 map->RemoveFromCodeCache(String::cast(name), target, index); | 218 map->RemoveFromCodeCache(String::cast(name), target, index); |
219 if (target->is_load_stub() || target->is_keyed_load_stub()) { | |
danno
2013/05/02 11:36:06
// For loads, handlers are stored in addition to t
Toon Verwaest
2013/05/02 12:27:20
Done.
| |
220 Code* handler = target->FindFirstCode(); | |
221 index = map->IndexInCodeCache(name, handler); | |
222 if (index >= 0) { | |
223 map->RemoveFromCodeCache(String::cast(name), handler, index); | |
224 } | |
225 } | |
220 return true; | 226 return true; |
221 } | 227 } |
222 | 228 |
223 return false; | 229 if (cache_holder != OWN_MAP) return false; |
danno
2013/05/02 11:36:06
// If the IC is shared between multiple receivers
Toon Verwaest
2013/05/02 12:27:20
Done.
| |
230 | |
231 // Also flag monomorphic prototype failure if the old map was deprecated. | |
232 Map* old_map = target->FindFirstMap(); | |
233 if (old_map == NULL) return false; | |
234 return old_map == map || old_map->is_deprecated(); | |
danno
2013/05/02 11:36:06
// The stub is not in the cache. We've ruled out a
Toon Verwaest
2013/05/02 12:27:20
Done.
| |
224 } | 235 } |
225 | 236 |
226 | 237 |
227 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) { | 238 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) { |
228 IC::State state = target->ic_state(); | 239 IC::State state = target->ic_state(); |
229 | 240 |
230 if (state != MONOMORPHIC || !name->IsString()) return state; | 241 if (state != MONOMORPHIC || !name->IsString()) return state; |
231 if (receiver->IsUndefined() || receiver->IsNull()) return state; | 242 if (receiver->IsUndefined() || receiver->IsNull()) return state; |
232 | 243 |
233 // For keyed load/store/call, the most likely cause of cache failure is | |
234 // that the key has changed. We do not distinguish between | |
235 // prototype and non-prototype failures for keyed access. | |
236 Code::Kind kind = target->kind(); | 244 Code::Kind kind = target->kind(); |
237 if (kind == Code::KEYED_LOAD_IC || | |
238 kind == Code::KEYED_STORE_IC || | |
239 kind == Code::KEYED_CALL_IC) { | |
240 return MONOMORPHIC; | |
241 } | |
242 | |
243 // Remove the target from the code cache if it became invalid | 245 // Remove the target from the code cache if it became invalid |
244 // because of changes in the prototype chain to avoid hitting it | 246 // because of changes in the prototype chain to avoid hitting it |
245 // again. | 247 // again. |
246 // Call stubs handle this later to allow extra IC state | 248 // Call stubs handle this later to allow extra IC state |
247 // transitions. | 249 // transitions. |
248 if (kind != Code::CALL_IC && | 250 if (kind != Code::CALL_IC && kind != Code::KEYED_CALL_IC && |
249 TryRemoveInvalidPrototypeDependentStub(target, receiver, name)) { | 251 TryRemoveInvalidPrototypeDependentStub(target, receiver, name)) { |
250 return MONOMORPHIC_PROTOTYPE_FAILURE; | 252 return MONOMORPHIC_PROTOTYPE_FAILURE; |
251 } | 253 } |
252 | 254 |
253 // The builtins object is special. It only changes when JavaScript | 255 // The builtins object is special. It only changes when JavaScript |
254 // builtins are loaded lazily. It is important to keep inline | 256 // builtins are loaded lazily. It is important to keep inline |
255 // caches for the builtins object monomorphic. Therefore, if we get | 257 // caches for the builtins object monomorphic. Therefore, if we get |
256 // an inline cache miss for the builtins object after lazily loading | 258 // an inline cache miss for the builtins object after lazily loading |
257 // JavaScript builtins, we return uninitialized as the state to | 259 // JavaScript builtins, we return uninitialized as the state to |
258 // force the inline cache back to monomorphic state. | 260 // force the inline cache back to monomorphic state. |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
717 // This is the first time we execute this inline cache. | 719 // This is the first time we execute this inline cache. |
718 // Set the target to the pre monomorphic stub to delay | 720 // Set the target to the pre monomorphic stub to delay |
719 // setting the monomorphic state. | 721 // setting the monomorphic state. |
720 code = isolate()->stub_cache()->ComputeCallPreMonomorphic( | 722 code = isolate()->stub_cache()->ComputeCallPreMonomorphic( |
721 argc, kind_, extra_ic_state); | 723 argc, kind_, extra_ic_state); |
722 } else if (state == MONOMORPHIC) { | 724 } else if (state == MONOMORPHIC) { |
723 if (kind_ == Code::CALL_IC && | 725 if (kind_ == Code::CALL_IC && |
724 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { | 726 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { |
725 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, | 727 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
726 object, name); | 728 object, name); |
727 } else if (kind_ == Code::CALL_IC && | 729 } else if (TryRemoveInvalidPrototypeDependentStub(target(), |
728 TryRemoveInvalidPrototypeDependentStub(target(), | |
729 *object, | 730 *object, |
730 *name)) { | 731 *name)) { |
731 state = MONOMORPHIC_PROTOTYPE_FAILURE; | 732 state = MONOMORPHIC_PROTOTYPE_FAILURE; |
732 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, | 733 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
733 object, name); | 734 object, name); |
734 } else { | 735 } else { |
735 code = isolate()->stub_cache()->ComputeCallMegamorphic( | 736 code = isolate()->stub_cache()->ComputeCallMegamorphic( |
736 argc, kind_, extra_ic_state); | 737 argc, kind_, extra_ic_state); |
737 } | 738 } |
738 } else { | 739 } else { |
739 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, | 740 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
740 object, name); | 741 object, name); |
741 } | 742 } |
742 | 743 |
743 // If there's no appropriate stub we simply avoid updating the caches. | 744 // If there's no appropriate stub we simply avoid updating the caches. |
744 if (code.is_null()) return; | 745 if (code.is_null()) return; |
745 | 746 |
746 // Patch the call site depending on the state of the cache. | 747 // Patch the call site depending on the state of the cache. |
747 switch (state) { | 748 switch (state) { |
748 case UNINITIALIZED: | 749 case UNINITIALIZED: |
749 case MONOMORPHIC_PROTOTYPE_FAILURE: | 750 case MONOMORPHIC_PROTOTYPE_FAILURE: |
750 case PREMONOMORPHIC: | 751 case PREMONOMORPHIC: |
751 set_target(*code); | |
752 break; | |
753 case MONOMORPHIC: | 752 case MONOMORPHIC: |
754 if (code->ic_state() != MONOMORPHIC) { | |
755 Map* map = target()->FindFirstMap(); | |
756 if (map != NULL) { | |
757 UpdateMegamorphicCache(map, *name, target()); | |
758 } | |
759 } | |
760 set_target(*code); | 753 set_target(*code); |
761 break; | 754 break; |
762 case MEGAMORPHIC: { | 755 case MEGAMORPHIC: { |
763 // Cache code holding map should be consistent with | 756 // Cache code holding map should be consistent with |
764 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. | 757 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. |
765 Handle<JSObject> cache_object = object->IsJSObject() | 758 Handle<JSObject> cache_object = object->IsJSObject() |
766 ? Handle<JSObject>::cast(object) | 759 ? Handle<JSObject>::cast(object) |
767 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())), | 760 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())), |
768 isolate()); | 761 isolate()); |
769 // Update the stub cache. | 762 // Update the stub cache. |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1000 if (number_of_valid_maps >= 4) return false; | 993 if (number_of_valid_maps >= 4) return false; |
1001 | 994 |
1002 // Only allow 0 maps in case target() was reset to UNINITIALIZED by the GC. | 995 // Only allow 0 maps in case target() was reset to UNINITIALIZED by the GC. |
1003 // In that case, allow the IC to go back monomorphic. | 996 // In that case, allow the IC to go back monomorphic. |
1004 if (number_of_maps == 0 && target()->ic_state() != UNINITIALIZED) { | 997 if (number_of_maps == 0 && target()->ic_state() != UNINITIALIZED) { |
1005 return false; | 998 return false; |
1006 } | 999 } |
1007 target()->FindAllCode(&handlers, receiver_maps.length()); | 1000 target()->FindAllCode(&handlers, receiver_maps.length()); |
1008 } | 1001 } |
1009 | 1002 |
1010 if (!AddOneReceiverMapIfMissing(&receiver_maps, | 1003 bool overwrote = false; |
danno
2013/05/02 11:36:06
// If the name doesn't match, go generic. Otherwis
Toon Verwaest
2013/05/02 12:27:20
Done.
| |
1011 Handle<Map>(receiver->map()))) { | 1004 Handle<Map> new_receiver_map(receiver->map()); |
1012 return false; | 1005 for (int current = 0; current < receiver_maps.length(); ++current) { |
1006 if (!receiver_maps.at(current).is_null() && | |
1007 receiver_maps.at(current).is_identical_to(new_receiver_map)) { | |
1008 overwrote = true; | |
1009 handlers.InsertAt(current, code); | |
1010 break; | |
1011 } | |
1013 } | 1012 } |
danno
2013/05/02 11:36:06
Move this loop about the code above to get the map
Toon Verwaest
2013/05/02 12:27:20
Done.
| |
1014 | 1013 |
1015 handlers.Add(code); | 1014 if (!overwrote) { |
1015 receiver_maps.Add(new_receiver_map); | |
1016 handlers.Add(code); | |
1017 number_of_valid_maps++; | |
1018 } | |
1019 | |
1016 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( | 1020 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( |
1017 &receiver_maps, &handlers, number_of_valid_maps + 1, name); | 1021 &receiver_maps, &handlers, number_of_valid_maps, name); |
1018 set_target(*ic); | 1022 set_target(*ic); |
1019 return true; | 1023 return true; |
1020 } | 1024 } |
1021 | 1025 |
1022 | 1026 |
1023 void LoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver, | 1027 void LoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver, |
1024 Handle<Code> handler, | 1028 Handle<Code> handler, |
1025 Handle<String> name) { | 1029 Handle<String> name) { |
1026 if (handler->type() == Code::NORMAL) return set_target(*handler); | 1030 if (handler->type() == Code::NORMAL) return set_target(*handler); |
1027 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( | 1031 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( |
(...skipping 14 matching lines...) Expand all Loading... | |
1042 | 1046 |
1043 void IC::CopyICToMegamorphicCache(Handle<String> name) { | 1047 void IC::CopyICToMegamorphicCache(Handle<String> name) { |
1044 MapHandleList receiver_maps; | 1048 MapHandleList receiver_maps; |
1045 CodeHandleList handlers; | 1049 CodeHandleList handlers; |
1046 { | 1050 { |
1047 AssertNoAllocation no_gc; | 1051 AssertNoAllocation no_gc; |
1048 target()->FindAllMaps(&receiver_maps); | 1052 target()->FindAllMaps(&receiver_maps); |
1049 target()->FindAllCode(&handlers, receiver_maps.length()); | 1053 target()->FindAllCode(&handlers, receiver_maps.length()); |
1050 } | 1054 } |
1051 for (int i = 0; i < receiver_maps.length(); i++) { | 1055 for (int i = 0; i < receiver_maps.length(); i++) { |
1056 if (receiver_maps.at(i)->is_deprecated()) continue; | |
danno
2013/05/02 11:36:06
Maybe defer this to Crankshaft? Don't throw away t
Toon Verwaest
2013/05/02 12:27:20
Done.
| |
1052 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); | 1057 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); |
1053 } | 1058 } |
1054 } | 1059 } |
1055 | 1060 |
1056 | 1061 |
1057 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { | 1062 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { |
1058 AssertNoAllocation no_allocation; | 1063 AssertNoAllocation no_allocation; |
1059 | 1064 |
1060 Map* current_map = target()->FindFirstMap(); | 1065 Map* current_map = target()->FindFirstMap(); |
1061 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); | 1066 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1094 is_same_handler = old_handler == *code; | 1099 is_same_handler = old_handler == *code; |
1095 } | 1100 } |
1096 if (is_same_handler | 1101 if (is_same_handler |
1097 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) { | 1102 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) { |
1098 UpdateMonomorphicIC(receiver, code, name); | 1103 UpdateMonomorphicIC(receiver, code, name); |
1099 break; | 1104 break; |
1100 } | 1105 } |
1101 if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) { | 1106 if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) { |
1102 break; | 1107 break; |
1103 } | 1108 } |
1104 } | 1109 |
1105 if (target()->type() != Code::NORMAL) { | 1110 if (target()->type() != Code::NORMAL) { |
1106 if (target()->is_load_stub()) { | |
1107 CopyICToMegamorphicCache(name); | 1111 CopyICToMegamorphicCache(name); |
1108 } else if (target()->is_store_stub()) { | |
1109 // Ensure that the IC stays monomorphic when replacing a monomorphic | |
1110 // IC for a deprecated map. | |
1111 // TODO(verwaest): Remove this code once polymorphic store ICs are | |
1112 // implemented. Updating the polymorphic IC will keep it monomorphic | |
1113 // by filtering deprecated maps. | |
1114 MapHandleList maps; | |
1115 Code* handler = target(); | |
1116 handler->FindAllMaps(&maps); | |
1117 for (int i = 0; i < Min(1, maps.length()); i++) { | |
1118 if (maps.at(i)->is_deprecated()) { | |
1119 UpdateMonomorphicIC(receiver, code, name); | |
1120 return; | |
1121 } | |
1122 } | |
1123 if (maps.length() > 0) { | |
1124 if (receiver->map() == *maps.at(0)) { | |
1125 UpdateMonomorphicIC(receiver, code, name); | |
1126 return; | |
1127 } | |
1128 UpdateMegamorphicCache(*maps.at(0), *name, handler); | |
1129 } | |
1130 } else { | |
1131 Code* handler = target(); | |
1132 Map* map = handler->FindFirstMap(); | |
1133 if (map != NULL) { | |
1134 UpdateMegamorphicCache(map, *name, handler); | |
1135 } | |
1136 } | 1112 } |
1137 } | 1113 } |
1138 | 1114 |
1139 UpdateMegamorphicCache(receiver->map(), *name, *code); | 1115 UpdateMegamorphicCache(receiver->map(), *name, *code); |
1140 set_target((strict_mode == kStrictMode) | 1116 set_target((strict_mode == kStrictMode) |
1141 ? *megamorphic_stub_strict() | 1117 ? *megamorphic_stub_strict() |
1142 : *megamorphic_stub()); | 1118 : *megamorphic_stub()); |
1143 } | 1119 } |
1144 break; | 1120 break; |
1145 case MEGAMORPHIC: | 1121 case MEGAMORPHIC: |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1228 } else { | 1204 } else { |
1229 code = ComputeLoadHandler(lookup, receiver, name); | 1205 code = ComputeLoadHandler(lookup, receiver, name); |
1230 if (code.is_null()) return; | 1206 if (code.is_null()) return; |
1231 } | 1207 } |
1232 | 1208 |
1233 PatchCache(state, kNonStrictMode, receiver, name, code); | 1209 PatchCache(state, kNonStrictMode, receiver, name, code); |
1234 TRACE_IC("LoadIC", name, state, target()); | 1210 TRACE_IC("LoadIC", name, state, target()); |
1235 } | 1211 } |
1236 | 1212 |
1237 | 1213 |
1238 void IC::UpdateMegamorphicCache(Map* map, String* name, Code* code) { | 1214 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { |
1239 // Cache code holding map should be consistent with | 1215 // Cache code holding map should be consistent with |
1240 // GenerateMonomorphicCacheProbe. | 1216 // GenerateMonomorphicCacheProbe. |
1241 isolate()->stub_cache()->Set(name, map, code); | 1217 isolate()->stub_cache()->Set(name, map, code); |
1242 } | 1218 } |
1243 | 1219 |
1244 | 1220 |
1245 Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup, | 1221 Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup, |
1246 Handle<JSObject> receiver, | 1222 Handle<JSObject> receiver, |
1247 Handle<String> name) { | 1223 Handle<String> name) { |
1248 if (!lookup->IsProperty()) { | 1224 if (!lookup->IsProperty()) { |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1490 // repeatedly try to rewrite. | 1466 // repeatedly try to rewrite. |
1491 return generic_stub(); | 1467 return generic_stub(); |
1492 } | 1468 } |
1493 return Handle<Code>::null(); | 1469 return Handle<Code>::null(); |
1494 } | 1470 } |
1495 | 1471 |
1496 | 1472 |
1497 static bool LookupForWrite(Handle<JSObject> receiver, | 1473 static bool LookupForWrite(Handle<JSObject> receiver, |
1498 Handle<String> name, | 1474 Handle<String> name, |
1499 Handle<Object> value, | 1475 Handle<Object> value, |
1500 LookupResult* lookup) { | 1476 LookupResult* lookup, |
1477 IC::State* state) { | |
1501 Handle<JSObject> holder = receiver; | 1478 Handle<JSObject> holder = receiver; |
1502 receiver->Lookup(*name, lookup); | 1479 receiver->Lookup(*name, lookup); |
1503 if (lookup->IsFound()) { | 1480 if (lookup->IsFound()) { |
1504 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; | 1481 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; |
1505 | 1482 |
1506 if (lookup->holder() == *receiver) { | 1483 if (lookup->holder() == *receiver) { |
1507 if (lookup->IsInterceptor() && | 1484 if (lookup->IsInterceptor() && |
1508 receiver->GetNamedInterceptor()->setter()->IsUndefined()) { | 1485 receiver->GetNamedInterceptor()->setter()->IsUndefined()) { |
1509 receiver->LocalLookupRealNamedProperty(*name, lookup); | 1486 receiver->LocalLookupRealNamedProperty(*name, lookup); |
1510 return lookup->IsFound() && | 1487 return lookup->IsFound() && |
(...skipping 16 matching lines...) Expand all Loading... | |
1527 // While normally LookupTransition gets passed the receiver, in this case we | 1504 // While normally LookupTransition gets passed the receiver, in this case we |
1528 // pass the holder of the property that we overwrite. This keeps the holder in | 1505 // pass the holder of the property that we overwrite. This keeps the holder in |
1529 // the LookupResult intact so we can later use it to generate a prototype | 1506 // the LookupResult intact so we can later use it to generate a prototype |
1530 // chain check. This avoids a double lookup, but requires us to pass in the | 1507 // chain check. This avoids a double lookup, but requires us to pass in the |
1531 // receiver when trying to fetch extra information from the transition. | 1508 // receiver when trying to fetch extra information from the transition. |
1532 receiver->map()->LookupTransition(*holder, *name, lookup); | 1509 receiver->map()->LookupTransition(*holder, *name, lookup); |
1533 if (!lookup->IsTransition()) return false; | 1510 if (!lookup->IsTransition()) return false; |
1534 PropertyDetails target_details = | 1511 PropertyDetails target_details = |
1535 lookup->GetTransitionDetails(receiver->map()); | 1512 lookup->GetTransitionDetails(receiver->map()); |
1536 if (target_details.IsReadOnly()) return false; | 1513 if (target_details.IsReadOnly()) return false; |
1537 return value->FitsRepresentation(target_details.representation()); | 1514 if (!value->FitsRepresentation(target_details.representation())) { |
danno
2013/05/02 11:36:06
Comment this.
Toon Verwaest
2013/05/02 12:27:20
Done.
| |
1515 Handle<Map> target(lookup->GetTransitionMapFromMap(receiver->map())); | |
1516 Map::GeneralizeRepresentation( | |
1517 target, target->LastAdded(), value->OptimalRepresentation()); | |
1518 *state = MONOMORPHIC_PROTOTYPE_FAILURE; | |
danno
2013/05/02 11:36:06
Check for already deprecated maps? Deprecated maps
Toon Verwaest
2013/05/02 12:27:20
Done.
| |
1519 } | |
1520 return true; | |
1538 } | 1521 } |
1539 | 1522 |
1540 | 1523 |
1541 MaybeObject* StoreIC::Store(State state, | 1524 MaybeObject* StoreIC::Store(State state, |
1542 StrictModeFlag strict_mode, | 1525 StrictModeFlag strict_mode, |
1543 Handle<Object> object, | 1526 Handle<Object> object, |
1544 Handle<String> name, | 1527 Handle<String> name, |
1545 Handle<Object> value, | 1528 Handle<Object> value, |
1546 JSReceiver::StoreFromKeyed store_mode) { | 1529 JSReceiver::StoreFromKeyed store_mode) { |
1547 // Handle proxies. | 1530 // Handle proxies. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1611 ? global_proxy_stub_strict() | 1594 ? global_proxy_stub_strict() |
1612 : global_proxy_stub(); | 1595 : global_proxy_stub(); |
1613 set_target(*stub); | 1596 set_target(*stub); |
1614 TRACE_IC("StoreIC", name, state, *stub); | 1597 TRACE_IC("StoreIC", name, state, *stub); |
1615 } | 1598 } |
1616 return JSReceiver::SetPropertyOrFail( | 1599 return JSReceiver::SetPropertyOrFail( |
1617 receiver, name, value, NONE, strict_mode, store_mode); | 1600 receiver, name, value, NONE, strict_mode, store_mode); |
1618 } | 1601 } |
1619 | 1602 |
1620 LookupResult lookup(isolate()); | 1603 LookupResult lookup(isolate()); |
1621 if (LookupForWrite(receiver, name, value, &lookup)) { | 1604 if (LookupForWrite(receiver, name, value, &lookup, &state)) { |
1622 if (FLAG_use_ic) { | 1605 if (FLAG_use_ic) { |
1623 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); | 1606 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); |
1624 } | 1607 } |
1625 } else if (strict_mode == kStrictMode && | 1608 } else if (strict_mode == kStrictMode && |
1626 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1609 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
1627 IsUndeclaredGlobal(object)) { | 1610 IsUndeclaredGlobal(object)) { |
1628 // Strict mode doesn't allow setting non-existent global property. | 1611 // Strict mode doesn't allow setting non-existent global property. |
1629 return ReferenceError("not_defined", name); | 1612 return ReferenceError("not_defined", name); |
1630 } | 1613 } |
1631 | 1614 |
(...skipping 1341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2973 #undef ADDR | 2956 #undef ADDR |
2974 }; | 2957 }; |
2975 | 2958 |
2976 | 2959 |
2977 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2960 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2978 return IC_utilities[id]; | 2961 return IC_utilities[id]; |
2979 } | 2962 } |
2980 | 2963 |
2981 | 2964 |
2982 } } // namespace v8::internal | 2965 } } // namespace v8::internal |
OLD | NEW |